void finishTestPlanRun(TestPlanRun run, Stopwatch testPlanTimer, failState runWentOk, TraceListener Logger, HybridStream logStream) { try { if (run != null) { if (runWentOk == failState.StartFail) { if (PrintTestPlanRunSummary) { summaryListener.OnTestPlanRunStart(run); // Call this to ensure that the correct planrun is being summarized } if (run.Verdict < Verdict.Aborted) { run.Verdict = Verdict.Error; } } for (int i = run.StepsWithPrePlanRun.Count - 1; i >= 0; i--) { Stopwatch postTimer = Stopwatch.StartNew(); String stepPath = string.Empty; try { ITestStep step = run.StepsWithPrePlanRun[i]; if ((step as TestStep)?.PrePostPlanRunUsed ?? true) { stepPath = step.GetStepPath(); run.AddTestStepStateUpdate(step.Id, null, StepState.PostPlanRun); try { run.ResourceManager.BeginStep(run, step, TestPlanExecutionStage.PostPlanRun, TapThread.Current.AbortToken); step.PlanRun = run; try { step.PostPlanRun(); } finally { run.ResourceManager.EndStep(step, TestPlanExecutionStage.PostPlanRun); step.PlanRun = null; } } finally { run.AddTestStepStateUpdate(step.Id, null, StepState.Idle); } Log.Debug(postTimer, "{0} PostPlanRun completed.", stepPath); } } catch (Exception ex) { Log.Warning("Error during post plan run of {0}.", stepPath); Log.Debug(ex); } } run.Duration = testPlanTimer.Elapsed; } if (run != null) { try { // The open resource threads might throw exceptions. If they do we must // Wait() for them to catch the exception. // If the run was aborted after the open resource threads were started but // before we wait for them (e.g. by an error in PrePlanRun), then we do it // here. run.ResourceManager.WaitUntilAllResourcesOpened(TapThread.Current.AbortToken); } catch (OperationCanceledException) { // Ignore this because this typically means that the wait was cancelled before. // Just to be sure also upgrade verdict to aborted. run.UpgradeVerdict(Verdict.Aborted); } catch (AggregateException e) { if (e.InnerExceptions.Count == 1) { Log.Error("Failed to open resource ({0})", e.GetInnerMostExceptionMessage()); Log.Debug(e); } else { Log.Error("Errors while opening resources:", e.GetInnerMostExceptionMessage()); foreach (Exception ie in e.InnerExceptions) { Log.Error(" {0}", ie.GetInnerMostExceptionMessage()); Log.Debug(ie); } } } if (PrintTestPlanRunSummary) { // wait for the summaryListener so the summary appears in the log file. run.WaitForResultListener(summaryListener); summaryListener.PrintSummary(); } OpenTap.Log.Flush(); Logger.Flush(); logStream.Flush(); run.AddTestPlanCompleted(logStream, runWentOk != failState.StartFail); run.ResourceManager.EndStep(this, TestPlanExecutionStage.Execute); if (!run.IsCompositeRun) { run.ResourceManager.EndStep(this, TestPlanExecutionStage.Open); } } } finally { if (monitors != null) { foreach (var item in monitors) { item.ExitTestPlanRun(run); } } } }
failState execTestPlan(TestPlanRun execStage, IList <ITestStep> steps) { WaitHandle.WaitAny(new[] { execStage.PromptWaitHandle, TapThread.Current.AbortToken.WaitHandle }); bool resultListenerError = false; execStage.ScheduleInResultProcessingThread <IResultListener>(resultListener => { try { using (TimeoutOperation.Create(() => PrintWaitingMessage(new List <IResource>() { resultListener }))) execStage.ResourceManager.WaitUntilResourcesOpened(TapThread.Current.AbortToken, resultListener); try { // some resources might set metadata in the Open methods. // this information needs to be propagated to result listeners as well. // this returns quickly if its a lazy resource manager. using (TimeoutOperation.Create( () => PrintWaitingMessage(new List <IResource>() { resultListener }))) execStage.ResourceManager.WaitUntilAllResourcesOpened(TapThread.Current.AbortToken); } catch // this error will also be handled somewhere else. { } execStage.WaitForSerialization(); foreach (var res in execStage.PromptedResources) { execStage.Parameters.AddRange(ResultParameters.GetMetadataFromObject(res)); } resultListener.OnTestPlanRunStart(execStage); } catch (OperationCanceledException) when(execStage.MainThread.AbortToken.IsCancellationRequested) { // test plan thread was aborted, this is OK. } catch (Exception ex) { Log.Error("Error in OnTestPlanRunStart for '{0}': '{1}'", resultListener, ex.Message); Log.Debug(ex); resultListenerError = true; } }, true); if (resultListenerError) { return(failState.StartFail); } var sw = Stopwatch.StartNew(); try { execStage.StepsWithPrePlanRun.Clear(); if (!runPrePlanRunMethods(steps, execStage)) { return(failState.StartFail); } } catch (Exception e) { Log.Error(e.GetInnerMostExceptionMessage()); Log.Debug(e); return(failState.StartFail); } finally{ { Log.Debug(sw, "PrePlanRun Methods completed"); } } Stopwatch planRunOnlyTimer = Stopwatch.StartNew(); var runs = new List <TestStepRun>(); try { for (int i = 0; i < steps.Count; i++) { var step = steps[i]; if (step.Enabled == false) { continue; } var run = step.DoRun(execStage, execStage); if (!run.Skipped) { runs.Add(run); } run.CheckBreakCondition(); // note: The following is copied inside TestStep.cs if (run.SuggestedNextStep is Guid id) { int nextindex = steps.IndexWhen(x => x.Id == id); if (nextindex >= 0) { i = nextindex - 1; } // if skip to next step, dont add it to the wait queue. } } } catch (TestStepBreakException breakEx) { Log.Info("{0}", breakEx.Message); } finally { // Now wait for them to actually complete. They might defer internally. foreach (var run in runs) { run.WaitForCompletion(); execStage.UpgradeVerdict(run.Verdict); } } Log.Debug(planRunOnlyTimer, "Test step runs finished."); return(failState.Ok); }