Adds documentation and test harness for Phase 3 (Boot-Time Recovery). Changes: - Update android-implementation-directive-phase3.md with concise boot recovery flow - Add PHASE3-EMULATOR-TESTING.md with detailed test procedures - Add PHASE3-VERIFICATION.md with test matrix and verification template - Add test-phase3.sh automated test harness Test harness features: - 4 test cases: future alarms, past alarms, no schedules, silent recovery - Automatic emulator reboot handling - Log parsing for boot recovery scenario and results - UI prompts for plugin configuration and scheduling - Verifies silent recovery without app launch Related: - Directive: android-implementation-directive-phase3.md - Requirements: docs/alarms/03-plugin-requirements.md §3.1.1 - Testing: docs/alarms/PHASE3-EMULATOR-TESTING.md - Verification: docs/alarms/PHASE3-VERIFICATION.md
9.6 KiB
PHASE 3 – EMULATOR TESTING
Boot-Time Recovery (Device Reboot / System Restart)
1. Purpose
Phase 3 verifies that the Daily Notification Plugin correctly:
- Reconstructs AlarmManager alarms after a full device/emulator reboot.
- Handles past scheduled times by marking them as missed and scheduling the next occurrence.
- Handles empty DB / no schedules without misfiring recovery.
- Performs silent boot recovery (recreate alarms) even when the app is never opened after reboot.
This testing is driven by the script:
test-apps/android-test-app/test-phase3.sh
2. Prerequisites
- Android emulator or device, e.g.:
- Pixel 8 / API 34 (recommended baseline)
- ADB available in
PATH(orADB_BINexported) - Project with:
- Daily Notification Plugin integrated
- Test app at
test-apps/android-test-app
- Debug APK path:
app/build/outputs/apk/debug/app-debug.apk
- Phase 1 and Phase 2 behaviors already implemented:
- Cold start detection
- Force-stop detection
- Missed / rescheduled / verified / errors summary fields
⚠️ Important: This script will reboot the emulator multiple times. Each reboot may take 30–60 seconds.
3. How to Run
From the android-test-app directory:
cd test-apps/android-test-app
chmod +x test-phase3.sh # first time only
./test-phase3.sh
The script will:
- Run pre-flight checks (ADB / emulator readiness).
- Build and install the debug APK.
- Guide you through four tests:
- TEST 1: Boot with Future Alarms
- TEST 2: Boot with Past Alarms
- TEST 3: Boot with No Schedules
- TEST 4: Silent Boot Recovery (App Never Opened)
- Parse and display
DNP-REACTIVATIONlogs, including:scenariomissedrescheduledverifiederrors
4. Test Cases (Script-Driven Flow)
4.1 TEST 1 – Boot with Future Alarms
Goal:
Verify alarms are recreated on boot when schedules have future run times.
Script flow:
-
Launch app & check plugin status
- Script calls
launch_app. - UI prompt: Confirm plugin status shows:
⚙️ Plugin Settings: ✅ Configured🔌 Native Fetcher: ✅ Configured
- If not, click Configure Plugin, wait until both show ✅, then continue.
- Script calls
-
Schedule at least one future notification
- UI prompt: Click e.g. Test Notification to schedule a notification a few minutes in the future.
-
Verify alarms are scheduled (pre-boot)
- Script calls
show_alarmsandcount_alarms. - You should see at least one
RTC_WAKEUPentry forcom.timesafari.dailynotification.
- Script calls
-
Reboot emulator
- Script calls
reboot_emulator:adb rebootadb wait-for-device- Polls
getprop sys.boot_completeduntil1.
- You are warned that reboot will take 30–60 seconds.
- Script calls
-
Collect boot recovery logs
- Script calls
get_recovery_logs:adb logcat -d | grep "DNP-REACTIVATION" - It parses:
missed,rescheduled,verified,errorsscenariovia:Starting boot recovery/boot recovery→scenario=BOOT- or
Detected scenario: <VALUE>
- Script calls
-
Verify alarms were recreated (post-boot)
- Script calls
show_alarmsandcount_alarmsagain. - Checks
scenarioandrescheduled.
- Script calls
Expected log patterns:
DNP-REACTIVATION: Starting boot recovery
DNP-REACTIVATION: Loaded <N> schedules from DB
DNP-REACTIVATION: Rescheduled alarm: daily_<id> for <time>
DNP-REACTIVATION: Boot recovery complete: missed=0, rescheduled>=1, verified=0, errors=0
Pass criteria (as per script):
errors = 0scenario = BOOT(or boot detected via log text)rescheduled > 0- Script prints:
✅ TEST 1 PASSED: Boot recovery detected and alarms rescheduled (scenario=BOOT, rescheduled=<n>).
If boot recovery runs but rescheduled=0, script warns and suggests checking boot logic.
4.2 TEST 2 – Boot with Past Alarms
Goal:
Verify past alarms are marked as missed and next occurrences are scheduled after boot.
Script flow:
-
Launch app & ensure plugin configured
- Same plugin status check as TEST 1.
-
Schedule a notification in the near future
- UI prompt: Schedule such that by the time you reboot and the device comes back, the planned notification time is in the past.
-
Wait or adjust so the alarm is effectively "in the past" at boot
- The script may instruct you to wait, or you can coordinate timing manually.
-
Reboot emulator
- Same
reboot_emulatorpath as TEST 1.
- Same
-
Collect boot recovery logs
- Script parses:
missed,rescheduled,errors,scenario.
- Script parses:
Expected log patterns:
DNP-REACTIVATION: Starting boot recovery
DNP-REACTIVATION: Loaded <N> schedules from DB
DNP-REACTIVATION: Marked missed notification: daily_<id>
DNP-REACTIVATION: Rescheduled alarm: daily_<id> for <next_time>
DNP-REACTIVATION: Boot recovery complete: missed>=1, rescheduled>=1, errors=0
Pass criteria:
errors = 0missed >= 1rescheduled >= 1- Script prints:
✅ TEST 2 PASSED: Past alarms detected and next occurrence scheduled (missed=<m>, rescheduled=<r>).
If missed >= 1 but rescheduled = 0, script warns that reschedule logic may be incomplete.
4.3 TEST 3 – Boot with No Schedules
Goal:
Verify boot recovery handles an empty DB / no schedules safely and does not schedule anything.
Script flow:
-
Uninstall app to clear DB/state
- Script calls:
adb uninstall com.timesafari.dailynotification
- Script calls:
-
Reinstall APK
- Script reinstalls
app-debug.apk.
- Script reinstalls
-
Launch app WITHOUT scheduling anything
- Script launches app; you do not configure or schedule.
-
Collect boot/logs
- Script reads
DNP-REACTIVATIONlogs and checks:- if there are no logs, or
- if there's a "No schedules found / present" message, or
- if
scenario=NONEandrescheduled=0.
- Script reads
Expected patterns:
- Ideal simple case: No
DNP-REACTIVATIONlogs at all, or: - Explicit message in logs:
DNP-REACTIVATION: ... No schedules found ...
Pass criteria (as per script):
- If no logs:
- Pass:
TEST 3 PASSED: No recovery logs when there are no schedules (safe behavior).
- Pass:
- If logs exist:
- Contains
No schedules found/No schedules presentandrescheduled=0, or scenario = NONEandrescheduled = 0.
- Contains
Any case where rescheduled > 0 with an empty DB is flagged as a warning (boot recovery misfiring).
4.4 TEST 4 – Silent Boot Recovery (App Never Opened)
Goal:
Verify that boot recovery occurs silently, recreating alarms without opening the app after reboot.
Script flow:
-
Launch app and configure plugin
- Same plugin status flow:
- Ensure both plugin checks are ✅.
- Schedule a future notification via UI.
- Same plugin status flow:
-
Verify alarms are scheduled
- Script shows alarms and counts (
before_count).
- Script shows alarms and counts (
-
Reboot emulator
- Script runs
reboot_emulatorand explicitly warns:- Do not open the app after reboot.
- After emulator returns, script instructs you to not touch the app UI.
- Script runs
-
Collect boot recovery logs
- Script gathers and parses
DNP-REACTIVATIONlines.
- Script gathers and parses
-
Verify alarms were recreated without app launch
- Script calls
show_alarmsandcount_alarmsagain. - Uses
rescheduled+ alarm count to decide.
- Script calls
Pass criteria (as per script):
rescheduled > 0after boot, and- Alarm count after boot is > 0, and
- App was never launched by the user after reboot.
Script prints one of:
✅ TEST 4 PASSED: Boot recovery occurred silently and alarms were recreated (rescheduled=<n>) without app launch.
✅ TEST 4 PASSED: Boot recovery occurred silently (rescheduled=<n>), but alarm count check unclear.
If boot recovery logs are present but no alarms appear, script warns; if no boot-recovery logs are found at all, script suggests verifying the boot receiver and BOOT_COMPLETED permission.
5. Overall Summary Section (from Script)
At the end, the script prints:
TEST 1: Boot with Future Alarms
- Check logs for boot recovery and rescheduled>0
TEST 2: Boot with Past Alarms
- Check logs for missed>=1 and rescheduled>=1
TEST 3: Boot with No Schedules
- Check that no recovery runs or that an explicit 'No schedules found' is logged without rescheduling
TEST 4: Silent Boot Recovery
- Check that boot recovery occurred and alarms were recreated without app launch
Use this as a quick checklist after a run.
6. Troubleshooting Notes
-
If no boot recovery logs ever appear:
- Check that
BootReceiveris declared andRECEIVE_BOOT_COMPLETEDpermission is set. - Ensure the app is installed in internal storage (not moved to SD).
- Check that
-
If errors > 0 in summary:
- Inspect the full
DNP-REACTIVATIONlogs printed by the script.
- Inspect the full
-
If alarming duplication is observed:
- Review
runBootRecoveryand dedupe logic around re-scheduling.
- Review
7. Related Documentation
- Phase 3 Directive - Implementation details
- Phase 3 Verification - Verification report
- Phase 1 Testing Guide - Prerequisite testing
- Phase 2 Testing Guide - Prerequisite testing
- Activation Guide - How to use directives
- Plugin Requirements - Requirements Phase 3 implements
Status: Ready for testing (Phase 3 implementation pending)
Last Updated: November 2025