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 }));
        }
Example #8
0
        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();
 }
Example #15
0
 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);
        }