using System; using System.Collections.Generic; using ArchestrA; using ZB.MOM.WW.OtOpcUa.Historian.Aveva; using ZB.MOM.WW.OtOpcUa.Host.Configuration; namespace ZB.MOM.WW.OtOpcUa.Historian.Aveva.Tests { /// /// Fake Historian connection factory for tests. Controls whether connections /// succeed, fail, or timeout without requiring the real Historian SDK runtime. /// internal sealed class FakeHistorianConnectionFactory : IHistorianConnectionFactory { /// /// Exception thrown on every CreateAndConnect call unless a more specific rule in /// or fires first. /// public Exception? ConnectException { get; set; } public int ConnectCallCount { get; private set; } public Action? OnConnect { get; set; } /// /// Per-server-name override: if the requested config.ServerName has an entry /// whose value is non-null, that exception is thrown instead of the global /// . Lets tests script cluster failover behavior like /// "node A always fails; node B always succeeds". /// public Dictionary ServerBehaviors { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); /// /// Ordered history of server names passed to CreateAndConnect so tests can assert the /// picker's iteration order and failover sequence. /// public List ConnectHistory { get; } = new List(); public HistorianAccess CreateAndConnect(HistorianConfiguration config, HistorianConnectionType type) { ConnectCallCount++; ConnectHistory.Add(config.ServerName); if (ServerBehaviors.TryGetValue(config.ServerName, out var serverException) && serverException != null) throw serverException; if (OnConnect != null) { OnConnect(ConnectCallCount); } else if (ConnectException != null) { throw ConnectException; } // Return a HistorianAccess that is not actually connected. // ReadRawAsync etc. will fail when they try to use it, which exercises // the HandleConnectionError → reconnect path. return new HistorianAccess(); } } }