using Opc.Ua; using ZB.MOM.WW.OtOpcUa.Client.Shared.Adapters; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Tests.Fakes; /// /// Test double for used to drive monitored-item behavior in shared-client tests. /// internal sealed class FakeSubscriptionAdapter : ISubscriptionAdapter { private readonly Dictionary? DataCallback, Action? EventCallback )> _items = new(); private uint _nextHandle = 100; /// /// Gets a value indicating whether the fake subscription has been deleted. /// public bool Deleted { get; private set; } /// /// Gets a value indicating whether a condition refresh was requested by the client under test. /// public bool ConditionRefreshCalled { get; private set; } /// /// Gets or sets a value indicating whether condition refresh should throw to simulate unsupported servers. /// public bool ThrowOnConditionRefresh { get; set; } public int AddDataChangeCount { get; private set; } public int AddEventCount { get; private set; } public int RemoveCount { get; private set; } /// /// Gets the handles of all active items. /// public IReadOnlyCollection ActiveHandles => _items.Keys.ToList(); /// public uint SubscriptionId { get; set; } = 42; /// public Task AddDataChangeMonitoredItemAsync(NodeId nodeId, int samplingIntervalMs, Action onDataChange, CancellationToken ct) { AddDataChangeCount++; var handle = _nextHandle++; _items[handle] = (nodeId, onDataChange, null); return Task.FromResult(handle); } /// public Task RemoveMonitoredItemAsync(uint clientHandle, CancellationToken ct) { RemoveCount++; _items.Remove(clientHandle); return Task.CompletedTask; } /// public Task AddEventMonitoredItemAsync(NodeId nodeId, int samplingIntervalMs, EventFilter filter, Action onEvent, CancellationToken ct) { AddEventCount++; var handle = _nextHandle++; _items[handle] = (nodeId, null, onEvent); return Task.FromResult(handle); } /// public Task ConditionRefreshAsync(CancellationToken ct) { ConditionRefreshCalled = true; if (ThrowOnConditionRefresh) throw new InvalidOperationException("Condition refresh not supported"); return Task.CompletedTask; } /// public Task DeleteAsync(CancellationToken ct) { Deleted = true; _items.Clear(); return Task.CompletedTask; } /// /// Clears tracked monitored items when the fake subscription is disposed by the client under test. /// public void Dispose() { _items.Clear(); } /// /// Simulates a data change notification for testing. /// public void SimulateDataChange(uint handle, DataValue value) { if (_items.TryGetValue(handle, out var item) && item.DataCallback != null) item.DataCallback(item.NodeId.ToString(), value); } /// /// Simulates an event notification for testing. /// public void SimulateEvent(uint handle, EventFieldList eventFields) { if (_items.TryGetValue(handle, out var item) && item.EventCallback != null) item.EventCallback(eventFields); } }