chore: organize solution into module folders (Core/Server/Drivers/Client/Tooling)
Group all 69 projects into category subfolders under src/ and tests/ so the Rider Solution Explorer mirrors the module structure. Folders: Core, Server, Drivers (with a nested Driver CLIs subfolder), Client, Tooling. - Move every project folder on disk with git mv (history preserved as renames). - Recompute relative paths in 57 .csproj files: cross-category ProjectReferences, the lib/ HintPath+None refs in Driver.Historian.Wonderware, and the external mxaccessgw refs in Driver.Galaxy and its test project. - Rebuild ZB.MOM.WW.OtOpcUa.slnx with nested solution folders. - Re-prefix project paths in functional scripts (e2e, compliance, smoke SQL, integration, install). Build green (0 errors); unit tests pass. Docs left for a separate pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
# ab_server container for the AB CIP integration suite.
|
||||
#
|
||||
# ab_server is a C program in libplctag/libplctag under src/tools/ab_server.
|
||||
# We clone at a pinned commit, build just the ab_server target via CMake,
|
||||
# and copy the resulting binary into a slim runtime stage so the published
|
||||
# image stays small (~60MB vs ~350MB for the build stage).
|
||||
|
||||
# -------- stage 1: build ab_server from source --------
|
||||
FROM debian:bookworm-slim AS build
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
git \
|
||||
build-essential \
|
||||
cmake \
|
||||
ca-certificates \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Pinned tag matches the `ab_server` version AbServerFixture + CI treat as
|
||||
# canonical. Bump deliberately alongside a driver-side change that needs
|
||||
# something newer.
|
||||
ARG LIBPLCTAG_TAG=release
|
||||
RUN git clone --depth 1 --branch "${LIBPLCTAG_TAG}" https://github.com/libplctag/libplctag.git /src
|
||||
|
||||
WORKDIR /src
|
||||
RUN cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \
|
||||
&& cmake --build build --target ab_server --parallel
|
||||
|
||||
# -------- stage 2: runtime --------
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
LABEL org.opencontainers.image.source="https://github.com/dohertj2/lmxopcua" \
|
||||
org.opencontainers.image.description="libplctag ab_server for OtOpcUa AB CIP driver integration tests"
|
||||
|
||||
# libplctag's ab_server is statically linked against libc / libstdc++ on
|
||||
# Debian bookworm; no runtime dependencies beyond what the slim image
|
||||
# already has.
|
||||
COPY --from=build /src/build/bin_dist/ab_server /usr/local/bin/ab_server
|
||||
|
||||
EXPOSE 44818
|
||||
|
||||
# docker-compose.yml overrides the command with per-family flags.
|
||||
CMD ["ab_server", "--plc=ControlLogix", "--path=1,0", "--port=44818", \
|
||||
"--tag=TestDINT:DINT[1]", "--tag=TestREAL:REAL[1]", "--tag=TestBOOL:BOOL[1]"]
|
||||
@@ -0,0 +1,89 @@
|
||||
# AB CIP integration-test fixture — `ab_server` (Docker)
|
||||
|
||||
[libplctag](https://github.com/libplctag/libplctag)'s `ab_server` — a
|
||||
MIT-licensed C program that emulates a ControlLogix / CompactLogix CIP
|
||||
endpoint over EtherNet/IP. Docker is the only supported launch path;
|
||||
`ab_server` ships as a source-only tool under libplctag's
|
||||
`src/tools/ab_server/` so the Dockerfile's multi-stage build is the only
|
||||
reproducible way to get a working binary across developer boxes. A fresh
|
||||
clone needs Docker Desktop and nothing else.
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| [`Dockerfile`](Dockerfile) | Multi-stage: build from libplctag at pinned tag → copy binary into `debian:bookworm-slim` runtime image |
|
||||
| [`docker-compose.yml`](docker-compose.yml) | One service per family (`controllogix` / `compactlogix` / `micro800` / `guardlogix`); all bind `:44818` |
|
||||
|
||||
## Run
|
||||
|
||||
From the repo root:
|
||||
|
||||
```powershell
|
||||
# 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:
|
||||
|
||||
```powershell
|
||||
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)
|
||||
- Override with `AB_SERVER_ENDPOINT=host:port` to point at a real PLC.
|
||||
|
||||
## Run the integration tests
|
||||
|
||||
In a separate shell with a container up:
|
||||
|
||||
```powershell
|
||||
cd C:\Users\dohertj2\Desktop\lmxopcua
|
||||
dotnet test tests\ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests
|
||||
```
|
||||
|
||||
`AbServerFixture` TCP-probes `localhost:44818` at collection init +
|
||||
records a skip reason when unreachable, so tests stay green on a fresh
|
||||
clone without the container running. Tests use `[AbServerFact]` /
|
||||
`[AbServerTheory]` which check the same probe.
|
||||
|
||||
## 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_server` covers 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`](../../../docs/drivers/AbServer-Test-Fixture.md)
|
||||
for the full coverage map.
|
||||
|
||||
## References
|
||||
|
||||
- [libplctag on GitHub](https://github.com/libplctag/libplctag)
|
||||
- [`docs/drivers/AbServer-Test-Fixture.md`](../../../docs/drivers/AbServer-Test-Fixture.md) — coverage map
|
||||
- [`docs/v2/dev-environment.md`](../../../docs/v2/dev-environment.md) §Docker fixtures
|
||||
@@ -0,0 +1,97 @@
|
||||
# AB CIP integration-test fixture — ab_server (libplctag).
|
||||
#
|
||||
# One service per family. All bind :44818 on the host; only one runs at a
|
||||
# time. Commands mirror the CLI args AbServerProfile.cs constructs for the
|
||||
# native-binary path.
|
||||
#
|
||||
# Usage:
|
||||
# docker compose --profile controllogix up
|
||||
# docker compose --profile compactlogix up
|
||||
# docker compose --profile micro800 up
|
||||
# docker compose --profile guardlogix up
|
||||
services:
|
||||
controllogix:
|
||||
profiles: ["controllogix"]
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: otopcua-ab-server:libplctag-release
|
||||
container_name: otopcua-ab-server-controllogix
|
||||
restart: "no"
|
||||
ports:
|
||||
- "44818:44818"
|
||||
command: [
|
||||
"ab_server",
|
||||
"--plc=ControlLogix",
|
||||
"--path=1,0",
|
||||
"--port=44818",
|
||||
"--tag=TestDINT:DINT[1]",
|
||||
"--tag=TestREAL:REAL[1]",
|
||||
"--tag=TestBOOL:BOOL[1]",
|
||||
"--tag=TestSINT:SINT[1]",
|
||||
"--tag=TestString:STRING[1]",
|
||||
"--tag=TestArray:DINT[16]"
|
||||
]
|
||||
|
||||
compactlogix:
|
||||
profiles: ["compactlogix"]
|
||||
image: otopcua-ab-server:libplctag-release
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: otopcua-ab-server-compactlogix
|
||||
restart: "no"
|
||||
ports:
|
||||
- "44818:44818"
|
||||
# ab_server doesn't distinguish CompactLogix from ControlLogix — no
|
||||
# dedicated --plc mode. Driver-side ConnectionSize cap is enforced
|
||||
# separately (see AbServerProfile.CompactLogix Notes).
|
||||
command: [
|
||||
"ab_server",
|
||||
"--plc=ControlLogix",
|
||||
"--path=1,0",
|
||||
"--port=44818",
|
||||
"--tag=TestDINT:DINT[1]",
|
||||
"--tag=TestREAL:REAL[1]",
|
||||
"--tag=TestBOOL:BOOL[1]"
|
||||
]
|
||||
|
||||
micro800:
|
||||
profiles: ["micro800"]
|
||||
image: otopcua-ab-server:libplctag-release
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: otopcua-ab-server-micro800
|
||||
restart: "no"
|
||||
ports:
|
||||
- "44818:44818"
|
||||
# ab_server does have a Micro800 plc mode (unconnected-only, empty path).
|
||||
command: [
|
||||
"ab_server",
|
||||
"--plc=Micro800",
|
||||
"--port=44818",
|
||||
"--tag=TestDINT:DINT[1]",
|
||||
"--tag=TestREAL:REAL[1]"
|
||||
]
|
||||
|
||||
guardlogix:
|
||||
profiles: ["guardlogix"]
|
||||
image: otopcua-ab-server:libplctag-release
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: otopcua-ab-server-guardlogix
|
||||
restart: "no"
|
||||
ports:
|
||||
- "44818:44818"
|
||||
# ab_server has no safety subsystem — _S suffix triggers driver-side
|
||||
# classification only.
|
||||
command: [
|
||||
"ab_server",
|
||||
"--plc=ControlLogix",
|
||||
"--path=1,0",
|
||||
"--port=44818",
|
||||
"--tag=TestDINT:DINT[1]",
|
||||
"--tag=SafetyDINT_S:DINT[1]"
|
||||
]
|
||||
Reference in New Issue
Block a user