Add automatic app state reset for TEST 1 to ensure clean starting state when lingering alarms from TEST 0 are detected. Create PHASE1_TEST1_GOLDEN.md with actual values from successful run. TEST 1 Auto-Reset: - Detect lingering plugin alarms before TEST 1 starts - Automatically uninstall/reinstall app to clear alarms - Verify clean state (0 alarms) before proceeding - Gracefully skip TEST 1 if clean state cannot be achieved - Take failure screenshots when reset fails - Wrap all TEST 1 steps in conditional to skip on reset failure Documentation: - Create PHASE1_TEST1_GOLDEN.md with actual values from passing run - Document auto-reset behavior in golden run steps - Add cross-references between TEST 0 and TEST 1 golden docs - Include actual timestamps, scheduleIds, and recovery metrics This ensures TEST 1 always starts from a known clean state, making test results reliable and reproducible. The golden doc serves as a baseline for comparing future TEST 1 runs.
9.1 KiB
Phase 1 — TEST 0 Golden Run (Daily Rollover Verification)
Last Updated: 2025-12-04
Status: ✅ PASS (Golden Baseline)
Related Docs:
- PHASE1_TEST0_GOLDEN.md - Daily Rollover Verification (this document)
- PHASE1_TEST1_GOLDEN.md - Force-Stop Recovery
1. Test Overview
This document captures a golden baseline for Phase 1 – TEST 0: Daily Rollover Verification.
Purpose: Verify that after a notification fires, the plugin:
- Computes next day's time (T + 24h)
- Schedules exactly one
AlarmManagernotification alarm for tomorrow - Does not create duplicates
- Leaves prefetch in WorkManager (not visible in
dumpsys alarm)
Golden Rule: If a future run looks like this doc, TEST 0 should be considered a PASS.
2. Environment & Build Info
Emulator / Device
- API Level: 35
- Android Version: 15
Build
- Gradle Version: 8.13
- Build Warnings:
WARNING: Using flatDir should be avoided because it doesn't support any meta-data formats.Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
Command Used
./test-phase1.sh
Environment Variables
ENABLE_SCREENSHOTS=1(screenshots enabled)ADB_BIN=adb(default)
3. Step-by-Step Execution (Golden Run)
- Ran
./test-phase1.sh. - Confirmed pre-flight checks (ADB device + emulator ready).
- Allowed script to rebuild and reinstall the app.
- Confirmed plugin status in the UI:
- ⚙️ Plugin Settings: ✅ Configured
- 🔌 Native Fetcher: ✅ Configured
- 🔔 Notifications: ✅ Granted
- ⏰ Exact Alarms: ✅ Granted
- 📢 Channel: ✅ Enabled (High)
- From the UI, scheduled a daily notification for ~1–2 minutes in the future (scheduled for
09:23:00on 2025-12-04). - Waited for the notification banner to fire.
- Pressed Enter to continue when prompted.
- Let the script perform the post-rollover alarm check.
4. Expected Script Output (Key Excerpts)
4.1. Pre-Schedule Check
✅ Found 1 notification alarm (expected: 1) – preliminary check passed.
ℹ️ This is preliminary check only; final verdict after rollover.
4.2. Notification Alarm Details (After Scheduling)
ℹ️ Notification alarm details:
tag=*walarm*:com.timesafari.daily.NOTIFICATION
type=RTC_WAKEUP origWhen=2025-12-04 09:23:00.000 window=0 exactAllowReason=policy_permission repeatInterval=0 count=0 flags=0x3
policyWhenElapsed: requester=+3m34s315ms app_standby=-10s456ms device_idle=-- battery_saver=--
4.3. Post-Rollover Check
ℹ️ Polling for stable alarm count (allowing up to ~10 seconds for Android to settle)...
ℹ️ Notification alarms after rollover: 1 (expected: 1)
ℹ️ System/other alarms: <N> (for context)
ℹ️ Note: Prefetch is scheduled via WorkManager (not AlarmManager), so it won't appear in alarm count
4.4. Final Verdict
✅ TEST 0 PASSED: Daily rollover created exactly one NOTIFICATION alarm for tomorrow.
Expected state after rollover:
✅ 1 notification alarm (AlarmManager) for tomorrow
✅ 1 prefetch job (WorkManager) for 2 minutes before tomorrow's notification
Note: The origWhen for tomorrow will be the next day at the same time (e.g., 2025-12-05 09:23:00.000 if scheduled for 2025-12-04 09:23:00.000).
5. Expected UI State (Screenshots)
5.1 Screenshot Files (Golden Run)
-
screenshots/phase1_test0_daily_rollover/phase1_test0_daily_rollover_before_scheduling_20251204-091910.png- Status: Active Schedules: No; Next Notification: None scheduled.
-
screenshots/phase1_test0_daily_rollover/phase1_test0_daily_rollover_after_scheduling_20251204-091925.png- Status: Active Schedules: Yes; Next Notification: today at 09:23:00 AM; Pending: 1.
-
screenshots/phase1_test0_daily_rollover/phase1_test0_daily_rollover_after_rollover_check_20251204-092307.png- Status: Active Schedules: Yes; Next Notification: tomorrow at 09:23:00 AM (24 hours later); Pending: 1.
6. Expected dumpsys alarm Shape
6.1. Representative Snippet
RTC_WAKEUP #<N>: Alarm{<handle> type 0 origWhen <timestamp> whenElapsed ... com.timesafari.dailynotification}
tag=*walarm*:com.timesafari.daily.NOTIFICATION
type=RTC_WAKEUP origWhen=2025-12-05 09:23:00.000 ...
...
Next wake from idle: Alarm{<handle> type 0 origWhen <timestamp> ... com.timesafari.dailynotification}
tag=*walarm*:com.timesafari.daily.NOTIFICATION
6.2. Key Observations
- There should be exactly one unique alarm handle for the plugin (the handle will differ between runs).
- It can appear both in the main list and in "Next wake from idle", but counted as one alarm (deduplication by alarm handle).
tagmust be*walarm*:com.timesafari.daily.NOTIFICATION.typemust beRTC_WAKEUP.origWhenshould be tomorrow at the same time-of-day as the scheduled notification (e.g.,2025-12-05 09:23:00.000if scheduled for2025-12-04 09:23:00.000).
7. Expected logcat Patterns
7.1. Scheduling Test Notification
DNP-SCHEDULE: Scheduling next daily alarm: id=daily_..., nextRun=2025-12-04 09:23:00, source=TEST_NOTIFICATION
DNP-NOTIFY: Stored notification content in database: id=daily_...
DNP-NOTIFY: Scheduling alarm: triggerTime=2025-12-04 09:23:00, ...
DNP-SCHEDULE: Scheduling OS alarm: variant=ALARM_CLOCK, action=com.timesafari.daily.NOTIFICATION, ...
7.2. Rollover on Fire
DNP-SCHEDULE: Scheduling next daily alarm: id=daily_rollover_..., nextRun=2025-12-05 09:23:00, source=ROLLOVER_ON_FIRE
DNP-NOTIFY: Stored notification content in database: id=notify_...
DNP-NOTIFY: Scheduling alarm: triggerTime=2025-12-05 09:23:00, ...
DNP-SCHEDULE: Scheduling OS alarm: variant=ALARM_CLOCK, action=com.timesafari.daily.NOTIFICATION, ...
7.3. Critical Requirements
Both sequences must be present for a true PASS:
source=TEST_NOTIFICATIONsequence when scheduling the initial test notificationsource=ROLLOVER_ON_FIREsequence when the notification fires and schedules tomorrow's alarm- Times must match: initial schedule time → tomorrow's time (T + 24h)
- Example:
2025-12-04 09:23:00→2025-12-05 09:23:00
- Example:
8. Quick Pass/Fail Checklist
A run of TEST 0 is a PASS if all of the following are true:
Script Output
- Shows "Found 1 notification alarm (expected: 1) – preliminary check passed."
- Shows "Notification alarms after rollover: 1 (expected: 1)".
- Ends with "✅ TEST 0 PASSED: Daily rollover created exactly one NOTIFICATION alarm for tomorrow."
UI State
- Before scheduling: Active Schedules: No; Next Notification: None scheduled.
- After scheduling: Active Schedules: Yes; Next Notification: today at the chosen time.
- After rollover: Active Schedules: Yes; Next Notification: tomorrow at the same time.
dumpsys alarm
- Exactly one
RTC_WAKEUPalarm withtag=*walarm*:com.timesafari.daily.NOTIFICATIONfor tomorrow. - Same alarm handle may appear under "Next wake from idle", but no second distinct handle.
origWhentimestamp is exactly 24 hours after the initial scheduled time.
logcat
- Shows both
source=TEST_NOTIFICATIONandsource=ROLLOVER_ON_FIREsequences with matching times. - No duplicate
DNP-SCHEDULEentries for the samenextRuntime. - No errors or warnings related to alarm scheduling.
9. Notes / Deviations
Failure Conditions
- If there is exactly 0 alarms after rollover, treat as INCONCLUSIVE and investigate:
- Check
logcatforROLLOVER_ON_FIREsequence - Verify
dumpsys alarmmanually - Check for scheduling errors in logs
- Check
- If there are >1 alarms after rollover, treat as FAIL (duplicate alarm bug):
- Check for multiple
DNP-SCHEDULEentries with samenextRun - Verify idempotence checks are working
- Check for race conditions between rollover and recovery paths
- Check for multiple
Time-of-Day Variations
- Time-of-day may differ in future golden runs; structure and relationships must remain the same.
- The key is: initial time → tomorrow's time (T + 24h), not the specific hour/minute.
Screenshot Timestamps
- Screenshot filenames include timestamps (
YYYYMMDD-HHMMSS), so exact filenames will differ between runs. - Focus on the content of screenshots (UI state) rather than exact filenames.
Alarm Handle Variations
- The alarm handle (e.g.,
Alarm{1f00a1b}) will differ between runs; this is expected. - The important thing is that there is exactly one unique handle per scheduled alarm.
10. Updating This Document
When updating this golden run document:
- Update timestamps and IDs with actual values from your successful run
- Replace placeholder values (marked with "Update...") with real data
- Update screenshot filenames with actual timestamps
- Add any environment-specific notes that might affect future runs
- Document any deviations or edge cases encountered
Last Golden Run Date: 2025-12-04 (09:23:00 scheduled time)