test: add isolated Linux server lifecycle soak launcher

This commit is contained in:
Joseph Doherty
2026-11-10 13:08:44 -05:00
parent 88ee30e0e4
commit 8d75ac8c6c
22 changed files with 4412 additions and 0 deletions
@@ -0,0 +1 @@
__pycache__/
@@ -0,0 +1,107 @@
# 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/`.
@@ -0,0 +1,41 @@
#!/usr/bin/env bash
# Task-owned Linux namespace only. Existing test logic and limits are unchanged.
set -euo pipefail
mkdir -p /task/tmp /task/data /task/results
export TMPDIR=/task/tmp
export XDG_DATA_HOME=/task/data
export OTOPCUA_SDK2_SOAK=1
export OTOPCUA_SDK2_SOAK_OUTPUT=/task/soak.jsonl
export DOTNET_CLI_TELEMETRY_OPTOUT=1
export DOTNET_NOLOGO=1
[[ $(uname -s) == Linux && $(uname -m) == aarch64 ]]
[[ -d /proc/self/fd ]]
printf 'kernel=%s machine=%s tmp=%s procfs=yes\n' "$(uname -s)" "$(uname -m)" "$(readlink -f "$TMPDIR")" > /task/linux-precheck.txt
dotnet --info > /task/container-dotnet-info.txt
dotnet vstest /app/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.dll \
--TestCaseFilter:'FullyQualifiedName~Sdk2LifecycleSoakTests.Descriptor_probe_' \
--ResultsDirectory:/task/results '--Logger:trx;LogFileName=descriptor-controls.trx' > /task/descriptor-controls.log 2>&1
# VSTest launches the published xUnit v3 self-contained Linux ELF apphost.
# A distinct invocation gives the soak its own otherwise idle test process.
dotnet vstest /app/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.dll \
--TestCaseFilter:'FullyQualifiedName=ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.Sdk2LifecycleSoakTests.Repeated_lifecycles_return_resources_to_a_steady_baseline' \
--ResultsDirectory:/task/results '--Logger:trx;LogFileName=soak.trx' > /task/soak.log 2>&1 &
vstest_pid=$!
observed=0
for attempt in $(seq 1 600); do
if [[ -s /task/soak.jsonl ]]; then
test_pid=$(head -n 1 /task/soak.jsonl | sed -n 's/.*"processId":\([0-9]*\),.*/\1/p')
[[ -n "$test_pid" ]]
test_exe=$(readlink "/proc/$test_pid/exe")
[[ "$test_exe" == /app/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests ]]
printf 'testProcessId=%s\nactualExecutable=%s\n' "$test_pid" "$test_exe" > /task/linux-runtime-process.txt
awk '$6 ~ /\/(libcoreclr.so|libhostfxr.so|libhostpolicy.so|System.Private.CoreLib.dll)$/ {print $6}' "/proc/$test_pid/maps" | sort -u >> /task/linux-runtime-process.txt
grep -Fx /app/libcoreclr.so /task/linux-runtime-process.txt > /dev/null
observed=1
break
fi
kill -0 "$vstest_pid" 2>/dev/null || break
sleep 0.1
done
[[ "$observed" == 1 ]]
wait "$vstest_pid"
@@ -0,0 +1,25 @@
{
"argv": [
"docker",
"run",
"--rm",
"--name",
"otopcua-server-linux-soak-fb2c804a7d01",
"--network",
"none",
"-e",
"OTOPCUA_SDK2_SOAK_MODE=diagnostic",
"-e",
"OTOPCUA_SDK2_SOAK_SECONDS=90",
"-e",
"OTOPCUA_SOAK_BUILD_SHA=74c938f37cbb9cf08b6ca72e4effc511120dc274",
"-v",
"/private/tmp/opcua2-server-linux-diagnostic-20261110a/app:/app:ro",
"-v",
"/private/tmp/opcua2-server-linux-diagnostic-20261110c/task:/task",
"sha256:b04611ee9e1b7d36797012ed921962c57189cb4dbb3dff12afb8e158110f293b",
"bash",
"/task/container.sh"
],
"timeoutSeconds": 390
}
@@ -0,0 +1,51 @@
.NET SDK:
Version: 10.0.103
Commit: c2435c3e0f
Workload version: 10.0.100-manifests.a62d7899
MSBuild version: 18.0.11+c2435c3e0
Runtime Environment:
OS Name: ubuntu
OS Version: 24.04
OS Platform: Linux
RID: linux-arm64
Base Path: /usr/share/dotnet/sdk/10.0.103/
.NET workloads installed:
There are no installed workloads to display.
Configured to use workload sets when installing new manifests.
No workload sets are installed. Run "dotnet workload restore" to install a workload set.
Host:
Version: 10.0.3
Architecture: arm64
Commit: c2435c3e0f
.NET SDKs installed:
10.0.103 [/usr/share/dotnet/sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 10.0.3 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 10.0.3 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
Other architectures found:
None
Environment variables:
DOTNET_CLI_TELEMETRY_OPTOUT [1]
DOTNET_GENERATE_ASPNET_CERTIFICATE [false]
DOTNET_NOLOGO [1]
DOTNET_ROLL_FORWARD [Major]
DOTNET_RUNNING_IN_CONTAINER [true]
DOTNET_SDK_VERSION [10.0.103]
DOTNET_USE_POLLING_FILE_WATCHER [true]
DOTNET_VERSION [10.0.3]
global.json file:
Not found
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
@@ -0,0 +1,7 @@
VSTest version 18.0.1 (arm64)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
Results File: /task/results/descriptor-controls.trx
Passed! - Failed: 0, Passed: 2, Skipped: 0, Total: 2, Duration: 297 ms - ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.dll (net10.0)
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<TestRun id="a4046507-6b54-4afc-b1d6-dbb3ad85db1c" name="@8c898f464f50 2026-11-10 18:06:02" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<Times creation="2026-11-10T18:06:02.0288408+00:00" queuing="2026-11-10T18:06:02.0288408+00:00" start="2026-11-10T18:06:01.1322717+00:00" finish="2026-11-10T18:06:02.0312051+00:00" />
<TestSettings name="default" id="bfdcc811-3a6d-455f-9eda-152573bdc6d9">
<Deployment runDeploymentRoot="_8c898f464f50_2026-11-10_18_06_02" />
</TestSettings>
<Results>
<UnitTestResult executionId="5dae5583-2c39-479e-9715-2339d7f6593d" testId="02aca891-6c73-5df6-4396-20f20d6490ce" testName="ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.Sdk2LifecycleSoakTests.Descriptor_probe_times_out_and_reaps_a_process_that_keeps_both_streams_open" computerName="8c898f464f50" duration="00:00:00.2676070" startTime="2026-11-10T18:06:01.6988716+00:00" endTime="2026-11-10T18:06:01.9669755+00:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="5dae5583-2c39-479e-9715-2339d7f6593d">
<Output>
<StdOut>Descriptor timeout control: deadlineMs=250, elapsedMs=267, childExited=True</StdOut>
</Output>
</UnitTestResult>
<UnitTestResult executionId="b05a5663-eb92-4c4c-993a-7236c459b1ce" testId="1d78597f-0424-4abc-5484-1d1084deba0d" testName="ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.Sdk2LifecycleSoakTests.Descriptor_probe_observes_an_open_PKI_file_through_a_symlink_alias_and_its_close" computerName="8c898f464f50" duration="00:00:00.0235426" startTime="2026-11-10T18:06:01.6695099+00:00" endTime="2026-11-10T18:06:01.6964907+00:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="b05a5663-eb92-4c4c-993a-7236c459b1ce">
<Output>
<StdOut>PKI descriptor control: before=0, opened=1, closed=0; siblingExcluded=true; aliasResolved=true</StdOut>
</Output>
</UnitTestResult>
</Results>
<TestDefinitions>
<UnitTest name="ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.Sdk2LifecycleSoakTests.Descriptor_probe_observes_an_open_PKI_file_through_a_symlink_alias_and_its_close" storage="/app/zb.mom.ww.otopcua.opcuaserver.integrationtests.dll" id="1d78597f-0424-4abc-5484-1d1084deba0d">
<Execution id="b05a5663-eb92-4c4c-993a-7236c459b1ce" />
<TestMethod codeBase="/app/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.dll" adapterTypeName="executor://xunit/VsTestRunner3/netcore/" className="ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.Sdk2LifecycleSoakTests" name="Descriptor_probe_observes_an_open_PKI_file_through_a_symlink_alias_and_its_close" />
</UnitTest>
<UnitTest name="ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.Sdk2LifecycleSoakTests.Descriptor_probe_times_out_and_reaps_a_process_that_keeps_both_streams_open" storage="/app/zb.mom.ww.otopcua.opcuaserver.integrationtests.dll" id="02aca891-6c73-5df6-4396-20f20d6490ce">
<Execution id="5dae5583-2c39-479e-9715-2339d7f6593d" />
<TestMethod codeBase="/app/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.dll" adapterTypeName="executor://xunit/VsTestRunner3/netcore/" className="ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.Sdk2LifecycleSoakTests" name="Descriptor_probe_times_out_and_reaps_a_process_that_keeps_both_streams_open" />
</UnitTest>
</TestDefinitions>
<TestEntries>
<TestEntry testId="02aca891-6c73-5df6-4396-20f20d6490ce" executionId="5dae5583-2c39-479e-9715-2339d7f6593d" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
<TestEntry testId="1d78597f-0424-4abc-5484-1d1084deba0d" executionId="b05a5663-eb92-4c4c-993a-7236c459b1ce" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
</TestEntries>
<TestLists>
<TestList name="Results Not in a List" id="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
<TestList name="All Loaded Results" id="19431567-8539-422a-85d7-44ee4e166bda" />
</TestLists>
<ResultSummary outcome="Completed">
<Counters total="2" executed="2" passed="2" failed="0" error="0" timeout="0" aborted="0" inconclusive="0" passedButRunAborted="0" notRunnable="0" notExecuted="0" disconnected="0" warning="0" completed="0" inProgress="0" pending="0" />
<Output>
<StdOut>[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v3.0.2+dd36e86129 (64-bit .NET 10.0.14)
[xUnit.net 00:00:00.08] Discovering: ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests
[xUnit.net 00:00:00.22] Discovered: ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests
[xUnit.net 00:00:00.30] Starting: ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests
[xUnit.net 00:00:00.64] Finished: ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests
</StdOut>
</Output>
</ResultSummary>
</TestRun>
@@ -0,0 +1,3 @@
usage: run.py [-h] --output OUTPUT [--duration DURATION] [--full]
[--published-app PUBLISHED_APP] [--image IMAGE]
run.py: error: full requires duration >=7200; diagnostic requires 60..120 seconds
@@ -0,0 +1 @@
kernel=Linux machine=aarch64 tmp=/task/tmp procfs=yes
@@ -0,0 +1,6 @@
testProcessId=196
actualExecutable=/app/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests
/app/System.Private.CoreLib.dll
/app/libcoreclr.so
/app/libhostfxr.so
/app/libhostpolicy.so
@@ -0,0 +1,29 @@
{
"sourceRevision": "74c938f37cbb9cf08b6ca72e4effc511120dc274",
"command": [
"dotnet",
"publish",
"/Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.csproj",
"-c",
"Release",
"-r",
"linux-arm64",
"--self-contained",
"true",
"-p:RuntimeFrameworkVersion=10.0.14",
"-p:PublishSingleFile=false",
"-p:PublishTrimmed=false",
"-p:UseAppHost=true",
"--artifacts-path",
"/tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts",
"-o",
"/tmp/opcua2-server-linux-diagnostic-20261110a/app",
"-m:1",
"--nologo"
],
"hostDotnet": ".NET SDK:\n Version: 10.0.403\n Commit: 5a2162bea6\n Workload version: 10.0.400-manifests.a00bebb6\n MSBuild version: 18.9.15+5a2162bea\n\nRuntime Environment:\n OS Name: Mac OS X\n OS Version: 26.5\n OS Platform: Darwin\n RID: osx-arm64\n Base Path: /opt/homebrew/Cellar/dotnet/10.0.403/libexec/sdk/10.0.403/\n\n.NET workloads installed:\nThere are no installed workloads to display.\nConfigured to use workload sets when installing new manifests.\nNo workload sets are installed. Run \"dotnet workload restore\" to install a workload set.\n\nHost:\n Version: 10.0.14\n Architecture: arm64\n Commit: 0427b9abbe\n\n.NET SDKs installed:\n 10.0.403 [/opt/homebrew/Cellar/dotnet/10.0.403/libexec/sdk]\n\n.NET runtimes installed:\n Microsoft.AspNetCore.App 10.0.14 [/opt/homebrew/Cellar/dotnet/10.0.403/libexec/shared/Microsoft.AspNetCore.App]\n Microsoft.NETCore.App 10.0.14 [/opt/homebrew/Cellar/dotnet/10.0.403/libexec/shared/Microsoft.NETCore.App]\n\nOther architectures found:\n None\n\nEnvironment variables:\n DOTNET_ROOT [/opt/homebrew/Cellar/dotnet/10.0.403/libexec]\n\nglobal.json file:\n /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/global.json\n\nLearn more:\n https://aka.ms/dotnet/info\n\nDownload .NET:\n https://aka.ms/dotnet/download\n",
"testSourceSha256": "e695783e05787d94bf5d167b25b1c48b446b800c28259f023c28ed6012d737d1",
"apphostSha256": "97531b8005df9dc8b129d2b22ba2049cf572d5d970046f7e8644ec632e860032",
"testAssemblySha256": "9d64b5b3dd9bf7eff38f6fabe10382c107ab824485a309ba9649bfee9bbd843a",
"publishExitCode": 0
}
@@ -0,0 +1,121 @@
Determining projects to restore...
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/ZB.MOM.WW.OtOpcUa.Core.Abstractions.csproj (in 490 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Contracts/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Contracts.csproj (in 494 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.MTConnect.Contracts/ZB.MOM.WW.OtOpcUa.Driver.MTConnect.Contracts.csproj (in 494 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Contracts/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Contracts.csproj (in 2 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing.csproj (in 4 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Session/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Session.csproj (in 569 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Tooling/ZB.MOM.WW.OtOpcUa.Analyzers/ZB.MOM.WW.OtOpcUa.Analyzers.csproj (in 574 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Calculation.Contracts/ZB.MOM.WW.OtOpcUa.Driver.Calculation.Contracts.csproj (in 1 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.OutOfProcess/ZB.MOM.WW.OtOpcUa.Core.Scripting.OutOfProcess.csproj (in 591 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Server/ZB.MOM.WW.OtOpcUa.ScriptWorker/ZB.MOM.WW.OtOpcUa.ScriptWorker.csproj (in 589 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport/ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport.csproj (in 6 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Contracts/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Contracts.csproj (in 6 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Server/ZB.MOM.WW.OtOpcUa.Security/ZB.MOM.WW.OtOpcUa.Security.csproj (in 605 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Contracts/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Contracts.csproj (in 2 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.csproj (in 36 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Calculation/ZB.MOM.WW.OtOpcUa.Driver.Calculation.csproj (in 101 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.csproj (in 107 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/ZB.MOM.WW.OtOpcUa.Driver.AbCip.csproj (in 31 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/ZB.MOM.WW.OtOpcUa.OpcUaServer.csproj (in 613 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Contracts/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Contracts.csproj (in 9 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Transport/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Transport.csproj (in 10 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.Protocol/ZB.MOM.WW.OtOpcUa.Core.Scripting.Protocol.csproj (in 6 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Browser/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Browser.csproj (in 19 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Core/ZB.MOM.WW.OtOpcUa.Core/ZB.MOM.WW.OtOpcUa.Core.csproj (in 30 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser.csproj (in 27 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.Abstractions/ZB.MOM.WW.OtOpcUa.Core.Scripting.Abstractions.csproj (in 2 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/ZB.MOM.WW.OtOpcUa.Runtime.csproj (in 651 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.csproj (in 12 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ZB.MOM.WW.OtOpcUa.Core.Scripting.csproj (in 12 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Core/ZB.MOM.WW.OtOpcUa.Commons/ZB.MOM.WW.OtOpcUa.Commons.csproj (in 4 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.MTConnect/ZB.MOM.WW.OtOpcUa.Driver.MTConnect.csproj (in 33 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.QuestDb/ZB.MOM.WW.OtOpcUa.Driver.Historian.QuestDb.csproj (in 656 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.csproj (in 655 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.SqlServer/ZB.MOM.WW.OtOpcUa.Driver.Historian.SqlServer.csproj (in 144 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.csproj (in 36 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms.csproj (in 11 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts/ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts.csproj (in 6 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/ZB.MOM.WW.OtOpcUa.Client.Shared.csproj (in 11 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Contracts/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Contracts.csproj (in 2 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7.Contracts/ZB.MOM.WW.OtOpcUa.Driver.S7.Contracts.csproj (in 2 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Core/ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian/ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian.csproj (in 44 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ZB.MOM.WW.OtOpcUa.Cluster.csproj (in 45 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Contracts/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Contracts.csproj (in 6 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Browser/ZB.MOM.WW.OtOpcUa.Driver.Sql.Browser.csproj (in 36 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common/ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common.csproj (in 10 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/ZB.MOM.WW.OtOpcUa.Driver.Sql.csproj (in 50 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Dialect/ZB.MOM.WW.OtOpcUa.Driver.Sql.Dialect.csproj (in 66 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/ZB.MOM.WW.OtOpcUa.ControlPlane.csproj (in 53 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Contracts/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Contracts.csproj (in 3 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ZB.MOM.WW.OtOpcUa.Driver.Modbus.csproj (in 41 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser.csproj (in 9 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7/ZB.MOM.WW.OtOpcUa.Driver.S7.csproj (in 49 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/ZB.MOM.WW.OtOpcUa.Configuration.csproj (in 92 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.csproj (in 51 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.csproj (in 86 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.csproj (in 24 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/ZB.MOM.WW.OtOpcUa.AdminUI.csproj (in 89 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/src/Server/ZB.MOM.WW.OtOpcUa.Host/ZB.MOM.WW.OtOpcUa.Host.csproj (in 784 ms).
Restored /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.csproj (in 793 ms).
ZB.MOM.WW.OtOpcUa.Analyzers -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Analyzers/release/ZB.MOM.WW.OtOpcUa.Analyzers.dll
ZB.MOM.WW.OtOpcUa.Core.Abstractions -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Core.Abstractions/release/ZB.MOM.WW.OtOpcUa.Core.Abstractions.dll
ZB.MOM.WW.OtOpcUa.Commons -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Commons/release/ZB.MOM.WW.OtOpcUa.Commons.dll
ZB.MOM.WW.OtOpcUa.Core.Scripting.Abstractions -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Core.Scripting.Abstractions/release/ZB.MOM.WW.OtOpcUa.Core.Scripting.Abstractions.dll
ZB.MOM.WW.OtOpcUa.Core.Scripting -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Core.Scripting/release/ZB.MOM.WW.OtOpcUa.Core.Scripting.dll
ZB.MOM.WW.OtOpcUa.Core.VirtualTags -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Core.VirtualTags/release/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.dll
ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts/release/ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts.dll
ZB.MOM.WW.OtOpcUa.Configuration -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Configuration/release/ZB.MOM.WW.OtOpcUa.Configuration.dll
ZB.MOM.WW.OtOpcUa.Core -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Core/release/ZB.MOM.WW.OtOpcUa.Core.dll
ZB.MOM.WW.OtOpcUa.OpcUaServer -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.OpcUaServer/release/ZB.MOM.WW.OtOpcUa.OpcUaServer.dll
ZB.MOM.WW.OtOpcUa.Cluster -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Cluster/release/ZB.MOM.WW.OtOpcUa.Cluster.dll
ZB.MOM.WW.OtOpcUa.Core.Scripting.Protocol -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Core.Scripting.Protocol/release/ZB.MOM.WW.OtOpcUa.Core.Scripting.Protocol.dll
ZB.MOM.WW.OtOpcUa.Core.Scripting.OutOfProcess -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Core.Scripting.OutOfProcess/release/ZB.MOM.WW.OtOpcUa.Core.Scripting.OutOfProcess.dll
ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms/release/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms.dll
ZB.MOM.WW.OtOpcUa.Security -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Security/release/ZB.MOM.WW.OtOpcUa.Security.dll
ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing/release/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing.dll
ZB.MOM.WW.OtOpcUa.Driver.Modbus.Contracts -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Contracts/release/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Contracts.dll
ZB.MOM.WW.OtOpcUa.Driver.S7.Contracts -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.S7.Contracts/release/ZB.MOM.WW.OtOpcUa.Driver.S7.Contracts.dll
ZB.MOM.WW.OtOpcUa.Driver.AbCip.Contracts -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Contracts/release/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Contracts.dll
ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Contracts -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Contracts/release/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Contracts.dll
ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Contracts -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Contracts/release/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Contracts.dll
ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Contracts -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Contracts/release/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Contracts.dll
ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Contracts -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Contracts/release/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Contracts.dll
ZB.MOM.WW.OtOpcUa.Driver.MTConnect.Contracts -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.MTConnect.Contracts/release/ZB.MOM.WW.OtOpcUa.Driver.MTConnect.Contracts.dll
ZB.MOM.WW.OtOpcUa.Driver.Calculation.Contracts -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Calculation.Contracts/release/ZB.MOM.WW.OtOpcUa.Driver.Calculation.Contracts.dll
ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Contracts -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Contracts/release/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Contracts.dll
ZB.MOM.WW.OtOpcUa.ControlPlane -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.ControlPlane/release/ZB.MOM.WW.OtOpcUa.ControlPlane.dll
ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian/release/ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian.dll
ZB.MOM.WW.OtOpcUa.Runtime -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Runtime/release/ZB.MOM.WW.OtOpcUa.Runtime.dll
ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Contracts -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Contracts/release/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Contracts.dll
ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Session -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Session/release/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Session.dll
ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser/release/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser.dll
ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser/release/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser.dll
ZB.MOM.WW.OtOpcUa.Driver.Sql.Dialect -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Sql.Dialect/release/ZB.MOM.WW.OtOpcUa.Driver.Sql.Dialect.dll
ZB.MOM.WW.OtOpcUa.Driver.Sql.Browser -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Sql.Browser/release/ZB.MOM.WW.OtOpcUa.Driver.Sql.Browser.dll
ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Transport -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Transport/release/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Transport.dll
ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Browser -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Browser/release/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Browser.dll
ZB.MOM.WW.OtOpcUa.AdminUI -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.AdminUI/release/ZB.MOM.WW.OtOpcUa.AdminUI.dll
ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport/release/ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport.dll
ZB.MOM.WW.OtOpcUa.Driver.AbCip -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.AbCip/release/ZB.MOM.WW.OtOpcUa.Driver.AbCip.dll
ZB.MOM.WW.OtOpcUa.Driver.AbLegacy -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/release/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.dll
ZB.MOM.WW.OtOpcUa.Driver.Calculation -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Calculation/release/ZB.MOM.WW.OtOpcUa.Driver.Calculation.dll
ZB.MOM.WW.OtOpcUa.Driver.FOCAS -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/release/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.dll
ZB.MOM.WW.OtOpcUa.Driver.Galaxy -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/release/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.dll
ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common/release/ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common.dll
ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway/release/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.dll
ZB.MOM.WW.OtOpcUa.Driver.Historian.SqlServer -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Historian.SqlServer/release/ZB.MOM.WW.OtOpcUa.Driver.Historian.SqlServer.dll
ZB.MOM.WW.OtOpcUa.Driver.Historian.QuestDb -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Historian.QuestDb/release/ZB.MOM.WW.OtOpcUa.Driver.Historian.QuestDb.dll
ZB.MOM.WW.OtOpcUa.Driver.Modbus -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Modbus/release/ZB.MOM.WW.OtOpcUa.Driver.Modbus.dll
ZB.MOM.WW.OtOpcUa.Driver.Mqtt -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Mqtt/release/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.dll
ZB.MOM.WW.OtOpcUa.Driver.MTConnect -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.MTConnect/release/ZB.MOM.WW.OtOpcUa.Driver.MTConnect.dll
ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient/release/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.dll
ZB.MOM.WW.OtOpcUa.Driver.S7 -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.S7/release/ZB.MOM.WW.OtOpcUa.Driver.S7.dll
ZB.MOM.WW.OtOpcUa.Driver.Sql -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.Sql/release/ZB.MOM.WW.OtOpcUa.Driver.Sql.dll
ZB.MOM.WW.OtOpcUa.Driver.TwinCAT -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/release/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.dll
ZB.MOM.WW.OtOpcUa.ScriptWorker -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.ScriptWorker/release_linux-arm64/ZB.MOM.WW.OtOpcUa.ScriptWorker.dll
ZB.MOM.WW.OtOpcUa.Host -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Host/release_linux-arm64/OtOpcUa.Host.dll
ZB.MOM.WW.OtOpcUa.Client.Shared -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.Client.Shared/release/ZB.MOM.WW.OtOpcUa.Client.Shared.dll
ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests -> /tmp/opcua2-server-linux-diagnostic-20261110a/build-artifacts/bin/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests/release_linux-arm64/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.dll
ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests -> /tmp/opcua2-server-linux-diagnostic-20261110a/app/
@@ -0,0 +1,160 @@
{
"status": "passed",
"containerExitCode": 0,
"containerElapsedSeconds": 95.26570125005674,
"descriptorControls": {
"counts": {
"total": "2",
"executed": "2",
"passed": "2",
"failed": "0",
"error": "0",
"timeout": "0",
"aborted": "0",
"inconclusive": "0",
"passedButRunAborted": "0",
"notRunnable": "0",
"notExecuted": "0",
"disconnected": "0",
"warning": "0",
"completed": "0",
"inProgress": "0",
"pending": "0"
},
"tests": [
"ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.Sdk2LifecycleSoakTests.Descriptor_probe_times_out_and_reaps_a_process_that_keeps_both_streams_open",
"ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.Sdk2LifecycleSoakTests.Descriptor_probe_observes_an_open_PKI_file_through_a_symlink_alias_and_its_close"
]
},
"soakTest": {
"counts": {
"total": "1",
"executed": "1",
"passed": "1",
"failed": "0",
"error": "0",
"timeout": "0",
"aborted": "0",
"inconclusive": "0",
"passedButRunAborted": "0",
"notRunnable": "0",
"notExecuted": "0",
"disconnected": "0",
"warning": "0",
"completed": "0",
"inProgress": "0",
"pending": "0"
},
"tests": [
"ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.Sdk2LifecycleSoakTests.Repeated_lifecycles_return_resources_to_a_steady_baseline"
]
},
"evidence": {
"start": {
"kind": "start",
"utc": "2026-11-10T18:06:04.0984012+00:00",
"processId": 196,
"mode": "diagnostic",
"requestedSeconds": 90,
"minimumFullSeconds": 7200,
"build": "74c938f37cbb9cf08b6ca72e4effc511120dc274",
"sdk": "2.0.1+07e62f72500cc0923a2bab940653c8c1116fa286",
"diagnosticInstrumentation": "SDK2.0.1 CP lists and certificate-validation cached stores; read-only",
"limits": {
"retainedManagedGrowthBytes": 67108864,
"rssGrowthBytes": 134217728,
"fdGrowth": 32
},
"coverage": "encrypted sessions; scalar/Int16[] Raw+UNS; subscription removal; browse abandonment; history release/cross-session/close; surgical changes/rebuild; revocation; paused TCP read/recovery; same-PKI restart"
},
"complete": {
"kind": "complete",
"utc": "2026-11-10T18:07:35.7007963+00:00",
"mode": "diagnostic",
"cycles": 25,
"restarts": 6,
"seconds": 91.6023965,
"satisfiesTwoHourDuration": false
},
"rowCounts": {
"active": 25,
"complete": 1,
"network-stall-recovered": 25,
"quiescent": 25,
"restart": 6,
"start": 1
},
"firstResources": {
"Cycle": 1,
"Seconds": 2.6710051,
"Sessions": 0,
"Subscriptions": 0,
"Items": 0,
"BrowsePoints": 0,
"HistoryPoints": 0,
"LiveDataItems": 0,
"LiveEventItems": 0,
"MonitoredNodes": 0,
"Variables": 19,
"Folders": 4,
"Conditions": 1,
"CachedCertificateStores": 2,
"Descriptors": 187,
"PkiDescriptors": 0,
"ManagedBytes": 19828144,
"RssBytes": 207749120,
"AllocatedBytes": 45697696,
"Gen0": 3,
"Gen1": 2,
"Gen2": 2
},
"baselineResources": {
"Cycle": 3,
"Seconds": 7.466919,
"Sessions": 0,
"Subscriptions": 0,
"Items": 0,
"BrowsePoints": 0,
"HistoryPoints": 0,
"LiveDataItems": 0,
"LiveEventItems": 0,
"MonitoredNodes": 0,
"Variables": 19,
"Folders": 4,
"Conditions": 1,
"CachedCertificateStores": 2,
"Descriptors": 188,
"PkiDescriptors": 0,
"ManagedBytes": 20404584,
"RssBytes": 212303872,
"AllocatedBytes": 52268352,
"Gen0": 7,
"Gen1": 6,
"Gen2": 6
},
"lastResources": {
"Cycle": 25,
"Seconds": 91.5753658,
"Sessions": 0,
"Subscriptions": 0,
"Items": 0,
"BrowsePoints": 0,
"HistoryPoints": 0,
"LiveDataItems": 0,
"LiveEventItems": 0,
"MonitoredNodes": 0,
"Variables": 19,
"Folders": 4,
"Conditions": 1,
"CachedCertificateStores": 2,
"Descriptors": 190,
"PkiDescriptors": 0,
"ManagedBytes": 20259504,
"RssBytes": 266043392,
"AllocatedBytes": 349723432,
"Gen0": 57,
"Gen1": 50,
"Gen2": 50
}
}
}
@@ -0,0 +1,83 @@
{"kind":"start","utc":"2026-11-10T18:06:04.0984012+00:00","processId":196,"mode":"diagnostic","requestedSeconds":90,"minimumFullSeconds":7200,"build":"74c938f37cbb9cf08b6ca72e4effc511120dc274","sdk":"2.0.1\u002B07e62f72500cc0923a2bab940653c8c1116fa286","diagnosticInstrumentation":"SDK2.0.1 CP lists and certificate-validation cached stores; read-only","limits":{"retainedManagedGrowthBytes":67108864,"rssGrowthBytes":134217728,"fdGrowth":32},"coverage":"encrypted sessions; scalar/Int16[] Raw\u002BUNS; subscription removal; browse abandonment; history release/cross-session/close; surgical changes/rebuild; revocation; paused TCP read/recovery; same-PKI restart"}
{"kind":"active","cycle":1,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":1,"status":"BadRequestInterrupted","seconds":1.0480969}
{"kind":"quiescent","cycleSeconds":2.6930539,"resources":{"Cycle":1,"Seconds":2.6710051,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":187,"PkiDescriptors":0,"ManagedBytes":19828144,"RssBytes":207749120,"AllocatedBytes":45697696,"Gen0":3,"Gen1":2,"Gen2":2}}
{"kind":"active","cycle":2,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":2,"status":"BadRequestInterrupted","seconds":1.0446531}
{"kind":"quiescent","cycleSeconds":2.4080887,"resources":{"Cycle":2,"Seconds":5.1027619,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":187,"PkiDescriptors":0,"ManagedBytes":20236624,"RssBytes":209514496,"AllocatedBytes":49129448,"Gen0":5,"Gen1":4,"Gen2":4}}
{"kind":"active","cycle":3,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":3,"status":"BadRequestInterrupted","seconds":1.0434837}
{"kind":"quiescent","cycleSeconds":2.3620647,"resources":{"Cycle":3,"Seconds":7.466919,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":188,"PkiDescriptors":0,"ManagedBytes":20404584,"RssBytes":212303872,"AllocatedBytes":52268352,"Gen0":7,"Gen1":6,"Gen2":6}}
{"kind":"active","cycle":4,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":4,"status":"BadRequestInterrupted","seconds":1.0417759}
{"kind":"quiescent","cycleSeconds":2.367273,"resources":{"Cycle":4,"Seconds":9.8310274,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":188,"PkiDescriptors":0,"ManagedBytes":20581856,"RssBytes":215437312,"AllocatedBytes":55331040,"Gen0":9,"Gen1":8,"Gen2":8}}
{"kind":"restart","cycles":4,"restarts":1,"seconds":5.1579086}
{"kind":"active","cycle":5,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":5,"status":"BadRequestInterrupted","seconds":1.0429156}
{"kind":"quiescent","cycleSeconds":2.4248818,"resources":{"Cycle":5,"Seconds":17.4116445,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":187,"PkiDescriptors":0,"ManagedBytes":20117312,"RssBytes":244072448,"AllocatedBytes":97741368,"Gen0":12,"Gen1":10,"Gen2":10}}
{"kind":"active","cycle":6,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":6,"status":"BadRequestInterrupted","seconds":1.0424929}
{"kind":"quiescent","cycleSeconds":2.359121,"resources":{"Cycle":6,"Seconds":19.7704339,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":188,"PkiDescriptors":0,"ManagedBytes":20256216,"RssBytes":244867072,"AllocatedBytes":100833504,"Gen0":14,"Gen1":12,"Gen2":12}}
{"kind":"active","cycle":7,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":7,"status":"BadRequestInterrupted","seconds":1.0036954}
{"kind":"quiescent","cycleSeconds":2.4160967,"resources":{"Cycle":7,"Seconds":22.1874361,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":187,"PkiDescriptors":0,"ManagedBytes":20426992,"RssBytes":245751808,"AllocatedBytes":103924024,"Gen0":16,"Gen1":14,"Gen2":14}}
{"kind":"active","cycle":8,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":8,"status":"BadRequestInterrupted","seconds":1.0523899}
{"kind":"quiescent","cycleSeconds":2.3926737,"resources":{"Cycle":8,"Seconds":24.5842524,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":188,"PkiDescriptors":0,"ManagedBytes":20713008,"RssBytes":247889920,"AllocatedBytes":107102792,"Gen0":18,"Gen1":16,"Gen2":16}}
{"kind":"restart","cycles":8,"restarts":2,"seconds":5.1120391}
{"kind":"active","cycle":9,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":9,"status":"BadRequestInterrupted","seconds":1.0461218}
{"kind":"quiescent","cycleSeconds":2.3757912,"resources":{"Cycle":9,"Seconds":32.0681461,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":187,"PkiDescriptors":0,"ManagedBytes":20283072,"RssBytes":256245760,"AllocatedBytes":149467600,"Gen0":21,"Gen1":18,"Gen2":18}}
{"kind":"active","cycle":10,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":10,"status":"BadRequestInterrupted","seconds":1.0032768}
{"kind":"quiescent","cycleSeconds":2.3840571,"resources":{"Cycle":10,"Seconds":34.4585736,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":187,"PkiDescriptors":0,"ManagedBytes":20400792,"RssBytes":256765952,"AllocatedBytes":152540856,"Gen0":23,"Gen1":20,"Gen2":20}}
{"kind":"active","cycle":11,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":11,"status":"BadRequestInterrupted","seconds":1.0055269}
{"kind":"quiescent","cycleSeconds":2.3664136,"resources":{"Cycle":11,"Seconds":36.8250058,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":187,"PkiDescriptors":0,"ManagedBytes":20611944,"RssBytes":256458752,"AllocatedBytes":155681752,"Gen0":25,"Gen1":22,"Gen2":22}}
{"kind":"active","cycle":12,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":12,"status":"BadRequestInterrupted","seconds":1.0483463}
{"kind":"quiescent","cycleSeconds":2.4039892,"resources":{"Cycle":12,"Seconds":39.2211123,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":187,"PkiDescriptors":0,"ManagedBytes":20794472,"RssBytes":257134592,"AllocatedBytes":158746992,"Gen0":27,"Gen1":24,"Gen2":24}}
{"kind":"restart","cycles":12,"restarts":3,"seconds":5.0988863}
{"kind":"active","cycle":13,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":13,"status":"BadRequestInterrupted","seconds":1.0450081}
{"kind":"quiescent","cycleSeconds":2.3795872,"resources":{"Cycle":13,"Seconds":46.7014719,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":189,"PkiDescriptors":0,"ManagedBytes":20332520,"RssBytes":261271552,"AllocatedBytes":199536496,"Gen0":30,"Gen1":26,"Gen2":26}}
{"kind":"active","cycle":14,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":14,"status":"BadRequestInterrupted","seconds":1.0436713}
{"kind":"quiescent","cycleSeconds":2.3497161,"resources":{"Cycle":14,"Seconds":49.0501604,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":190,"PkiDescriptors":0,"ManagedBytes":20431480,"RssBytes":261554176,"AllocatedBytes":202614280,"Gen0":32,"Gen1":28,"Gen2":28}}
{"kind":"active","cycle":15,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":15,"status":"BadRequestInterrupted","seconds":1.04895}
{"kind":"quiescent","cycleSeconds":2.371092,"resources":{"Cycle":15,"Seconds":51.4268968,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":189,"PkiDescriptors":0,"ManagedBytes":20505512,"RssBytes":264040448,"AllocatedBytes":205694824,"Gen0":34,"Gen1":30,"Gen2":30}}
{"kind":"active","cycle":16,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":16,"status":"BadRequestInterrupted","seconds":1.0443525}
{"kind":"quiescent","cycleSeconds":2.9848582,"resources":{"Cycle":16,"Seconds":53.9203748,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":189,"PkiDescriptors":0,"ManagedBytes":20622096,"RssBytes":264884224,"AllocatedBytes":208715944,"Gen0":36,"Gen1":32,"Gen2":32}}
{"kind":"restart","cycles":16,"restarts":4,"seconds":5.454083}
{"kind":"active","cycle":17,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":17,"status":"BadRequestInterrupted","seconds":1.0473067}
{"kind":"quiescent","cycleSeconds":2.3818575,"resources":{"Cycle":17,"Seconds":62.2447867,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":189,"PkiDescriptors":0,"ManagedBytes":20191360,"RssBytes":259485696,"AllocatedBytes":249582344,"Gen0":39,"Gen1":34,"Gen2":34}}
{"kind":"active","cycle":18,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":18,"status":"BadRequestInterrupted","seconds":1.0423094}
{"kind":"quiescent","cycleSeconds":2.3561291,"resources":{"Cycle":18,"Seconds":64.6095248,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":189,"PkiDescriptors":0,"ManagedBytes":20373376,"RssBytes":255721472,"AllocatedBytes":252706544,"Gen0":41,"Gen1":36,"Gen2":36}}
{"kind":"active","cycle":19,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":19,"status":"BadRequestInterrupted","seconds":1.0436178}
{"kind":"quiescent","cycleSeconds":2.3444876,"resources":{"Cycle":19,"Seconds":66.9546586,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":189,"PkiDescriptors":0,"ManagedBytes":20552264,"RssBytes":254763008,"AllocatedBytes":255808392,"Gen0":43,"Gen1":38,"Gen2":38}}
{"kind":"active","cycle":20,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":20,"status":"BadRequestInterrupted","seconds":1.0451534}
{"kind":"quiescent","cycleSeconds":2.3495591,"resources":{"Cycle":20,"Seconds":69.2963186,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":189,"PkiDescriptors":0,"ManagedBytes":20702232,"RssBytes":255512576,"AllocatedBytes":258843576,"Gen0":45,"Gen1":40,"Gen2":40}}
{"kind":"restart","cycles":20,"restarts":5,"seconds":5.1129163}
{"kind":"active","cycle":21,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":21,"status":"BadRequestInterrupted","seconds":1.049048}
{"kind":"quiescent","cycleSeconds":2.4246867,"resources":{"Cycle":21,"Seconds":76.8338727,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":190,"PkiDescriptors":0,"ManagedBytes":20221440,"RssBytes":262025216,"AllocatedBytes":299637616,"Gen0":48,"Gen1":42,"Gen2":42}}
{"kind":"active","cycle":22,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":22,"status":"BadRequestInterrupted","seconds":1.0419365}
{"kind":"quiescent","cycleSeconds":2.404919,"resources":{"Cycle":22,"Seconds":79.246374,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":189,"PkiDescriptors":0,"ManagedBytes":20324024,"RssBytes":262062080,"AllocatedBytes":302774600,"Gen0":50,"Gen1":44,"Gen2":44}}
{"kind":"active","cycle":23,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":23,"status":"BadRequestInterrupted","seconds":1.0409262}
{"kind":"quiescent","cycleSeconds":2.3874906,"resources":{"Cycle":23,"Seconds":81.6319445,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":189,"PkiDescriptors":0,"ManagedBytes":20478784,"RssBytes":260964352,"AllocatedBytes":305840432,"Gen0":52,"Gen1":46,"Gen2":46}}
{"kind":"active","cycle":24,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":24,"status":"BadRequestInterrupted","seconds":1.0526128}
{"kind":"quiescent","cycleSeconds":2.4292523,"resources":{"Cycle":24,"Seconds":84.060344,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":189,"PkiDescriptors":0,"ManagedBytes":20663008,"RssBytes":261554176,"AllocatedBytes":308902736,"Gen0":54,"Gen1":48,"Gen2":48}}
{"kind":"restart","cycles":24,"restarts":6,"seconds":5.0922583}
{"kind":"active","cycle":25,"sessions":2,"subscriptions":1,"items":3,"browsePoints":1,"historyPoints":6}
{"kind":"network-stall-recovered","cycle":25,"status":"BadRequestInterrupted","seconds":1.0433366}
{"kind":"quiescent","cycleSeconds":2.4269109,"resources":{"Cycle":25,"Seconds":91.5753658,"Sessions":0,"Subscriptions":0,"Items":0,"BrowsePoints":0,"HistoryPoints":0,"LiveDataItems":0,"LiveEventItems":0,"MonitoredNodes":0,"Variables":19,"Folders":4,"Conditions":1,"CachedCertificateStores":2,"Descriptors":190,"PkiDescriptors":0,"ManagedBytes":20259504,"RssBytes":266043392,"AllocatedBytes":349723432,"Gen0":57,"Gen1":50,"Gen2":50}}
{"kind":"complete","utc":"2026-11-10T18:07:35.7007963+00:00","mode":"diagnostic","cycles":25,"restarts":6,"seconds":91.6023965,"satisfiesTwoHourDuration":false}
@@ -0,0 +1,7 @@
VSTest version 18.0.1 (arm64)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
Results File: /task/results/soak.trx
Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: 1 m 33 s - ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.dll (net10.0)
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<TestRun id="d79bf095-24b8-47e5-8bf9-bb794d432137" name="@8c898f464f50 2026-11-10 18:07:35" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<Times creation="2026-11-10T18:07:35.7508628+00:00" queuing="2026-11-10T18:07:35.7508628+00:00" start="2026-11-10T18:06:02.1473749+00:00" finish="2026-11-10T18:07:35.7545626+00:00" />
<TestSettings name="default" id="68e934f0-45b1-46c2-93b4-062f7d8f2596">
<Deployment runDeploymentRoot="_8c898f464f50_2026-11-10_18_07_35" />
</TestSettings>
<Results>
<UnitTestResult executionId="dbfea690-8558-4eb5-96a6-b0d19015f837" testId="3a3639bf-5159-da35-0b1a-0a6c89f03e2c" testName="ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.Sdk2LifecycleSoakTests.Repeated_lifecycles_return_resources_to_a_steady_baseline" computerName="8c898f464f50" duration="00:01:33.0080309" startTime="2026-11-10T18:06:02.6943262+00:00" endTime="2026-11-10T18:07:35.7059381+00:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="dbfea690-8558-4eb5-96a6-b0d19015f837" />
</Results>
<TestDefinitions>
<UnitTest name="ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.Sdk2LifecycleSoakTests.Repeated_lifecycles_return_resources_to_a_steady_baseline" storage="/app/zb.mom.ww.otopcua.opcuaserver.integrationtests.dll" id="3a3639bf-5159-da35-0b1a-0a6c89f03e2c">
<Execution id="dbfea690-8558-4eb5-96a6-b0d19015f837" />
<TestMethod codeBase="/app/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.dll" adapterTypeName="executor://xunit/VsTestRunner3/netcore/" className="ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.Sdk2LifecycleSoakTests" name="Repeated_lifecycles_return_resources_to_a_steady_baseline" />
</UnitTest>
</TestDefinitions>
<TestEntries>
<TestEntry testId="3a3639bf-5159-da35-0b1a-0a6c89f03e2c" executionId="dbfea690-8558-4eb5-96a6-b0d19015f837" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
</TestEntries>
<TestLists>
<TestList name="Results Not in a List" id="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
<TestList name="All Loaded Results" id="19431567-8539-422a-85d7-44ee4e166bda" />
</TestLists>
<ResultSummary outcome="Completed">
<Counters total="1" executed="1" passed="1" failed="0" error="0" timeout="0" aborted="0" inconclusive="0" passedButRunAborted="0" notRunnable="0" notExecuted="0" disconnected="0" warning="0" completed="0" inProgress="0" pending="0" />
<Output>
<StdOut>[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v3.0.2+dd36e86129 (64-bit .NET 10.0.14)
[xUnit.net 00:00:00.10] Discovering: ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests
[xUnit.net 00:00:00.25] Discovered: ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests
[xUnit.net 00:00:00.33] Starting: ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests
[xUnit.net 00:01:33.38] Finished: ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests
</StdOut>
</Output>
</ResultSummary>
</TestRun>
@@ -0,0 +1,57 @@
{
"launcherSourceRevision": "74c938f37cbb9cf08b6ca72e4effc511120dc274",
"publishedSourceRevision": "74c938f37cbb9cf08b6ca72e4effc511120dc274",
"productionEquivalentTo": "7b353d7bae5311a2f0a33c0a82c88d2c5b49d76f",
"productionDiffEmpty": true,
"canonicalDescriptorProbeCommit": "642aefe3",
"testSourceSha256": "e695783e05787d94bf5d167b25b1c48b446b800c28259f023c28ed6012d737d1",
"publishCommand": "reused self-contained artifact: /private/tmp/opcua2-server-linux-diagnostic-20261110a/app",
"appPath": "/private/tmp/opcua2-server-linux-diagnostic-20261110a/app",
"apphost": {
"format": "ELF64 AArch64",
"sha256": "97531b8005df9dc8b129d2b22ba2049cf572d5d970046f7e8644ec632e860032"
},
"runtimeConfig": {
"runtimeOptions": {
"tfm": "net10.0",
"includedFrameworks": [
{
"name": "Microsoft.NETCore.App",
"version": "10.0.14"
},
{
"name": "Microsoft.AspNetCore.App",
"version": "10.0.14"
}
],
"configProperties": {
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
"System.Reflection.NullabilityInfoContext.IsSupported": true,
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
}
}
},
"sdkDependencies": [
"OPCFoundation.NetStandard.Opc.Ua.Client/2.0.1",
"OPCFoundation.NetStandard.Opc.Ua.Configuration/2.0.1",
"OPCFoundation.NetStandard.Opc.Ua.Core.Schema/2.0.1",
"OPCFoundation.NetStandard.Opc.Ua.Core.Types/2.0.1",
"OPCFoundation.NetStandard.Opc.Ua.Core/2.0.1",
"OPCFoundation.NetStandard.Opc.Ua.Security.Certificates/2.0.1",
"OPCFoundation.NetStandard.Opc.Ua.Server/2.0.1",
"OPCFoundation.NetStandard.Opc.Ua.Types/2.0.1"
],
"image": {
"Id": "sha256:b04611ee9e1b7d36797012ed921962c57189cb4dbb3dff12afb8e158110f293b",
"RepoDigests": [
"mcr.microsoft.com/dotnet/sdk@sha256:e362a8dbcd691522456da26a5198b8f3ca1d7641c95624fadc5e3e82678bd08a"
],
"Architecture": "arm64",
"Os": "linux"
},
"hostDotnet": ".NET SDK:\n Version: 10.0.403\n Commit: 5a2162bea6\n Workload version: 10.0.400-manifests.a00bebb6\n MSBuild version: 18.9.15+5a2162bea\n\nRuntime Environment:\n OS Name: Mac OS X\n OS Version: 26.5\n OS Platform: Darwin\n RID: osx-arm64\n Base Path: /opt/homebrew/Cellar/dotnet/10.0.403/libexec/sdk/10.0.403/\n\n.NET workloads installed:\nThere are no installed workloads to display.\nConfigured to use workload sets when installing new manifests.\nNo workload sets are installed. Run \"dotnet workload restore\" to install a workload set.\n\nHost:\n Version: 10.0.14\n Architecture: arm64\n Commit: 0427b9abbe\n\n.NET SDKs installed:\n 10.0.403 [/opt/homebrew/Cellar/dotnet/10.0.403/libexec/sdk]\n\n.NET runtimes installed:\n Microsoft.AspNetCore.App 10.0.14 [/opt/homebrew/Cellar/dotnet/10.0.403/libexec/shared/Microsoft.AspNetCore.App]\n Microsoft.NETCore.App 10.0.14 [/opt/homebrew/Cellar/dotnet/10.0.403/libexec/shared/Microsoft.NETCore.App]\n\nOther architectures found:\n None\n\nEnvironment variables:\n DOTNET_ROOT [/opt/homebrew/Cellar/dotnet/10.0.403/libexec]\n\nglobal.json file:\n /Users/dohertj2/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/global.json\n\nLearn more:\n https://aka.ms/dotnet/info\n\nDownload .NET:\n https://aka.ms/dotnet/download\n",
"network": "none",
"mode": "diagnostic",
"durationSeconds": 90,
"startedUtc": "2026-11-10T18:06:00Z"
}
@@ -0,0 +1,12 @@
[
{
"control": "short_diagnostic_cannot_satisfy_full",
"status": "passed",
"observedRejection": "Duration header mismatch"
},
{
"control": "wrong_executed_test_count_rejected",
"status": "passed",
"observedRejection": "TRX expected exact passed/executed count 1: /tmp/opcua2-server-linux-diagnostic-20261110b/task/results/descriptor-controls.trx"
}
]
@@ -0,0 +1,29 @@
{
"diagnosticExitCode": 0,
"descriptorControlTestsExecuted": 2,
"lifecycleTestsExecuted": 1,
"fullDurationCliGuardExitCode": 2,
"currentLauncherRevalidatedExistingEvidence": true,
"rawArtifactRoot": "/private/tmp/opcua2-server-linux-diagnostic-20261110c",
"publishArtifactRoot": "/private/tmp/opcua2-server-linux-diagnostic-20261110a/app",
"noFullRunPerformed": true,
"sourceProductionDiffFrom7b353d7bEmpty": true,
"harnessFiles": [
{
"path": "scripts/validation/opcua-server-lifecycle-linux/.gitignore",
"sha256": "32dae3052f331ee34d628ef535709b301259a45df7c7522c4d35dcf49873f00b"
},
{
"path": "scripts/validation/opcua-server-lifecycle-linux/README.md",
"sha256": "1a67d8a6bb4b604bad0f6772ea450306a1e5313723a755e9985d1a739b77f72c"
},
{
"path": "scripts/validation/opcua-server-lifecycle-linux/container.sh",
"sha256": "2a27d66e36d61431e6d413afe9d9d5d22959e82d9bf520767140b5d738487b31"
},
{
"path": "scripts/validation/opcua-server-lifecycle-linux/run.py",
"sha256": "770f164588e90df2c4a4fcc883ca82fc17a1037c80f62fa2b40e92ce511d6f15"
}
]
}
+183
View File
@@ -0,0 +1,183 @@
#!/usr/bin/env python3
"""Run the unchanged SDK2 server lifecycle test in isolated Linux ARM64."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import shutil
import struct
import subprocess
import time
import uuid
import xml.etree.ElementTree as ET
HERE = Path(__file__).resolve().parent
ROOT = HERE.parents[2]
PROJECT = ROOT / 'tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.csproj'
APPNAME = 'ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests'
TARGET = 'Repeated_lifecycles_return_resources_to_a_steady_baseline'
BASE = '7b353d7bae5311a2f0a33c0a82c88d2c5b49d76f'
def write(path, value):
path.write_text(json.dumps(value, indent=2) + '\n')
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def command(argv, log, timeout, **kwargs):
with log.open('w') as stream:
result = subprocess.run([str(x) for x in argv], stdout=stream, stderr=subprocess.STDOUT, timeout=timeout, **kwargs)
return result.returncode
def trx(path, count):
doc = ET.parse(path)
ns = {'t': 'http://microsoft.com/schemas/VisualStudio/TeamTest/2010'}
counts = doc.find('.//t:Counters', ns)
results = doc.findall('.//t:UnitTestResult', ns)
if counts is None or any(int(counts.attrib[k]) != count for k in ('total', 'executed', 'passed')):
raise RuntimeError('TRX expected exact passed/executed count ' + str(count) + ': ' + str(path))
if len(results) != count or any(r.attrib['outcome'] != 'Passed' for r in results):
raise RuntimeError('TRX missing or non-passing result: ' + str(path))
for key in ('failed', 'error', 'timeout', 'aborted', 'notExecuted'):
if int(counts.attrib.get(key, '0')):
raise RuntimeError('TRX has nonzero ' + key)
return {'counts': counts.attrib, 'tests': [r.attrib['testName'] for r in results]}
def validate_evidence(task, seconds, full):
rows = [json.loads(line) for line in (task / 'soak.jsonl').read_text().splitlines()]
starts = [r for r in rows if r['kind'] == 'start']
complete = [r for r in rows if r['kind'] == 'complete']
if len(starts) != 1 or len(complete) != 1 or any(r['kind'] == 'failed' for r in rows):
raise RuntimeError('Expected one start and one complete with no failed evidence row')
start, done = starts[0], complete[0]
if start['requestedSeconds'] != seconds or start['minimumFullSeconds'] != 7200:
raise RuntimeError('Duration header mismatch')
expected_mode = 'full' if full else 'diagnostic'
if start['mode'] != expected_mode or done['mode'] != expected_mode or done['seconds'] < seconds:
raise RuntimeError('Real duration/completion mode mismatch')
if start['limits'] != {'retainedManagedGrowthBytes': 64 << 20, 'rssGrowthBytes': 128 << 20, 'fdGrowth': 32}:
raise RuntimeError('Canonical test resource budgets changed')
if done['satisfiesTwoHourDuration'] != full or (full and done['seconds'] < 7200):
raise RuntimeError('Two-hour gate mismatch')
samples = [r for r in rows if r['kind'] == 'quiescent']
active = [r for r in rows if r['kind'] == 'active']
stalls = [r for r in rows if r['kind'] == 'network-stall-recovered']
restarts = [r for r in rows if r['kind'] == 'restart']
if done['cycles'] < 4 or done['restarts'] != done['cycles'] // 4:
raise RuntimeError('Missing actual lifecycle/restart coverage')
if not (len(samples) == len(active) == len(stalls) == done['cycles']) or len(restarts) != done['restarts']:
raise RuntimeError('Incomplete cycle/stall/restart evidence counts')
if not start['sdk'].startswith('2.0.1+'):
raise RuntimeError('Runtime SDK header mismatch')
return {'start': start, 'complete': done, 'rowCounts': {k: sum(r['kind'] == k for r in rows) for k in sorted({r['kind'] for r in rows})},
'firstResources': samples[0]['resources'], 'baselineResources': samples[2]['resources'], 'lastResources': samples[-1]['resources']}
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--output', required=True, type=Path, help='Fresh output including task private PKI; do not commit the whole directory')
parser.add_argument('--duration', type=int, default=90)
parser.add_argument('--full', action='store_true')
parser.add_argument('--published-app', type=Path, help='Reuse immutable self-contained publish from this launcher/recorded matching build')
parser.add_argument('--image', default='mcr.microsoft.com/dotnet/sdk:10.0.103-noble')
args = parser.parse_args()
if (args.full and args.duration < 7200) or (not args.full and not 60 <= args.duration <= 120):
parser.error('full requires duration >=7200; diagnostic requires 60..120 seconds')
output = args.output.resolve()
output.mkdir(parents=True, exist_ok=False)
os.chmod(output, 0o700)
task = output / 'task'
task.mkdir()
revision = subprocess.check_output(['git', '-C', str(ROOT), 'rev-parse', 'HEAD'], text=True).strip()
production_diff = subprocess.check_output(['git', '-C', str(ROOT), 'diff', BASE, 'HEAD', '--', 'src', 'Directory.Packages.props', 'Directory.Build.props'], text=True)
if production_diff:
raise RuntimeError('Production/package source differs from recorded 7b353d7b compatibility build; review required')
image = json.loads(subprocess.check_output(['docker', 'image', 'inspect', args.image, '--format', '{{json .}}'], text=True))
if image['Architecture'] != 'arm64' or image['Os'] != 'linux':
raise RuntimeError('Expected cached official Linux ARM64 image')
app = args.published_app.resolve() if args.published_app else output / 'app'
build_cmd = ['dotnet', 'publish', str(PROJECT), '-c', 'Release', '-r', 'linux-arm64', '--self-contained', 'true',
'-p:RuntimeFrameworkVersion=10.0.14', '-p:PublishSingleFile=false', '-p:PublishTrimmed=false', '-p:UseAppHost=true',
'--artifacts-path', str(output / 'build-artifacts'), '-o', str(app), '-m:1', '--nologo']
if not args.published_app:
status = command(build_cmd, output / 'publish.log', 600)
if status:
raise RuntimeError('Self-contained Linux publish failed: ' + str(status))
receipt_path = app.parent / 'publish-receipt.json'
receipt = json.loads(receipt_path.read_text()) if args.published_app else {
'sourceRevision': revision, 'command': build_cmd,
'hostDotnet': subprocess.check_output(['dotnet', '--info'], text=True),
'testSourceSha256': sha(PROJECT.parent / 'Sdk2LifecycleSoakTests.cs')}
if receipt['testSourceSha256'] != sha(PROJECT.parent / 'Sdk2LifecycleSoakTests.cs'):
raise RuntimeError('Reused publish test source differs from current canonical source')
apphost = app / APPNAME
magic = apphost.read_bytes()[:20]
if magic[:4] != b'\x7fELF' or magic[4] != 2 or struct.unpack('<H', magic[18:20])[0] != 183:
raise RuntimeError('xUnit v3 apphost must be Linux AArch64 ELF64, not macOS Mach-O')
runtime = json.loads((app / (APPNAME + '.runtimeconfig.json')).read_text())
frameworks = runtime['runtimeOptions'].get('includedFrameworks', [])
if not any(f['name'] == 'Microsoft.NETCore.App' and f['version'] == '10.0.14' for f in frameworks):
raise RuntimeError('Test app must carry self-contained runtime 10.0.14')
deps = json.loads((app / (APPNAME + '.deps.json')).read_text())
sdkdeps = {k: v for k, v in deps['libraries'].items() if k.startswith('OPCFoundation.')}
if not sdkdeps or any(k.rsplit('/', 1)[-1] != '2.0.1' for k in sdkdeps):
raise RuntimeError('Expected only OPC Foundation SDK 2.0.1 dependencies')
manifest = [{'name': p.name, 'bytes': p.stat().st_size, 'sha256': sha(p)} for p in sorted(app.glob('*')) if p.is_file()]
if args.published_app and (receipt['apphostSha256'] != sha(apphost)
or receipt['testAssemblySha256'] != sha(app / (APPNAME + '.dll'))):
raise RuntimeError('Reused publish has changed since its receipt')
if not args.published_app:
receipt.update({'apphostSha256': sha(apphost), 'testAssemblySha256': sha(app / (APPNAME + '.dll'))})
write(receipt_path, receipt)
write(output / 'publish-receipt.json', receipt)
write(output / 'artifact-manifest.json', manifest)
source = {'launcherSourceRevision': revision, 'publishedSourceRevision': receipt['sourceRevision'],
'productionEquivalentTo': BASE, 'productionDiffEmpty': True,
'canonicalDescriptorProbeCommit': '642aefe3', 'testSourceSha256': sha(PROJECT.parent / 'Sdk2LifecycleSoakTests.cs'),
'publishCommand': build_cmd if not args.published_app else 'reused self-contained artifact: ' + str(app),
'appPath': str(app), 'apphost': {'format': 'ELF64 AArch64', 'sha256': sha(apphost)}, 'runtimeConfig': runtime,
'sdkDependencies': sorted(sdkdeps), 'image': {k: image.get(k) for k in ('Id', 'RepoDigests', 'Architecture', 'Os')},
'hostDotnet': subprocess.check_output(['dotnet', '--info'], text=True),
'network': 'none', 'mode': 'full' if args.full else 'diagnostic', 'durationSeconds': args.duration,
'startedUtc': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())}
write(output / 'source.json', source)
shutil.copy2(HERE / 'container.sh', task / 'container.sh')
name = 'otopcua-server-linux-soak-' + uuid.uuid4().hex[:12]
cmd = ['docker', 'run', '--rm', '--name', name, '--network', 'none',
'-e', 'OTOPCUA_SDK2_SOAK_MODE=' + ('full' if args.full else 'diagnostic'),
'-e', 'OTOPCUA_SDK2_SOAK_SECONDS=' + str(args.duration), '-e', 'OTOPCUA_SOAK_BUILD_SHA=' + revision,
'-v', str(app) + ':/app:ro', '-v', str(task) + ':/task', image['Id'], 'bash', '/task/container.sh']
write(output / 'command.json', {'argv': cmd, 'timeoutSeconds': args.duration + 300})
started = time.monotonic()
try:
status = command(cmd, output / 'container.log', args.duration + 300)
except BaseException:
subprocess.run(['docker', 'rm', '-f', name], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=20)
raise
write(output / 'result.json', {'status': 'failed', 'containerExitCode': status,
'containerElapsedSeconds': time.monotonic() - started,
'validation': 'pending TRX and completion validation'})
try:
controls = trx(task / 'results' / 'descriptor-controls.trx', 2)
test = trx(task / 'results' / 'soak.trx', 1)
if TARGET not in test['tests'][0] or status:
raise RuntimeError('Soak test did not complete successfully; container exit=' + str(status))
evidence = validate_evidence(task, args.duration, args.full)
except Exception as error:
write(output / 'result.json', {'status': 'failed', 'containerExitCode': status,
'containerElapsedSeconds': time.monotonic() - started,
'validationError': str(error)})
raise
write(output / 'result.json', {'status': 'passed', 'containerExitCode': status, 'containerElapsedSeconds': time.monotonic() - started,
'descriptorControls': controls, 'soakTest': test, 'evidence': evidence})
print(json.dumps({'output': str(output), 'status': 'passed', 'complete': evidence['complete']}, indent=2))
if __name__ == '__main__':
main()