diff --git a/docs/alarms/PHASE2-EMULATOR-TESTING.md b/docs/alarms/PHASE2-EMULATOR-TESTING.md new file mode 100644 index 0000000..f48987e --- /dev/null +++ b/docs/alarms/PHASE2-EMULATOR-TESTING.md @@ -0,0 +1,358 @@ +# PHASE 2 – EMULATOR TESTING + +**Force Stop Detection & Recovery** + +--- + +## 1. Purpose + +Phase 2 verifies that the Daily Notification Plugin correctly: + +1. Detects **force stop** scenarios (where alarms may be cleared by the OS). +2. **Reschedules** future notifications when alarms are missing but schedules remain in the database. +3. **Avoids heavy recovery** when alarms are still intact. +4. **Does not misfire** force-stop recovery on first launch / empty database. + +This document defines the emulator test procedure for Phase 2 using the script: + +```bash +test-apps/android-test-app/test-phase2.sh +``` + +--- + +## 2. Prerequisites + +* Android emulator or device, e.g.: + * Pixel 8 / API 34 (recommended baseline) +* ADB available in `PATH` (or `ADB_BIN` exported) +* Project built 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 behavior already implemented and verified: + * Cold start detection + * Missed notification marking + +> **Note:** Some OS/device combinations do not clear alarms on `am force-stop`. In such cases, TEST 1 may partially skip or only verify scenario logging. + +--- + +## 3. How to Run + +From the `android-test-app` directory: + +```bash +cd test-apps/android-test-app +chmod +x test-phase2.sh # first time only +./test-phase2.sh +``` + +The script will: + +1. Perform pre-flight checks (ADB/emulator). +2. Build and install the debug APK. +3. Guide you through three tests: + * TEST 1: Force stop – alarms cleared + * TEST 2: Force stop / process stop – alarms intact + * TEST 3: First launch / empty DB safeguard +4. Print parsed recovery summaries from `DNP-REACTIVATION` logs. + +You will be prompted for **UI actions** at each step (e.g., configuring the plugin, pressing "Test Notification"). + +--- + +## 4. Test Cases + +### 4.1 TEST 1 – Force Stop with Cleared Alarms + +**Goal:** + +Verify that when a force stop clears alarms, the plugin: + +* Detects the **FORCE_STOP** scenario. +* Reschedules future notifications. +* Completes recovery with `errors=0`. + +**Steps (Script Flow):** + +1. **Launch & configure plugin** + * Script launches the app. + * In the app UI, confirm: + * `⚙️ Plugin Settings: ✅ Configured` + * `🔌 Native Fetcher: ✅ Configured` + * If not, press **Configure Plugin** and wait until both are ✅. + +2. **Schedule a future notification** + * Click **Test Notification** (or equivalent) to schedule a notification a few minutes in the future. + +3. **Verify alarms are scheduled** + * Script runs: + ```bash + adb shell dumpsys alarm | grep com.timesafari.dailynotification + ``` + * Confirm at least one `RTC_WAKEUP` alarm for `com.timesafari.dailynotification`. + +4. **Force stop the app** + * Script executes: + ```bash + adb shell am force-stop com.timesafari.dailynotification + ``` + +5. **Confirm alarms after force stop** + * Script re-runs `dumpsys alarm`. + * Ideal test case: **0** alarms for `com.timesafari.dailynotification` (alarms cleared). + +6. **Trigger recovery** + * Script clears logcat and launches the app. + * Wait ~5 seconds for recovery. + +7. **Collect and inspect logs** + * Script collects `DNP-REACTIVATION` logs and parses: + * `scenario=` + * `missed=` + * `rescheduled=` + * `verified=` + * `errors=` + +**Expected Logs (Ideal Case):** + +* Scenario: + ```text + DNP-REACTIVATION: Detected scenario: FORCE_STOP + ``` + +* Alarm handling: + ```text + DNP-REACTIVATION: Rescheduled alarm: daily_ for