diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt index 8d3d50bef73f1b4ed81fd3287f76d39bdd889ee5..70aec69b8c14b7d8d870012f18722c4fddde2bb4 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt @@ -135,16 +135,18 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor( fun startENFObserver() { launch { try { + val appConfig = appConfigProvider.getAppConfig() + var workState = riskScoreState.value!! val exposureWindows = enfClient.exposureWindows() val riskResultsPerWindow = exposureWindows.mapNotNull { window -> - riskLevels.calculateRisk(window)?.let { window to it } + riskLevels.calculateRisk(appConfig, window)?.let { window to it } }.toMap() - val aggregatedResult = riskLevels.aggregateResults(riskResultsPerWindow) + val aggregatedResult = riskLevels.aggregateResults(appConfig, riskResultsPerWindow) val riskAsString = "Level: ${RiskLevelRepository.getLastCalculatedScore()}\n" + "Last successful Level: " + @@ -159,8 +161,6 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor( workState = workState.copy(riskScoreMsg = riskAsString) - val appConfig = appConfigProvider.getAppConfig() - val configAsString = "Transmission RiskLevel Multiplier: ${appConfig.transmissionRiskLevelMultiplier}\n" + "Minutes At Attenuation Filters: ${appConfig.minutesAtAttenuationFilters}\n" + diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/ENFClient.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/ENFClient.kt index c965b791d0c50cb0fff69412843c6709f4277c55..587603da757c029bf13e0a553538130c9737fa96 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/ENFClient.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/ENFClient.kt @@ -29,7 +29,7 @@ class ENFClient @Inject constructor( private val exposureWindowProvider: ExposureWindowProvider, private val exposureDetectionTracker: ExposureDetectionTracker, private val enfVersion: ENFVersion -) : DiagnosisKeyProvider, TracingStatus, ScanningSupport, ExposureWindowProvider, ENFVersion by enfVersion { +) : DiagnosisKeyProvider, TracingStatus, ScanningSupport, ExposureWindowProvider, ENFVersion by enfVersion { // TODO Remove this once we no longer need direct access to the ENF Client, // i.e. in **[InternalExposureNotificationClient]** diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/ExposureStateUpdateWorker.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/ExposureStateUpdateWorker.kt index e1a84422b7ca39f9c9149ffbb77828ee77f6df33..92fe1c96528f12f4c324d68f59268b8e6dec23b1 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/ExposureStateUpdateWorker.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/ExposureStateUpdateWorker.kt @@ -8,8 +8,8 @@ import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.reporting.report -import de.rki.coronawarnapp.risk.RiskLevelTask import de.rki.coronawarnapp.risk.ExposureResultStore +import de.rki.coronawarnapp.risk.RiskLevelTask import de.rki.coronawarnapp.task.TaskController import de.rki.coronawarnapp.task.common.DefaultTaskRequest import de.rki.coronawarnapp.util.worker.InjectedWorkerFactory @@ -27,9 +27,9 @@ class ExposureStateUpdateWorker @AssistedInject constructor( try { Timber.v("worker to persist exposure summary started") enfClient.exposureWindows().also { - exposureResultStore.entities.value = Pair(it, null) - Timber.v("exposure summary state updated: $it") - } + exposureResultStore.entities.value = Pair(it, null) + Timber.v("exposure summary state updated: $it") + } taskController.submit( DefaultTaskRequest(RiskLevelTask::class, originTag = "ExposureStateUpdateWorker") diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/diagnosiskeyprovider/DefaultDiagnosisKeyProvider.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/diagnosiskeyprovider/DefaultDiagnosisKeyProvider.kt index c612cf3f0b2ca93a726a36b919d23aa89a485ebd..df3351c534882bff35403f49bb5f0c6484dffd2c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/diagnosiskeyprovider/DefaultDiagnosisKeyProvider.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/diagnosiskeyprovider/DefaultDiagnosisKeyProvider.kt @@ -27,7 +27,7 @@ class DefaultDiagnosisKeyProvider @Inject constructor( if (!enfVersion.isAtLeast(ENFVersion.V15)) { // Actually this shouldn't happen - Timber.d("No key files submitted because client uses an old unsupported version") + Timber.e("No key files submitted because client uses an old unsupported version") return false } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/diagnosiskeyprovider/SubmissionQuota.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/diagnosiskeyprovider/SubmissionQuota.kt index bf5ff885a0c194492cc122e266e34ddb5d3ee019..b671c3502ad5bf0fc014461b1e182895a6c25875 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/diagnosiskeyprovider/SubmissionQuota.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/diagnosiskeyprovider/SubmissionQuota.kt @@ -87,9 +87,9 @@ class SubmissionQuota @Inject constructor( companion object { @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) /** - * This quota changes when using ExposureWindow mode from 20 to 6 per day + * This quota should be 6 when using ExposureWindow * See: https://developers.google.com/android/exposure-notifications/release-notes */ - internal const val DEFAULT_QUOTA = 20 + internal const val DEFAULT_QUOTA = 6 } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/DefaultRiskLevels.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/DefaultRiskLevels.kt index c8d817c8d2f68f609133035992a961956206d615..9e542ee8e6d22fe0cc8797ebaa54e1d4c9e26f87 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/DefaultRiskLevels.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/DefaultRiskLevels.kt @@ -8,7 +8,6 @@ import com.google.android.gms.nearby.exposurenotification.Infectiousness import com.google.android.gms.nearby.exposurenotification.ReportType import de.rki.coronawarnapp.CoronaWarnApplication import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.appconfig.AppConfigProvider import de.rki.coronawarnapp.appconfig.ConfigData import de.rki.coronawarnapp.appconfig.internal.ApplicationConfigurationInvalidException import de.rki.coronawarnapp.exception.RiskLevelCalculationException @@ -24,8 +23,6 @@ import de.rki.coronawarnapp.storage.RiskLevelRepository import de.rki.coronawarnapp.util.TimeAndDateExtensions.millisecondsToHours import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.runBlocking import org.joda.time.Instant import timber.log.Timber import javax.inject.Inject @@ -34,20 +31,8 @@ typealias ProtoRiskLevel = RiskCalculationParametersOuterClass.NormalizedTimeToR @Singleton class DefaultRiskLevels @Inject constructor( - private val appConfigProvider: AppConfigProvider, private val exposureResultStore: ExposureResultStore ) : RiskLevels { - private var appConfig: ConfigData - - init { - runBlocking { - appConfig = appConfigProvider.getAppConfig() - } - - appConfigProvider.currentConfig - .onEach { if (it != null) appConfig = it } - } - override fun updateRepository(riskLevel: RiskLevel, time: Long) { val rollbackItems = mutableListOf<RollbackItem>() try { @@ -102,13 +87,13 @@ class DefaultRiskLevels @Inject constructor( } } - override fun isIncreasedRisk(exposureWindows: List<ExposureWindow>): Boolean { + override fun isIncreasedRisk(appConfig: ConfigData, exposureWindows: List<ExposureWindow>): Boolean { val riskResultsPerWindow = exposureWindows.mapNotNull { window -> - calculateRisk(window)?.let { window to it } + calculateRisk(appConfig, window)?.let { window to it } }.toMap() - val aggregatedResult = aggregateResults(riskResultsPerWindow) + val aggregatedResult = aggregateResults(appConfig, riskResultsPerWindow) exposureResultStore.entities.value = Pair(exposureWindows, aggregatedResult) @@ -180,26 +165,24 @@ class DefaultRiskLevels @Inject constructor( RiskLevelRepository.setRiskLevelScore(riskLevel) } - private fun dropDueToMinutesAtAttenuation( - exposureWindow: ExposureWindow, + private fun ExposureWindow.dropDueToMinutesAtAttenuation( attenuationFilters: List<RiskCalculationParametersOuterClass.MinutesAtAttenuationFilter> ) = attenuationFilters.any { attenuationFilter -> // Get total seconds at attenuation in exposure window - val secondsAtAttenuation = exposureWindow.scanInstances + val secondsAtAttenuation: Double = scanInstances .filter { attenuationFilter.attenuationRange.inRange(it.typicalAttenuationDb) } - .fold(0) { acc, scanInstance -> acc + scanInstance.secondsSinceLastScan } + .fold(.0) { acc, scanInstance -> acc + scanInstance.secondsSinceLastScan } val minutesAtAttenuation = secondsAtAttenuation / 60 return attenuationFilter.dropIfMinutesInRange.inRange(minutesAtAttenuation) } - private fun determineTransmissionRiskLevel( - exposureWindow: ExposureWindow, + private fun ExposureWindow.determineTransmissionRiskLevel( transmissionRiskLevelEncoding: RiskCalculationParametersOuterClass.TransmissionRiskLevelEncoding ): Int { - val reportTypeOffset = when (exposureWindow.reportType) { + val reportTypeOffset = when (reportType) { ReportType.RECURSIVE -> transmissionRiskLevelEncoding .reportTypeOffsetRecursive ReportType.SELF_REPORT -> transmissionRiskLevelEncoding @@ -211,7 +194,7 @@ class DefaultRiskLevels @Inject constructor( else -> throw UnknownReportTypeException() } - val infectiousnessOffset = when (exposureWindow.infectiousness) { + val infectiousnessOffset = when (infectiousness) { Infectiousness.HIGH -> transmissionRiskLevelEncoding .infectiousnessOffsetHigh else -> transmissionRiskLevelEncoding @@ -229,12 +212,11 @@ class DefaultRiskLevels @Inject constructor( it.dropIfTrlInRange.inRange(transmissionRiskLevel) } - private fun determineWeightedSeconds( - exposureWindow: ExposureWindow, + private fun ExposureWindow.determineWeightedSeconds( minutesAtAttenuationWeight: List<RiskCalculationParametersOuterClass.MinutesAtAttenuationWeight> ): Double = - exposureWindow.scanInstances.fold(.0) { seconds, scanInstance -> - val weight = + scanInstances.fold(.0) { seconds, scanInstance -> + val weight: Double = minutesAtAttenuationWeight .filter { it.attenuationRange.inRange(scanInstance.typicalAttenuationDb) } .map { it.weight } @@ -252,9 +234,10 @@ class DefaultRiskLevels @Inject constructor( .firstOrNull() override fun calculateRisk( + appConfig: ConfigData, exposureWindow: ExposureWindow ): RiskResult? { - if (dropDueToMinutesAtAttenuation(exposureWindow, appConfig.minutesAtAttenuationFilters)) { + if (exposureWindow.dropDueToMinutesAtAttenuation(appConfig.minutesAtAttenuationFilters)) { Timber.d( "%s dropped due to minutes at attenuation filter", exposureWindow @@ -262,8 +245,7 @@ class DefaultRiskLevels @Inject constructor( return null } - val transmissionRiskLevel = determineTransmissionRiskLevel( - exposureWindow, + val transmissionRiskLevel: Int = exposureWindow.determineTransmissionRiskLevel( appConfig.transmissionRiskLevelEncoding ) @@ -276,7 +258,7 @@ class DefaultRiskLevels @Inject constructor( return null } - val transmissionRiskValue = + val transmissionRiskValue: Double = transmissionRiskLevel * appConfig.transmissionRiskLevelMultiplier Timber.d( @@ -285,10 +267,9 @@ class DefaultRiskLevels @Inject constructor( transmissionRiskValue ) - val weightedMinutes = determineWeightedSeconds( - exposureWindow, + val weightedMinutes: Double = exposureWindow.determineWeightedSeconds( appConfig.minutesAtAttenuationWeights - ) / 60 + ) / 60f Timber.d( "%s's weightedMinutes are: %s", @@ -296,7 +277,7 @@ class DefaultRiskLevels @Inject constructor( weightedMinutes ) - val normalizedTime = transmissionRiskValue * weightedMinutes + val normalizedTime: Double = transmissionRiskValue * weightedMinutes Timber.d( "%s's normalizedTime is: %s", @@ -324,6 +305,7 @@ class DefaultRiskLevels @Inject constructor( } override fun aggregateResults( + appConfig: ConfigData, exposureWindowsAndResult: Map<ExposureWindow, RiskResult> ): AggregatedRiskResult { val uniqueDatesMillisSinceEpoch = exposureWindowsAndResult.keys @@ -336,7 +318,7 @@ class DefaultRiskLevels @Inject constructor( }" ) val exposureHistory = uniqueDatesMillisSinceEpoch.map { - aggregateRiskPerDate(it, exposureWindowsAndResult) + aggregateRiskPerDate(appConfig, it, exposureWindowsAndResult) } Timber.d("exposureHistory size: ${exposureHistory.size}") @@ -413,6 +395,7 @@ class DefaultRiskLevels @Inject constructor( .size private fun aggregateRiskPerDate( + appConfig: ConfigData, dateMillisSinceEpoch: Long, exposureWindowsAndResult: Map<ExposureWindow, RiskResult> ): AggregatedRiskPerDateResult { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelTask.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelTask.kt index 960d30f494cacabfbb57b7528eef12a7ac406f17..414ec6e9d8692724e11f496faed669f5ee051c1f 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelTask.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelTask.kt @@ -78,7 +78,7 @@ class RiskLevelTask @Inject constructor( UNKNOWN_RISK_OUTDATED_RESULTS_MANUAL } - isIncreasedRisk(getExposureWindows()).also { + isIncreasedRisk(configData, getExposureWindows()).also { checkCancel() } -> INCREASED_RISK diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevels.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevels.kt index 63c83ac7730eaf8f2a523b8046226e94e6c49f39..f741b8b6b508b5f25da1e38afadb2cbb50765d80 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevels.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevels.kt @@ -1,6 +1,7 @@ package de.rki.coronawarnapp.risk import com.google.android.gms.nearby.exposurenotification.ExposureWindow +import de.rki.coronawarnapp.appconfig.ConfigData import de.rki.coronawarnapp.risk.result.AggregatedRiskResult import de.rki.coronawarnapp.risk.result.RiskResult @@ -16,7 +17,7 @@ interface RiskLevels { */ fun isActiveTracingTimeAboveThreshold(): Boolean - fun isIncreasedRisk(exposureWindows: List<ExposureWindow>): Boolean + fun isIncreasedRisk(appConfig: ConfigData, exposureWindows: List<ExposureWindow>): Boolean fun updateRepository( riskLevel: RiskLevel, @@ -24,10 +25,12 @@ interface RiskLevels { ) fun calculateRisk( + appConfig: ConfigData, exposureWindow: ExposureWindow ): RiskResult? fun aggregateResults( + appConfig: ConfigData, exposureWindowsAndResult: Map<ExposureWindow, RiskResult> ): AggregatedRiskResult } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt index b9452f8b00b29de6d1775d730fa6127dc71191a2..4c2b2f955c6b11c0f0a33541b72d6149be4206ad 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt @@ -19,10 +19,10 @@ import de.rki.coronawarnapp.nearby.ENFModule import de.rki.coronawarnapp.playbook.Playbook import de.rki.coronawarnapp.playbook.PlaybookModule import de.rki.coronawarnapp.receiver.ReceiverBinder +import de.rki.coronawarnapp.risk.ExposureResultStore import de.rki.coronawarnapp.risk.RiskModule import de.rki.coronawarnapp.service.ServiceBinder import de.rki.coronawarnapp.storage.SettingsRepository -import de.rki.coronawarnapp.risk.ExposureResultStore import de.rki.coronawarnapp.storage.interoperability.InteroperabilityRepository import de.rki.coronawarnapp.submission.SubmissionModule import de.rki.coronawarnapp.submission.SubmissionTaskModule diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/appconfig/mapping/ExposureDetectionConfigMapperTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/appconfig/mapping/ExposureDetectionConfigMapperTest.kt index d93da32760a5af027f46add929fea19a347a4ce9..f39e4f9dee0a89f0d4d073cca27b76c99cabfe1b 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/appconfig/mapping/ExposureDetectionConfigMapperTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/appconfig/mapping/ExposureDetectionConfigMapperTest.kt @@ -75,7 +75,6 @@ class ExposureDetectionConfigMapperTest : BaseTest() { @Test fun `if protobuf is missing the datastructure we return defaults`() { val rawConfig = AppConfigAndroid.ApplicationConfigurationAndroid.newBuilder() - .setMinRiskScore(1) .build() createInstance().map(rawConfig).apply { overallDetectionTimeout shouldBe Duration.standardMinutes(15) diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/modules/diagnosiskeyprovider/DefaultDiagnosisKeyProviderTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/modules/diagnosiskeyprovider/DefaultDiagnosisKeyProviderTest.kt index a563e4abbcecc54c7a91b7cb5dadfa486e51a9c2..bc40640c80f231ce59679e264c3360aaff2a3c56 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/modules/diagnosiskeyprovider/DefaultDiagnosisKeyProviderTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/modules/diagnosiskeyprovider/DefaultDiagnosisKeyProviderTest.kt @@ -46,7 +46,7 @@ class DefaultDiagnosisKeyProviderTest : BaseTest() { ) @Test - fun `key provision is used on older ENF versions`() { + fun `provide diagnosis keys with outdated ENF versions`() { coEvery { enfVersion.isAtLeast(ENFVersion.V15) } returns false val provider = createProvider() @@ -77,7 +77,7 @@ class DefaultDiagnosisKeyProviderTest : BaseTest() { } @Test - fun `quota is consumed silently`() { + fun `provide diagnosis key when quota is empty`() { coEvery { enfVersion.isAtLeast(ENFVersion.V15) } returns true coEvery { submissionQuota.consumeQuota(any()) } returns false diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/modules/diagnosiskeyprovider/SubmissionQuotaTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/modules/diagnosiskeyprovider/SubmissionQuotaTest.kt index c5d7238a84bd7dea1318173e73841f09ee74bbdc..52c90fc86ad19a59195445262bde726331554c80 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/modules/diagnosiskeyprovider/SubmissionQuotaTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/modules/diagnosiskeyprovider/SubmissionQuotaTest.kt @@ -69,26 +69,25 @@ class SubmissionQuotaTest : BaseTest() { quota.consumeQuota(5) shouldBe true } - coVerify { enfData.currentQuota = 20 } + coVerify { enfData.currentQuota = 6 } // Reset to 20, then consumed 5 - testStorageCurrentQuota shouldBe 15 + testStorageCurrentQuota shouldBe 1 } @Test fun `quota consumption return true if quota was available`() { - testStorageCurrentQuota shouldBe 20 + testStorageCurrentQuota shouldBe 6 val quota = createQuota() runBlocking { - quota.consumeQuota(10) shouldBe true - quota.consumeQuota(10) shouldBe true - quota.consumeQuota(10) shouldBe false + quota.consumeQuota(3) shouldBe true + quota.consumeQuota(3) shouldBe true quota.consumeQuota(1) shouldBe false } - verify(exactly = 4) { timeStamper.nowUTC } + verify(exactly = 3) { timeStamper.nowUTC } } @Test @@ -97,7 +96,7 @@ class SubmissionQuotaTest : BaseTest() { runBlocking { quota.consumeQuota(0) shouldBe true - quota.consumeQuota(20) shouldBe true + quota.consumeQuota(6) shouldBe true quota.consumeQuota(0) shouldBe true quota.consumeQuota(1) shouldBe false } @@ -105,12 +104,12 @@ class SubmissionQuotaTest : BaseTest() { @Test fun `partial consumption is not possible`() { - testStorageCurrentQuota shouldBe 20 + testStorageCurrentQuota shouldBe 6 val quota = createQuota() runBlocking { - quota.consumeQuota(18) shouldBe true + quota.consumeQuota(4) shouldBe true quota.consumeQuota(1) shouldBe true quota.consumeQuota(2) shouldBe false } @@ -124,23 +123,23 @@ class SubmissionQuotaTest : BaseTest() { val timeTravelTarget = Instant.parse("2020-12-24T00:00:00.001Z") runBlocking { - quota.consumeQuota(20) shouldBe true - quota.consumeQuota(20) shouldBe false + quota.consumeQuota(6) shouldBe true + quota.consumeQuota(6) shouldBe false every { timeStamper.nowUTC } returns timeTravelTarget - quota.consumeQuota(20) shouldBe true + quota.consumeQuota(6) shouldBe true quota.consumeQuota(1) shouldBe false } - coVerify(exactly = 1) { enfData.currentQuota = 20 } + coVerify(exactly = 1) { enfData.currentQuota = 6 } verify(exactly = 4) { timeStamper.nowUTC } verify(exactly = 1) { enfData.lastQuotaResetAt = timeTravelTarget } } @Test fun `quota fill up is at midnight`() { - testStorageCurrentQuota = 20 + testStorageCurrentQuota = 6 testStorageLastQuotaReset = Instant.parse("2020-12-24T23:00:00.000Z") val startTime = Instant.parse("2020-12-24T23:59:59.998Z") every { timeStamper.nowUTC } returns startTime @@ -148,7 +147,7 @@ class SubmissionQuotaTest : BaseTest() { val quota = createQuota() runBlocking { - quota.consumeQuota(20) shouldBe true + quota.consumeQuota(6) shouldBe true quota.consumeQuota(1) shouldBe false every { timeStamper.nowUTC } returns startTime.plus(1) @@ -161,10 +160,10 @@ class SubmissionQuotaTest : BaseTest() { quota.consumeQuota(1) shouldBe true every { timeStamper.nowUTC } returns startTime.plus(4) - quota.consumeQuota(20) shouldBe false + quota.consumeQuota(6) shouldBe false every { timeStamper.nowUTC } returns startTime.plus(3).plus(Duration.standardDays(1)) - quota.consumeQuota(20) shouldBe true + quota.consumeQuota(6) shouldBe true } } @@ -175,26 +174,26 @@ class SubmissionQuotaTest : BaseTest() { runBlocking { every { timeStamper.nowUTC } returns startTime val quota = createQuota() - quota.consumeQuota(17) shouldBe true + quota.consumeQuota(3) shouldBe true } runBlocking { every { timeStamper.nowUTC } returns startTime.plus(Duration.standardDays(365)) val quota = createQuota() - quota.consumeQuota(20) shouldBe true + quota.consumeQuota(6) shouldBe true quota.consumeQuota(1) shouldBe false } runBlocking { every { timeStamper.nowUTC } returns startTime.plus(Duration.standardDays(365 * 2)) val quota = createQuota() - quota.consumeQuota(17) shouldBe true + quota.consumeQuota(3) shouldBe true } runBlocking { every { timeStamper.nowUTC } returns startTime.plus(Duration.standardDays(365 * 3)) val quota = createQuota() quota.consumeQuota(3) shouldBe true - quota.consumeQuota(17) shouldBe true + quota.consumeQuota(3) shouldBe true quota.consumeQuota(1) shouldBe false } } @@ -208,12 +207,12 @@ class SubmissionQuotaTest : BaseTest() { val quota = createQuota() runBlocking { - quota.consumeQuota(20) shouldBe true + quota.consumeQuota(6) shouldBe true quota.consumeQuota(1) shouldBe false // Go forward and get a reset every { timeStamper.nowUTC } returns startTime.plus(Duration.standardHours(1)) - quota.consumeQuota(20) shouldBe true + quota.consumeQuota(6) shouldBe true quota.consumeQuota(1) shouldBe false // Go backwards and don't gain a reset diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/windows/ExposureWindowsCalculationTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/windows/ExposureWindowsCalculationTest.kt index 496cbb0ff1b47f5ce5b91f290fe3ccff6e964a10..ece66bfcb20995de6a14d2bc80487d8022177d2b 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/windows/ExposureWindowsCalculationTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/windows/ExposureWindowsCalculationTest.kt @@ -104,7 +104,10 @@ class ExposureWindowsCalculationTest : BaseTest() { coEvery { appConfigProvider.getAppConfig() } returns testConfig every { appConfigProvider.currentConfig } returns flow { testConfig } logConfiguration(testConfig) - riskLevels = DefaultRiskLevels(appConfigProvider, exposureResultStore) + + riskLevels = DefaultRiskLevels(exposureResultStore) + + val appConfig = appConfigProvider.getAppConfig() // 4 - Mock and log exposure windows val allExposureWindows = mutableListOf<ExposureWindow>() @@ -118,12 +121,12 @@ class ExposureWindowsCalculationTest : BaseTest() { for (exposureWindow: ExposureWindow in exposureWindows) { logExposureWindow(exposureWindow, "âž¡âž¡ EXPOSURE WINDOW PASSED âž¡âž¡", LogLevel.EXTENDED) - val riskResult = riskLevels.calculateRisk(exposureWindow) ?: continue + val riskResult = riskLevels.calculateRisk(appConfig, exposureWindow) ?: continue exposureWindowsAndResult[exposureWindow] = riskResult } debugLog("Exposure windows and result: ${exposureWindowsAndResult.size}") - val aggregatedRiskResult = riskLevels.aggregateResults(exposureWindowsAndResult) + val aggregatedRiskResult = riskLevels.aggregateResults(appConfig, exposureWindowsAndResult) debugLog( "\n" + comparisonDebugTable(aggregatedRiskResult, case), @@ -297,7 +300,7 @@ class ExposureWindowsCalculationTest : BaseTest() { testConfig = ConfigDataContainer( serverTime = Instant.now(), - cacheValidity = Duration.ZERO, + cacheValidity = Duration.standardMinutes(5), localOffset = Duration.ZERO, mappedConfig = configData, identifier = "soup", diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelsTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelsTest.kt index 26b3cd86f7952399c02b0929698f7c3761558714..9d1d03b6c949956d784c51bb22ca03d5fb9c3c1a 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelsTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelsTest.kt @@ -1,19 +1,13 @@ package de.rki.coronawarnapp.risk -import de.rki.coronawarnapp.appconfig.AppConfigProvider import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations -import io.mockk.coEvery -import io.mockk.every import io.mockk.impl.annotations.MockK -import io.mockk.mockk import org.junit.Before import org.junit.Test import testhelpers.BaseTest class RiskLevelsTest : BaseTest() { - - @MockK lateinit var appConfigProvider: AppConfigProvider @MockK lateinit var exposureResultStore: ExposureResultStore private lateinit var riskLevels: DefaultRiskLevels @@ -21,10 +15,7 @@ class RiskLevelsTest : BaseTest() { fun setUp() { MockKAnnotations.init(this) - coEvery { appConfigProvider.getAppConfig() } returns mockk() - every { appConfigProvider.currentConfig } returns mockk() - - riskLevels = DefaultRiskLevels(appConfigProvider, exposureResultStore) + riskLevels = DefaultRiskLevels(exposureResultStore) } @Test diff --git a/Corona-Warn-App/src/testDeviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModelTest.kt b/Corona-Warn-App/src/testDeviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModelTest.kt index 2eb25af0cdcf0c4d52f3dded257154ee33eae5d8..42cc57dc1358757b6fa3f751e42ed6e64b68932c 100644 --- a/Corona-Warn-App/src/testDeviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModelTest.kt +++ b/Corona-Warn-App/src/testDeviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModelTest.kt @@ -6,6 +6,7 @@ import com.google.android.gms.nearby.exposurenotification.ExposureNotificationCl import de.rki.coronawarnapp.appconfig.AppConfigProvider import de.rki.coronawarnapp.diagnosiskeys.storage.KeyCacheRepository import de.rki.coronawarnapp.nearby.ENFClient +import de.rki.coronawarnapp.risk.ExposureResultStore import de.rki.coronawarnapp.risk.RiskLevels import de.rki.coronawarnapp.task.TaskController import de.rki.coronawarnapp.ui.tracing.card.TracingCardStateProvider @@ -41,6 +42,7 @@ class TestRiskLevelCalculationFragmentCWAViewModelTest : BaseTest() { @MockK lateinit var taskController: TaskController @MockK lateinit var riskLevels: RiskLevels @MockK lateinit var appConfigProvider: AppConfigProvider + @MockK lateinit var exposureResultStore: ExposureResultStore @BeforeEach fun setup() { @@ -68,7 +70,8 @@ class TestRiskLevelCalculationFragmentCWAViewModelTest : BaseTest() { dispatcherProvider = TestDispatcherProvider, riskLevels = riskLevels, taskController = taskController, - appConfigProvider = appConfigProvider + appConfigProvider = appConfigProvider, + exposureResultStore = exposureResultStore ) @Test