494da22cd1
- DriverTestConnectE2eTests: 3 scenarios (sim/wrong-port/black-hole) against the Modbus Docker fixture. Sim + wrong-port skip if fixture unreachable; black-hole uses ModbusDriverProbe directly (no fixture). - DriverReconnectE2eTests: message round-trip through AdminOperationsActor cluster singleton — Ok=true + audit write, without live driver side effect. - DriverStatusHubE2eTests: bridge-mocked fallback — spawns DriverStatusSignalRBridge in the harness ActorSystem with a mock IHubContext, publishes DriverHealthChanged to the driver-health DPS topic, asserts store upsert + hub SendAsync call. - DockerFixtureAvailability helper: TCP-connect probe for skip guards. - Moq 4.20.72 added to central package management for hub mocking. - Design doc §8.3 replaced with concrete pre-ship operator runbook.
61 lines
2.4 KiB
C#
61 lines
2.4 KiB
C#
using System.Net.Sockets;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Host.IntegrationTests;
|
|
|
|
/// <summary>
|
|
/// Lightweight TCP-connect probe used by E2E integration tests to detect whether a Docker
|
|
/// fixture is reachable before attempting live work. Tests skip cleanly when this returns
|
|
/// <c>false</c>; CI with fixtures available lets them run.
|
|
/// </summary>
|
|
public static class DockerFixtureAvailability
|
|
{
|
|
/// <summary>
|
|
/// Attempts a TCP connect to <paramref name="host"/>:<paramref name="port"/>. Returns
|
|
/// <c>true</c> if the connection is accepted within <paramref name="timeoutMs"/>
|
|
/// milliseconds; <c>false</c> on refusal, timeout, or DNS failure.
|
|
/// </summary>
|
|
/// <param name="host">The host to probe.</param>
|
|
/// <param name="port">The TCP port to connect to.</param>
|
|
/// <param name="timeoutMs">Maximum time to wait in milliseconds; defaults to 500.</param>
|
|
public static bool IsReachable(string host, int port, int timeoutMs = 500)
|
|
{
|
|
try
|
|
{
|
|
// Force IPv4 — remote Docker host binds only on IPv4 (0.0.0.0).
|
|
using var client = new TcpClient(AddressFamily.InterNetwork);
|
|
var ipv4 = System.Net.Dns.GetHostAddresses(host)
|
|
.FirstOrDefault(a => a.AddressFamily == AddressFamily.InterNetwork)
|
|
?? System.Net.IPAddress.Parse(host);
|
|
|
|
var task = client.ConnectAsync(ipv4, port);
|
|
return task.Wait(timeoutMs) && client.Connected;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parses an <c>HOST:PORT</c> endpoint string and probes reachability.
|
|
/// Returns <c>true</c> if the connection succeeds within <paramref name="timeoutMs"/>
|
|
/// milliseconds. Handles malformed strings gracefully by returning <c>false</c>.
|
|
/// </summary>
|
|
/// <param name="endpoint">Endpoint in <c>host:port</c> format.</param>
|
|
/// <param name="timeoutMs">Maximum time to wait in milliseconds; defaults to 500.</param>
|
|
public static bool IsReachable(string endpoint, int timeoutMs = 500)
|
|
{
|
|
try
|
|
{
|
|
var parts = endpoint.Split(':', 2);
|
|
if (parts.Length != 2 || !int.TryParse(parts[1], out var port))
|
|
return false;
|
|
return IsReachable(parts[0], port, timeoutMs);
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|