fix(opcuaserver-tests): supply client cert-store paths + adapt to SDK read-throws
v2-ci / build (pull_request) Successful in 7m23s
v2-ci / unit-tests (pull_request) Failing after 15m33s

OpcUaServer.IntegrationTests was 4F. Two distinct, previously-masked issues:

1. Cert-store gap: the in-test client SecurityConfiguration used a bare
   new SecurityConfiguration()/CertificateIdentifier(), so ValidateAsync threw
   'TrustedIssuerCertificates StorePath must be specified' before any connect.
   Added TestClientSecurity helper building Directory own/issuer/trusted/rejected
   stores under a throwaway temp PKI dir (mirrors DefaultApplicationConfigurationFactory);
   wired into DualEndpointTests + SubscriptionSurvivalTests.

2. Fixing #1 unmasked an SDK-version drift: the 1.5.378 node-cache read path
   throws ServiceResultException(BadNodeIdUnknown) for a removed node instead of
   returning a bad DataValue. The two subscription-survival assertions now expect
   the throw via Should.ThrowAsync. Behavior under test (removed node -> unknown)
   is unchanged; only the delivery mechanism differs.

Suite 4F -> 4/4 green. Integration-sweep follow-up #5.
This commit is contained in:
Joseph Doherty
2026-07-15 03:34:14 -04:00
parent c1482802d4
commit de9d9697fd
4 changed files with 108 additions and 44 deletions
+15 -5
View File
@@ -27,7 +27,7 @@ need sudo to create new ones — I deployed FOCAS to `~/otopcua-focas` on the ho
| **AbCip** | ✅ 10P/3skip (was 6F/1P/3skip) | static-init-order bug FIXED 2026-07-15 (`326b22a7`) — see below |
| **FOCAS** | ❌ 9F/1P | tests assume a localhost-colocated mock — see below |
| **AbLegacy** | ❌ 4F | no AbLegacy sim fixture deployed to the host |
| **OpcUaServer** | 4F | test-harness cert-store config gap |
| **OpcUaServer** | ✅ 4/4 (was 4F) | cert-store gap + SDK read-throws drift FIXED 2026-07-15 — see below |
### Headline conclusion
**No OtOpcUa production regression.** Every failure is **pre-existing test/fixture infrastructure rot** in
@@ -66,9 +66,13 @@ and never run, so they've bit-rotted in several distinct ways.
- **AbLegacy** — 4F on `StatusCode` because **no AbLegacy sim exists on the host** (no `/opt/otopcua-ablegacy`,
none deployed). Reads return Bad. **Fix:** deploy an AbLegacy fixture (check `tests/.../AbLegacy.IntegrationTests/Docker/`).
- **OpcUaServer** — 4F on `Opc.Ua.ServiceResultException : TrustedIssuerCertificates StorePath must be
specified` — the in-test OPC UA server config omits a cert-store path. Test-harness config gap, not a
fixture. **Fix:** supply the trusted-issuer StorePath in the harness's `ApplicationConfiguration`.
- **OpcUaServer** — **FIXED 2026-07-15** (PR #447). Was 4F on `Opc.Ua.ServiceResultException :
TrustedIssuerCertificates StorePath must be specified` — the in-test *client* `SecurityConfiguration`
omitted the trusted-issuer/peer/rejected store paths that `ValidateAsync` requires. Fix: `TestClientSecurity`
helper rooting Directory stores at a throwaway PKI dir (mirrors `DefaultApplicationConfigurationFactory`).
Fixing it unmasked a second drift — the 1.5.378 node-cache read path throws
`ServiceResultException(BadNodeIdUnknown)` for a removed node rather than returning a bad `DataValue`;
the two subscription-survival assertions now use `Should.ThrowAsync`. Suite **4F → 4/4 green**.
- **Host** — largely healthy (105/117). 7 failures are the heavy 2-node deploy/failover/reconnect E2E tests
(`DeployHappyPathTests`, `FailoverDuringDeployTests`, `DriverReconnectE2eTests`,
@@ -92,7 +96,13 @@ and never run, so they've bit-rotted in several distinct ways.
2. **Modbus non-standard profiles** — pin pymodbus in the fixture Dockerfile (or update expected values for 4.x).
3. **FOCAS** — reconcile the 127.0.0.1-mock topology with the remote-fixture model.
4. **AbLegacy** — deploy an AbLegacy sim fixture (none on host).
5. **OpcUaServer** — supply cert-store StorePath in the harness config.
5. ~~**OpcUaServer** — supply cert-store StorePath in the harness config.~~
✅ **DONE 2026-07-15** (PR #447). Added `TestClientSecurity` helper building a validated client
`SecurityConfiguration` with Directory own/issuer/trusted/rejected stores under a throwaway PKI dir
(mirrors `DefaultApplicationConfigurationFactory`); wired into both `DualEndpointTests` +
`SubscriptionSurvivalTests`. That unmasked a **second** drift: the 1.5.378 node-cache read path
*throws* `ServiceResultException(BadNodeIdUnknown)` for a removed node instead of returning a bad
`DataValue` — updated the two subscription-survival assertions to `Should.ThrowAsync`. Suite **4F → 4/4**.
6. **Host** — replace `bitnami/openldap:2.6` (image gone); run E2E on real SQL or raise deadlines.
7. **Fixture deployment gap** — FOCAS + AbLegacy fixtures aren't on the host at `/opt/otopcua-*`; the sweep
requires deploying them (and `/opt` needs sudo — used `~/otopcua-<driver>` for FOCAS).