deprecate(lmxproxy): move all LmxProxy code, tests, and docs to deprecated/
LmxProxy is no longer needed. Moved the entire lmxproxy/ workspace, DCL adapter files, and related docs to deprecated/. Removed LmxProxy registration from DataConnectionFactory, project reference from DCL, protocol option from UI, and cleaned up all requirement docs.
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
using ZB.MOM.WW.LmxProxy.Client.Domain;
|
||||
|
||||
namespace ZB.MOM.WW.LmxProxy.Client.Tests.Fakes;
|
||||
|
||||
/// <summary>
|
||||
/// Hand-written fake implementation of ILmxProxyClient for unit testing streaming extensions.
|
||||
/// </summary>
|
||||
internal class FakeLmxProxyClient : ILmxProxyClient
|
||||
{
|
||||
public TimeSpan DefaultTimeout { get; set; } = TimeSpan.FromSeconds(30);
|
||||
|
||||
// Track calls
|
||||
public List<List<string>> ReadBatchCalls { get; } = [];
|
||||
public List<IDictionary<string, TypedValue>> WriteBatchCalls { get; } = [];
|
||||
public List<IEnumerable<string>> SubscribeCalls { get; } = [];
|
||||
|
||||
// Configurable responses
|
||||
public Func<IEnumerable<string>, CancellationToken, Task<IDictionary<string, Vtq>>>? ReadBatchHandler { get; set; }
|
||||
public Exception? ReadBatchExceptionToThrow { get; set; }
|
||||
public int ReadBatchExceptionCount { get; set; }
|
||||
private int _readBatchCallCount;
|
||||
|
||||
// Subscription support
|
||||
public Action<string, Vtq>? CapturedOnUpdate { get; private set; }
|
||||
public Action<Exception>? CapturedOnError { get; private set; }
|
||||
|
||||
public Task ConnectAsync(CancellationToken cancellationToken = default) => Task.CompletedTask;
|
||||
public Task DisconnectAsync() => Task.CompletedTask;
|
||||
public Task<bool> IsConnectedAsync() => Task.FromResult(true);
|
||||
|
||||
public Task<Vtq> ReadAsync(string address, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult(new Vtq(null, DateTime.UtcNow, Quality.Good));
|
||||
|
||||
public Task<IDictionary<string, Vtq>> ReadBatchAsync(IEnumerable<string> addresses, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var addressList = addresses.ToList();
|
||||
ReadBatchCalls.Add(addressList);
|
||||
_readBatchCallCount++;
|
||||
|
||||
if (ReadBatchExceptionToThrow is not null && _readBatchCallCount <= ReadBatchExceptionCount)
|
||||
throw ReadBatchExceptionToThrow;
|
||||
|
||||
if (ReadBatchHandler is not null)
|
||||
return ReadBatchHandler(addressList, cancellationToken);
|
||||
|
||||
var result = new Dictionary<string, Vtq>();
|
||||
foreach (var addr in addressList)
|
||||
result[addr] = new Vtq(42.0, DateTime.UtcNow, Quality.Good);
|
||||
return Task.FromResult<IDictionary<string, Vtq>>(result);
|
||||
}
|
||||
|
||||
public Task WriteAsync(string address, TypedValue value, CancellationToken cancellationToken = default)
|
||||
=> Task.CompletedTask;
|
||||
|
||||
public Task WriteBatchAsync(IDictionary<string, TypedValue> values, CancellationToken cancellationToken = default)
|
||||
{
|
||||
WriteBatchCalls.Add(new Dictionary<string, TypedValue>(values));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<WriteBatchAndWaitResponse> WriteBatchAndWaitAsync(
|
||||
IDictionary<string, TypedValue> values, string flagTag, TypedValue flagValue,
|
||||
int timeoutMs = 5000, int pollIntervalMs = 100, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult(new WriteBatchAndWaitResponse { Success = true });
|
||||
|
||||
public Task<LmxProxyClient.ISubscription> SubscribeAsync(
|
||||
IEnumerable<string> addresses,
|
||||
Action<string, Vtq> onUpdate,
|
||||
Action<Exception>? onStreamError = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
SubscribeCalls.Add(addresses);
|
||||
CapturedOnUpdate = onUpdate;
|
||||
CapturedOnError = onStreamError;
|
||||
return Task.FromResult<LmxProxyClient.ISubscription>(new FakeSubscription());
|
||||
}
|
||||
|
||||
public Task<LmxProxyClient.ApiKeyInfo> CheckApiKeyAsync(string apiKey, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult(new LmxProxyClient.ApiKeyInfo { IsValid = true });
|
||||
|
||||
public Dictionary<string, object> GetMetrics() => [];
|
||||
|
||||
public void Dispose() { }
|
||||
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
|
||||
|
||||
private class FakeSubscription : LmxProxyClient.ISubscription
|
||||
{
|
||||
public void Dispose() { }
|
||||
public Task DisposeAsync() => Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using ZB.MOM.WW.LmxProxy.Client.Domain;
|
||||
|
||||
namespace ZB.MOM.WW.LmxProxy.Client.Tests.Fakes;
|
||||
|
||||
/// <summary>
|
||||
/// Hand-written fake implementation of IScadaService for unit testing.
|
||||
/// </summary>
|
||||
internal class FakeScadaService : IScadaService
|
||||
{
|
||||
// Configure responses
|
||||
public ConnectResponse ConnectResponseToReturn { get; set; } = new() { Success = true, SessionId = "test-session-123", Message = "OK" };
|
||||
public DisconnectResponse DisconnectResponseToReturn { get; set; } = new() { Success = true, Message = "OK" };
|
||||
public GetConnectionStateResponse GetConnectionStateResponseToReturn { get; set; } = new() { IsConnected = true };
|
||||
public ReadResponse ReadResponseToReturn { get; set; } = new() { Success = true };
|
||||
public ReadBatchResponse ReadBatchResponseToReturn { get; set; } = new() { Success = true };
|
||||
public WriteResponse WriteResponseToReturn { get; set; } = new() { Success = true };
|
||||
public WriteBatchResponse WriteBatchResponseToReturn { get; set; } = new() { Success = true };
|
||||
public WriteBatchAndWaitResponse WriteBatchAndWaitResponseToReturn { get; set; } = new() { Success = true };
|
||||
public CheckApiKeyResponse CheckApiKeyResponseToReturn { get; set; } = new() { IsValid = true, Message = "Valid" };
|
||||
|
||||
// Track calls
|
||||
public List<ConnectRequest> ConnectCalls { get; } = [];
|
||||
public List<DisconnectRequest> DisconnectCalls { get; } = [];
|
||||
public List<GetConnectionStateRequest> GetConnectionStateCalls { get; } = [];
|
||||
public List<ReadRequest> ReadCalls { get; } = [];
|
||||
public List<ReadBatchRequest> ReadBatchCalls { get; } = [];
|
||||
public List<WriteRequest> WriteCalls { get; } = [];
|
||||
public List<WriteBatchRequest> WriteBatchCalls { get; } = [];
|
||||
public List<WriteBatchAndWaitRequest> WriteBatchAndWaitCalls { get; } = [];
|
||||
public List<CheckApiKeyRequest> CheckApiKeyCalls { get; } = [];
|
||||
public List<SubscribeRequest> SubscribeCalls { get; } = [];
|
||||
|
||||
// Error injection
|
||||
public Exception? GetConnectionStateException { get; set; }
|
||||
|
||||
// Subscription data
|
||||
public List<VtqMessage> SubscriptionMessages { get; set; } = [];
|
||||
public Exception? SubscriptionException { get; set; }
|
||||
|
||||
public ValueTask<ConnectResponse> ConnectAsync(ConnectRequest request)
|
||||
{
|
||||
ConnectCalls.Add(request);
|
||||
return new ValueTask<ConnectResponse>(ConnectResponseToReturn);
|
||||
}
|
||||
|
||||
public ValueTask<DisconnectResponse> DisconnectAsync(DisconnectRequest request)
|
||||
{
|
||||
DisconnectCalls.Add(request);
|
||||
return new ValueTask<DisconnectResponse>(DisconnectResponseToReturn);
|
||||
}
|
||||
|
||||
public ValueTask<GetConnectionStateResponse> GetConnectionStateAsync(GetConnectionStateRequest request)
|
||||
{
|
||||
GetConnectionStateCalls.Add(request);
|
||||
if (GetConnectionStateException is not null)
|
||||
throw GetConnectionStateException;
|
||||
return new ValueTask<GetConnectionStateResponse>(GetConnectionStateResponseToReturn);
|
||||
}
|
||||
|
||||
public ValueTask<ReadResponse> ReadAsync(ReadRequest request)
|
||||
{
|
||||
ReadCalls.Add(request);
|
||||
return new ValueTask<ReadResponse>(ReadResponseToReturn);
|
||||
}
|
||||
|
||||
public ValueTask<ReadBatchResponse> ReadBatchAsync(ReadBatchRequest request)
|
||||
{
|
||||
ReadBatchCalls.Add(request);
|
||||
return new ValueTask<ReadBatchResponse>(ReadBatchResponseToReturn);
|
||||
}
|
||||
|
||||
public ValueTask<WriteResponse> WriteAsync(WriteRequest request)
|
||||
{
|
||||
WriteCalls.Add(request);
|
||||
return new ValueTask<WriteResponse>(WriteResponseToReturn);
|
||||
}
|
||||
|
||||
public ValueTask<WriteBatchResponse> WriteBatchAsync(WriteBatchRequest request)
|
||||
{
|
||||
WriteBatchCalls.Add(request);
|
||||
return new ValueTask<WriteBatchResponse>(WriteBatchResponseToReturn);
|
||||
}
|
||||
|
||||
public ValueTask<WriteBatchAndWaitResponse> WriteBatchAndWaitAsync(WriteBatchAndWaitRequest request)
|
||||
{
|
||||
WriteBatchAndWaitCalls.Add(request);
|
||||
return new ValueTask<WriteBatchAndWaitResponse>(WriteBatchAndWaitResponseToReturn);
|
||||
}
|
||||
|
||||
public ValueTask<CheckApiKeyResponse> CheckApiKeyAsync(CheckApiKeyRequest request)
|
||||
{
|
||||
CheckApiKeyCalls.Add(request);
|
||||
return new ValueTask<CheckApiKeyResponse>(CheckApiKeyResponseToReturn);
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<VtqMessage> SubscribeAsync(
|
||||
SubscribeRequest request, [EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
SubscribeCalls.Add(request);
|
||||
|
||||
foreach (var msg in SubscriptionMessages)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
yield return msg;
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
if (SubscriptionException is not null)
|
||||
throw SubscriptionException;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using ZB.MOM.WW.LmxProxy.Client.Domain;
|
||||
|
||||
namespace ZB.MOM.WW.LmxProxy.Client.Tests.Fakes;
|
||||
|
||||
/// <summary>
|
||||
/// Helper to create an LmxProxyClient wired to a FakeScadaService, bypassing real gRPC.
|
||||
/// Uses reflection to set private fields since the client has no test seam for IScadaService injection.
|
||||
/// </summary>
|
||||
internal static class TestableClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates an LmxProxyClient with a fake service injected into its internal state,
|
||||
/// simulating a connected client.
|
||||
/// </summary>
|
||||
public static (LmxProxyClient Client, FakeScadaService Fake) CreateConnected(
|
||||
string sessionId = "test-session-123",
|
||||
ILogger<LmxProxyClient>? logger = null)
|
||||
{
|
||||
var fake = new FakeScadaService
|
||||
{
|
||||
ConnectResponseToReturn = new ConnectResponse
|
||||
{
|
||||
Success = true,
|
||||
SessionId = sessionId,
|
||||
Message = "OK"
|
||||
}
|
||||
};
|
||||
|
||||
var client = new LmxProxyClient("localhost", 50051, "test-key", null, logger);
|
||||
|
||||
// Use reflection to inject fake service and simulate connected state
|
||||
var clientType = typeof(LmxProxyClient);
|
||||
|
||||
var clientField = clientType.GetField("_client",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!;
|
||||
clientField.SetValue(client, fake);
|
||||
|
||||
var sessionField = clientType.GetField("_sessionId",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!;
|
||||
sessionField.SetValue(client, sessionId);
|
||||
|
||||
var connectedField = clientType.GetField("_isConnected",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!;
|
||||
connectedField.SetValue(client, true);
|
||||
|
||||
return (client, fake);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user