示例#1
0
        private async Task <string> ExecuteTestsWithNativeRunnerAsync(
            string workingDir,
            string testsLibraryPath,
            string assemblyName,
            bool runInParallel,
            int maxParallelProcessesCount,
            string nativeArguments,
            int testAgentRunTimeout,
            bool isTimeBasedBalance,
            bool sameMachineByClass,
            List <TestCase> distributedTestCases,
            CancellationTokenSource outerCancellationTokenSource)
        {
            var outputFilesDir = _pathProvider.GetDirectoryName(testsLibraryPath);
            var availableCores = runInParallel ? maxParallelProcessesCount : 1;

            // Merge logic of CreateRunFilterArgument here. remove inner foreach
            var listOfDistributedTestCases = _nativeTestsRunner.SplitTestCases(availableCores, sameMachineByClass, distributedTestCases);
            var testRunsToBeMerged         = new List <object>();
            var testRunProcesses           = new List <Process>();
            var resultsFiles = new List <string>();

            var processCreationTime = _dateTimeProvider.GetCurrentTime();

            foreach (var distributedTestCasesList in listOfDistributedTestCases)
            {
                var currentTestResultsFilePath = _pathProvider.GetTempFileName();
                resultsFiles.Add(currentTestResultsFilePath);
                var arguments = _nativeTestsRunner.BuildNativeRunnerArguments(
                    assemblyName,
                    testsLibraryPath,
                    distributedTestCasesList,
                    currentTestResultsFilePath,
                    outputFilesDir,
                    nativeArguments);

                var currentProcess = _processStarter.InitializeProcess(
                    _nativeTestsRunner.RunnerFile,
                    workingDir,
                    arguments,
                    LogStandardOutput,
                    LogErrorOutput);
                testRunProcesses.Add(currentProcess);
            }

            var innerCancellationTokenSource = new CancellationTokenSource();

            var waitForNativeRunnerProcessesToFinishTask = _taskProvider.StartNewLongRunning(
                (c) =>
            {
                var ranProcesses = new List <int>();
                do
                {
                    var coresCount = availableCores;
                    if (runInParallel)
                    {
                        foreach (var process in testRunProcesses)
                        {
                            if (coresCount == 0)
                            {
                                break;
                            }

                            if (!ranProcesses.Contains(process.GetHashCode()))
                            {
                                _processStarter.StartProcess(process, LogStandardOutput, LogErrorOutput);
                                Thread.Sleep(500);
                                ranProcesses.Add(process.GetHashCode());
                                coresCount--;
                            }
                        }
                    }

                    foreach (var process in testRunProcesses)
                    {
                        if (outerCancellationTokenSource.Token.IsCancellationRequested)
                        {
                            return;
                        }

                        if (!runInParallel)
                        {
                            // Start processes one by one, otherwise they are started all upfront.
                            _processStarter.StartProcess(process, LogStandardOutput, LogErrorOutput);
                            ranProcesses.Add(process.GetHashCode());
                        }

                        if (ranProcesses.Contains(process.GetHashCode()))
                        {
                            _processStarter.WaitForProcessToFinish(testAgentRunTimeout, process);
                        }
                    }
                }while (ranProcesses.Count != testRunProcesses.Count);
            },
                innerCancellationTokenSource);

            var checkCancellationRequestsTask = _taskProvider.StartNewLongRunningRepeating(
                innerCancellationTokenSource,
                () =>
            {
                if (waitForNativeRunnerProcessesToFinishTask.IsCompleted || waitForNativeRunnerProcessesToFinishTask.IsFaulted)
                {
                    if (waitForNativeRunnerProcessesToFinishTask.IsFaulted)
                    {
                        _testRunLogService.CreateTestRunLogAsync($"waitForNativeRunnerProcessesToFinishTask FAULTED- {waitForNativeRunnerProcessesToFinishTask.Exception}", _currentTestRunId).Wait();
                    }

                    innerCancellationTokenSource.Cancel();
                }
                else if (outerCancellationTokenSource.Token.IsCancellationRequested)
                {
                    foreach (var processName in _nativeTestsRunner.RunnerProcessesNamesToKill)
                    {
                        var processes = Process.GetProcessesByName(processName);
                        foreach (var process in processes)
                        {
                            try
                            {
                                if (process.StartTime > processCreationTime)
                                {
                                    process.Kill();
                                    process.WaitForExit();
                                }
                            }
                            catch (Exception e)
                            {
                                _consoleProvider.WriteLine(e.ToString());
                            }
                        }
                    }
                }
            },
                500);

            checkCancellationRequestsTask.Wait();

            string result = null;

            if (!outerCancellationTokenSource.Token.IsCancellationRequested)
            {
                foreach (var testResultFile in resultsFiles)
                {
                    if (_fileProvider.Exists(testResultFile))
                    {
                        var testTestResults = _fileProvider.ReadAllText(testResultFile);
                        var currentTestRun  = _nativeTestsRunner.DeserializeTestResults(testTestResults);
                        testRunsToBeMerged.Add(currentTestRun);
                    }
                    else if (_directoryProvider.Exists(testResultFile))
                    {
                        // TODO: Added this because of the Protractor Plugin, since it produces folder instead of file.
                        // Fix it later with something more generic solution. Maybe, we have to save the test results to plugin folder and
                        // add a plugin method for deleting them at the end.
                        var files = _directoryProvider.GetFiles(testResultFile);
                        if (!files.Any())
                        {
                            throw new Exception("No test results' file was produced for test run");
                        }

                        var firstFile       = _directoryProvider.GetFiles(testResultFile).First();
                        var testTestResults = _fileProvider.ReadAllText(firstFile);
                        var currentTestRun  = _nativeTestsRunner.DeserializeTestResults(testTestResults);
                        testRunsToBeMerged.Add(currentTestRun);
                    }
                    else
                    {
                        throw new Exception("No test results' file was produced for test run");
                    }
                }

                var mergedTestRun = _nativeTestsRunner.MergeTestResults(testRunsToBeMerged);
                if (isTimeBasedBalance)
                {
                    var testCaseRuns = _nativeTestsRunner.UpdateTestCasesHistory(mergedTestRun, assemblyName);
                    await _testCasesHistoryService.UpdateTestCaseExecutionHistoryAsync(testCaseRuns).ConfigureAwait(false);
                }

                try
                {
                    _nativeTestsRunner.ExecutePostRunActions();
                }
                catch (Exception ex)
                {
                    _testRunLogService.CreateTestRunLogAsync($"There was a problem executing ExecutePostRunActions on {Environment.MachineName}. Exception: {ex}", _currentTestRunId).Wait();
                }

                result = mergedTestRun;
            }

            return(result);
        }
