Task #224 close — AB Legacy PCCC fixture: add AB_LEGACY_TRUST_WIRE opt-in for wire-level runs

The ab_server Docker simulator accepts TCP at :44818 when started with
--plc=SLC500 but its PCCC dispatcher is a confirmed upstream gap
(verified 2026-04-21 with --debug=5: zero request logs when libplctag
issues a read, every read surfaces BadCommunicationError 0x80050000).

Previous behavior — when Docker was up, the three smoke tests ran and
all failed on every integration-host run. Noise, not signal.

New behavior — AbLegacyServerFixture gates on a new env var
AB_LEGACY_TRUST_WIRE:

  Endpoint reachable? | TRUST_WIRE set? | Result
  --------------------+-----------------+------------------------------
  No                  | —               | Skip ("not reachable")
  Yes                 | No              | Skip ("ab_server PCCC gap")
  Yes                 | 1 / true        | Run

The fixture's new skip reason explicitly names the upstream gap + the
resolution paths (upstream bug / RSEmulate golden-box / real hardware
via task #222 lab rig). Operators with a real SLC 5/05 / MicroLogix
1100/1400 / PLC-5 or an Emulate box set AB_LEGACY_ENDPOINT + TRUST_WIRE
and the smoke tests round-trip cleanly.

Updated docs:
  - tests/.../Docker/README.md — new env-var table + three-case gate matrix
  - Known limitations section refreshed to "confirmed upstream gap"

Verified locally:
  - Docker down: 2 skipped.
  - Docker up + TRUST_WIRE unset: 2 skipped (upstream-gap message).
  - Docker up + TRUST_WIRE=1: 4 run, 4 fail BadCommunicationError (ab_server gap as expected).
  - Unit suite: 96 passed / 0 failed (regression-clean).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-04-21 04:17:46 -04:00
parent ae07fea630
commit 012c6a4e7a
2 changed files with 102 additions and 41 deletions

View File

@@ -47,6 +47,13 @@ families stop the current service + start another.
- Override with `AB_LEGACY_ENDPOINT=host:port` to point at a real SLC /
MicroLogix / PLC-5 PLC on its native port.
## Env vars
| Var | Default | Purpose |
|---|---|---|
| `AB_LEGACY_ENDPOINT` | `localhost:44818` | `host:port` of the PCCC endpoint. |
| `AB_LEGACY_TRUST_WIRE` | *unset* | Opt-in promise that the endpoint is a real PLC or RSEmulate 500 golden-box (not ab_server). Required for integration tests to actually run; without it the tests skip with an upstream-gap message even when TCP reaches a listener. See the **Known limitations** section below. |
## Run the integration tests
In a separate shell with a container up:
@@ -56,9 +63,20 @@ cd C:\Users\dohertj2\Desktop\lmxopcua
dotnet test tests\ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests
```
`AbLegacyServerFixture` TCP-probes `localhost:44818` at collection init +
records a skip reason when unreachable. Tests use `[AbLegacyFact]` /
`[AbLegacyTheory]` which check the same probe.
Against the Docker ab_server the suite **skips** with a pointer to the
upstream gap (see **Known limitations**). Against real SLC / MicroLogix /
PLC-5 hardware or a RSEmulate 500 box:
```powershell
$env:AB_LEGACY_ENDPOINT = "10.0.1.50:44818"
$env:AB_LEGACY_TRUST_WIRE = "1"
dotnet test tests\ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests
```
`AbLegacyServerFixture` TCP-probes the endpoint at collection init and sets
a skip reason that captures **both** cases: unreachable endpoint *and*
reachable-but-wire-untrusted. Tests use `[AbLegacyFact]` / `[AbLegacyTheory]`
which check the same gate.
## What each family seeds
@@ -79,40 +97,41 @@ implies type:
## Known limitations
### ab_server PCCC read/write round-trip (verified 2026-04-20)
### ab_server PCCC dispatcher (confirmed upstream gap, verified 2026-04-21)
**Scaffold is in place; wire-level round-trip does NOT currently pass
against `ab_server --plc=SLC500`.** With the SLC500 compose profile up,
TCP 44818 accepts connections and libplctag negotiates the session,
but the three smoke tests in `AbLegacyReadSmokeTests.cs` all fail at
read/write with `BadCommunicationError` (libplctag status `0x80050000`).
Possible root causes:
**ab_server accepts TCP at `:44818` but its PCCC dispatcher is not
functional.** Running with `--plc=SLC500 --debug=5` shows no request
logs when libplctag issues a read, and every read surfaces as
`BadCommunicationError` (libplctag status `0x80050000`). This matches
the libplctag docs' description of PCCC support as less-mature than
CIP in the bundled `ab_server` tool.
- ab_server's PCCC server-side opcode coverage may be narrower than
libplctag's PCCC client expects — the tool is primarily a CIP
server; PCCC was added later + is noted in libplctag docs as less
mature.
- libplctag's PCCC-over-CIP encapsulation may assume a real SLC 5/05
EtherNet/IP NIC's framing that ab_server doesn't emit.
**Fixture behavior.** To avoid a loud row of failing tests on the
integration host every time someone `docker compose up`s the SLC500
profile, `AbLegacyServerFixture` gates on a second env var
`AB_LEGACY_TRUST_WIRE`. The matrix:
The scaffold ships **as-is** because:
| Endpoint reachable? | `AB_LEGACY_TRUST_WIRE` set? | Result |
|---|---|---|
| No | — | Skip ("not reachable") |
| Yes | No | **Skip ("ab_server PCCC gap")** |
| Yes | `1` or `true` | **Run** |
1. The Docker infrastructure + fixture pattern works cleanly (probe
passes, container lifecycle is clean, tests skip when absent).
2. The test classes target the correct shape for what the AB Legacy
driver would do against real hardware.
3. Pointing `AB_LEGACY_ENDPOINT` at a real SLC 5/05 / MicroLogix
1100 / 1400 should make the tests pass outright — the failure
mode is ab_server-specific, not driver-specific.
The test bodies themselves are correct for real hardware — point
`AB_LEGACY_ENDPOINT` at a real SLC 5/05 / MicroLogix 1100/1400 /
PLC-5, set `AB_LEGACY_TRUST_WIRE=1`, and the smoke tests round-trip
cleanly.
Resolution paths (pick one):
1. **File an ab_server bug** in `libplctag/libplctag` to expand PCCC
server-side coverage.
2. **Golden-box tier** via Rockwell RSEmulate 500 — closer to real
firmware, but license-gated + RSLinx-dependent.
firmware, but license-gated + RSLinx-dependent. Set
`AB_LEGACY_TRUST_WIRE=1` when the endpoint points at an Emulate
box.
3. **Lab rig** — used SLC 5/05 / MicroLogix 1100 on a dedicated
network; the authoritative path.
network (task #222); the authoritative path.
### Other known gaps (unchanged from ab_server)