public void BuildAssemblyDependencyGraph_creates_a_graph_of_all_dependencies() { _graphBuilder.AddAssemblyAndAllDependencies(_testAssembly); AssemblyDependencyGraph graph = _graphBuilder.BuildAssemblyDependencyGraph(); graph.GetAssemblies().Should().Have.Count.EqualTo(5); // 5 non-System assemblies graph.GetAssemblies().Single(o => o.GetName().Name == "nunit.framework"); graph.GetAssemblies().Single(o => o.GetName().Name == "Inspector.Engine"); }
public void Add_should_obey_filtering() { var digraph = EmptyGraph(); var graph = new AssemblyDependencyGraph(digraph, new AssemblyLoaderStub(), x => false); var assembly = new AssemblyStub("MyAssembly"); graph.Add(assembly); digraph.Nodes.ShouldBeEmpty(); }
private static void FixUnityAssembliesStatusInDependencyGraph(AssemblyDependencyGraph dependencyGraph, IEnumerable <string> assemblyNames) { var unityAssemblies = assemblyNames.Where(an => an.StartsWith("UnityEngine") || an.StartsWith("UnityEditor")); foreach (var assemblyName in unityAssemblies) { var dep = dependencyGraph.FindAssembly(assemblyName); dep.Status |= AssemblyStatus.PublishesUpdaterConfigurations; // we know that those assemblies contains update configs } }
public void BuildAssemblyDependencyGraph_creates_edges_between_dependencies() { _graphBuilder.AddAssemblyAndAllDependencies(_testAssembly); AssemblyDependencyGraph graph = _graphBuilder.BuildAssemblyDependencyGraph(); IEnumerable <Assembly> dependencies = graph.GetDependantAssemblies(_testAssembly); dependencies.Single(o => o.GetName().Name == "nunit.framework"); dependencies.Single(o => o.GetName().Name == "Inspector.Engine"); }
public void Can_load_external_dlls_from_outside_bin_directory() { string libDir = GetLibDirectory(); string graphSharpFullPath = Path.Combine(libDir, "GraphSharp.dll"); _graphBuilder.AddAssemblyAndAllDependencies(graphSharpFullPath); AssemblyDependencyGraph graph = _graphBuilder.BuildAssemblyDependencyGraph(); Assembly graphSharpAssembly = new AssemblyLoader().LoadAssembly(graphSharpFullPath); IEnumerable <Assembly> dependencies = graph.GetDependantAssemblies(graphSharpAssembly); dependencies.Single(o => o.GetName().Name == "QuickGraph"); }
private static AssemblyDependencyGraph ReadOrCreateAssemblyDependencyGraph(string assemblyDependencyGraphFilePath) { try { if (File.Exists(assemblyDependencyGraphFilePath)) { using (var stream = File.OpenRead(assemblyDependencyGraphFilePath)) { return(AssemblyDependencyGraph.LoadFrom(stream)); } } } catch (IOException e) { APIUpdaterLogger.WriteToFile(string.Format(L10n.Tr("Failed to read assembly dependency graph ({0}). Exception: {1}")), assemblyDependencyGraphFilePath, e); } return(new AssemblyDependencyGraph()); }
public void Should_follow_dependency_chain() { var digraph = EmptyGraph(); var loader = new AssemblyLoaderStub(); var graph = new AssemblyDependencyGraph(digraph, loader); var root = new AssemblyStub("RootAssembly"); var systemXml = new AssemblyStub("System.Xml"); var system = new AssemblyName("System"); var loaded = new List<AssemblyName>(); loader.Loading += loaded.Add; loader.Add(systemXml); root.GetReferencedAssembliesHandler = () => new []{ systemXml.Name }; systemXml.GetReferencedAssembliesHandler = () => new []{ system }; graph.Add(root); Assert.That(loaded.Map(x => x.Name).ToList(), Is.EquivalentTo(new[] { system.Name, systemXml.Name.Name })); }
static void Main(string[] args) { var config = XmlConfiguration.FromFile(args[0]).Read<ProjectConfiguration>(); var loader = new StaticAssemblyLoader(); var assemblies = new List<IAssembly>(); var fs = new FileSystem(); fs.GetFiles(new Pencil.IO.Path(config.BinPath), "*.*") .ForEach(IsAssembly, path => { var assembly = AssemblyLoader.LoadFrom(path.ToString()); loader.Register(assembly); assemblies.Add(assembly); }); var digraph = new DirectedGraph(); var dependencies = new AssemblyDependencyGraph(digraph, loader, IgnoreFilter.From(config.IgnoreAssemblies)); assemblies.ForEach(dependencies.Add); new Pipe("invalid_path_to_dot", "-Tpng").Transfer( stream => new DotBuilder(stream).Write(digraph), stream => fs.WriteFile(new Path("output.png"), stream)); }
private static void SaveDependencyGraph(AssemblyDependencyGraph dependencyGraph, string path) { try { var targetDir = Path.GetDirectoryName(path); if (!Directory.Exists(targetDir)) { Directory.CreateDirectory(targetDir); } using (var file = File.Open(path, System.IO.FileMode.Create)) { dependencyGraph.SaveTo(file); } } catch (UnauthorizedAccessException ex) { APIUpdaterLogger.WriteToFile(string.Format(L10n.Tr("Failed to save assembly dependency graph ({0}). Exception: {1}")), path, ex); } catch (IOException ex) { APIUpdaterLogger.WriteToFile(string.Format(L10n.Tr("Failed to save assembly dependency graph ({0}). Exception: {1}")), path, ex); } }
public void Should_support_filter_function() { var digraph = EmptyGraph(); var graph = new AssemblyDependencyGraph(digraph, new AssemblyLoaderStub(), x => x.Name != "System"); var assembly = GetAssemblyDependingOnSystem(); graph.Add(assembly); Assert.That(digraph.Nodes.Map(x => x.Label).ToList(), Is.EquivalentTo(new[]{ assembly.Name.Name})); }
private static AssemblyUpdateCandidate CandidateForUpdatingFrom(string candidateAssemblyName, AssemblyDependencyGraph rootDepGraph) { string resolvedAssemblyPath = ResolveAssemblyPath(candidateAssemblyName); // this may happen if, for instance, after setting the dependency A -> B, *B* gets removed and *A* gets updated to a new version (we don't remove // the dependency from the graph. if (string.IsNullOrEmpty(resolvedAssemblyPath)) { return(null); } var depGraph = rootDepGraph.FindAssembly(candidateAssemblyName); var referencesAssemblyWithUpdaterConfigs = depGraph.Dependencies.Where(depAssembly => (rootDepGraph.FindAssembly(depAssembly.Name)?.Status & AssemblyStatus.PublishesUpdaterConfigurations) == AssemblyStatus.PublishesUpdaterConfigurations); var updaterConfigSources = ResolvePathOfAssembliesWithUpdaterConfigurations(referencesAssemblyWithUpdaterConfigs); return(new AssemblyUpdateCandidate { Name = candidateAssemblyName, Path = resolvedAssemblyPath, DependencyGraph = depGraph, UpdateConfigSources = updaterConfigSources }); }
private static void AddDependentAssembliesToUpdateList(HashSet <AssemblyUpdateCandidate> assembliesToUpdate, AssemblyDependencyGraph depGraph, AssemblyUpdateCandidate imported) { var dependents = depGraph.GetDependentsOf(imported.Name); var candidatesToUpdate = dependents.Select(assemblyName => CandidateForUpdatingFrom(assemblyName, depGraph)); foreach (var candidate in candidatesToUpdate.Where(c => c != null)) { assembliesToUpdate.Add(candidate); } }
private static void UpdatePublishUpdaterConfigStatusAndAddDependents(HashSet <AssemblyUpdateCandidate> assembliesToUpdate, IEnumerable <AssemblyUpdateCandidate> candidatesForUpdating, AssemblyDependencyGraph depGraph) { var tasks = candidatesForUpdating .Where(a => AssemblyHelper.IsManagedAssembly(a.Path) && IsAssemblyInPackageOrExtensionFolder(a)) .Select(a => new AssemblyUpdaterCheckAssemblyPublishConfigsTask(a)).ToArray(); if (tasks.Length == 0) { return; } foreach (var task in tasks) { ThreadPool.QueueUserWorkItem(RunAssemblyUpdaterTask, task); } var waitEvents = tasks.Select(t => t.Event).ToArray(); var timeout = TimeSpan.FromSeconds(30); if (!WaitHandle.WaitAll(waitEvents, timeout)) { LogTimeoutError(tasks, timeout); } var nonTimedOutTasks = tasks.Where(t => t.Event.WaitOne(0)).ToArray(); if (HandleCheckAssemblyPublishUpdaterConfigErrors(nonTimedOutTasks)) { return; } foreach (var task in nonTimedOutTasks) { if ((task.Result & APIUpdaterAssemblyHelper.ContainsUpdaterConfigurations) == APIUpdaterAssemblyHelper.ContainsUpdaterConfigurations) { var importedCandidate = task.Candidate; importedCandidate.DependencyGraph.Status |= AssemblyStatus.PublishesUpdaterConfigurations; AddDependentAssembliesToUpdateList(assembliesToUpdate, depGraph, importedCandidate); } } }
public void SetUp() { _assembly1 = GetType().Assembly; _assembly2 = typeof(AssemblyDependencyGraph).Assembly; _graph = new AssemblyDependencyGraph(); }
public void Should_handle_circular_dependencies() { var digraph = EmptyGraph(); var loader = new AssemblyLoaderStub(); var graph = new AssemblyDependencyGraph(digraph, loader); var system = new AssemblyStub("System"); var systemXml = new AssemblyStub("System.Xml"); system.GetReferencedAssembliesHandler = () => new[] { systemXml.Name }; systemXml.GetReferencedAssembliesHandler = () => new[] { system.Name }; loader.Add(system); loader.Add(systemXml); graph.Add(system); Assert.That(digraph.Edges.Map(x => x.ToString()).ToList(), Is.EquivalentTo(new[] { "0->1", "1->0" })); }
/* * Given a list of assemblies, returns those that references assemblies contributing updater configurations * sorted by dependency (i.e, given assemblies, A, B & C such A -> B -> C, should return in C, B, A order) */ private static IEnumerable <AssemblyUpdateCandidate> FindCandidatesForUpdatingSortedByDependency(IEnumerable <string> assemblyPaths, AssemblyDependencyGraph depGraph) { var candidates = new HashSet <AssemblyUpdateCandidate>(); foreach (var assemblyPath in assemblyPaths) { var assemblyName = Path.GetFileNameWithoutExtension(assemblyPath); var depInfo = depGraph.FindAssembly(assemblyName); Debug.Assert(depInfo != null); // Any referenced assemblies contains updater configs? var referencedAssembliesWithUpdaterConfigs = depInfo.Dependencies.Where(a => (depGraph.FindAssembly(a.Name)?.Status & AssemblyStatus.PublishesUpdaterConfigurations) == AssemblyStatus.PublishesUpdaterConfigurations); if (referencedAssembliesWithUpdaterConfigs.Any()) { var isUnityExtension = assemblyPath.IsUnityExtension(); IEnumerable <string> updateConfigSources = new string[0]; // UnityExtensions should never use obsolete APIs (i.e, we should never need to update them) if (!isUnityExtension) { updateConfigSources = ResolvePathOfAssembliesWithUpdaterConfigurations(referencedAssembliesWithUpdaterConfigs); } candidates.Add(new AssemblyUpdateCandidate { Name = assemblyName, Path = assemblyPath, DependencyGraph = depInfo, UpdateConfigSources = updateConfigSources }); } } // add the candidates sorted based on the dependency graph... var result = new List <AssemblyUpdateCandidate>(); foreach (var assemblyName in depGraph.SortedDependents()) { // We may have assemblies with the same name in different folders // (for example GUISystem/Standalone/UnityEngine.UI.dll & GUISystem/UnityEngine.UI.dll) var filteredCandidates = candidates.Where(c => CompareIgnoreCase(c.Name, assemblyName)); result.AddRange(filteredCandidates); } return(result); }