Files

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 ]]