Files
lmxopcua/tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests
Joseph Doherty 5468b79d19 test(mesh): real two-ActorSystem ClusterClient boundary test with falsifiability control
Two genuinely separate single-member clusters sharing the ActorSystem name and
joined only by ClusterClient, so the mesh boundary is exercised over the wire
rather than through an in-process relay: a relay cannot fail for a missing
receptionist extension, an unregistered service, a malformed contact path or a
serialization break, which are the Phase 2 failure modes.

Covers both legs plus the control:
  * central SendToAll -> node comm actor -> node EventStream
  * node ApplyAck -> central comm actor, through the node's own client
  * a node without the receptionist extension receives nothing

Sabotage-verified. Suppressing the node-side EventStream publish and the
outbound ack Tell reddens one leg each. Restoring the receptionist and the
service registration on the control node reddens the control, which is what
proves the control's send is live rather than silently misaddressed.

The control removes the extension AND the RegisterService call, since resolving
the receptionist to register would materialise the extension whose absence is
the point; it falsifies "delivery happens without a receptionist boundary", not
the extension line alone. Recorded in the test.

Also corrects MeshCommActorPathTests: with one node per side, per-node and
singleton registration are indistinguishable here, so the property the dropped
Task 6 assertion covered belongs to live-gate step 8, not to this class.

Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
2026-07-22 17:32:19 -04:00
..

ZB.MOM.WW.OtOpcUa.Host.IntegrationTests

Two-node Akka cluster integration tests on top of TwoNodeClusterHarness.

Default mode (no infra required)

dotnet test tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests

Uses Microsoft.EntityFrameworkCore.InMemory for ConfigDb and a stub ILdapAuthService that accepts any username when the password is valid-password. Each harness instance creates a unique in-memory database scoped to its lifetime. This is the mode CI runs by default.

Real-infra mode (SQL Server + OpenLDAP)

When you need to exercise EF behaviors that diverge between providers (index uniqueness, RowVersion concurrency, JSON columns, migration application) or a real LDAP bind, bring up the bundled compose stack and set the env-var switches:

docker compose -f tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests/docker-compose.yml up -d

export OTOPCUA_HARNESS_USE_SQL=1
export OTOPCUA_HARNESS_USE_LDAP=1
dotnet test tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests

docker compose -f tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests/docker-compose.yml down -v

SQL Server mode (OTOPCUA_HARNESS_USE_SQL=1)

  • Container: mcr.microsoft.com/mssql/server:2022-latest on localhost:14331
  • Each TwoNodeClusterHarness.StartAsync() creates a unique database OtOpcUa_Harness_{guid} via Database.EnsureCreatedAsync() and drops it on DisposeAsync() (best-effort).
  • Port 14331 chosen to avoid colliding with the docker-dev/ fleet (which uses 14330).

LDAP mode (OTOPCUA_HARNESS_USE_LDAP=1)

  • Container: bitnami/openldap:2.6 on localhost:3894
  • Users alice / alice123 and bob / bob123, all under ou=FleetAdmin.
  • Port 3894 chosen to avoid colliding with the docker-dev/ fleet (which uses 3893).

Local-dev caveat

This dev VM (DESKTOP-6JL3KKO) does not run Docker locally. Real-infra mode runs on the shared Linux Docker host (10.100.0.35) per docs/v2/dev-environment.md, or in CI on Linux.