コード例 #1
0
        /// <inheritdoc />
        public ITestCommand BuildCommands(TestModel testModel, FilterSet <ITestDescriptor> filterSet, bool exactFilter, ITestContextManager contextManager)
        {
            if (testModel == null)
            {
                throw new ArgumentNullException("testModel");
            }
            if (filterSet == null)
            {
                throw new ArgumentNullException("filterSet");
            }
            if (contextManager == null)
            {
                throw new ArgumentNullException("contextManager");
            }

            var  commands                  = new Dictionary <Test, ManagedTestCommand>();
            bool hasExplicitAncestor       = !filterSet.HasInclusionRules;
            ManagedTestCommand rootCommand = CreateFilteredClosure(commands, testModel.RootTest, filterSet, exactFilter,
                                                                   hasExplicitAncestor, contextManager);

            if (rootCommand == null)
            {
                return(null);
            }

            var siblingDependencies = new MultiMap <ManagedTestCommand, ManagedTestCommand>();

            PopulateCommandDependencies(commands, siblingDependencies);

            SortChildren(rootCommand, siblingDependencies);
            return(rootCommand);
        }
コード例 #2
0
        /// <summary>
        /// Gets the list of children as an array.
        /// </summary>
        /// <returns>The array of children.</returns>
        public ManagedTestCommand[] ChildrenToArray()
        {
            if (children == null)
            {
                return(EmptyArray <ManagedTestCommand> .Instance);
            }

            ManagedTestCommand[] array = new ManagedTestCommand[children.Count];
            children.CopyTo(array);
            return(array);
        }
コード例 #3
0
        /// <summary>
        /// Adds a test command dependency.
        /// </summary>
        /// <param name="dependency">The dependency to add.</param>
        public void AddDependency(ManagedTestCommand dependency)
        {
            if (dependency == null)
            {
                throw new ArgumentNullException("dependency");
            }

            if (dependencies == null)
            {
                dependencies = new List <ITestCommand>();
            }
            dependencies.Add(dependency);
        }
コード例 #4
0
        /// <summary>
        /// Adds a child test command.
        /// </summary>
        /// <param name="child">The child to add.</param>
        public void AddChild(ManagedTestCommand child)
        {
            if (child == null)
            {
                throw new ArgumentNullException("child");
            }

            if (children == null)
            {
                children = new List <ITestCommand>();
            }
            children.Add(child);
        }
コード例 #5
0
        private ManagedTestCommand CreateCommand(Dictionary <Test, ManagedTestCommand> commands,
                                                 Test test, IEnumerable <ManagedTestCommand> children, bool isExplicit, ITestContextManager contextManager)
        {
            var testMonitor = new ManagedTestCommand(contextManager, test, isExplicit);

            foreach (ManagedTestCommand child in children)
            {
                testMonitor.AddChild(child);
            }

            commands.Add(test, testMonitor);
            return(testMonitor);
        }
コード例 #6
0
        private ManagedTestCommand CreateFilteredClosure(Dictionary <Test, ManagedTestCommand> commands,
                                                         Test test, FilterSet <ITestDescriptor> filterSet, bool exactFilter, bool hasExplicitAncestor, ITestContextManager contextManager)
        {
            FilterSetResult filterSetResult = filterSet.Evaluate(test);

            if (filterSetResult == FilterSetResult.Exclude)
            {
                return(null);
            }

            bool isMatch          = filterSetResult == FilterSetResult.Include;
            bool isExplicit       = isMatch && !hasExplicitAncestor;
            bool hasExplicitChild = false;

            var children = new List <ManagedTestCommand>(test.Children.Count);

            foreach (Test child in test.Children)
            {
                ManagedTestCommand childMonitor = CreateFilteredClosure(commands, child, filterSet, exactFilter,
                                                                        hasExplicitAncestor || isExplicit, contextManager);
                if (childMonitor != null)
                {
                    children.Add(childMonitor);

                    if (childMonitor.IsExplicit)
                    {
                        hasExplicitChild = true;
                    }
                }
            }

            if (isMatch || children.Count != 0 || (!exactFilter && hasExplicitAncestor))
            {
                return(CreateCommand(commands, test, children, isExplicit || hasExplicitChild, contextManager));
            }

            return(null);
        }
