# Phase 1 Emulator Testing Guide

**Author**: Matthew Raymer  
**Date**: November 2025  
**Status**: Testing Guide  
**Version**: 1.0.0

## Purpose

This guide provides step-by-step instructions for testing Phase 1 (Cold Start Recovery) implementation on an Android emulator. All Phase 1 tests can be run entirely on an emulator using ADB commands.

---

## Latest Known Good Run (Emulator)

**Environment**

- Device: Android Emulator – Pixel 8 API 34
- App ID: `org.timesafari.dailynotification`
- Build: Debug APK from `test-apps/android-test-app`
- Script: `./test-phase1.sh`
- Date: 27 November 2025

**Observed Results**

- ✅ TEST 1: Cold Start Missed Detection  
  - Logs show:
    - `Marked missed notification: daily_<id>`
    - `Cold start recovery complete: missed=1, rescheduled=0, verified=0, errors=0`
  - "Stored notification content in database" present in logs
  - Alarm present in `dumpsys alarm` before kill

- ✅ TEST 2: Future Alarm Verification / Rescheduling  
  - Logs show:
    - `Rescheduled alarm: daily_<id> for <time>`
    - `Rescheduled missing alarm: daily_<id> at <time>`
    - `Cold start recovery complete: missed=1, rescheduled=1, verified=0, errors=0`
  - Script output:
    - `✅ TEST 2 PASSED: Missing future alarms were detected and rescheduled (rescheduled=1)!`

- ✅ TEST 3: Recovery Timeout  
  - Timeout protection confirmed at **2 seconds**
  - No blocking of app startup

- ✅ TEST 4: Invalid Data Handling  
  - Confirmed in code review:
    - Reactivation code safely skips invalid IDs
    - Errors are logged but do not crash recovery

**Conclusion:**  
Phase 1 cold-start recovery behavior is **successfully verified on emulator** using `test-phase1.sh`. This run is the reference baseline for future regressions.

---

## Prerequisites

### Required Software

- **Android SDK** with command line tools
- **Android Emulator** (`emulator` command)
- **ADB** (Android Debug Bridge)
- **Gradle** (via Gradle Wrapper)
- **Java** (JDK 11+)

### Emulator Setup

1. **List available emulators**:
```bash
emulator -list-avds
```

2. **Start emulator** (choose one):
```bash
# Start in background (recommended)
emulator -avd Pixel8_API34 -no-snapshot-load &

# Or start in foreground
emulator -avd Pixel8_API34
```

3. **Wait for emulator to boot**:
```bash
adb wait-for-device
adb shell getprop sys.boot_completed
# Wait until returns "1"
```

4. **Verify emulator is connected**:
```bash
adb devices
# Should show: emulator-5554   device
```

---

## Build and Install Test App

### Option 1: Android Test App (Simpler)

```bash
# Navigate to test app directory
cd test-apps/android-test-app

# Build debug APK (builds plugin automatically)
./gradlew assembleDebug

# Install on emulator
adb install -r app/build/outputs/apk/debug/app-debug.apk

# Verify installation
adb shell pm list packages | grep timesafari
# Should show: package:org.timesafari.dailynotification
```

### Option 2: Vue Test App (More Features)

```bash
# Navigate to Vue test app
cd test-apps/daily-notification-test

# Build Vue app
npm run build

# Sync with Capacitor
npx cap sync android

# Build Android APK
cd android
./gradlew assembleDebug

# Install on emulator
adb install -r app/build/outputs/apk/debug/app-debug.apk
```

---

## Test Setup

### 1. Clear Logs Before Testing

```bash
# Clear logcat buffer
adb logcat -c
```

### 2. Monitor Logs in Separate Terminal

**Keep this running in a separate terminal window**:

```bash
# Monitor all plugin-related logs
adb logcat | grep -E "DNP-REACTIVATION|DNP-PLUGIN|DNP-NOTIFY|DailyNotification"

# Or monitor just recovery logs
adb logcat -s DNP-REACTIVATION

# Or save logs to file
adb logcat -s DNP-REACTIVATION > recovery_test.log
```

### 3. Launch App Once (Initial Setup)

```bash
# Launch app to initialize database
adb shell am start -n org.timesafari.dailynotification/.MainActivity

# Wait a few seconds for initialization
sleep 3
```

---

## Test 1: Cold Start Missed Detection

**Purpose**: Verify missed notifications are detected and marked.

### Steps

