1
0
mirror of https://github.com/chylex/.NET-Community-Toolkit.git synced 2025-04-13 20:15:45 +02:00

Adds Unit Tests and reverts IDisposable pattern

This commit is contained in:
Pedro Lamas 2021-02-19 15:33:29 +00:00
parent 639d411272
commit 818633db90
4 changed files with 146 additions and 62 deletions
Microsoft.Toolkit/Deferred
UnitTests/UnitTests.Shared

View File

@ -4,14 +4,15 @@
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
#pragma warning disable CA1001
namespace Microsoft.Toolkit.Deferred
{
/// <summary>
/// <see cref="EventArgs"/> which can retrieve a <see cref="EventDeferral"/> in order to process data asynchronously before an <see cref="EventHandler"/> completes and returns to the calling control.
/// </summary>
public class DeferredEventArgs : EventArgs, IDisposable
public class DeferredEventArgs : EventArgs
{
/// <summary>
/// Gets a new <see cref="DeferredEventArgs"/> to use in cases where no <see cref="EventArgs"/> wish to be provided.
@ -21,12 +22,6 @@ public class DeferredEventArgs : EventArgs, IDisposable
private readonly object _eventDeferralLock = new object();
private EventDeferral? _eventDeferral;
private bool _disposed;
/// <summary>
/// Finalizes an instance of the <see cref="DeferredEventArgs"/> class.
/// </summary>
~DeferredEventArgs() => Dispose(false);
/// <summary>
/// Returns an <see cref="EventDeferral"/> which can be completed when deferred event is ready to continue.
@ -36,7 +31,7 @@ public EventDeferral GetDeferral()
{
lock (_eventDeferralLock)
{
return _eventDeferral ?? (_eventDeferral = new EventDeferral());
return _eventDeferral ??= new EventDeferral();
}
}
@ -61,31 +56,5 @@ public EventDeferral GetDeferral()
return eventDeferral;
}
}
/// <summary>
/// Recommended helper method pattern for <see cref="IDisposable"/>.
/// </summary>
/// <param name="disposing">Source of dispose request.</param>
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
_eventDeferral?.Dispose();
_disposed = true;
}
/// <inheritdoc/>
public void Dispose()
{
// Dispose of unmanaged resources.
Dispose(true);
// Suppress finalization.
GC.SuppressFinalize(this);
}
}
}

View File

@ -7,6 +7,8 @@
using System.Threading;
using System.Threading.Tasks;
#pragma warning disable CA1063
namespace Microsoft.Toolkit.Deferred
{
/// <summary>
@ -16,17 +18,11 @@ public class EventDeferral : IDisposable
{
//// TODO: If/when .NET 5 is base, we can upgrade to non-generic version
private readonly TaskCompletionSource<object?> _taskCompletionSource = new TaskCompletionSource<object?>();
private bool _disposed = false;
internal EventDeferral()
{
}
/// <summary>
/// Finalizes an instance of the <see cref="EventDeferral"/> class.
/// </summary>
~EventDeferral() => Dispose(false);
/// <summary>
/// Call when finished with the Deferral.
/// </summary>
@ -50,30 +46,10 @@ public async Task WaitForCompletion(CancellationToken cancellationToken)
}
}
/// <summary>
/// Recommended helper method pattern for <see cref="IDisposable"/>.
/// </summary>
/// <param name="disposing">Source of dispose request.</param>
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
Complete();
_disposed = true;
}
/// <inheritdoc/>
public void Dispose()
{
// Dispose of unmanaged resources.
Dispose(true);
// Suppress finalization.
GC.SuppressFinalize(this);
Complete();
}
}
}

View File

@ -0,0 +1,138 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Threading.Tasks;
using Microsoft.Toolkit.Deferred;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTests.Extensions
{
[TestClass]
public class Test_EventHandlerExtensions
{
[TestCategory("Deferred")]
[TestMethod]
public void Test_EventHandlerExtensions_GettingDeferralCausesAwait()
{
var tsc = new TaskCompletionSource<bool>();
var testClass = new TestClass();
testClass.TestEvent += async (s, e) =>
{
var deferral = e.GetDeferral();
await tsc.Task;
deferral.Complete();
};
var handlersTask = testClass.RaiseTestEvent();
Assert.IsFalse(handlersTask.IsCompleted);
tsc.SetResult(true);
Assert.IsTrue(handlersTask.IsCompleted);
}
[TestCategory("Deferred")]
[TestMethod]
public void Test_EventHandlerExtensions_NotGettingDeferralCausesNoAwait()
{
var tsc = new TaskCompletionSource<bool>();
var testClass = new TestClass();
testClass.TestEvent += async (s, e) =>
{
await tsc.Task;
};
var handlersTask = testClass.RaiseTestEvent();
Assert.IsTrue(handlersTask.IsCompleted);
tsc.SetResult(true);
}
[TestCategory("Deferred")]
[TestMethod]
public void Test_EventHandlerExtensions_UsingDeferralCausesAwait()
{
var tsc = new TaskCompletionSource<bool>();
var testClass = new TestClass();
testClass.TestEvent += async (s, e) =>
{
using (e.GetDeferral())
{
await tsc.Task;
}
};
var handlersTask = testClass.RaiseTestEvent();
Assert.IsFalse(handlersTask.IsCompleted);
tsc.SetResult(true);
Assert.IsTrue(handlersTask.IsCompleted);
}
[TestCategory("Deferred")]
[DataTestMethod]
[DataRow(0, 1)]
[DataRow(1, 0)]
public void Test_EventHandlerExtensions_MultipleHandlersCauseAwait(int firstToReleaseDeferral, int lastToReleaseDeferral)
{
var tsc = new[]
{
new TaskCompletionSource<bool>(),
new TaskCompletionSource<bool>()
};
var testClass = new TestClass();
testClass.TestEvent += async (s, e) =>
{
var deferral = e.GetDeferral();
await tsc[0].Task;
deferral.Complete();
};
testClass.TestEvent += async (s, e) =>
{
var deferral = e.GetDeferral();
await tsc[1].Task;
deferral.Complete();
};
var handlersTask = testClass.RaiseTestEvent();
Assert.IsFalse(handlersTask.IsCompleted);
tsc[firstToReleaseDeferral].SetResult(true);
Assert.IsFalse(handlersTask.IsCompleted);
tsc[lastToReleaseDeferral].SetResult(true);
Assert.IsTrue(handlersTask.IsCompleted);
}
private class TestClass
{
public event EventHandler<DeferredEventArgs> TestEvent;
public Task RaiseTestEvent() => TestEvent.InvokeAsync(this, new DeferredEventArgs());
}
}
}

View File

@ -19,6 +19,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\Test_Guard.Array.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\Test_Guard.Comparable.Numeric.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\Test_Guard.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\Test_EventHandlerExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\Test_TaskExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\Test_ArrayExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\Test_TypeExtensions.cs" />