Fix WaitForNextTickAsync_CanceledWaitThenWaitAgain_Succeeds test (#54775)
authorStephen Toub <stoub@microsoft.com>
Sat, 26 Jun 2021 19:30:56 +0000 (15:30 -0400)
committerGitHub <noreply@github.com>
Sat, 26 Jun 2021 19:30:56 +0000 (15:30 -0400)
There's a race condition in the test between the timer firing and cancellation being requested.  It repros more on Linux because there's a smaller quantum on Linux than on Windows.

src/libraries/System.Runtime/tests/System/Threading/PeriodicTimerTests.cs

index 92367b8..099096a 100644 (file)
@@ -177,18 +177,24 @@ namespace System.Threading.Tests
         {
             using var timer = new PeriodicTimer(TimeSpan.FromMilliseconds(1));
 
-            ValueTask<bool> task = timer.WaitForNextTickAsync(new CancellationToken(true));
-            Assert.ThrowsAny<OperationCanceledException>(() => task.Result);
-
             var cts = new CancellationTokenSource();
-            task = timer.WaitForNextTickAsync(cts.Token);
+            ValueTask<bool> task = timer.WaitForNextTickAsync(cts.Token);
             cts.Cancel();
-            Assert.Equal(cts.Token, Assert.ThrowsAny<OperationCanceledException>(() => task.Result).CancellationToken);
 
-            for (int i = 0; i < 10; i++)
+            try
             {
-                Assert.True(await timer.WaitForNextTickAsync());
+                // If the task happens to succeed because the operation completes fast enough
+                // that it beats the cancellation request, then make sure it completed successfully.
+                Assert.True(await task);
             }
+            catch (OperationCanceledException oce)
+            {
+                // Otherwise, it must have been canceled with the relevant token.
+                Assert.Equal(cts.Token, oce.CancellationToken);
+            }
+
+            // We should be able to await the next tick either way.
+            Assert.True(await timer.WaitForNextTickAsync());
         }
 
         private static void WaitForTimerToBeCollected(WeakReference<PeriodicTimer> timer, bool expected)