From a2e23cf40aea7e14c86cf4dd6b2f10d18b3285e1 Mon Sep 17 00:00:00 2001 From: csdahlberg Date: Wed, 7 Oct 2015 21:38:45 -0500 Subject: [PATCH] Fixed deadlock issues with the non-Async methods of AsyncLock, AsyncWaitHandle, AsyncManualResetEvent, and AsyncAutoResetEvent. Improved unit tests of threading-related types. Upgraded xunit to v2.1.0 and disabled test parallelization. --- CodeTiger.Core/CodeTiger.Core.csproj | 1 - .../Threading/AsyncAutoResetEvent.cs | 32 + CodeTiger.Core/Threading/AsyncLock.cs | 79 +- .../Threading/AsyncManualResetEvent.cs | 11 + CodeTiger.Core/Threading/AsyncWaitHandle.cs | 79 +- .../Threading/Tasks/TaskExtensions.cs | 67 +- .../UnitTests.CodeTiger.Core.Portable.csproj | 25 +- .../packages.config | 13 +- .../AsyncLazy`1Tests.cs | 6 +- .../Properties/AssemblyInfo.cs | 6 +- .../Threading/AsyncAutoResetEventTests.cs | 994 +++++++++--------- .../Threading/AsyncLockTests.cs | 64 +- .../Threading/AsyncManualResetEventTests.cs | 988 ++++++++++++++--- .../Threading/AsyncWaitHandleTests.cs | 199 +++- .../Tasks/TaskExtensionsUnitTests.cs | 186 +++- .../UnitTests.CodeTiger.Core.csproj | 31 +- .../UnitTests.CodeTiger.Core/packages.config | 11 +- 17 files changed, 1936 insertions(+), 856 deletions(-) diff --git a/CodeTiger.Core/CodeTiger.Core.csproj b/CodeTiger.Core/CodeTiger.Core.csproj index 0ed54ed..6f9ff28 100644 --- a/CodeTiger.Core/CodeTiger.Core.csproj +++ b/CodeTiger.Core/CodeTiger.Core.csproj @@ -83,7 +83,6 @@ CodeTigerLib.snk - diff --git a/CodeTiger.Core/Threading/AsyncAutoResetEvent.cs b/CodeTiger.Core/Threading/AsyncAutoResetEvent.cs index 56618da..baa54b9 100644 --- a/CodeTiger.Core/Threading/AsyncAutoResetEvent.cs +++ b/CodeTiger.Core/Threading/AsyncAutoResetEvent.cs @@ -96,6 +96,38 @@ public void Reset() Interlocked.Exchange(ref _isSignaled, 0); } + /// + /// Gets a to use for a new wait operation. + /// + /// A to use for a new wait operation. + protected override TaskCompletionSource GetWaitTaskSource( + CancellationToken cancellationToken) + { + if (Interlocked.CompareExchange(ref _isSignaled, 0, 1) == 1) + { + return CompletedWaitTaskSource; + } + + TaskCompletionSource waitTaskSource; + + using (_pendingWaitTaskSourcesLock.Acquire(cancellationToken)) + { + // If this event is already signaled, return the already-completed wait task. + if (Interlocked.CompareExchange(ref _isSignaled, 0, 1) == 1) + { + waitTaskSource = CompletedWaitTaskSource; + } + else + { + waitTaskSource = new TaskCompletionSource(); + cancellationToken.Register(() => waitTaskSource.TrySetCanceled()); + _pendingWaitTaskSources.Enqueue(waitTaskSource); + } + } + + return waitTaskSource; + } + /// /// Gets a to use for a new wait operation. /// diff --git a/CodeTiger.Core/Threading/AsyncLock.cs b/CodeTiger.Core/Threading/AsyncLock.cs index 4f14c1f..a6d622b 100644 --- a/CodeTiger.Core/Threading/AsyncLock.cs +++ b/CodeTiger.Core/Threading/AsyncLock.cs @@ -37,7 +37,7 @@ public AsyncLock() /// public IDisposable Acquire() { - return GetWaitTask(CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); + return Acquire(CancellationToken.None); } /// @@ -48,7 +48,30 @@ public IDisposable Acquire() /// public IDisposable Acquire(CancellationToken cancellationToken) { - return GetWaitTask(cancellationToken).ConfigureAwait(false).GetAwaiter().GetResult(); + if (Interlocked.CompareExchange(ref _acquiredCount, 1, 0) == 0) + { + return _releaser; + } + + TaskCompletionSource waitTaskSource; + + lock (_pendingWaitTaskSources) + { + if (Interlocked.CompareExchange(ref _acquiredCount, 1, 0) == 0) + { + return _releaser; + } + + waitTaskSource = new TaskCompletionSource(); + _pendingWaitTaskSources.Enqueue(waitTaskSource); + } + + if (cancellationToken.CanBeCanceled) + { + var cancellationRegistration = cancellationToken.Register(() => waitTaskSource.TrySetCanceled()); + } + + return Task.Run(() => waitTaskSource.Task).Result; } /// @@ -58,7 +81,7 @@ public IDisposable Acquire(CancellationToken cancellationToken) /// public Task AcquireAsync() { - return GetWaitTask(CancellationToken.None); + return AcquireAsync(CancellationToken.None); } /// @@ -68,17 +91,14 @@ public Task AcquireAsync() /// An object that must be disposed to release the acquired lock. /// public Task AcquireAsync(CancellationToken cancellationToken) - { - return GetWaitTask(cancellationToken); - } - - private Task GetWaitTask(CancellationToken cancellationToken) { if (Interlocked.CompareExchange(ref _acquiredCount, 1, 0) == 0) { return _completedWaitTask; } + TaskCompletionSource waitTaskSource; + lock (_pendingWaitTaskSources) { if (Interlocked.CompareExchange(ref _acquiredCount, 1, 0) == 0) @@ -86,32 +106,29 @@ private Task GetWaitTask(CancellationToken cancellationToken) return _completedWaitTask; } - var waitTaskSource = new TaskCompletionSource(); - var waitTask = waitTaskSource.Task; - - if (cancellationToken != CancellationToken.None) - { - var cancellationRegistration = cancellationToken - .Register(() => waitTaskSource.TrySetCanceled()); - - waitTask = waitTask - .ContinueWith(task => - { - if (waitTask.IsCanceled) - { - cancellationRegistration.Dispose(); - } - - return task; - }, - TaskContinuationOptions.ExecuteSynchronously) - .Unwrap(); - } - + waitTaskSource = new TaskCompletionSource(); _pendingWaitTaskSources.Enqueue(waitTaskSource); + } - return waitTask; + if (!cancellationToken.CanBeCanceled) + { + return waitTaskSource.Task; } + + var cancellationRegistration = cancellationToken.Register(() => waitTaskSource.TrySetCanceled()); + + return waitTaskSource.Task + .ContinueWith(task => + { + if (waitTaskSource.Task.IsCanceled) + { + cancellationRegistration.Dispose(); + } + + return task; + }, + TaskContinuationOptions.ExecuteSynchronously) + .Unwrap(); } private void ReleaseLock() diff --git a/CodeTiger.Core/Threading/AsyncManualResetEvent.cs b/CodeTiger.Core/Threading/AsyncManualResetEvent.cs index 148f706..754af1d 100644 --- a/CodeTiger.Core/Threading/AsyncManualResetEvent.cs +++ b/CodeTiger.Core/Threading/AsyncManualResetEvent.cs @@ -53,6 +53,17 @@ public void Reset() #pragma warning restore 0420 } + /// + /// Gets a to use for a new wait operation. + /// + /// A cancellation token to observe. + /// A to use for a new wait operation. + protected override TaskCompletionSource GetWaitTaskSource( + CancellationToken cancellationToken) + { + return _waitTaskSource; + } + /// /// Gets a to use for a new wait operation. /// diff --git a/CodeTiger.Core/Threading/AsyncWaitHandle.cs b/CodeTiger.Core/Threading/AsyncWaitHandle.cs index 5dc379c..6e5acf1 100644 --- a/CodeTiger.Core/Threading/AsyncWaitHandle.cs +++ b/CodeTiger.Core/Threading/AsyncWaitHandle.cs @@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; +using CodeTiger.Threading.Tasks; namespace CodeTiger.Threading { @@ -89,45 +90,24 @@ public bool WaitOne(int timeoutMilliseconds, CancellationToken cancellationToken /// public bool WaitOne(TimeSpan timeout, CancellationToken cancellationToken) { - var waitTaskSource = GetWaitTaskSourceAsync(cancellationToken).GetAwaiter().GetResult(); + var waitTaskSource = GetWaitTaskSource(cancellationToken); - if (cancellationToken != CancellationToken.None) + if (cancellationToken.CanBeCanceled) { // Have the cancellation token attempt to cancel the wait task. cancellationToken.Register(() => waitTaskSource.TrySetCanceled()); } - if (timeout != Timeout.InfiniteTimeSpan) - { - using (var compositeCancellationSource = CancellationTokenSource.CreateLinkedTokenSource( - cancellationToken)) - { - var timeoutTask = Task.Delay(timeout, compositeCancellationSource.Token); - var completedTask = Task.WhenAny(waitTaskSource.Task, timeoutTask).GetAwaiter().GetResult(); - - if (completedTask == timeoutTask) - { - waitTaskSource.TrySetResult(false); - } - else - { - // If the timeout task has not yet completed, use the composite cancellation token to - // cancel it so it will not continue running in the background. - compositeCancellationSource.Cancel(); - } - } - } - - return waitTaskSource.Task.GetAwaiter().GetResult(); + return Task.Run(() => waitTaskSource.Task.Wait(timeout, cancellationToken)).Result; } /// /// Asynchronously waits until this event is signaled. /// /// A that will complete when the event is signaled. - public async Task WaitOneAsync() + public Task WaitOneAsync() { - await WaitOneAsync(Timeout.InfiniteTimeSpan, CancellationToken.None).ConfigureAwait(false); + return WaitOneAsync(Timeout.InfiniteTimeSpan, CancellationToken.None); } /// @@ -137,10 +117,9 @@ public async Task WaitOneAsync() /// (negative 1) to wait indefinitely. /// A that will complete with a result of true if this wait /// handle was signaled before the timeout elapsed; otherwise, with a result of false. - public async Task WaitOneAsync(int timeoutMilliseconds) + public Task WaitOneAsync(int timeoutMilliseconds) { - return await WaitOneAsync(TimeSpan.FromMilliseconds(timeoutMilliseconds), CancellationToken.None) - .ConfigureAwait(false); + return WaitOneAsync(TimeSpan.FromMilliseconds(timeoutMilliseconds), CancellationToken.None); } /// @@ -150,9 +129,9 @@ public async Task WaitOneAsync(int timeoutMilliseconds) /// milliseconds) to wait indefinitely. /// A that will complete with a result of true if this wait /// handle was signaled before the timeout elapsed; otherwise, with a result of false. - public async Task WaitOneAsync(TimeSpan timeout) + public Task WaitOneAsync(TimeSpan timeout) { - return await WaitOneAsync(timeout, CancellationToken.None).ConfigureAwait(false); + return WaitOneAsync(timeout, CancellationToken.None); } /// @@ -161,9 +140,9 @@ public async Task WaitOneAsync(TimeSpan timeout) /// A cancellation token to observe. /// A that will complete with a result of true if this wait /// handle was signaled before the timeout elapsed; otherwise, with a result of false. - public async Task WaitOneAsync(CancellationToken cancellationToken) + public Task WaitOneAsync(CancellationToken cancellationToken) { - return await WaitOneAsync(Timeout.InfiniteTimeSpan, cancellationToken).ConfigureAwait(false); + return WaitOneAsync(Timeout.InfiniteTimeSpan, cancellationToken); } /// @@ -175,10 +154,9 @@ public async Task WaitOneAsync(CancellationToken cancellationToken) /// A cancellation token to observe. /// A that will complete with a result of true if this wait /// handle was signaled before the timeout elapsed; otherwise, with a result of false. - public async Task WaitOneAsync(int timeoutMilliseconds, CancellationToken cancellationToken) + public Task WaitOneAsync(int timeoutMilliseconds, CancellationToken cancellationToken) { - return await WaitOneAsync(TimeSpan.FromMilliseconds(timeoutMilliseconds), cancellationToken) - .ConfigureAwait(false); + return WaitOneAsync(TimeSpan.FromMilliseconds(timeoutMilliseconds), cancellationToken); } /// @@ -194,26 +172,22 @@ public async Task WaitOneAsync(TimeSpan timeout, CancellationToken cancell { var waitTaskSource = await GetWaitTaskSourceAsync(cancellationToken).ConfigureAwait(false); - if (cancellationToken != CancellationToken.None) + if (cancellationToken.CanBeCanceled) { // Have the cancellation token attempt to cancel the wait task. cancellationToken.Register(() => waitTaskSource.TrySetCanceled()); } - Task completedTask; - Task timeoutTask = null; + if (timeout == Timeout.InfiniteTimeSpan) + { + return await waitTaskSource.Task.ConfigureAwait(false); + } + using (var compositeCancellationSource = CancellationTokenSource.CreateLinkedTokenSource( cancellationToken)) { - if (timeout != Timeout.InfiniteTimeSpan) - { - timeoutTask = Task.Delay(timeout, compositeCancellationSource.Token); - completedTask = await Task.WhenAny(waitTaskSource.Task, timeoutTask).ConfigureAwait(false); - } - else - { - completedTask = waitTaskSource.Task; - } + var timeoutTask = Task.Delay(timeout, compositeCancellationSource.Token); + var completedTask = await Task.WhenAny(waitTaskSource.Task, timeoutTask).ConfigureAwait(false); if (completedTask == timeoutTask) { @@ -230,6 +204,15 @@ public async Task WaitOneAsync(TimeSpan timeout, CancellationToken cancell return await waitTaskSource.Task.ConfigureAwait(false); } + /// + /// Gets a object to use for a new wait operation. + /// + /// A cancellation token to observe. + /// A object to use for a new wait operation. + /// + protected abstract TaskCompletionSource GetWaitTaskSource( + CancellationToken cancellationToken); + /// /// Gets a object to use for a new wait operation. /// diff --git a/CodeTiger.Core/Threading/Tasks/TaskExtensions.cs b/CodeTiger.Core/Threading/Tasks/TaskExtensions.cs index f71314a..66024fa 100644 --- a/CodeTiger.Core/Threading/Tasks/TaskExtensions.cs +++ b/CodeTiger.Core/Threading/Tasks/TaskExtensions.cs @@ -42,12 +42,28 @@ public static Task WithTimeout(this Task task, int timeoutMilliseconds) /// amount of time to complete. public static Task WithTimeout(this Task task, TimeSpan timeout) { - if (task == null || task.IsCompleted || timeout == Timeout.InfiniteTimeSpan) + Guard.ArgumentIsNotNull(nameof(task), task); + + if (task.IsCompleted || timeout == Timeout.InfiniteTimeSpan) { return task; } - return WaitForCompletionOrTimeoutAsync(task, timeout); + var timeoutCancelTokenSource = new CancellationTokenSource(); + var timeoutTask = Task.Delay(timeout, timeoutCancelTokenSource.Token); + return Task.Factory.ContinueWhenAny(new[] { task, timeoutTask }, + completedTask => + { + if (completedTask == timeoutTask) + { + throw new TimeoutException(); + } + + timeoutCancelTokenSource.Cancel(); + + return task; + }) + .Unwrap(); } /// @@ -83,30 +99,49 @@ public static Task WithTimeout(this Task task, int ti /// or has already completed. /// Thrown when takes longer than the specified /// amount of time to complete. - public static async Task WithTimeout(this Task task, TimeSpan timeout) + public static Task WithTimeout(this Task task, TimeSpan timeout) { + Guard.ArgumentIsNotNull(nameof(task), task); + if (timeout == Timeout.InfiniteTimeSpan || task.IsCompleted) { - return await task; + return task; } - await WaitForCompletionOrTimeoutAsync(task, timeout); + var timeoutCancelTokenSource = new CancellationTokenSource(); + var timeoutTask = Task.Delay(timeout, timeoutCancelTokenSource.Token); + + return Task.WhenAny(task, timeoutTask) + .ContinueWith(completedTask => + { + if (completedTask == timeoutTask) + { + throw new TimeoutException(); + } + + timeoutCancelTokenSource.Cancel(); - return await task; + return task; + }) + .Unwrap(); } - private static async Task WaitForCompletionOrTimeoutAsync(Task task, TimeSpan timeout) + /// + /// Waits for a to complete execution. The wait terminates if a timeout interval + /// elapses or a cancellation token is canceled before the task completes. + /// + /// The original task. + /// The maximum amount of time to wait for to complete. + /// + /// A cancellation token to observe while waiting for the task to complete. + /// + /// true if completed execution within the allotted time, + /// false otherwise. + public static bool Wait(this Task task, TimeSpan timeout, CancellationToken cancellationToken) { - var timeoutCancelTokenSource = new CancellationTokenSource(); - var timeoutTask = Task.Delay(timeout, timeoutCancelTokenSource.Token); + Guard.ArgumentIsNotNull(nameof(task), task); - var completedTask = await Task.WhenAny(task, timeoutTask).ConfigureAwait(false); - if (completedTask == timeoutTask) - { - throw new TimeoutException(); - } - - timeoutCancelTokenSource.Cancel(); + return task.Wait((int)timeout.TotalMilliseconds, cancellationToken); } } } \ No newline at end of file diff --git a/UnitTests/UnitTests.CodeTiger.Core.Portable/UnitTests.CodeTiger.Core.Portable.csproj b/UnitTests/UnitTests.CodeTiger.Core.Portable/UnitTests.CodeTiger.Core.Portable.csproj index 864c8cb..1cbad7c 100644 --- a/UnitTests/UnitTests.CodeTiger.Core.Portable/UnitTests.CodeTiger.Core.Portable.csproj +++ b/UnitTests/UnitTests.CodeTiger.Core.Portable/UnitTests.CodeTiger.Core.Portable.csproj @@ -1,7 +1,7 @@  - - + + 10.0 @@ -17,7 +17,8 @@ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} Profile111 v4.5 - 8172711b + + true @@ -99,11 +100,17 @@ ..\..\packages\xunit.abstractions.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - - ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + + ..\..\packages\xunit.assert.2.1.0\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll + True - - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.1.0\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + + + ..\..\packages\xunit.extensibility.execution.2.1.0\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll + True @@ -114,7 +121,7 @@ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - + + \ No newline at end of file diff --git a/UnitTests/UnitTests.CodeTiger.Core.Portable/packages.config b/UnitTests/UnitTests.CodeTiger.Core.Portable/packages.config index 8a18dd7..f0ca925 100644 --- a/UnitTests/UnitTests.CodeTiger.Core.Portable/packages.config +++ b/UnitTests/UnitTests.CodeTiger.Core.Portable/packages.config @@ -1,9 +1,10 @@  - - - - - - + + + + + + + \ No newline at end of file diff --git a/UnitTests/UnitTests.CodeTiger.Core/AsyncLazy`1Tests.cs b/UnitTests/UnitTests.CodeTiger.Core/AsyncLazy`1Tests.cs index aef4879..bc735c3 100644 --- a/UnitTests/UnitTests.CodeTiger.Core/AsyncLazy`1Tests.cs +++ b/UnitTests/UnitTests.CodeTiger.Core/AsyncLazy`1Tests.cs @@ -33,8 +33,10 @@ public void CreatesTaskWhichReturnsDefaultValueOfObject() { var target = new AsyncLazy(); - Assert.NotNull(target.Value.GetAwaiter().GetResult()); - Assert.Equal(typeof(object), target.Value.GetAwaiter().GetResult().GetType()); + var actual = target.Value.ConfigureAwait(false).GetAwaiter().GetResult(); + + Assert.NotNull(actual); + Assert.Equal(typeof(object), actual.GetType()); } [Fact] diff --git a/UnitTests/UnitTests.CodeTiger.Core/Properties/AssemblyInfo.cs b/UnitTests/UnitTests.CodeTiger.Core/Properties/AssemblyInfo.cs index 6e354ef..811f3d7 100644 --- a/UnitTests/UnitTests.CodeTiger.Core/Properties/AssemblyInfo.cs +++ b/UnitTests/UnitTests.CodeTiger.Core/Properties/AssemblyInfo.cs @@ -2,6 +2,7 @@ using System.Reflection; using System.Resources; using System.Runtime.InteropServices; +using Xunit; [assembly: AssemblyTitle("UnitTests.CodeTiger.Core")] [assembly: AssemblyDescription("Contains unit tests for the CodeTiger.Core assembly.")] @@ -16,4 +17,7 @@ [assembly: AssemblyVersion("0.0.1.0")] [assembly: AssemblyFileVersion("0.0.1.0")] -[assembly: AssemblyInformationalVersion("0.0.1.0")] \ No newline at end of file +[assembly: AssemblyInformationalVersion("0.0.1.0")] + +// Disable test parallelization due to intermittent timing issues with async-related tests +[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file diff --git a/UnitTests/UnitTests.CodeTiger.Core/Threading/AsyncAutoResetEventTests.cs b/UnitTests/UnitTests.CodeTiger.Core/Threading/AsyncAutoResetEventTests.cs index 85e954e..a708901 100644 --- a/UnitTests/UnitTests.CodeTiger.Core/Threading/AsyncAutoResetEventTests.cs +++ b/UnitTests/UnitTests.CodeTiger.Core/Threading/AsyncAutoResetEventTests.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Threading; using System.Threading.Tasks; using CodeTiger.Threading; @@ -21,7 +22,7 @@ public void ReturnsOnceWhenEventIsInitiallySet() var successfulWaitTask = Task.Run(() => target.WaitOne()); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(250))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(250))).Result); } [Fact] @@ -32,7 +33,7 @@ public void ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() var successfulWaitTask = Task.Run(() => target.WaitOne()); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(250))).Result); } [Fact] @@ -41,15 +42,12 @@ public void ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOne() var target = new AsyncAutoResetEvent(false); var successfulWaitTask = Task.Run(() => target.WaitOne()); - - // Add a small delay to make sure the first task calls WaitOne first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); - - Assert.False(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(250))); + + Assert.False(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(250))).Result); target.Set(); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); } [Fact] @@ -60,7 +58,7 @@ public void ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOne() var successfulWaitTask = Task.Run(() => target.WaitOne()); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); } [Fact] @@ -78,12 +76,12 @@ public void ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOne() // Add a small delay to make sure the second task calls WaitOne first Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); - Assert.True(successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(250))).Result); + Assert.False(Task.Run(() => successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(250))).Result); target.Set(); - Assert.True(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))).Result); } } @@ -96,11 +94,9 @@ public void DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() var waitTask = Task.Run(() => target.WaitOne(250)); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(150))); - - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.False(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(200))).Result); + Assert.True(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(100))).Result); + Assert.False(waitTask.Result); } [Fact] @@ -111,11 +107,9 @@ public void DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() var waitTask = Task.Run(() => target.WaitOne(250)); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(150))); - - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.False(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(200))).Result); + Assert.True(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(100))).Result); + Assert.False(waitTask.Result); } [Fact] @@ -130,12 +124,10 @@ public void ReturnsOnceWhenEventIsInitiallySet() var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(250)); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask.Result); + Assert.True(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(300))).Result); + Assert.False(unsuccessfulWaitTask.Result); } [Fact] @@ -151,12 +143,12 @@ public void ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(250)); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + Assert.True(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(300))).Result); + Assert.False(unsuccessfulWaitTask.Result); } [Fact] @@ -171,17 +163,17 @@ public void ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOne() var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(250)); - Assert.False(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - + Assert.False(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + target.Set(); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + Assert.True(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(300))).Result); + Assert.False(unsuccessfulWaitTask.Result); } [Fact] @@ -197,12 +189,11 @@ public void ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOne() var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(250)); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + Assert.True(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(300))).Result); + Assert.False(unsuccessfulWaitTask.Result); } [Fact] @@ -222,18 +213,19 @@ public void ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOne() var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(250)); - Assert.True(successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask1.Result); + Assert.False(Task.Run(() => successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); target.Set(); - Assert.True(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask2.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + Assert.True(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))).Result); + Assert.False(unsuccessfulWaitTask.Result); } } @@ -246,11 +238,11 @@ public void DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() var waitTask = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(150))); + Assert.False(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(200))).Result); // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.True(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(100))).Result); + Assert.False(waitTask.Result); } [Fact] @@ -261,11 +253,10 @@ public void DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() var waitTask = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(150))); + Assert.False(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(200))).Result); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.True(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(100))).Result); + Assert.False(waitTask.Result); } [Fact] @@ -280,12 +271,13 @@ public void ReturnsOnceWhenEventIsInitiallySet() var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + Assert.True(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(300))).Result); + Assert.False(unsuccessfulWaitTask.Result); } [Fact] @@ -301,12 +293,12 @@ public void ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + Assert.True(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(300))).Result); + Assert.False(unsuccessfulWaitTask.Result); } [Fact] @@ -321,17 +313,18 @@ public void ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOne() var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); - Assert.False(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.False(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); target.Set(); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + Assert.True(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(300))).Result); + Assert.False(unsuccessfulWaitTask.Result); } [Fact] @@ -347,12 +340,12 @@ public void ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOne() var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + Assert.True(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(300))).Result); + Assert.False(unsuccessfulWaitTask.Result); } [Fact] @@ -372,41 +365,44 @@ public void ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOne() var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); - Assert.True(successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask1.Result); + Assert.False(Task.Run(() => successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); target.Set(); - Assert.True(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask2.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + Assert.True(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(300))).Result); + Assert.False(unsuccessfulWaitTask.Result); } } public class WaitOne_CancellationToken { [Fact] - public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() + public void DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() { var target = new AsyncAutoResetEvent(false); var cancelSource = new CancellationTokenSource(); var waitTask = Task.Run(() => target.WaitOne(cancelSource.Token)); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(250))); + Assert.False(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(250))).Result); cancelSource.Cancel(); - await Assert.ThrowsAsync( - async () => await waitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => waitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] - public async Task ReturnsOnceWhenEventIsInitiallySet() + public void ReturnsOnceWhenEventIsInitiallySet() { var target = new AsyncAutoResetEvent(true); @@ -418,18 +414,18 @@ public async Task ReturnsOnceWhenEventIsInitiallySet() var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(cancelSource.Token)); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => unsuccessfulWaitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] - public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() + public void ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() { var target = new AsyncAutoResetEvent(false); target.Set(); @@ -442,18 +438,18 @@ public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitO var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(cancelSource.Token)); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => unsuccessfulWaitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] - public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOne() + public void ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOne() { var target = new AsyncAutoResetEvent(false); @@ -465,23 +461,23 @@ public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOn var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(cancelSource.Token)); - Assert.False(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - + Assert.False(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + target.Set(); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => unsuccessfulWaitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] - public async Task ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOne() + public void ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOne() { var target = new AsyncAutoResetEvent(true); target.Set(); @@ -494,18 +490,18 @@ public async Task ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOne() var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(cancelSource.Token)); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => unsuccessfulWaitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] - public async Task ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOne() + public void ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOne() { var target = new AsyncAutoResetEvent(true); @@ -522,20 +518,20 @@ public async Task ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOne() var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(cancelSource.Token)); - Assert.True(successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); target.Set(); - Assert.True(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => unsuccessfulWaitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } } @@ -549,24 +545,25 @@ public void DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() var waitTask = Task.Run(() => target.WaitOne(250, CancellationToken.None)); // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.True(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(1000))).Result); + Assert.False(waitTask.Result); } [Fact] - public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() + public void DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() { var target = new AsyncAutoResetEvent(false); var cancelSource = new CancellationTokenSource(); var waitTask = Task.Run(() => target.WaitOne(Timeout.Infinite, cancelSource.Token)); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(250))); + Assert.False(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(250))).Result); cancelSource.Cancel(); - await Assert.ThrowsAsync( - async () => await waitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => waitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] @@ -578,12 +575,12 @@ public void DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() var waitTask = Task.Run(() => target.WaitOne(250, CancellationToken.None)); // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.True(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(1000))).Result); + Assert.False(waitTask.Result); } [Fact] - public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsInitiallySetThenReset() + public void DoesNotReturnUntilCancelTokenIsSetWhenEventIsInitiallySetThenReset() { var target = new AsyncAutoResetEvent(true); target.Reset(); @@ -591,16 +588,17 @@ public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsInitiallySetThenR var cancelSource = new CancellationTokenSource(); var waitTask = Task.Run(() => target.WaitOne(Timeout.Infinite, cancelSource.Token)); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(250))); + Assert.False(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(250))).Result); cancelSource.Cancel(); - await Assert.ThrowsAsync( - async () => await waitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => waitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] - public async Task ReturnsOnceWhenEventIsInitiallySet() + public void ReturnsOnceWhenEventIsInitiallySet() { var target = new AsyncAutoResetEvent(true); @@ -612,18 +610,19 @@ public async Task ReturnsOnceWhenEventIsInitiallySet() var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(Timeout.Infinite, cancelSource.Token)); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => unsuccessfulWaitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] - public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() + public void ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() { var target = new AsyncAutoResetEvent(false); target.Set(); @@ -636,18 +635,19 @@ public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitO var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(Timeout.Infinite, cancelSource.Token)); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => unsuccessfulWaitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] - public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOne() + public void ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOne() { var target = new AsyncAutoResetEvent(false); @@ -659,23 +659,23 @@ public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOn var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(Timeout.Infinite, cancelSource.Token)); - Assert.False(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - + Assert.False(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + target.Set(); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => unsuccessfulWaitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] - public async Task ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOne() + public void ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOne() { var target = new AsyncAutoResetEvent(true); target.Set(); @@ -688,18 +688,19 @@ public async Task ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOne() var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(Timeout.Infinite, cancelSource.Token)); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => unsuccessfulWaitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] - public async Task ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOne() + public void ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOne() { var target = new AsyncAutoResetEvent(true); @@ -716,20 +717,22 @@ public async Task ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOne() var unsuccessfulWaitTask = Task.Run(() => target.WaitOne(Timeout.Infinite, cancelSource.Token)); - Assert.True(successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask1.Result); + Assert.False(Task.Run(() => successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); target.Set(); - Assert.True(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask2.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => unsuccessfulWaitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } } @@ -743,15 +746,15 @@ public void DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() var waitTask = Task.Run( () => target.WaitOne(TimeSpan.FromMilliseconds(250), CancellationToken.None)); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(150))); + Assert.False(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(150))).Result); // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.True(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(1000))).Result); + Assert.False(waitTask.Result); } [Fact] - public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() + public void DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() { var target = new AsyncAutoResetEvent(false); @@ -759,12 +762,13 @@ public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() var waitTask = Task.Run( () => target.WaitOne(Timeout.InfiniteTimeSpan, cancelSource.Token)); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(250))); + Assert.False(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(250))).Result); cancelSource.Cancel(); - await Assert.ThrowsAsync( - async () => await waitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => waitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] @@ -777,12 +781,12 @@ public void DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() () => target.WaitOne(TimeSpan.FromMilliseconds(250), CancellationToken.None)); // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.True(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(300))).Result); + Assert.False(waitTask.Result); } [Fact] - public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsInitiallySetThenReset() + public void DoesNotReturnUntilCancelTokenIsSetWhenEventIsInitiallySetThenReset() { var target = new AsyncAutoResetEvent(true); target.Reset(); @@ -791,16 +795,17 @@ public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsInitiallySetThenR var waitTask = Task.Run( () => target.WaitOne(Timeout.InfiniteTimeSpan, cancelSource.Token)); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(250))); + Assert.False(Task.Run(() => waitTask.Wait(TimeSpan.FromMilliseconds(250))).Result); cancelSource.Cancel(); - await Assert.ThrowsAsync( - async () => await waitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => waitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] - public async Task ReturnsOnceWhenEventIsInitiallySet() + public void ReturnsOnceWhenEventIsInitiallySet() { var target = new AsyncAutoResetEvent(true); @@ -814,18 +819,19 @@ public async Task ReturnsOnceWhenEventIsInitiallySet() var unsuccessfulWaitTask = Task.Run( () => target.WaitOne(Timeout.InfiniteTimeSpan, cancelSource.Token)); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => unsuccessfulWaitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] - public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() + public void ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() { var target = new AsyncAutoResetEvent(false); target.Set(); @@ -840,18 +846,19 @@ public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitO var unsuccessfulWaitTask = Task.Run( () => target.WaitOne(Timeout.InfiniteTimeSpan, cancelSource.Token)); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => unsuccessfulWaitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] - public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOne() + public void ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOne() { var target = new AsyncAutoResetEvent(false); @@ -865,23 +872,24 @@ public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOn var unsuccessfulWaitTask = Task.Run( () => target.WaitOne(Timeout.InfiniteTimeSpan, cancelSource.Token)); - Assert.False(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - + Assert.False(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + target.Set(); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => unsuccessfulWaitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] - public async Task ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOne() + public void ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOne() { var target = new AsyncAutoResetEvent(true); target.Set(); @@ -896,18 +904,19 @@ public async Task ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOne() var unsuccessfulWaitTask = Task.Run( () => target.WaitOne(Timeout.InfiniteTimeSpan, cancelSource.Token)); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => unsuccessfulWaitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] - public async Task ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOne() + public void ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOne() { var target = new AsyncAutoResetEvent(true); @@ -927,152 +936,152 @@ public async Task ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOne() var unsuccessfulWaitTask = Task.Run( () => target.WaitOne(Timeout.InfiniteTimeSpan, cancelSource.Token)); - Assert.True(successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask1.Result); + Assert.False(Task.Run(() => successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); target.Set(); - Assert.True(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.Run(() => successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))).Result); + Assert.True(successfulWaitTask2.Result); + Assert.False(Task.Run(() => unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))).Result); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + var aggregateException = Assert.Throws(() => unsuccessfulWaitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } } public class WaitOneAsync { [Fact] - public void ReturnsOnceWhenEventIsInitiallySet() + public async Task ReturnsOnceWhenEventIsInitiallySet() { var target = new AsyncAutoResetEvent(true); var successfulWaitTask = target.WaitOneAsync(); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(250))); + await successfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(250)); } [Fact] - public void ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOneAsync() + public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOneAsync() { var target = new AsyncAutoResetEvent(false); target.Set(); var successfulWaitTask = target.WaitOneAsync(); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); + await successfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(250)); } [Fact] - public void ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOneAsync() + public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOneAsync() { var target = new AsyncAutoResetEvent(false); var successfulWaitTask = target.WaitOneAsync(); - // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(250); - Assert.False(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(250))); + Assert.False(successfulWaitTask.IsCompleted); target.Set(); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await successfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(50)); } [Fact] - public void ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOneAsync() + public async Task ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOneAsync() { var target = new AsyncAutoResetEvent(true); target.Set(); - var cancelSource = new CancellationTokenSource(); var successfulWaitTask = target.WaitOneAsync(); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await successfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(50)); } [Fact] - public void ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOneAsync() + public async Task ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOneAsync() { var target = new AsyncAutoResetEvent(true); var successfulWaitTask1 = target.WaitOneAsync(); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(50); var successfulWaitTask2 = target.WaitOneAsync(); // Add a small delay to make sure the second task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(50); + + await successfulWaitTask1.WithTimeout(TimeSpan.FromMilliseconds(50)); - Assert.True(successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.False(successfulWaitTask2.IsCompleted); target.Set(); - Assert.True(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); + await successfulWaitTask2.WithTimeout(TimeSpan.FromMilliseconds(50)); } } public class WaitOneAsync_Int32 { [Fact] - public void DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() + public async Task DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() { var target = new AsyncAutoResetEvent(false); var waitTask = target.WaitOneAsync(250); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(150))); + await Task.Delay(200); + Assert.False(waitTask.IsCompleted); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(10000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.False(await waitTask.WithTimeout(100)); } [Fact] - public void DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() + public async Task DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() { var target = new AsyncAutoResetEvent(true); target.Reset(); var waitTask = target.WaitOneAsync(250); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(150))); + await Task.Delay(200); + Assert.False(waitTask.IsCompleted); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.False(await waitTask.WithTimeout(TimeSpan.FromMilliseconds(100))); } [Fact] - public void ReturnsOnceWhenEventIsInitiallySet() + public async Task ReturnsOnceWhenEventIsInitiallySet() { var target = new AsyncAutoResetEvent(true); var successfulWaitTask = target.WaitOneAsync(250); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(250); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(await successfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(50))); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + await Task.Delay(200); + Assert.False(unsuccessfulWaitTask.IsCompleted); + + Assert.False(await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(100))); } [Fact] - public void ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOneAsync() + public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOneAsync() { var target = new AsyncAutoResetEvent(false); target.Set(); @@ -1080,45 +1089,48 @@ public void ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOneAsyn var successfulWaitTask = target.WaitOneAsync(250); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(250); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(await successfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(50))); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + await Task.Delay(200); + Assert.False(unsuccessfulWaitTask.IsCompleted); + + Assert.False(await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(300))); } [Fact] - public void ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOneAsync() + public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOneAsync() { var target = new AsyncAutoResetEvent(false); var successfulWaitTask = target.WaitOneAsync(250); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(250); - Assert.False(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.False(successfulWaitTask.IsCompleted); + Assert.False(unsuccessfulWaitTask.IsCompleted); target.Set(); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.True(successfulWaitTask.IsCompleted); + Assert.True(successfulWaitTask.Result); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + await Task.Delay(100); + Assert.False(unsuccessfulWaitTask.IsCompleted); + + Assert.False(await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(300))); } [Fact] - public void ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOneAsync() + public async Task ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOneAsync() { var target = new AsyncAutoResetEvent(true); target.Set(); @@ -1126,103 +1138,103 @@ public void ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOneAsync() var successfulWaitTask = target.WaitOneAsync(250); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(250); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(await successfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(50))); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + await Task.Delay(200); + Assert.False(unsuccessfulWaitTask.IsCompleted); + + Assert.False(await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(300))); } [Fact] - public void ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOneAsync() + public async Task ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOneAsync() { var target = new AsyncAutoResetEvent(true); var successfulWaitTask1 = target.WaitOneAsync(250); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var successfulWaitTask2 = target.WaitOneAsync(250); // Add a small delay to make sure the second task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(250); - Assert.True(successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(await successfulWaitTask1.WithTimeout(TimeSpan.FromMilliseconds(50))); + + await Task.Delay(TimeSpan.FromMilliseconds(50)); + Assert.False(successfulWaitTask2.IsCompleted); + Assert.False(unsuccessfulWaitTask.IsCompleted); target.Set(); - Assert.True(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(await successfulWaitTask2.WithTimeout(TimeSpan.FromMilliseconds(50))); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + await Task.Delay(TimeSpan.FromMilliseconds(50)); + Assert.False(unsuccessfulWaitTask.IsCompleted); + + Assert.False(await unsuccessfulWaitTask.WithTimeout(100)); } } public class WaitOneAsync_TimeSpan { [Fact] - public void DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() + public async Task DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() { var target = new AsyncAutoResetEvent(false); var waitTask = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(150))); + await Task.Delay(200); + Assert.False(waitTask.IsCompleted); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.False(await waitTask.WithTimeout(100)); } [Fact] - public void DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() + public async Task DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() { var target = new AsyncAutoResetEvent(true); target.Reset(); var waitTask = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(150))); + await Task.Delay(200); + Assert.False(waitTask.IsCompleted); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.False(await waitTask.WithTimeout(TimeSpan.FromMilliseconds(100))); } [Fact] - public void ReturnsOnceWhenEventIsInitiallySet() + public async Task ReturnsOnceWhenEventIsInitiallySet() { var target = new AsyncAutoResetEvent(true); var successfulWaitTask = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(await successfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(50))); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + await Task.Delay(200); + Assert.False(unsuccessfulWaitTask.IsCompleted); + + Assert.False(await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(100))); } [Fact] - public void ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOneAsync() + public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOneAsync() { var target = new AsyncAutoResetEvent(false); target.Set(); @@ -1230,45 +1242,48 @@ public void ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOneAsyn var successfulWaitTask = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(await successfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(50))); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + await Task.Delay(200); + Assert.False(unsuccessfulWaitTask.IsCompleted); + + Assert.False(await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(300))); } [Fact] - public void ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOneAsync() + public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOneAsync() { var target = new AsyncAutoResetEvent(false); var successfulWaitTask = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); - Assert.False(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.False(successfulWaitTask.IsCompleted); + Assert.False(unsuccessfulWaitTask.IsCompleted); target.Set(); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.True(successfulWaitTask.IsCompleted); + Assert.True(successfulWaitTask.Result); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + await Task.Delay(100); + Assert.False(unsuccessfulWaitTask.IsCompleted); + + Assert.False(await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(300))); } [Fact] - public void ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOneAsync() + public async Task ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOneAsync() { var target = new AsyncAutoResetEvent(true); target.Set(); @@ -1276,47 +1291,49 @@ public void ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOneAsync() var successfulWaitTask = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(await successfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(50))); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + await Task.Delay(200); + Assert.False(unsuccessfulWaitTask.IsCompleted); + + Assert.False(await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(300))); } [Fact] - public void ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOneAsync() + public async Task ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOneAsync() { var target = new AsyncAutoResetEvent(true); var successfulWaitTask1 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var successfulWaitTask2 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); // Add a small delay to make sure the second task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); - Assert.True(successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(await successfulWaitTask1.WithTimeout(TimeSpan.FromMilliseconds(50))); + + await Task.Delay(TimeSpan.FromMilliseconds(50)); + Assert.False(successfulWaitTask2.IsCompleted); + Assert.False(unsuccessfulWaitTask.IsCompleted); target.Set(); - Assert.True(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(await successfulWaitTask2.WithTimeout(TimeSpan.FromMilliseconds(50))); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(unsuccessfulWaitTask.GetAwaiter().GetResult()); + await Task.Delay(TimeSpan.FromMilliseconds(50)); + Assert.False(unsuccessfulWaitTask.IsCompleted); + + Assert.False(await unsuccessfulWaitTask.WithTimeout(100)); } } @@ -1330,12 +1347,12 @@ public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() var cancelSource = new CancellationTokenSource(); var waitTask = target.WaitOneAsync(cancelSource.Token); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(250))); + await Task.Delay(250); + Assert.False(waitTask.IsCompleted); cancelSource.Cancel(); - await Assert.ThrowsAsync( - async () => await waitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => waitTask.WithTimeout(50)); } [Fact] @@ -1347,18 +1364,18 @@ public async Task ReturnsOnceWhenEventIsInitiallySet() var successfulWaitTask = target.WaitOneAsync(cancelSource.Token); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(cancelSource.Token); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(TimeSpan.FromMilliseconds(50)); + Assert.True(successfulWaitTask.IsCompleted); + Assert.True(successfulWaitTask.Result); + Assert.False(unsuccessfulWaitTask.IsCompleted); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => unsuccessfulWaitTask.WithTimeout(50)); } [Fact] @@ -1371,18 +1388,18 @@ public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitO var successfulWaitTask = target.WaitOneAsync(cancelSource.Token); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(cancelSource.Token); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.True(successfulWaitTask.IsCompleted); + Assert.True(successfulWaitTask.Result); + Assert.False(unsuccessfulWaitTask.IsCompleted); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => unsuccessfulWaitTask.WithTimeout(50)); } [Fact] @@ -1394,23 +1411,24 @@ public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOn var successfulWaitTask = target.WaitOneAsync(cancelSource.Token); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(cancelSource.Token); - Assert.False(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.False(successfulWaitTask.IsCompleted); + Assert.False(unsuccessfulWaitTask.IsCompleted); target.Set(); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.True(successfulWaitTask.IsCompleted); + Assert.True(successfulWaitTask.Result); + Assert.False(unsuccessfulWaitTask.IsCompleted); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => unsuccessfulWaitTask.WithTimeout(50)); } [Fact] @@ -1423,18 +1441,18 @@ public async Task ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOneAsync() var successfulWaitTask = target.WaitOneAsync(cancelSource.Token); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(cancelSource.Token); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.True(successfulWaitTask.IsCompleted); + Assert.True(successfulWaitTask.Result); + Assert.False(unsuccessfulWaitTask.IsCompleted); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => unsuccessfulWaitTask.WithTimeout(50)); } [Fact] @@ -1446,44 +1464,47 @@ public async Task ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOneAsync() var successfulWaitTask1 = target.WaitOneAsync(cancelSource.Token); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var successfulWaitTask2 = target.WaitOneAsync(cancelSource.Token); // Add a small delay to make sure the second task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(cancelSource.Token); - Assert.True(successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(TimeSpan.FromMilliseconds(50)); + Assert.True(successfulWaitTask1.IsCompleted); + Assert.True(successfulWaitTask1.Result); + Assert.False(successfulWaitTask2.IsCompleted); + Assert.False(unsuccessfulWaitTask.IsCompleted); target.Set(); - Assert.True(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(TimeSpan.FromMilliseconds(50)); + Assert.True(successfulWaitTask2.IsCompleted); + Assert.True(successfulWaitTask2.Result); + Assert.False(unsuccessfulWaitTask.IsCompleted); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => unsuccessfulWaitTask.WithTimeout(50)); } } public class WaitOneAsync_Int32_CancellationToken { [Fact] - public void DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() + public async Task DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() { var target = new AsyncAutoResetEvent(false); var waitTask = target.WaitOneAsync(250, CancellationToken.None); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + await Task.Delay(200); + Assert.False(waitTask.IsCompleted); + + Assert.False(await waitTask.WithTimeout(100)); } [Fact] @@ -1494,25 +1515,23 @@ public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() var cancelSource = new CancellationTokenSource(); var waitTask = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(250))); + await Task.Delay(250); + Assert.False(waitTask.IsCompleted); cancelSource.Cancel(); - await Assert.ThrowsAsync( - async () => await waitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => waitTask.WithTimeout(50)); } [Fact] - public void DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() + public async Task DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() { var target = new AsyncAutoResetEvent(true); target.Reset(); var waitTask = target.WaitOneAsync(250, CancellationToken.None); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.False(await waitTask.WithTimeout(TimeSpan.FromMilliseconds(300))); } [Fact] @@ -1524,12 +1543,12 @@ public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsInitiallySetThenR var cancelSource = new CancellationTokenSource(); var waitTask = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(250))); + await Task.Delay(TimeSpan.FromMilliseconds(250)); + Assert.False(waitTask.IsCompleted); cancelSource.Cancel(); - await Assert.ThrowsAsync( - async () => await waitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => waitTask.WithTimeout(50)); } [Fact] @@ -1541,18 +1560,18 @@ public async Task ReturnsOnceWhenEventIsInitiallySet() var successfulWaitTask = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(TimeSpan.FromMilliseconds(50)); + Assert.True(successfulWaitTask.IsCompleted); + Assert.True(successfulWaitTask.Result); + Assert.False(unsuccessfulWaitTask.IsCompleted); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => unsuccessfulWaitTask.WithTimeout(50)); } [Fact] @@ -1565,18 +1584,18 @@ public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitO var successfulWaitTask = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.True(successfulWaitTask.IsCompleted); + Assert.True(successfulWaitTask.Result); + Assert.False(unsuccessfulWaitTask.IsCompleted); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => unsuccessfulWaitTask.WithTimeout(50)); } [Fact] @@ -1588,47 +1607,48 @@ public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOn var successfulWaitTask = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); - Assert.False(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.False(successfulWaitTask.IsCompleted); + Assert.False(unsuccessfulWaitTask.IsCompleted); target.Set(); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.True(successfulWaitTask.IsCompleted); + Assert.True(successfulWaitTask.Result); + Assert.False(unsuccessfulWaitTask.IsCompleted); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => unsuccessfulWaitTask.WithTimeout(50)); } [Fact] public async Task ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOneAsync() { - var target = new AsyncAutoResetEvent(false); + var target = new AsyncAutoResetEvent(true); target.Set(); var cancelSource = new CancellationTokenSource(); var successfulWaitTask = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.True(successfulWaitTask.IsCompleted); + Assert.True(successfulWaitTask.Result); + Assert.False(unsuccessfulWaitTask.IsCompleted); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => unsuccessfulWaitTask.WithTimeout(50)); } [Fact] @@ -1640,46 +1660,47 @@ public async Task ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOneAsync() var successfulWaitTask1 = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var successfulWaitTask2 = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); // Add a small delay to make sure the second task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); - Assert.True(successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(TimeSpan.FromMilliseconds(50)); + Assert.True(successfulWaitTask1.IsCompleted); + Assert.True(successfulWaitTask1.Result); + Assert.False(successfulWaitTask2.IsCompleted); + Assert.False(unsuccessfulWaitTask.IsCompleted); target.Set(); - Assert.True(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(TimeSpan.FromMilliseconds(50)); + Assert.True(successfulWaitTask2.IsCompleted); + Assert.True(successfulWaitTask2.Result); + Assert.False(unsuccessfulWaitTask.IsCompleted); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => unsuccessfulWaitTask.WithTimeout(50)); } } public class WaitOneAsync_TimeSpan_CancellationToken { [Fact] - public void DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() + public async Task DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() { var target = new AsyncAutoResetEvent(false); var waitTask = target.WaitOneAsync(TimeSpan.FromMilliseconds(250), CancellationToken.None); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(150))); + await Task.Delay(200); + Assert.False(waitTask.IsCompleted); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.False(await waitTask.WithTimeout(100)); } [Fact] @@ -1690,25 +1711,23 @@ public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() var cancelSource = new CancellationTokenSource(); var waitTask = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(250))); + await Task.Delay(250); + Assert.False(waitTask.IsCompleted); cancelSource.Cancel(); - await Assert.ThrowsAsync( - async () => await waitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => waitTask.WithTimeout(50)); } [Fact] - public void DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() + public async Task DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() { var target = new AsyncAutoResetEvent(true); target.Reset(); var waitTask = target.WaitOneAsync(TimeSpan.FromMilliseconds(250), CancellationToken.None); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.False(await waitTask.WithTimeout(TimeSpan.FromMilliseconds(300))); } [Fact] @@ -1720,12 +1739,12 @@ public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsInitiallySetThenR var cancelSource = new CancellationTokenSource(); var waitTask = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(250))); + await Task.Delay(TimeSpan.FromMilliseconds(250)); + Assert.False(waitTask.IsCompleted); cancelSource.Cancel(); - await Assert.ThrowsAsync( - async () => await waitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => waitTask.WithTimeout(50)); } [Fact] @@ -1737,18 +1756,18 @@ public async Task ReturnsOnceWhenEventIsInitiallySet() var successfulWaitTask = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(TimeSpan.FromMilliseconds(50)); + Assert.True(successfulWaitTask.IsCompleted); + Assert.True(successfulWaitTask.Result); + Assert.False(unsuccessfulWaitTask.IsCompleted); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => unsuccessfulWaitTask.WithTimeout(50)); } [Fact] @@ -1761,18 +1780,18 @@ public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitO var successfulWaitTask = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.True(successfulWaitTask.IsCompleted); + Assert.True(successfulWaitTask.Result); + Assert.False(unsuccessfulWaitTask.IsCompleted); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => unsuccessfulWaitTask.WithTimeout(50)); } [Fact] @@ -1784,23 +1803,24 @@ public async Task ReturnsOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOn var successfulWaitTask = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); - Assert.False(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.False(successfulWaitTask.IsCompleted); + Assert.False(unsuccessfulWaitTask.IsCompleted); target.Set(); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.True(successfulWaitTask.IsCompleted); + Assert.True(successfulWaitTask.Result); + Assert.False(unsuccessfulWaitTask.IsCompleted); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => unsuccessfulWaitTask.WithTimeout(50)); } [Fact] @@ -1813,18 +1833,18 @@ public async Task ReturnsOnceWhenEventIsSetTwiceBeforeCallingWaitOneAsync() var successfulWaitTask = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); - Assert.True(successfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(50); + Assert.True(successfulWaitTask.IsCompleted); + Assert.True(successfulWaitTask.Result); + Assert.False(unsuccessfulWaitTask.IsCompleted); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => unsuccessfulWaitTask.WithTimeout(50)); } [Fact] @@ -1836,29 +1856,31 @@ public async Task ReturnsTwiceWhenEventIsSetBeforeAndAfterCallingWaitOneAsync() var successfulWaitTask1 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); // Add a small delay to make sure the first task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var successfulWaitTask2 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); // Add a small delay to make sure the second task calls WaitOneAsync first - Task.Delay(TimeSpan.FromMilliseconds(50)).Wait(); + await Task.Delay(TimeSpan.FromMilliseconds(50)); var unsuccessfulWaitTask = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); - Assert.True(successfulWaitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(TimeSpan.FromMilliseconds(50)); + Assert.True(successfulWaitTask1.IsCompleted); + Assert.True(successfulWaitTask1.Result); + Assert.False(successfulWaitTask2.IsCompleted); + Assert.False(unsuccessfulWaitTask.IsCompleted); target.Set(); - Assert.True(successfulWaitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(unsuccessfulWaitTask.Wait(TimeSpan.FromMilliseconds(50))); + await Task.Delay(TimeSpan.FromMilliseconds(50)); + Assert.True(successfulWaitTask2.IsCompleted); + Assert.True(successfulWaitTask2.Result); + Assert.False(unsuccessfulWaitTask.IsCompleted); cancelSource.Cancel(); - // Wait for the canceled task to complete so aren't any lingering background threads. - await Assert.ThrowsAsync( - async () => await unsuccessfulWaitTask.WithTimeout(TimeSpan.FromMilliseconds(1000))); + await Assert.ThrowsAsync(() => unsuccessfulWaitTask.WithTimeout(50)); } } } diff --git a/UnitTests/UnitTests.CodeTiger.Core/Threading/AsyncLockTests.cs b/UnitTests/UnitTests.CodeTiger.Core/Threading/AsyncLockTests.cs index 28886ac..e526f3e 100644 --- a/UnitTests/UnitTests.CodeTiger.Core/Threading/AsyncLockTests.cs +++ b/UnitTests/UnitTests.CodeTiger.Core/Threading/AsyncLockTests.cs @@ -1,4 +1,6 @@ -using System.Threading; +using System; +using System.Linq; +using System.Threading; using System.Threading.Tasks; using CodeTiger.Threading; using Xunit; @@ -42,7 +44,7 @@ public void DoesNotReturnIfFirstCallerHasNotDisposedLockObject() var firstLockObject = target.Acquire(); - Task.Delay(50).GetAwaiter().GetResult(); + Task.Delay(50).Wait(); var secondLockObjectTask = Task.Factory.StartNew(() => target.Acquire()); @@ -56,11 +58,11 @@ public void ReturnsToSecondCallerWhenFirstCallerDisposesLockObject() var firstLockObject = target.Acquire(); - Task.Delay(50).GetAwaiter().GetResult(); + Task.Delay(50).Wait(); var secondLockObjectTask = Task.Factory.StartNew(() => target.Acquire()); - Task.Delay(100).GetAwaiter().GetResult(); + Task.Delay(100).Wait(); Assert.False(secondLockObjectTask.IsCompleted); @@ -88,7 +90,7 @@ public void ReturnsImmediatelyToSecondCallerIfFirstCallerHasAlreadyDisposedLockO var target = new AsyncLock(); var firstLockObjectTask = Task.Factory.StartNew(() => target.Acquire(CancellationToken.None)); - firstLockObjectTask.GetAwaiter().GetResult().Dispose(); + firstLockObjectTask.Result.Dispose(); var secondLockObjectTask = Task.Factory.StartNew(() => target.Acquire(CancellationToken.None)); @@ -102,7 +104,7 @@ public void DoesNotReturnIfFirstCallerHasNotDisposedLockObject() var firstLockObject = target.Acquire(CancellationToken.None); - Task.Delay(50).GetAwaiter().GetResult(); + Task.Delay(50).Wait(); var secondLockObjectTask = Task.Factory.StartNew(() => target.Acquire(CancellationToken.None)); @@ -116,11 +118,11 @@ public void ReturnsToSecondCallerWhenFirstCallerDisposesLockObject() var firstLockObject = target.Acquire(CancellationToken.None); - Task.Delay(50).GetAwaiter().GetResult(); + Task.Delay(50).Wait(); var secondLockObjectTask = Task.Factory.StartNew(() => target.Acquire(CancellationToken.None)); - Task.Delay(100).GetAwaiter().GetResult(); + Task.Delay(100).Wait(); Assert.False(secondLockObjectTask.IsCompleted); @@ -136,19 +138,21 @@ public void ThrowsTaskCanceledExceptionWhenCancellationTokenIsSet() var firstLockObject = target.Acquire(CancellationToken.None); - Task.Delay(50).GetAwaiter().GetResult(); + Task.Delay(50).Wait(); var cancellationTokenSource = new CancellationTokenSource(); var secondLockObjectTask = Task.Factory.StartNew( () => target.Acquire(cancellationTokenSource.Token)); - Task.Delay(50).GetAwaiter().GetResult(); + Task.Delay(50).Wait(); Assert.False(secondLockObjectTask.Wait(50)); cancellationTokenSource.Cancel(); - Assert.Throws(() => secondLockObjectTask.GetAwaiter().GetResult()); + var aggregateException = Assert.Throws(() => secondLockObjectTask.Wait(50)); + Assert.Equal(typeof(TaskCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } } @@ -170,7 +174,10 @@ public void ReturnsSameCompletedTaskToSecondCallerIfFirstCallerHasAlreadyDispose var target = new AsyncLock(); var firstLockObjectTask = target.AcquireAsync(); - firstLockObjectTask.GetAwaiter().GetResult().Dispose(); + + Assert.True(firstLockObjectTask.IsCompleted); + + firstLockObjectTask.Result.Dispose(); var secondLockObjectTask = target.AcquireAsync(); @@ -178,37 +185,39 @@ public void ReturnsSameCompletedTaskToSecondCallerIfFirstCallerHasAlreadyDispose } [Fact] - public void ReturnsUncompletedTaskToSecondCallerIfFirstCallerHasNotDisposedLockObject() + public async Task ReturnsUncompletedTaskToSecondCallerIfFirstCallerHasNotDisposedLockObject() { var target = new AsyncLock(); var firstLockObjectTask = target.AcquireAsync(); - Task.Delay(50).GetAwaiter().GetResult(); + await Task.Delay(50); var secondLockObjectTask = target.AcquireAsync(); Assert.NotSame(firstLockObjectTask, secondLockObjectTask); Assert.False(secondLockObjectTask.IsCompleted); + + firstLockObjectTask.Result.Dispose(); } [Fact] - public void ReturnsUncompletedTaskToSecondCallerThatCompletesWhenFirstCallerDisposesLockObject() + public async Task ReturnsUncompletedTaskToSecondCallerThatCompletesWhenFirstCallerDisposesLockObject() { var target = new AsyncLock(); var firstLockObjectTask = target.AcquireAsync(); - Task.Delay(50).GetAwaiter().GetResult(); + await Task.Delay(50); var secondLockObjectTask = target.AcquireAsync(); Assert.NotSame(firstLockObjectTask, secondLockObjectTask); Assert.False(secondLockObjectTask.IsCompleted); - firstLockObjectTask.GetAwaiter().GetResult().Dispose(); + (await firstLockObjectTask).Dispose(); - Task.Delay(50).GetAwaiter().GetResult(); + await Task.Delay(50); Assert.True(secondLockObjectTask.IsCompleted); } @@ -232,7 +241,10 @@ public void ReturnsSameCompletedTaskToSecondCallerIfFirstCallerHasAlreadyDispose var target = new AsyncLock(); var firstLockObjectTask = target.AcquireAsync(CancellationToken.None); - firstLockObjectTask.GetAwaiter().GetResult().Dispose(); + + Assert.True(firstLockObjectTask.IsCompleted); + + firstLockObjectTask.Result.Dispose(); var secondLockObjectTask = target.AcquireAsync(CancellationToken.None); @@ -240,37 +252,39 @@ public void ReturnsSameCompletedTaskToSecondCallerIfFirstCallerHasAlreadyDispose } [Fact] - public void ReturnsUncompletedTaskToSecondCallerIfFirstCallerHasNotDisposedLockObject() + public async Task ReturnsUncompletedTaskToSecondCallerIfFirstCallerHasNotDisposedLockObject() { var target = new AsyncLock(); var firstLockObjectTask = target.AcquireAsync(CancellationToken.None); - Task.Delay(50).GetAwaiter().GetResult(); + await Task.Delay(50); var secondLockObjectTask = target.AcquireAsync(CancellationToken.None); Assert.NotSame(firstLockObjectTask, secondLockObjectTask); Assert.False(secondLockObjectTask.IsCompleted); + + firstLockObjectTask.Result.Dispose(); } [Fact] - public void ReturnsUncompletedTaskToSecondCallerThatCompletesWhenFirstCallerDisposesLockObject() + public async Task ReturnsUncompletedTaskToSecondCallerThatCompletesWhenFirstCallerDisposesLockObject() { var target = new AsyncLock(); var firstLockObjectTask = target.AcquireAsync(CancellationToken.None); - Task.Delay(50).GetAwaiter().GetResult(); + await Task.Delay(50); var secondLockObjectTask = target.AcquireAsync(CancellationToken.None); Assert.NotSame(firstLockObjectTask, secondLockObjectTask); Assert.False(secondLockObjectTask.IsCompleted); - firstLockObjectTask.GetAwaiter().GetResult().Dispose(); + (await firstLockObjectTask).Dispose(); - Task.Delay(50).GetAwaiter().GetResult(); + await Task.Delay(50); Assert.True(secondLockObjectTask.IsCompleted); } diff --git a/UnitTests/UnitTests.CodeTiger.Core/Threading/AsyncManualResetEventTests.cs b/UnitTests/UnitTests.CodeTiger.Core/Threading/AsyncManualResetEventTests.cs index 0235518..f527815 100644 --- a/UnitTests/UnitTests.CodeTiger.Core/Threading/AsyncManualResetEventTests.cs +++ b/UnitTests/UnitTests.CodeTiger.Core/Threading/AsyncManualResetEventTests.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Threading; using System.Threading.Tasks; using CodeTiger.Threading; @@ -23,9 +24,7 @@ public void ReturnsMoreThanOnceWhenEventIsInitiallySet() var waitTask2 = Task.Run(() => target.WaitOne()); var waitTask3 = Task.Run(() => target.WaitOne()); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(250))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(250))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(250))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); } [Fact] @@ -38,9 +37,7 @@ public void ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWai var waitTask2 = Task.Run(() => target.WaitOne()); var waitTask3 = Task.Run(() => target.WaitOne()); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(250))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(250))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(250))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); } [Fact] @@ -52,15 +49,11 @@ public void ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetAfterCallingWait var waitTask2 = Task.Run(() => target.WaitOne()); var waitTask3 = Task.Run(() => target.WaitOne()); - Assert.False(waitTask1.Wait(TimeSpan.FromMilliseconds(250))); - Assert.False(waitTask2.Wait(TimeSpan.FromMilliseconds(250))); - Assert.False(waitTask3.Wait(TimeSpan.FromMilliseconds(250))); + Assert.Equal(-1, Task.WaitAny(new[] { waitTask1, waitTask2, waitTask3 }, 250)); target.Set(); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); } [Fact] @@ -73,9 +66,7 @@ public void ReturnsMoreThanOnceWhenEventIsSetTwiceBeforeCallingWaitOne() var waitTask2 = Task.Run(() => target.WaitOne()); var waitTask3 = Task.Run(() => target.WaitOne()); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); } } @@ -88,11 +79,10 @@ public void DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() var waitTask = Task.Run(() => target.WaitOne(250)); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(150))); + Assert.False(waitTask.Wait(200)); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.True(waitTask.Wait(100)); + Assert.False(waitTask.Result); } [Fact] @@ -103,11 +93,10 @@ public void DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() var waitTask = Task.Run(() => target.WaitOne(250)); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(150))); + Assert.False(waitTask.Wait(200)); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.True(waitTask.Wait(100)); + Assert.False(waitTask.Result); } [Fact] @@ -119,9 +108,11 @@ public void ReturnsMoreThanOnceWhenEventIsInitiallySet() var waitTask2 = Task.Run(() => target.WaitOne(250)); var waitTask3 = Task.Run(() => target.WaitOne(250)); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); } [Fact] @@ -134,9 +125,11 @@ public void ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWai var waitTask2 = Task.Run(() => target.WaitOne(250)); var waitTask3 = Task.Run(() => target.WaitOne(250)); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); } [Fact] @@ -148,15 +141,15 @@ public void ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetAfterCallingWait var waitTask2 = Task.Run(() => target.WaitOne(250)); var waitTask3 = Task.Run(() => target.WaitOne(250)); - Assert.False(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.Equal(-1, Task.WaitAny(new[] { waitTask1, waitTask2, waitTask3 }, 150)); target.Set(); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); } [Fact] @@ -169,9 +162,11 @@ public void ReturnsMoreThanOnceWhenEventIsSetTwiceBeforeCallingWaitOne() var waitTask2 = Task.Run(() => target.WaitOne(250)); var waitTask3 = Task.Run(() => target.WaitOne(250)); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); } } @@ -184,11 +179,10 @@ public void DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() var waitTask = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(150))); + Assert.False(waitTask.Wait(200)); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.True(waitTask.Wait(100)); + Assert.False(waitTask.Result); } [Fact] @@ -199,11 +193,10 @@ public void DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() var waitTask = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(150))); + Assert.False(waitTask.Wait(200)); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(1000))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.True(waitTask.Wait(100)); + Assert.False(waitTask.Result); } [Fact] @@ -215,9 +208,11 @@ public void ReturnsMoreThanOnceWhenEventIsInitiallySet() var waitTask2 = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); var waitTask3 = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); } [Fact] @@ -230,9 +225,11 @@ public void ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWai var waitTask2 = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); var waitTask3 = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); } [Fact] @@ -244,15 +241,15 @@ public void ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetAfterCallingWait var waitTask2 = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); var waitTask3 = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); - Assert.False(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.False(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.Equal(-1, Task.WaitAny(new[] { waitTask1, waitTask2, waitTask3 }, 200)); target.Set(); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); } [Fact] @@ -265,29 +262,31 @@ public void ReturnsMoreThanOnceWhenEventIsSetTwiceBeforeCallingWaitOne() var waitTask2 = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); var waitTask3 = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250))); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); } } public class WaitOne_CancellationToken { [Fact] - public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() + public void DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() { var target = new AsyncManualResetEvent(false); var cancelSource = new CancellationTokenSource(); var waitTask = Task.Run(() => target.WaitOne(cancelSource.Token)); - Assert.False(waitTask.Wait(TimeSpan.FromMilliseconds(250))); + Assert.False(waitTask.Wait(200)); cancelSource.Cancel(); - await Assert.ThrowsAsync( - async () => await waitTask.WithTimeout(TimeSpan.FromMilliseconds(500)) - .ConfigureAwait(false)); + var aggregateException = Assert.Throws(() => waitTask.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] @@ -299,9 +298,7 @@ public void ReturnsMoreThanOnceWhenEventIsInitiallySet() var waitTask2 = Task.Run(() => target.WaitOne(CancellationToken.None)); var waitTask3 = Task.Run(() => target.WaitOne(CancellationToken.None)); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(250))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(250))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(250))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); } [Fact] @@ -314,9 +311,7 @@ public void ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWai var waitTask2 = Task.Run(() => target.WaitOne(CancellationToken.None)); var waitTask3 = Task.Run(() => target.WaitOne(CancellationToken.None)); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(250))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(250))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(250))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); } [Fact] @@ -330,9 +325,7 @@ public void ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetAfterCallingWait target.Set(); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(250))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(250))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(250))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); } [Fact] @@ -344,10 +337,8 @@ public void ReturnsMoreThanOnceWhenEventIsSetTwiceBeforeCallingWaitOne() var waitTask1 = Task.Run(() => target.WaitOne(CancellationToken.None)); var waitTask2 = Task.Run(() => target.WaitOne(CancellationToken.None)); var waitTask3 = Task.Run(() => target.WaitOne(CancellationToken.None)); - - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(250))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(250))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(250))); + + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); } } @@ -360,13 +351,12 @@ public void DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() var waitTask = Task.Run(() => target.WaitOne(250, CancellationToken.None)); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(500))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.True(waitTask.Wait(300)); + Assert.False(waitTask.Result); } [Fact] - public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() + public void DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() { var target = new AsyncManualResetEvent(false); @@ -375,18 +365,19 @@ public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() var waitTask2 = Task.Run(() => target.WaitOne(Timeout.Infinite, cancelSource.Token)); var waitTask3 = Task.Run(() => target.WaitOne(Timeout.Infinite, cancelSource.Token)); - Assert.False(waitTask1.Wait(TimeSpan.FromMilliseconds(250))); - Assert.False(waitTask2.Wait(TimeSpan.FromMilliseconds(250))); - Assert.False(waitTask3.Wait(TimeSpan.FromMilliseconds(250))); + Assert.Equal(-1, Task.WaitAny(new[] { waitTask1, waitTask2, waitTask3 }, 250)); cancelSource.Cancel(); - await Assert.ThrowsAsync( - async () => await waitTask1.WithTimeout(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false)); - await Assert.ThrowsAsync( - async () => await waitTask2.WithTimeout(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false)); - await Assert.ThrowsAsync( - async () => await waitTask3.WithTimeout(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false)); + var aggregateException1 = Assert.Throws(() => waitTask1.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException1.Flatten().InnerExceptions.Single().GetType()); + var aggregateException2 = Assert.Throws(() => waitTask2.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException2.Flatten().InnerExceptions.Single().GetType()); + var aggregateException3 = Assert.Throws(() => waitTask3.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException3.Flatten().InnerExceptions.Single().GetType()); } [Fact] @@ -399,16 +390,17 @@ public void DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() var waitTask2 = Task.Run(() => target.WaitOne(250, CancellationToken.None)); var waitTask3 = Task.Run(() => target.WaitOne(250, CancellationToken.None)); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(500))); - Assert.False(waitTask1.GetAwaiter().GetResult()); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(500))); - Assert.False(waitTask2.GetAwaiter().GetResult()); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(500))); - Assert.False(waitTask3.GetAwaiter().GetResult()); + Assert.Equal(-1, Task.WaitAny(new[] { waitTask1, waitTask2, waitTask3 }, 200)); + + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 100)); + + Assert.False(waitTask1.Result); + Assert.False(waitTask2.Result); + Assert.False(waitTask3.Result); } [Fact] - public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsInitiallySetThenReset() + public void DoesNotReturnUntilCancelTokenIsSetWhenEventIsInitiallySetThenReset() { var target = new AsyncManualResetEvent(true); target.Reset(); @@ -418,16 +410,19 @@ public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsInitiallySetThenR var waitTask2 = Task.Run(() => target.WaitOne(Timeout.Infinite, cancelSource.Token)); var waitTask3 = Task.Run(() => target.WaitOne(Timeout.Infinite, cancelSource.Token)); - Assert.False(waitTask1.Wait(TimeSpan.FromMilliseconds(250))); + Assert.Equal(-1, Task.WaitAny(new[] { waitTask1, waitTask2, waitTask3 }, 250)); cancelSource.Cancel(); - await Assert.ThrowsAsync( - async () => await waitTask1.WithTimeout(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false)); - await Assert.ThrowsAsync( - async () => await waitTask2.WithTimeout(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false)); - await Assert.ThrowsAsync( - async () => await waitTask3.WithTimeout(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false)); + var aggregateException1 = Assert.Throws(() => waitTask1.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException1.Flatten().InnerExceptions.Single().GetType()); + var aggregateException2 = Assert.Throws(() => waitTask2.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException2.Flatten().InnerExceptions.Single().GetType()); + var aggregateException3 = Assert.Throws(() => waitTask3.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException3.Flatten().InnerExceptions.Single().GetType()); } [Fact] @@ -439,13 +434,15 @@ public void ReturnsMoreThanOnceWhenEventIsInitiallySet() var waitTask2 = Task.Run(() => target.WaitOne(Timeout.Infinite, CancellationToken.None)); var waitTask3 = Task.Run(() => target.WaitOne(Timeout.Infinite, CancellationToken.None)); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); } [Fact] - public void ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() + public void ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() { var target = new AsyncManualResetEvent(false); target.Set(); @@ -454,9 +451,11 @@ public void ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() var waitTask2 = Task.Run(() => target.WaitOne(Timeout.Infinite, CancellationToken.None)); var waitTask3 = Task.Run(() => target.WaitOne(Timeout.Infinite, CancellationToken.None)); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); } [Fact] @@ -470,11 +469,11 @@ public void ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetAfterCallingWait target.Set(); - Task.Delay(50).GetAwaiter().GetResult(); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); } [Fact] @@ -487,9 +486,11 @@ public void ReturnsMoreThanOnceWhenEventIsSetTwiceBeforeCallingWaitOne() var waitTask2 = Task.Run(() => target.WaitOne(Timeout.Infinite, CancellationToken.None)); var waitTask3 = Task.Run(() => target.WaitOne(Timeout.Infinite, CancellationToken.None)); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); } } @@ -500,16 +501,17 @@ public void DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() { var target = new AsyncManualResetEvent(false); - var waitTask = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250), - CancellationToken.None)); + var waitTask = Task.Run( + () => target.WaitOne(TimeSpan.FromMilliseconds(250), CancellationToken.None)); - // Wait for the task to complete so aren't any lingering background threads. - Assert.True(waitTask.Wait(TimeSpan.FromMilliseconds(500))); - Assert.False(waitTask.GetAwaiter().GetResult()); + Assert.False(waitTask.Wait(200)); + + Assert.True(waitTask.Wait(100)); + Assert.False(waitTask.Result); } [Fact] - public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() + public void DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() { var target = new AsyncManualResetEvent(false); @@ -518,18 +520,19 @@ public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() var waitTask2 = Task.Run(() => target.WaitOne(Timeout.InfiniteTimeSpan, cancelSource.Token)); var waitTask3 = Task.Run(() => target.WaitOne(Timeout.InfiniteTimeSpan, cancelSource.Token)); - Assert.False(waitTask1.Wait(TimeSpan.FromMilliseconds(250))); - Assert.False(waitTask2.Wait(TimeSpan.FromMilliseconds(250))); - Assert.False(waitTask3.Wait(TimeSpan.FromMilliseconds(250))); + Assert.Equal(-1, Task.WaitAny(new[] { waitTask1, waitTask2, waitTask3 }, 250)); cancelSource.Cancel(); - await Assert.ThrowsAsync( - async () => await waitTask1.WithTimeout(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false)); - await Assert.ThrowsAsync( - async () => await waitTask2.WithTimeout(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false)); - await Assert.ThrowsAsync( - async () => await waitTask3.WithTimeout(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false)); + var aggregateException1 = Assert.Throws(() => waitTask1.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException1.Flatten().InnerExceptions.Single().GetType()); + var aggregateException2 = Assert.Throws(() => waitTask2.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException2.Flatten().InnerExceptions.Single().GetType()); + var aggregateException3 = Assert.Throws(() => waitTask3.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException3.Flatten().InnerExceptions.Single().GetType()); } [Fact] @@ -545,16 +548,17 @@ public void DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() var waitTask3 = Task.Run(() => target.WaitOne(TimeSpan.FromMilliseconds(250), CancellationToken.None)); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(500))); - Assert.False(waitTask1.GetAwaiter().GetResult()); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(500))); - Assert.False(waitTask2.GetAwaiter().GetResult()); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(500))); - Assert.False(waitTask3.GetAwaiter().GetResult()); + Assert.Equal(-1, Task.WaitAny(new[] { waitTask1, waitTask2, waitTask3 }, 200)); + + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 100)); + + Assert.False(waitTask1.Result); + Assert.False(waitTask2.Result); + Assert.False(waitTask3.Result); } [Fact] - public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsInitiallySetThenReset() + public void DoesNotReturnUntilCancelTokenIsSetWhenEventIsInitiallySetThenReset() { var target = new AsyncManualResetEvent(true); target.Reset(); @@ -564,16 +568,19 @@ public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsInitiallySetThenR var waitTask2 = Task.Run(() => target.WaitOne(Timeout.InfiniteTimeSpan, cancelSource.Token)); var waitTask3 = Task.Run(() => target.WaitOne(Timeout.InfiniteTimeSpan, cancelSource.Token)); - Assert.False(waitTask1.Wait(TimeSpan.FromMilliseconds(250))); + Assert.Equal(-1, Task.WaitAny(new[] { waitTask1, waitTask2, waitTask3 }, 250)); cancelSource.Cancel(); - await Assert.ThrowsAsync( - async () => await waitTask1.WithTimeout(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false)); - await Assert.ThrowsAsync( - async () => await waitTask2.WithTimeout(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false)); - await Assert.ThrowsAsync( - async () => await waitTask3.WithTimeout(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false)); + var aggregateException1 = Assert.Throws(() => waitTask1.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException1.Flatten().InnerExceptions.Single().GetType()); + var aggregateException2 = Assert.Throws(() => waitTask2.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException2.Flatten().InnerExceptions.Single().GetType()); + var aggregateException3 = Assert.Throws(() => waitTask3.Wait(50)); + Assert.Equal(typeof(OperationCanceledException), + aggregateException3.Flatten().InnerExceptions.Single().GetType()); } [Fact] @@ -585,13 +592,15 @@ public void ReturnsMoreThanOnceWhenEventIsInitiallySet() var waitTask2 = Task.Run(() => target.WaitOne(Timeout.InfiniteTimeSpan, CancellationToken.None)); var waitTask3 = Task.Run(() => target.WaitOne(Timeout.InfiniteTimeSpan, CancellationToken.None)); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); } [Fact] - public void ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() + public void ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() { var target = new AsyncManualResetEvent(false); target.Set(); @@ -600,9 +609,11 @@ public void ReturnsOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() var waitTask2 = Task.Run(() => target.WaitOne(Timeout.InfiniteTimeSpan, CancellationToken.None)); var waitTask3 = Task.Run(() => target.WaitOne(Timeout.InfiniteTimeSpan, CancellationToken.None)); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); } [Fact] @@ -616,11 +627,11 @@ public void ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetAfterCallingWait target.Set(); - Task.Delay(50).GetAwaiter().GetResult(); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); } [Fact] @@ -633,9 +644,660 @@ public void ReturnsMoreThanOnceWhenEventIsSetTwiceBeforeCallingWaitOne() var waitTask2 = Task.Run(() => target.WaitOne(Timeout.InfiniteTimeSpan, CancellationToken.None)); var waitTask3 = Task.Run(() => target.WaitOne(Timeout.InfiniteTimeSpan, CancellationToken.None)); - Assert.True(waitTask1.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask2.Wait(TimeSpan.FromMilliseconds(50))); - Assert.True(waitTask3.Wait(TimeSpan.FromMilliseconds(50))); + Assert.True(Task.WaitAll(new[] { waitTask1, waitTask2, waitTask3 }, 50)); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); + } + } + + public class WaitOneAsync + { + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsInitiallySet() + { + var target = new AsyncManualResetEvent(true); + + var waitTask1 = target.WaitOneAsync(); + var waitTask2 = target.WaitOneAsync(); + var waitTask3 = target.WaitOneAsync(); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() + { + var target = new AsyncManualResetEvent(false); + target.Set(); + + var waitTask1 = target.WaitOneAsync(); + var waitTask2 = target.WaitOneAsync(); + var waitTask3 = target.WaitOneAsync(); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOne() + { + var target = new AsyncManualResetEvent(false); + + var waitTask1 = target.WaitOneAsync(); + var waitTask2 = target.WaitOneAsync(); + var waitTask3 = target.WaitOneAsync(); + + await Task.Delay(250); + + Assert.False(waitTask1.IsCompleted); + Assert.False(waitTask2.IsCompleted); + Assert.False(waitTask3.IsCompleted); + + target.Set(); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsSetTwiceBeforeCallingWaitOne() + { + var target = new AsyncManualResetEvent(true); + target.Set(); + + var waitTask1 = target.WaitOneAsync(); + var waitTask2 = target.WaitOneAsync(); + var waitTask3 = target.WaitOneAsync(); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + } + } + + public class WaitOneAsync_Int32 + { + [Fact] + public async Task DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() + { + var target = new AsyncManualResetEvent(false); + + var waitTask = target.WaitOneAsync(250); + + await Task.Delay(200); + Assert.False(waitTask.IsCompleted); + + Assert.False(await waitTask.WithTimeout(100)); + } + + [Fact] + public async Task DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() + { + var target = new AsyncManualResetEvent(true); + target.Reset(); + + var waitTask = target.WaitOneAsync(250); + + await Task.Delay(200); + Assert.False(waitTask.IsCompleted); + + Assert.False(await waitTask.WithTimeout(100)); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsInitiallySet() + { + var target = new AsyncManualResetEvent(true); + + var waitTask1 = target.WaitOneAsync(250); + var waitTask2 = target.WaitOneAsync(250); + var waitTask3 = target.WaitOneAsync(250); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() + { + var target = new AsyncManualResetEvent(false); + target.Set(); + + var waitTask1 = target.WaitOneAsync(250); + var waitTask2 = target.WaitOneAsync(250); + var waitTask3 = target.WaitOneAsync(250); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOne() + { + var target = new AsyncManualResetEvent(false); + + var waitTask1 = target.WaitOneAsync(250); + var waitTask2 = target.WaitOneAsync(250); + var waitTask3 = target.WaitOneAsync(250); + + await Task.Delay(200); + Assert.False(waitTask1.IsCompleted); + Assert.False(waitTask2.IsCompleted); + Assert.False(waitTask3.IsCompleted); + + target.Set(); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsSetTwiceBeforeCallingWaitOne() + { + var target = new AsyncManualResetEvent(true); + target.Set(); + + var waitTask1 = target.WaitOneAsync(250); + var waitTask2 = target.WaitOneAsync(250); + var waitTask3 = target.WaitOneAsync(250); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); + } + } + + public class WaitOneAsync_TimeSpan + { + [Fact] + public async Task DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() + { + var target = new AsyncManualResetEvent(false); + + var waitTask = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); + + await Task.Delay(200); + + Assert.False(waitTask.IsCompleted); + + Assert.False(await waitTask.WithTimeout(100)); + } + + [Fact] + public async Task DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() + { + var target = new AsyncManualResetEvent(true); + target.Reset(); + + var waitTask = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); + + await Task.Delay(200); + Assert.False(waitTask.IsCompleted); + + Assert.False(await waitTask.WithTimeout(100)); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsInitiallySet() + { + var target = new AsyncManualResetEvent(true); + + var waitTask1 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); + var waitTask2 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); + var waitTask3 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOneAsync() + { + var target = new AsyncManualResetEvent(false); + target.Set(); + + var waitTask1 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); + var waitTask2 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); + var waitTask3 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOneAsync() + { + var target = new AsyncManualResetEvent(false); + + var waitTask1 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); + var waitTask2 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); + var waitTask3 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); + + await Task.Delay(200); + Assert.False(waitTask1.IsCompleted); + Assert.False(waitTask2.IsCompleted); + Assert.False(waitTask3.IsCompleted); + + target.Set(); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsSetTwiceBeforeCallingWaitOneAsync() + { + var target = new AsyncManualResetEvent(true); + target.Set(); + + var waitTask1 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); + var waitTask2 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); + var waitTask3 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250)); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); + } + } + + public class WaitOneAsync_CancellationToken + { + [Fact] + public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() + { + var target = new AsyncManualResetEvent(false); + + var cancelSource = new CancellationTokenSource(); + var waitTask = target.WaitOneAsync(cancelSource.Token); + + await Task.Delay(200); + Assert.False(waitTask.IsCompleted); + + cancelSource.Cancel(); + + await Assert.ThrowsAsync(() => waitTask.WithTimeout(50)); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsInitiallySet() + { + var target = new AsyncManualResetEvent(true); + + var waitTask1 = target.WaitOneAsync(CancellationToken.None); + var waitTask2 = target.WaitOneAsync(CancellationToken.None); + var waitTask3 = target.WaitOneAsync(CancellationToken.None); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOneAsync() + { + var target = new AsyncManualResetEvent(false); + target.Set(); + + var waitTask1 = target.WaitOneAsync(CancellationToken.None); + var waitTask2 = target.WaitOneAsync(CancellationToken.None); + var waitTask3 = target.WaitOneAsync(CancellationToken.None); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOneAsync() + { + var target = new AsyncManualResetEvent(false); + + var waitTask1 = target.WaitOneAsync(CancellationToken.None); + var waitTask2 = target.WaitOneAsync(CancellationToken.None); + var waitTask3 = target.WaitOneAsync(CancellationToken.None); + + target.Set(); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsSetTwiceBeforeCallingWaitOneAsync() + { + var target = new AsyncManualResetEvent(true); + target.Set(); + + var waitTask1 = target.WaitOneAsync(CancellationToken.None); + var waitTask2 = target.WaitOneAsync(CancellationToken.None); + var waitTask3 = target.WaitOneAsync(CancellationToken.None); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + } + } + + public class WaitOneAsync_Int32_CancellationToken + { + [Fact] + public async Task DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() + { + var target = new AsyncManualResetEvent(false); + + var waitTask = target.WaitOneAsync(250, CancellationToken.None); + + await Task.Delay(200); + + Assert.False(waitTask.IsCompleted); + + Assert.False(await waitTask.WithTimeout(100)); + } + + [Fact] + public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() + { + var target = new AsyncManualResetEvent(false); + + var cancelSource = new CancellationTokenSource(); + var waitTask1 = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); + var waitTask2 = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); + var waitTask3 = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); + + await Task.Delay(200); + + Assert.False(waitTask1.IsCompleted); + Assert.False(waitTask2.IsCompleted); + Assert.False(waitTask3.IsCompleted); + + cancelSource.Cancel(); + + await Assert.ThrowsAsync(() => waitTask1.WithTimeout(50)); + await Assert.ThrowsAsync(() => waitTask2.WithTimeout(50)); + await Assert.ThrowsAsync(() => waitTask3.WithTimeout(50)); + } + + [Fact] + public async Task DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() + { + var target = new AsyncManualResetEvent(true); + target.Reset(); + + var waitTask1 = target.WaitOneAsync(250, CancellationToken.None); + var waitTask2 = target.WaitOneAsync(250, CancellationToken.None); + var waitTask3 = target.WaitOneAsync(250, CancellationToken.None); + + await Task.Delay(200); + + Assert.False(waitTask1.IsCompleted); + Assert.False(waitTask2.IsCompleted); + Assert.False(waitTask3.IsCompleted); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(100); + + Assert.False(waitTask1.Result); + Assert.False(waitTask2.Result); + Assert.False(waitTask3.Result); + } + + [Fact] + public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsInitiallySetThenReset() + { + var target = new AsyncManualResetEvent(true); + target.Reset(); + + var cancelSource = new CancellationTokenSource(); + var waitTask1 = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); + var waitTask2 = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); + var waitTask3 = target.WaitOneAsync(Timeout.Infinite, cancelSource.Token); + + await Task.Delay(200); + + Assert.False(waitTask1.IsCompleted); + Assert.False(waitTask2.IsCompleted); + Assert.False(waitTask3.IsCompleted); + + cancelSource.Cancel(); + + await Assert.ThrowsAsync(() => waitTask1.WithTimeout(50)); + await Assert.ThrowsAsync(() => waitTask2.WithTimeout(50)); + await Assert.ThrowsAsync(() => waitTask3.WithTimeout(50)); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsInitiallySet() + { + var target = new AsyncManualResetEvent(true); + + var waitTask1 = target.WaitOneAsync(Timeout.Infinite, CancellationToken.None); + var waitTask2 = target.WaitOneAsync(Timeout.Infinite, CancellationToken.None); + var waitTask3 = target.WaitOneAsync(Timeout.Infinite, CancellationToken.None); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOne() + { + var target = new AsyncManualResetEvent(false); + target.Set(); + + var waitTask1 = target.WaitOneAsync(Timeout.Infinite, CancellationToken.None); + var waitTask2 = target.WaitOneAsync(Timeout.Infinite, CancellationToken.None); + var waitTask3 = target.WaitOneAsync(Timeout.Infinite, CancellationToken.None); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOneAsync() + { + var target = new AsyncManualResetEvent(false); + + var waitTask1 = target.WaitOneAsync(Timeout.Infinite, CancellationToken.None); + var waitTask2 = target.WaitOneAsync(Timeout.Infinite, CancellationToken.None); + var waitTask3 = target.WaitOneAsync(Timeout.Infinite, CancellationToken.None); + + target.Set(); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsSetTwiceBeforeCallingWaitOnAsynce() + { + var target = new AsyncManualResetEvent(true); + target.Set(); + + var waitTask1 = target.WaitOneAsync(Timeout.Infinite, CancellationToken.None); + var waitTask2 = target.WaitOneAsync(Timeout.Infinite, CancellationToken.None); + var waitTask3 = target.WaitOneAsync(Timeout.Infinite, CancellationToken.None); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); + } + } + + public class WaitOneAsync_TimeSpan_CancellationToken + { + [Fact] + public async Task DoesNotReturnUntilTimeoutElapsesWhenEventIsAlwaysUnset() + { + var target = new AsyncManualResetEvent(false); + + var waitTask = target.WaitOneAsync(TimeSpan.FromMilliseconds(250), CancellationToken.None); + + await Task.Delay(200); + + Assert.False(waitTask.IsCompleted); + + Assert.False(await waitTask.WithTimeout(100)); + } + + [Fact] + public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsAlwaysUnset() + { + var target = new AsyncManualResetEvent(false); + + var cancelSource = new CancellationTokenSource(); + var waitTask1 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); + var waitTask2 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); + var waitTask3 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); + + await Task.Delay(200); + + Assert.False(waitTask1.IsCompleted); + Assert.False(waitTask2.IsCompleted); + Assert.False(waitTask3.IsCompleted); + + cancelSource.Cancel(); + + await Assert.ThrowsAsync(() => waitTask1.WithTimeout(50)); + await Assert.ThrowsAsync(() => waitTask2.WithTimeout(50)); + await Assert.ThrowsAsync(() => waitTask3.WithTimeout(50)); + } + + [Fact] + public async Task DoesNotReturnUntilTimeoutElapsesWhenEventIsInitiallySetThenReset() + { + var target = new AsyncManualResetEvent(true); + target.Reset(); + + var waitTask1 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250), CancellationToken.None); + var waitTask2 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250), CancellationToken.None); + var waitTask3 = target.WaitOneAsync(TimeSpan.FromMilliseconds(250), CancellationToken.None); + + await Task.Delay(200); + + Assert.False(waitTask1.IsCompleted); + Assert.False(waitTask2.IsCompleted); + Assert.False(waitTask3.IsCompleted); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(100); + + Assert.False(waitTask1.Result); + Assert.False(waitTask2.Result); + Assert.False(waitTask3.Result); + } + + [Fact] + public async Task DoesNotReturnUntilCancelTokenIsSetWhenEventIsInitiallySetThenReset() + { + var target = new AsyncManualResetEvent(true); + target.Reset(); + + var cancelSource = new CancellationTokenSource(); + var waitTask1 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); + var waitTask2 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); + var waitTask3 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, cancelSource.Token); + + await Task.Delay(200); + + Assert.False(waitTask1.IsCompleted); + Assert.False(waitTask2.IsCompleted); + Assert.False(waitTask3.IsCompleted); + + cancelSource.Cancel(); + + await Assert.ThrowsAsync(() => waitTask1.WithTimeout(50)); + await Assert.ThrowsAsync(() => waitTask2.WithTimeout(50)); + await Assert.ThrowsAsync(() => waitTask3.WithTimeout(50)); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsInitiallySet() + { + var target = new AsyncManualResetEvent(true); + + var waitTask1 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, CancellationToken.None); + var waitTask2 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, CancellationToken.None); + var waitTask3 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, CancellationToken.None); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetBeforeCallingWaitOneAsync() + { + var target = new AsyncManualResetEvent(false); + target.Set(); + + var waitTask1 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, CancellationToken.None); + var waitTask2 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, CancellationToken.None); + var waitTask3 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, CancellationToken.None); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsNotInitiallySetThenSetAfterCallingWaitOneAsync() + { + var target = new AsyncManualResetEvent(false); + + var waitTask1 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, CancellationToken.None); + var waitTask2 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, CancellationToken.None); + var waitTask3 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, CancellationToken.None); + + target.Set(); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); + } + + [Fact] + public async Task ReturnsMoreThanOnceWhenEventIsSetTwiceBeforeCallingWaitOneAsync() + { + var target = new AsyncManualResetEvent(true); + target.Set(); + + var waitTask1 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, CancellationToken.None); + var waitTask2 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, CancellationToken.None); + var waitTask3 = target.WaitOneAsync(Timeout.InfiniteTimeSpan, CancellationToken.None); + + await Task.WhenAll(waitTask1, waitTask2, waitTask3).WithTimeout(50); + + Assert.True(waitTask1.Result); + Assert.True(waitTask2.Result); + Assert.True(waitTask3.Result); } } } diff --git a/UnitTests/UnitTests.CodeTiger.Core/Threading/AsyncWaitHandleTests.cs b/UnitTests/UnitTests.CodeTiger.Core/Threading/AsyncWaitHandleTests.cs index f43dd1b..25ca15d 100644 --- a/UnitTests/UnitTests.CodeTiger.Core/Threading/AsyncWaitHandleTests.cs +++ b/UnitTests/UnitTests.CodeTiger.Core/Threading/AsyncWaitHandleTests.cs @@ -22,14 +22,103 @@ public void DoesNotCallGetWaitTaskSource() } } + public class WaitOne + { + [Fact] + public void CallsGetWaitTaskSourceWithCorrectCancellationToken() + { + var tcs = new TaskCompletionSource(); + var target = new MockAsyncWaitHandle(tcs); + + tcs.SetResult(false); + + target.WaitOne(); + + Assert.Equal(1, target.WaitTaskRetrievalCount); + Assert.Equal(CancellationToken.None, target.MostRecentCancellationToken); + } + } + + public class WaitOne_Int32 + { + [Fact] + public void CallsGetWaitTaskSourceWithCorrectCancellationToken() + { + var tcs = new TaskCompletionSource(); + var target = new MockAsyncWaitHandle(tcs); + + tcs.SetResult(false); + + target.WaitOne(0); + + Assert.Equal(1, target.WaitTaskRetrievalCount); + Assert.Equal(CancellationToken.None, target.MostRecentCancellationToken); + } + } + + public class WaitOne_TimeSpan + { + [Fact] + public void CallsGetWaitTaskSourceWithCorrectCancellationToken() + { + var tcs = new TaskCompletionSource(); + var target = new MockAsyncWaitHandle(tcs); + + tcs.SetResult(false); + + target.WaitOne(TimeSpan.Zero); + + Assert.Equal(1, target.WaitTaskRetrievalCount); + Assert.Equal(CancellationToken.None, target.MostRecentCancellationToken); + } + } + + public class WaitOne_CancellationToken + { + [Fact] + public void CallsGetWaitTaskSourceWithSameCancellationToken() + { + var tcs = new TaskCompletionSource(); + var target = new MockAsyncWaitHandle(tcs); + + tcs.SetResult(false); + + var cts = new CancellationTokenSource(); + target.WaitOne(cts.Token); + + Assert.Equal(1, target.WaitTaskRetrievalCount); + Assert.Equal(cts.Token, target.MostRecentCancellationToken); + } + } + + public class WaitOne_Int32_CancellationToken + { + [Fact] + public void CallsGetWaitTaskSourceWithSameCancellationToken() + { + var tcs = new TaskCompletionSource(); + var target = new MockAsyncWaitHandle(tcs); + + tcs.SetResult(false); + + var cts = new CancellationTokenSource(); + target.WaitOne(0, cts.Token); + + Assert.Equal(1, target.WaitTaskRetrievalCount); + Assert.Equal(cts.Token, target.MostRecentCancellationToken); + } + } + public class WaitOne_TimeSpan_CancellationToken { [Fact] - public void CallsGetWaitTaskSourceAsyncWithSameCancellationToken() + public void CallsGetWaitTaskSourceWithSameCancellationToken() { var tcs = new TaskCompletionSource(); var target = new MockAsyncWaitHandle(tcs); + tcs.SetResult(false); + var cts = new CancellationTokenSource(); target.WaitOne(TimeSpan.Zero, cts.Token); @@ -38,18 +127,107 @@ public void CallsGetWaitTaskSourceAsyncWithSameCancellationToken() } } + public class WaitOneAsync + { + [Fact] + public async Task CallsGetWaitTaskSourceAsyncWithCorrectCancellationToken() + { + var tcs = new TaskCompletionSource(); + var target = new MockAsyncWaitHandle(tcs); + + tcs.SetResult(false); + + await target.WaitOneAsync(); + + Assert.Equal(1, target.WaitTaskAsyncRetrievalCount); + Assert.Equal(CancellationToken.None, target.MostRecentCancellationToken); + } + } + + public class WaitOneAsync_Int32 + { + [Fact] + public async Task CallsGetWaitTaskSourceAsyncWithCorrectCancellationToken() + { + var tcs = new TaskCompletionSource(); + var target = new MockAsyncWaitHandle(tcs); + + tcs.SetResult(false); + + await target.WaitOneAsync(0); + + Assert.Equal(1, target.WaitTaskAsyncRetrievalCount); + Assert.Equal(CancellationToken.None, target.MostRecentCancellationToken); + } + } + + public class WaitOneAsync_TimeSpan + { + [Fact] + public async Task CallsGetWaitTaskSourceAsyncWithCorrectCancellationToken() + { + var tcs = new TaskCompletionSource(); + var target = new MockAsyncWaitHandle(tcs); + + tcs.SetResult(false); + + await target.WaitOneAsync(TimeSpan.Zero); + + Assert.Equal(1, target.WaitTaskAsyncRetrievalCount); + Assert.Equal(CancellationToken.None, target.MostRecentCancellationToken); + } + } + + public class WaitOneAsync_CancellationToken + { + [Fact] + public async Task CallsGetWaitTaskSourceAsyncWithSameCancellationToken() + { + var tcs = new TaskCompletionSource(); + var target = new MockAsyncWaitHandle(tcs); + + tcs.SetResult(false); + + var cts = new CancellationTokenSource(); + await target.WaitOneAsync(cts.Token); + + Assert.Equal(1, target.WaitTaskAsyncRetrievalCount); + Assert.Equal(cts.Token, target.MostRecentCancellationToken); + } + } + + public class WaitOneAsync_Int32_CancellationToken + { + [Fact] + public async Task CallsGetWaitTaskSourceAsyncWithSameCancellationToken() + { + var tcs = new TaskCompletionSource(); + var target = new MockAsyncWaitHandle(tcs); + + tcs.SetResult(false); + + var cts = new CancellationTokenSource(); + await target.WaitOneAsync(0, cts.Token); + + Assert.Equal(1, target.WaitTaskAsyncRetrievalCount); + Assert.Equal(cts.Token, target.MostRecentCancellationToken); + } + } + public class WaitOneAsync_TimeSpan_CancellationToken { [Fact] - public void CallsGetWaitTaskSourceAsyncWithSameCancellationToken() + public async Task CallsGetWaitTaskSourceAsyncWithSameCancellationToken() { var tcs = new TaskCompletionSource(); var target = new MockAsyncWaitHandle(tcs); + tcs.SetResult(false); + var cts = new CancellationTokenSource(); - target.WaitOneAsync(TimeSpan.Zero, cts.Token).GetAwaiter().GetResult(); + await target.WaitOneAsync(TimeSpan.Zero, cts.Token); - Assert.Equal(1, target.WaitTaskRetrievalCount); + Assert.Equal(1, target.WaitTaskAsyncRetrievalCount); Assert.Equal(cts.Token, target.MostRecentCancellationToken); } } @@ -65,17 +243,28 @@ private class MockAsyncWaitHandle : AsyncWaitHandle public int WaitTaskRetrievalCount { get; private set; } + public int WaitTaskAsyncRetrievalCount { get; private set; } + public MockAsyncWaitHandle(TaskCompletionSource waitTaskCompletionSource) { _waitTaskCompletionSource = waitTaskCompletionSource; } - protected override Task> GetWaitTaskSourceAsync( + protected override TaskCompletionSource GetWaitTaskSource( CancellationToken cancellationToken) { MostRecentCancellationToken = cancellationToken; WaitTaskRetrievalCount++; + return _waitTaskCompletionSource; + } + + protected override Task> GetWaitTaskSourceAsync( + CancellationToken cancellationToken) + { + MostRecentCancellationToken = cancellationToken; + WaitTaskAsyncRetrievalCount++; + return Task.FromResult(_waitTaskCompletionSource); } } diff --git a/UnitTests/UnitTests.CodeTiger.Core/Threading/Tasks/TaskExtensionsUnitTests.cs b/UnitTests/UnitTests.CodeTiger.Core/Threading/Tasks/TaskExtensionsUnitTests.cs index e674d87..0a35e29 100644 --- a/UnitTests/UnitTests.CodeTiger.Core/Threading/Tasks/TaskExtensionsUnitTests.cs +++ b/UnitTests/UnitTests.CodeTiger.Core/Threading/Tasks/TaskExtensionsUnitTests.cs @@ -1,8 +1,10 @@ using System; +using System.Linq; using System.Threading; using System.Threading.Tasks; using CodeTiger.Threading.Tasks; using Xunit; +using TaskExtensions = CodeTiger.Threading.Tasks.TaskExtensions; namespace UnitTests.CodeTiger.Threading.Tasks { @@ -16,7 +18,7 @@ public class TaskExtensionsUnitTests public class WithTimeout_Int32 { [Fact] - public void ReturnsSameTaskWhenTimeoutIsInfinite() + public void ReturnsOriginalTaskWhenTimeoutIsInfinite() { var taskWithTimeout = _completedTask.WithTimeout(Timeout.Infinite); @@ -24,7 +26,7 @@ public void ReturnsSameTaskWhenTimeoutIsInfinite() } [Fact] - public void ReturnsSameTaskWhenTimeoutIsZeroAndTaskIsSynchronous() + public void ReturnsOriginalTaskWhenTimeoutIsZeroAndOriginalTaskIsSynchronous() { var taskWithTimeout = _completedTask.WithTimeout(0); @@ -32,57 +34,50 @@ public void ReturnsSameTaskWhenTimeoutIsZeroAndTaskIsSynchronous() } [Fact] - public async Task ReturnsDifferentTaskWhenTimeoutIsZeroAndTaskIsAsynchronous() + public void ReturnsDifferentTaskWhenTimeoutIsZeroAndOriginalTaskIsAsynchronous() { - var task = Task.Delay(250); + var task = Task.Delay(50); var taskWithTimeout = task.WithTimeout(0); Assert.NotSame(task, taskWithTimeout); - - await Assert.ThrowsAsync(async () => await taskWithTimeout.ConfigureAwait(false)) - .ConfigureAwait(false); - await task.ConfigureAwait(false); } [Fact] - public async Task ThrowsTimeoutExceptionWhenTimeoutIsLessThanTaskCompletionTime() + public async Task ReturnsTaskWhichThrowsTimeoutExceptionWhenTimeoutIsLessThanOriginalTaskDuration() { - var task = Task.Delay(250); - var taskWithTimeout = task.WithTimeout(200); + var task = Task.Delay(200); + var taskWithTimeout = task.WithTimeout(100); - Assert.NotSame(task, taskWithTimeout); - - await Assert.ThrowsAsync(async () => await taskWithTimeout) - .ConfigureAwait(false); - await task.ConfigureAwait(false); + await Assert.ThrowsAsync(() => taskWithTimeout); } [Fact] - public async Task DoesNotThrowExceptionWhenTimeoutIsGreaterThanTaskCompletionTime() + public void ReturnsTaskWhichCompletesNormallyWhenTimeoutIsGreaterThanTaskCompletionTime() { - var task = Task.Delay(250); - var taskWithTimeout = task.WithTimeout(500); + var task = Task.Delay(100); + var taskWithTimeout = task.WithTimeout(200); - await taskWithTimeout.ConfigureAwait(false); + Assert.True(taskWithTimeout.Wait(150)); } [Fact] - public async Task ThrowsTaskCanceledExceptionWhenOriginalTaskIsCanceled() + public void ReturnsTaskWhichThrowsTaskCanceledExceptionWhenOriginalTaskIsCanceled() { var taskSource = new TaskCompletionSource(); var taskWithTimeout = taskSource.Task.WithTimeout(500); taskSource.SetCanceled(); - await Assert.ThrowsAsync(async () => await taskWithTimeout) - .ConfigureAwait(false); + var aggregateException = Assert.Throws(() => taskWithTimeout.Wait(50)); + Assert.Equal(typeof(TaskCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } } public class WithTimeout_TimeSpan { [Fact] - public void ReturnsSameTaskWhenTimeoutIsInfiniteTimeSpan() + public void ReturnsOriginalTaskWhenTimeoutIsInfiniteTimeSpan() { var taskWithTimeout = _completedTask.WithTimeout(Timeout.InfiniteTimeSpan); @@ -90,7 +85,7 @@ public void ReturnsSameTaskWhenTimeoutIsInfiniteTimeSpan() } [Fact] - public void ReturnsSameTaskWhenTimeoutIsZeroAndTaskIsSynchronous() + public void ReturnsOriginalTaskWhenTimeoutIsZeroAndOriginalTaskIsSynchronous() { var taskWithTimeout = _completedTask.WithTimeout(TimeSpan.Zero); @@ -98,50 +93,151 @@ public void ReturnsSameTaskWhenTimeoutIsZeroAndTaskIsSynchronous() } [Fact] - public async Task ReturnsDifferentTaskWhenTimeoutIsZeroAndTaskIsAsynchronous() + public void ReturnsDifferentTaskWhenTimeoutIsZeroAndOriginalTaskIsAsynchronous() { - var task = Task.Delay(500); + var task = Task.Delay(50); var taskWithTimeout = task.WithTimeout(TimeSpan.Zero); Assert.NotSame(task, taskWithTimeout); + } - Task.Delay(50).Wait(); + [Fact] + public async Task ReturnsTaskWhichThrowsTimeoutExceptionWhenTimeoutIsLessThanOriginalTaskDuration() + { + var task = Task.Delay(200); + var taskWithTimeout = task.WithTimeout(TimeSpan.FromMilliseconds(100)); - await Assert.ThrowsAsync(async () => await taskWithTimeout) - .ConfigureAwait(false); + await Assert.ThrowsAsync(() => taskWithTimeout); } [Fact] - public async Task ThrowsTimeoutExceptionWhenTimeoutIsLessThanTaskCompletionTime() + public void ReturnsTaskWhichCompletesNormallyWhenTimeoutIsGreaterThanTaskCompletionTime() { - var task = Task.Delay(500); + var task = Task.Delay(100); var taskWithTimeout = task.WithTimeout(TimeSpan.FromMilliseconds(200)); - Assert.NotSame(task, taskWithTimeout); - await Assert.ThrowsAsync(async () => await taskWithTimeout.ConfigureAwait(false)) - .ConfigureAwait(false); + Assert.True(taskWithTimeout.Wait(150)); + } + + [Fact] + public void ReturnsTaskWhichThrowsTaskCanceledExceptionWhenOriginalTaskIsCanceled() + { + var taskSource = new TaskCompletionSource(); + var taskWithTimeout = taskSource.Task.WithTimeout(TimeSpan.FromMilliseconds(500)); + + taskSource.SetCanceled(); + + var aggregateException = Assert.Throws(() => taskWithTimeout.Wait(50)); + Assert.Equal(typeof(TaskCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } + } + public class Wait_TimeSpan_CancellationToken + { [Fact] - public async Task DoesNotThrowExceptionWhenTimeoutIsGreaterThanTaskCompletionTime() + public void ThrowsArgumentNullExceptionWhenTaskIsNull() { + Task task = null; + + Assert.Throws( + () => TaskExtensions.Wait(task, Timeout.InfiniteTimeSpan, CancellationToken.None)); + } + + [Fact] + public void ReturnsImmediatelyWhenTaskIsCompleted() + { + var task = Task.FromResult(true); + + var target = Task.Run( + () => TaskExtensions.Wait(task, Timeout.InfiniteTimeSpan, CancellationToken.None)); + + Task.Delay(1).Wait(); + + Assert.True(target.IsCompleted); + Assert.True(target.Result); + } + + [Fact] + public void ReturnsWhenTaskCompletesWhenTaskCompletesBeforeTimeout() + { + var task = Task.Delay(50); + + var target = Task.Run( + () => TaskExtensions.Wait(task, TimeSpan.FromMilliseconds(100), CancellationToken.None)); + + Task.Delay(80).Wait(); + + Assert.True(target.IsCompleted); + Assert.True(target.Result); + } + + [Fact] + public void ThrowsOperationCanceledExceptionImmediatelyWhenCancellationTokenIsInitiallySet() + { + var cancellationTokenSource = new CancellationTokenSource(); + var task = Task.Delay(250); - var taskWithTimeout = task.WithTimeout(TimeSpan.FromMilliseconds(500)); - Assert.NotSame(task, taskWithTimeout); - await taskWithTimeout.ConfigureAwait(false); + var target = Task.Run( + () => TaskExtensions.Wait(task, Timeout.InfiniteTimeSpan, cancellationTokenSource.Token)); + + Task.Delay(150).Wait(); + + Assert.False(target.IsCompleted); + + cancellationTokenSource.Cancel(); + + Task.Delay(1).Wait(); + + Assert.True(target.IsCompleted); + var aggregateException = Assert.Throws(() => target.Wait()); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); } [Fact] - public async Task ThrowsTaskCanceledExceptionWhenOriginalTaskIsCanceled() + public void ThrowsOperationCanceledExceptionWhenCancellationTokenIsSet() { - var taskSource = new TaskCompletionSource(); - var taskWithTimeout = taskSource.Task.WithTimeout(TimeSpan.FromMilliseconds(500)); + var task = Task.Delay(50); - taskSource.SetCanceled(); + var target = Task.Run( + () => TaskExtensions.Wait(task, Timeout.InfiniteTimeSpan, new CancellationToken(true))); + + Task.Delay(1).Wait(); + + Assert.True(target.IsCompleted); + var aggregateException = Assert.Throws(() => target.Wait()); + Assert.Equal(typeof(OperationCanceledException), + aggregateException.Flatten().InnerExceptions.Single().GetType()); + } + + [Fact] + public void ReturnsFalseImmediatelyWhenTimeoutIsZero() + { + var task = Task.Delay(50); + + var target = Task.Run( + () => TaskExtensions.Wait(task, TimeSpan.Zero, CancellationToken.None)); + + Task.Delay(1).Wait(); + + Assert.True(target.IsCompleted); + Assert.False(target.Result); + } + + [Fact] + public void ReturnsFalseWhenTimeoutExpires() + { + var task = Task.Delay(50); + + var target = Task.Run( + () => TaskExtensions.Wait(task, TimeSpan.FromMilliseconds(30), CancellationToken.None)); + + Task.Delay(40).Wait(); - await Assert.ThrowsAsync(async () => await taskWithTimeout) - .ConfigureAwait(false); + Assert.True(target.IsCompleted); + Assert.False(target.Result); } } } diff --git a/UnitTests/UnitTests.CodeTiger.Core/UnitTests.CodeTiger.Core.csproj b/UnitTests/UnitTests.CodeTiger.Core/UnitTests.CodeTiger.Core.csproj index 431ecc7..8172e7b 100644 --- a/UnitTests/UnitTests.CodeTiger.Core/UnitTests.CodeTiger.Core.csproj +++ b/UnitTests/UnitTests.CodeTiger.Core/UnitTests.CodeTiger.Core.csproj @@ -1,7 +1,6 @@  - - + Debug AnyCPU @@ -17,7 +16,8 @@ 512 {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 723ba4cb + + true @@ -79,24 +79,29 @@ ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - - False - ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + + ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + True - - False - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + True + + + ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + True - + + Designer + - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - + \ No newline at end of file diff --git a/UnitTests/UnitTests.CodeTiger.Core/packages.config b/UnitTests/UnitTests.CodeTiger.Core/packages.config index 6f1fb7f..dcbf45e 100644 --- a/UnitTests/UnitTests.CodeTiger.Core/packages.config +++ b/UnitTests/UnitTests.CodeTiger.Core/packages.config @@ -1,9 +1,10 @@  - + - - - - + + + + + \ No newline at end of file