AbServerProfileGate — static helper that reads `AB_SERVER_PROFILE` env var (defaults to "abserver") + exposes `SkipUnless(params string[] requiredProfiles)` matching the MODBUS_SIM_PROFILE pattern the DL205StringQuirkTests uses one directory over. Emulate-only tests call `AbServerProfileGate.SkipUnless("emulate")` at the top of each fact body; ab_server-default runs see them skip with a clear message pointing at the Emulate setup steps.
AbCipEmulateUdtReadTests — one test proving the #194 whole-UDT read optimization works against the real Logix Template Object, not just the golden byte buffers the unit suite uses. Builds an `AbCipDriverOptions` with a Structure tag `Motor1 : Motor_UDT` that has three declared members (Speed : DINT, Torque : REAL, Status : DINT), reads them via the `.Speed / .Torque / .Status` dotted-tag syntax, asserts the driver gets the grouped whole-UDT path + decodes each at the right offset. Required seed values documented inline + in LogixProject/README.md: Speed=1800, Torque=42.5f, Status=0x0001.
AbCipEmulateAlmdTests — one test proving the #177 ALMD projection fires `OnAlarmEvent` when a real ALMD instruction's `In` edge rises, not just the fake `InFaulted` timer edges the unit suite drives. Needs a `SimulateAlarm : BOOL` tag routed through `MainRoutine` ladder (`XIC SimulateAlarm OTE HighTempAlarm.In`) so the test case can pulse the input via the existing `IWritable.WriteAsync` path instead of scripting Emulate via its own socket. Alarm-projection options carry `EnableAlarmProjection = true` + 200 ms poll interval; a `TaskCompletionSource` gates the raise-event assertion with a 5 s deadline. Cleanup writes SimulateAlarm=false so consecutive runs start from known state.
LogixProject/README.md — the Studio 5000 project state the Emulate-tier tests depend on. Explains why L5X over ACD (text diff, reproducible import, no per-install state), the UDT + tag + routine structure, how to bring it up on the Emulate PC. Ships as a stub pending actual author + L5X export + commit; the README itself keeps the requirements visible so the L5X author has a checklist.
docs/drivers/AbServer-Test-Fixture.md — new §Logix Emulate golden-box tier section with the coverage-promotion table (ab_server / Emulate / hardware per gap), the setup-env-var recipe, the costs to accept (license, Hyper-V conflict, manual lifecycle). "When to trust" table extended from 3 columns (ab_server / unit / rig) to 4 (ab_server / unit / Logix Emulate / rig); two new rows for EtherNet/IP embedded-switch + redundant-chassis failover that even Emulate can't help with. Follow-up candidates list gets Logix Emulate as option 1 ahead of the pre-existing "extend ab_server upstream" + "stand up a lab rig". See-also file list gains AbServerProfileGate.cs + Docker/ + Emulate/ + LogixProject/README.md entries.
docs/v2/dev-environment.md — §C Integration host gains a Rockwell Studio 5000 Logix Emulate row: purpose (AB CIP golden-box tier closing UDT/ALMD/AOI/safety/ConnectionSize gaps), type (Windows-only, Hyper-V conflict matching TwinCAT XAR's constraint), port 44818, credentials note, owner split between integration-host admin for license+install and developer for per-session runtime start.
Verified: Emulate tests skip cleanly when AB_SERVER_PROFILE is unset — both `[SKIP]` with the operator-facing message pointing at the env-var setup. Whole-solution build 0 errors. Tests will transition from skip → pass once the L5X + Emulate PC land per #223.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
103 lines
4.2 KiB
Markdown
103 lines
4.2 KiB
Markdown
# Logix Emulate project stub
|
|
|
|
This folder holds the Studio 5000 project that Logix Emulate loads when running
|
|
the Emulate-tier integration tests
|
|
(`tests/.../AbCip.IntegrationTests/Emulate/*.cs`, gated on
|
|
`AB_SERVER_PROFILE=emulate`).
|
|
|
|
**Status today**: stub. The actual `.L5X` export isn't committed yet; once
|
|
the Emulate PC is running + a project with the required state exists,
|
|
export to L5X + drop it here as `OtOpcUaAbCipFixture.L5X`.
|
|
|
|
## Why L5X, not .ACD
|
|
|
|
Studio 5000 ships two save formats: `.ACD` (binary, the runtime project)
|
|
and `.L5X` (XML export). Ship the L5X because:
|
|
|
|
- Text format — reviewable in PR diffs, diffable in git
|
|
- Reproducible import across Studio 5000 versions
|
|
- Doesn't carry per-installation state (license watermarks, revision history)
|
|
|
|
Reconstruction workflow: Studio 5000 → open project → File → Save As
|
|
→ `.L5X`. On a fresh Emulate install: File → Open → select the L5X → it
|
|
rebuilds the ACD from the XML.
|
|
|
|
## Required project state
|
|
|
|
The Emulate-tier tests rely on this exact tag / UDT set. Missing any of
|
|
these makes the dependent test fail loudly (TagNotFound, wrong value,
|
|
wrong type), not skip silently — Emulate is a tier above the Docker
|
|
simulator; operators who opted into it get opt-in-level coverage
|
|
expectations.
|
|
|
|
### UDT definitions
|
|
|
|
| UDT name | Members | Notes |
|
|
|---|---|---|
|
|
| `Motor_UDT` | `Speed : DINT`, `Torque : REAL`, `Status : DINT` | Matches `AbCipUdtMemberLayoutTests` declared-layout golden. Member order fixed — Logix Template Object offsets depend on it |
|
|
|
|
### Controller tags
|
|
|
|
| Tag | Type | Seed value | Purpose |
|
|
|---|---|---|---|
|
|
| `Motor1` | `Motor_UDT` | `{Speed=1800, Torque=42.5, Status=0x0001}` | `AbCipEmulateUdtReadTests.WholeUdt_read_decodes_each_member_at_its_Template_Object_offset` |
|
|
| `HighTempAlarm` | `ALMD` | default ALMD config, `In` tied to `SimulateAlarm` bit | `AbCipEmulateAlmdTests.Real_ALMD_raise_fires_OnAlarmEvent_through_the_driver_projection` |
|
|
| `SimulateAlarm` | `BOOL` | `0` | Operator-writable bit the ladder routes into `HighTempAlarm.In` — gives the test a clean way to drive the alarm edge without scripting Emulate directly |
|
|
|
|
### Program structure
|
|
|
|
- One periodic task `MainTask` @ 100 ms
|
|
- One program `MainProgram`
|
|
- One routine `MainRoutine` (Ladder) with a single rung:
|
|
`XIC SimulateAlarm OTE HighTempAlarm.In`
|
|
|
|
That's enough ladder for `SimulateAlarm := 1` to raise the alarm + for
|
|
`SimulateAlarm := 0` to clear it.
|
|
|
|
## Tier-level behaviours this project enables
|
|
|
|
Coverage the existing Dockerized `ab_server` fixture can't produce —
|
|
each verified by an `Emulate/*Tests.cs` class gated on
|
|
`AB_SERVER_PROFILE=emulate`:
|
|
|
|
- **CIP Template Object round-trip** — real Logix template bytes,
|
|
reads produce the same offset layout the CIP Symbol Object decoder +
|
|
`AbCipUdtMemberLayout` expect.
|
|
- **ALMD rising-edge semantics** — real Logix ALMD instruction fires
|
|
`InFaulted` / `Acked` transitions at cycle boundaries, not at our
|
|
unit-test fake's timer boundaries.
|
|
- **Optimized vs unoptimized DB behaviour** — Logix 5380/5580 series
|
|
runs the Studio 5000 project with optimized-DB-equivalent member
|
|
access; the driver's read path exercises that wire surface.
|
|
|
|
Not in scope even with Emulate — needs real hardware:
|
|
|
|
- EtherNet/IP embedded-switch behaviour (Stratix 5700, 1756-EN4TR)
|
|
- CIP Safety across partitions (Emulate 5580 emulates safety within
|
|
the chassis but not across nodes)
|
|
- Redundant chassis failover (1756-RM)
|
|
- Motion control timing
|
|
- High-speed discrete-input scheduling
|
|
|
|
## How to run the Emulate-tier tests
|
|
|
|
On the dev box:
|
|
|
|
```powershell
|
|
$env:AB_SERVER_PROFILE = 'emulate'
|
|
$env:AB_SERVER_ENDPOINT = '10.0.0.42:44818' # replace with the Emulate PC IP
|
|
dotnet test tests\ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests
|
|
```
|
|
|
|
With `AB_SERVER_PROFILE` unset or `abserver`, the `Emulate/*Tests.cs`
|
|
classes skip cleanly; ab_server-backed tests run as usual.
|
|
|
|
## See also
|
|
|
|
- [`docs/drivers/AbServer-Test-Fixture.md`](../../../docs/drivers/AbServer-Test-Fixture.md)
|
|
§Logix Emulate golden-box tier — coverage map
|
|
- [`docs/v2/dev-environment.md`](../../../docs/v2/dev-environment.md)
|
|
§Integration host — license + networking notes
|
|
- Studio 5000 Logix Designer + Logix Emulate product pages on the
|
|
Rockwell TechConnect portal (licensed; internal link only).
|