/// <summary> /// Adds the specified test unit. /// </summary> /// <param name="testUnit">The test unit.</param> public void Add(TestUnitWithMetadata testUnit) { lock (SyncObject) { if (available.Contains(testUnit)) return; if (running.Contains(testUnit)) running.Remove(testUnit); available.Add(testUnit); } AvailableAdded.SafeInvoke(this); }
/// <summary> /// Gets the no available agents failure. /// </summary> /// <param name="test">The test.</param> /// <param name="exception">The exception.</param> /// <returns></returns> public static TestResult GetNoAvailableAgentsFailure(TestUnitWithMetadata test, Exception exception) { var result = GetResultForTest(test.Test, exception); TestResult suite = result; while (suite.HasResults) { suite = (TestResult)suite.Results[0]; } // A test can be either test suite or test case // Here it is a suite if (test.Test.Info.IsSuite && test.Children.Any()) { foreach (var child in test.Children) { var childResult = new TestResult(child.Test.Info); childResult.SetResult(ResultState.NotRunnable, exception, FailureSite.Parent); suite.AddResult(childResult); } } return result; }
/// <summary> /// Moves to running. /// </summary> /// <param name="testUnit">The test unit.</param> public void MarkRunning(TestUnitWithMetadata testUnit) { lock (SyncObject) { if (running.Contains(testUnit)) return; available.Remove(testUnit); running.Add(testUnit); } }
/// <summary> /// Marks the completed. /// </summary> /// <param name="test">The test.</param> public void MarkCompleted(TestUnitWithMetadata test) { lock (SyncObject) { available.Remove(test); running.Remove(test); } }
private static void FindTestUnits(ITest test, ITestFilter filter, List<TestUnitWithMetadata> result, TestRun testRun, string assemblyName = null) { var assembly = test as TestAssembly; if (assembly != null) assemblyName = assembly.TestName.FullName; if (filter.Pass(test)) { var isTestSuiteWithAtLeastOneTestMethod = (test.IsSuite && test.Tests != null && test.Tests.Count != 0 && !((ITest) test.Tests[0]).IsSuite); if (!test.IsSuite || isTestSuiteWithAtLeastOneTestMethod) { List<TestUnitWithMetadata> subTests = null; if (test.IsSuite && test.Tests != null) { subTests = new List<TestUnitWithMetadata>(); foreach (ITest child in test.Tests) { FindTestUnits(child, filter, subTests, testRun, assemblyName); } } var testUnitWithMetadata = new TestUnitWithMetadata(testRun, test, assemblyName, subTests); result.Add(testUnitWithMetadata); } else if ((test.Tests != null && test.Tests.Count > 0)) { foreach (ITest child in test.Tests) { FindTestUnits(child, filter, result, testRun, assemblyName); } } } }
/// <summary> /// Adds for reprocessing if required. /// </summary> /// <param name="test">The test.</param> /// <param name="result">The result.</param> /// <param name="agent"> </param> public void AddForReprocessingIfRequired(TestUnitWithMetadata test, TestResult result, AgentMetadata agent) { var request = requests != null ? requests.GetBy(test.Test.Run) : null; Action registerReprocessing = () => { if (request != null) request.Statistics.RegisterReprocessing(); }; if (result == null) { test.AttachedData.NullReprocessingCount++; collection.Add(test); log.Info(string.Format("REPROCESSING (as null): '{0}' was added for reprocessing. [{1}]", test.FullName, test.Test.Run)); registerReprocessing(); return; } if (!test.Test.Info.IsSuite) { var childResult = result.FindDescedant(d => d.FullName.Equals(test.FullName)); if (childResult != null && ProcessResult(childResult, test.Test.Run, test) == ReprocessingVerdict.PerformReprocessing) { AddTestForReprocessing(test, agent); registerReprocessing(); } return; } foreach (var suiteResult in result.FindBottomLevelTestSuites()) { if (test.FullName.Equals(suiteResult.FullName)) { var reprocessingVerdict = ProcessResult(suiteResult, test.Test.Run, test); if (reprocessingVerdict == ReprocessingVerdict.MaximumCountWasReached) return; if (reprocessingVerdict == ReprocessingVerdict.PerformReprocessing) { AddTestForReprocessing(test, agent); registerReprocessing(); continue; } } var childrenForReprocessing = new List<Tuple<TestResult, TestUnitWithMetadata>>(); foreach (TestResult childResult in suiteResult.Results) { var childTest = test.Children.FirstOrDefault(ct => ct.FullName.Equals(childResult.FullName)); if (ProcessResult(childResult, test.Test.Run, childTest, () => { childTest = new TestUnitWithMetadata(test.Test.Run, childResult.Test, test.Test.AssemblyName); test.Children.Add(childTest); return childTest; })==ReprocessingVerdict.PerformReprocessing) childrenForReprocessing.Add(new Tuple<TestResult, TestUnitWithMetadata>(childResult, childTest)); } if (childrenForReprocessing.Count > 0 && childrenForReprocessing.Count == suiteResult.Results.Count) { AddTestForReprocessing(test, agent); registerReprocessing(); } else { foreach (var childForReprocessing in childrenForReprocessing) { AddTestForReprocessing(childForReprocessing.Item2, agent); registerReprocessing(); } } } }
private ReprocessingVerdict ProcessResult(TestResult result, TestRun testRun, TestUnitWithMetadata test, Func<TestUnitWithMetadata> createTestUnit = null) { if (result == null) return ReprocessingVerdict.Other; if (result.ResultState.IsOneOf( ResultState.Ignored, ResultState.Success, ResultState.Cancelled)) return ReprocessingVerdict.Skipped; var specialHandling = testRun.Parameters.GetSpecialHandling(result.Message, result.StackTrace); if (specialHandling == null) return ReprocessingVerdict.NoHandlingFound; test = (test ?? (createTestUnit != null ? createTestUnit() : null)); if (test == null) return ReprocessingVerdict.Other; var doReprocess = test.AttachedData.GetCountAndIncrease(specialHandling) <= specialHandling.RetryCount; if (doReprocess) { log.Info(string.Format("REPROCESSING ({2}/{3}): '{0}' was added for reprocessing. [{1}]", test.FullName, test.Test.Run, test.AttachedData.GetCount(specialHandling), specialHandling.RetryCount)); } return doReprocess ? ReprocessingVerdict.PerformReprocessing : ReprocessingVerdict.MaximumCountWasReached; }
private void AddTestForReprocessing(TestUnitWithMetadata test, AgentMetadata agent) { test.AttachedData.MarkAgentAs(agent, SchedulingHint.NotRecommended); collection.Add(test); }
// Should be started in a separate thread private void Run(TestUnitWithMetadata test, AgentMetadata agent, DistributedConfigurationSubstitutions configurationSubstitutions) { log.BeginActivity(string.Format("[{0}] Started test {1}", test.Test.Run, test.Test.Info.TestName.FullName)); var request = requests.GetBy(test.Test.Run); if (request != null) request.Status = TestRunRequestStatus.Pending; try { log.BeginActivity(string.Format("Connecting to agent [{0}]...", agent)); var testRunnerAgent = connectionProvider.GetConnection<IAgent>(agent.Address); log.BeginActivity(string.Format("Connected to agent [{0}]", agent)); log.BeginActivity(string.Format("Checking project existence ('{0}') on agent {1}", test.Test.Run, agent)); if (!testRunnerAgent.HasProject(test.Test.Run)) { log.EndActivity(string.Format("Project '{0}' doesn't exist on agent {1}", test.Test.Run, agent)); log.BeginActivity(string.Format("Sending project ('{0}') to agent {1}", test.Test.Run, agent)); using (Stream project = projects.GetStreamToPacked(test.Test.Run) ?? new MemoryStream(1)) { testRunnerAgent.ReceiveProject(new ProjectMessage { TestRun = test.Test.Run, Project = project }); } log.EndActivity(string.Format("Sent project ('{0}') to agent {1}", test.Test.Run, agent)); } else log.EndActivity(string.Format("Project '{0}' exist on agent {1}", test.Test.Run, agent)); var reprocessedCount = request.Statistics.ReprocessedCount; log.BeginActivity(string.Format("[{3}/{4}]: Running {0} on {1} with variables ({2})...", test.Test.UniqueTestId, agent, configurationSubstitutions, request.Statistics.GetCountAndIncrement(), reprocessedCount == 0 ? request.Statistics.Total.ToString(CultureInfo.InvariantCulture) : string.Format("{2}({0}+{1})", request.Statistics.Total, reprocessedCount, request.Statistics.Total + reprocessedCount))); TestResult result = testRunnerAgent.RunTests(test.Test, configurationSubstitutions); log.EndActivity(string.Format("Finished running {0} on {1}...", test.Test.UniqueTestId, agent)); if (result == null) throw new FaultException("Result is not available"); ProcessResult(test, agent, result); } catch (FaultException ex) { log.Error(string.Format("Exception while running test {0} on {1}", test.Test.UniqueTestId, agent), ex); agents.MarkAsFailure(agent); tests.Add(test); } catch (CommunicationException ex) { log.Error(string.Format("Exception in communication while running test {0} on {1}", test.Test.UniqueTestId, agent), ex); agents.MarkAsDisconnected(agent); tests.Add(test); } catch(Exception ex) { log.Error(string.Format("Something bad and unhandled happened while running test {0} on {1}", test.Test.UniqueTestId, agent), ex); } }
private void ProcessResult(TestUnitWithMetadata test, AgentMetadata agent, TestResult result) { bool isRequestCompleted; using (agents.Lock()) { lock (tests.SyncObject) { AddResultsToTestUnitMetadata(test, result); tests.MarkCompleted(test); agents.MarkAsReady(agent); reprocessor.AddForReprocessingIfRequired(test, result, agent); isRequestCompleted = !tests.IsAnyAvailableFor(test.Test.Run); } } results.Add(result, test.Test.Run); var request = requests.GetBy(test.Test.Run); if (request != null) request.PipeToClient.Publish(result.DeepClone().SetFinal(false)); if (isRequestCompleted) ProcessCompletedTestRun(test.Test.Run); }
private static void AddResultsToTestUnitMetadata(TestUnitWithMetadata test, TestResult result) { var found = FindByName(result, test.Test.UniqueTestId); if (found == null) return; test.Results.Add(found); foreach (var child in test.Children) { var foundChildResult = FindByName(found, child.Test.UniqueTestId); if (foundChildResult == null) continue; child.Results.Add(foundChildResult); } }