From 326b22a7bad91106fa31c3f178d051216c809d59 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Wed, 15 Jul 2026 03:28:04 -0400 Subject: [PATCH 1/2] fix(abcip-tests): expression-body KnownProfiles.All to fix static-init NRE KnownProfiles.All used a { get; } = [...] initialiser declared textually before the static readonly profile fields it references, so C# static-init order captured an all-null list. ForFamily() then NRE'd on p.Family, faulting AbServerFixture..ctor and blocking the whole AbCip.IntegrationTests suite. Expression-body it so it evaluates on access, after the fields are set. Live-verified against the controllogix fixture: suite goes 6F/1P/3skip -> 10 pass / 0 fail / 3 skip (skips = emulator-mode tests). Integration-sweep follow-up #1 (archreview/plans/INTEGRATION-SWEEP-STATUS.md). --- .../AbServerProfile.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbServerProfile.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbServerProfile.cs index 04bb1509..066bfd50 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbServerProfile.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbServerProfile.cs @@ -27,7 +27,11 @@ public sealed record AbServerProfile( public static class KnownProfiles { /// Gets all known server profiles. - public static IReadOnlyList All { get; } = + /// Expression-bodied (evaluated on access) so it observes the + /// static readonly profile fields below after they are initialised; + /// a { get; } = initialiser here runs in textual order — before those + /// fields — and would capture an all-null list. + public static IReadOnlyList All => [ControlLogix, CompactLogix, Micro800, GuardLogix]; /// Gets the ControlLogix profile. From 2ba867b0f8f3193c22b731d5d0014bf0c5b25304 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Wed, 15 Jul 2026 03:28:24 -0400 Subject: [PATCH 2/2] docs(archreview): mark integration-sweep follow-up #1 (AbCip static-init) done --- archreview/plans/INTEGRATION-SWEEP-STATUS.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/archreview/plans/INTEGRATION-SWEEP-STATUS.md b/archreview/plans/INTEGRATION-SWEEP-STATUS.md index 39c59ed7..463cc298 100644 --- a/archreview/plans/INTEGRATION-SWEEP-STATUS.md +++ b/archreview/plans/INTEGRATION-SWEEP-STATUS.md @@ -24,7 +24,7 @@ need sudo to create new ones — I deployed FOCAS to `~/otopcua-focas` on the ho | **Host** | ⚠️ **105/117** (7F, 5 skip) | 7 heavy 2-node deploy/failover E2E time out (20–45 s) under amd64-emulated SQL; 5 LDAP-backed skip | | **TwinCAT** | ⏭️ 13 skip | no TC3 XAR fixture exists (expected clean-skip) | | **Modbus** (dl205 / mitsubishi / s7_1500 / exception_injection) | ❌ 8F/5F/3F/8F | sim-behavior drift — see below | -| **AbCip** | ❌ 6F/1P/3skip | test-harness static-init-order bug — see below | +| **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 | @@ -85,7 +85,10 @@ and never run, so they've bit-rotted in several distinct ways. ## Follow-up backlog (distinct, not one fix) -1. **AbCip static-init bug** — trivial always-fail test bug. Expression-body `KnownProfiles.All`. *Clean win.* +1. ~~**AbCip static-init bug** — trivial always-fail test bug. Expression-body `KnownProfiles.All`.~~ + ✅ **DONE 2026-07-15** (commit `326b22a7`, PR #446). Live-verified against the controllogix fixture: + suite went **6F/1P/3skip → 10 pass / 0 fail / 3 skip** (skips = emulator-mode tests needing a different + fixture mode). 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).