public void Transform_SyncFaultedFunction_CancellationRequested_IgnoresTransform() { using var cts = new CancellationTokenSource(); cts.Cancel(); var executedTransform = false; var fault = ExceptionUtilities.Unreachable; var cancellationToken = cts.Token; Func <StateType, CancellationToken, ValueTask <IntermediateType> > func = (_, _) => new(Task.FromException <IntermediateType>(fault)); Func <IntermediateType, StateType, ResultType> transform = (_, _) => { executedTransform = true; return(new ResultType()); }; var arg = new StateType(); var task = SpecializedTasks.TransformWithoutIntermediateCancellationExceptionAsync(func, transform, arg, cancellationToken).Preserve(); Assert.True(task.IsCanceled); var exception = Assert.Throws <TaskCanceledException>(() => task.Result); Assert.Equal(cancellationToken, exception.CancellationToken); Assert.False(executedTransform); }
public async Task Transform_AsyncFaultedFunction_CancellationRequested_IgnoresTransform() { using var cts = new CancellationTokenSource(); cts.Cancel(); var executedTransform = false; var fault = ExceptionUtilities.Unreachable; var cancellationToken = cts.Token; var gate = new ManualResetEventSlim(); Func <StateType, CancellationToken, ValueTask <IntermediateType> > func = async(_, _) => { await Task.Yield(); gate.Wait(CancellationToken.None); throw fault; }; Func <IntermediateType, StateType, ResultType> transform = (_, _) => { executedTransform = true; return(new ResultType()); }; var arg = new StateType(); var task = SpecializedTasks.TransformWithoutIntermediateCancellationExceptionAsync(func, transform, arg, cancellationToken).Preserve(); Assert.False(task.IsCompleted); gate.Set(); var exception = await Assert.ThrowsAsync <TaskCanceledException>(() => task.AsTask()); Assert.True(task.IsCanceled); Assert.Equal(cancellationToken, exception.CancellationToken); Assert.False(executedTransform); }
public void Transform_SyncCanceledFunction_NotRequested_IgnoresTransform() { using var unexpectedCts = new CancellationTokenSource(); unexpectedCts.Cancel(); var executedTransform = false; var cancellationToken = new CancellationToken(canceled: false); Func <StateType, CancellationToken, ValueTask <IntermediateType> > func = (_, _) => new(Task.FromCanceled <IntermediateType>(unexpectedCts.Token)); Func <IntermediateType, StateType, ResultType> transform = (_, _) => { executedTransform = true; return(new ResultType()); }; var arg = new StateType(); var task = SpecializedTasks.TransformWithoutIntermediateCancellationExceptionAsync(func, transform, arg, cancellationToken).Preserve(); Assert.True(task.IsCanceled); var exception = Assert.Throws <TaskCanceledException>(() => task.Result); // ⚠ Due to the way cancellation is handled in ContinueWith, the resulting exception fails to preserve the // cancellation token applied when the intermediate task was cancelled. Assert.Equal(cancellationToken, exception.CancellationToken); Assert.False(executedTransform); }
public void Transform_SyncCompletedFunction_CompletedTransform() { Func <StateType, CancellationToken, ValueTask <IntermediateType> > func = (_, _) => new(new IntermediateType()); Func <IntermediateType, StateType, ResultType> transform = (_, _) => new(); var arg = new StateType(); var cancellationToken = new CancellationToken(canceled: false); var task = SpecializedTasks.TransformWithoutIntermediateCancellationExceptionAsync(func, transform, arg, cancellationToken).Preserve(); Assert.True(task.IsCompletedSuccessfully); Assert.NotNull(task.Result); }
public void Transform_ArgumentValidation() { Func <StateType, CancellationToken, ValueTask <IntermediateType> > func = (_, _) => new(new IntermediateType()); Func <IntermediateType, StateType, ResultType> transform = (_, _) => new(); var arg = new StateType(); var cancellationToken = new CancellationToken(canceled: false); #pragma warning disable CA2012 // Use ValueTasks correctly (the instance is never created) Assert.Throws <ArgumentNullException>("func", () => SpecializedTasks.TransformWithoutIntermediateCancellationExceptionAsync(null !, transform, arg, cancellationToken)); Assert.Throws <ArgumentNullException>("transform", () => SpecializedTasks.TransformWithoutIntermediateCancellationExceptionAsync <StateType, IntermediateType, ResultType>(func, null !, arg, cancellationToken)); #pragma warning restore CA2012 // Use ValueTasks correctly }
public void Transform_SyncCompletedFunction_FaultedTransform() { var fault = ExceptionUtilities.Unreachable; Func <StateType, CancellationToken, ValueTask <IntermediateType> > func = (_, _) => new(new IntermediateType()); Func <IntermediateType, StateType, ResultType> transform = (_, _) => throw fault; var arg = new StateType(); var cancellationToken = new CancellationToken(canceled: false); #pragma warning disable CA2012 // Use ValueTasks correctly (the instance is never created) var exception = Assert.Throws <InvalidOperationException>(() => SpecializedTasks.TransformWithoutIntermediateCancellationExceptionAsync(func, transform, arg, cancellationToken)); #pragma warning restore CA2012 // Use ValueTasks correctly Assert.Same(fault, exception); }
public async Task Transform_AsyncCompletedFunction_CompletedTransform() { var gate = new ManualResetEventSlim(); Func <StateType, CancellationToken, ValueTask <IntermediateType> > func = async(_, _) => { await Task.Yield(); gate.Wait(CancellationToken.None); return(new IntermediateType()); }; Func <IntermediateType, StateType, ResultType> transform = (_, _) => new(); var arg = new StateType(); var cancellationToken = new CancellationToken(canceled: false); var task = SpecializedTasks.TransformWithoutIntermediateCancellationExceptionAsync(func, transform, arg, cancellationToken).Preserve(); Assert.False(task.IsCompleted); gate.Set(); Assert.NotNull(await task); }
public void Transform_SyncFaultedFunction_IgnoresTransform() { var executedTransform = false; var fault = ExceptionUtilities.Unreachable; var cancellationToken = new CancellationToken(canceled: false); Func <StateType, CancellationToken, ValueTask <IntermediateType> > func = (_, _) => new(Task.FromException <IntermediateType>(fault)); Func <IntermediateType, StateType, ResultType> transform = (_, _) => { executedTransform = true; return(new ResultType()); }; var arg = new StateType(); var task = SpecializedTasks.TransformWithoutIntermediateCancellationExceptionAsync(func, transform, arg, cancellationToken).Preserve(); Assert.True(task.IsFaulted); var exception = Assert.Throws <InvalidOperationException>(() => task.Result); Assert.Same(fault, exception); Assert.False(executedTransform); }
public async Task Transform_AsyncCanceledFunction_NotRequested_IgnoresTransform() { using var unexpectedCts = new CancellationTokenSource(); unexpectedCts.Cancel(); var executedTransform = false; var cancellationToken = new CancellationToken(canceled: false); var gate = new ManualResetEventSlim(); Func <StateType, CancellationToken, ValueTask <IntermediateType> > func = async(_, _) => { await Task.Yield(); gate.Wait(CancellationToken.None); unexpectedCts.Token.ThrowIfCancellationRequested(); throw ExceptionUtilities.Unreachable; }; Func <IntermediateType, StateType, ResultType> transform = (_, _) => { executedTransform = true; return(new ResultType()); }; var arg = new StateType(); var task = SpecializedTasks.TransformWithoutIntermediateCancellationExceptionAsync(func, transform, arg, cancellationToken).Preserve(); Assert.False(task.IsCompleted); gate.Set(); var exception = await Assert.ThrowsAsync <TaskCanceledException>(async() => await task); Assert.True(task.IsCanceled); // ⚠ Due to the way cancellation is handled in ContinueWith, the resulting exception fails to preserve the // cancellation token applied when the intermediate task was cancelled. Assert.Equal(cancellationToken, exception.CancellationToken); Assert.False(executedTransform); }
public void Transform_SyncDirectFaultedFunction_CancellationRequested_IgnoresTransform() { using var cts = new CancellationTokenSource(); cts.Cancel(); var executedTransform = false; var fault = ExceptionUtilities.Unreachable; var cancellationToken = cts.Token; Func <StateType, CancellationToken, ValueTask <IntermediateType> > func = (_, _) => throw fault; Func <IntermediateType, StateType, ResultType> transform = (_, _) => { executedTransform = true; return(new ResultType()); }; var arg = new StateType(); #pragma warning disable CA2012 // Use ValueTasks correctly (the instance is never created) var exception = Assert.Throws <InvalidOperationException>(() => SpecializedTasks.TransformWithoutIntermediateCancellationExceptionAsync(func, transform, arg, cancellationToken)); #pragma warning restore CA2012 // Use ValueTasks correctly Assert.Same(fault, exception); Assert.False(executedTransform); }
public async Task Transform_AsyncCompletedFunction_FaultedTransform() { var fault = ExceptionUtilities.Unreachable; var gate = new ManualResetEventSlim(); Func <StateType, CancellationToken, ValueTask <IntermediateType> > func = async(_, _) => { await Task.Yield(); gate.Wait(CancellationToken.None); return(new IntermediateType()); }; Func <IntermediateType, StateType, ResultType> transform = (_, _) => throw fault; var arg = new StateType(); var cancellationToken = new CancellationToken(canceled: false); var task = SpecializedTasks.TransformWithoutIntermediateCancellationExceptionAsync(func, transform, arg, cancellationToken).Preserve(); Assert.False(task.IsCompleted); gate.Set(); var exception = await Assert.ThrowsAsync <InvalidOperationException>(() => task.AsTask()); Assert.Same(fault, exception); }