Files
lmxopcua/docs/v1/drivers/Galaxy-Test-Fixture.md
Joseph Doherty 006af51768 docs: post-PR-7.2 cleanup — audit + three-track scrub
Audit (three parallel agent passes) found 43 markdown files carrying
stale references to the deleted Galaxy.Host/Proxy/Shared projects
after the v2-mxgw merge. This commit lands the prioritized fixes.

Track 1 — high-traffic in-place rewrites (3 files, ~454 lines deleted)
- README.md (202 → 91 lines): drops .NET 4.8 / x86 / TopShelf install
  text; leads with the multi-driver .NET 10 server identity and points
  at scripts/install/Install-Services.ps1 and the parity rig.
- docs/v2/driver-specs.md §1 Galaxy (~289 → ~66 lines): replaces the
  Tier-C out-of-process spec with a Tier-A in-process description
  matching the current GalaxyDriver code, with the four-section
  GalaxyDriverOptions JSON shape pulled verbatim from
  Config/GalaxyDriverOptions.cs.
- docs/drivers/Galaxy.md (211 → 92 lines): full rewrite around the
  current Browse/Runtime/Health/Config sub-folders.

Track 2 — historical banners (5 files)
- lmx_mxgw.md, lmx_mxgw_impl.md, lmx_backend.md,
  docs/v2/Galaxy.ParityMatrix.md,
  docs/v2/implementation/phase-2-galaxy-out-of-process.md each get a
  " Completed 2026-04-30 — historical record" banner block. lmx_mxgw.md
  also fixes two dead links (`docs/Galaxy.Driver.md` and
  `docs/v2/Galaxy.Driver.md`) → `docs/drivers/Galaxy.md`.

Track 3 — v1 archive sweep (10 git mv + 1 new index + 2 in-place scrubs)
- Moved 10 v1 docs under docs/v1/ preserving subpath structure:
  AlarmTracking, Configuration, DataTypeMapping, HistoricalDataAccess,
  Subscriptions (top-level); drivers/Galaxy-Repository,
  drivers/Galaxy-Test-Fixture; reqs/GalaxyRepositoryReqs,
  reqs/MxAccessClientReqs, reqs/ServiceHostReqs.
- New docs/v1/README.md is the shared archive banner + per-file table.
- docs/README.md repointed to the v1 paths and updated to reflect the
  v2 two-process deploy shape (Server + Admin + optional
  OtOpcUaWonderwareHistorian).
- docs/v2/Galaxy.ParityRig.md got a historical banner + four inline
  scrubs marking the OtOpcUaGalaxyHost service / Driver.Galaxy.Host
  EXE / Driver.Galaxy.ParityTests project as deleted-in-PR-7.2.

The repo's live-reading surface (README + CLAUDE.md + docs/v2/) now
describes only the post-PR-7.2 architecture. v1 docs are preserved as
a labelled archive under docs/v1/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 08:59:59 -04:00

166 lines
7.2 KiB
Markdown

