#!/usr/bin/env bash set -euo pipefail # ======================================== # Phase 3 Testing Script – Boot Recovery # ======================================== # Source shared library SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPT_DIR}/alarm-test-lib.sh" # Phase 3 specific configuration # Log tags / patterns (matched to actual ReactivationManager logs) BOOT_SCENARIO_VALUE="BOOT" NONE_SCENARIO_VALUE="NONE" # Allow selecting specific tests on the command line (e.g. ./test-phase3.sh 1 3) SELECTED_TESTS=() # Phase 3 specific: override extract_scenario_from_logs to handle boot recovery extract_scenario_from_logs() { local logs="$1" local scen # Looks for "Detected scenario: BOOT" or "Starting boot recovery" format if echo "$logs" | grep -qi "Starting boot recovery\|boot recovery"; then echo "$BOOT_SCENARIO_VALUE" else # Use shared library function as fallback scen="$(grep -oE "${SCENARIO_KEY}[A-Z_]+" <<<"$logs" | tail -n1 | sed "s/${SCENARIO_KEY}//" || true)" echo "$scen" fi } # ------------------------------------------------------------------------------ # TEST 1 – Boot with Future Alarms # ------------------------------------------------------------------------------ test1_boot_future_alarms() { section "TEST 1: Boot with Future Alarms" echo "Purpose: Verify alarms are recreated on boot when schedules have future run times." 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 reboot: $before_count" if [[ "$before_count" -eq 0 ]]; then warn "No alarms found before reboot; TEST 1 may not be meaningful." fi pause substep "Step 3: Reboot emulator" warn "The emulator will reboot now. This will take 30-60 seconds." pause reboot_emulator substep "Step 4: Collect boot recovery logs" info "Collecting recovery logs from boot..." sleep 2 # Give recovery a moment to complete local logs logs="$(get_recovery_logs)" echo "$logs" local missed rescheduled verified errors scenario missed="$(extract_field_from_logs "$logs" "missed")" rescheduled="$(extract_field_from_logs "$logs" "rescheduled")" verified="$(extract_field_from_logs "$logs" "verified")" errors="$(extract_field_from_logs "$logs" "errors")" scenario="$(extract_scenario_from_logs "$logs")" echo info "Parsed recovery summary:" echo " scenario = ${scenario:-}" echo " missed = ${missed}" echo " rescheduled= ${rescheduled}" echo " verified = ${verified}" echo " errors = ${errors}" echo if [[ "$errors" -gt 0 ]]; then error "Recovery reported errors>0 (errors=$errors)" fi substep "Step 5: Verify alarms were recreated" show_alarms local after_count after_count="$(count_alarms)" info "Alarm count after boot: $after_count" if [[ "$scenario" == "$BOOT_SCENARIO_VALUE" && "$rescheduled" -gt 0 ]]; then ok "TEST 1 PASSED: Boot recovery detected and alarms rescheduled (scenario=$scenario, rescheduled=$rescheduled)." elif echo "$logs" | grep -qi "Starting boot recovery\|boot recovery"; then if [[ "$rescheduled" -gt 0 ]]; then ok "TEST 1 PASSED: Boot recovery ran and alarms rescheduled (rescheduled=$rescheduled)." else warn "TEST 1: Boot recovery ran but rescheduled=0. Check implementation or logs." fi else warn "TEST 1: Boot recovery not clearly detected. Review logs and boot receiver implementation." info "Scenario detected: ${scenario:-}, rescheduled=$rescheduled" fi } # ------------------------------------------------------------------------------ # TEST 2 – Boot with Past Alarms # ------------------------------------------------------------------------------ test2_boot_past_alarms() { section "TEST 2: Boot with Past Alarms" echo "Purpose: Verify missed alarms are detected and next occurrence is scheduled on boot." pause substep "Step 1: Launch app & ensure plugin configured" launch_app ui_prompt "In the app UI, verify plugin status:\n\n ⚙️ Plugin Settings: ✅ Configured\n 🔌 Native Fetcher: ✅ Configured\n\nIf needed, click 'Configure Plugin', then press Enter." ui_prompt "Click 'Test Notification' to schedule a notification for 2 minutes in the future.\n\nAfter scheduling, we'll wait for the alarm time to pass, then reboot." substep "Step 2: Wait for alarm time to pass" info "Waiting 3 minutes for scheduled alarm time to pass..." warn "You can manually advance system time if needed (requires root/emulator)" sleep 180 # Wait 3 minutes substep "Step 3: Verify alarm time has passed" info "Alarm time should now be in the past" show_alarms pause substep "Step 4: Reboot emulator" warn "The emulator will reboot now. This will take 30-60 seconds." pause reboot_emulator substep "Step 5: Collect boot recovery logs" info "Collecting recovery logs from boot..." sleep 2 local logs logs="$(get_recovery_logs)" echo "$logs" local missed rescheduled verified errors scenario missed="$(extract_field_from_logs "$logs" "missed")" rescheduled="$(extract_field_from_logs "$logs" "rescheduled")" verified="$(extract_field_from_logs "$logs" "verified")" errors="$(extract_field_from_logs "$logs" "errors")" scenario="$(extract_scenario_from_logs "$logs")" echo info "Parsed recovery summary:" echo " scenario = ${scenario:-}" echo " missed = ${missed}" echo " rescheduled= ${rescheduled}" echo " verified = ${verified}" echo " errors = ${errors}" echo if [[ "$errors" -gt 0 ]]; then error "Recovery reported errors>0 (errors=$errors)" fi if [[ "$missed" -ge 1 && "$rescheduled" -ge 1 ]]; then ok "TEST 2 PASSED: Past alarms detected and next occurrence scheduled (missed=$missed, rescheduled=$rescheduled)." elif [[ "$missed" -ge 1 ]]; then warn "TEST 2: Past alarms detected (missed=$missed) but rescheduled=$rescheduled. Check reschedule logic." else warn "TEST 2: No missed alarms detected. Verify alarm time actually passed before reboot." fi } # ------------------------------------------------------------------------------ # TEST 3 – Boot with No Schedules # ------------------------------------------------------------------------------ test3_boot_no_schedules() { section "TEST 3: Boot with No Schedules" echo "Purpose: Verify boot recovery handles empty database gracefully." 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: Reboot emulator WITHOUT scheduling anything" warn "Do NOT schedule any notifications. The app should have no schedules in the database." warn "The emulator will reboot now. This will take 30-60 seconds." pause reboot_emulator substep "Step 4: Collect boot recovery logs" info "Collecting recovery logs from boot..." sleep 2 local logs logs="$(get_recovery_logs)" echo "$logs" local scenario rescheduled missed scenario="$(extract_scenario_from_logs "$logs")" rescheduled="$(extract_field_from_logs "$logs" "rescheduled")" missed="$(extract_field_from_logs "$logs" "missed")" echo info "Parsed recovery summary:" echo " scenario = ${scenario:-}" echo " rescheduled= ${rescheduled}" echo " missed = ${missed}" echo if [[ -z "$logs" ]]; then ok "TEST 3 PASSED: No recovery logs when there are no schedules (safe behavior)." return fi if echo "$logs" | grep -qiE "No schedules found|No schedules present"; then ok "TEST 3 PASSED: Explicit 'No schedules found' message logged with no rescheduling." elif [[ "$scenario" == "$NONE_SCENARIO_VALUE" && "$rescheduled" -eq 0 ]]; then ok "TEST 3 PASSED: NONE scenario detected with no rescheduling." elif [[ "$rescheduled" -gt 0 ]]; then warn "TEST 3: rescheduled>0 on first launch / empty DB. Check that boot recovery isn't misfiring." else info "TEST 3: Logs present but no rescheduling; review scenario handling to ensure it's explicit about NONE / NO_SCHEDULES." fi } # ------------------------------------------------------------------------------ # TEST 4 – Silent Boot Recovery (App Never Opened) # ------------------------------------------------------------------------------ test4_silent_boot_recovery() { section "TEST 4: Silent Boot Recovery (App Never Opened)" echo "Purpose: Verify boot recovery occurs even when the app is never opened after reboot." pause substep "Step 1: Launch app & ensure plugin configured" launch_app ui_prompt "In the app UI, verify plugin status:\n\n ⚙️ Plugin Settings: ✅ Configured\n 🔌 Native Fetcher: ✅ Configured\n\nIf needed, click 'Configure Plugin', then press Enter." ui_prompt "Click 'Test Notification' to schedule a notification 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 reboot: $before_count" if [[ "$before_count" -eq 0 ]]; then warn "No alarms found; TEST 4 may not be meaningful." fi pause substep "Step 3: Reboot emulator (DO NOT open app after reboot)" warn "IMPORTANT: After reboot, DO NOT open the app. Boot recovery should run silently." warn "The emulator will reboot now. This will take 30-60 seconds." pause reboot_emulator substep "Step 4: Collect boot recovery logs (without opening app)" info "Collecting recovery logs from boot (app was NOT opened)..." sleep 2 local logs logs="$(get_recovery_logs)" echo "$logs" local missed rescheduled verified errors scenario missed="$(extract_field_from_logs "$logs" "missed")" rescheduled="$(extract_field_from_logs "$logs" "rescheduled")" verified="$(extract_field_from_logs "$logs" "verified")" errors="$(extract_field_from_logs "$logs" "errors")" scenario="$(extract_scenario_from_logs "$logs")" echo info "Parsed recovery summary:" echo " scenario = ${scenario:-}" echo " missed = ${missed}" echo " rescheduled= ${rescheduled}" echo " verified = ${verified}" echo " errors = ${errors}" echo substep "Step 5: Verify alarms were recreated (without opening app)" show_alarms local after_count after_count="$(count_alarms)" info "Alarm count after boot (app never opened): $after_count" if [[ "$after_count" -gt 0 && "$rescheduled" -gt 0 ]]; then ok "TEST 4 PASSED: Boot recovery occurred silently and alarms were recreated (rescheduled=$rescheduled) without app launch." elif [[ "$rescheduled" -gt 0 ]]; then ok "TEST 4 PASSED: Boot recovery occurred silently (rescheduled=$rescheduled), but alarm count check unclear." elif echo "$logs" | grep -qi "Starting boot recovery\|boot recovery"; then warn "TEST 4: Boot recovery ran but alarms may not have been recreated. Check logs and implementation." else warn "TEST 4: Boot recovery not detected. Verify boot receiver is registered and has BOOT_COMPLETED permission." fi } # ------------------------------------------------------------------------------ # Main # ------------------------------------------------------------------------------ main() { # Allow selecting specific tests: e.g. `./test-phase3.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, 4) 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" echo " $0 4 # run only TEST 4 (silent boot recovery)" return 0 fi SELECTED_TESTS=("$@") echo echo "========================================" echo "Phase 3 Testing Script – Boot Recovery" echo "========================================" echo echo "This script will guide you through Phase 3 tests." echo "You'll be prompted when UI interaction is needed." echo echo "⚠️ WARNING: This script will reboot the emulator multiple times." echo " Each reboot takes 30-60 seconds." echo pause require_adb_device build_app install_app if should_run_test "1" SELECTED_TESTS; then test1_boot_future_alarms pause fi if should_run_test "2" SELECTED_TESTS; then test2_boot_past_alarms pause fi if should_run_test "3" SELECTED_TESTS; then test3_boot_no_schedules pause fi if should_run_test "4" SELECTED_TESTS; then test4_silent_boot_recovery fi section "Testing Complete" echo "Test Results Summary (see logs above for details):" echo echo "TEST 1: Boot with Future Alarms" echo " - Check logs for scenario=$BOOT_SCENARIO_VALUE and rescheduled>0" echo echo "TEST 2: Boot with Past Alarms" echo " - Check that missed>=1 and rescheduled>=1" echo echo "TEST 3: Boot with No Schedules" echo " - Check that no recovery runs, or NONE scenario is logged with rescheduled=0" echo echo "TEST 4: Silent Boot Recovery" echo " - Check that boot recovery occurred and alarms were recreated without app launch" echo ok "Phase 3 testing script complete!" echo echo "Next steps:" echo " - Review logs above" echo " - Capture snippets into PHASE3-EMULATOR-TESTING.md" echo " - Update PHASE3-VERIFICATION.md and unified directive status matrix" echo } main "$@"