private StateStringBuilder AddStatus( TestOperationStatus status, string description, [CanBeNull] Action <StateStringBuilder> extraContext = null) => this .AddIndented( status.MakeStatusLine(description), _ => this.AddFailureDetails(status, extraContext));
public async Task <TResult> ExecuteUnsafe <TResult>(RunContext runContext, CancellationToken cancellationToken) { TestOperationStatus.AssertNotStarted(this.Status); var nestedRunContext = this.sourceContext != null ? runContext.MakeNested(this.sourceContext.Value) : runContext; this.Status = new TestOperationStatus.Waiting(this.Status, runContext.MakeWaitContext()); try { var result = await this.ExecuteInner(nestedRunContext, cancellationToken); this.Status = new TestOperationStatus.Completed(this.Status); return((TResult)(object)result); // See the Execute extension method for why this is safe. } catch (OperationCanceledException) { this.Status = new TestOperationStatus.Canceled(this.Status); throw; } catch (Exception e) { this.Status = new TestOperationStatus.Failed(this.Status, e, nestedRunContext.SourceContext); throw; } }
private StateStringBuilder AddFailureDetails( TestOperationStatus status, [CanBeNull] Action <StateStringBuilder> extraContext = null) { if (status is TestOperationStatus.Failed failed) { this.AddEmptyLine(); var e = failed.Error; this.AddIndented( "Failed with:", b => b.Add($"{e.GetType()}: '{TruncatedExceptionMessage(e)}'")); this.AddEmptyLine(); this.AddIndented("Test operation stack:", b => { foreach (var sourceLine in failed.SourceContext.SourceLines) { b.Add(sourceLine); } }); } if (extraContext != null && (status is TestOperationStatus.Failed || status is TestOperationStatus.Waiting)) { this.AddEmptyLine(); extraContext(this); } return(this); }
[ExcludeFromCodeCoverage] // Unreachable defensive code internal static void AssertNotStarted(TestOperationStatus status) { if (status != NotExecuted.Instance) { throw new InvalidOperationException( $"Operation already started ({status?.GetType().Name})"); } }
public Failed(TestOperationStatus previous, Exception error, SourceContext sourceContext) { var waiting = this.ExpectWaiting(previous); this.elapsedTime = waiting.WaitContext.ElapsedString; this.Error = error; this.SourceContext = sourceContext; }
internal void AddSelect <T1, T2>( ITestOperationState primaryState, TestOperationStatus selectStatus) { primaryState.BuildDescription(this); this.AddStatus( selectStatus, $"SELECT {typeof(T1).Name} -> {typeof(T2).Name}"); }
[ExcludeFromCodeCoverage] // Unreachable defensive code private Waiting ExpectWaiting(TestOperationStatus status) { if (status is Waiting waiting) { return(waiting); } else { throw new InvalidOperationException( $"Can not transition from {status.GetType().Name} to {this.GetType().Name}"); } }
public async Task <TSecond> Execute( TFirst source, RunContext runContext, CancellationToken cancellationToken) { this.creationStatus = new TestOperationStatus.Waiting(this.creationStatus, runContext.MakeWaitContext()); try { this.executionState = this.makeContinuation(source); } catch (Exception e) { this.creationStatus = new TestOperationStatus.Failed(this.creationStatus, e, runContext.SourceContext); throw; } this.creationStatus = new TestOperationStatus.Completed(this.creationStatus); return(await this.executionState.Execute(runContext, cancellationToken)); }
public Canceled(TestOperationStatus previous) { var waiting = this.ExpectWaiting(previous); this.elapsedTime = waiting.WaitContext.ElapsedString; }
public Waiting(TestOperationStatus previous, WaitContext waitContext) { AssertNotStarted(previous); this.WaitContext = waitContext; }