Пример #1
0
        public List <TestEntry> GetTestsFor(List <string> assemblies)
        {
            var ret   = new List <TestEntry>();
            var param = from a in assemblies select new BuildFullMapParams(a, a);

            BuildFullMap(param);
            toDispose.Clear();
            changes = GetChanges(assemblies);
            if (changes != null)
            {
                foreach (var change in changes)
                {
                    InvokeMinimizerMessage(MessageType.Debug, change.ChangeType + " " + change.ItemChanged.GetCacheName());
                }
                ReIndex(changes);
            }

            toDispose.ForEach(x => x.Dispose());
            ModuleDefinition.KillAllReadModules();
            var strategy = new GraphBuilder(_cache, _testStrategies, new IfInTestAssemblyContinueInterfaceFollowingStrategy(_cache), _debug, _numThreads);

            strategy.DebugMessage += (x, y) => InvokeMinimizerMessage(y.MessageType, y.Message);
            _lastAffectedGraph     = strategy.GetAffectedGraphForChangeSet(changes);
            var entries = BuildEntriesFor(_lastAffectedGraph).ToList();

            foreach (var file in assemblies)
            {
                WriteHistoryFile(file);
            }
            return(entries);
        }
Пример #2
0
        public AffectedGraph GetAffectedGraphForChangeSet(IEnumerable <Change <MethodReference> > changes)
        {
            InvokeMinimizerMessage(MessageType.Debug, "getting tests for changes");
            var start         = DateTime.Now;
            var graph         = new AffectedGraph();
            var breadCrumbs   = new Dictionary <string, bool>();
            var affectedItems = GetAffectedItems(changes, graph);
            var rets          = affectedItems.ForkAndJoinTo(_numthreads, x =>
            {
                var tmp = new AffectedGraph();
                FillAfferentGraph(x.Member, breadCrumbs,
                                  tmp, null, 0, null, false,
                                  new List <string>(),
                                  GenericContext.Empty(), false);
                return(tmp);
            });

            InvokeMinimizerMessage(MessageType.Debug, "there are " + rets.Count() + " graphs returned. Combining.");
            foreach (var g in rets)
            {
                if (g != null)
                {
                    InvokeMinimizerMessage(MessageType.Debug,
                                           "there are " + g.AllNodes().Count() + " Nodes in graph. TOTAL=" +
                                           graph.AllNodes().Count());
                    graph = graph.Merge(g);
                }
            }
            InvokeMinimizerMessage(MessageType.Debug, "there are " + rets.Count() + " nodes in combined graph.");
            var end = DateTime.Now;

            InvokeMinimizerMessage(MessageType.Debug, "took " + (end - start) + " to walk graph");
            return(graph);
        }
Пример #3
0
        public AffectedGraph GetCouplingGraphFor(string cacheName)
        {
            var            affected            = new List <ChangeContext>();
            var            graph               = new AffectedGraph();
            var            forwardCutOffPoints = new Dictionary <string, bool>();
            var            backCutOffPoints    = new Dictionary <string, bool>();
            TypeDefinition scope               = null;

            GetEfferentGraph(null, cacheName, forwardCutOffPoints, affected, graph, true, scope);
            WriteWalkerDebug("got " + affected + " nodes for " + cacheName, 0);
            var rets = affected.ForkAndJoinTo(_numthreads, x =>
            {
                FillAfferentGraph(x.Member, backCutOffPoints, graph, null, 0, null, false, new List <string>(), GenericContext.Empty(), false); //gets all tests Ca
                return(true);
            });

            return(graph);
        }
Пример #4
0
 public void EnrichGraph(AffectedGraph graph)
 {
     foreach (var node in graph.AllNodes())
     {
         var cachenode = TryGetEfferentCouplingNode(node.FullName.Replace('+', '/'));
         if (cachenode != null)
         {
             var r = cachenode.MemberReference;
             if (r != null)
             {
                 node.DisplayName = r.DeclaringType.Name + "::" + r.Name;
                 node.Assembly    = r.Module.Assembly.FullName;
                 node.IsInterface = r.DeclaringType.ThreadSafeResolve().IsInterface;
             }
             node.Profiled = true;
             node.IsTest   = _testIdentifiers.IsTest(cachenode.MemberReference);
         }
     }
 }
Пример #5
0
 private IEnumerable <TestEntry> BuildEntriesFor(AffectedGraph graph)
 {
     InvokeMinimizerMessage(MessageType.Info, "there are " + graph.AllNodes().Count() + "in the graph.");
     foreach (var n in graph.AllNodes())
     {
         if (n.TestDescriptors == null)
         {
             continue;
         }
         foreach (var desc in n.TestDescriptors)
         {
             yield return(new TestEntry
             {
                 TestAssembly = n.Assembly,
                 TestClass = n.Type,
                 TestName = desc.Target,
                 TestRunners = new List <string> {
                     desc.TestRunner
                 }
             });
         }
     }
 }
