diff options
| author | Kalle Lindström <karl.lindstrom@mullvad.net> | 2025-06-09 17:16:45 +0200 |
|---|---|---|
| committer | Kalle Lindström <karl.lindstrom@mullvad.net> | 2025-06-19 09:36:26 +0200 |
| commit | cdc2c4d700cd41f37cf4b1607a0396019b1fbee5 (patch) | |
| tree | 10fbfcebf826159d515b5599634ce5b7be256f54 /android/service/src/test | |
| parent | 1748d8a7b3e8044f6b2718d25903bf1b38afad4e (diff) | |
| download | mullvadvpn-cdc2c4d700cd41f37cf4b1607a0396019b1fbee5.tar.xz mullvadvpn-cdc2c4d700cd41f37cf4b1607a0396019b1fbee5.zip | |
Use AlarmManager for notifications
Instead of scheduling system notifications from a flow we now
schedule them independently from the app lifecycle via AlarmManager.
This is done so that for example an expiry notification that the user
dismissed won't get redisplayed if the app process gets killed and
then restarted.
When the account exiry time is fetched we schedule an alarm that will
show a notification 3 days before the account time expires. This alarm
then also schedules a new alarm to show the following notification and
so on.
To make this work this PR also introduces two new broadcast receivers;
one on boot received listener and one on time time/timezone changed
listener.
Beause Android clears alarms when the devices is rebooted/the time is
changed we need these listeners to re-trigger the alarm.
To enable the broadcast receivers to re-trigger the alarm we also have
to persist the expiry time in the DataStore preferences.
Diffstat (limited to 'android/service/src/test')
| -rw-r--r-- | android/service/src/test/kotlin/net/mullvad/mullvadvpn/service/notifications/accountexpiry/AccountExpiryNotificationTriggerTest.kt | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/android/service/src/test/kotlin/net/mullvad/mullvadvpn/service/notifications/accountexpiry/AccountExpiryNotificationTriggerTest.kt b/android/service/src/test/kotlin/net/mullvad/mullvadvpn/service/notifications/accountexpiry/AccountExpiryNotificationTriggerTest.kt new file mode 100644 index 0000000000..ff4340f168 --- /dev/null +++ b/android/service/src/test/kotlin/net/mullvad/mullvadvpn/service/notifications/accountexpiry/AccountExpiryNotificationTriggerTest.kt @@ -0,0 +1,71 @@ +package net.mullvad.mullvadvpn.service.notifications.accountexpiry + +import java.time.Duration +import java.time.ZonedDateTime +import kotlin.test.assertEquals +import org.junit.jupiter.api.Test + +class AccountExpiryNotificationTriggerTest { + + @Test + fun `long account expiry should trigger 3 days before expiry`() { + val now = ZonedDateTime.now() + + val threeMonthsExpiry = now.plusDays(90) + val trigger1 = accountExpiryNotificationTriggerAt(now, threeMonthsExpiry) + assertEquals(87, Duration.between(now, trigger1).toDays()) + + val fourAndHalfDaysExpiry = now.plusDays(4).plusHours(12) + val trigger2 = accountExpiryNotificationTriggerAt(now, fourAndHalfDaysExpiry) + assertEquals(Duration.ofDays(1).plusHours(12), Duration.between(now, trigger2)) + } + + @Test + fun `account expiry that more than 2 days but less than 3 days should trigger 2 days before expiry`() { + val now = ZonedDateTime.now() + val expiry = now.plusHours(50) + val trigger = accountExpiryNotificationTriggerAt(now, expiry) + // Because acc + assertEquals(2, Duration.between(now, trigger).toHours()) + } + + @Test + fun `account expiry that is more than 1 day but less than 2 days should trigger 1 day before expiry`() { + val now = ZonedDateTime.now() + val expiry = now.plusHours(36).plusMinutes(20).plusSeconds(7) + val trigger = accountExpiryNotificationTriggerAt(now, expiry) + assertEquals( + Duration.ofHours(12).plusMinutes(20).plusSeconds(7), + Duration.between(now, trigger), + ) + } + + @Test + fun `account expiry that is less than 24 hours should trigger when account expires`() { + val now = ZonedDateTime.now() + val expiry = now.plusHours(2).plusMinutes(1).plusSeconds(30) + val trigger = accountExpiryNotificationTriggerAt(now, expiry) + + assertEquals( + Duration.ofHours(2).plusMinutes(1).plusSeconds(30), + Duration.between(now, trigger), + ) + } + + @Test + fun `account that expires now should return now`() { + val now = ZonedDateTime.now() + val trigger = accountExpiryNotificationTriggerAt(now, now) + + assertEquals(Duration.ofMillis(0), Duration.between(now, trigger)) + } + + @Test + fun `account expiry that is in the past should return the account expiry date`() { + val now = ZonedDateTime.now() + val expiry = now.minusDays(1).minusHours(17).minusMinutes(3).minusSeconds(40) + val trigger = accountExpiryNotificationTriggerAt(now, expiry) + + assertEquals(expiry, trigger) + } +} |