コード例 #7
0
        /// <summary>
        /// Gets the list of children as an array.
        /// </summary>
        /// <returns>The array of children.</returns>
        public ManagedTestCommand[] ChildrenToArray()
        {
            if (children == null)
                return EmptyArray<ManagedTestCommand>.Instance;

            ManagedTestCommand[] array = new ManagedTestCommand[children.Count];
            children.CopyTo(array);
            return array;
        }
コード例 #8
0
        /// <summary>
        /// Adds a test command dependency.
        /// </summary>
        /// <param name="dependency">The dependency to add.</param>
        public void AddDependency(ManagedTestCommand dependency)
        {
            if (dependency == null)
                throw new ArgumentNullException("dependency");

            if (dependencies == null)
                dependencies = new List<ITestCommand>();
            dependencies.Add(dependency);
        }
コード例 #9
0
        /// <summary>
        /// Adds a child test command.
        /// </summary>
        /// <param name="child">The child to add.</param>
        public void AddChild(ManagedTestCommand child)
        {
            if (child == null)
                throw new ArgumentNullException("child");

            if (children == null)
                children = new List<ITestCommand>();
            children.Add(child);
        }
コード例 #10
0
 public DepthFirstEntry(ManagedTestCommand source, IEnumerable<ManagedTestCommand> dependencies)
 {
     Source = source;
     DependencyEnumerator = dependencies.GetEnumerator();
 }
コード例 #11
0
 private void SortCommandsByOrder(ManagedTestCommand[] commands)
 {
     Array.Sort(commands, (a, b) => testOrderStrategy.Compare(a.Test, b.Test));
 }
コード例 #12
0
        private void SortChildren(ManagedTestCommand parent, MultiMap<ManagedTestCommand, ManagedTestCommand> siblingDependencies)
        {
            ManagedTestCommand[] children = parent.ChildrenToArray();
            if (children.Length == 0)
                return;

            // Clear the array of children since we are about to reshuffle them.
            parent.ClearChildren();

            // Sort the children by order.  Because the topological sort emits vertices precisely
            // in the ordert that it visits them (depth-first) it will preserve the relative ordering
            // of independent vertices.  So we influence test execution order by pre-sorting.
            // Dependencies will of course interfere with the ordering slightly.  However, if the
            // user explicitly specifies orderings in dependency order then they'll indeed run in
            // that specified order.  -- Jeff.
            SortCommandsByOrder(children);

            // Perform a topological sort of the children using depth-first search.
            // Because at this stage a command only has dependencies on its siblings the depth-first search
            // actually proceeds down the chain of sibling dependencies only; it does not
            // traverse the whole test hierarchy.  -- Jeff.
            Dictionary<ManagedTestCommand, bool> visitedSet = new Dictionary<ManagedTestCommand, bool>();
            Stack<DepthFirstEntry> stack = new Stack<DepthFirstEntry>();

            stack.Push(new DepthFirstEntry(null, children));
            for (;;)
            {
                DepthFirstEntry top = stack.Peek();
                if (top.DependencyEnumerator.MoveNext())
                {
                    ManagedTestCommand current = top.DependencyEnumerator.Current;

                    bool inProgressFlag;
                    if (visitedSet.TryGetValue(current, out inProgressFlag))
                    {
                        if (inProgressFlag)
                            throw new ModelException(String.Format("Found a test dependency cycle involving test '{0}'.",
                                current.Test.FullName));
                    }
                    else
                    {
                        IList<ManagedTestCommand> unorderedDependencies = siblingDependencies[current];
                        if (unorderedDependencies.Count != 0)
                        {
                            visitedSet[current] = true;

                            // We need to sort all visited children so that dependencies run in relative order.
                            ManagedTestCommand[] dependencies = GenericCollectionUtils.ToArray(unorderedDependencies);
                            SortCommandsByOrder(dependencies);

                            stack.Push(new DepthFirstEntry(current, dependencies));
                        }
                        else
                        {
                            parent.AddChild(current);
                            visitedSet[current] = false;
                        }
                    }
                }
                else
                {
                    ManagedTestCommand current = top.Source;
                    if (current == null)
                        break;

                    parent.AddChild(current);
                    visitedSet[current] = false;
                    stack.Pop();
                }
            }

            // Recursively sort the children of this command.
            foreach (ManagedTestCommand child in children)
                SortChildren(child, siblingDependencies);
        }
