Skip to content

Commit

Permalink
[PTAL] add a commandLine flag for specifying geometryLib path (#9949)
Browse files Browse the repository at this point in the history
* do not recurse during product lookup
remove RSA (need to use flag)
add flag for passing ASM path to command line args
add overload to use flag when present to sandbox,cli,cliwpf

* continue to recurse for most flexible sandbox

* add RSA back

* review comments

* add some simple tests
refactor for testing
modify docs from review

* fix parsing of flags

* use a new process in test to avoid testing the wrong thing
sandbox should still start even if path is invalid asm path

* review comments
  • Loading branch information
mjkkirschner authored Sep 5, 2019
1 parent 60ad7ef commit 1d49129
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 13 deletions.
3 changes: 3 additions & 0 deletions src/DynamoApplications/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
Expand All @@ -9,3 +10,5 @@

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("72464112-159f-4542-88c9-55734f67074e")]

[assembly:InternalsVisibleTo("IntegrationTests")]
67 changes: 59 additions & 8 deletions src/DynamoApplications/StartupUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,21 @@ public static CommandLineArguments Parse(string[] args)
// dll paths we'll import before running a graph
var importPaths = new List<string>() ;

var asmPath = string.Empty;

bool showHelp = false;
var optionsSet = new OptionSet().Add("o=|O=", "OpenFilePath, Instruct Dynamo to open headless and run a dyn file at this path", o => openfilepath = o)
.Add("c=|C=", "CommandFilePath, Instruct Dynamo to open a commandfile and run the commands it contains at this path," +
"this option is only supported when run from DynamoSandbox", c => commandFilePath = c)
.Add("l=|L=", "Running Dynamo under a different locale setting", l => locale = l)
.Add("v=|V=", "Verbose, Instruct Dynamo to output all evalautions it performs to an xml file at this path", v => verbose = v)
.Add("x|X", "When used in combination with the 'O' flag, opens a .dyn file from the specified path and converts it to .json." +
.Add("x|X", "When used in combination with the 'O' flag, opens a .dyn file from the specified path and converts it to .json." +
"File will have the .json extension and be located in the same directory as the original file.", x => convertFile = x != null)
.Add("h|H|help", "Get some help", h => showHelp = h != null)
.Add("g=|G=|geometry", "Geometry, Instruct Dynamo to output geometry from all evaluations to a json file at this path", g => geometryFilePath = g)
.Add("i=|I=|import", "Import, Instruct Dynamo to import an assembly as a node library. This argument should be a filepath to a single .dll" +
" - if you wish to import multiple dlls - use this flag multiple times: -i 'assembly1.dll' -i 'assembly2.dll' ", i=>importPaths.Add(i));
" - if you wish to import multiple dlls - use this flag multiple times: -i 'assembly1.dll' -i 'assembly2.dll' ", i => importPaths.Add(i)).
Add("gp=|GP=|geometrypath=|GeometryPath=", "relative or absolute path to a directory containing ASM. When supplied, instead of searching the hard disk for ASM, it will be loaded directly from this path.", gp => asmPath = gp);

optionsSet.Parse(args);

Expand All @@ -123,7 +126,8 @@ public static CommandLineArguments Parse(string[] args)
Verbose = verbose,
ConvertFile = convertFile,
GeometryFilePath = geometryFilePath,
ImportedPaths = importPaths
ImportedPaths = importPaths,
ASMPath = asmPath,
};
}

Expand All @@ -140,6 +144,7 @@ private static void ShowHelp(OptionSet opSet)
public bool ConvertFile { get; set; }
public string GeometryFilePath { get; set; }
public IEnumerable<String> ImportedPaths { get; set; }
public string ASMPath { get; set; }
}

public static void PreloadShapeManager(ref string geometryFactoryPath, ref string preloaderLocation)
Expand Down Expand Up @@ -174,21 +179,67 @@ private static IUpdateManager InitializeUpdateManager()
return um;
}



