From 9221fe95b6fd65915a9736f6d49b9af060c17437 Mon Sep 17 00:00:00 2001 From: Altay Date: Sun, 20 Sep 2026 17:11:58 +0300 Subject: [PATCH 1/2] fix(harness): scope local launch proof to smoke test --- docs/harness.md | 7 ++++--- scripts/prove.sh | 3 ++- scripts/test-emulator.sh | 29 +++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/docs/harness.md b/docs/harness.md index b6048788..a57fb5a8 100644 --- a/docs/harness.md +++ b/docs/harness.md @@ -48,9 +48,10 @@ One command from source to a verified, evidenced launch: ./scripts/prove.sh tv --record # also captures a screen recording ``` -Verification is the instrumented smoke test (`LaunchSmokeTest`), run through -`connectedAndroidTest` on the booted emulator. It asserts RESUMED state, a -3 s stability window, and real composited pixels (mean luma) via platform +Verification explicitly selects the instrumented smoke test (`LaunchSmokeTest`) +through `connectedAndroidTest` on the booted emulator. Opt-in feature suites and +the separately scheduled OAuth regression are not part of this launch proof. +It asserts RESUMED state, a 3 s stability window, and real composited pixels (mean luma) via platform test APIs; a crash or ANR fails the instrumentation. The exit code is the proof. The `verifyMobileLaunchProof` and `verifyTvLaunchProof` tasks also require the named smoke test's successful XML result; an empty, skipped, or diff --git a/scripts/prove.sh b/scripts/prove.sh index de743215..95546e8d 100755 --- a/scripts/prove.sh +++ b/scripts/prove.sh @@ -249,7 +249,8 @@ esac smoke_out="$(mktemp)" run_smoke_test() { - (cd "${REPO_ROOT}" && ANDROID_SERIAL="${SERIAL}" ./gradlew "${CONNECTED_TASK}") >"${smoke_out}" 2>&1 + (cd "${REPO_ROOT}" && ANDROID_SERIAL="${SERIAL}" ./gradlew "${CONNECTED_TASK}" \ + -Pandroid.testInstrumentationRunnerArguments.class=io.putdotio.android.LaunchSmokeTest) >"${smoke_out}" 2>&1 } # Only the black-render assertion earns a retry; crashes, ANRs, and other diff --git a/scripts/test-emulator.sh b/scripts/test-emulator.sh index f0a83af4..c9d4d5b2 100755 --- a/scripts/test-emulator.sh +++ b/scripts/test-emulator.sh @@ -105,6 +105,7 @@ case "$*" in pid="$(cat "${state}/emulator-pid" 2>/dev/null || true)" [[ "${pid}" =~ ^[0-9]+$ ]] && kill "${pid}" 2>/dev/null || true ;; + *" install -r "*) echo "Success" ;; *" settings put global hide_error_dialogs 1") ;; *" getprop sys.boot_completed") echo 1 ;; *" getprop ro.build.version.sdk") @@ -502,6 +503,34 @@ grep -q " install " "${state}/adb-calls" && fail "negative proof attempted app i [[ "$(<"${state}/running")" == "1" ]] || fail "negative proof stopped a reused emulator" grep -q " emu kill" "${state}/adb-calls" && fail "negative proof killed a reused emulator" +# Exercise the real launch-proof script through its Gradle boundary without +# starting a device or reaching screenshot capture. +proof_repo="${tmpdir}/proof-repo" +mkdir -p "${proof_repo}/scripts" +cp "${REPO_ROOT}/scripts/"{prove,emulator,lib}.sh "${proof_repo}/scripts/" +cat > "${proof_repo}/gradlew" <<'EOF' +#!/usr/bin/env bash +set -euo pipefail +[[ "$#" == 2 && "$1" == ":app:verifyMobileLaunchProof" && + "$2" == "-Pandroid.testInstrumentationRunnerArguments.class=io.putdotio.android.LaunchSmokeTest" ]] || { + echo "unscoped instrumentation would run opt-in feature suites" >&2 + exit 1 +} +echo "selected LaunchSmokeTest" >> "${FAKE_STATE_DIR}/proof-selection" +echo "stopping after selected instrumentation boundary" >&2 +exit 1 +EOF +chmod +x "${proof_repo}/gradlew" +reset_avd "${PHONE_AVD}" "${target_image}" 1 +reset_runtime +if PUTIO_PROVE_APK="${fake_apk}" "${proof_repo}/scripts/prove.sh" mobile --skip-build >"${prove_out}" 2>&1; then + fail "launch proof ignored its failed instrumentation gate" +fi +[[ -f "${state}/proof-selection" ]] || fail "launch proof did not select only LaunchSmokeTest" +[[ "$(wc -l < "${state}/proof-selection" | tr -d ' ')" == "1" ]] || fail "non-render failure retried instrumentation" +[[ "$(<"${state}/running")" == "1" ]] || fail "launch-proof failure stopped a reused emulator" +grep -q '^PROOF FAIL mobile$' "${prove_out}" || fail "launch-proof failure omitted its failure marker" + # A readiness failure after this invocation starts an emulator must stop that # exact process. prove.sh must also delete an ephemeral registration it created. reset_avd "${PHONE_AVD}" "${target_image}" 0 From ba23e4d394421223c749d0386acd8f3126dd2ca2 Mon Sep 17 00:00:00 2001 From: Altay Date: Sun, 20 Sep 2026 17:16:00 +0300 Subject: [PATCH 2/2] docs(harness): name the launch proof tasks --- docs/harness.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/harness.md b/docs/harness.md index a57fb5a8..735b00bd 100644 --- a/docs/harness.md +++ b/docs/harness.md @@ -49,8 +49,10 @@ One command from source to a verified, evidenced launch: ``` Verification explicitly selects the instrumented smoke test (`LaunchSmokeTest`) -through `connectedAndroidTest` on the booted emulator. Opt-in feature suites and -the separately scheduled OAuth regression are not part of this launch proof. +through `verifyMobileLaunchProof` or `verifyTvLaunchProof` on the booted emulator. +These tasks run the matching production-debug connected instrumentation task. +Opt-in feature suites and the separately scheduled OAuth regression are not +part of this launch proof. It asserts RESUMED state, a 3 s stability window, and real composited pixels (mean luma) via platform test APIs; a crash or ANR fails the instrumentation. The exit code is the proof. The `verifyMobileLaunchProof` and `verifyTvLaunchProof` tasks also