using System.Net.Sockets;
namespace ZB.MOM.WW.OtOpcUa.Host.IntegrationTests;
///
/// 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
/// false; CI with fixtures available lets them run.
///
public static class DockerFixtureAvailability
{
///
/// Attempts a TCP connect to :. Returns
/// true if the connection is accepted within
/// milliseconds; false on refusal, timeout, or DNS failure.
///
/// The host to probe.
/// The TCP port to connect to.
/// Maximum time to wait in milliseconds; defaults to 500.
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;
}
}
///
/// Parses an HOST:PORT endpoint string and probes reachability.
/// Returns true if the connection succeeds within
/// milliseconds. Handles malformed strings gracefully by returning false.
///
/// Endpoint in host:port format.
/// Maximum time to wait in milliseconds; defaults to 500.
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;
}
}
}