108 lines
6.2 KiB
Markdown
108 lines
6.2 KiB
Markdown
# Linux SDK 2 server lifecycle soak
|
||
|
||
This launcher publishes and runs the existing
|
||
`Sdk2LifecycleSoakTests.Repeated_lifecycles_return_resources_to_a_steady_baseline`
|
||
without copying, rewriting, suppressing or changing its test logic. It imports the
|
||
canonical descriptor fixes from `642aefe3`: physical symlink resolution, path
|
||
separator boundaries, open/closed PKI positive controls, and bounded probe process
|
||
and stream cleanup. The same test still owns the production server, node manager,
|
||
sessions, subscriptions, continuation points, revocation, stalled TCP proxy,
|
||
surgical changes/rebuild and same-PKI restarts.
|
||
|
||
A diagnostic run:
|
||
|
||
```sh
|
||
python3 scripts/validation/opcua-server-lifecycle-linux/run.py \
|
||
--duration 90 --output /tmp/otopcua-server-linux-diagnostic-unique
|
||
```
|
||
|
||
The coordinator must launch and own a full run in its persistent execution
|
||
session. A diagnostic cannot satisfy the full gate:
|
||
|
||
```sh
|
||
python3 scripts/validation/opcua-server-lifecycle-linux/run.py \
|
||
--full --duration 7200 --output /tmp/otopcua-server-linux-full-unique
|
||
```
|
||
|
||
An already published artifact can be reused with
|
||
`--published-app /absolute/path/to/app`. Its parent must contain the launcher's
|
||
`publish-receipt.json`; the test source, apphost and test assembly hashes must
|
||
match. The recorded diagnostic artifact can be reused with:
|
||
|
||
```sh
|
||
python3 /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-server-lifecycle-linux/run.py \
|
||
--full --duration 7200 \
|
||
--published-app /tmp/opcua2-server-linux-diagnostic-20261110a/app \
|
||
--output /tmp/opcua2-server-linux-full-20261110
|
||
```
|
||
|
||
The output directory must be fresh. It is mode 0700 and can contain task-owned
|
||
private PKI under `task/tmp` during a run or after a failure. Never commit the
|
||
entire output. The existing successful test removes its own stores. Only selected
|
||
redacted receipt/log/JSONL/TRX files belong under this directory's `evidence/`.
|
||
|
||
The exact publish command uses the host .NET SDK (recorded as 10.0.403 for the
|
||
verified diagnostic), RID `linux-arm64`, self-contained runtime 10.0.14, explicit
|
||
`UseAppHost=true`, `PublishSingleFile=false`, `PublishTrimmed=false`, one MSBuild
|
||
node, and an external task-owned artifacts directory. All runtime packs were
|
||
already cached. No production or test source is patched during publish. The
|
||
launcher requires an empty production/package source diff against `7b353d7b` and
|
||
records the actual published revision separately from the launcher revision.
|
||
That is source equivalence, not a claim that separately built Linux and macOS
|
||
assemblies have identical hashes. The full publish file hashes, exact test source
|
||
hash, runtimeconfig and SDK dependency versions are retained.
|
||
|
||
The cached official SDK image
|
||
`mcr.microsoft.com/dotnet/sdk:10.0.103-noble` is resolved to its immutable local
|
||
image ID and must be Linux arm64. The container has `--network none`, no host
|
||
ports and only a read-only application mount plus its fresh task volume.
|
||
`TMPDIR=/task/tmp` and `XDG_DATA_HOME=/task/data` isolate temporary files and PKI;
|
||
`HOME` is not changed. Nothing targets fleet instances, production stores or
|
||
other task fixtures.
|
||
|
||
The image's VSTest runner first executes exactly the two existing descriptor
|
||
controls. A separate invocation executes exactly one lifecycle test. Both TRX
|
||
files must contain the expected exact executed/passed counts, no skips and no
|
||
failure/error/abort/timeout. The published xUnit v3 application must be ELF64
|
||
AArch64. During the live test, `/proc/<testpid>/exe` must point to the published
|
||
application and the mapped CLR must be `/app/libcoreclr.so`, proving that the
|
||
out-of-process test host is the self-contained Linux publish rather than an
|
||
accidentally copied macOS host.
|
||
|
||
The original test resource limits remain **64 MiB retained managed growth,
|
||
128 MiB RSS growth, and 32 additional FDs**, using its original third-cycle
|
||
baseline and original managed trend check. Quiescent sessions, subscriptions,
|
||
items, browse/history points, monitored-node/live-item counts and PKI FDs must be
|
||
zero. Cached certificate stores and address-space shape must remain at baseline.
|
||
The original exact-tag read-only diagnostics and manager/store disposal assertions
|
||
are unchanged. The wrapper verifies the same limits in the header and requires
|
||
one start, one completion, no failed row, one active/stall/quiescent row per
|
||
completed cycle and one restart per four cycles. Full mode requires both requested
|
||
and actual monotonic observation time of at least 7200 seconds and a true final
|
||
`satisfiesTwoHourDuration`. The outer container deadline is duration plus 300
|
||
seconds. Its own container is forcibly removed on timeout/interruption.
|
||
|
||
Artifacts include `publish.log`, `publish-receipt.json`, `source.json`,
|
||
`artifact-manifest.json`, `command.json`, `result.json`, `container.log`, and
|
||
`task/{soak.jsonl,soak.log,descriptor-controls.log,linux-precheck.txt,
|
||
linux-runtime-process.txt,container-dotnet-info.txt,results/*.trx}`. A reused
|
||
artifact keeps its original publish receipt; `source.json` identifies both source
|
||
revisions. `result.json` is passing only after TRX and completion validation.
|
||
|
||
This supplies supported Linux runtime evidence. It does not resolve the observed
|
||
macOS RSS failure or establish its cause. A short Linux pass is not a two-hour
|
||
pass, and a later Linux pass alone cannot explain away the macOS failure. This
|
||
lane makes no Windows, AVEVA, interoperability or complete G4 performance claim.
|
||
|
||
The final checked-in diagnostic completed **91.602 seconds**, 25 cycles, six
|
||
actual server restarts, 25 recovered network stalls, and one passing lifecycle
|
||
TRX result. Both descriptor tests passed: the symlink control observed
|
||
`before=0, opened=1, closed=0`, excluded the sibling path, and the timed-out probe
|
||
was reaped in 267 ms. All quiescent logical-resource counts and PKI FDs were zero.
|
||
Third-cycle to final deltas were **−145,080 managed bytes, +53,739,520 RSS bytes,
|
||
and +2 FDs**, within the unchanged diagnostic limits. These short observations do
|
||
not establish a two-hour resource trend. The full Linux gate remains pending.
|
||
CLI rejection of `--full --duration 90`, rejection of a short completion as a full
|
||
run, and rejection of the wrong TRX executed count were also verified. Selected
|
||
receipts are in `evidence/2026-11-10-diagnostic/`.
|