Skip to content

Commit

Permalink
Fixed disposable extensions bugs and added relevant tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
TheSquidCombatant committed Mar 2, 2024
1 parent a349a54 commit c1a0001
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 4 deletions.
1 change: 1 addition & 0 deletions CodeJam.Main.Tests/CodeJam.Main.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<TargetFrameworks Condition=" '$(NetFrameworkTests)' == 'true' ">net48;net472;net471;net47;net461;net45;net40;net35</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
<LangVersion>12.0</LangVersion>
</PropertyGroup>

<!-- #region Targeting -->
Expand Down
79 changes: 79 additions & 0 deletions CodeJam.Main.Tests/DisposableExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

using NUnit.Framework;

namespace CodeJam;

[TestFixture(Category = "Disposable")]
[SuppressMessage("ReSharper", "HeapView.CanAvoidClosure")]
public static class DisposableExtensionsTests
{
[Test]
public static void DisposeAllMustReleaseAllObjects()
{
const int expectedDisposeCount = 10;

int actualDisposeCount = 0;

var objectsForDispose = Enumerable
.Range(0, expectedDisposeCount)
.Select(x => Disposable.Create(() => ++actualDisposeCount));

objectsForDispose.DisposeAll();

Assert.AreEqual(expectedDisposeCount, actualDisposeCount);
}

[Test]
public static void DisposeAllMustCollectAllExceptions()
{
const int expectedExceptionCount = 7;

var objectsWithException = Enumerable
.Range(0, expectedExceptionCount)
.Select(x => Disposable.Create(() => throw new Exception()));

const int expectedSuccessCount = 3;

var objectsWithoutException = Enumerable
.Range(0, expectedSuccessCount)
.Select(x => Disposable.Create(() => { }));

var objectsForDispose = objectsWithException.Concat(objectsWithoutException).ToArray();

int actualExceptionCount = -1;

try
{
objectsForDispose.DisposeAll();
}
catch (AggregateException ex)
{
actualExceptionCount = ex.InnerExceptions.Count;
}

Assert.AreEqual(expectedExceptionCount, actualExceptionCount);
}

#if NETSTANDARD21_OR_GREATER || NETCOREAPP30_OR_GREATER
[Test]
public static void DisposeAsyncMustNotBlockThread()
{
var disposeDuration = new TimeSpan(0, 0, 1);

var longDisposableObject = Disposable.Create(() => Thread.Sleep(disposeDuration));

var startTime = DateTime.Now;

var task = longDisposableObject.DisposeAsync();

var callDuration = DateTime.Now - startTime;

Assert.Less(callDuration, disposeDuration);
}
#endif
}
7 changes: 3 additions & 4 deletions CodeJam.Main/DisposableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ public static void DisposeAll([InstantHandle] this IEnumerable<IDisposable> disp
}
catch (Exception ex)
{
exceptions = new List<Exception> { ex };
if (exceptions != null) exceptions.Add(ex);
else exceptions = new List<Exception> { ex };
}
}

Expand Down Expand Up @@ -71,9 +72,7 @@ public static ValueTask DisposeAsync(this IDisposable disposable)
Code.NotNull(disposable, nameof(disposable));
if (disposable is IAsyncDisposable asyncDisposable)
return asyncDisposable.DisposeAsync();

disposable.Dispose();
return new ValueTask();
return new ValueTask(Task.Run(() => disposable.Dispose()));
}
#endif
}
Expand Down

0 comments on commit c1a0001

Please sign in to comment.