using Opc.Ua; using ZB.MOM.WW.OtOpcUa.Client.Shared.Adapters; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Tests.Fakes; internal sealed class FakeSessionFactory : ISessionFactory { private readonly List _createdSessions = []; private readonly Queue _sessions = new(); public int CreateCallCount { get; private set; } public bool ThrowOnCreate { get; set; } public string? LastEndpointUrl { get; private set; } /// /// Optional gate that, when set, blocks until completed. /// Lets tests hold a failover loop in-flight to exercise re-entrancy. /// public TaskCompletionSource? CreateGate { get; set; } public IReadOnlyList CreatedSessions => _createdSessions; public async Task CreateSessionAsync( ApplicationConfiguration config, EndpointDescription endpoint, string sessionName, uint sessionTimeoutMs, UserIdentity identity, CancellationToken ct) { CreateCallCount++; LastEndpointUrl = endpoint.EndpointUrl; if (CreateGate != null) await CreateGate.Task; if (ThrowOnCreate) throw new InvalidOperationException("FakeSessionFactory configured to fail."); FakeSessionAdapter session; if (_sessions.Count > 0) session = _sessions.Dequeue(); else session = new FakeSessionAdapter { EndpointUrl = endpoint.EndpointUrl, ServerName = endpoint.Server?.ApplicationName?.Text ?? "FakeServer", SecurityMode = endpoint.SecurityMode.ToString(), SecurityPolicyUri = endpoint.SecurityPolicyUri ?? string.Empty }; // Ensure endpoint URL matches session.EndpointUrl = endpoint.EndpointUrl; _createdSessions.Add(session); return session; } /// /// Enqueues a session adapter to be returned on the next call to CreateSessionAsync. /// public void EnqueueSession(FakeSessionAdapter session) { _sessions.Enqueue(session); } }