Files
scadalink-design/lmxproxy/tests/ZB.MOM.WW.LmxProxy.Client.Tests/LmxProxyClientReadWriteTests.cs
2026-03-22 00:22:29 -04:00

178 lines
5.7 KiB
C#

using FluentAssertions;
using Xunit;
using ZB.MOM.WW.LmxProxy.Client.Domain;
using ZB.MOM.WW.LmxProxy.Client.Tests.Fakes;
namespace ZB.MOM.WW.LmxProxy.Client.Tests;
public class LmxProxyClientReadWriteTests
{
[Fact]
public async Task ReadAsync_ReturnsVtqFromResponse()
{
var (client, fake) = TestableClient.CreateConnected();
fake.ReadResponseToReturn = new ReadResponse
{
Success = true,
Vtq = new VtqMessage
{
Tag = "TestTag",
Value = new TypedValue { DoubleValue = 42.5 },
TimestampUtcTicks = new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks,
Quality = new QualityCode { StatusCode = 0x00000000 }
}
};
var result = await client.ReadAsync("TestTag");
result.Value.Should().Be(42.5);
result.Quality.Should().Be(Quality.Good);
fake.ReadCalls.Should().HaveCount(1);
fake.ReadCalls[0].Tag.Should().Be("TestTag");
fake.ReadCalls[0].SessionId.Should().Be("test-session-123");
client.Dispose();
}
[Fact]
public async Task ReadAsync_ThrowsOnFailureResponse()
{
var (client, fake) = TestableClient.CreateConnected();
fake.ReadResponseToReturn = new ReadResponse { Success = false, Message = "Tag not found" };
var act = () => client.ReadAsync("BadTag");
await act.Should().ThrowAsync<InvalidOperationException>()
.WithMessage("*Tag not found*");
client.Dispose();
}
[Fact]
public async Task ReadAsync_ThrowsWhenNotConnected()
{
var client = new LmxProxyClient("localhost", 50051, null, null);
var act = () => client.ReadAsync("AnyTag");
await act.Should().ThrowAsync<InvalidOperationException>()
.WithMessage("*not connected*");
client.Dispose();
}
[Fact]
public async Task ReadBatchAsync_ReturnsDictionaryOfVtqs()
{
var (client, fake) = TestableClient.CreateConnected();
fake.ReadBatchResponseToReturn = new ReadBatchResponse
{
Success = true,
Vtqs =
[
new VtqMessage
{
Tag = "Tag1",
Value = new TypedValue { Int32Value = 100 },
TimestampUtcTicks = DateTime.UtcNow.Ticks,
Quality = new QualityCode { StatusCode = 0x00000000 }
},
new VtqMessage
{
Tag = "Tag2",
Value = new TypedValue { BoolValue = true },
TimestampUtcTicks = DateTime.UtcNow.Ticks,
Quality = new QualityCode { StatusCode = 0x00000000 }
}
]
};
var result = await client.ReadBatchAsync(["Tag1", "Tag2"]);
result.Should().HaveCount(2);
result["Tag1"].Value.Should().Be(100);
result["Tag2"].Value.Should().Be(true);
client.Dispose();
}
[Fact]
public async Task WriteAsync_SendsTypedValueDirectly()
{
var (client, fake) = TestableClient.CreateConnected();
var typedValue = new TypedValue { DoubleValue = 99.9 };
await client.WriteAsync("TestTag", typedValue);
fake.WriteCalls.Should().HaveCount(1);
fake.WriteCalls[0].Tag.Should().Be("TestTag");
fake.WriteCalls[0].Value.Should().NotBeNull();
fake.WriteCalls[0].Value!.DoubleValue.Should().Be(99.9);
client.Dispose();
}
[Fact]
public async Task WriteAsync_ThrowsOnFailureResponse()
{
var (client, fake) = TestableClient.CreateConnected();
fake.WriteResponseToReturn = new WriteResponse { Success = false, Message = "Write error" };
var act = () => client.WriteAsync("Tag", new TypedValue { Int32Value = 1 });
await act.Should().ThrowAsync<InvalidOperationException>()
.WithMessage("*Write error*");
client.Dispose();
}
[Fact]
public async Task WriteBatchAsync_SendsAllItems()
{
var (client, fake) = TestableClient.CreateConnected();
var values = new Dictionary<string, TypedValue>
{
["Tag1"] = new TypedValue { DoubleValue = 1.0 },
["Tag2"] = new TypedValue { Int32Value = 2 },
["Tag3"] = new TypedValue { BoolValue = true }
};
await client.WriteBatchAsync(values);
fake.WriteBatchCalls.Should().HaveCount(1);
fake.WriteBatchCalls[0].Items.Should().HaveCount(3);
client.Dispose();
}
[Fact]
public async Task WriteBatchAndWaitAsync_ReturnsResponse()
{
var (client, fake) = TestableClient.CreateConnected();
fake.WriteBatchAndWaitResponseToReturn = new WriteBatchAndWaitResponse
{
Success = true,
FlagReached = true,
ElapsedMs = 150,
WriteResults = [new WriteResult { Tag = "Tag1", Success = true }]
};
var values = new Dictionary<string, TypedValue>
{
["Tag1"] = new TypedValue { Int32Value = 1 }
};
var result = await client.WriteBatchAndWaitAsync(
values, "FlagTag", new TypedValue { BoolValue = true });
result.FlagReached.Should().BeTrue();
result.ElapsedMs.Should().Be(150);
client.Dispose();
}
[Fact]
public async Task CheckApiKeyAsync_ReturnsApiKeyInfo()
{
var (client, fake) = TestableClient.CreateConnected();
fake.CheckApiKeyResponseToReturn = new CheckApiKeyResponse { IsValid = true, Message = "Admin key" };
var result = await client.CheckApiKeyAsync("my-api-key");
result.IsValid.Should().BeTrue();
result.Description.Should().Be("Admin key");
client.Dispose();
}
}