Files
lmxopcua/tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests
Joseph Doherty 7654f24dab
v2-ci / build (push) Successful in 3m51s
v2-ci / unit-tests (push) Failing after 13m29s
test(harness): serialize Host.IntegrationTests; drop the reconciler's unused singleton proxy
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
2026-07-22 09:51:10 -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.