- Add comprehensive-testing-guide-v2.md with detailed test procedures - Add testing-quick-reference-v2.md for quick access to test commands - Add reboot-test-v2.sh for automated reboot testing - Covers all P0 production-grade features: * Channel management (P0 Priority 1) * PendingIntent flags & exact alarms (P0 Priority 2) * JIT freshness re-check (P0 Priority 3) * Recovery coexistence (P0 Priority 4) - Includes manual and automated testing procedures - Ready for comprehensive test run after P0 completion
1110 lines
31 KiB
Markdown
1110 lines
31 KiB
Markdown
# Comprehensive Testing Guide v2.0 - P0 Production-Grade Features
|
|
|
|
## Overview
|
|
|
|
This document provides comprehensive testing procedures for the DailyNotification Capacitor plugin with all P0 production-grade improvements implemented. The current version includes:
|
|
|
|
- ✅ **P0 Priority 1**: Channel Management (ChannelManager)
|
|
- ✅ **P0 Priority 2**: PendingIntent & Exact Alarms (PendingIntentManager)
|
|
- ✅ **P0 Priority 3**: JIT Freshness Re-check (Soft TTL)
|
|
- ✅ **P0 Priority 4**: Recovery Coexistence (RecoveryManager)
|
|
|
|
## Table of Contents
|
|
|
|
1. [P0 Feature Testing](#p0-feature-testing)
|
|
2. [Reboot Testing Procedures](#reboot-testing-procedures)
|
|
3. [Automated Test Suites](#automated-test-suites)
|
|
4. [Edge Case Testing](#edge-case-testing)
|
|
5. [Performance Testing](#performance-testing)
|
|
6. [Troubleshooting Guide](#troubleshooting-guide)
|
|
|
|
---
|
|
|
|
## P0 Feature Testing
|
|
|
|
### Test Suite 1: Channel Management (P0 Priority 1)
|
|
|
|
#### Test 1.1: Channel Creation and Status
|
|
|
|
**Objective**: Verify ChannelManager creates and manages notification channels correctly
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Launch app and check channel status
|
|
adb shell am start -n com.timesafari.dailynotification/.MainActivity
|
|
|
|
# 2. In app UI, tap "Check Channel Status"
|
|
# 3. Verify channel exists and is enabled
|
|
```
|
|
|
|
**Expected Results**:
|
|
- Channel ID: `daily_default`
|
|
- Channel Name: `Daily Notifications`
|
|
- Channel Importance: `IMPORTANCE_HIGH` (3)
|
|
- Channel Enabled: `true`
|
|
|
|
**Verification Commands**:
|
|
```bash
|
|
# Check channel in system
|
|
adb shell "dumpsys notification | grep -A10 -B5 daily_default"
|
|
|
|
# Check channel importance
|
|
adb shell "dumpsys notification | grep -A5 'daily_default'"
|
|
```
|
|
|
|
#### Test 1.2: Channel Blocking Detection
|
|
|
|
**Objective**: Test detection and handling of blocked notification channels
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Block the notification channel manually
|
|
adb shell "am start -a android.settings.CHANNEL_NOTIFICATION_SETTINGS -e android.provider.extra.APP_PACKAGE com.timesafari.dailynotification -e android.provider.extra.CHANNEL_ID daily_default"
|
|
|
|
# 2. In system settings, disable the channel
|
|
# 3. Return to app and tap "Check Channel Status"
|
|
```
|
|
|
|
**Expected Results**:
|
|
- Channel Importance: `IMPORTANCE_NONE` (0)
|
|
- Channel Enabled: `false`
|
|
- Status shows blocked channel warning
|
|
|
|
#### Test 1.3: Channel Settings Deep Link
|
|
|
|
**Objective**: Test deep linking to channel settings
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. In app UI, tap "Open Channel Settings"
|
|
# 2. Verify system settings open to correct channel
|
|
```
|
|
|
|
**Expected Results**:
|
|
- System settings open
|
|
- Correct app package selected
|
|
- Correct channel ID selected
|
|
|
|
### Test Suite 2: PendingIntent & Exact Alarms (P0 Priority 2)
|
|
|
|
#### Test 2.1: Exact Alarm Permission Check
|
|
|
|
**Objective**: Verify exact alarm permission detection and handling
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. In app UI, tap "Comprehensive Status"
|
|
# 2. Check exact alarm status
|
|
```
|
|
|
|
**Expected Results**:
|
|
- `exactAlarmsSupported`: `true` (Android 12+)
|
|
- `exactAlarmsGranted`: `true` or `false`
|
|
- `canScheduleNow`: Depends on all permissions
|
|
|
|
**Verification Commands**:
|
|
```bash
|
|
# Check exact alarm permission
|
|
adb shell "dumpsys alarm | grep SCHEDULE_EXACT_ALARM"
|
|
|
|
# Check alarm manager status
|
|
adb shell "dumpsys alarm | grep -A5 -B5 timesafari"
|
|
```
|
|
|
|
#### Test 2.2: Modern PendingIntent Flags
|
|
|
|
**Objective**: Verify PendingIntent uses modern flags
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Schedule a notification
|
|
# 2. Check alarm details
|
|
```
|
|
|
|
**Verification Commands**:
|
|
```bash
|
|
# Check PendingIntent flags in alarm
|
|
adb shell "dumpsys alarm | grep -A10 -B5 timesafari"
|
|
|
|
# Look for FLAG_IMMUTABLE in alarm details
|
|
```
|
|
|
|
**Expected Results**:
|
|
- PendingIntent uses `FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE`
|
|
- No security warnings in logs
|
|
|
|
#### Test 2.3: Exact Alarm Settings Deep Link
|
|
|
|
**Objective**: Test deep linking to exact alarm settings
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. In app UI, tap "Exact Alarm Settings"
|
|
# 2. Verify system settings open
|
|
```
|
|
|
|
**Expected Results**:
|
|
- System settings open to exact alarm settings
|
|
- Correct app package selected
|
|
|
|
### Test Suite 3: JIT Freshness Re-check (P0 Priority 3)
|
|
|
|
#### Test 3.1: Fresh Content Check
|
|
|
|
**Objective**: Verify JIT freshness check for recent content
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Schedule a notification
|
|
# 2. Wait for it to fire (should be fresh)
|
|
# 3. Check logs for JIT behavior
|
|
```
|
|
|
|
**Verification Commands**:
|
|
```bash
|
|
# Monitor JIT freshness logs
|
|
adb logcat | grep -i "jit\|freshness\|stale"
|
|
|
|
# Look for: "Content is fresh (age: X minutes), skipping JIT refresh"
|
|
```
|
|
|
|
**Expected Results**:
|
|
- Content age < 6 hours: JIT refresh skipped
|
|
- Log shows: "Content is fresh, skipping JIT refresh"
|
|
|
|
#### Test 3.2: Stale Content Refresh
|
|
|
|
**Objective**: Test JIT refresh for stale content
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Schedule a notification
|
|
# 2. Wait 6+ hours (or modify code to use shorter threshold for testing)
|
|
# 3. Wait for notification to fire
|
|
# 4. Check logs for refresh attempt
|
|
```
|
|
|
|
**Verification Commands**:
|
|
```bash
|
|
# Monitor JIT refresh logs
|
|
adb logcat | grep -i "stale.*minutes.*attempting.*refresh"
|
|
|
|
# Look for: "Content is stale (age: X minutes), attempting JIT refresh"
|
|
```
|
|
|
|
**Expected Results**:
|
|
- Content age > 6 hours: JIT refresh attempted
|
|
- Log shows: "Content is stale, attempting JIT refresh"
|
|
- Either: "JIT refresh succeeded" or "JIT refresh failed, using original content"
|
|
|
|
#### Test 3.3: JIT Refresh Fallback
|
|
|
|
**Objective**: Test graceful fallback when refresh fails
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Disable network connectivity
|
|
# 2. Schedule notification with stale content
|
|
# 3. Wait for notification to fire
|
|
# 4. Check logs for fallback behavior
|
|
```
|
|
|
|
**Expected Results**:
|
|
- JIT refresh attempted
|
|
- Refresh fails due to network
|
|
- Original content used as fallback
|
|
- Log shows: "JIT refresh failed, using original content"
|
|
|
|
### Test Suite 4: Recovery Coexistence (P0 Priority 4)
|
|
|
|
#### Test 4.1: App Startup Recovery
|
|
|
|
**Objective**: Test idempotent app startup recovery
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Schedule notifications
|
|
# 2. Close app normally
|
|
# 3. Launch app multiple times quickly
|
|
# 4. Check recovery logs
|
|
```
|
|
|
|
**Verification Commands**:
|
|
```bash
|
|
# Check recovery manager logs
|
|
adb logcat | grep -i "recovery.*requested.*app_startup"
|
|
|
|
# Look for cooldown behavior
|
|
adb logcat | grep -i "recovery.*performed.*recently.*skipping"
|
|
```
|
|
|
|
**Expected Results**:
|
|
- First launch: Recovery performed
|
|
- Subsequent launches: Recovery skipped due to cooldown
|
|
- Log shows: "Recovery performed recently (Xs ago), skipping"
|
|
|
|
#### Test 4.2: Boot Recovery Integration
|
|
|
|
**Objective**: Test boot recovery with app startup recovery
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Schedule notifications
|
|
# 2. Reboot device
|
|
# 3. Check boot recovery logs
|
|
# 4. Launch app and check startup recovery
|
|
```
|
|
|
|
**Verification Commands**:
|
|
```bash
|
|
# Check boot recovery
|
|
adb logcat -d | grep -i "boot.*completed.*restoring"
|
|
|
|
# Check startup recovery cooldown
|
|
adb logcat -d | grep -i "recovery.*requested.*app_startup"
|
|
```
|
|
|
|
**Expected Results**:
|
|
- Boot recovery: "Recovery requested from: BOOT_COMPLETED"
|
|
- App startup: "Recovery performed recently, skipping"
|
|
- No duplicate recovery operations
|
|
|
|
#### Test 4.3: Recovery Statistics
|
|
|
|
**Objective**: Test recovery statistics tracking
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Perform multiple recovery operations
|
|
# 2. Check recovery stats
|
|
```
|
|
|
|
**Verification Commands**:
|
|
```bash
|
|
# Check recovery stats (if implemented in UI)
|
|
# Or check logs for recovery count
|
|
adb logcat -d | grep -i "recovery.*count"
|
|
```
|
|
|
|
**Expected Results**:
|
|
- Recovery count increments correctly
|
|
- Last recovery time tracked
|
|
- Success status tracked
|
|
|
|
---
|
|
|
|
## Reboot Testing Procedures
|
|
|
|
### Enhanced Reboot Test Suite
|
|
|
|
#### Test R1: Boot Receiver with RecoveryManager
|
|
|
|
**Objective**: Test new RecoveryManager-based boot recovery
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Schedule notification
|
|
adb shell am start -n com.timesafari.dailynotification/.MainActivity
|
|
# Tap "Test Notification" in UI
|
|
|
|
# 2. Verify initial scheduling
|
|
adb shell "dumpsys alarm | grep timesafari"
|
|
|
|
# 3. Reboot device
|
|
adb reboot
|
|
|
|
# 4. Wait for boot completion
|
|
adb wait-for-device
|
|
sleep 30
|
|
|
|
# 5. Check recovery logs
|
|
adb logcat -d | grep -i "recovery.*requested.*boot_completed"
|
|
```
|
|
|
|
**Expected Results**:
|
|
- Boot recovery triggered: "Recovery requested from: BOOT_COMPLETED"
|
|
- Recovery performed or skipped based on cooldown
|
|
- Alarms restored correctly
|
|
|
|
#### Test R2: App Update Recovery
|
|
|
|
**Objective**: Test MY_PACKAGE_REPLACED recovery
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Schedule notification
|
|
# 2. Update app
|
|
cd android && ./gradlew assembleDebug
|
|
adb install -r app/build/outputs/apk/debug/app-debug.apk
|
|
|
|
# 3. Check recovery logs
|
|
adb logcat -d | grep -i "recovery.*requested.*my_package_replaced"
|
|
```
|
|
|
|
**Expected Results**:
|
|
- Package replacement recovery triggered
|
|
- Notifications restored after update
|
|
|
|
#### Test R3: Recovery Coexistence Test
|
|
|
|
**Objective**: Test boot recovery + app startup recovery coexistence
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Schedule notification
|
|
# 2. Reboot device
|
|
# 3. Immediately launch app after boot
|
|
# 4. Check both recovery logs
|
|
```
|
|
|
|
**Verification Commands**:
|
|
```bash
|
|
# Check both recovery sources
|
|
adb logcat -d | grep -i "recovery.*requested.*\(boot_completed\|app_startup\)"
|
|
|
|
# Verify cooldown prevents duplicate recovery
|
|
adb logcat -d | grep -i "recovery.*performed.*recently.*skipping"
|
|
```
|
|
|
|
**Expected Results**:
|
|
- Boot recovery performed
|
|
- App startup recovery skipped due to cooldown
|
|
- No duplicate operations
|
|
|
|
---
|
|
|
|
## Automated Test Suites
|
|
|
|
### Comprehensive Test Script v2.0
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# comprehensive-test-v2.sh
|
|
|
|
set -e
|
|
|
|
APP_PACKAGE="com.timesafari.dailynotification"
|
|
APP_ACTIVITY=".MainActivity"
|
|
TEST_TIMEOUT=300 # 5 minutes
|
|
|
|
echo "🧪 DailyNotification Plugin Comprehensive Test Suite v2.0"
|
|
echo "========================================================"
|
|
echo "Testing P0 Production-Grade Features:"
|
|
echo "✅ Channel Management (P0 Priority 1)"
|
|
echo "✅ PendingIntent & Exact Alarms (P0 Priority 2)"
|
|
echo "✅ JIT Freshness Re-check (P0 Priority 3)"
|
|
echo "✅ Recovery Coexistence (P0 Priority 4)"
|
|
echo ""
|
|
|
|
# Test results tracking
|
|
declare -A test_results
|
|
|
|
# Function to run test and track result
|
|
run_test() {
|
|
local test_name="$1"
|
|
local test_function="$2"
|
|
|
|
echo "🧪 Running: $test_name"
|
|
echo "----------------------------------------"
|
|
|
|
if $test_function; then
|
|
echo "✅ PASS: $test_name"
|
|
test_results["$test_name"]="PASS"
|
|
else
|
|
echo "❌ FAIL: $test_name"
|
|
test_results["$test_name"]="FAIL"
|
|
fi
|
|
echo ""
|
|
}
|
|
|
|
# Test 1: Channel Management
|
|
test_channel_management() {
|
|
echo "📢 Testing Channel Management..."
|
|
|
|
# Launch app
|
|
adb shell am start -n $APP_PACKAGE/$APP_ACTIVITY
|
|
sleep 3
|
|
|
|
# Check channel exists
|
|
if adb shell "dumpsys notification | grep -q daily_default"; then
|
|
echo "✅ Channel exists"
|
|
else
|
|
echo "❌ Channel not found"
|
|
return 1
|
|
fi
|
|
|
|
# Check channel importance
|
|
local importance=$(adb shell "dumpsys notification | grep -A5 daily_default | grep importance" | head -1)
|
|
if [[ "$importance" == *"3"* ]]; then
|
|
echo "✅ Channel importance correct (HIGH)"
|
|
else
|
|
echo "❌ Channel importance incorrect: $importance"
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Test 2: PendingIntent & Exact Alarms
|
|
test_pendingintent_alarms() {
|
|
echo "⏰ Testing PendingIntent & Exact Alarms..."
|
|
|
|
# Check exact alarm support
|
|
if adb shell "dumpsys alarm | grep -q SCHEDULE_EXACT_ALARM"; then
|
|
echo "✅ Exact alarm permission system available"
|
|
else
|
|
echo "⚠️ Exact alarm permission system not available (pre-Android 12)"
|
|
fi
|
|
|
|
# Schedule notification and check alarm
|
|
echo "📅 Scheduling test notification..."
|
|
echo "⚠️ Manual step: Schedule notification in app UI"
|
|
read -p "Press Enter when notification is scheduled..."
|
|
|
|
# Check alarm scheduled
|
|
if adb shell "dumpsys alarm | grep -q timesafari"; then
|
|
echo "✅ Alarm scheduled successfully"
|
|
else
|
|
echo "❌ No alarm found"
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Test 3: JIT Freshness Re-check
|
|
test_jit_freshness() {
|
|
echo "🔄 Testing JIT Freshness Re-check..."
|
|
|
|
# Clear logs
|
|
adb logcat -c
|
|
|
|
# Schedule notification
|
|
echo "📅 Scheduling notification for JIT test..."
|
|
echo "⚠️ Manual step: Schedule notification in app UI"
|
|
read -p "Press Enter when notification is scheduled..."
|
|
|
|
# Wait for notification to fire
|
|
echo "⏰ Waiting for notification to fire..."
|
|
timeout 60 bash -c '
|
|
while true; do
|
|
if adb logcat -d | grep -q "Content is fresh.*skipping JIT refresh"; then
|
|
echo "✅ JIT freshness check working (fresh content)"
|
|
exit 0
|
|
elif adb logcat -d | grep -q "Content is stale.*attempting JIT refresh"; then
|
|
echo "✅ JIT freshness check working (stale content)"
|
|
exit 0
|
|
fi
|
|
sleep 5
|
|
done
|
|
'
|
|
|
|
if [ $? -eq 0 ]; then
|
|
echo "✅ JIT freshness re-check working"
|
|
return 0
|
|
else
|
|
echo "❌ JIT freshness re-check not working"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Test 4: Recovery Coexistence
|
|
test_recovery_coexistence() {
|
|
echo "🔄 Testing Recovery Coexistence..."
|
|
|
|
# Clear logs
|
|
adb logcat -c
|
|
|
|
# Schedule notification
|
|
echo "📅 Scheduling notification for recovery test..."
|
|
echo "⚠️ Manual step: Schedule notification in app UI"
|
|
read -p "Press Enter when notification is scheduled..."
|
|
|
|
# Launch app multiple times to test cooldown
|
|
echo "🚀 Testing app startup recovery cooldown..."
|
|
adb shell am start -n $APP_PACKAGE/$APP_ACTIVITY
|
|
sleep 2
|
|
adb shell am start -n $APP_PACKAGE/$APP_ACTIVITY
|
|
sleep 2
|
|
adb shell am start -n $APP_PACKAGE/$APP_ACTIVITY
|
|
sleep 2
|
|
|
|
# Check recovery logs
|
|
local recovery_count=$(adb logcat -d | grep -c "Recovery requested from: APP_STARTUP")
|
|
local cooldown_count=$(adb logcat -d | grep -c "Recovery performed recently.*skipping")
|
|
|
|
if [ $recovery_count -eq 1 ] && [ $cooldown_count -gt 0 ]; then
|
|
echo "✅ Recovery cooldown working correctly"
|
|
echo " - Recovery performed: $recovery_count times"
|
|
echo " - Cooldown skips: $cooldown_count times"
|
|
return 0
|
|
else
|
|
echo "❌ Recovery cooldown not working"
|
|
echo " - Recovery performed: $recovery_count times"
|
|
echo " - Cooldown skips: $cooldown_count times"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Test 5: Reboot Recovery
|
|
test_reboot_recovery() {
|
|
echo "🔄 Testing Reboot Recovery..."
|
|
|
|
# Schedule notification
|
|
echo "📅 Scheduling notification for reboot test..."
|
|
echo "⚠️ Manual step: Schedule notification in app UI"
|
|
read -p "Press Enter when notification is scheduled..."
|
|
|
|
# Verify initial scheduling
|
|
if ! adb shell "dumpsys alarm | grep -q timesafari"; then
|
|
echo "❌ No alarm scheduled before reboot"
|
|
return 1
|
|
fi
|
|
|
|
echo "🔄 Rebooting device..."
|
|
adb reboot
|
|
|
|
echo "⏳ Waiting for device to boot..."
|
|
adb wait-for-device
|
|
sleep 30
|
|
|
|
# Check recovery logs
|
|
if adb logcat -d | grep -q "Recovery requested from: BOOT_COMPLETED"; then
|
|
echo "✅ Boot recovery triggered"
|
|
else
|
|
echo "❌ Boot recovery not triggered"
|
|
return 1
|
|
fi
|
|
|
|
# Check alarms restored
|
|
if adb shell "dumpsys alarm | grep -q timesafari"; then
|
|
echo "✅ Alarms restored after reboot"
|
|
return 0
|
|
else
|
|
echo "❌ Alarms not restored after reboot"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Main test execution
|
|
main() {
|
|
echo "🚀 Starting comprehensive test suite..."
|
|
echo ""
|
|
|
|
# Run all tests
|
|
run_test "Channel Management" test_channel_management
|
|
run_test "PendingIntent & Exact Alarms" test_pendingintent_alarms
|
|
run_test "JIT Freshness Re-check" test_jit_freshness
|
|
run_test "Recovery Coexistence" test_recovery_coexistence
|
|
run_test "Reboot Recovery" test_reboot_recovery
|
|
|
|
# Print results summary
|
|
echo "📊 Test Results Summary"
|
|
echo "======================"
|
|
local pass_count=0
|
|
local total_count=0
|
|
|
|
for test_name in "${!test_results[@]}"; do
|
|
local result="${test_results[$test_name]}"
|
|
echo "$test_name: $result"
|
|
if [ "$result" = "PASS" ]; then
|
|
((pass_count++))
|
|
fi
|
|
((total_count++))
|
|
done
|
|
|
|
echo ""
|
|
echo "Overall: $pass_count/$total_count tests passed"
|
|
|
|
if [ $pass_count -eq $total_count ]; then
|
|
echo "🎉 All tests passed! P0 features working correctly."
|
|
exit 0
|
|
else
|
|
echo "❌ Some tests failed. Check logs for details."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Run main function
|
|
main
|
|
```
|
|
|
|
### Python Test Suite v2.0
|
|
|
|
```python
|
|
#!/usr/bin/env python3
|
|
"""
|
|
DailyNotification Plugin Comprehensive Test Suite v2.0
|
|
Tests all P0 production-grade features
|
|
"""
|
|
|
|
import subprocess
|
|
import time
|
|
import sys
|
|
import json
|
|
from typing import Dict, List, Optional, Tuple
|
|
|
|
class DailyNotificationTesterV2:
|
|
def __init__(self, package: str = "com.timesafari.dailynotification"):
|
|
self.package = package
|
|
self.activity = f"{package}/.MainActivity"
|
|
self.test_results: Dict[str, bool] = {}
|
|
|
|
def run_adb_command(self, command: str) -> subprocess.CompletedProcess:
|
|
"""Run ADB command and return result"""
|
|
return subprocess.run(
|
|
f"adb {command}",
|
|
shell=True,
|
|
capture_output=True,
|
|
text=True
|
|
)
|
|
|
|
def is_app_running(self) -> bool:
|
|
"""Check if app is currently running"""
|
|
result = self.run_adb_command(f'shell "ps | grep {self.package}"')
|
|
return result.returncode == 0 and self.package in result.stdout
|
|
|
|
def launch_app(self) -> bool:
|
|
"""Launch the app"""
|
|
result = self.run_adb_command(f"shell am start -n {self.activity}")
|
|
time.sleep(3)
|
|
return self.is_app_running()
|
|
|
|
def test_channel_management(self) -> bool:
|
|
"""Test P0 Priority 1: Channel Management"""
|
|
print("📢 Testing Channel Management...")
|
|
|
|
# Launch app
|
|
if not self.launch_app():
|
|
print("❌ Failed to launch app")
|
|
return False
|
|
|
|
# Check channel exists
|
|
result = self.run_adb_command('shell "dumpsys notification | grep daily_default"')
|
|
if result.returncode != 0:
|
|
print("❌ Channel not found")
|
|
return False
|
|
|
|
# Check channel importance
|
|
result = self.run_adb_command('shell "dumpsys notification | grep -A5 daily_default"')
|
|
if "3" not in result.stdout: # IMPORTANCE_HIGH = 3
|
|
print("❌ Channel importance incorrect")
|
|
return False
|
|
|
|
print("✅ Channel management working")
|
|
return True
|
|
|
|
def test_pendingintent_alarms(self) -> bool:
|
|
"""Test P0 Priority 2: PendingIntent & Exact Alarms"""
|
|
print("⏰ Testing PendingIntent & Exact Alarms...")
|
|
|
|
# Check exact alarm support
|
|
result = self.run_adb_command('shell "dumpsys alarm | grep SCHEDULE_EXACT_ALARM"')
|
|
if result.returncode == 0:
|
|
print("✅ Exact alarm permission system available")
|
|
else:
|
|
print("⚠️ Exact alarm permission system not available (pre-Android 12)")
|
|
|
|
# Manual step: Schedule notification
|
|
print("⚠️ Manual step: Schedule notification in app UI")
|
|
input("Press Enter when notification is scheduled...")
|
|
|
|
# Check alarm scheduled
|
|
result = self.run_adb_command('shell "dumpsys alarm | grep timesafari"')
|
|
if result.returncode != 0:
|
|
print("❌ No alarm found")
|
|
return False
|
|
|
|
print("✅ PendingIntent & Exact Alarms working")
|
|
return True
|
|
|
|
def test_jit_freshness(self) -> bool:
|
|
"""Test P0 Priority 3: JIT Freshness Re-check"""
|
|
print("🔄 Testing JIT Freshness Re-check...")
|
|
|
|
# Clear logs
|
|
self.run_adb_command("logcat -c")
|
|
|
|
# Manual step: Schedule notification
|
|
print("⚠️ Manual step: Schedule notification in app UI")
|
|
input("Press Enter when notification is scheduled...")
|
|
|
|
# Wait for notification to fire and check logs
|
|
print("⏰ Waiting for notification to fire...")
|
|
start_time = time.time()
|
|
timeout = 60
|
|
|
|
while time.time() - start_time < timeout:
|
|
result = self.run_adb_command("logcat -d")
|
|
if "Content is fresh" in result.stdout and "skipping JIT refresh" in result.stdout:
|
|
print("✅ JIT freshness check working (fresh content)")
|
|
return True
|
|
elif "Content is stale" in result.stdout and "attempting JIT refresh" in result.stdout:
|
|
print("✅ JIT freshness check working (stale content)")
|
|
return True
|
|
time.sleep(5)
|
|
|
|
print("❌ JIT freshness re-check not working")
|
|
return False
|
|
|
|
def test_recovery_coexistence(self) -> bool:
|
|
"""Test P0 Priority 4: Recovery Coexistence"""
|
|
print("🔄 Testing Recovery Coexistence...")
|
|
|
|
# Clear logs
|
|
self.run_adb_command("logcat -c")
|
|
|
|
# Manual step: Schedule notification
|
|
print("⚠️ Manual step: Schedule notification in app UI")
|
|
input("Press Enter when notification is scheduled...")
|
|
|
|
# Launch app multiple times to test cooldown
|
|
print("🚀 Testing app startup recovery cooldown...")
|
|
for i in range(3):
|
|
self.run_adb_command(f"shell am start -n {self.activity}")
|
|
time.sleep(2)
|
|
|
|
# Check recovery logs
|
|
result = self.run_adb_command("logcat -d")
|
|
recovery_count = result.stdout.count("Recovery requested from: APP_STARTUP")
|
|
cooldown_count = result.stdout.count("Recovery performed recently")
|
|
|
|
if recovery_count == 1 and cooldown_count > 0:
|
|
print(f"✅ Recovery cooldown working correctly")
|
|
print(f" - Recovery performed: {recovery_count} times")
|
|
print(f" - Cooldown skips: {cooldown_count} times")
|
|
return True
|
|
else:
|
|
print(f"❌ Recovery cooldown not working")
|
|
print(f" - Recovery performed: {recovery_count} times")
|
|
print(f" - Cooldown skips: {cooldown_count} times")
|
|
return False
|
|
|
|
def test_reboot_recovery(self) -> bool:
|
|
"""Test Reboot Recovery with RecoveryManager"""
|
|
print("🔄 Testing Reboot Recovery...")
|
|
|
|
# Manual step: Schedule notification
|
|
print("⚠️ Manual step: Schedule notification in app UI")
|
|
input("Press Enter when notification is scheduled...")
|
|
|
|
# Verify initial scheduling
|
|
result = self.run_adb_command('shell "dumpsys alarm | grep timesafari"')
|
|
if result.returncode != 0:
|
|
print("❌ No alarm scheduled before reboot")
|
|
return False
|
|
|
|
print("🔄 Rebooting device...")
|
|
self.run_adb_command("reboot")
|
|
|
|
print("⏳ Waiting for device to boot...")
|
|
self.run_adb_command("wait-for-device")
|
|
time.sleep(30)
|
|
|
|
# Check recovery logs
|
|
result = self.run_adb_command("logcat -d")
|
|
if "Recovery requested from: BOOT_COMPLETED" not in result.stdout:
|
|
print("❌ Boot recovery not triggered")
|
|
return False
|
|
|
|
# Check alarms restored
|
|
result = self.run_adb_command('shell "dumpsys alarm | grep timesafari"')
|
|
if result.returncode != 0:
|
|
print("❌ Alarms not restored after reboot")
|
|
return False
|
|
|
|
print("✅ Reboot recovery working")
|
|
return True
|
|
|
|
def run_comprehensive_test_suite(self) -> Dict[str, bool]:
|
|
"""Run complete test suite for all P0 features"""
|
|
print("🧪 DailyNotification Plugin Comprehensive Test Suite v2.0")
|
|
print("=" * 60)
|
|
print("Testing P0 Production-Grade Features:")
|
|
print("✅ Channel Management (P0 Priority 1)")
|
|
print("✅ PendingIntent & Exact Alarms (P0 Priority 2)")
|
|
print("✅ JIT Freshness Re-check (P0 Priority 3)")
|
|
print("✅ Recovery Coexistence (P0 Priority 4)")
|
|
print("")
|
|
|
|
# Run all tests
|
|
self.test_results["Channel Management"] = self.test_channel_management()
|
|
self.test_results["PendingIntent & Exact Alarms"] = self.test_pendingintent_alarms()
|
|
self.test_results["JIT Freshness Re-check"] = self.test_jit_freshness()
|
|
self.test_results["Recovery Coexistence"] = self.test_recovery_coexistence()
|
|
self.test_results["Reboot Recovery"] = self.test_reboot_recovery()
|
|
|
|
return self.test_results
|
|
|
|
def print_results_summary(self):
|
|
"""Print test results summary"""
|
|
print("\n📊 Test Results Summary")
|
|
print("=" * 30)
|
|
|
|
pass_count = 0
|
|
total_count = len(self.test_results)
|
|
|
|
for test_name, passed in self.test_results.items():
|
|
status = "✅ PASS" if passed else "❌ FAIL"
|
|
print(f"{test_name}: {status}")
|
|
if passed:
|
|
pass_count += 1
|
|
|
|
print(f"\nOverall: {pass_count}/{total_count} tests passed")
|
|
|
|
if pass_count == total_count:
|
|
print("🎉 All tests passed! P0 features working correctly.")
|
|
return True
|
|
else:
|
|
print("❌ Some tests failed. Check logs for details.")
|
|
return False
|
|
|
|
def main():
|
|
tester = DailyNotificationTesterV2()
|
|
tester.run_comprehensive_test_suite()
|
|
|
|
if tester.print_results_summary():
|
|
sys.exit(0)
|
|
else:
|
|
sys.exit(1)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
```
|
|
|
|
---
|
|
|
|
## Edge Case Testing
|
|
|
|
### Test Suite E: Edge Cases
|
|
|
|
#### Test E1: Network Connectivity Issues
|
|
|
|
**Objective**: Test behavior with poor/no network connectivity
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Disable network connectivity
|
|
adb shell "svc wifi disable"
|
|
adb shell "svc data disable"
|
|
|
|
# 2. Schedule notification
|
|
# 3. Wait for JIT refresh attempt
|
|
# 4. Check fallback behavior
|
|
```
|
|
|
|
**Expected Results**:
|
|
- JIT refresh attempted
|
|
- Refresh fails gracefully
|
|
- Original content used as fallback
|
|
|
|
#### Test E2: Battery Optimization
|
|
|
|
**Objective**: Test behavior with battery optimization enabled
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Enable battery optimization for app
|
|
adb shell "dumpsys deviceidle whitelist -com.timesafari.dailynotification"
|
|
|
|
# 2. Schedule notification
|
|
# 3. Wait for notification
|
|
# 4. Check if notification appears
|
|
```
|
|
|
|
**Expected Results**:
|
|
- Notification appears despite battery optimization
|
|
- Logs show proper alarm scheduling
|
|
|
|
#### Test E3: Multiple Rapid Scheduling
|
|
|
|
**Objective**: Test rapid notification scheduling
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Schedule multiple notifications rapidly
|
|
# 2. Check alarm manager state
|
|
# 3. Verify all notifications fire
|
|
```
|
|
|
|
**Expected Results**:
|
|
- All notifications scheduled correctly
|
|
- No conflicts or errors
|
|
- All notifications fire at correct times
|
|
|
|
---
|
|
|
|
## Performance Testing
|
|
|
|
### Test Suite P: Performance
|
|
|
|
#### Test P1: Memory Usage
|
|
|
|
**Objective**: Monitor memory usage during operation
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Check initial memory usage
|
|
adb shell "dumpsys meminfo com.timesafari.dailynotification"
|
|
|
|
# 2. Schedule multiple notifications
|
|
# 3. Check memory usage again
|
|
# 4. Wait for notifications to fire
|
|
# 5. Check final memory usage
|
|
```
|
|
|
|
**Expected Results**:
|
|
- Memory usage remains stable
|
|
- No memory leaks detected
|
|
- Proper cleanup after notifications
|
|
|
|
#### Test P2: CPU Usage
|
|
|
|
**Objective**: Monitor CPU usage during recovery operations
|
|
|
|
**Steps**:
|
|
```bash
|
|
# 1. Monitor CPU usage during app startup
|
|
adb shell "top -n 1 | grep timesafari"
|
|
|
|
# 2. Monitor CPU usage during recovery
|
|
# 3. Check CPU usage during JIT refresh
|
|
```
|
|
|
|
**Expected Results**:
|
|
- CPU usage remains reasonable
|
|
- No excessive CPU usage during recovery
|
|
- Efficient JIT refresh operations
|
|
|
|
---
|
|
|
|
## Troubleshooting Guide
|
|
|
|
### Common Issues and Solutions
|
|
|
|
#### Issue 1: Channel Not Created
|
|
|
|
**Symptoms**: Channel status shows "not found"
|
|
|
|
**Solutions**:
|
|
```bash
|
|
# Check channel creation logs
|
|
adb logcat -d | grep -i "channel.*created"
|
|
|
|
# Verify ChannelManager initialization
|
|
adb logcat -d | grep -i "channelmanager"
|
|
```
|
|
|
|
#### Issue 2: Exact Alarm Permission Denied
|
|
|
|
**Symptoms**: `exactAlarmsGranted: false`
|
|
|
|
**Solutions**:
|
|
```bash
|
|
# Check exact alarm permission
|
|
adb shell "dumpsys alarm | grep SCHEDULE_EXACT_ALARM"
|
|
|
|
# Open exact alarm settings
|
|
adb shell "am start -a android.settings.REQUEST_SCHEDULE_EXACT_ALARM -d package:com.timesafari.dailynotification"
|
|
```
|
|
|
|
#### Issue 3: JIT Refresh Not Working
|
|
|
|
**Symptoms**: No JIT refresh logs
|
|
|
|
**Solutions**:
|
|
```bash
|
|
# Check JIT refresh logs
|
|
adb logcat -d | grep -i "jit\|freshness"
|
|
|
|
# Verify content age calculation
|
|
adb logcat -d | grep -i "age.*minutes"
|
|
```
|
|
|
|
#### Issue 4: Recovery Not Working
|
|
|
|
**Symptoms**: No recovery logs after reboot
|
|
|
|
**Solutions**:
|
|
```bash
|
|
# Check RecoveryManager logs
|
|
adb logcat -d | grep -i "recovery.*requested"
|
|
|
|
# Check recovery state
|
|
adb logcat -d | grep -i "recovery.*performed.*recently"
|
|
```
|
|
|
|
### Debug Commands
|
|
|
|
```bash
|
|
# Comprehensive status check
|
|
adb shell "dumpsys notification | grep -A10 daily_default"
|
|
adb shell "dumpsys alarm | grep -A5 timesafari"
|
|
adb shell "dumpsys package com.timesafari.dailynotification | grep -A5 receiver"
|
|
|
|
# Recovery state check
|
|
adb shell "run-as com.timesafari.dailynotification ls -la /data/data/com.timesafari.dailynotification/shared_prefs/"
|
|
|
|
# Channel status check
|
|
adb shell "cmd notification list | grep daily_default"
|
|
|
|
# Alarm manager state
|
|
adb shell "dumpsys alarm | head -20"
|
|
```
|
|
|
|
---
|
|
|
|
## Success Criteria
|
|
|
|
### ✅ All Tests Pass When:
|
|
|
|
1. **Channel Management**:
|
|
- Channel created with correct ID and importance
|
|
- Channel blocking detection works
|
|
- Settings deep linking works
|
|
|
|
2. **PendingIntent & Exact Alarms**:
|
|
- Modern PendingIntent flags used
|
|
- Exact alarm permission detection works
|
|
- Settings deep linking works
|
|
|
|
3. **JIT Freshness Re-check**:
|
|
- Fresh content skips refresh
|
|
- Stale content attempts refresh
|
|
- Graceful fallback on failure
|
|
|
|
4. **Recovery Coexistence**:
|
|
- App startup recovery works
|
|
- Boot recovery works
|
|
- Cooldown prevents duplicate recovery
|
|
- Statistics tracking works
|
|
|
|
5. **Reboot Recovery**:
|
|
- Boot receiver triggered
|
|
- Notifications restored
|
|
- Alarms rescheduled correctly
|
|
|
|
### ❌ Tests Fail When:
|
|
|
|
- Any P0 feature doesn't work as expected
|
|
- Recovery operations conflict
|
|
- Memory leaks detected
|
|
- Performance issues observed
|
|
- Error logs show critical failures
|
|
|
|
---
|
|
|
|
## Conclusion
|
|
|
|
This comprehensive testing guide ensures all P0 production-grade features work correctly. The test suite covers:
|
|
|
|
- **Channel Management**: Notification channel creation and management
|
|
- **PendingIntent & Exact Alarms**: Modern Android compatibility
|
|
- **JIT Freshness Re-check**: Content freshness validation
|
|
- **Recovery Coexistence**: Idempotent recovery operations
|
|
- **Reboot Recovery**: Robust persistence across reboots
|
|
|
|
Regular testing with this guide ensures the DailyNotification plugin maintains production-grade reliability and performance.
|
|
|
|
For questions or issues, refer to the troubleshooting section or check the plugin logs using the provided ADB commands.
|