fix(notify): eliminate duplicate alarm scheduling and fix test harness counting
Centralize all notification alarm scheduling through NotifyReceiver.scheduleExactNotification() with idempotence checks to prevent duplicate alarms. Implement one-alarm policy using setAlarmClock() only. Fix test harness alarm counting to deduplicate by Alarm handle. Plugin Changes: - Add ScheduleSource enum to track scheduling paths (INITIAL_SETUP, ROLLOVER_ON_FIRE, etc.) - Add DB-level idempotence check before scheduling (prevents logical duplicates) - Add explicit alarm cancellation before scheduling (safety net) - Implement one-alarm policy: use setAlarmClock() only, no setExact* fallbacks for same event - Add deep logging for all AlarmManager calls (variant, requestCode, pendingIntentHash) - Update all rollover paths (DailyNotificationReceiver, DailyNotificationWorker) to use centralized function with ROLLOVER_ON_FIRE source - Add @JvmStatic annotation to scheduleExactNotification for Java interop Test Harness Changes: - Fix get_plugin_alarm_count() to deduplicate by Alarm handle (prevents double-counting same alarm in main list and "Next wake from idle" section) - Update TEST 0 messaging: treat 0 alarms as race condition (inconclusive, not failure) - Make post-rollover check the authoritative assertion point (only fails on >1 or 0 alarms) - Remove redundant "Found 0 alarms - test may not be accurate" messages This fixes the duplicate alarm bug where two distinct AlarmManager entries were created for the same daily notification, violating the "one notification per day" contract.
This commit is contained in:
@@ -52,12 +52,18 @@ test1_boot_future_alarms() {
|
||||
|
||||
substep "Step 2: Verify alarms are scheduled"
|
||||
show_alarms
|
||||
local before_count
|
||||
before_count="$(count_alarms)"
|
||||
info "Alarm count before reboot: $before_count"
|
||||
local before_count system_before
|
||||
before_count="$(get_plugin_alarm_count)"
|
||||
system_before="$(get_system_alarm_count)"
|
||||
info "Plugin alarms before reboot: $before_count (expected: 1)"
|
||||
info "System/other alarms: $system_before (for context)"
|
||||
|
||||
if [[ "$before_count" -eq 0 ]]; then
|
||||
warn "No alarms found before reboot; TEST 1 may not be meaningful."
|
||||
warn "No plugin alarms found before reboot; TEST 1 may not be meaningful."
|
||||
elif [[ "$before_count" -eq 1 ]]; then
|
||||
ok "Single plugin alarm confirmed (one per day)"
|
||||
else
|
||||
warn "Found $before_count plugin alarms (expected: 1)"
|
||||
fi
|
||||
|
||||
pause
|
||||
@@ -96,9 +102,11 @@ test1_boot_future_alarms() {
|
||||
|
||||
substep "Step 5: Verify alarms were recreated"
|
||||
show_alarms
|
||||
local after_count
|
||||
after_count="$(count_alarms)"
|
||||
info "Alarm count after boot: $after_count"
|
||||
local after_count system_after
|
||||
after_count="$(get_plugin_alarm_count)"
|
||||
system_after="$(get_system_alarm_count)"
|
||||
info "Plugin alarms after boot: $after_count (expected: 1)"
|
||||
info "System/other alarms: $system_after (for context)"
|
||||
|
||||
if [[ "$scenario" == "$BOOT_SCENARIO_VALUE" && "$rescheduled" -gt 0 ]]; then
|
||||
ok "TEST 1 PASSED: Boot recovery detected and alarms rescheduled (scenario=$scenario, rescheduled=$rescheduled)."
|
||||
@@ -276,12 +284,18 @@ test4_silent_boot_recovery() {
|
||||
|
||||
substep "Step 2: Verify alarms are scheduled"
|
||||
show_alarms
|
||||
local before_count
|
||||
before_count="$(count_alarms)"
|
||||
info "Alarm count before reboot: $before_count"
|
||||
local before_count system_before
|
||||
before_count="$(get_plugin_alarm_count)"
|
||||
system_before="$(get_system_alarm_count)"
|
||||
info "Plugin alarms before reboot: $before_count (expected: 1)"
|
||||
info "System/other alarms: $system_before (for context)"
|
||||
|
||||
if [[ "$before_count" -eq 0 ]]; then
|
||||
warn "No alarms found; TEST 4 may not be meaningful."
|
||||
warn "No plugin alarms found; TEST 4 may not be meaningful."
|
||||
elif [[ "$before_count" -eq 1 ]]; then
|
||||
ok "Single plugin alarm confirmed (one per day)"
|
||||
else
|
||||
warn "Found $before_count plugin alarms (expected: 1)"
|
||||
fi
|
||||
|
||||
pause
|
||||
@@ -317,9 +331,11 @@ test4_silent_boot_recovery() {
|
||||
|
||||
substep "Step 5: Verify alarms were recreated (without opening app)"
|
||||
show_alarms
|
||||
local after_count
|
||||
after_count="$(count_alarms)"
|
||||
info "Alarm count after boot (app never opened): $after_count"
|
||||
local after_count system_after
|
||||
after_count="$(get_plugin_alarm_count)"
|
||||
system_after="$(get_system_alarm_count)"
|
||||
info "Plugin alarms after boot (app never opened): $after_count (expected: 1)"
|
||||
info "System/other alarms: $system_after (for context)"
|
||||
|
||||
if [[ "$after_count" -gt 0 && "$rescheduled" -gt 0 ]]; then
|
||||
ok "TEST 4 PASSED: Boot recovery occurred silently and alarms were recreated (rescheduled=$rescheduled) without app launch."
|
||||
|
||||
Reference in New Issue
Block a user