#!/usr/bin/env bash set -euo pipefail # ======================================== # Phase 2 Testing Script – Force Stop Recovery # ======================================== # Source shared library SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPT_DIR}/alarm-test-lib.sh" # Phase 2 specific configuration # Log tags / patterns (matched to actual ReactivationManager logs) FORCE_STOP_SCENARIO_VALUE="FORCE_STOP" COLD_START_SCENARIO_VALUE="COLD_START" NONE_SCENARIO_VALUE="NONE" BOOT_SCENARIO_VALUE="BOOT" # Allow selecting specific tests on the command line (e.g. ./test-phase2.sh 2 3) SELECTED_TESTS=() # ------------------------------------------------------------------------------ # TEST 1 – Force Stop with Cleared Alarms # ------------------------------------------------------------------------------ test1_force_stop_cleared_alarms() { section "TEST 1: Force Stop – Alarms Cleared" echo "Purpose: Verify force stop detection and alarm rescheduling when alarms are cleared." pause substep "Step 1: Launch app & check plugin status" launch_app ui_prompt "In the app UI, verify plugin status:\n\n ⚙️ Plugin Settings: ✅ Configured\n 🔌 Native Fetcher: ✅ Configured\n\nIf either shows ❌ or 'Not configured', click 'Configure Plugin', wait until both are ✅, then press Enter." ui_prompt "Now schedule at least one future notification (e.g., click 'Test Notification' to schedule for a few minutes in the future)." substep "Step 2: Verify alarms are scheduled" show_alarms local before_count before_count="$(count_alarms)" info "Alarm count before force stop: $before_count" if [[ "$before_count" -eq 0 ]]; then warn "No alarms found before force stop; TEST 1 may not be meaningful." fi pause substep "Step 3: Force stop app (should clear alarms on many devices)" force_stop_app substep "Step 4: Check alarms after force stop" local after_count after_count="$(count_alarms)" info "Alarm count after force stop: $after_count" show_alarms if [[ "$after_count" -gt 0 ]]; then warn "Alarms still present after force stop. This device/OS may not clear alarms on force stop." warn "TEST 1 will continue but may not fully validate FORCE_STOP scenario." fi pause substep "Step 5: Launch app (triggers recovery) and capture logs" clear_logs launch_app sleep 5 # give recovery a moment to run info "Collecting recovery logs..." local logs logs="$(get_recovery_logs)" echo "$logs" local scenario rescheduled verified errors scenario="$(extract_scenario_from_logs "$logs")" rescheduled="$(extract_field_from_logs "$logs" "rescheduled")" verified="$(extract_field_from_logs "$logs" "verified")" errors="$(extract_field_from_logs "$logs" "errors")" echo info "Parsed recovery summary:" echo " scenario = ${scenario:-}" echo " rescheduled= ${rescheduled}" echo " verified = ${verified}" echo " errors = ${errors}" echo if [[ "$errors" -gt 0 ]]; then error "Recovery reported errors>0 (errors=$errors)" fi if [[ "$scenario" == "$FORCE_STOP_SCENARIO_VALUE" && "$rescheduled" -gt 0 ]]; then ok "TEST 1 PASSED: Force stop detected and alarms rescheduled (scenario=$scenario, rescheduled=$rescheduled)." elif [[ "$scenario" == "$FORCE_STOP_SCENARIO_VALUE" && "$rescheduled" -eq 0 ]]; then warn "TEST 1: scenario=FORCE_STOP but rescheduled=0. Check implementation or logs." elif [[ "$after_count" -gt 0 ]]; then info "TEST 1: Device/emulator kept alarms after force stop; FORCE_STOP scenario may not trigger here." if [[ "$rescheduled" -gt 0 ]]; then info "Recovery still worked (rescheduled=$rescheduled), but scenario was ${scenario:-COLD_START} instead of FORCE_STOP" fi else warn "TEST 1: Expected FORCE_STOP scenario not clearly detected. Review logs and scenario detection logic." info "Scenario detected: ${scenario:-}, rescheduled=$rescheduled" fi substep "Step 6: Verify alarms are rescheduled in AlarmManager" show_alarms } # ------------------------------------------------------------------------------ # TEST 2 – Force Stop / Process Stop with Intact Alarms # ------------------------------------------------------------------------------ test2_force_stop_intact_alarms() { section "TEST 2: Force Stop / Process Stop – Alarms Intact" echo "Purpose: Verify that heavy FORCE_STOP recovery does not run when alarms are still present." pause substep "Step 1: Launch app & schedule notifications" launch_app ui_prompt "In the app UI, ensure plugin is configured and schedule at least one future notification.\n\nPress Enter when done." substep "Step 2: Verify alarms are scheduled" show_alarms local before before="$(count_alarms)" info "Alarm count before stop: $before" if [[ "$before" -eq 0 ]]; then warn "No alarms found; TEST 2 may not be meaningful." fi pause substep "Step 3: Simulate a 'soft' stop or process kill that does NOT clear alarms" info "Killing app process (non-destructive - may not clear alarms)..." $ADB_BIN shell am kill "$APP_ID" || true sleep 2 ok "Kill signal sent (soft stop)" substep "Step 4: Verify alarms are still scheduled" local after after="$(count_alarms)" info "Alarm count after soft stop: $after" show_alarms if [[ "$after" -eq 0 ]]; then warn "Alarms appear cleared after soft stop; this environment may not distinguish TEST 2 well." fi pause substep "Step 5: Relaunch app and check recovery logs" clear_logs launch_app sleep 5 info "Collecting recovery logs..." local logs logs="$(get_recovery_logs)" echo "$logs" local scenario rescheduled missed verified errors scenario="$(extract_scenario_from_logs "$logs")" rescheduled="$(extract_field_from_logs "$logs" "rescheduled")" missed="$(extract_field_from_logs "$logs" "missed")" verified="$(extract_field_from_logs "$logs" "verified")" errors="$(extract_field_from_logs "$logs" "errors")" echo info "Parsed recovery summary:" echo " scenario = ${scenario:-}" echo " rescheduled= ${rescheduled}" echo " missed = ${missed}" echo " verified = ${verified}" echo " errors = ${errors}" echo if [[ "$errors" -gt 0 ]]; then error "Recovery reported errors>0 (errors=$errors)" fi if [[ "$after" -gt 0 && "$rescheduled" -eq 0 && "$scenario" != "$FORCE_STOP_SCENARIO_VALUE" ]]; then ok "TEST 2 PASSED: Alarms remained intact, and FORCE_STOP scenario did not run (scenario=$scenario, rescheduled=0)." else warn "TEST 2: Verify that FORCE_STOP recovery didn't misfire when alarms were intact." info "Scenario=${scenario:-}, rescheduled=$rescheduled, after_count=$after" fi } # ------------------------------------------------------------------------------ # TEST 3 – First Launch / Empty DB Safeguard # ------------------------------------------------------------------------------ test3_first_launch_no_schedules() { section "TEST 3: First Launch / No Schedules Safeguard" echo "Purpose: Ensure force-stop recovery is NOT triggered when DB is empty or plugin isn't configured." pause substep "Step 1: Uninstall app to clear DB/state" set +e $ADB_BIN uninstall "$APP_ID" >/dev/null 2>&1 set -e ok "App uninstalled (state cleared)" substep "Step 2: Reinstall app" if $ADB_BIN install -r "$APK_PATH"; then ok "App installed" else error "Reinstall failed" exit 1 fi info "Clearing logcat..." $ADB_BIN logcat -c ok "Logs cleared" pause substep "Step 3: Launch app for the first time" launch_app sleep 5 substep "Step 4: Collect logs and ensure no force-stop recovery ran" local logs logs="$(get_recovery_logs)" echo "$logs" local scenario rescheduled scenario="$(extract_scenario_from_logs "$logs")" rescheduled="$(extract_field_from_logs "$logs" "rescheduled")" echo info "Parsed summary:" echo " scenario = ${scenario:-}" echo " rescheduled= ${rescheduled}" echo if [[ -z "$logs" ]]; then ok "TEST 3 PASSED: No force-stop recovery logs on first launch." elif [[ "$scenario" == "$NONE_SCENARIO_VALUE" && "$rescheduled" -eq 0 ]]; then ok "TEST 3 PASSED: NONE scenario logged with rescheduled=0 on first launch." elif [[ "$rescheduled" -gt 0 ]]; then warn "TEST 3: rescheduled>0 on first launch / empty DB. Check that force-stop recovery isn't misfiring." else info "TEST 3: Logs present but no rescheduling; review scenario handling to ensure it's explicit about NONE / FIRST_LAUNCH." fi } # ------------------------------------------------------------------------------ # Main # ------------------------------------------------------------------------------ main() { # Allow selecting specific tests: e.g. `./test-phase2.sh 1 3` if [[ "$#" -gt 0 && ( "$1" == "-h" || "$1" == "--help" ) ]]; then echo "Usage: $0 [TEST_IDS...]" echo echo "If no TEST_IDS are given, all tests (1, 2, 3) will run." echo "Examples:" echo " $0 # run all tests" echo " $0 1 # run only TEST 1" echo " $0 2 3 # run only TEST 2 and TEST 3" return 0 fi SELECTED_TESTS=("$@") echo echo "========================================" echo "Phase 2 Testing Script – Force Stop Recovery" echo "========================================" echo echo "This script will guide you through Phase 2 tests." echo "You'll be prompted when UI interaction is needed." echo pause require_adb_device build_app install_app if should_run_test "1" SELECTED_TESTS; then test1_force_stop_cleared_alarms pause fi if should_run_test "2" SELECTED_TESTS; then test2_force_stop_intact_alarms pause fi if should_run_test "3" SELECTED_TESTS; then test3_first_launch_no_schedules fi section "Testing Complete" echo "Test Results Summary (see logs above for details):" echo echo "TEST 1: Force Stop – Alarms Cleared" echo " - Check logs for scenario=$FORCE_STOP_SCENARIO_VALUE and rescheduled>0" echo echo "TEST 2: Force Stop / Process Stop – Alarms Intact" echo " - Verify FORCE_STOP scenario is not incorrectly triggered when alarms are still present" echo echo "TEST 3: First Launch / No Schedules" echo " - Confirm that no force-stop recovery runs, or that NONE/FIRST_LAUNCH scenario is logged with rescheduled=0" echo ok "Phase 2 testing script complete!" echo echo "Next steps:" echo " - Review logs above" echo " - Capture snippets into PHASE2-EMULATOR-TESTING.md" echo " - Update PHASE2-VERIFICATION.md and unified directive status matrix" echo } main "$@"