Fix daily backups being incorrectly scheduled for multiple days away.

This commit is contained in:
Cody Henthorne
2025-09-09 14:58:40 -04:00
parent a05d5ff5e6
commit 3bb6a0a560
3 changed files with 65 additions and 3 deletions

View File

@@ -5,17 +5,64 @@
package org.thoughtcrime.securesms.service
import android.app.Application
import androidx.test.core.app.ApplicationProvider
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.isGreaterThan
import assertk.assertions.isLessThan
import io.mockk.every
import io.mockk.just
import io.mockk.runs
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.testutil.MockRandom
import org.thoughtcrime.securesms.testutil.MockSignalStoreRule
import java.time.Duration
import java.time.LocalDateTime
import java.util.concurrent.TimeUnit
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.minutes
class BackPendingParticipantsListenerTest {
@RunWith(RobolectricTestRunner::class)
@Config(manifest = Config.NONE, application = Application::class)
class MessageBackupListenerTest {
@get:Rule
val rule = MockSignalStoreRule()
@Test
fun testGetNextScheduledExecutionTime() {
val listener = MessageBackupListener()
var nextTime = System.currentTimeMillis() + 1.days.inWholeMilliseconds
every { SignalStore.backup.nextBackupTime } returns nextTime
assertThat(listener.getNextScheduledExecutionTime(ApplicationProvider.getApplicationContext())).isEqualTo(nextTime)
nextTime = System.currentTimeMillis() + 2.days.inWholeMilliseconds
every { SignalStore.backup.nextBackupTime } returns nextTime
assertThat(listener.getNextScheduledExecutionTime(ApplicationProvider.getApplicationContext())).isEqualTo(nextTime)
nextTime = System.currentTimeMillis() + 8.hours.inWholeMilliseconds
every { SignalStore.backup.nextBackupTime } returns nextTime
assertThat(listener.getNextScheduledExecutionTime(ApplicationProvider.getApplicationContext())).isEqualTo(nextTime)
nextTime = System.currentTimeMillis() + 7.days.inWholeMilliseconds
every { SignalStore.backup.nextBackupTime } returns nextTime
every { SignalStore.settings.backupHour } returns 2
every { SignalStore.settings.backupMinute } returns 0
every { SignalStore.backup.nextBackupTime = any() } just runs
val adjustedTime = listener.getNextScheduledExecutionTime(ApplicationProvider.getApplicationContext())
assertThat(adjustedTime).isGreaterThan(System.currentTimeMillis())
assertThat(adjustedTime).isLessThan(System.currentTimeMillis() + 2.days.inWholeMilliseconds)
}
@Test
fun testBackupJitterExactlyWithinJitterWindow() {

View File

@@ -16,6 +16,7 @@ import org.thoughtcrime.securesms.keyvalue.EmojiValues
import org.thoughtcrime.securesms.keyvalue.InAppPaymentValues
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues
import org.thoughtcrime.securesms.keyvalue.RegistrationValues
import org.thoughtcrime.securesms.keyvalue.SettingsValues
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.keyvalue.SvrValues
import kotlin.reflect.KClass
@@ -53,6 +54,9 @@ class MockSignalStoreRule(private val relaxed: Set<KClass<*>> = emptySet()) : Ex
lateinit var backup: BackupValues
private set
lateinit var settings: SettingsValues
private set
override fun before() {
account = mockk(relaxed = relaxed.contains(AccountValues::class), relaxUnitFun = true)
phoneNumberPrivacy = mockk(relaxed = relaxed.contains(PhoneNumberPrivacyValues::class), relaxUnitFun = true)
@@ -61,6 +65,7 @@ class MockSignalStoreRule(private val relaxed: Set<KClass<*>> = emptySet()) : Ex
emoji = mockk(relaxed = relaxed.contains(EmojiValues::class), relaxUnitFun = true)
inAppPayments = mockk(relaxed = relaxed.contains(InAppPaymentValues::class), relaxUnitFun = true)
backup = mockk(relaxed = relaxed.contains(BackupValues::class), relaxUnitFun = true)
settings = mockk(relaxed = relaxed.contains(SettingsValues::class), relaxUnitFun = true)
mockkObject(SignalStore)
every { SignalStore.account } returns account
@@ -70,6 +75,7 @@ class MockSignalStoreRule(private val relaxed: Set<KClass<*>> = emptySet()) : Ex
every { SignalStore.emoji } returns emoji
every { SignalStore.inAppPayments } returns inAppPayments
every { SignalStore.backup } returns backup
every { SignalStore.settings } returns settings
}
override fun after() {