Files
lmxopcua/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/FixtureCleanupTests.cs
T

93 lines
3.3 KiB
C#

using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Tests;
namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests;
[Trait("Category", "Unit")]
public sealed class FixtureCleanupTests
{
[Fact]
public async Task Successful_body_runs_one_awaited_cleanup()
{
var calls = 0;
var release = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
var run = FixtureCleanup.RunAsync(() => Task.CompletedTask, async () =>
{
calls++;
await release.Task;
}, _ => throw new Exception("unexpected report"));
run.IsCompleted.ShouldBeFalse();
release.SetResult();
await run;
calls.ShouldBe(1);
}
[Fact]
public async Task Body_fault_remains_same_exception_and_original_throwing_stack()
{
var primary = new InvalidOperationException("body");
var cleanupCalls = 0;
var actual = await Should.ThrowAsync<InvalidOperationException>(() => FixtureCleanup.RunAsync(
() => ThrowFromBody(primary),
() => { cleanupCalls++; return Task.CompletedTask; },
_ => throw new Exception("unexpected report")));
actual.ShouldBeSameAs(primary);
actual.StackTrace.ShouldNotBeNull().ShouldContain(nameof(ThrowFromBody));
cleanupCalls.ShouldBe(1);
}
[Fact]
public async Task Cleanup_only_fault_is_thrown_exactly()
{
var cleanup = new ApplicationException("cleanup");
var actual = await Should.ThrowAsync<ApplicationException>(() => FixtureCleanup.RunAsync(
() => Task.CompletedTask,
() => Task.FromException(cleanup),
_ => throw new Exception("unexpected report")));
actual.ShouldBeSameAs(cleanup);
}
[Fact]
public async Task Both_faults_preserve_primary_and_record_secondary_once()
{
var primary = new InvalidOperationException("body");
var cleanup = new ApplicationException("cleanup");
var reported = new List<Exception>();
var actual = await Should.ThrowAsync<InvalidOperationException>(() => FixtureCleanup.RunAsync(
() => ThrowFromBody(primary),
() => Task.FromException(cleanup),
reported.Add));
actual.ShouldBeSameAs(primary);
actual.StackTrace.ShouldNotBeNull().ShouldContain(nameof(ThrowFromBody));
actual.Data[FixtureCleanup.SecondaryExceptionKey].ShouldBeSameAs(cleanup);
reported.Count.ShouldBe(1);
reported[0].ShouldBeSameAs(cleanup);
}
[Fact]
public async Task Reporting_fault_does_not_replace_primary()
{
var primary = new InvalidOperationException("body");
var cleanup = new ApplicationException("cleanup");
var reportCalls = 0;
var actual = await Should.ThrowAsync<InvalidOperationException>(() => FixtureCleanup.RunAsync(
() => ThrowFromBody(primary),
() => Task.FromException(cleanup),
_ => { reportCalls++; throw new Exception("report"); }));
actual.ShouldBeSameAs(primary);
actual.Data[FixtureCleanup.SecondaryExceptionKey].ShouldBeSameAs(cleanup);
reportCalls.ShouldBe(1);
}
private static async Task ThrowFromBody(Exception failure)
{
await Task.Yield();
throw failure;
}
}