# Galaxy test fixture
Coverage map + gap inventory for the Galaxy driver — out-of-process Host
(net48 x86 MXAccess COM) + Proxy (net10) + Shared protocol.
**TL;DR: Galaxy has the richest test harness in the fleet** — real Host
subprocess spawn, real ZB SQL queries, IPC parity checks against the v1
LmxProxy reference, + live-smoke tests when MXAccess runtime is actually
installed. Gaps are live-plant + failover-shaped: the E2E suite covers the
representative ~50-tag deployment but not large-site discovery stress, real
Rockwell/Siemens PLC enumeration through MXAccess, or ZB SQL Always-On
replica failover.
## What the fixture is
Multi-project test topology:
- **E2E parity** —
`tests/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.E2E/ParityFixture.cs` spawns the
production `OtOpcUa.Driver.Galaxy.Host.exe` as a subprocess, opens the
named-pipe IPC, connects `GalaxyProxyDriver` + runs hierarchy / stability
parity tests against both.
- **Host.Tests** —
`tests/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Host.Tests/` — direct Host process
testing (18+ test classes covering alarm discovery, AVEVA prerequisite
checks, IPC dispatcher, alarm tracker, probe manager, historian
cluster/quality/wiring, history read, OPC UA attribute mapping,
subscription lifecycle, reconnect, multi-host proxy, ADS address routing,
expression evaluation) + `GalaxyRepositoryLiveSmokeTests` that hit real
ZB SQL.
- **Proxy.Tests** — `GalaxyProxyDriver` client contract tests.
- **Shared.Tests** — shared protocol + address model.
- **TestSupport** — test helpers reused across the above.
## How tests skip
- **E2E parity**: `ParityFixture.SkipIfUnavailable()` runs at class init and
checks Windows-only, ZB SQL reachable on `localhost:1433`, Host EXE built
in the expected `bin/` folder. Any miss → tests skip.
- **Live-smoke** (`GalaxyRepositoryLiveSmokeTests`): `Assert.Skip` when ZB
unreachable. A `per project_galaxy_host_installed` memory on this repo's
dev box notes the MXAccess runtime is installed. The pipe ACL allows the
configured SID outright; elevation of the caller doesn't matter because
the per-connection SID check in `PipeServer.VerifyCaller` only compares
user SIDs (not group membership or integrity level).
- **Unit** tests (Shared, Proxy contract, most Host.Tests) have no skip —
they run anywhere.
## What it actually covers
### E2E parity suite
- `HierarchyParityTests` — Host address-space hierarchy vs v1 LmxProxy
reference (same ZB, same Galaxy, same shape)
- `StabilityFindingsRegressionTests` — probe subscription failure
handling + host-status mutation guard from the v1 stability findings
backlog
### Host.Tests (representative)
- Alarm discovery → subsystem setup
- AVEVA prerequisite checks (runtime installed, platform deployed, etc.)
- IPC dispatcher — request/response routing over the named pipe
- Alarm tracker state machine
- Probe manager — per-runtime probe subscription + reconnect
- Historian cluster / quality / wiring — Aveva Historian integration
- OPC UA attribute mapping
- Subscription lifecycle + reconnect
- Multi-host proxy routing
- ADS address routing + expression evaluation (Galaxy's legacy expression
language)
### Live-smoke
- `GalaxyRepositoryLiveSmokeTests` — real SQL against ZB database, verifies
the ZB schema + `LocalPlatform` scope filter + change-detection query
shape match production.
### Capability surfaces hit
All of them: `IDriver`, `IReadable`, `IWritable`, `ITagDiscovery`,
`ISubscribable`, `IHostConnectivityProbe`, `IPerCallHostResolver`,
`IAlarmSource`, `IHistoryProvider`. Galaxy is the only driver where every
interface sees both contract + real-integration coverage.
## What it does NOT cover
### 1. MXAccess COM by default
The E2E parity suite backs subscriptions via the DB-only path; MXAccess COM
integration opts in via a separate live-smoke. So "does the MXAccess STA
pump correctly handle real Wonderware runtime events" is exercised only
when the operator runs live smoke on a machine with MXAccess installed.
### 2. Real Rockwell / Siemens PLC enumeration
Galaxy runtime talks to PLCs through MXAccess (Device Integration Objects).
The CI parity suite uses a representative ~50-tag deployment; large sites
(1000+ tag hierarchies, multi-Galaxy replication, deeply-nested templates)
are not stressed.
### 3. ZB SQL Always-On failover
Live-smoke hits a single SQL instance. Real production ZB often runs on
Always-On availability groups; replica failover behavior is not tested.
### 4. Galaxy replication / backup-restore
Galaxy supports backup + partial replication across platforms — these
rewrite the ZB schema in ways that change the contained_name vs tag_name
mapping. Not exercised.
### 5. Historian failover
Aveva Historian can be clustered. `historian cluster / quality` tests
verify the cluster-config query; they don't exercise actual failover
(primary dies → secondary takes over mid-HistoryRead).
### 6. AVEVA runtime version matrix
MXAccess COM contract varies subtly across System Platform 2017 / 2020 /
2023. The live-smoke runs against whatever version is installed on the dev
box; CI has no AVEVA installed at all (licensing + footprint).
## When to trust the Galaxy suite, when to reach for a live plant
| Question | E2E parity | Live-smoke | Real plant |
| --- | --- | --- | --- |
| "Does Host spawn + IPC round-trip work?" | yes | yes | yes |
| "Does the ZB schema query match production shape?" | partial | yes | yes |
| "Does MXAccess COM handle runtime reconnect correctly?" | no | yes | yes |
| "Does the driver scale to 1000+ tags on one Galaxy?" | no | partial | yes (required) |
| "Does historian failover mid-read return a clean error?" | no | no | yes (required) |
| "Does System Platform 2023's MXAccess differ from 2020?" | no | partial | yes (required) |
| "Does ZB Always-On replica failover preserve generation?" | no | no | yes (required) |
## Follow-up candidates
1. **System Platform 2023 live-smoke matrix** — set up a second dev box
running SP2023; run the same live-smoke against both to catch COM-contract
drift early.
2. **Synthetic large-site fixture** — script a ZB populator that creates a
1000-Equipment / 20000-tag hierarchy, run the parity suite against it.
Catches O(N) → O(N²) discovery regressions.
3. **Historian failover scripted test** — with a two-node AVEVA Historian
cluster, tear down primary mid-HistoryRead + verify the driver's failover
behavior + error surface.
4. **ZB Always-On CI** — SQL Server 2022 on Linux supports Always-On;
could stand up a two-replica group for replica-failover coverage.
This is already the best-tested driver; the remaining work is site-scale
+ production-topology coverage, not capability coverage.
## Key fixture / config files
- `tests/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.E2E/ParityFixture.cs` — E2E fixture
that spawns Host + connects Proxy
- `tests/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Host.Tests/GalaxyRepositoryLiveSmokeTests.cs`
— live ZB smoke with `Assert.Skip` gate
- `tests/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.TestSupport/` — shared helpers
- `docs/drivers/Galaxy.md` — COM bridge + STA pump + IPC architecture
- `docs/drivers/Galaxy-Repository.md` — ZB SQL reader + `LocalPlatform`
scope filter + change detection
- `docs/v2/aveva-system-platform-io-research.md` — MXAccess + Wonderware
background