```bash
# 1. Clear logs
adb logcat -c

# 2. Launch app
adb shell am start -n org.timesafari.dailynotification/.MainActivity

# 3. Schedule notification for 2 minutes in future
#    (Use app UI or API - see "Scheduling Notifications" below)

# 4. Wait for app to schedule (check logs)
adb logcat -d | grep "DN|SCHEDULE\|DN|ALARM"
# Should show alarm scheduled

# 5. Verify alarm is scheduled
adb shell dumpsys alarm | grep -i timesafari
# Should show scheduled alarm

# 6. Kill app process (simulates OS kill, NOT force stop)
adb shell am kill org.timesafari.dailynotification

# 7. Verify app is killed
adb shell ps | grep timesafari
# Should return nothing

# 8. Wait 5 minutes (past scheduled time)
#    Use: sleep 300  (or wait manually)
#    Or: Set system time forward (see "Time Manipulation" below)

# 9. Launch app (cold start)
adb shell am start -n org.timesafari.dailynotification/.MainActivity

# 10. Check recovery logs immediately
adb logcat -d | grep DNP-REACTIVATION
```

### Expected Log Output

```
DNP-REACTIVATION: Starting app launch recovery (Phase 1: cold start only)
DNP-REACTIVATION: Cold start recovery: checking for missed notifications
DNP-REACTIVATION: Marked missed notification: <id>
DNP-REACTIVATION: Cold start recovery complete: missed=1, rescheduled=0, verified=0, errors=0
DNP-REACTIVATION: App launch recovery completed: missed=1, rescheduled=0, verified=0, errors=0
```

### Verification

```bash
# Check database (requires root or debug build)
adb shell run-as org.timesafari.dailynotification sqlite3 databases/daily_notification_plugin.db \
  "SELECT id, delivery_status, scheduled_time FROM notification_content WHERE delivery_status = 'missed';"

# Or check history table
adb shell run-as org.timesafari.dailynotification sqlite3 databases/daily_notification_plugin.db \
  "SELECT * FROM history WHERE kind = 'recovery' ORDER BY occurredAt DESC LIMIT 1;"
```

### Pass Criteria

- ✅ Log shows "Cold start recovery: checking for missed notifications"
- ✅ Log shows "Marked missed notification: <id>"
- ✅ Database shows `delivery_status = 'missed'`
- ✅ History table has recovery entry

---

## Test 2: Future Alarm Rescheduling

**Purpose**: Verify missing future alarms are rescheduled.

### Steps

```bash
# 1. Clear logs
adb logcat -c

# 2. Launch app
adb shell am start -n org.timesafari.dailynotification/.MainActivity

# 3. Schedule notification for 10 minutes in future
#    (Use app UI or API)

# 4. Verify alarm is scheduled
adb shell dumpsys alarm | grep -i timesafari
# Note the request code or trigger time

# 5. Manually cancel alarm (simulate missing alarm)
#    Find the alarm request code from dumpsys output
#    Then cancel using PendingIntent (requires root or app code)
#    OR: Use app UI to cancel if available

# Alternative: Use app code to cancel
#    (This test may require app modification to add cancel button)

# 6. Verify alarm is cancelled
adb shell dumpsys alarm | grep -i timesafari
# Should show no alarms (or fewer alarms)

# 7. Launch app (triggers recovery)
adb shell am start -n org.timesafari.dailynotification/.MainActivity

# 8. Check recovery logs
adb logcat -d | grep DNP-REACTIVATION

# 9. Verify alarm is rescheduled
adb shell dumpsys alarm | grep -i timesafari
# Should show rescheduled alarm
```

### Expected Log Output

```
DNP-REACTIVATION: Starting app launch recovery (Phase 1: cold start only)
DNP-REACTIVATION: Cold start recovery: checking for missed notifications
DNP-REACTIVATION: Rescheduled missing alarm: <id> at <timestamp>
DNP-REACTIVATION: Cold start recovery complete: missed=0, rescheduled=1, verified=0, errors=0
```

### Pass Criteria

- ✅ Log shows "Rescheduled missing alarm: <id>"
- ✅ AlarmManager shows rescheduled alarm
- ✅ No duplicate alarms created

---

## Test 3: Recovery Timeout

**Purpose**: Verify recovery times out gracefully.

### Steps

```bash
# 1. Clear logs
adb logcat -c

# 2. Create large number of schedules (100+)
#    This requires app modification or database manipulation
#    See "Database Manipulation" section below

# 3. Launch app
adb shell am start -n org.timesafari.dailynotification/.MainActivity

# 4. Check logs immediately
adb logcat -d | grep DNP-REACTIVATION
```

### Expected Behavior

- ✅ Recovery completes within 2 seconds OR times out
- ✅ App doesn't crash
- ✅ Partial recovery logged if timeout occurs

### Pass Criteria

