7654f24dab
Closes the last branch-only failures. Measured across five full-suite runs on this branch versus two on master in a clean worktree: master failed only AbCip in this assembly (2/2), while the branch additionally failed one or two E2E deploy tests, rotating between DeployHappyPath, DriverReconnect and EquipmentNamespaceMaterialization (4/4). Each passed in isolation, and the assembly on its own was 195/201 throughout — the failures only appeared under full-suite CPU contention. Cause is contention, not correctness. Every test here builds a real two-node Akka cluster — two Kestrel hosts, two ActorSystems with remoting, six admin singletons, an EF context, a deploy pipeline — and xUnit ran them concurrently with each other and with every other assembly. That was survivable while the coordinator sealed instantly on an empty expected-ack set; now that it waits for a real ack from every configured node, these tests measure an end-to-end round-trip and starve. Serialising this one assembly makes them deterministic: 195/201 with only AbCip_Green_AgainstSim, and the full-solution failure set is now IDENTICAL to master's — 7 shared, zero branch-only. Cost is wall-clock for this assembly, 40s -> 3m35s; it is a handful of heavyweight E2E tests, not a broad unit suite, and a widened timeout alone did not fix it (tried first, at 45s). Also drops createProxyToo for the address reconciler. Nothing resolves ClusterNodeAddressReconcilerKey from the registry — the actor only reads cluster state and logs — so the proxy was a second actor per node hunting for a singleton nobody addresses. Kept because it removes dead machinery, not because it fixed the flakiness; measured on its own, it did not. Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
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-latestonlocalhost:14331 - Each
TwoNodeClusterHarness.StartAsync()creates a unique databaseOtOpcUa_Harness_{guid}viaDatabase.EnsureCreatedAsync()and drops it onDisposeAsync()(best-effort). - Port
14331chosen to avoid colliding with thedocker-dev/fleet (which uses14330).
LDAP mode (OTOPCUA_HARNESS_USE_LDAP=1)
- Container:
bitnami/openldap:2.6onlocalhost:3894 - Users
alice/alice123andbob/bob123, all underou=FleetAdmin. - Port
3894chosen to avoid colliding with thedocker-dev/fleet (which uses3893).
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.