コード例 #13
0
        private ManagedTestCommand CreateCommand(Dictionary<Test, ManagedTestCommand> commands,
            Test test, IEnumerable<ManagedTestCommand> children, bool isExplicit, ITestContextManager contextManager)
        {
            var testMonitor = new ManagedTestCommand(contextManager, test, isExplicit);
            foreach (ManagedTestCommand child in children)
                testMonitor.AddChild(child);

            commands.Add(test, testMonitor);
            return testMonitor;
        }
コード例 #14
0
 public DepthFirstEntry(ManagedTestCommand source, IEnumerable <ManagedTestCommand> dependencies)
 {
     Source = source;
     DependencyEnumerator = dependencies.GetEnumerator();
 }
コード例 #15
0
        private void SortChildren(ManagedTestCommand parent, MultiMap <ManagedTestCommand, ManagedTestCommand> siblingDependencies)
        {
            ManagedTestCommand[] children = parent.ChildrenToArray();
            if (children.Length == 0)
            {
                return;
            }

            // Clear the array of children since we are about to reshuffle them.
            parent.ClearChildren();

            // Sort the children by order.  Because the topological sort emits vertices precisely
            // in the ordert that it visits them (depth-first) it will preserve the relative ordering
            // of independent vertices.  So we influence test execution order by pre-sorting.
            // Dependencies will of course interfere with the ordering slightly.  However, if the
            // user explicitly specifies orderings in dependency order then they'll indeed run in
            // that specified order.  -- Jeff.
            SortCommandsByOrder(children);

            // Perform a topological sort of the children using depth-first search.
            // Because at this stage a command only has dependencies on its siblings the depth-first search
            // actually proceeds down the chain of sibling dependencies only; it does not
            // traverse the whole test hierarchy.  -- Jeff.
            Dictionary <ManagedTestCommand, bool> visitedSet = new Dictionary <ManagedTestCommand, bool>();
            Stack <DepthFirstEntry> stack = new Stack <DepthFirstEntry>();

            stack.Push(new DepthFirstEntry(null, children));
            for (;;)
            {
                DepthFirstEntry top = stack.Peek();
                if (top.DependencyEnumerator.MoveNext())
                {
                    ManagedTestCommand current = top.DependencyEnumerator.Current;

                    bool inProgressFlag;
                    if (visitedSet.TryGetValue(current, out inProgressFlag))
                    {
                        if (inProgressFlag)
                        {
                            throw new ModelException(String.Format("Found a test dependency cycle involving test '{0}'.",
                                                                   current.Test.FullName));
                        }
                    }
                    else
                    {
                        IList <ManagedTestCommand> unorderedDependencies = siblingDependencies[current];
                        if (unorderedDependencies.Count != 0)
                        {
                            visitedSet[current] = true;

                            // We need to sort all visited children so that dependencies run in relative order.
                            ManagedTestCommand[] dependencies = GenericCollectionUtils.ToArray(unorderedDependencies);
                            SortCommandsByOrder(dependencies);

                            stack.Push(new DepthFirstEntry(current, dependencies));
                        }
                        else
                        {
                            parent.AddChild(current);
                            visitedSet[current] = false;
                        }
                    }
                }
                else
                {
                    ManagedTestCommand current = top.Source;
                    if (current == null)
                    {
                        break;
                    }

                    parent.AddChild(current);
                    visitedSet[current] = false;
                    stack.Pop();
                }
            }

            // Recursively sort the children of this command.
            foreach (ManagedTestCommand child in children)
            {
                SortChildren(child, siblingDependencies);
            }
        }