Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release/9.0] Check CancellationToken before TimeSpan in TimeProviderTaskExtensions #107416

Merged
merged 2 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions src/libraries/Common/tests/System/TimeProviderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,18 +310,25 @@ public static void RunDelayTests(TimeProvider provider, ITestTaskFactory taskFac
}
catch (Exception e)
{
Assert.Fail(string.Format("RunDelayTests: > FAILED. Unexpected exception on WaitAll(simple tasks): {0}", e));
Assert.Fail($"RunDelayTests: > FAILED. Unexpected exception on WaitAll(simple tasks): {e}");
}

Assert.True(task1.Status == TaskStatus.RanToCompletion, " > FAILED. Expected Delay(TimeSpan(0), timeProvider) to run to completion");
Assert.True(task2.Status == TaskStatus.RanToCompletion, " > FAILED. Expected Delay(TimeSpan(0), timeProvider, uncanceledToken) to run to completion");

// This should complete quickly with a CANCELED status.
Task task3 = taskFactory.Delay(provider, new TimeSpan(0), new CancellationToken(true));
var canceledException = Record.Exception(task3.Wait);
Assert.True(canceledException is AggregateException { InnerException: OperationCanceledException },
$"RunDelayTests: > FAILED. Unexpected exception on canceled task Wait(): {canceledException}");
Assert.True(task3.Status == TaskStatus.Canceled, " > FAILED. Expected Delay(timeProvider, TimeSpan(0), canceledToken) to be canceled");

// This should take some time
Task task3 = taskFactory.Delay(provider, TimeSpan.FromMilliseconds(20000));
Task task4 = taskFactory.Delay(provider, TimeSpan.FromMilliseconds(20000));

Assert.False(task3.IsCompleted, "RunDelayTests: > FAILED. Delay(20000) appears to have completed too soon(1).");
Assert.False(task4.IsCompleted, "RunDelayTests: > FAILED. Delay(20000) appears to have completed too soon(1).");
Task t2 = Task.Delay(TimeSpan.FromMilliseconds(10));
Assert.False(task3.IsCompleted, "RunDelayTests: > FAILED. Delay(10000) appears to have completed too soon(2).");
Assert.False(task4.IsCompleted, "RunDelayTests: > FAILED. Delay(10000) appears to have completed too soon(2).");
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
Expand Down Expand Up @@ -359,6 +366,7 @@ public static async Task RunWaitAsyncTests(TimeProvider provider, ITestTaskFacto

cts.Cancel();
await Assert.ThrowsAsync<TaskCanceledException>(() => taskFactory.WaitAsync(tcs5.Task, TimeSpan.FromMilliseconds(10), provider, cts.Token));
await Assert.ThrowsAsync<TaskCanceledException>(() => taskFactory.WaitAsync(tcs5.Task, TimeSpan.Zero, provider, cts.Token));

using CancellationTokenSource cts1 = new CancellationTokenSource();
Task task5 = Task.Run(() => { while (!cts1.Token.IsCancellationRequested) { Thread.Sleep(10); } });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ public static Task Delay(this TimeProvider timeProvider, TimeSpan delay, Cancell
throw new ArgumentOutOfRangeException(nameof(delay));
}

if (delay == TimeSpan.Zero)
if (cancellationToken.IsCancellationRequested)
{
return Task.CompletedTask;
return Task.FromCanceled(cancellationToken);
}

if (cancellationToken.IsCancellationRequested)
if (delay == TimeSpan.Zero)
{
return Task.FromCanceled(cancellationToken);
return Task.CompletedTask;
}

DelayState state = new(cancellationToken);
Expand Down Expand Up @@ -161,14 +161,14 @@ public static Task WaitAsync(this Task task, TimeSpan timeout, TimeProvider time
return task;
}

if (timeout == TimeSpan.Zero)
if (cancellationToken.IsCancellationRequested)
{
return Task.FromException(new TimeoutException());
return Task.FromCanceled(cancellationToken);
}

if (cancellationToken.IsCancellationRequested)
if (timeout == TimeSpan.Zero)
{
return Task.FromCanceled(cancellationToken);
return Task.FromException(new TimeoutException());
}

WaitAsyncState state = new(cancellationToken);
Expand Down
Loading