86 lines
4.0 KiB
Bash
86 lines
4.0 KiB
Bash
#!/usr/bin/env bash
|
|
# Execute the immutable self-contained apphost through the cached Linux VSTest controller.
|
|
verify_mapped_coreclr() {
|
|
awk -v identity="$2" '
|
|
$6 ~ /\/libcoreclr.so$/ {
|
|
if (NF != 6 || ($5 " " $6) != identity) bad = 1
|
|
else matched = 1
|
|
}
|
|
END { exit (matched && !bad) ? 0 : 1 }
|
|
' "$1"
|
|
}
|
|
|
|
# The offline controls source only the mapping check above.
|
|
if [[ ${BASH_SOURCE[0]} != "$0" ]]; then return 0; fi
|
|
|
|
set -euo pipefail
|
|
umask 077
|
|
app=ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests
|
|
test_class="$app.Sdk2LifecycleSoakTests"
|
|
[[ -d /task/tmp && ! -L /task/tmp && -d /tmp && ! -L /tmp ]]
|
|
[[ $(stat -c '%a' /task/tmp) == 700 && $(stat -c '%d:%i' /task/tmp) == "$(stat -c '%d:%i' /tmp)" ]]
|
|
mkdir -p /task/data /task/cli /task/results
|
|
export TMPDIR=/task/tmp XDG_DATA_HOME=/task/data DOTNET_CLI_HOME=/task/cli
|
|
export OTOPCUA_SDK2_SOAK=1 OTOPCUA_SDK2_SOAK_MODE=late-slope OTOPCUA_SDK2_SOAK_SECONDS=7200
|
|
export OTOPCUA_SDK2_SOAK_OUTPUT=/task/resources.jsonl OPCUA_CERTIFICATE_LEAK_TRACKING=1
|
|
export DOTNET_CLI_TELEMETRY_OPTOUT=1 DOTNET_NOLOGO=1
|
|
[[ $(uname -s) == Linux && $(uname -m) == aarch64 && -d /proc/self/fd ]]
|
|
[[ ${OTOPCUA_SOAK_BUILD_SHA:-} =~ ^[0-9a-f]{40}$ ]]
|
|
dotnet --info > /task/controller-runtime.txt
|
|
|
|
dotnet vstest "/app/$app.dll" \
|
|
--TestCaseFilter:"FullyQualifiedName~$test_class.Descriptor_probe_" \
|
|
--ResultsDirectory:/task/results '--Logger:trx;LogFileName=descriptor-controls.trx' > /task/descriptor-controls.log 2>&1
|
|
|
|
# Verify actual execution before starting the long test. The host parses the complete TRX independently.
|
|
controls=/task/results/descriptor-controls.trx
|
|
counters=$(grep -E '^[[:space:]]*<Counters ' "$controls")
|
|
[[ $(grep -Ec '^[[:space:]]*<Counters ' "$controls") == 1 ]]
|
|
for attribute in total=2 executed=2 passed=2 failed=0 notExecuted=0 error=0 timeout=0 aborted=0; do
|
|
[[ $counters == *" ${attribute%=*}=\"${attribute#*=}\""* ]]
|
|
done
|
|
[[ $(grep -Ec '^[[:space:]]*<UnitTestResult ' "$controls") == 2 ]]
|
|
for name in Descriptor_probe_observes_an_open_PKI_file_through_a_symlink_alias_and_its_close \
|
|
Descriptor_probe_times_out_and_reaps_a_process_that_keeps_both_streams_open; do
|
|
result=$(grep -E '^[[:space:]]*<UnitTestResult ' "$controls" | grep -F "testName=\"$test_class.$name\"")
|
|
[[ $result == *' outcome="Passed"'* && $result != *$'\n'* ]]
|
|
done
|
|
|
|
vstest_pid=
|
|
cleanup() {
|
|
if [[ -n "$vstest_pid" ]]; then kill "$vstest_pid" 2>/dev/null || true; fi
|
|
}
|
|
trap cleanup EXIT
|
|
dotnet vstest "/app/$app.dll" \
|
|
--TestCaseFilter:"FullyQualifiedName=$test_class.Repeated_lifecycles_return_resources_to_a_steady_baseline" \
|
|
--ResultsDirectory:/task/results '--Logger:trx;LogFileName=late-slope.trx' > /task/test.log 2>&1 &
|
|
vstest_pid=$!
|
|
|
|
# The canonical startup deadline is 120 seconds. Allow controller startup before observing its first complete row.
|
|
proof_deadline=$((SECONDS + 150))
|
|
observed=0
|
|
while ((SECONDS < proof_deadline)) && kill -0 "$vstest_pid" 2>/dev/null; do
|
|
if [[ -s /task/resources.jsonl ]] && IFS= read -r header < /task/resources.jsonl; then
|
|
[[ $header == *'"kind":"start"'* && $header == *'"mode":"late-slope"'* ]]
|
|
pid=$(sed -n 's/.*"processId":\([1-9][0-9]*\),.*/\1/p' <<< "$header")
|
|
[[ $pid =~ ^[1-9][0-9]*$ ]]
|
|
executable=$(readlink "/proc/$pid/exe")
|
|
[[ $executable == "/app/$app" ]]
|
|
runtime=/app/libcoreclr.so
|
|
verify_mapped_coreclr "/proc/$pid/maps" "$(stat -c '%i %n' "$runtime")"
|
|
runtime_hash=$(sha256sum "$runtime")
|
|
printf 'targetPid=%s\nactualExecutable=%s\nmappedCoreClr=%s\ncoreClrSha256=%s\n' \
|
|
"$pid" "$executable" "$runtime" "${runtime_hash%% *}" > /task/target-runtime.txt
|
|
observed=1
|
|
break
|
|
fi
|
|
sleep 0.1
|
|
done
|
|
if [[ $observed != 1 ]]; then kill "$vstest_pid" 2>/dev/null || true; fi
|
|
test_status=0
|
|
wait "$vstest_pid" || test_status=$?
|
|
vstest_pid=
|
|
printf '%s\n' "$test_status" > /task/test-exit-status.txt
|
|
if [[ $test_status != 0 ]]; then exit "$test_status"; fi
|
|
[[ $observed == 1 ]]
|