using ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Adapters;
namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Tests.Adapters;
///
/// In-memory fake for adapter unit tests. Lets tests
/// drive the event loop (push updates / fault the stream) and stub read/write/browse.
///
public sealed class FakeMxGatewayClient : IMxGatewayClient, IMxGatewayClientFactory
{
public MxGatewayConnectionOptions? ConnectedWith;
public readonly List Subscribed = new();
public readonly List Unsubscribed = new();
public readonly TaskCompletionSource EventLoopGate = new(TaskCreationOptions.RunContinuationsAsynchronously);
public Action? OnUpdate;
public Func, IReadOnlyList>? ReadHandler;
public Func, IReadOnlyList>? WriteHandler;
public Func, bool)>? BrowseHandler;
private int _nextHandle;
public IMxGatewayClient Create() => this;
public Task ConnectAsync(MxGatewayConnectionOptions o, CancellationToken ct = default)
{
ConnectedWith = o;
return Task.CompletedTask;
}
public Task DisconnectAsync(CancellationToken ct = default) => Task.CompletedTask;
public Task SubscribeAsync(string tag, CancellationToken ct = default)
{
var id = (++_nextHandle).ToString();
Subscribed.Add(tag);
return Task.FromResult(id);
}
public Task UnsubscribeAsync(string id, CancellationToken ct = default)
{
Unsubscribed.Add(id);
return Task.CompletedTask;
}
public Task> ReadAsync(IReadOnlyList tags, CancellationToken ct = default)
=> Task.FromResult(ReadHandler!(tags));
public Task> WriteAsync(IReadOnlyList<(string TagPath, object? Value)> w, CancellationToken ct = default)
=> Task.FromResult(WriteHandler!(w));
public Task<(IReadOnlyList Children, bool Truncated)> BrowseChildrenAsync(string? p, CancellationToken ct = default)
=> Task.FromResult(BrowseHandler!(p));
public async Task RunEventLoopAsync(Action onUpdate, CancellationToken ct = default)
{
OnUpdate = onUpdate;
using var reg = ct.Register(() => EventLoopGate.TrySetResult());
await EventLoopGate.Task; // test completes this to end the loop…
ct.ThrowIfCancellationRequested(); // …or FaultEventLoop() faults it to simulate a stream break
}
public Task RunAlarmStreamAsync(
string? alarmFilterPrefix,
Action onTransition,
CancellationToken ct = default)
=> Task.CompletedTask; // no alarm feed in the fake
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
/// Simulate a stream break so the adapter raises Disconnected.
public void FaultEventLoop() => EventLoopGate.TrySetException(new Exception("stream broke"));
}