AB CIP integration-test fixture — ab_server (Docker)
libplctag's ab_server — a
MIT-licensed C program that emulates a ControlLogix / CompactLogix CIP
endpoint over EtherNet/IP. Docker is the primary launcher because
ab_server otherwise requires per-OS build-from-source (libplctag ships
it as a source-only tool under src/tools/ab_server/). The existing
native-binary-on-PATH path via AbServerFixture.LocateBinary stays as a
fallback for contributors who've already built it locally.
| File | Purpose |
|---|---|
Dockerfile |
Multi-stage: build from libplctag at pinned tag → copy binary into debian:bookworm-slim runtime image |
docker-compose.yml |
One service per family (controllogix / compactlogix / micro800 / guardlogix); all bind :44818 |
Run
From the repo root:
# ControlLogix — widest-coverage profile
docker compose -f tests\ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests\Docker\docker-compose.yml --profile controllogix up
# Per-family
docker compose -f tests\...\Docker\docker-compose.yml --profile compactlogix up
docker compose -f tests\...\Docker\docker-compose.yml --profile micro800 up
docker compose -f tests\...\Docker\docker-compose.yml --profile guardlogix up
Detached + stop:
docker compose -f tests\...\Docker\docker-compose.yml --profile controllogix up -d
docker compose -f tests\...\Docker\docker-compose.yml --profile controllogix down
First run builds the image (~3-5 minutes — clones libplctag + compiles
ab_server + its dependencies). Subsequent runs are fast because the
multi-stage build layer-caches the checkout + compile.
Endpoint
- Default:
localhost:44818(EtherNet/IP standard; non-privileged) - No env-var override in the fixture today — add one if pointing at a real PLC becomes a use case.
Run the integration tests
In a separate shell with a container up:
cd C:\Users\dohertj2\Desktop\lmxopcua
dotnet test tests\ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests
AbServerFixture resolves ab_server off PATH — but when the Docker
container is running, the tests dial 127.0.0.1:44818 directly through
the libplctag client so the on-PATH lookup is effectively informational.
Tests skip via [AbServerFact] / [AbServerTheory] when the binary
isn't on PATH + the container's not running.
What each family seeds
Tag sets match AbServerProfile.cs exactly — changing seeds in one
place means updating both.
| Family | Seeded tags | Notes |
|---|---|---|
| ControlLogix | TestDINT TestREAL TestBOOL TestSINT TestString TestArray |
Widest-coverage; PR 9 baseline. UDT emulation missing from ab_server |
| CompactLogix | TestDINT TestREAL TestBOOL |
Narrow ConnectionSize cap enforced driver-side; ab_server accepts any size |
| Micro800 | TestDINT TestREAL |
ab_server has no micro800 mode; falls back to controllogix emulation |
| GuardLogix | TestDINT SafetyDINT_S |
ab_server has no safety subsystem; _S suffix triggers driver-side classification only |
Known limitations
- No UDT / CIP Template Object emulation —
ab_servercovers atomic types only. UDT reads + task #194 whole-UDT optimization verify via unit tests with golden byte buffers. - Family-specific quirks trust driver-side code — ab_server emulates a generic Logix CPU; the ConnectionSize cap, empty-path unconnected mode, and safety-partition write rejection all need lab rigs for wire-level proof.
See docs/drivers/AbServer-Test-Fixture.md
for the full coverage map.
Native-binary fallback
AbServerFixture.LocateBinary checks PATH for ab_server /
ab_server.exe. Build from source via
libplctag's build docs
and drop the binary on PATH to use it. Kept for contributors who've
already built libplctag locally. Docker is the reproducible path.
References
- libplctag on GitHub
docs/drivers/AbServer-Test-Fixture.md— coverage mapdocs/v2/dev-environment.md§Docker fixtures