/// <summary>
/// Use this overload to construct a DynamoModel when the location of ASM to use is known.
/// </summary>
/// <param name="CLImode">CLI mode starts the model in test mode and uses a seperate path resolver.</param>
/// <param name="asmPath">Path to directory containing geometry library binaries</param>
/// <returns></returns>
public static DynamoModel MakeModel(bool CLImode, string asmPath)
{
//get sandbox executing location - this is where libG will be located.
var exePath = Assembly.GetExecutingAssembly().Location;
var rootFolder = Path.GetDirectoryName(exePath);
//defaults - these will fail.
var preloaderLocation = "libg_0_0_0";
var geometryFactoryPath = Path.Combine(preloaderLocation, DynamoShapeManager.Utilities.GeometryFactoryAssembly);

try
{
if (!Directory.Exists(asmPath))
{
throw new FileNotFoundException($"{nameof(asmPath)}:{asmPath}");
}
Version asmBinariesVersion = DynamoShapeManager.Utilities.GetVersionFromPath(asmPath);

//get version of libG that matches the asm version that was supplied from geometryLibraryPath.
preloaderLocation = DynamoShapeManager.Utilities.GetLibGPreloaderLocation(asmBinariesVersion, rootFolder);
geometryFactoryPath = Path.Combine(preloaderLocation, DynamoShapeManager.Utilities.GeometryFactoryAssembly);

//load asm and libG.
DynamoShapeManager.Utilities.PreloadAsmFromPath(preloaderLocation, asmPath);
}
catch(Exception e)
{
Console.WriteLine("A problem occured while trying to load ASM or LibG");
Console.WriteLine($"{e?.Message} : {e?.StackTrace}");
}
return StartDynamoWithDefaultConfig(CLImode, geometryFactoryPath, preloaderLocation);

}
//TODO (DYN-2118) remove this method in 3.0 and unify this method with the overload above.
public static DynamoModel MakeModel(bool CLImode)
{
var geometryFactoryPath = string.Empty;
var preloaderLocation = string.Empty;
PreloadShapeManager(ref geometryFactoryPath, ref preloaderLocation);

return StartDynamoWithDefaultConfig(CLImode, geometryFactoryPath, preloaderLocation);
}

