Skip to content
Snippets Groups Projects
Unverified Commit 85a0efcc authored by Kolya Opahle's avatar Kolya Opahle Committed by GitHub
Browse files

Refactor local data unit tests (DEV) #2601

parent d31bdaf5
No related branches found
No related tags found
No related merge requests found
...@@ -3,6 +3,7 @@ package de.rki.coronawarnapp.util.encryptionmigration ...@@ -3,6 +3,7 @@ package de.rki.coronawarnapp.util.encryptionmigration
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteDatabase
import androidx.annotation.VisibleForTesting
import de.rki.coronawarnapp.bugreporting.reportProblem import de.rki.coronawarnapp.bugreporting.reportProblem
import de.rki.coronawarnapp.main.CWASettings import de.rki.coronawarnapp.main.CWASettings
import de.rki.coronawarnapp.storage.OnboardingSettings import de.rki.coronawarnapp.storage.OnboardingSettings
...@@ -97,7 +98,8 @@ class EncryptedPreferencesMigration @Inject constructor( ...@@ -97,7 +98,8 @@ class EncryptedPreferencesMigration @Inject constructor(
} }
} }
private class SettingsLocalData(private val sharedPreferences: SharedPreferences) { @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
class SettingsLocalData(private val sharedPreferences: SharedPreferences) {
fun wasInteroperabilityShown() = sharedPreferences.getBoolean(PREFERENCE_INTEROPERABILITY_WAS_USED, false) fun wasInteroperabilityShown() = sharedPreferences.getBoolean(PREFERENCE_INTEROPERABILITY_WAS_USED, false)
...@@ -109,15 +111,22 @@ class EncryptedPreferencesMigration @Inject constructor( ...@@ -109,15 +111,22 @@ class EncryptedPreferencesMigration @Inject constructor(
sharedPreferences.getInt(PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT, Int.MIN_VALUE) sharedPreferences.getInt(PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT, Int.MIN_VALUE)
companion object { companion object {
private const val PREFERENCE_INTEROPERABILITY_WAS_USED = "preference_interoperability_is_used_at_least_once" @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
private const val PKEY_NOTIFICATIONS_RISK_ENABLED = "preference_notifications_risk_enabled" const val PREFERENCE_INTEROPERABILITY_WAS_USED = "preference_interoperability_is_used_at_least_once"
private const val PKEY_NOTIFICATIONS_TEST_ENABLED = "preference_notifications_test_enabled"
private const val PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT = @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
"preference_positive_test_result_reminder_count" const val PKEY_NOTIFICATIONS_RISK_ENABLED = "preference_notifications_risk_enabled"
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
const val PKEY_NOTIFICATIONS_TEST_ENABLED = "preference_notifications_test_enabled"
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
const val PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT = "preference_positive_test_result_reminder_count"
} }
} }
private class OnboardingLocalData(private val sharedPreferences: SharedPreferences) { @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
class OnboardingLocalData(private val sharedPreferences: SharedPreferences) {
fun onboardingCompletedTimestamp(): Long? { fun onboardingCompletedTimestamp(): Long? {
val timestamp = sharedPreferences.getLong(PKEY_ONBOARDING_COMPLETED_TIMESTAMP, 0L) val timestamp = sharedPreferences.getLong(PKEY_ONBOARDING_COMPLETED_TIMESTAMP, 0L)
...@@ -128,12 +137,16 @@ class EncryptedPreferencesMigration @Inject constructor( ...@@ -128,12 +137,16 @@ class EncryptedPreferencesMigration @Inject constructor(
fun isBackgroundCheckDone(): Boolean = sharedPreferences.getBoolean(PKEY_BACKGROUND_CHECK_DONE, false) fun isBackgroundCheckDone(): Boolean = sharedPreferences.getBoolean(PKEY_BACKGROUND_CHECK_DONE, false)
companion object { companion object {
private const val PKEY_ONBOARDING_COMPLETED_TIMESTAMP = "preference_onboarding_completed_timestamp" @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
private const val PKEY_BACKGROUND_CHECK_DONE = "preference_background_check_done" const val PKEY_ONBOARDING_COMPLETED_TIMESTAMP = "preference_onboarding_completed_timestamp"
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
const val PKEY_BACKGROUND_CHECK_DONE = "preference_background_check_done"
} }
} }
private class TracingLocalData(private val sharedPreferences: SharedPreferences) { @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
class TracingLocalData(private val sharedPreferences: SharedPreferences) {
fun initialPollingForTestResultTimeStamp() = sharedPreferences.getLong(PKEY_POOLING_TEST_RESULT_STARTED, 0L) fun initialPollingForTestResultTimeStamp() = sharedPreferences.getLong(PKEY_POOLING_TEST_RESULT_STARTED, 0L)
...@@ -144,14 +157,22 @@ class EncryptedPreferencesMigration @Inject constructor( ...@@ -144,14 +157,22 @@ class EncryptedPreferencesMigration @Inject constructor(
fun initialTracingActivationTimestamp(): Long = sharedPreferences.getLong(PKEY_TRACING_ACTIVATION_TIME, 0L) fun initialTracingActivationTimestamp(): Long = sharedPreferences.getLong(PKEY_TRACING_ACTIVATION_TIME, 0L)
companion object { companion object {
private const val PKEY_POOLING_TEST_RESULT_STARTED = "preference_polling_test_result_started" @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
private const val PKEY_TEST_RESULT_NOTIFICATION = "preference_test_result_notification" const val PKEY_POOLING_TEST_RESULT_STARTED = "preference_polling_test_result_started"
private const val PKEY_HAS_RISK_STATUS_LOWERED = "preference_has_risk_status_lowered"
private const val PKEY_TRACING_ACTIVATION_TIME = "preference_initial_tracing_activation_time" @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
const val PKEY_TEST_RESULT_NOTIFICATION = "preference_test_result_notification"
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
const val PKEY_HAS_RISK_STATUS_LOWERED = "preference_has_risk_status_lowered"
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
const val PKEY_TRACING_ACTIVATION_TIME = "preference_initial_tracing_activation_time"
} }
} }
private class SubmissionLocalData(private val sharedPreferences: SharedPreferences) { @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
class SubmissionLocalData(private val sharedPreferences: SharedPreferences) {
fun registrationToken(): String? = sharedPreferences.getString(PKEY_REGISTRATION_TOKEN, null) fun registrationToken(): String? = sharedPreferences.getString(PKEY_REGISTRATION_TOKEN, null)
fun initialTestResultReceivedTimestamp(): Long? { fun initialTestResultReceivedTimestamp(): Long? {
...@@ -168,11 +189,20 @@ class EncryptedPreferencesMigration @Inject constructor( ...@@ -168,11 +189,20 @@ class EncryptedPreferencesMigration @Inject constructor(
fun isAllowedToSubmitDiagnosisKeys(): Boolean = sharedPreferences.getBoolean(PKEY_IS_ALLOWED_TO_SUBMIT, false) fun isAllowedToSubmitDiagnosisKeys(): Boolean = sharedPreferences.getBoolean(PKEY_IS_ALLOWED_TO_SUBMIT, false)
companion object { companion object {
private const val PKEY_REGISTRATION_TOKEN = "preference_registration_token" @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
private const val PKEY_INITIAL_RESULT_RECEIVED_TIME = "preference_initial_result_received_time" const val PKEY_REGISTRATION_TOKEN = "preference_registration_token"
private const val PKEY_DEVICE_PARING_SUCCESSFUL_TIME = "preference_device_pairing_successful_time"
private const val PKEY_NUMBER_SUCCESSFUL_SUBMISSIONS = "preference_number_successful_submissions" @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
private const val PKEY_IS_ALLOWED_TO_SUBMIT = "preference_is_allowed_to_submit_diagnosis_keys" const val PKEY_INITIAL_RESULT_RECEIVED_TIME = "preference_initial_result_received_time"
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
const val PKEY_DEVICE_PARING_SUCCESSFUL_TIME = "preference_device_pairing_successful_time"
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
const val PKEY_NUMBER_SUCCESSFUL_SUBMISSIONS = "preference_number_successful_submissions"
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
const val PKEY_IS_ALLOWED_TO_SUBMIT = "preference_is_allowed_to_submit_diagnosis_keys"
} }
} }
} }
package de.rki.coronawarnapp.util.encryptionmigration
import android.content.Context
import android.content.SharedPreferences
import androidx.core.content.edit
import de.rki.coronawarnapp.main.CWASettings
import de.rki.coronawarnapp.storage.OnboardingSettings
import de.rki.coronawarnapp.storage.TracingSettings
import de.rki.coronawarnapp.submission.SubmissionSettings
import io.kotest.assertions.throwables.shouldNotThrowAny
import io.kotest.matchers.shouldBe
import io.mockk.MockKAnnotations
import io.mockk.Runs
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.just
import io.mockk.mockk
import org.joda.time.Instant
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import testhelpers.BaseIOTest
import testhelpers.preferences.MockSharedPreferences
import testhelpers.preferences.mockFlowPreference
import java.io.File
class EncryptedPreferencesMigrationTest : BaseIOTest() {
@MockK lateinit var context: Context
@MockK lateinit var encryptedPreferencesHelper: EncryptedPreferencesHelper
@MockK lateinit var cwaSettings: CWASettings
@MockK lateinit var submissionSettings: SubmissionSettings
@MockK lateinit var tracingSettings: TracingSettings
@MockK lateinit var onboardingSettings: OnboardingSettings
@MockK lateinit var encryptedErrorResetTool: EncryptionErrorResetTool
private val testDir = File(IO_TEST_BASEDIR, this::class.java.simpleName)
private val dbFile = File(testDir, "database.sql")
@BeforeEach
fun setup() {
MockKAnnotations.init(this)
testDir.mkdirs()
}
@AfterEach
fun teardown() {
testDir.deleteRecursively()
}
private fun createInstance() = EncryptedPreferencesMigration(
context = context,
encryptedPreferences = encryptedPreferencesHelper,
cwaSettings = cwaSettings,
submissionSettings = submissionSettings,
tracingSettings = tracingSettings,
onboardingSettings = onboardingSettings,
errorResetTool = encryptedErrorResetTool
)
private fun createOldPreferences() = MockSharedPreferences().also {
it.edit {
// SettingsLocalData
putBoolean(EncryptedPreferencesMigration.SettingsLocalData.PREFERENCE_INTEROPERABILITY_WAS_USED, true)
putBoolean(EncryptedPreferencesMigration.SettingsLocalData.PKEY_NOTIFICATIONS_RISK_ENABLED, false)
putBoolean(EncryptedPreferencesMigration.SettingsLocalData.PKEY_NOTIFICATIONS_TEST_ENABLED, false)
putInt(
EncryptedPreferencesMigration.SettingsLocalData.PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT,
Int.MAX_VALUE
)
// OnboardingLocalData
putLong(EncryptedPreferencesMigration.OnboardingLocalData.PKEY_ONBOARDING_COMPLETED_TIMESTAMP, 10101010L)
putBoolean(EncryptedPreferencesMigration.OnboardingLocalData.PKEY_BACKGROUND_CHECK_DONE, true)
// TracingLocalData
putLong(EncryptedPreferencesMigration.TracingLocalData.PKEY_POOLING_TEST_RESULT_STARTED, 10101010L)
putBoolean(EncryptedPreferencesMigration.TracingLocalData.PKEY_TEST_RESULT_NOTIFICATION, true)
putBoolean(EncryptedPreferencesMigration.TracingLocalData.PKEY_HAS_RISK_STATUS_LOWERED, true)
putLong(EncryptedPreferencesMigration.TracingLocalData.PKEY_TRACING_ACTIVATION_TIME, 10101010L)
// SubmissionLocalData
putString(EncryptedPreferencesMigration.SubmissionLocalData.PKEY_REGISTRATION_TOKEN, "super_secret_token")
putLong(EncryptedPreferencesMigration.SubmissionLocalData.PKEY_INITIAL_RESULT_RECEIVED_TIME, 10101010L)
putLong(EncryptedPreferencesMigration.SubmissionLocalData.PKEY_DEVICE_PARING_SUCCESSFUL_TIME, 10101010L)
putInt(EncryptedPreferencesMigration.SubmissionLocalData.PKEY_NUMBER_SUCCESSFUL_SUBMISSIONS, 1)
putBoolean(EncryptedPreferencesMigration.SubmissionLocalData.PKEY_IS_ALLOWED_TO_SUBMIT, true)
}
}
@Test
fun `is migration successful`() {
every { context.getDatabasePath("coronawarnapp-db") } returns dbFile
every { encryptedPreferencesHelper.clean() } just Runs
val oldPreferences = createOldPreferences()
every { encryptedPreferencesHelper.instance } returns oldPreferences
// SettingsLocalData
every { cwaSettings.wasInteroperabilityShownAtLeastOnce = true } just Runs
val mockRiskPreference = mockFlowPreference(true)
every { cwaSettings.isNotificationsRiskEnabled } returns mockRiskPreference
val mockTestPreference = mockFlowPreference(true)
every { cwaSettings.isNotificationsTestEnabled } returns mockTestPreference
every { cwaSettings.numberOfRemainingSharePositiveTestResultReminders = Int.MAX_VALUE } just Runs
// OnboardingLocalData
every { onboardingSettings.onboardingCompletedTimestamp = Instant.ofEpochMilli(10101010L) } just Runs
every { onboardingSettings.isBackgroundCheckDone = true } just Runs
// TracingLocalData
every { tracingSettings.initialPollingForTestResultTimeStamp = 10101010L } just Runs
every { tracingSettings.isTestResultAvailableNotificationSent = true } just Runs
val mockNotificationPreference = mockFlowPreference(false)
every { tracingSettings.isUserToBeNotifiedOfLoweredRiskLevel } returns mockNotificationPreference
every { tracingSettings.isConsentGiven = true } just Runs
// SubmissionLocalData
val mockRegtokenPreference = mockFlowPreference<String?>(null)
every { submissionSettings.registrationToken } returns mockRegtokenPreference
every { submissionSettings.initialTestResultReceivedAt = Instant.ofEpochMilli(10101010L) } just Runs
every { submissionSettings.devicePairingSuccessfulAt = Instant.ofEpochMilli(10101010L) } just Runs
every { submissionSettings.isSubmissionSuccessful = true } just Runs
every { submissionSettings.isAllowedToSubmitKeys = true } just Runs
val migrationInstance = createInstance()
migrationInstance.doMigration()
// SettingsLocalData
mockRiskPreference.value shouldBe false
mockTestPreference.value shouldBe false
// TracingLocalData
mockNotificationPreference.value shouldBe true
// SubmissionLocalData
mockRegtokenPreference.value shouldBe "super_secret_token"
}
@Test
fun `error during migration will be caught`() {
every { context.getDatabasePath("coronawarnapp-db") } returns dbFile
val mockPrefs = mockk<SharedPreferences>()
every {
mockPrefs.getBoolean(
EncryptedPreferencesMigration.SettingsLocalData.PREFERENCE_INTEROPERABILITY_WAS_USED,
false
)
} throws Exception("No one expects the spanish inquisition")
every { encryptedPreferencesHelper.instance } returns mockPrefs
every { encryptedPreferencesHelper.clean() } just Runs
every { encryptedErrorResetTool.isResetNoticeToBeShown = true } just Runs
shouldNotThrowAny {
val instance = createInstance()
instance.doMigration()
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment