using System; using System.Threading; using System.Threading.Tasks; using Shouldly; using Xunit; using ZB.MOM.WW.GRAccess.Cli.Session; namespace ZB.MOM.WW.GRAccess.Cli.Tests.Session { public class StaComThreadTests : IDisposable { private readonly StaComThread _sut; public StaComThreadTests() { _sut = new StaComThread(); _sut.Start(); } public void Dispose() { _sut.Dispose(); } [Fact] public async Task RunAsync_ExecutesOnStaThread() { var apartmentState = await _sut.RunAsync(() => Thread.CurrentThread.GetApartmentState()); apartmentState.ShouldBe(ApartmentState.STA); } [Fact] public async Task RunAsync_ReturnsResult() { var result = await _sut.RunAsync(() => 42); result.ShouldBe(42); } [Fact] public async Task RunAsync_PropagatesException() { var ex = await Should.ThrowAsync( _sut.RunAsync(() => throw new InvalidOperationException("test error"))); ex.Message.ShouldBe("test error"); } [Fact] public async Task RunAsync_VoidAction_Completes() { var executed = false; await _sut.RunAsync(() => { executed = true; }); executed.ShouldBeTrue(); } [Fact] public async Task RunAsync_VoidAction_PropagatesException() { var ex = await Should.ThrowAsync( _sut.RunAsync(() => throw new InvalidOperationException("void error"))); ex.Message.ShouldBe("void error"); } [Fact] public async Task RunAsync_MultipleWorkItems_ExecuteInOrder() { var results = new int[3]; await _sut.RunAsync(() => { results[0] = 1; }); await _sut.RunAsync(() => { results[1] = 2; }); await _sut.RunAsync(() => { results[2] = 3; }); results.ShouldBe(new[] { 1, 2, 3 }); } [Fact] public async Task RunAsync_AllWorkRunsOnSameThread() { var threadId1 = await _sut.RunAsync(() => Thread.CurrentThread.ManagedThreadId); var threadId2 = await _sut.RunAsync(() => Thread.CurrentThread.ManagedThreadId); threadId1.ShouldBe(threadId2); } [Fact] public void Dispose_CanBeCalledMultipleTimes() { var thread = new StaComThread(); thread.Start(); thread.Dispose(); Should.NotThrow(() => thread.Dispose()); } [Fact] public void RunAsync_AfterDispose_ThrowsObjectDisposed() { var thread = new StaComThread(); thread.Start(); thread.Dispose(); Should.Throw(() => thread.RunAsync(() => { })); } } }