diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/api/ui/DebugOptionsState.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/api/ui/DebugOptionsState.kt index a86be3932b084a0c27af1488d8681d0aeab6e427..1b6dfba3e38df02fb09a5a9ea586cf4d2eabf1da 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/api/ui/DebugOptionsState.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/api/ui/DebugOptionsState.kt @@ -2,5 +2,5 @@ package de.rki.coronawarnapp.test.api.ui data class DebugOptionsState( val areNotificationsEnabled: Boolean, - val is3HourModeEnabled: Boolean + val isHourlyTestingMode: Boolean ) diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/api/ui/TestForAPIFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/api/ui/TestForAPIFragment.kt index 56b698bd963029fff8b59a291b1529d30cb5f6ea..f9a8c07a390713a995e1cef6eddf47dd8a38d60e 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/api/ui/TestForAPIFragment.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/api/ui/TestForAPIFragment.kt @@ -140,12 +140,10 @@ class TestForAPIFragment : Fragment(R.layout.fragment_test_for_a_p_i), qrPager.adapter = qrPagerAdapter // Debug card - binding.threeHourModeToggle.apply { - setOnClickListener { vm.setLast3HoursMode(isChecked) } - } - vm.last3HourToggleEvent.observe2(this) { - showToast("Last 3 Hours Mode is activated: $it") + binding.hourlyKeyPkgMode.apply { + setOnClickListener { vm.setHourlyKeyPkgMode(isChecked) } } + binding.backgroundNotificationsToggle.apply { setOnClickListener { vm.setBackgroundNotifications(isChecked) } } @@ -155,7 +153,7 @@ class TestForAPIFragment : Fragment(R.layout.fragment_test_for_a_p_i), vm.debugOptionsState.observe2(this) { state -> binding.apply { backgroundNotificationsToggle.isChecked = state.areNotificationsEnabled - threeHourModeToggle.isChecked = state.is3HourModeEnabled + hourlyKeyPkgMode.isChecked = state.isHourlyTestingMode } } binding.testLogfileToggle.apply { diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/api/ui/TestForApiFragmentViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/api/ui/TestForApiFragmentViewModel.kt index 47f89e72e1b79d80d0973fb172ea81db548b18bb..d18f0f8149c9901f22f70a81de4cc7012139c6e6 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/api/ui/TestForApiFragmentViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/api/ui/TestForApiFragmentViewModel.kt @@ -11,6 +11,7 @@ import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.TransactionException import de.rki.coronawarnapp.exception.reporting.report import de.rki.coronawarnapp.storage.LocalData +import de.rki.coronawarnapp.storage.TestSettings import de.rki.coronawarnapp.test.api.ui.EnvironmentState.Companion.toEnvironmentState import de.rki.coronawarnapp.test.api.ui.LoggerState.Companion.toLoggerState import de.rki.coronawarnapp.transaction.RiskLevelTransaction @@ -26,24 +27,22 @@ import java.io.File class TestForApiFragmentViewModel @AssistedInject constructor( @AppContext private val context: Context, - private val envSetup: EnvironmentSetup + private val envSetup: EnvironmentSetup, + private val testSettings: TestSettings ) : CWAViewModel() { val debugOptionsState by smartLiveData { DebugOptionsState( areNotificationsEnabled = LocalData.backgroundNotification(), - is3HourModeEnabled = LocalData.last3HoursMode() + isHourlyTestingMode = testSettings.isHourKeyPkgMode ) } - val last3HourToggleEvent = SingleLiveEvent<Boolean>() - - fun setLast3HoursMode(enabled: Boolean) { + fun setHourlyKeyPkgMode(enabled: Boolean) { debugOptionsState.update { - LocalData.last3HoursMode(enabled) - it.copy(is3HourModeEnabled = enabled) + testSettings.isHourKeyPkgMode = enabled + it.copy(isHourlyTestingMode = enabled) } - last3HourToggleEvent.postValue(enabled) } val environmentState by smartLiveData { diff --git a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_for_a_p_i.xml b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_for_a_p_i.xml index 9f51b5f868023c208e1c39c163a1619ea9b76dcb..41cce389352812b097f8162d07292b26dbc67372 100644 --- a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_for_a_p_i.xml +++ b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_for_a_p_i.xml @@ -40,12 +40,12 @@ app:layout_constraintTop_toTopOf="parent" /> <Switch - android:id="@+id/three_hour_mode_toggle" + android:id="@+id/hourly_key_pkg_mode" style="@style/body1" android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginTop="@dimen/spacing_small" - android:text="@string/test_api_switch_last_three_hours_from_server" + android:text="Hourly keyfile mode (last 24)" android:theme="@style/switchBase" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -61,7 +61,7 @@ android:theme="@style/switchBase" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/three_hour_mode_toggle" /> + app:layout_constraintTop_toBottomOf="@+id/hourly_key_pkg_mode" /> <Switch android:id="@+id/test_logfile_toggle" diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyFileDownloader.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyFileDownloader.kt index 7c70a16f944ea3fb4963af1a4d05eca980c6cf8b..60f6aca3482890c3a3148a2845f130293923d62e 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyFileDownloader.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyFileDownloader.kt @@ -8,8 +8,8 @@ import de.rki.coronawarnapp.diagnosiskeys.storage.CachedKeyInfo import de.rki.coronawarnapp.diagnosiskeys.storage.KeyCacheRepository import de.rki.coronawarnapp.diagnosiskeys.storage.legacy.LegacyKeyCacheMigration import de.rki.coronawarnapp.risk.TimeVariables -import de.rki.coronawarnapp.storage.AppSettings import de.rki.coronawarnapp.storage.DeviceStorage +import de.rki.coronawarnapp.storage.TestSettings import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll @@ -28,7 +28,7 @@ class KeyFileDownloader @Inject constructor( private val keyServer: DiagnosisKeyServer, private val keyCache: KeyCacheRepository, private val legacyKeyCache: LegacyKeyCacheMigration, - private val settings: AppSettings, + private val testSettings: TestSettings, private val dispatcherProvider: DispatcherProvider ) { @@ -78,7 +78,7 @@ class KeyFileDownloader @Inject constructor( ) val availableKeys = - if (settings.isLast3HourModeEnabled) { + if (testSettings.isHourKeyPkgMode) { syncMissing3Hours(filteredCountries, DEBUG_HOUR_LIMIT) keyCache.getEntriesForType(CachedKeyInfo.Type.COUNTRY_HOUR) } else { @@ -338,7 +338,7 @@ class KeyFileDownloader @Inject constructor( companion object { private val TAG: String? = KeyFileDownloader::class.simpleName - private const val DEBUG_HOUR_LIMIT = 3 + private const val DEBUG_HOUR_LIMIT = 24 // Daymode: ~512KB per day, ~14 days // Hourmode: ~20KB per hour, 24 hours, also ~512KB diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/AppSettings.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/AppSettings.kt deleted file mode 100644 index c89378bffdc07c8cb218c5b1bbdbe884f8f3daff..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/AppSettings.kt +++ /dev/null @@ -1,12 +0,0 @@ -package de.rki.coronawarnapp.storage - -import de.rki.coronawarnapp.util.CWADebug -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AppSettings @Inject constructor() { - - val isLast3HourModeEnabled: Boolean - get() = LocalData.last3HoursMode() && CWADebug.isDebugBuildOrMode -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt index 30e0c58f6ea6006f10774524888d2b8c56795fc0..a7fbff324c42d389c1626b019ea68a7ad4772c82 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt @@ -682,19 +682,6 @@ object LocalData { CoronaWarnApplication.getAppContext().getString(R.string.preference_teletan), null ) - fun last3HoursMode(value: Boolean) = getSharedPreferenceInstance().edit(true) { - putBoolean( - CoronaWarnApplication.getAppContext() - .getString(R.string.preference_last_three_hours_from_server), - value - ) - } - - fun last3HoursMode(): Boolean = getSharedPreferenceInstance().getBoolean( - CoronaWarnApplication.getAppContext() - .getString(R.string.preference_last_three_hours_from_server), false - ) - fun backgroundNotification(value: Boolean) = getSharedPreferenceInstance().edit(true) { putBoolean( CoronaWarnApplication.getAppContext() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TestSettings.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TestSettings.kt new file mode 100644 index 0000000000000000000000000000000000000000..11152b8ff33380629b06d97205a1ba66e8bc30f0 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TestSettings.kt @@ -0,0 +1,30 @@ +package de.rki.coronawarnapp.storage + +import android.content.Context +import androidx.core.content.edit +import de.rki.coronawarnapp.util.CWADebug +import de.rki.coronawarnapp.util.di.AppContext +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class TestSettings @Inject constructor( + @AppContext private val context: Context +) { + private val prefs by lazy { + context.getSharedPreferences("test_settings", Context.MODE_PRIVATE) + } + + var isHourKeyPkgMode: Boolean + get() { + val value = prefs.getBoolean(PKEY_HOURLY_TESTING_MODE, false) + return value && CWADebug.isDeviceForTestersBuild + } + set(value) = prefs.edit { + putBoolean(PKEY_HOURLY_TESTING_MODE, value) + } + + companion object { + private const val PKEY_HOURLY_TESTING_MODE = "diagnosiskeys.hourlytestmode" + } +} diff --git a/Corona-Warn-App/src/main/res/values-bg/strings.xml b/Corona-Warn-App/src/main/res/values-bg/strings.xml index d38cc68a83b8e4b6fbebd61383310db8a6d9ad0c..f7dc5b021fb369f3bc0a65835e175106807d733f 100644 --- a/Corona-Warn-App/src/main/res/values-bg/strings.xml +++ b/Corona-Warn-App/src/main/res/values-bg/strings.xml @@ -66,8 +66,6 @@ <!-- NOTR --> <string name="preference_teletan"><xliff:g id="preference">"preference_teletan"</xliff:g></string> <!-- NOTR --> - <string name="preference_last_three_hours_from_server"><xliff:g id="preference">"preference_last_three_hours_from_server"</xliff:g></string> - <!-- NOTR --> <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string> <!-- NOTR --> <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string> diff --git a/Corona-Warn-App/src/main/res/values-de/strings.xml b/Corona-Warn-App/src/main/res/values-de/strings.xml index c5f35e0859770ca209aabe0baaa89850e780f3fe..622ccee35449f2f4ba15132a8cb663717603427e 100644 --- a/Corona-Warn-App/src/main/res/values-de/strings.xml +++ b/Corona-Warn-App/src/main/res/values-de/strings.xml @@ -67,8 +67,6 @@ <!-- NOTR --> <string name="preference_teletan"><xliff:g id="preference">"preference_teletan"</xliff:g></string> <!-- NOTR --> - <string name="preference_last_three_hours_from_server"><xliff:g id="preference">"preference_last_three_hours_from_server"</xliff:g></string> - <!-- NOTR --> <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string> <!-- NOTR --> <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string> diff --git a/Corona-Warn-App/src/main/res/values-en/strings.xml b/Corona-Warn-App/src/main/res/values-en/strings.xml index 4bd148520dd683ec27c602259e062aa934cf1ba2..4cecbea3b3765eaca7cdca7f4737fdbda0588cde 100644 --- a/Corona-Warn-App/src/main/res/values-en/strings.xml +++ b/Corona-Warn-App/src/main/res/values-en/strings.xml @@ -66,8 +66,6 @@ <!-- NOTR --> <string name="preference_teletan"><xliff:g id="preference">"preference_teletan"</xliff:g></string> <!-- NOTR --> - <string name="preference_last_three_hours_from_server"><xliff:g id="preference">"preference_last_three_hours_from_server"</xliff:g></string> - <!-- NOTR --> <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string> <!-- NOTR --> <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string> diff --git a/Corona-Warn-App/src/main/res/values-pl/strings.xml b/Corona-Warn-App/src/main/res/values-pl/strings.xml index 0e9f29f0f83eadb8f44884d60eca6ff622f73bb7..63847ae8c71f1a0bd18d0ee7ce95f718844e7462 100644 --- a/Corona-Warn-App/src/main/res/values-pl/strings.xml +++ b/Corona-Warn-App/src/main/res/values-pl/strings.xml @@ -66,8 +66,6 @@ <!-- NOTR --> <string name="preference_teletan"><xliff:g id="preference">"preference_teletan"</xliff:g></string> <!-- NOTR --> - <string name="preference_last_three_hours_from_server"><xliff:g id="preference">"preference_last_three_hours_from_server"</xliff:g></string> - <!-- NOTR --> <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string> <!-- NOTR --> <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string> diff --git a/Corona-Warn-App/src/main/res/values-ro/strings.xml b/Corona-Warn-App/src/main/res/values-ro/strings.xml index f65289c55c21c6352ef3a3f201372f64b4ba130d..d5fb207a362b307c64a95a56f91064b9b04b927d 100644 --- a/Corona-Warn-App/src/main/res/values-ro/strings.xml +++ b/Corona-Warn-App/src/main/res/values-ro/strings.xml @@ -66,8 +66,6 @@ <!-- NOTR --> <string name="preference_teletan"><xliff:g id="preference">"preference_teletan"</xliff:g></string> <!-- NOTR --> - <string name="preference_last_three_hours_from_server"><xliff:g id="preference">"preference_last_three_hours_from_server"</xliff:g></string> - <!-- NOTR --> <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string> <!-- NOTR --> <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string> diff --git a/Corona-Warn-App/src/main/res/values-tr/strings.xml b/Corona-Warn-App/src/main/res/values-tr/strings.xml index 2c2df2c626c6deb0ed7fc78fdf6bb167aeab44db..7c38e8f7fe4f94ec077b6545ebe2afde16ad4450 100644 --- a/Corona-Warn-App/src/main/res/values-tr/strings.xml +++ b/Corona-Warn-App/src/main/res/values-tr/strings.xml @@ -66,8 +66,6 @@ <!-- NOTR --> <string name="preference_teletan"><xliff:g id="preference">"preference_teletan"</xliff:g></string> <!-- NOTR --> - <string name="preference_last_three_hours_from_server"><xliff:g id="preference">"preference_last_three_hours_from_server"</xliff:g></string> - <!-- NOTR --> <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string> <!-- NOTR --> <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string> diff --git a/Corona-Warn-App/src/main/res/values/strings.xml b/Corona-Warn-App/src/main/res/values/strings.xml index 01bc71d867c4ec3e4d0815d4aacf6b602442466b..1a60ecb5d71d074225a73b2bc28559d79766e10e 100644 --- a/Corona-Warn-App/src/main/res/values/strings.xml +++ b/Corona-Warn-App/src/main/res/values/strings.xml @@ -67,8 +67,6 @@ <!-- NOTR --> <string name="preference_teletan"><xliff:g id="preference">"preference_teletan"</xliff:g></string> <!-- NOTR --> - <string name="preference_last_three_hours_from_server"><xliff:g id="preference">"preference_last_three_hours_from_server"</xliff:g></string> - <!-- NOTR --> <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string> <!-- NOTR --> <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string> diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyFileDownloaderTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyFileDownloaderTest.kt index 960dae2060523e92a70b98da9b9b1c7669e3df75..b105a1b36e76664d7fcf518f640cc56bde8620b5 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyFileDownloaderTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyFileDownloaderTest.kt @@ -8,9 +8,9 @@ import de.rki.coronawarnapp.diagnosiskeys.storage.CachedKeyInfo import de.rki.coronawarnapp.diagnosiskeys.storage.CachedKeyInfo.Type import de.rki.coronawarnapp.diagnosiskeys.storage.KeyCacheRepository import de.rki.coronawarnapp.diagnosiskeys.storage.legacy.LegacyKeyCacheMigration -import de.rki.coronawarnapp.storage.AppSettings import de.rki.coronawarnapp.storage.DeviceStorage import de.rki.coronawarnapp.storage.InsufficientStorageException +import de.rki.coronawarnapp.storage.TestSettings import io.kotest.assertions.throwables.shouldThrow import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations @@ -55,7 +55,7 @@ class KeyFileDownloaderTest : BaseIOTest() { private lateinit var deviceStorage: DeviceStorage @MockK - private lateinit var settings: AppSettings + private lateinit var testSettings: TestSettings private val testDir = File(IO_TEST_BASEDIR, this::class.simpleName!!) private val keyRepoData = mutableMapOf<String, CachedKeyInfo>() @@ -70,7 +70,7 @@ class KeyFileDownloaderTest : BaseIOTest() { testDir.mkdirs() testDir.exists() shouldBe true - every { settings.isLast3HourModeEnabled } returns false + every { testSettings.isHourKeyPkgMode } returns false coEvery { server.getCountryIndex() } returns listOf("DE".loc, "NL".loc) coEvery { deviceStorage.requireSpacePrivateStorage(any()) } returns mockk<DeviceStorage.CheckResult>().apply { @@ -212,7 +212,7 @@ class KeyFileDownloaderTest : BaseIOTest() { keyServer = server, keyCache = keyCache, legacyKeyCache = legacyMigration, - settings = settings, + testSettings = testSettings, dispatcherProvider = TestDispatcherProvider ) Timber.i("createDownloader(): %s", downloader) @@ -229,7 +229,7 @@ class KeyFileDownloaderTest : BaseIOTest() { @Test fun `wanted country list is empty, hour mode`() { - every { settings.isLast3HourModeEnabled } returns true + every { testSettings.isHourKeyPkgMode } returns true val downloader = createDownloader() runBlocking { @@ -254,9 +254,9 @@ class KeyFileDownloaderTest : BaseIOTest() { @Test fun `fetching is aborted in hour if not enough free storage`() { - every { settings.isLast3HourModeEnabled } returns true + every { testSettings.isHourKeyPkgMode } returns true - coEvery { deviceStorage.requireSpacePrivateStorage(67584L) } throws InsufficientStorageException( + coEvery { deviceStorage.requireSpacePrivateStorage(540672L) } throws InsufficientStorageException( mockk(relaxed = true) ) @@ -435,12 +435,12 @@ class KeyFileDownloaderTest : BaseIOTest() { @Test fun `last3Hours fetch without prior data`() { - every { settings.isLast3HourModeEnabled } returns true + every { testSettings.isHourKeyPkgMode } returns true val downloader = createDownloader() runBlocking { - downloader.asyncFetchKeyFiles(listOf("DE".loc, "NL".loc)).size shouldBe 6 + downloader.asyncFetchKeyFiles(listOf("DE".loc, "NL".loc)).size shouldBe 48 } coVerify { @@ -482,17 +482,17 @@ class KeyFileDownloaderTest : BaseIOTest() { hourIdentifier = "10".hour ) } - coVerify(exactly = 6) { keyCache.markKeyComplete(any(), any()) } + coVerify(exactly = 48) { keyCache.markKeyComplete(any(), any()) } - keyRepoData.size shouldBe 6 + keyRepoData.size shouldBe 48 keyRepoData.values.forEach { it.isDownloadComplete shouldBe true } - coVerify { deviceStorage.requireSpacePrivateStorage(135168L) } + coVerify { deviceStorage.requireSpacePrivateStorage(1081344L) } } @Test fun `last3Hours fetch with prior data`() { - every { settings.isLast3HourModeEnabled } returns true + every { testSettings.isHourKeyPkgMode } returns true mockAddData( type = Type.COUNTRY_HOUR, @@ -512,9 +512,7 @@ class KeyFileDownloaderTest : BaseIOTest() { val downloader = createDownloader() runBlocking { - downloader.asyncFetchKeyFiles( - listOf("DE".loc, "NL".loc) - ).size shouldBe 6 + downloader.asyncFetchKeyFiles(listOf("DE".loc, "NL".loc)).size shouldBe 48 } coVerify { @@ -527,8 +525,8 @@ class KeyFileDownloaderTest : BaseIOTest() { keyCache.createCacheEntry( type = Type.COUNTRY_HOUR, location = "DE".loc, - dayIdentifier = "2020-09-03".day, - hourIdentifier = "10".hour + dayIdentifier = "2020-09-02".day, + hourIdentifier = "13".hour ) keyCache.createCacheEntry( @@ -540,19 +538,19 @@ class KeyFileDownloaderTest : BaseIOTest() { keyCache.createCacheEntry( type = Type.COUNTRY_HOUR, location = "NL".loc, - dayIdentifier = "2020-09-03".day, - hourIdentifier = "10".hour + dayIdentifier = "2020-09-02".day, + hourIdentifier = "13".hour ) } - coVerify(exactly = 4) { + coVerify(exactly = 46) { server.downloadKeyFile(any(), any(), any(), any(), any()) } - coVerify { deviceStorage.requireSpacePrivateStorage(90112L) } + coVerify { deviceStorage.requireSpacePrivateStorage(1036288L) } } @Test fun `last3Hours fetch deletes stale data`() { - every { settings.isLast3HourModeEnabled } returns true + every { testSettings.isHourKeyPkgMode } returns true val (staleKey1, _) = mockAddData( type = Type.COUNTRY_HOUR, @@ -588,7 +586,7 @@ class KeyFileDownloaderTest : BaseIOTest() { val downloader = createDownloader() runBlocking { - downloader.asyncFetchKeyFiles(listOf("DE".loc, "NL".loc)).size shouldBe 6 + downloader.asyncFetchKeyFiles(listOf("DE".loc, "NL".loc)).size shouldBe 48 } coVerify { @@ -601,8 +599,8 @@ class KeyFileDownloaderTest : BaseIOTest() { keyCache.createCacheEntry( type = Type.COUNTRY_HOUR, location = "DE".loc, - dayIdentifier = "2020-09-03".day, - hourIdentifier = "11".hour + dayIdentifier = "2020-09-02".day, + hourIdentifier = "13".hour ) keyCache.createCacheEntry( @@ -614,11 +612,11 @@ class KeyFileDownloaderTest : BaseIOTest() { keyCache.createCacheEntry( type = Type.COUNTRY_HOUR, location = "NL".loc, - dayIdentifier = "2020-09-03".day, - hourIdentifier = "11".hour + dayIdentifier = "2020-09-02".day, + hourIdentifier = "13".hour ) } - coVerify(exactly = 4) { + coVerify(exactly = 46) { server.downloadKeyFile(any(), any(), any(), any(), any()) } coVerify(exactly = 1) { keyCache.delete(listOf(staleKey1, staleKey2)) } @@ -626,12 +624,12 @@ class KeyFileDownloaderTest : BaseIOTest() { @Test fun `last3Hours fetch skips single download failures`() { - every { settings.isLast3HourModeEnabled } returns true + every { testSettings.isHourKeyPkgMode } returns true var dlCounter = 0 coEvery { server.downloadKeyFile(any(), any(), any(), any(), any()) } answers { dlCounter++ - if (dlCounter == 2) throw IOException("Timeout") + if (dlCounter % 3 == 0) throw IOException("Timeout") mockDownloadServerDownload( locationCode = arg(0), day = arg(1), @@ -643,11 +641,11 @@ class KeyFileDownloaderTest : BaseIOTest() { val downloader = createDownloader() runBlocking { - downloader.asyncFetchKeyFiles(listOf("DE".loc, "NL".loc)).size shouldBe 5 + downloader.asyncFetchKeyFiles(listOf("DE".loc, "NL".loc)).size shouldBe 32 } // We delete the entry for the failed download - coVerify(exactly = 1) { keyCache.delete(any()) } + coVerify(exactly = 16) { keyCache.delete(any()) } } @Test diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/TestSettingsTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/TestSettingsTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..6468dda956d4974478fb320e5ec5587ccf77e880 --- /dev/null +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/TestSettingsTest.kt @@ -0,0 +1,69 @@ +package de.rki.coronawarnapp.storage + +import android.content.Context +import de.rki.coronawarnapp.util.CWADebug +import io.kotest.matchers.shouldBe +import io.mockk.MockKAnnotations +import io.mockk.clearAllMocks +import io.mockk.every +import io.mockk.impl.annotations.MockK +import io.mockk.mockkObject +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import testhelpers.BaseTest +import testhelpers.preferences.MockSharedPreferences + +class TestSettingsTest : BaseTest() { + + @MockK lateinit var context: Context + private lateinit var mockPreferences: MockSharedPreferences + + @BeforeEach + fun setup() { + MockKAnnotations.init(this) + + mockkObject(CWADebug) + + mockPreferences = MockSharedPreferences() + every { + context.getSharedPreferences("test_settings", Context.MODE_PRIVATE) + } returns mockPreferences + } + + @AfterEach + fun teardown() { + clearAllMocks() + } + + private fun buildInstance(): TestSettings = TestSettings( + context = context + ) + + @Test + fun `hourly keypkg testing mode`() { + buildInstance().apply { + every { CWADebug.isDeviceForTestersBuild } returns true + + isHourKeyPkgMode shouldBe false + isHourKeyPkgMode = true + isHourKeyPkgMode shouldBe true + mockPreferences.dataMapPeek.values.single() shouldBe true + + isHourKeyPkgMode = false + isHourKeyPkgMode shouldBe false + mockPreferences.dataMapPeek.values.single() shouldBe false + + isHourKeyPkgMode = true + } + + buildInstance().apply { + isHourKeyPkgMode shouldBe true + + // In normal builds this should default to false + every { CWADebug.isDeviceForTestersBuild } returns false + + isHourKeyPkgMode shouldBe false + } + } +} diff --git a/Corona-Warn-App/src/test/java/testhelpers/KotestExtensions.kt b/Corona-Warn-App/src/test/java/testhelpers/KotestExtensions.kt index 4841a1926aff437c96ae59385930252709e2ff63..c48b1a7be39f5b60c9e1ececdfbe2219a795f193 100644 --- a/Corona-Warn-App/src/test/java/testhelpers/KotestExtensions.kt +++ b/Corona-Warn-App/src/test/java/testhelpers/KotestExtensions.kt @@ -14,8 +14,8 @@ import kotlin.time.seconds @ExperimentalTime fun <T> flakyTest(flakyAction: () -> T): Unit = runBlocking { retry( - maxRetry = 10, - timeout = 60.seconds, + maxRetry = 5, + timeout = 30.seconds, delay = 1.seconds, multiplier = 1, exceptionClass = Exception::class, diff --git a/Corona-Warn-App/src/testDeviceForTesters/java/de/rki/coronawarnapp/test/api/ui/TestForApiFragmentViewModelTest.kt b/Corona-Warn-App/src/testDeviceForTesters/java/de/rki/coronawarnapp/test/api/ui/TestForApiFragmentViewModelTest.kt index 9003b9ce6ddb1c575ae6258e00ce84eb221c4b4f..b54765d667c86b0982e70ce7be28accfc838080f 100644 --- a/Corona-Warn-App/src/testDeviceForTesters/java/de/rki/coronawarnapp/test/api/ui/TestForApiFragmentViewModelTest.kt +++ b/Corona-Warn-App/src/testDeviceForTesters/java/de/rki/coronawarnapp/test/api/ui/TestForApiFragmentViewModelTest.kt @@ -3,6 +3,7 @@ package de.rki.coronawarnapp.test.api.ui import android.content.Context import androidx.lifecycle.Observer import de.rki.coronawarnapp.environment.EnvironmentSetup +import de.rki.coronawarnapp.storage.TestSettings import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations import io.mockk.Runs @@ -30,6 +31,7 @@ class TestForApiFragmentViewModelTest : BaseTest() { @MockK private lateinit var environmentSetup: EnvironmentSetup @MockK private lateinit var context: Context + @MockK private lateinit var testSettings: TestSettings private var currentEnvironment = EnvironmentSetup.Type.DEV @@ -59,7 +61,8 @@ class TestForApiFragmentViewModelTest : BaseTest() { private fun createViewModel(): TestForApiFragmentViewModel = TestForApiFragmentViewModel( envSetup = environmentSetup, - context = context + context = context, + testSettings = testSettings ) @Test