@@ -0,0 +1,56 @@
|
||||
namespace ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.IntegrationTests;
|
||||
|
||||
/// <summary>
|
||||
/// Fixture for the reverse-connect variant of opc-plc (PR-11). Unlike the
|
||||
/// dial-mode <see cref="OpcPlcFixture"/>, the simulator here is the dialer:
|
||||
/// it reaches OUT to the test runner's listener URL on
|
||||
/// <c>opc.tcp://host.docker.internal:4844</c>. The fixture's job is to
|
||||
/// advertise the listener URL the test should bind and provide a clear
|
||||
/// skip reason when the docker-compose service isn't running.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// <b>Why no port-probe</b>: the conventional fixture probes the simulator's
|
||||
/// server port to detect docker-up. In reverse-connect the simulator opens
|
||||
/// no inbound port — it's a pure dialer — so a probe would always fail.
|
||||
/// Tests that want a hard skip should look at <see cref="SkipReason"/>
|
||||
/// which is set from the <c>OPCUA_RC_SIM</c> env var (any value =
|
||||
/// "simulator running"; absent = skip).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The "shared listener URL" model is enforced by the driver's
|
||||
/// <c>ReverseConnectListener</c> singleton — multiple smoke tests in the
|
||||
/// same xunit assembly share one listener instance even if they run in
|
||||
/// parallel. Tests should pick distinct <c>ExpectedServerUri</c> values to
|
||||
/// demultiplex inbound connections.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public sealed class OpcPlcReverseConnectFixture : IAsyncDisposable
|
||||
{
|
||||
private const string DefaultListenerUrl = "opc.tcp://0.0.0.0:4844";
|
||||
private const string EnvVar = "OPCUA_RC_SIM";
|
||||
|
||||
/// <summary>The listener URL the driver should bind for incoming reverse-connect dials.</summary>
|
||||
public string ListenerUrl { get; } = DefaultListenerUrl;
|
||||
|
||||
/// <summary>Skip reason when the reverse-connect simulator isn't available; null when ready.</summary>
|
||||
public string? SkipReason { get; }
|
||||
|
||||
public OpcPlcReverseConnectFixture()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(EnvVar)))
|
||||
{
|
||||
SkipReason =
|
||||
$"Reverse-connect smoke skipped — set {EnvVar}=1 once `docker compose -f Docker/docker-compose.yml up opc-plc-rc` is healthy. " +
|
||||
"The dialer needs host.docker.internal to reach this machine — verify Docker Desktop's network mode supports it.";
|
||||
}
|
||||
}
|
||||
|
||||
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
|
||||
}
|
||||
|
||||
[Xunit.CollectionDefinition(Name)]
|
||||
public sealed class OpcPlcReverseConnectCollection : Xunit.ICollectionFixture<OpcPlcReverseConnectFixture>
|
||||
{
|
||||
public const string Name = "OpcPlcReverseConnect";
|
||||
}
|
||||
Reference in New Issue
Block a user