- ✅ Recovery doesn't block app launch
- ✅ No app crash
- ✅ Timeout logged if occurs

**Note**: This test may be difficult to execute without creating many schedules. Consider testing with smaller numbers first (10, 50 schedules) to verify behavior.

---

## Test 4: Invalid Data Handling

**Purpose**: Verify invalid data doesn't crash recovery.

### Steps

```bash
# 1. Clear logs
adb logcat -c

# 2. Manually insert invalid notification (empty ID) into database
#    See "Database Manipulation" section below

# 3. Launch app
adb shell am start -n org.timesafari.dailynotification/.MainActivity

# 4. Check logs
adb logcat -d | grep DNP-REACTIVATION
```

### Expected Log Output

```
DNP-REACTIVATION: Starting app launch recovery (Phase 1: cold start only)
DNP-REACTIVATION: Cold start recovery: checking for missed notifications
DNP-REACTIVATION: Skipping invalid notification: empty ID
DNP-REACTIVATION: Cold start recovery complete: missed=0, rescheduled=0, verified=0, errors=0
```

### Pass Criteria

- ✅ Invalid notification skipped
- ✅ Warning logged
- ✅ Recovery continues normally
- ✅ App doesn't crash

---

## Helper Scripts and Commands

### Scheduling Notifications

**Option 1: Use App UI**
- Launch app
- Use "Schedule Notification" button
- Set time to 2-5 minutes in future

**Option 2: Use Capacitor API (if test app has console)**
```javascript
// In browser console or test app
const { DailyNotification } = Plugins.DailyNotification;
await DailyNotification.scheduleDailyNotification({
  schedule: "*/2 * * * *", // Every 2 minutes
  title: "Test Notification",
  body: "Testing Phase 1 recovery"
});
```

**Option 3: Direct Database Insert (Advanced)**
```bash
# See "Database Manipulation" section
```

### Time Manipulation (Emulator)

**Fast-forward system time** (for testing without waiting):

```bash
# Get current time
adb shell date +%s

# Set time forward (e.g., 5 minutes)
adb shell date -s @$(($(adb shell date +%s) + 300))

# Or set specific time
adb shell date -s "2025-11-15 14:30:00"
```

**Note**: Some emulators may not support time changes. Test with actual waiting if time manipulation doesn't work.

### Database Manipulation

**Access database** (requires root or debug build):

```bash
# Check if app is debuggable
adb shell dumpsys package org.timesafari.dailynotification | grep debuggable

# Access database
adb shell run-as org.timesafari.dailynotification sqlite3 databases/daily_notification_plugin.db

# Example: Insert test notification
sqlite> INSERT INTO notification_content (
  id, plugin_version, title, body, scheduled_time, 
  delivery_status, delivery_attempts, last_delivery_attempt,
  created_at, updated_at, ttl_seconds, priority,
  vibration_enabled, sound_enabled
) VALUES (
  'test_notification_1', '1.1.0', 'Test', 'Test body',
  $(($(date +%s) * 1000 - 300000)), -- 5 minutes ago
  'pending', 0, 0,
  $(date +%s) * 1000, $(date +%s) * 1000,
  604800, 0, 1, 1
);

# Example: Insert invalid notification (empty ID)
sqlite> INSERT INTO notification_content (
  id, plugin_version, title, body, scheduled_time,
  delivery_status, delivery_attempts, last_delivery_attempt,
  created_at, updated_at, ttl_seconds, priority,
  vibration_enabled, sound_enabled
) VALUES (
  '', '1.1.0', 'Invalid', 'Invalid body',
  $(($(date +%s) * 1000 - 300000)),
  'pending', 0, 0,
  $(date +%s) * 1000, $(date +%s) * 1000,
  604800, 0, 1, 1
);

# Example: Create many schedules (for timeout test)
sqlite> .read create_many_schedules.sql
# (Create SQL file with 100+ INSERT statements)
```

### Log Filtering

**Useful log filters**:

```bash
# Recovery-specific logs
adb logcat -s DNP-REACTIVATION

# All plugin logs
adb logcat | grep -E "DNP-|DailyNotification"

# Recovery + scheduling logs
adb logcat | grep -E "DNP-REACTIVATION|DN|SCHEDULE"

# Save logs to file
adb logcat -d > phase1_test_$(date +%Y%m%d_%H%M%S).log
```

---

## Complete Test Sequence

**Run all tests in sequence**:

