Phase 3 PR 32 — Multi-driver integration test #31

Merged
dohertj2 merged 1 commits from phase-3-pr32-multi-driver-integration into v2 2026-04-18 15:34:17 -04:00
Owner

Closes LMX follow-up #6. Exercises two IDriver instances on one DriverHost end-to-end through the OPC UA server.

What it proves

Server.Tests/MultipleDriverInstancesIntegrationTests.cs registers two StubDriver instances (alpha + beta) with distinct DriverInstanceIds, boots the full OpcUaApplicationHost, and connects a real OPC UA client:

  1. Namespace isolation — each driver's URI (urn:OtOpcUa:alpha / urn:OtOpcUa:beta) resolves to a distinct index in the client's NamespaceUris. Proves DriverNodeManager's per-driver namespaceUris wiring actually produces two separate INodeManager registrations.
  2. Subtree isolation — browsing alpha's root returns AlphaFolder and does NOT leak BetaFolder, and vice versa. This is the assertion that catches a cross-driver routing regression the v1 single-driver code path couldn't surface. If a future refactor flattens both drivers into a shared namespace, shouldNotContain fails cleanly.
  3. Read routing — alpha's ReadAsync returns 42 while beta's returns 99. A misroute would surface as 99 showing up on an alpha node id or vice versa — concrete failure mode, not abstract.

Design

StubDriver is parameterized on (DriverInstanceId, folderName, readValue) so the same class constructs both instances without copy-paste. Each driver exposes a single folder with one variable.

Test posture

  • Server.Tests Integration: 3 new tests pass; existing OpcUaServerIntegrationTests stays green (single-driver case still exercised there).
  • Server.Tests Unit: still 43 / 0.
  • No production code changes — pure additive test.

Deferred

Multi-driver alarm-event case (two drivers each raising GalaxyAlarmEvent, assert each condition lands on its owning instance's condition node). Needs a stub IAlarmSource and is scoped for a separate PR.

Closes LMX follow-up #6. Exercises two `IDriver` instances on one `DriverHost` end-to-end through the OPC UA server. ## What it proves `Server.Tests/MultipleDriverInstancesIntegrationTests.cs` registers two `StubDriver` instances (`alpha` + `beta`) with distinct `DriverInstanceId`s, boots the full `OpcUaApplicationHost`, and connects a real OPC UA client: 1. **Namespace isolation** — each driver's URI (`urn:OtOpcUa:alpha` / `urn:OtOpcUa:beta`) resolves to a distinct index in the client's `NamespaceUris`. Proves `DriverNodeManager`'s per-driver `namespaceUris` wiring actually produces two separate `INodeManager` registrations. 2. **Subtree isolation** — browsing `alpha`'s root returns `AlphaFolder` and does NOT leak `BetaFolder`, and vice versa. This is the assertion that catches a cross-driver routing regression the v1 single-driver code path couldn't surface. If a future refactor flattens both drivers into a shared namespace, `shouldNotContain` fails cleanly. 3. **Read routing** — alpha's `ReadAsync` returns 42 while beta's returns 99. A misroute would surface as 99 showing up on an alpha node id or vice versa — concrete failure mode, not abstract. ## Design `StubDriver` is parameterized on `(DriverInstanceId, folderName, readValue)` so the same class constructs both instances without copy-paste. Each driver exposes a single folder with one variable. ## Test posture - Server.Tests Integration: **3 new tests pass**; existing `OpcUaServerIntegrationTests` stays green (single-driver case still exercised there). - Server.Tests Unit: still 43 / 0. - No production code changes — pure additive test. ## Deferred Multi-driver alarm-event case (two drivers each raising `GalaxyAlarmEvent`, assert each condition lands on its owning instance's condition node). Needs a stub `IAlarmSource` and is scoped for a separate PR.
dohertj2 added 1 commit 2026-04-18 15:34:15 -04:00
No production code changes — pure additive test. Server.Tests Integration: 3 new tests pass; existing OpcUaServerIntegrationTests stays green (single-driver case still exercised there). Full Server.Tests Unit still 43 / 0. Deferred: multi-driver alarm-event case (two drivers each raising a GalaxyAlarmEvent, assert each condition lands on its owning instance's condition node) — needs a stub IAlarmSource and is worth its own focused PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dohertj2 merged commit a9357600e7 into v2 2026-04-18 15:34:17 -04:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#31