# 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.