```bash
#!/bin/bash
# Phase 1 Complete Test Sequence

PACKAGE="org.timesafari.dailynotification"
ACTIVITY="${PACKAGE}/.MainActivity"

echo "=== Phase 1 Testing on Emulator ==="
echo ""

# Setup
echo "1. Setting up emulator..."
adb wait-for-device
adb logcat -c

# Test 1: Cold Start Missed Detection
echo ""
echo "=== Test 1: Cold Start Missed Detection ==="
echo "1. Launch app and schedule notification for 2 minutes"
adb shell am start -n $ACTIVITY
echo "   (Use app UI to schedule notification)"
read -p "Press Enter after scheduling notification..."

echo "2. Killing app process..."
adb shell am kill $PACKAGE

echo "3. Waiting 5 minutes (or set time forward)..."
echo "   (You can set time forward: adb shell date -s ...)"
read -p "Press Enter after waiting 5 minutes..."

echo "4. Launching app (cold start)..."
adb shell am start -n $ACTIVITY
sleep 2

echo "5. Checking recovery logs..."
adb logcat -d | grep DNP-REACTIVATION

echo ""
echo "=== Test 1 Complete ==="
read -p "Press Enter to continue to Test 2..."

# Test 2: Future Alarm Rescheduling
echo ""
echo "=== Test 2: Future Alarm Rescheduling ==="
echo "1. Schedule notification for 10 minutes"
adb shell am start -n $ACTIVITY
echo "   (Use app UI to schedule notification)"
read -p "Press Enter after scheduling..."

echo "2. Verify alarm scheduled..."
adb shell dumpsys alarm | grep -i timesafari

echo "3. Cancel alarm (use app UI or see Database Manipulation)"
read -p "Press Enter after cancelling alarm..."

echo "4. Launch app (triggers recovery)..."
adb shell am start -n $ACTIVITY
sleep 2

echo "5. Check recovery logs..."
adb logcat -d | grep DNP-REACTIVATION

echo "6. Verify alarm rescheduled..."
adb shell dumpsys alarm | grep -i timesafari

echo ""
echo "=== Test 2 Complete ==="
echo ""
echo "=== All Tests Complete ==="
```

---

## Troubleshooting

### Emulator Issues

**Emulator won't start**:
```bash
# Check available AVDs
emulator -list-avds

# Kill existing emulator
pkill -f emulator

# Start with verbose logging
emulator -avd Pixel8_API34 -verbose
```

**Emulator is slow**:
```bash
# Use hardware acceleration
emulator -avd Pixel8_API34 -accel on -gpu host

# Allocate more RAM
emulator -avd Pixel8_API34 -memory 4096
```

### ADB Issues

**ADB not detecting emulator**:
```bash
# Restart ADB server
adb kill-server
adb start-server

# Check devices
adb devices
```

**Permission denied for database access**:
```bash
# Check if app is debuggable
adb shell dumpsys package org.timesafari.dailynotification | grep debuggable

# If not debuggable, rebuild with debug signing
cd test-apps/android-test-app
./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk
```

### App Issues

**App won't launch**:
```bash
# Check if app is installed
adb shell pm list packages | grep timesafari

# Uninstall and reinstall
adb uninstall org.timesafari.dailynotification
adb install -r app/build/outputs/apk/debug/app-debug.apk
```

**No logs appearing**:
```bash
# Check logcat buffer size
adb logcat -G 10M

# Clear and monitor
adb logcat -c
adb logcat -s DNP-REACTIVATION
```

---

## Expected Test Results Summary

| Test | Expected Outcome | Verification Method |
|------|------------------|---------------------|
| **Test 1** | Missed notification detected and marked | Logs + Database query |
| **Test 2** | Missing alarm rescheduled | Logs + AlarmManager check |
| **Test 3** | Recovery times out gracefully | Logs (timeout message) |
| **Test 4** | Invalid data skipped | Logs (warning message) |

---

## Quick Reference

### Essential Commands

```bash
# Start emulator
emulator -avd Pixel8_API34 &

# Build and install
cd test-apps/android-test-app
./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk

# Launch app
adb shell am start -n org.timesafari.dailynotification/.MainActivity

# Kill app
adb shell am kill org.timesafari.dailynotification

# Monitor logs
adb logcat -s DNP-REACTIVATION

# Check alarms
adb shell dumpsys alarm | grep -i timesafari
```

---

## Related Documentation

- [Phase 1 Directive](../android-implementation-directive-phase1.md) - Implementation details
- [Phase 1 Verification](./PHASE1-VERIFICATION.md) - Verification report
- [Activation Guide](./ACTIVATION-GUIDE.md) - How to use directives
- [Standalone Emulator Guide](../standalone-emulator-guide.md) - Emulator setup

---

**Status**: Emulator-verified (test-phase1.sh)  
**Last Updated**: 27 November 2025