private static DynamoModel StartDynamoWithDefaultConfig(bool CLImode, string geometryFactoryPath, string preloaderLocation)
{
var config = new DynamoModel.DefaultStartConfiguration()
{
GeometryFactoryPath = geometryFactoryPath,
ProcessMode = TaskProcessMode.Asynchronous
};
{
GeometryFactoryPath = geometryFactoryPath,
ProcessMode = TaskProcessMode.Asynchronous
};

config.UpdateManager = CLImode ? null : InitializeUpdateManager();
config.StartInTestMode = CLImode ? true : false;
config.PathResolver = CLImode ? new CLIPathResolver(preloaderLocation) as IPathResolver : new SandboxPathResolver(preloaderLocation) as IPathResolver ;
config.PathResolver = CLImode ? new CLIPathResolver(preloaderLocation) as IPathResolver : new SandboxPathResolver(preloaderLocation) as IPathResolver;

var model = DynamoModel.Start(config);
return model;
Expand Down
10 changes: 9 additions & 1 deletion src/DynamoCLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@ static internal void Main(string[] args)
{
var cmdLineArgs = StartupUtils.CommandLineArguments.Parse(args);
var locale = StartupUtils.SetLocale(cmdLineArgs);
var model = StartupUtils.MakeModel(true);
DynamoModel model;
if (!String.IsNullOrEmpty(cmdLineArgs.ASMPath))
{
model = Dynamo.Applications.StartupUtils.MakeModel(true, cmdLineArgs.ASMPath);
}
else
{
model = Dynamo.Applications.StartupUtils.MakeModel(true);
}
var runner = new CommandLineRunner(model);
runner.Run(cmdLineArgs);

Expand Down
16 changes: 13 additions & 3 deletions src/DynamoSandbox/DynamoCoreSetup.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows;
using Dynamo.Applications;
Expand All @@ -19,6 +20,7 @@ class DynamoCoreSetup
private DynamoViewModel viewModel = null;
private string commandFilePath;
private Stopwatch startupTimer = Stopwatch.StartNew();
private string ASMPath;

[DllImport("msvcrt.dll")]
public static extern int _putenv(string env);
Expand All @@ -29,16 +31,24 @@ public DynamoCoreSetup(string[] args)
var locale = StartupUtils.SetLocale(cmdLineArgs);
_putenv(locale);
commandFilePath = cmdLineArgs.CommandFilePath;
ASMPath = cmdLineArgs.ASMPath;
}

public void RunApplication(Application app)
{
try
{
DynamoModel.RequestMigrationStatusDialog += MigrationStatusDialogRequested;

var model = Dynamo.Applications.StartupUtils.MakeModel(false);

DynamoModel model;
if (!String.IsNullOrEmpty(ASMPath))
{
model = Dynamo.Applications.StartupUtils.MakeModel(false,ASMPath);
}
else
{
model = Dynamo.Applications.StartupUtils.MakeModel(false);
}

viewModel = DynamoViewModel.Start(
new DynamoViewModel.StartConfiguration()
{
Expand Down
10 changes: 9 additions & 1 deletion src/DynamoWPFCLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@ static internal void Main(string[] args)
{
var cmdLineArgs = StartupUtils.CommandLineArguments.Parse(args);
var locale = StartupUtils.SetLocale(cmdLineArgs);
var model = StartupUtils.MakeModel(true);
DynamoModel model;
if (!String.IsNullOrEmpty(cmdLineArgs.ASMPath))
{
model = Dynamo.Applications.StartupUtils.MakeModel(true, cmdLineArgs.ASMPath);
}
else
{
model = Dynamo.Applications.StartupUtils.MakeModel(true);
}
var viewModel = DynamoViewModel.Start(
new DynamoViewModel.StartConfiguration()
{
Expand Down
20 changes: 20 additions & 0 deletions src/Tools/DynamoShapeManager/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -443,5 +443,25 @@ private static IEnumerable GetAsmInstallations(string rootFolder)
var methodParams = new object[] { ProductsWithASM, ASMFileMask };
return installationsMethod.Invoke(null, methodParams) as IEnumerable;
}

/// <summary>
/// Extracts version of ASM dlls from a path by scanning for ASM dlls in the path.
/// Throws if ASM binaries cannot be found in the path.
/// </summary>
/// <param name="asmPath">path to directory containing asm dlls</param>
/// <returns></returns>
/// <param name="searchPattern">optional - to be used for testing - default is the ASM search pattern</param>
/// <returns></returns>
public static Version GetVersionFromPath(string asmPath, string searchPattern = "ASMAHL*.dll")
{
var ASMFilePath = Directory.GetFiles(asmPath, searchPattern, SearchOption.TopDirectoryOnly).FirstOrDefault();
if (ASMFilePath != null && File.Exists(ASMFilePath))
{
var asmVersion = FileVersionInfo.GetVersionInfo(ASMFilePath);
var libGversion = new Version(asmVersion.FileMajorPart, asmVersion.FileMinorPart, asmVersion.FileBuildPart);
return libGversion;
}
throw new FileNotFoundException("$Could not find geometry library binaries at : {geometryLibraryPath}");
}
}
}
79 changes: 79 additions & 0 deletions test/System/IntegrationTests/DynamoApplicationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Dynamo.Applications;
using NUnit.Framework;

namespace IntegrationTests
{
public class DynamoApplicationTests
{
[Test]
public void DynamoSandboxLoadsASMFromValidPath()
{
var versions = new List<Version>(){
new Version(224, 4, 0),
new Version(224, 0, 1),
new Version(223, 0, 1),
new Version(225, 0, 0) };


//go get a valid asm path.
var locatedPath = string.Empty;
var coreDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
Process dynamoSandbox = null;

DynamoShapeManager.Utilities.GetInstalledAsmVersion2(versions, ref locatedPath, coreDirectory);
try
{
Assert.DoesNotThrow(() =>
{
// we use a new process to avoid checking against previously loaded
// asm modules in the nunit-agent process.
dynamoSandbox = System.Diagnostics.Process.Start(Path.Combine(coreDirectory, "DynamoSandbox.exe"), $"-gp \"{locatedPath}\"");
dynamoSandbox.WaitForInputIdle();

var firstASMmodulePath = string.Empty;
foreach (ProcessModule module in dynamoSandbox.Modules)
{
if (module.FileName.Contains("ASMAHL"))
{
firstASMmodulePath = module.FileName;
break;
}
}
//assert that ASM is really loaded from exactly where we specified.
Assert.AreEqual(Path.GetDirectoryName(firstASMmodulePath), locatedPath);
});
}
finally
{

dynamoSandbox?.Kill();

}
}

[Test]
public void IfASMPathInvalidExceptionNotThrown()
{
var asmMockPath = @"./doesNotExist/";
Assert.DoesNotThrow(() =>
{
var model = Dynamo.Applications.StartupUtils.MakeModel(true, asmMockPath);
Assert.IsNotNull(model);
});

}
[Test]
public void GetVersionFromASMPath_returnsFileVersionForMockdll()
{
var version = DynamoShapeManager.Utilities.GetVersionFromPath(@"./", "DynamoCore*.dll");
var thisVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
Assert.AreEqual(version.Major, thisVersion.Major);
Assert.AreEqual(version.Minor, thisVersion.Minor);
Assert.AreEqual(version.Build, thisVersion.Build);
}
}
}
9 changes: 9 additions & 0 deletions test/System/IntegrationTests/IntegrationTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,18 @@
<Link>AssemblySharedInfo.cs</Link>
</Compile>
<Compile Include="CallsiteRegen.cs" />
<Compile Include="DynamoApplicationTests.cs" />
<Compile Include="ExecutionEventsObserver.cs" />
<Compile Include="IncrementingTraceTests.cs" />
<Compile Include="MinimalTraceTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestWrapperCleanup.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\DynamoApplications\DynamoApplications.csproj">
<Project>{aa782772-fe61-4226-baa4-eb529fa1646b}</Project>
<Name>DynamoApplications</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\src\DynamoCoreWpf\DynamoCoreWpf.csproj">
<Project>{51bb6014-43f7-4f31-b8d3-e3c37ebedaf4}</Project>
<Name>DynamoCoreWpf</Name>
Expand All @@ -147,6 +152,10 @@
<Name>DynamoServices</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\src\Tools\DynamoShapeManager\DynamoShapeManager.csproj">
<Project>{263fa9c1-f81e-4a8e-95e0-8cdae20f177b}</Project>
<Name>DynamoShapeManager</Name>
</ProjectReference>
<ProjectReference Include="..\..\DynamoCoreTests\DynamoCoreTests.csproj">
<Project>{472084ED-1067-4B2C-8737-3839A6143EB2}</Project>
<Name>DynamoCoreTests</Name>
Expand Down

0 comments on commit 1d49129

Please sign in to comment.