31 KiB
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
- P0 Feature Testing
- Reboot Testing Procedures
- Automated Test Suites
- Edge Case Testing
- Performance Testing
- 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:
# 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:
# 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:
# 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:
# 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:
# 1. In app UI, tap "Comprehensive Status"
# 2. Check exact alarm status
Expected Results:
exactAlarmsSupported
:true
(Android 12+)exactAlarmsGranted
:true
orfalse
canScheduleNow
: Depends on all permissions
Verification Commands:
# 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:
# 1. Schedule a notification
# 2. Check alarm details
Verification Commands:
# 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:
# 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:
# 1. Schedule a notification
# 2. Wait for it to fire (should be fresh)
# 3. Check logs for JIT behavior
Verification Commands:
# 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:
# 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:
# 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:
# 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:
# 1. Schedule notifications
# 2. Close app normally
# 3. Launch app multiple times quickly
# 4. Check recovery logs
Verification Commands:
# 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:
# 1. Schedule notifications
# 2. Reboot device
# 3. Check boot recovery logs
# 4. Launch app and check startup recovery
Verification Commands:
# 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:
# 1. Perform multiple recovery operations
# 2. Check recovery stats
Verification Commands:
# 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:
# 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:
# 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:
# 1. Schedule notification
# 2. Reboot device
# 3. Immediately launch app after boot
# 4. Check both recovery logs
Verification Commands:
# 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
#!/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
#!/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:
# 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:
# 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:
# 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:
# 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:
# 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:
# 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:
# 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:
# 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:
# Check RecoveryManager logs
adb logcat -d | grep -i "recovery.*requested"
# Check recovery state
adb logcat -d | grep -i "recovery.*performed.*recently"
Debug Commands
# 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:
-
Channel Management:
- Channel created with correct ID and importance
- Channel blocking detection works
- Settings deep linking works
-
PendingIntent & Exact Alarms:
- Modern PendingIntent flags used
- Exact alarm permission detection works
- Settings deep linking works
-
JIT Freshness Re-check:
- Fresh content skips refresh
- Stale content attempts refresh
- Graceful fallback on failure
-
Recovery Coexistence:
- App startup recovery works
- Boot recovery works
- Cooldown prevents duplicate recovery
- Statistics tracking works
-
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.