Пример #6
0
 static IEnumerable <TestDescriptor> GetTestsInGraph(AffectedGraph graph)
 {
     return(graph.AllNodes().Where(entry => entry.IsTest).SelectMany(entry => entry.TestDescriptors));
 }
Пример #7
0
        private void RecurseSynonyms(int depth, Dictionary <string, bool> history, TypeDefinition inheritedTypeContext, MethodDefinition currentDefinition, AffectedGraph graph, List <string> breadCrumbs, GenericContext genericContext)
        {
            var synonyms = SynonymFinder.FindSynonymsFor(currentDefinition);

            foreach (var current in synonyms)
            {
                var c = current as MethodDefinition;
                if (c == null)
                {
                    continue;            //shouldn't happen
                }
                if (!c.DeclaringType.IsInterface)
                {
                    FillAfferentGraph(current.GetCacheName(), history, graph, currentDefinition, depth + 1,
                                      inheritedTypeContext, true, breadCrumbs, genericContext, true); //always a base
                }
                else
                {
                    FillAfferentGraph(current.GetCacheName(), history, graph, currentDefinition, depth + 1,
                                      inheritedTypeContext, false, breadCrumbs, genericContext, false);
                }
            }
        }
Пример #8
0
        private void RecurseAfferentCouplings(string fullName, int depth, Dictionary <string, bool> history, bool inInheritanceChain, TypeDefinition inheritedTypeContext, AffectedGraph graph, MemberReference parent, List <string> breadCrumbs, GenericContext genericContext)
        {
            var afferentEntry = _cache.TryGetAfferentCouplingNode(fullName);

            if (afferentEntry == null)
            {
                return;
            }
            genericContext.SetIndirectConstraintsOn(afferentEntry.MemberReference, parent, inInheritanceChain);
            if (!inInheritanceChain && genericContext.IsClear())
            {
                lock (history) //double lock, TryCutPointPrune already did this
                {
                    if (!history.ContainsKey(fullName))
                    {
                        history.Add(fullName, true);
                    }
                }
            }
            foreach (var current in afferentEntry.Couplings)
            {
                if (current.IgnoreWalk)
                {
                    continue;
                }
                var proposed = genericContext.GetGenericContextOf(current.ActualReference);
                if (!genericContext.CanTransitionTo(proposed))
                {
                    WriteWalkerDebug("Generics truncate", depth);
                    continue;
                }
                var newContext = genericContext.TransitionTo(proposed);
                FillAfferentGraph(current.To, history, graph, afferentEntry.MemberReference, depth + 1, inheritedTypeContext, inInheritanceChain && current.IsSelfCall, breadCrumbs, newContext, current.IsSelfCall);
            }
        }
Пример #9
0
        private void FillAfferentGraph(string fullName, Dictionary <string, bool> cutPoints, AffectedGraph graph, MemberReference parent, int depth, TypeDefinition inheritedTypeContext, bool inVirtual, List <string> breadCrumbs, GenericContext genericContext, bool inSelf)
        {
            WriteWalkerDebug(fullName, depth);
            if (TryBreadCrumbsPrune(fullName, depth, breadCrumbs))
            {
                if (parent != null)
                {
                    WriteWalkerDebug("truncating but adding connection to " + fullName, depth);
                    graph.AddConnection(parent.GetCacheName(), fullName, false);
                }
                return;
            }
            breadCrumbs.Add(fullName);
            if (TryCutPointPrune(fullName, depth, cutPoints))
            {
                if (parent != null)
                {
                    WriteWalkerDebug("bread crumbs truncating but adding connection to " + fullName, depth);
                    graph.AddConnection(parent.GetCacheName(), fullName, false);
                }
                return;
            }

            var efferentEntry = _cache.TryGetEfferentCouplingNode(fullName);
            var afferentEntry = _cache.TryGetEfferentCouplingNode(fullName);
            MethodDefinition currentDefinition = null;

            if (efferentEntry != null)
            {
                TypeReference parentType = null;
                if (parent != null)
                {
                    parentType = parent.DeclaringType;
                }
                var definition = efferentEntry.MemberReference.DeclaringType.ThreadSafeResolve();
                if (TryInterfacePrune(fullName, depth, breadCrumbs, efferentEntry, parentType, definition))
                {
                    return;
                }
                if (TryInheritancePrune(fullName, depth, breadCrumbs, inVirtual, definition, inheritedTypeContext))
                {
                    return;
                }
                inheritedTypeContext = GetNewTypeContext(inheritedTypeContext, definition);
                currentDefinition    = efferentEntry.MemberReference as MethodDefinition;
                if (currentDefinition != null)
                {
                    if (currentDefinition.DeclaringType == null)
                    {
                    }
                    if (parent is FieldReference && currentDefinition.IsConstructor)
                    {
                        breadCrumbs.Remove(fullName);
                        return;
                    }
                }
            }
            var touse = afferentEntry ?? efferentEntry;

            WriteWalkerDebug("adding node " + fullName, depth);
            var newnode = GetGraphNode(fullName, touse, parent == null, false);

            graph.AddNode(newnode);
            if (parent != null)
            {
                graph.AddConnection(parent.GetCacheName(), newnode.FullName, false);
            }
            if (currentDefinition != null)
            {
                RecurseSynonyms(depth, cutPoints, inheritedTypeContext, currentDefinition, graph, breadCrumbs, genericContext);
            }
            RecurseAfferentCouplings(fullName, depth, cutPoints, inVirtual, inheritedTypeContext, graph, parent, breadCrumbs, genericContext);
            breadCrumbs.Remove(fullName);
        }
