feat(lmxproxy): phase 2 — host core (MxAccessClient, SessionManager, SubscriptionManager)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.LmxProxy.Host.MxAccess;
|
||||
|
||||
namespace ZB.MOM.WW.LmxProxy.Host.Tests.MxAccess
|
||||
{
|
||||
public class StaDispatchThreadTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task DispatchAsync_ExecutesOnStaThread()
|
||||
{
|
||||
using var sta = new StaDispatchThread("Test-STA");
|
||||
var threadId = await sta.DispatchAsync(() => Thread.CurrentThread.ManagedThreadId);
|
||||
threadId.Should().NotBe(Thread.CurrentThread.ManagedThreadId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DispatchAsync_ReturnsResult()
|
||||
{
|
||||
using var sta = new StaDispatchThread("Test-STA");
|
||||
var result = await sta.DispatchAsync(() => 42);
|
||||
result.Should().Be(42);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DispatchAsync_PropagatesException()
|
||||
{
|
||||
using var sta = new StaDispatchThread("Test-STA");
|
||||
Func<Task> act = () => sta.DispatchAsync<int>(() => throw new InvalidOperationException("test error"));
|
||||
await act.Should().ThrowAsync<InvalidOperationException>().WithMessage("test error");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DispatchAsync_Action_Completes()
|
||||
{
|
||||
using var sta = new StaDispatchThread("Test-STA");
|
||||
int value = 0;
|
||||
await sta.DispatchAsync(() => { value = 99; });
|
||||
value.Should().Be(99);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Dispose_CompletesGracefully()
|
||||
{
|
||||
var sta = new StaDispatchThread("Test-STA");
|
||||
sta.Dispose(); // Should not throw
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DispatchAfterDispose_ThrowsObjectDisposedException()
|
||||
{
|
||||
var sta = new StaDispatchThread("Test-STA");
|
||||
sta.Dispose();
|
||||
Func<Task> act = () => sta.DispatchAsync(() => 42);
|
||||
act.Should().ThrowAsync<ObjectDisposedException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MultipleDispatches_ExecuteInOrder()
|
||||
{
|
||||
using var sta = new StaDispatchThread("Test-STA");
|
||||
var results = new System.Collections.Concurrent.ConcurrentBag<int>();
|
||||
|
||||
var tasks = new Task[10];
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
int idx = i;
|
||||
tasks[i] = sta.DispatchAsync(() => { results.Add(idx); });
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
results.Count.Should().Be(10);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StaThread_HasStaApartmentState()
|
||||
{
|
||||
using var sta = new StaDispatchThread("Test-STA");
|
||||
var apartmentState = await sta.DispatchAsync(() => Thread.CurrentThread.GetApartmentState());
|
||||
apartmentState.Should().Be(ApartmentState.STA);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.LmxProxy.Host.Domain;
|
||||
|
||||
namespace ZB.MOM.WW.LmxProxy.Host.Tests.MxAccess
|
||||
{
|
||||
public class TypedValueEqualsTests
|
||||
{
|
||||
[Fact]
|
||||
public void NullEqualsNull() => TypedValueComparer.Equals(null, null).Should().BeTrue();
|
||||
|
||||
[Fact]
|
||||
public void NullNotEqualsValue() => TypedValueComparer.Equals(null, 42).Should().BeFalse();
|
||||
|
||||
[Fact]
|
||||
public void ValueNotEqualsNull() => TypedValueComparer.Equals(42, null).Should().BeFalse();
|
||||
|
||||
[Fact]
|
||||
public void SameTypeAndValue() => TypedValueComparer.Equals(42.5, 42.5).Should().BeTrue();
|
||||
|
||||
[Fact]
|
||||
public void SameTypeDifferentValue() => TypedValueComparer.Equals(42.5, 43.0).Should().BeFalse();
|
||||
|
||||
[Fact]
|
||||
public void DifferentTypes_NeverEqual() => TypedValueComparer.Equals(1, 1.0).Should().BeFalse();
|
||||
|
||||
[Fact]
|
||||
public void BoolTrue() => TypedValueComparer.Equals(true, true).Should().BeTrue();
|
||||
|
||||
[Fact]
|
||||
public void BoolFalse() => TypedValueComparer.Equals(false, true).Should().BeFalse();
|
||||
|
||||
[Fact]
|
||||
public void String_CaseSensitive()
|
||||
{
|
||||
TypedValueComparer.Equals("DONE", "DONE").Should().BeTrue();
|
||||
TypedValueComparer.Equals("done", "DONE").Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Array_SameElements()
|
||||
{
|
||||
TypedValueComparer.Equals(new[] { 1, 2, 3 }, new[] { 1, 2, 3 }).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Array_DifferentElements()
|
||||
{
|
||||
TypedValueComparer.Equals(new[] { 1, 2, 3 }, new[] { 1, 2, 4 }).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Array_DifferentLengths()
|
||||
{
|
||||
TypedValueComparer.Equals(new[] { 1, 2 }, new[] { 1, 2, 3 }).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Int32_NotEqual_ToDouble()
|
||||
{
|
||||
TypedValueComparer.Equals(1, 1.0).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Long_Equality()
|
||||
{
|
||||
TypedValueComparer.Equals(long.MaxValue, long.MaxValue).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DateTime_TickPrecision()
|
||||
{
|
||||
var dt1 = new System.DateTime(638789000000000000, System.DateTimeKind.Utc);
|
||||
var dt2 = new System.DateTime(638789000000000000, System.DateTimeKind.Utc);
|
||||
TypedValueComparer.Equals(dt1, dt2).Should().BeTrue();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user