Extract common helper functions from test-phase1.sh, test-phase2.sh, and test-phase3.sh into a shared library (alarm-test-lib.sh) to reduce code duplication and improve maintainability. Changes: - Create alarm-test-lib.sh with shared configuration, UI helpers, ADB helpers, log parsing, and test selection logic - Refactor all three phase test scripts to source the shared library - Remove ~200 lines of duplicated code across the three scripts - Preserve all existing behavior, CLI arguments, and test semantics - Maintain Phase 1 compatibility (print_* functions, VERIFY_FIRE flag) - Update all adb references to use $ADB_BIN variable - Standardize alarm counting to use shared count_alarms() function Benefits: - Single source of truth for shared helpers - Easier maintenance (fix once, benefits all scripts) - Consistent behavior across all test phases - No functional changes to test execution or results
331 lines
10 KiB
Bash
Executable File
331 lines
10 KiB
Bash
Executable File
#!/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:-<none>}"
|
||
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:-<none>}, 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:-<none>}"
|
||
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:-<none>}, 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:-<none>}"
|
||
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 "$@"
|