Files
lmxopcua/tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests
Joseph Doherty 34829ea0d7 test(scripting): Evaluate_racing_ClearCompiledScripts no longer assumes a single clear per evaluation
The racing test encoded two timing assumptions and failed under full-solution
parallel load while passing in isolation. Both are removed; no production code
changed.

1. Assertion shape. failures.ShouldBeEmpty() assumed at most ONE apply-boundary
   clear can land inside a single evaluation, so the evaluator's one-shot retry
   always suffices. Under contention two can land and the retry legitimately
   exhausts. The test now asserts the invariant the retry actually guarantees and
   which is timing-independent: no raw disposed-script failure ESCAPES the retry.
   Every failure must be the documented exhaustion outcome ("evaluator disposed
   during evaluation") and never the pre-fix generic escape ("script threw:
   Cannot access a disposed object..."), plus a deliberately loose bound on the
   exhaustion rate so the check cannot go vacuous.

2. Workload shape. The fixed 12x400 evaluations against a fixed 45s WaitAsync
   budget is CPU-dependent (every clear forces a recompile). Four concurrent
   instances of this class reproduced a hard TimeoutException 4/4 - the likely
   real shape of the reported load failure. The loops are now duration-bounded
   (10s race window or 400 iterations, whichever first); the 45s WaitAsync stays
   purely as a hang detector.

Renamed to Evaluate_racing_ClearCompiledScripts_never_leaks_a_raw_disposed_failure
so the name matches what it now asserts; the old name is cited in the doc-comment
for traceability.
2026-08-18 07:48:44 -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.