public static async Task Invoke(this Func <Task> action, ExceptionAggregator aggregator, ExecutionTimer timer) { var oldSyncContext = SynchronizationContext.Current; try { var asyncSyncContext = new AsyncTestSyncContext(oldSyncContext); SetSynchronizationContext(asyncSyncContext); await aggregator?.RunAsync( () => timer.AggregateAsync( async() => { await action(); var ex = await asyncSyncContext.WaitForCompletionAsync(); if (ex != null) { aggregator.Add(ex); } })); } finally { SetSynchronizationContext(oldSyncContext); } }
private async Task <IDisposable[]> InvokeBodyAsync() { var stepContext = new StepContext(this.step); if (this.body != null) { var oldSyncContext = SynchronizationContext.Current; try { var asyncSyncContext = new AsyncTestSyncContext(oldSyncContext); SetSynchronizationContext(asyncSyncContext); await this.aggregator.RunAsync( () => this.timer.AggregateAsync( async() => { await this.body(stepContext); var ex = await asyncSyncContext.WaitForCompletionAsync(); if (ex != null) { this.aggregator.Add(ex); } })); } finally { SetSynchronizationContext(oldSyncContext); } } return(stepContext.Disposables.ToArray()); }
public override void Execute() { try { Exception exception = null; var @event = new ManualResetEvent(false); ThreadPool.QueueUserWorkItem(o => { var oldSyncContext = SynchronizationContext.Current; using (var syncContext = new AsyncTestSyncContext()) { SynchronizationContext.SetSynchronizationContext(syncContext); try { this.body.Invoke(); exception = syncContext.WaitForCompletion(); } catch (Exception ex) { exception = ex; } finally { SynchronizationContext.SetSynchronizationContext(oldSyncContext); @event.Set(); } } }); // NOTE: we do not call the WaitOne(int) overload because it wasn't introduced until .NET 3.5 SP1 and we want to support pre-SP1 if ([email protected](this.MillisecondsTimeout, false)) { throw new Xunit.Sdk.TimeoutException(this.MillisecondsTimeout); } if (exception != null) { ExceptionUtility.RethrowWithNoStackTraceLoss(exception); } } finally { foreach (var disposable in this.ExtractDisposables) { CurrentScenario.AddTeardown(() => disposable.Dispose()); } foreach (var teardown in this.Teardowns) { CurrentScenario.AddTeardown(teardown); } } }
public static void Run(Func <object> performStep) { var oldSyncContext = SynchronizationContext.Current; try { var asyncSyncContext = new AsyncTestSyncContext(); SetSynchronizationContext(asyncSyncContext); var result = performStep(); var task = result as Task; if (task != null) { try { task.Wait(); } catch (AggregateException ae) { var innerException = ae.InnerException; ExceptionProcessor.PreserveStackTrace(innerException); throw innerException; } } else { var ex = asyncSyncContext.WaitForCompletion(); if (ex != null) { ExceptionProcessor.PreserveStackTrace(ex); throw ex; } } } finally { SetSynchronizationContext(oldSyncContext); } }
public static void Run(Func<object> performStep) { var oldSyncContext = SynchronizationContext.Current; try { var asyncSyncContext = new AsyncTestSyncContext(); SetSynchronizationContext(asyncSyncContext); var result = performStep(); var task = result as Task; if (task != null) { try { task.Wait(); } catch (AggregateException ae) { var innerException = ae.InnerException; ExceptionProcessor.PreserveStackTrace(innerException); throw innerException; } } else { var ex = asyncSyncContext.WaitForCompletion(); if (ex != null) { ExceptionProcessor.PreserveStackTrace(ex); throw ex; } } } finally { SetSynchronizationContext(oldSyncContext); } }
public static void Run(Func <object> performStep) { var oldSyncContext = SynchronizationContext.Current; try { var asyncSyncContext = new AsyncTestSyncContext(); SetSynchronizationContext(asyncSyncContext); performStep(); { var ex = asyncSyncContext.WaitForCompletion(); if (ex != null) { ExceptionProcessor.PreserveStackTrace(ex); throw ex; } } } finally { SetSynchronizationContext(oldSyncContext); } }
/// <summary> /// Invokes the test method on the given test class instance. This method sets up support for "async void" /// test methods, ensures that the test method has the correct number of arguments, then calls <see cref="CallTestMethod"/> /// to do the actual method invocation. It ensure that any async test method is fully completed before returning, and /// returns the measured clock time that the invocation took. This method should NEVER throw; any exceptions should be /// placed into the aggregator in <paramref name="ctxt"/>. /// </summary> /// <param name="ctxt">The context that describes the current test</param> /// <param name="testClassInstance">The test class instance</param> /// <returns>Returns the amount of time the test took to run, in seconds</returns> protected virtual async ValueTask <decimal> InvokeTestMethodAsync( TContext ctxt, object?testClassInstance) { var oldSyncContext = default(SynchronizationContext); var asyncSyncContext = default(AsyncTestSyncContext); try { if (AsyncUtility.IsAsyncVoid(ctxt.TestMethod)) { oldSyncContext = SynchronizationContext.Current; asyncSyncContext = new AsyncTestSyncContext(oldSyncContext); SetSynchronizationContext(asyncSyncContext); } var elapsed = await ExecutionTimer.MeasureAsync( () => ctxt.Aggregator.RunAsync( async() => { var parameterCount = ctxt.TestMethod.GetParameters().Length; var valueCount = ctxt.TestMethodArguments == null ? 0 : ctxt.TestMethodArguments.Length; if (parameterCount != valueCount) { ctxt.Aggregator.Add( new InvalidOperationException( $"The test method expected {parameterCount} parameter value{(parameterCount == 1 ? "" : "s")}, but {valueCount} parameter value{(valueCount == 1 ? "" : "s")} {(valueCount == 1 ? "was" : "were")} provided." ) ); } else { var result = CallTestMethod(ctxt, testClassInstance); var valueTask = AsyncUtility.TryConvertToValueTask(result); if (valueTask.HasValue) { await valueTask.Value; } else if (asyncSyncContext != null) { var ex = await asyncSyncContext.WaitForCompletionAsync(); if (ex != null) { ctxt.Aggregator.Add(ex); } } } } ) ); return((decimal)elapsed.TotalSeconds); } finally { if (asyncSyncContext != null) { SetSynchronizationContext(oldSyncContext); } } }
/// <inheritdoc/> protected override async Task <decimal> InvokeTestMethodAsync(object testClassInstance) { var oldSyncContext = SynchronizationContext.Current; try { var asyncSyncContext = new AsyncTestSyncContext(oldSyncContext); SetSynchronizationContext(asyncSyncContext); await this.Aggregator.RunAsync( () => this.Timer.AggregateAsync( async() => { var parameterCount = this.TestMethod.GetParameters().Length; var valueCount = this.TestMethodArguments == null ? 0 : this.TestMethodArguments.Length; if (parameterCount != valueCount) { this.Aggregator.Add( new InvalidOperationException( $"The test method expected {parameterCount} parameter value{(parameterCount == 1 ? "" : "s")}," + $"but {valueCount} parameter value{(valueCount == 1 ? "" : "s")} {(valueCount == 1 ? "was" : "were")} provided.") ); } else { var result = this.TestMethod.Invoke(testClassInstance, this.TestMethodArguments); var task = result as Task; if (task != null) { await task; } else { var ex = await asyncSyncContext.WaitForCompletionAsync(); if (ex != null) { this.Aggregator.Add(ex); } } } } ) ); //if (Aggregator.HasExceptions) //{ // var handleTestFailure = testClassInstance as INeedToKnowTestFailure; // if (handleTestFailure != null) // { // await // Aggregator.RunAsync( // () => Timer.AggregateAsync( // () => handleTestFailure.HandleFailureAsync(Test, Aggregator.ToException()))); // } //} } finally { SetSynchronizationContext(oldSyncContext); } return(this.Timer.Total); }
public static SynchronizationContext GetInnerSyncContext(this AsyncTestSyncContext context) { return((SynchronizationContext)context.GetType() .GetField("innerContext", BindingFlags.NonPublic | BindingFlags.Instance) .GetValue(context)); }