Пример #10
0
        private void GetEfferentGraph(string parent, string fullName, IDictionary <string, bool> cutOffs, List <ChangeContext> found, AffectedGraph graph, bool isRootNode, TypeDefinition originalContext)
        {
            var entry    = _cache.TryGetEfferentCouplingNode(fullName);
            var afferent = _cache.TryGetAfferentCouplingNode(fullName);

            if (isRootNode)
            {
                entry = entry ?? afferent;
                found.Add(new ChangeContext(fullName, null));
                graph.AddNode(GetGraphNode(fullName, entry, true, true));
                if (entry != null && entry.MemberReference != null)
                {
                    var refer = entry.MemberReference as MethodReference;
                    if (refer != null && _testStrategies.IsTest(refer))
                    {
                        return;
                    }
                }
            }
            //TODO Greg this hamstrings some stuff but should work better in most cases
            //I think we only really need statics past here but need to look it over a bit.
            return;

            WriteWalkerDebug("checking " + fullName, 0);
            if (entry == null)
            {
                WriteWalkerDebug("efferent entry is null", 0);
                if (afferent != null && afferent.MemberReference is MethodReference)
                {
                    return;                                                                  //Leaf node to a method call
                }
            }
            if (afferent == null)
            {
                WriteWalkerDebug("afferent entry is null", 0);
            }
            if (afferent != null)
            {
                var memref           = afferent.MemberReference as MethodReference;
                MethodDefinition def = null;
                if (memref != null)
                {
                    def = memref.ThreadSafeResolve();
                }
                if (!isRootNode && def != null)
                {
                    if (def.IsGetter)
                    {
                        return;
                    }
                    if (def.DeclaringType.IsInterface)
                    {
                        return;                                //don't recurse forward on interface calls
                    }
                    if (!def.HasThis)
                    {
                        return;
                    }
                }
                var reference = afferent.MemberReference as FieldReference; //Leaf node to a field reference
                if (reference != null)
                {
                    graph.AddNode(GetGraphNode(fullName, afferent, isRootNode, false));
                    if (parent != null)
                    {
                        graph.AddConnection(parent, fullName, true);
                    }

                    found.Add(new ChangeContext(fullName, originalContext));
                }
            }

            if (entry == null)
            {
                return;
            }
            graph.AddNode(GetGraphNode(fullName, entry, isRootNode, false));
            if (parent != null)
            {
                graph.AddConnection(parent, fullName, true);
            }
            foreach (var current in entry.Couplings)
            {
                if (cutOffs.ContainsKey(current.To))
                {
                    continue;
                }
                if (current.IgnoreWalk)
                {
                    continue;
                }
                if (current.ActualReference is MethodReference && !current.IsSelfCall)
                {
                    continue;
                }
                cutOffs.Add(current.To, true);
                GetEfferentGraph(fullName, current.To, cutOffs, found, graph, false, originalContext);
            }
        }
Пример #11
0
        private IEnumerable <ChangeContext> GetAffectedItems(IEnumerable <Change <MethodReference> > changes, AffectedGraph graph)
        {
            var affected = new List <ChangeContext>();

            foreach (var change in changes)
            {
                var forwardCutOffPoints = new Dictionary <string, bool>();
                if (change.ChangeType == ChangeType.Remove)
                {
                    continue;
                }
                change.ItemChanged.GetCacheName();
                var scope = change.ItemChanged.DeclaringType.ThreadSafeResolve();
                GetEfferentGraph(null, change.ItemChanged.GetCacheName(), forwardCutOffPoints, affected, graph, true, scope);
            }
            return(affected);
        }
Пример #12
0
 public void EnrichGraph(AffectedGraph graph)
 {
     _cache.EnrichGraph(graph);
 }