178 lines
5.7 KiB
C#
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();
|
|
}
|
|
}
|