private void ExecuteTestsInSource()

in src/Adapter/MSTest.CoreAdapter/Execution/TestExecutionManager.cs [210:355]


        private void ExecuteTestsInSource(IEnumerable<TestCase> tests, IRunContext runContext, IFrameworkHandle frameworkHandle, string source, bool isDeploymentDone)
        {
            Debug.Assert(!string.IsNullOrEmpty(source), "Source cannot be empty");

            if (isDeploymentDone)
            {
                source = Path.Combine(PlatformServiceProvider.Instance.TestDeployment.GetDeploymentDirectory(), Path.GetFileName(source));
            }

            using (var isolationHost = PlatformServiceProvider.Instance.CreateTestSourceHost(source, runContext?.RunSettings, frameworkHandle))
            {
                // Create an instance of a type defined in adapter so that adapter gets loaded in the child app domain
                var testRunner = isolationHost.CreateInstanceForType(
                    typeof(UnitTestRunner),
                    new object[] { MSTestSettings.CurrentSettings }) as UnitTestRunner;

                PlatformServiceProvider.Instance.AdapterTraceLogger.LogInfo("Created unit-test runner {0}", source);

                // Default test set is filtered tests based on user provided filter criteria
                ICollection<TestCase> testsToRun = new TestCase[0];
                var filterExpression = this.TestMethodFilter.GetFilterExpression(runContext, frameworkHandle, out var filterHasError);
                if (filterHasError)
                {
                    // Bail out without processing everything else below.
                    return;
                }

                testsToRun = tests.Where(t => MatchTestFilter(filterExpression, t, this.TestMethodFilter)).ToArray();

                // this is done so that appropriate values of test context properties are set at source level
                // and are merged with session level parameters
                var sourceLevelParameters = PlatformServiceProvider.Instance.SettingsProvider.GetProperties(source);

                if (this.sessionParameters != null && this.sessionParameters.Count > 0)
                {
                    sourceLevelParameters = this.sessionParameters.ConcatWithOverwrites(sourceLevelParameters);
                }

                TestAssemblySettingsProvider sourceSettingsProvider = null;

                try
                {
                    sourceSettingsProvider = isolationHost.CreateInstanceForType(
                        typeof(TestAssemblySettingsProvider),
                        null) as TestAssemblySettingsProvider;
                }
                catch (Exception ex)
                {
                    PlatformServiceProvider.Instance.AdapterTraceLogger.LogInfo("Could not create TestAssemblySettingsProvider instance in child app-domain", ex);
                }

                var sourceSettings = (sourceSettingsProvider != null) ? sourceSettingsProvider.GetSettings(source) : new TestAssemblySettings();
                var parallelWorkers = sourceSettings.Workers;
                var parallelScope = sourceSettings.Scope;
                this.InitializeClassCleanupManager(source, testRunner, testsToRun, sourceSettings);

                if (MSTestSettings.CurrentSettings.ParallelizationWorkers.HasValue)
                {
                    // The runsettings value takes precedence over an assembly level setting. Reset the level.
                    parallelWorkers = MSTestSettings.CurrentSettings.ParallelizationWorkers.Value;
                }

                if (MSTestSettings.CurrentSettings.ParallelizationScope.HasValue)
                {
                    // The runsettings value takes precedence over an assembly level setting. Reset the level.
                    parallelScope = MSTestSettings.CurrentSettings.ParallelizationScope.Value;
                }

                if (!MSTestSettings.CurrentSettings.DisableParallelization && sourceSettings.CanParallelizeAssembly && parallelWorkers > 0)
                {
                    // Parallelization is enabled. Let's do further classification for sets.
                    var logger = (IMessageLogger)frameworkHandle;
                    logger.SendMessage(
                        TestMessageLevel.Informational,
                        string.Format(CultureInfo.CurrentCulture, Resource.TestParallelizationBanner, source, parallelWorkers, parallelScope));

                    // Create test sets for execution, we can execute them in parallel based on parallel settings
                    IEnumerable<IGrouping<bool, TestCase>> testsets = Enumerable.Empty<IGrouping<bool, TestCase>>();

                    // Parallel and not parallel sets.
                    testsets = testsToRun.GroupBy(t => t.GetPropertyValue<bool>(TestAdapter.Constants.DoNotParallelizeProperty, false));

                    var parallelizableTestSet = testsets.FirstOrDefault(g => g.Key == false);
                    var nonparallelizableTestSet = testsets.FirstOrDefault(g => g.Key == true);

                    if (parallelizableTestSet != null)
                    {
                        ConcurrentQueue<IEnumerable<TestCase>> queue = null;

                        // Chunk the sets into further groups based on parallel level
                        switch (parallelScope)
                        {
                            case ExecutionScope.MethodLevel:
                                queue = new ConcurrentQueue<IEnumerable<TestCase>>(parallelizableTestSet.Select(t => new[] { t }));
                                break;

                            case ExecutionScope.ClassLevel:
                                queue = new ConcurrentQueue<IEnumerable<TestCase>>(parallelizableTestSet.GroupBy(t => t.GetPropertyValue(TestAdapter.Constants.TestClassNameProperty) as string));
                                break;
                        }

                        var tasks = new List<Task>();

                        for (int i = 0; i < parallelWorkers; i++)
                        {
                            tasks.Add(Task.Factory.StartNew(
                                () =>
                                {
                                    while (!queue.IsEmpty)
                                    {
                                        if (this.cancellationToken != null && this.cancellationToken.Canceled)
                                        {
                                            // if a cancellation has been requested, do not queue any more test runs.
                                            break;
                                        }

                                        if (queue.TryDequeue(out IEnumerable<TestCase> testSet))
                                        {
                                            this.ExecuteTestsWithTestRunner(testSet, runContext, frameworkHandle, source, sourceLevelParameters, testRunner);
                                        }
                                    }
                                },
                            CancellationToken.None,
                            TaskCreationOptions.LongRunning,
                            TaskScheduler.Default));
                        }

                        Task.WaitAll(tasks.ToArray());
                    }

                    // Queue the non parallel set
                    if (nonparallelizableTestSet != null)
                    {
                        this.ExecuteTestsWithTestRunner(nonparallelizableTestSet, runContext, frameworkHandle, source, sourceLevelParameters, testRunner);
                    }
                }
                else
                {
                    this.ExecuteTestsWithTestRunner(testsToRun, runContext, frameworkHandle, source, sourceLevelParameters, testRunner);
                }

                this.RunCleanup(frameworkHandle, testRunner);

                PlatformServiceProvider.Instance.AdapterTraceLogger.LogInfo("Executed tests belonging to source {0}", source);
            }
        }