示例#2
0
        public async Task RunTestsForCurrentAgentAsync(string testAgentTag, int testAgentRunTimeout)
        {
            if (await IsEligibleToStartTestAgentRunAsync(testAgentTag).ConfigureAwait(false))
            {
                var newTestAgentRun = await GetFirstNewTestAgentRunForCurrentTestAgentAsync().ConfigureAwait(false);

                if (newTestAgentRun != null)
                {
                    await _testRunLogService.CreateTestRunLogAsync($"Test agent with tag {testAgentTag} starts tests execution on machine {_environmentService.MachineName}.", newTestAgentRun.TestRunId).ConfigureAwait(false);

                    await _testAgentStateSwitcher.SetTestAgentAsRunningTestsAsync(testAgentTag).ConfigureAwait(false);

                    var cancellationTokenSource = new CancellationTokenSource();
                    var cancellationTokenSourceLastAvailable = new CancellationTokenSource();
                    var testAgentUpdateAvailabilityTask      = _taskProvider.StartNewLongRunningRepeating(
                        cancellationTokenSourceLastAvailable,
                        () =>
                    {
                        UpdateTestAgentLastAvailable(newTestAgentRun.TestAgentRunId);
                    },
                        15000);

                    var executeTestAgentRunTask = _taskProvider.StartNewLongRunning(
                        (c) =>
                    {
                        ExecuteTestAgentRunAsync(newTestAgentRun, testAgentRunTimeout, cancellationTokenSource).Wait();
                    },
                        cancellationTokenSource);

                    var checkTestRunnerLastAvailableTask = _taskProvider.StartNewLongRunningRepeating(
                        cancellationTokenSource,
                        () =>
                    {
                        if (executeTestAgentRunTask.IsCompleted)
                        {
                            cancellationTokenSource.Cancel();
                            return;
                        }

                        if (executeTestAgentRunTask.IsFaulted)
                        {
                            cancellationTokenSource.Cancel();
                            return;
                        }

                        CheckTestRunnerStatus(newTestAgentRun.TestAgentRunId, cancellationTokenSource);
                    },
                        15000);

                    checkTestRunnerLastAvailableTask.Wait();
                    cancellationTokenSourceLastAvailable.Cancel();
                    testAgentUpdateAvailabilityTask.Wait();
                    try
                    {
                        // DEBUG: Turn-off if debugging
                        _consoleProvider.Clear();

                        if (_wasTestAgentRunCompleted)
                        {
                            await _testRunLogService.CreateTestRunLogAsync($"Test agent with tag {testAgentTag} finished tests execution on machine {_environmentService.MachineName}.", newTestAgentRun.TestRunId).ConfigureAwait(false);

                            await _testRunLogService.CreateTestRunLogAsync($"Test agent with tag {testAgentTag} starts waiting for new jobs on machine {_environmentService.MachineName}.", newTestAgentRun.TestRunId).ConfigureAwait(false);
                        }
                        else
                        {
                            SendTestAgentRunExceptionToRunner(newTestAgentRun, executeTestAgentRunTask);

                            // TODO: Move logic to be executed on Test Agent Run Abort- extension.
                            await _testRunLogService
                            .CreateTestRunLogAsync(
                                $"Test agent with tag {testAgentTag} starts waiting for new jobs on machine {_environmentService.MachineName}.",
                                newTestAgentRun.TestRunId).ConfigureAwait(false);

                            _consoleProvider.WriteLine($"Test agent run aborted.");
                            _consoleProvider.WriteLine($"Test agent with tag {testAgentTag} starts waiting for new jobs on machine {_environmentService.MachineName}.");
                            var cts = new CancellationTokenSource();
                            var waitForTestRunToCompleteTask = _taskProvider.StartNewLongRunningRepeating(
                                cts,
                                () =>
                            {
                                if (IsTestRunCompleted(newTestAgentRun.TestRunId).Result)
                                {
                                    cts.Cancel();
                                }
                            },
                                5000);
                            waitForTestRunToCompleteTask.Wait();
                        }
                    }
                    finally
                    {
                        await _testAgentStateSwitcher.SetTestAgentAsActiveAsync(testAgentTag).ConfigureAwait(false);
                    }
                }
            }
        }
