using Microsoft.Extensions.Logging.Abstractions;
using NSubstitute;
using ScadaLink.Commons.Types.Enums;
using ScadaLink.DataConnectionLayer.Adapters;
namespace ScadaLink.DataConnectionLayer.Tests;
///
/// WP-8: Tests for LmxProxy adapter.
///
public class LmxProxyDataConnectionTests
{
private readonly ILmxProxyClient _mockClient;
private readonly ILmxProxyClientFactory _mockFactory;
private readonly LmxProxyDataConnection _adapter;
public LmxProxyDataConnectionTests()
{
_mockClient = Substitute.For();
_mockFactory = Substitute.For();
_mockFactory.Create().Returns(_mockClient);
_adapter = new LmxProxyDataConnection(_mockFactory, NullLogger.Instance);
}
[Fact]
public async Task Connect_OpensSessionWithHostAndPort()
{
_mockClient.OpenSessionAsync("myhost", 5001, Arg.Any())
.Returns("session-123");
_mockClient.IsConnected.Returns(true);
await _adapter.ConnectAsync(new Dictionary
{
["Host"] = "myhost",
["Port"] = "5001"
});
Assert.Equal(ConnectionHealth.Connected, _adapter.Status);
await _mockClient.Received(1).OpenSessionAsync("myhost", 5001, Arg.Any());
}
[Fact]
public async Task Disconnect_ClosesSession()
{
_mockClient.IsConnected.Returns(true);
_mockClient.OpenSessionAsync(Arg.Any(), Arg.Any(), Arg.Any())
.Returns("session-123");
await _adapter.ConnectAsync(new Dictionary());
await _adapter.DisconnectAsync();
Assert.Equal(ConnectionHealth.Disconnected, _adapter.Status);
await _mockClient.Received(1).CloseSessionAsync(Arg.Any());
}
[Fact]
public async Task Write_Success_ReturnsGoodResult()
{
_mockClient.IsConnected.Returns(true);
_mockClient.OpenSessionAsync(Arg.Any(), Arg.Any(), Arg.Any())
.Returns("session-123");
_mockClient.WriteTagAsync("Tag1", 42, Arg.Any())
.Returns(true);
await _adapter.ConnectAsync(new Dictionary());
var result = await _adapter.WriteAsync("Tag1", 42);
Assert.True(result.Success);
}
[Fact]
public async Task Write_Failure_ReturnsError()
{
_mockClient.IsConnected.Returns(true);
_mockClient.OpenSessionAsync(Arg.Any(), Arg.Any(), Arg.Any())
.Returns("session-123");
_mockClient.WriteTagAsync("Tag1", 42, Arg.Any())
.Returns(false);
await _adapter.ConnectAsync(new Dictionary());
var result = await _adapter.WriteAsync("Tag1", 42);
Assert.False(result.Success);
Assert.Equal("LmxProxy write failed", result.ErrorMessage);
}
[Fact]
public async Task Read_Good_ReturnsValue()
{
_mockClient.IsConnected.Returns(true);
_mockClient.OpenSessionAsync(Arg.Any(), Arg.Any(), Arg.Any())
.Returns("session-123");
_mockClient.ReadTagAsync("Tag1", Arg.Any())
.Returns((42.5, DateTime.UtcNow, true));
await _adapter.ConnectAsync(new Dictionary());
var result = await _adapter.ReadAsync("Tag1");
Assert.True(result.Success);
Assert.Equal(42.5, result.Value!.Value);
}
[Fact]
public async Task Read_Bad_ReturnsFailure()
{
_mockClient.IsConnected.Returns(true);
_mockClient.OpenSessionAsync(Arg.Any(), Arg.Any(), Arg.Any())
.Returns("session-123");
_mockClient.ReadTagAsync("Tag1", Arg.Any())
.Returns((null, DateTime.UtcNow, false));
await _adapter.ConnectAsync(new Dictionary());
var result = await _adapter.ReadAsync("Tag1");
Assert.False(result.Success);
}
[Fact]
public async Task NotConnected_ThrowsOnOperations()
{
_mockClient.IsConnected.Returns(false);
await Assert.ThrowsAsync(() =>
_adapter.ReadAsync("tag1"));
}
}