From 5bbdfa1cb6e6a978fe83170b39b2fa316e466bb8 Mon Sep 17 00:00:00 2001 From: Michael Kirschner Date: Wed, 20 Feb 2019 16:04:10 -0500 Subject: [PATCH] GeometryFactoryPath lookup should be more consistent with other preloader utilities. (#9493) * add new simple API - should harden / define edge cases and add tests next * add more tests define edge cases * obsolete other methods add exception throwing for null or bad inputs define expected outputs in tests * do not add a new API, just make existing method more tolerant of similar versions * adjust comments * fix comments, remove unused var --- src/Tools/DynamoShapeManager/Utilities.cs | 42 +++++----- test/DynamoCoreTests/libGPreloaderTests.cs | 89 ++++++++++++++++++++++ 2 files changed, 114 insertions(+), 17 deletions(-) diff --git a/src/Tools/DynamoShapeManager/Utilities.cs b/src/Tools/DynamoShapeManager/Utilities.cs index 6bc2ebd0f79..da72dffa409 100644 --- a/src/Tools/DynamoShapeManager/Utilities.cs +++ b/src/Tools/DynamoShapeManager/Utilities.cs @@ -346,17 +346,18 @@ internal static string RemapOldLibGPathToNewVersionPath(string preloaderLocation } /// - /// Call this method to resolve full path to GeometryFactoryAssembly - /// assembly, given the root folder and the version. This method throws - /// an exception if either of the folders/assembly cannot be found. + /// This method will return the path to the GeometryFactory assembly location + /// for a requested version of the geometry library. + /// This method is tolerant to the requested version in that it will attempt to + /// locate an exact or lower version of the GeometryFactory assembly. /// /// Full path of the directory that contains - /// LibG_xxx folder, where 'xxx' represents the library version. In a + /// LibG_xxx_y_z folder, where 'xxx y z' represents the library version of asm. In a /// typical setup this would be the same directory that contains Dynamo - /// core modules. This must represent a valid directory. + /// core modules. This must represent a valid directory - it cannot be null. /// Version number of the targeted geometry library. - /// If the resulting folder does not exist, this method throws an - /// FileNotFoundException. + /// If the resulting assembly does not exist, this method will look for a lower version match. + /// This parameter cannot be null. /// The full path to GeometryFactoryAssembly assembly. /// [Obsolete("Please use GetGeometryFactoryPath2(string rootFolder, Version version).")] @@ -366,17 +367,18 @@ public static string GetGeometryFactoryPath(string rootFolder, LibraryVersion ve } /// - /// Call this method to resolve full path to GeometryFactoryAssembly - /// assembly, given the root folder and the version. This method throws - /// an exception if either of the folders/assembly cannot be found. + /// This method will return the path to the GeometryFactory assembly location + /// for a requested version of the geometry library. + /// This method is tolerant to the requested version in that it will attempt to + /// locate an exact or lower version of the GeometryFactory assembly. /// /// Full path of the directory that contains /// LibG_xxx_y_z folder, where 'xxx y z' represents the library version of asm. In a /// typical setup this would be the same directory that contains Dynamo - /// core modules. This must represent a valid directory. + /// core modules. This must represent a valid directory - it cannot be null. /// Version number of the targeted geometry library. - /// If the resulting folder does not exist, this method throws an - /// FileNotFoundException. + /// If the resulting assembly does not exist, this method will look for a lower version match. + /// This parameter cannot be null. /// The full path to GeometryFactoryAssembly assembly. /// public static string GetGeometryFactoryPath2(string rootFolder, Version version) @@ -392,8 +394,14 @@ public static string GetGeometryFactoryPath2(string rootFolder, Version version) } //IMPORTANT_ Going forward libg folders will be named as follows: libg_major_minor_build - in reference to ASM. - var libGFolderName = string.Format("libg_{0}_{1}_{2}", version.Major, version.Minor, version.Build); - var libGFolder = Path.Combine(rootFolder, libGFolderName); + if (version == null) + { + throw new ArgumentNullException("version"); + } + + //lookup libG with a fallback to older versions which share the major version number. + var libGFolder = Utilities.GetLibGPreloaderLocation(version, rootFolder); + if (!Directory.Exists(libGFolder)) { // LibG_version folder must be valid. @@ -410,8 +418,8 @@ public static string GetGeometryFactoryPath2(string rootFolder, Version version) return assemblyPath; } - - + + private static IEnumerable GetAsmInstallations(string rootFolder) { var assemblyPath = Path.Combine(Path.Combine(rootFolder, "DynamoInstallDetective.dll")); diff --git a/test/DynamoCoreTests/libGPreloaderTests.cs b/test/DynamoCoreTests/libGPreloaderTests.cs index 711d15a85ea..ee26c83f14c 100644 --- a/test/DynamoCoreTests/libGPreloaderTests.cs +++ b/test/DynamoCoreTests/libGPreloaderTests.cs @@ -204,6 +204,95 @@ public void GetLibGPreloaderLocation_libGVersionFallback() libG22500path.Delete(true); } + [Test] + public void GetGeometryFactoryPath_libGVersionFallback() + { + var versions = new List() + { + new Version(225,0,0) + }; + + var mockedInstalledASMs = new Dictionary>() + { + + {"revit_2020_InstallLocation" ,Tuple.Create(225,2,0,0)}, + }; + + var targetVersion = new Version(225, 2, 0); + + // mock a folder with libASMLibVersionToVersion folders with correct names + var foundPath = ""; + var rootFolder = Path.Combine(Path.GetTempPath(), "LibGTest"); + // both versions of libG exist + var libG22440path = System.IO.Directory.CreateDirectory(Path.Combine(rootFolder, "LibG_224_4_0")); + var libG22500path = System.IO.Directory.CreateDirectory(Path.Combine(rootFolder, "LibG_225_0_0")); + //create a fake libg interface assembly + File.WriteAllText(Path.Combine(libG22500path.FullName, DynamoShapeManager.Utilities.GeometryFactoryAssembly), "someText"); + + var foundVersion = DynamoShapeManager.Utilities.GetInstalledAsmVersion2( + versions, ref foundPath, rootFolder, (path) => { return mockedInstalledASMs; }); + + // The found ASM version in this case is a fallback of lowest version within same major which should be 225.2.0 + Assert.AreEqual(targetVersion, foundVersion); + Assert.AreEqual("revit_2020_InstallLocation", foundPath); + + // The found libG preloader version in this case is another fallback of closest version below 225.2.0 + Assert.AreEqual(libG22500path.FullName.ToLower(), DynamoShapeManager.Utilities.GetLibGPreloaderLocation(foundVersion, rootFolder).ToLower()); + + //assert that the geometryFactory method returns the path of the lib225_0_0 path. + Assert.AreEqual(Path.Combine(libG22500path.FullName,DynamoShapeManager.Utilities.GeometryFactoryAssembly).ToLower(), + DynamoShapeManager.Utilities.GetGeometryFactoryPath2(rootFolder, targetVersion).ToLower()); + + // cleanup + libG22440path.Delete(true); + libG22500path.Delete(true); + } + + [Test] + public void GetGeometryFactoryPathTolerant_NoMatch() + { + var versions = new List() + { + new Version(225,0,0) + }; + + var mockedInstalledASMs = new Dictionary>() + { + + {"someInstallWithNoMatchingASM" ,Tuple.Create(224,0,0,0)}, + }; + + // mock a folder with libASMLibVersionToVersion folders with correct names + var foundPath = ""; + var rootFolder = Path.Combine(Path.GetTempPath(), "LibGTest"); + //there is no matching libG for the installed version of asm. + var libG22500path = System.IO.Directory.CreateDirectory(Path.Combine(rootFolder, "LibG_225_0_0")); + var foundVersion = DynamoShapeManager.Utilities.GetInstalledAsmVersion2( + versions, ref foundPath, rootFolder, (path) => { return mockedInstalledASMs; }); + + // There is no match, so found version is null. + Assert.AreEqual(null, foundVersion); + // There is no match, so path to ASM is null. + Assert.AreEqual(string.Empty, foundPath); + + // when passed null as a version, GetLibGPreloaderLocation will return LibG_0_0_0 + Assert.IsTrue(DynamoShapeManager.Utilities.GetLibGPreloaderLocation(foundVersion, rootFolder).ToLower().Contains("libg_0_0_0")); + + //when passed a null version this method should throw + Assert.Throws(() => { DynamoShapeManager.Utilities.GetGeometryFactoryPath2(rootFolder, null); }); + + //when passed a null root directory this method should throw - as a valid root directory is required. + Assert.Throws(() => { DynamoShapeManager.Utilities.GetGeometryFactoryPath2(null, new Version(224, 24, 24)); }); + + // when passed a non null, non matching version and existing root directory + // this method should throw. + + Assert.Throws(() => { DynamoShapeManager.Utilities.GetGeometryFactoryPath2(rootFolder, new Version(224, 24, 24)); }); + + // cleanup + libG22500path.Delete(true); + } + [Test] public void GetInstalledASMVersions2_FindsVersionedLibGFolders_WithRootFolderFallback()