示例#3
0
        private async Task <string> ExecuteTestsWithNativeRunnerAsync(
            string workingDir,
            string testsLibraryPath,
            string assemblyName,
            bool runInParallel,
            int maxParallelProcessesCount,
            string nativeArguments,
            int testAgentRunTimeout,
            bool isTimeBasedBalance,
            List <TestCase> distributedTestCases,
            CancellationTokenSource outerCancellationTokenSource)
        {
            string outputFilesDir = _pathProvider.GetDirectoryName(testsLibraryPath);
            ////var updatedMaxParallelProcessesCount = maxParallelProcessesCount > 1 ? maxParallelProcessesCount - 1 : maxParallelProcessesCount;
            int availableCores = runInParallel ? maxParallelProcessesCount : 1;

            // Merge logic of CreateRunFilterArgument here. remove inner foreach
            var listOfDistributedTestCases = _nativeTestsRunner.SplitTestCases(distributedTestCases, availableCores);
            var testRunsToBeMerged         = new List <object>();

            var testRunProcesses = new List <Process>();
            var resultsFiles     = new List <string>();

            DateTime processCreationTime = _dateTimeProvider.GetCurrentTime();

            // DEBUG:
            ////await _testRunLogService.CreateTestRunLogAsync($"Number of tests to be executed- {distributedTestCases.Count}", _currentTestRunId);

            // DEBUG:
            ////await _testRunLogService.CreateTestRunLogAsync($"Number of listOfDistributedTestCases- {listOfDistributedTestCases.Count()}", _currentTestRunId);
            int index = 1;

            foreach (var distributedTestCasesList in listOfDistributedTestCases)
            {
                // DEBUG:
                ////await _testRunLogService.CreateTestRunLogAsync($"{index++} distributedTestCasesList items- {distributedTestCasesList.Count()}", _currentTestRunId);
                var currentTestResultsFilePath = _pathProvider.GetTempFileName();
                resultsFiles.Add(currentTestResultsFilePath);
                var arguments = _nativeTestsRunner.BuildNativeRunnerArguments(
                    assemblyName,
                    testsLibraryPath,
                    distributedTestCasesList,
                    currentTestResultsFilePath,
                    outputFilesDir,
                    nativeArguments);

                var currentProcess = _processStarter.InitializeProcess(
                    _nativeTestsRunner.RunnerFile,
                    workingDir,
                    arguments,
                    LogStandardOutput,
                    LogErrorOutput);
                testRunProcesses.Add(currentProcess);
            }

            var innerCancellationTokenSource = new CancellationTokenSource();

            // DEBUG:
            ////await _testRunLogService.CreateTestRunLogAsync($"The native runs will be executed in parallel- {runInParallel}. Available core on machine {Environment.MachineName}- {availableCores}", _currentTestRunId);
            ////await _testRunLogService.CreateTestRunLogAsync($"Number of native test runner process to be run- {testRunProcesses.Count}", _currentTestRunId);
            var waitForNativeRunnerProcessesToFinishTask = _taskProvider.StartNewLongRunning(
                (c) =>
            {
                var ranProcesses = new List <int>();
                do
                {
                    var coresCount = availableCores;
                    if (runInParallel)
                    {
                        foreach (var process in testRunProcesses)
                        {
                            if (coresCount == 0)
                            {
                                break;
                            }

                            if (!ranProcesses.Contains(process.GetHashCode()))
                            {
                                _processStarter.StartProcess(process, LogStandardOutput, LogErrorOutput);
                                Thread.Sleep(1000);
                                ranProcesses.Add(process.GetHashCode());
                                coresCount--;
                            }
                        }
                    }

                    // Do not start all processes upfront
                    // if parallel here start all of them?
                    // run in task and pass cancelation token. If is canceled kill all processes. DO IT for NUNIT TOO
                    foreach (var process in testRunProcesses)
                    {
                        if (outerCancellationTokenSource.Token.IsCancellationRequested)
                        {
                            return;
                        }

                        if (!runInParallel)
                        {
                            // Start processes one by one, otherwise they are started all upfront.
                            _processStarter.StartProcess(process, LogStandardOutput, LogErrorOutput);
                            ranProcesses.Add(process.GetHashCode());
                        }

                        if (ranProcesses.Contains(process.GetHashCode()))
                        {
                            _processStarter.WaitForProcessToFinish(testAgentRunTimeout, process);
                        }
                    }

                    // DEBUG:
                    ////_testRunLogService.CreateTestRunLogAsync($"ranProcesses.Count {ranProcesses.Count} testRunProcesses.Count {testRunProcesses.Count} {_dateTimeProvider.GetCurrentTime()}", _currentTestRunId).Wait();
                }while (ranProcesses.Count != testRunProcesses.Count);
            },
                innerCancellationTokenSource);

            var checkCancellationRequestsTask = _taskProvider.StartNewLongRunningRepeating(
                innerCancellationTokenSource,
                () =>
            {
                if (waitForNativeRunnerProcessesToFinishTask.IsCompleted || waitForNativeRunnerProcessesToFinishTask.IsFaulted)
                {
                    if (waitForNativeRunnerProcessesToFinishTask.IsFaulted)
                    {
                        _testRunLogService.CreateTestRunLogAsync($"waitForNativeRunnerProcessesToFinishTask FAULTED- {waitForNativeRunnerProcessesToFinishTask.Exception}", _currentTestRunId).Wait();
                    }

                    innerCancellationTokenSource.Cancel();
                    return;
                }
                else if (outerCancellationTokenSource.Token.IsCancellationRequested)
                {
                    foreach (var processName in _nativeTestsRunner.RunnerProcessesNamesToKill)
                    {
                        var processes = Process.GetProcessesByName(processName);
                        foreach (var process in processes)
                        {
                            try
                            {
                                if (process.StartTime > processCreationTime)
                                {
                                    process.Kill();
                                    process.WaitForExit();
                                }
                            }
                            catch (Exception e)
                            {
                                _consoleProvider.WriteLine(e.ToString());
                            }
                        }
                    }

                    return;
                }
            },
                5000);

            checkCancellationRequestsTask.Wait();

            string result = null;

            if (!outerCancellationTokenSource.Token.IsCancellationRequested)
            {
                // DEBUG:
                _testRunLogService.CreateTestRunLogAsync($"START MERGING RESULTS- on machine {Environment.MachineName}", _currentTestRunId).Wait();
                foreach (var testResultFile in resultsFiles)
                {
                    if (_fileProvider.Exists(testResultFile))
                    {
                        var testTestResults = _fileProvider.ReadAllText(testResultFile);
                        var currentTestRun  = _nativeTestsRunner.DeserializeTestResults(testTestResults);
                        testRunsToBeMerged.Add(currentTestRun);
                    }
                    else
                    {
                        throw new Exception("No test results' file was produced for test run");
                    }
                }

                var mergedTestRun = _nativeTestsRunner.MergeTestResults(testRunsToBeMerged);
                if (isTimeBasedBalance)
                {
                    // DEBUG:
                    var startTime = _dateTimeProvider.GetCurrentTime();
                    _testRunLogService.CreateTestRunLogAsync($"START updating test case history- on machine {Environment.MachineName}", _currentTestRunId).Wait();
                    var testCaseRuns = _nativeTestsRunner.UpdateTestCasesHistory(mergedTestRun, assemblyName);
                    await _testCasesHistoryService.UpdateTestCaseExecutionHistoryAsync(testCaseRuns);

                    // DEBUG:
                    var endTime = _dateTimeProvider.GetCurrentTime();
                    _testRunLogService.CreateTestRunLogAsync($"END updating test case history- on machine {Environment.MachineName} for {(endTime - startTime).Seconds} seconds", _currentTestRunId).Wait();
                }

                result = mergedTestRun;
            }

            return(result);
        }