test(android): add auto-reset for TEST 1 and create golden run documentation
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.
This commit is contained in:
@@ -3,6 +3,10 @@
|
|||||||
**Last Updated:** 2025-12-04
|
**Last Updated:** 2025-12-04
|
||||||
**Status:** ✅ PASS (Golden Baseline)
|
**Status:** ✅ PASS (Golden Baseline)
|
||||||
|
|
||||||
|
**Related Docs:**
|
||||||
|
- [PHASE1_TEST0_GOLDEN.md](./PHASE1_TEST0_GOLDEN.md) - Daily Rollover Verification (this document)
|
||||||
|
- [PHASE1_TEST1_GOLDEN.md](./PHASE1_TEST1_GOLDEN.md) - Force-Stop Recovery
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Test Overview
|
## 1. Test Overview
|
||||||
|
|||||||
327
test-apps/android-test-app/docs/PHASE1_TEST1_GOLDEN.md
Normal file
327
test-apps/android-test-app/docs/PHASE1_TEST1_GOLDEN.md
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
# Phase 1 — TEST 1 Golden Run (Force-Stop Recovery - Database Restoration)
|
||||||
|
|
||||||
|
**Related Docs:**
|
||||||
|
- [PHASE1_TEST0_GOLDEN.md](./PHASE1_TEST0_GOLDEN.md)
|
||||||
|
- [PHASE1_TEST1_GOLDEN.md](./PHASE1_TEST1_GOLDEN.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Test Overview
|
||||||
|
|
||||||
|
**Test Name:** TEST 1 — Force-Stop Recovery: Database Restoration
|
||||||
|
**Purpose:** Verify that after an Android **force-stop** (which clears all scheduled alarms), the plugin:
|
||||||
|
|
||||||
|
1. **Persists** the alarm schedule in its database.
|
||||||
|
2. **Detects** that alarms are missing on app launch.
|
||||||
|
3. **Rebuilds** the missing alarm(s) from the database.
|
||||||
|
4. Restores the **one-notification-per-day** contract:
|
||||||
|
- Before force-stop: 1 alarm
|
||||||
|
- After force-stop: 0 alarms
|
||||||
|
- After recovery: 1 alarm (same trigger time as before force-stop)
|
||||||
|
|
||||||
|
This golden run documents a **known-good execution** on 2025-12-04.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Environment & Build Info
|
||||||
|
|
||||||
|
- **Date/Time of Run:** 2025-12-04 (around 09:51–09:55 UTC)
|
||||||
|
- **Command Used:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./test-phase1.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Project:** `daily-notification-plugin` — `test-apps/android-test-app`
|
||||||
|
|
||||||
|
* **Gradle:**
|
||||||
|
|
||||||
|
* Build invoked via `./gradlew assembleDebug` (through the script)
|
||||||
|
* Gradle output included:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
|
||||||
|
```
|
||||||
|
|
||||||
|
* **APK Built:**
|
||||||
|
|
||||||
|
```text
|
||||||
|
./app/build/outputs/apk/debug/app-debug.apk
|
||||||
|
```
|
||||||
|
|
||||||
|
* **App ID:** `com.timesafari.dailynotification`
|
||||||
|
|
||||||
|
> **Note:** Device/emulator model & API level can be added here later if desired.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Step-by-Step Execution (Golden Run)
|
||||||
|
|
||||||
|
This section captures the **actual** sequence for the golden run.
|
||||||
|
|
||||||
|
1. Ran `./test-phase1.sh`.
|
||||||
|
2. Pre-flight checks:
|
||||||
|
* ✅ ADB device connected
|
||||||
|
* ✅ Emulator ready
|
||||||
|
3. Build phase:
|
||||||
|
* ✅ Debug APK built successfully.
|
||||||
|
* ✅ APK path: `./app/build/outputs/apk/debug/app-debug.apk`
|
||||||
|
4. Install phase:
|
||||||
|
* ✅ Previous app uninstall succeeded
|
||||||
|
* ✅ APK installed successfully
|
||||||
|
* ✅ App verified in package list
|
||||||
|
* ✅ Logcat cleared (twice)
|
||||||
|
5. **TEST 0** executed:
|
||||||
|
* Configured plugin in UI (if needed).
|
||||||
|
* Scheduled daily notification.
|
||||||
|
* Verified:
|
||||||
|
* Before scheduling: 0 plugin alarms.
|
||||||
|
* After scheduling: 1 plugin alarm for **today**.
|
||||||
|
* After fire/rollover: 1 plugin alarm for **tomorrow**.
|
||||||
|
* **TEST 0 PASSED.**
|
||||||
|
6. **TEST 1** started:
|
||||||
|
* Step 1: Detected 1 lingering plugin alarm (tomorrow's alarm from TEST 0).
|
||||||
|
* Auto-reset:
|
||||||
|
* Uninstalled app
|
||||||
|
* Reinstalled APK
|
||||||
|
* Cleared logcat
|
||||||
|
* Verified plugin alarms = 0
|
||||||
|
* Confirmed **clean starting state** for TEST 1.
|
||||||
|
7. Step 2: Launched app and confirmed plugin configured.
|
||||||
|
8. In UI: tapped **"Test Notification"** button (schedules a notification ~4 minutes in the future).
|
||||||
|
9. Step 3 (pre-FS verify):
|
||||||
|
* Verified **1** plugin alarm exists in AlarmManager.
|
||||||
|
* Confirmed alarm details (time, tag, type).
|
||||||
|
* Confirmed scheduling logs with `source=TEST_NOTIFICATION`.
|
||||||
|
10. Step 4: Performed **force-stop** via `adb shell am force-stop com.timesafari.dailynotification`.
|
||||||
|
11. Step 5 (post-FS verify):
|
||||||
|
* Verified plugin alarms = **0** (force-stop cleared alarms).
|
||||||
|
12. Step 6: Relaunched app (cold start).
|
||||||
|
13. Step 7 (recovery verify):
|
||||||
|
* Verified plugin alarms = **1** after recovery.
|
||||||
|
* Confirmed recovery logs under `DNP-REACTIVATION`:
|
||||||
|
* App launch recovery
|
||||||
|
* Boot recovery
|
||||||
|
* `rescheduled=1`
|
||||||
|
* Confirmed rescheduled alarm uses the **same scheduleId and triggerTime** as pre-force-stop.
|
||||||
|
14. Fire verification was **skipped** (`VERIFY_FIRE=false`).
|
||||||
|
15. TEST 1 summary:
|
||||||
|
* ✅ Before FS: 1 alarm
|
||||||
|
* ✅ After FS: 0 alarms
|
||||||
|
* ✅ After recovery: 1 alarm
|
||||||
|
* ✅ `rescheduled=1`, `errors=0`
|
||||||
|
* ✅ TEST 1 PASSED.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Expected Script Output (Key Excerpts)
|
||||||
|
|
||||||
|
These are the **critical excerpts** from the test harness output for a passing TEST 1.
|
||||||
|
|
||||||
|
### 4.1 Clean Start & Auto-Reset
|
||||||
|
|
||||||
|
```text
|
||||||
|
→ Step 1: Clean start - checking for lingering alarms...
|
||||||
|
ℹ️ Current plugin notification alarms: 1
|
||||||
|
ℹ️ System/other alarms: 17 (for context)
|
||||||
|
⚠️ Found 1 lingering plugin alarm(s) - these will interfere with TEST 1.
|
||||||
|
ℹ️ TEST 1 needs a clean state (no existing plugin alarms).
|
||||||
|
ℹ️ Resetting app state via uninstall + reinstall...
|
||||||
|
ℹ️ Uninstalling existing app...
|
||||||
|
✅ App uninstall succeeded (clean slate).
|
||||||
|
ℹ️ Reinstalling APK...
|
||||||
|
✅ App reinstall succeeded.
|
||||||
|
ℹ️ Clearing logcat buffer after reinstall...
|
||||||
|
ℹ️ Rechecking plugin alarms after reset...
|
||||||
|
ℹ️ Plugin alarms after reset: 0 (expected: 0)
|
||||||
|
✅ App state reset complete. TEST 1 starting from clean state.
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 Alarm Scheduled Before Force-Stop
|
||||||
|
|
||||||
|
```text
|
||||||
|
→ Step 3: Verifying alarm exists in AlarmManager (BEFORE force-stop)...
|
||||||
|
ℹ️ Plugin alarms: 1 (expected: 1)
|
||||||
|
ℹ️ System/other alarms: 19 (for context)
|
||||||
|
✅ ✅ Single plugin alarm confirmed in AlarmManager (one per day)
|
||||||
|
ℹ️ Alarm details:
|
||||||
|
RTC_WAKEUP #4: Alarm{161cd2b type 0 origWhen 1764842100000 whenElapsed 13009441 com.timesafari.dailynotification}
|
||||||
|
tag=*walarm*:com.timesafari.daily.NOTIFICATION
|
||||||
|
type=RTC_WAKEUP origWhen=2025-12-04 09:55:00.000 window=0 exactAllowReason=policy_permission repeatInterval=0 count=0 flags=0x3
|
||||||
|
policyWhenElapsed: requester=+3m4s281ms app_standby=-6s566ms device_idle=-- battery_saver=--
|
||||||
|
--
|
||||||
|
ℹ️ Alarm scheduled for: Thu Dec 4 09:55:00 AM UTC 2025 (1764842100000 ms)
|
||||||
|
ℹ️ Checking logs for scheduling confirmation...
|
||||||
|
12-04 09:51:49.150 6803 6867 W DNP-SCHEDULE: Cancelling existing alarm before rescheduling: requestCode=3454, scheduleId=daily_1764841909137, source=TEST_NOTIFICATION
|
||||||
|
12-04 09:51:49.151 6803 6867 I DNP-NOTIFY: Scheduling alarm: triggerTime=2025-12-04 09:55:00, delayMs=190849, requestCode=3454, scheduleId=daily_1764841909137
|
||||||
|
12-04 09:51:49.152 6803 6867 I DNP-SCHEDULE: Scheduling OS alarm: variant=ALARM_CLOCK, action=com.timesafari.daily.NOTIFICATION, triggerTime=1764842100000, requestCode=3454, scheduleId=daily_1764841909137, source=TEST_NOTIFICATION, pendingIntentHash=267839060, showIntentHash=256236029
|
||||||
|
12-04 09:51:49.153 6803 6867 I DNP-NOTIFY: Alarm clock scheduled (setAlarmClock): triggerAt=1764842100000, requestCode=3454
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3 Force-Stop & Alarm Clearance
|
||||||
|
|
||||||
|
```text
|
||||||
|
→ Step 4: Force-stopping app (clears all alarms)...
|
||||||
|
⚠️ Force-stop will clear ALL alarms from AlarmManager
|
||||||
|
ℹ️ Executing: adb shell am force-stop com.timesafari.dailynotification
|
||||||
|
ℹ️ Forcing stop of app process...
|
||||||
|
✅ Force stop issued
|
||||||
|
→ Step 5: Verifying alarms are MISSING from AlarmManager (AFTER force-stop)...
|
||||||
|
ℹ️ Plugin alarms after force-stop: 0 (expected: 0)
|
||||||
|
ℹ️ System/other alarms: 17 (for context)
|
||||||
|
✅ ✅ Plugin alarms cleared by force-stop (count: 0)
|
||||||
|
ℹ️ This confirms: Force-stop cleared alarms from AlarmManager
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.4 Recovery & Rescheduling
|
||||||
|
|
||||||
|
```text
|
||||||
|
→ Step 6: Relaunching app (triggers recovery from database)...
|
||||||
|
ℹ️ Clearing logcat buffer...
|
||||||
|
✅ Logs cleared
|
||||||
|
ℹ️ Launching app...
|
||||||
|
Starting: Intent { cmp=com.timesafari.dailynotification/.MainActivity }
|
||||||
|
✅ App launched
|
||||||
|
→ Step 7: Verifying recovery rebuilt alarms from database...
|
||||||
|
ℹ️ Plugin alarms after recovery: 1 (expected: 1)
|
||||||
|
ℹ️ System/other alarms: 21 (for context)
|
||||||
|
ℹ️ Checking recovery logs...
|
||||||
|
|
||||||
|
12-04 09:52:21.919 6954 7015 I DNP-REACTIVATION: Starting app launch recovery (Phase 1: cold start only)
|
||||||
|
12-04 09:52:21.926 6954 7015 I DNP-REACTIVATION: Cold start recovery: checking for missed notifications
|
||||||
|
12-04 09:52:21.937 6954 7015 I DNP-REACTIVATION: Rescheduled alarm: daily_1764841909137 for 1764842100000
|
||||||
|
12-04 09:52:21.937 6954 7015 I DNP-REACTIVATION: Rescheduled missing alarm: daily_1764841909137 at 1764842100000
|
||||||
|
12-04 09:52:21.952 6954 7015 I DNP-REACTIVATION: Cold start recovery complete: missed=0, rescheduled=1, verified=0, errors=0
|
||||||
|
12-04 09:52:21.952 6954 7015 I DNP-REACTIVATION: App launch recovery completed: missed=0, rescheduled=1, verified=0, errors=0
|
||||||
|
12-04 09:52:22.077 6954 7015 I DNP-REACTIVATION: Starting boot recovery
|
||||||
|
12-04 09:52:22.135 6954 7017 I DNP-REACTIVATION: Loaded 1 schedules from DB
|
||||||
|
12-04 09:52:22.138 6954 7017 I DNP-REACTIVATION: Rescheduled alarm: daily_1764841909137 for 1764842100000
|
||||||
|
12-04 09:52:22.143 6954 7017 I DNP-REACTIVATION: Boot recovery complete: missed=0, rescheduled=1, verified=0, errors=0
|
||||||
|
```
|
||||||
|
|
||||||
|
Final summary:
|
||||||
|
|
||||||
|
```text
|
||||||
|
✅ ✅ Alarms restored in AlarmManager (count: 1)
|
||||||
|
✅ ✅ Recovery logs confirm rescheduling (rescheduled=1)
|
||||||
|
✅ TEST 1 PASSED: Recovery successfully rebuilt alarms from database!
|
||||||
|
ℹ️ Summary:
|
||||||
|
- Before force-stop: 1 alarm(s)
|
||||||
|
- After force-stop: 0 alarm(s) (cleared)
|
||||||
|
- After recovery: 1 alarm(s) (rebuilt)
|
||||||
|
- Rescheduled: 1 alarm(s)
|
||||||
|
- Verified: 0 alarm(s)
|
||||||
|
ℹ️ Skipping fire verification (VERIFY_FIRE=false, set VERIFY_FIRE=true to enable)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Expected `dumpsys alarm` Shapes
|
||||||
|
|
||||||
|
### 5.1 Before Force-Stop (Scheduled)
|
||||||
|
|
||||||
|
* **Plugin alarm count:** 1
|
||||||
|
* Example block (shape, not necessarily exact handle):
|
||||||
|
|
||||||
|
```text
|
||||||
|
RTC_WAKEUP #4: Alarm{161cd2b type 0 origWhen 1764842100000 whenElapsed 13009441 com.timesafari.dailynotification}
|
||||||
|
tag=*walarm*:com.timesafari.daily.NOTIFICATION
|
||||||
|
type=RTC_WAKEUP origWhen=2025-12-04 09:55:00.000 window=0 exactAllowReason=policy_permission repeatInterval=0 count=0 flags=0x3
|
||||||
|
policyWhenElapsed: requester=+3m4s281ms app_standby=-6s566ms device_idle=-- battery_saver=--
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 After Force-Stop
|
||||||
|
|
||||||
|
* **Plugin alarm count:** 0
|
||||||
|
* No `*walarm*:com.timesafari.daily.NOTIFICATION` entries should appear.
|
||||||
|
|
||||||
|
### 5.3 After Recovery
|
||||||
|
|
||||||
|
* **Plugin alarm count:** 1
|
||||||
|
* Alarm should be restored with:
|
||||||
|
* Same `scheduleId`: `daily_1764841909137`
|
||||||
|
* Same `triggerTime`: `1764842100000` → `2025-12-04 09:55:00`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Expected `logcat` Patterns
|
||||||
|
|
||||||
|
For a passing run, look for:
|
||||||
|
|
||||||
|
* **Scheduling (before FS):**
|
||||||
|
|
||||||
|
```text
|
||||||
|
DNP-NOTIFY: Scheduling alarm: triggerTime=2025-12-04 09:55:00, delayMs=..., requestCode=3454, scheduleId=daily_1764841909137
|
||||||
|
DNP-SCHEDULE: Scheduling OS alarm: variant=ALARM_CLOCK, action=com.timesafari.daily.NOTIFICATION, triggerTime=1764842100000, requestCode=3454, scheduleId=daily_1764841909137, source=TEST_NOTIFICATION, ...
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Recovery (after FS + relaunch):**
|
||||||
|
|
||||||
|
```text
|
||||||
|
DNP-REACTIVATION: Starting app launch recovery (Phase 1: cold start only)
|
||||||
|
DNP-REACTIVATION: Rescheduled alarm: daily_1764841909137 for 1764842100000
|
||||||
|
DNP-REACTIVATION: Cold start recovery complete: missed=0, rescheduled=1, verified=0, errors=0
|
||||||
|
DNP-REACTIVATION: App launch recovery completed: missed=0, rescheduled=1, verified=0, errors=0
|
||||||
|
|
||||||
|
DNP-REACTIVATION: Starting boot recovery
|
||||||
|
DNP-REACTIVATION: Loaded 1 schedules from DB
|
||||||
|
DNP-REACTIVATION: Rescheduled alarm: daily_1764841909137 for 1764842100000
|
||||||
|
DNP-REACTIVATION: Boot recovery complete: missed=0, rescheduled=1, verified=0, errors=0
|
||||||
|
```
|
||||||
|
|
||||||
|
Key invariants:
|
||||||
|
|
||||||
|
* `rescheduled=1`
|
||||||
|
* `errors=0`
|
||||||
|
* `scheduleId` and `triggerTime` match pre-FS values.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Quick Pass/Fail Checklist
|
||||||
|
|
||||||
|
A TEST 1 run is a **PASS** if all of the following are true:
|
||||||
|
|
||||||
|
* **Starting state:**
|
||||||
|
* Script auto-resets if lingering alarms exist from TEST 0.
|
||||||
|
* After reset: plugin alarm count = **0**.
|
||||||
|
|
||||||
|
* **Pre-force-stop:**
|
||||||
|
* Plugin alarm count = **1**.
|
||||||
|
* Alarm is tagged `*walarm*:com.timesafari.daily.NOTIFICATION`.
|
||||||
|
* `triggerTime` and `origWhen` are consistent (e.g. `2025-12-04 09:55:00`, `1764842100000`).
|
||||||
|
* `scheduleId` looks like `daily_<timestamp>` (here: `daily_1764841909137`).
|
||||||
|
* Logs show `source=TEST_NOTIFICATION`.
|
||||||
|
|
||||||
|
* **After force-stop:**
|
||||||
|
* Plugin alarm count = **0**.
|
||||||
|
* No NOTIFICATION alarms remain in `dumpsys`.
|
||||||
|
|
||||||
|
* **After recovery (relaunch):**
|
||||||
|
* Plugin alarm count = **1**.
|
||||||
|
* Logs show `DNP-REACTIVATION` with:
|
||||||
|
* `rescheduled=1`
|
||||||
|
* `errors=0`
|
||||||
|
* Same `scheduleId` and `triggerTime` as pre-FS.
|
||||||
|
|
||||||
|
* **Script summary:**
|
||||||
|
* States:
|
||||||
|
* Before force-stop: 1 alarm
|
||||||
|
* After force-stop: 0 alarms
|
||||||
|
* After recovery: 1 alarm
|
||||||
|
* Ends with: `✅ TEST 1 PASSED: Recovery successfully rebuilt alarms from database!`
|
||||||
|
|
||||||
|
If any of these conditions fail, the run is **NOT GOLDEN** and should not overwrite this reference.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Notes / Deviations
|
||||||
|
|
||||||
|
* This golden run **skips fire verification** (`VERIFY_FIRE=false`).
|
||||||
|
Future runs may enable fire verification; if that becomes standard, update this doc.
|
||||||
|
* It is acceptable for both:
|
||||||
|
* **Cold start recovery** and
|
||||||
|
* **Boot recovery**
|
||||||
|
to run on app launch, as long as:
|
||||||
|
* `rescheduled=1`
|
||||||
|
* No duplicate alarms are scheduled.
|
||||||
|
* If OS behavior changes (e.g., force-stop no longer clears alarms on a future Android version), this test's expectations may need to be revised; document any such deviations explicitly here before changing the checklist.
|
||||||
@@ -434,15 +434,86 @@ main() {
|
|||||||
print_step "1" "Clean start - checking for lingering alarms..."
|
print_step "1" "Clean start - checking for lingering alarms..."
|
||||||
LINGERING_COUNT=$(get_plugin_alarm_count)
|
LINGERING_COUNT=$(get_plugin_alarm_count)
|
||||||
SYSTEM_COUNT=$(get_system_alarm_count)
|
SYSTEM_COUNT=$(get_system_alarm_count)
|
||||||
if [ "${LINGERING_COUNT}" -gt "0" ] 2>/dev/null; then
|
print_info "Current plugin notification alarms: ${LINGERING_COUNT}"
|
||||||
print_warn "Found ${LINGERING_COUNT} lingering plugin alarm(s) - these may interfere with test"
|
|
||||||
print_info "System/other alarms: ${SYSTEM_COUNT} (for context)"
|
print_info "System/other alarms: ${SYSTEM_COUNT} (for context)"
|
||||||
print_info "Consider uninstalling/reinstalling app for clean state"
|
|
||||||
|
if [ "${LINGERING_COUNT}" -gt "0" ] 2>/dev/null; then
|
||||||
|
print_warn "Found ${LINGERING_COUNT} lingering plugin alarm(s) - these will interfere with TEST 1."
|
||||||
|
print_info "TEST 1 needs a clean state (no existing plugin alarms)."
|
||||||
|
print_info "Resetting app state via uninstall + reinstall..."
|
||||||
|
|
||||||
|
# Uninstall existing app
|
||||||
|
print_info "Uninstalling existing app..."
|
||||||
|
set +e
|
||||||
|
uninstall_output="$($ADB_BIN uninstall "$APP_ID" 2>&1)"
|
||||||
|
uninstall_status=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ $uninstall_status -eq 0 ]; then
|
||||||
|
print_success "App uninstall succeeded (clean slate)."
|
||||||
|
else
|
||||||
|
if grep -q "DELETE_FAILED_INTERNAL_ERROR" <<<"$uninstall_output"; then
|
||||||
|
print_info "No existing app to uninstall (continuing)"
|
||||||
|
else
|
||||||
|
print_warn "App uninstall reported an error: $uninstall_output (continuing anyway)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Reinstall APK
|
||||||
|
print_info "Reinstalling APK..."
|
||||||
|
if $ADB_BIN install -r "$APK_PATH" >/dev/null 2>&1; then
|
||||||
|
print_success "App reinstall succeeded."
|
||||||
|
else
|
||||||
|
print_error "App reinstall FAILED - cannot proceed with TEST 1."
|
||||||
|
print_warn "Marking TEST 1 as INCONCLUSIVE due to dirty starting state."
|
||||||
|
take_failure_screenshot "phase1_test1_force_stop" "dirty_state_reinstall_failed"
|
||||||
|
wait_for_user
|
||||||
|
# Skip to end of TEST 1 block
|
||||||
|
goto_test1_end=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${goto_test1_end:-false}" != "true" ]; then
|
||||||
|
# Verify install
|
||||||
|
if ! $ADB_BIN shell pm list packages | grep -q "$APP_ID"; then
|
||||||
|
print_error "App not found in package list after reinstall - aborting TEST 1."
|
||||||
|
take_failure_screenshot "phase1_test1_force_stop" "dirty_state_verify_failed"
|
||||||
|
wait_for_user
|
||||||
|
goto_test1_end=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${goto_test1_end:-false}" != "true" ]; then
|
||||||
|
# Clear logs
|
||||||
|
print_info "Clearing logcat buffer after reinstall..."
|
||||||
|
$ADB_BIN logcat -c || true
|
||||||
|
|
||||||
|
# Re-check plugin alarms
|
||||||
|
print_info "Rechecking plugin alarms after reset..."
|
||||||
|
sleep 2 # Give system time to clear alarms
|
||||||
|
LINGERING_COUNT=$(get_plugin_alarm_count)
|
||||||
|
print_info "Plugin alarms after reset: ${LINGERING_COUNT} (expected: 0)"
|
||||||
|
|
||||||
|
if [ "${LINGERING_COUNT}" -ne "0" ] 2>/dev/null; then
|
||||||
|
print_warn "TEST 1 starting with non-zero alarm count even after reset; treating as INCONCLUSIVE."
|
||||||
|
print_info "This may indicate device-specific behavior where alarms persist across uninstall."
|
||||||
|
take_failure_screenshot "phase1_test1_force_stop" "unexpected_alarms_after_reset"
|
||||||
|
wait_for_user
|
||||||
|
goto_test1_end=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${goto_test1_end:-false}" = "true" ]; then
|
||||||
|
print_warn "TEST 1 skipped due to inability to achieve clean starting state."
|
||||||
wait_for_user
|
wait_for_user
|
||||||
else
|
else
|
||||||
print_success "No lingering plugin alarms found (clean state)"
|
print_success "App state reset complete. TEST 1 starting from clean state."
|
||||||
print_info "System/other alarms: ${SYSTEM_COUNT} (for context)"
|
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
print_success "No lingering plugin alarms found (clean state)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Skip remaining TEST 1 steps if we couldn't achieve clean state
|
||||||
|
if [ "${goto_test1_end:-false}" != "true" ]; then
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# Step 2: Schedule a known future alarm
|
# Step 2: Schedule a known future alarm
|
||||||
@@ -664,8 +735,10 @@ main() {
|
|||||||
print_info "Skipping fire verification (VERIFY_FIRE=false, set VERIFY_FIRE=true to enable)"
|
print_info "Skipping fire verification (VERIFY_FIRE=false, set VERIFY_FIRE=true to enable)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
fi # End of "if goto_test1_end != true" block (wraps all TEST 1 steps after clean state check)
|
||||||
|
|
||||||
wait_for_user
|
wait_for_user
|
||||||
fi
|
fi # End of "if should_run_test 1" block
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# TEST 2: Schedule Update (One-Per-Day Semantics)
|
# TEST 2: Schedule Update (One-Per-Day Semantics)
|
||||||
|
|||||||
Reference in New Issue
Block a user