Commit a77b3a75 authored by Alex Aisting's avatar Alex Aisting

* Updated from develop branch

parent ecf321f4
Pipeline #1177 skipped with stage
......@@ -7,20 +7,27 @@
| 16.06.2020 | Harri Kirik | Added the EventBus and Material Dialogs library. |
| 15.07.2020 | Harri Kirik | Updated DP-3T library version. Added "Java JWT: JSON Web Token for Java and Android" and "Bouncy Castle Crypto". |
| 15.07.2020 | Lauris Kruusamäe | Updated DP-3T library version. |
| 09.09.2020 | Lauris Kruusamäe | Updated DP-3T library version. |
| 09.09.2020 | Harri Kirik | Updated DP-3T library version. |
| 30.09.2020 | Harri Kirik | Added Mockito-Android library. |
| 19.11.2020 | Michelle Mueller | Added AndroidX SwipeRefreshLayout library. |
| 20.11.2020 | Harri Kirik | Updated versions of Kotlin language, Kotlin plugin, Gradle plugin and Java JWT. |
## Licenses
### dp3t-sdk-android
Version: 1.0.0.b5-EE
Version: 1.0.5.b1-EE-PRODUCTION
https://github.com/DP-3T/dp3t-sdk-android
License: https://github.com/DP-3T/dp3t-sdk-android/blob/master-alpha/LICENSE
Changelog: https://github.com/DP-3T/dp3t-sdk-android/blob/master-alpha/CHANGELOG.md
### Kotlin
Version: 1.3.72
Version: 1.4.20
https://github.com/JetBrains/kotlin
License: https://github.com/JetBrains/kotlin/blob/master/license/LICENSE.txt
Changelog: https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md
### Java 8 desugaring
Version: 1.0.5
https://developer.android.com/studio/write/java8-support
......@@ -42,11 +49,20 @@ Version: 3.3.3
https://github.com/mockito/mockito
License: https://github.com/mockito/mockito/blob/release/3.x/LICENSE
Changelog: https://github.com/mockito/mockito/blob/release/3.x/doc/release-notes/official.md
### Mockito Kotlin
Version: 2.2.2
https://github.com/nhaarman/mockito-kotlin
License: https://github.com/nhaarman/mockito-kotlin/blob/2.x/LICENSE
Changelog: https://github.com/nhaarman/mockito-kotlin/releases
### Mockito Android
Version: 3.3.3
https://github.com/mockito/mockito
License: https://github.com/mockito/mockito/blob/release/3.x/LICENSE
Changelog: https://github.com/mockito/mockito/blob/release/3.x/doc/release-notes/official.md
### AndroidX Test
Version: 2.1.0
https://developer.android.com/jetpack/androidx/releases/test
......@@ -87,6 +103,11 @@ Version: 1.1.3
https://developer.android.com/jetpack/androidx/releases/constraintlayout
License: https://developer.android.com/license
Changelog: https://developer.android.com/jetpack/androidx/releases/constraintlayout
### AndroidX SwipeRefreshLayout
Version: 1.1.0
https://developer.android.com/jetpack/androidx/releases/swiperefreshlayout
License: https://developer.android.com/license
Changelog: https://developer.android.com/jetpack/androidx/releases/swiperefreshlayout
### AndroidX Lifecycle Extensions
Version: 2.2.0
https://developer.android.com/jetpack/androidx/releases/lifecycle
......@@ -173,15 +194,17 @@ https://github.com/ben-manes/gradle-versions-plugin
License: https://github.com/ben-manes/gradle-versions-plugin/blob/master/LICENSE.txt
Changelog: https://github.com/ben-manes/gradle-versions-plugin/releases
### Android Gradle Plugin
Version: 4.0.0
Version: 4.1.1
https://developer.android.com/studio/releases/gradle-plugin
License: https://developer.android.com/license
Changelog: https://developer.android.com/studio/releases/gradle-plugin
### Kotlin Gradle Plugin
Version: 1.3.72
Version: 1.4.20
https://github.com/JetBrains/kotlin
License: https://github.com/JetBrains/kotlin/blob/master/license/LICENSE.txt
Changelog: https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md
### Ktlint Gradle
Version: 9.2.1
https://github.com/JLLeitschuh/ktlint-gradle
......@@ -217,7 +240,7 @@ Changelog: https://github.com/afollestad/material-dialogs/releases
### Java JWT: JSON Web Token for Java and Android
Version: 0.11.1
Version: 0.11.2
https://github.com/jwtk/jjwt
License: https://github.com/jwtk/jjwt/blob/master/LICENSE
Changelog: https://github.com/jwtk/jjwt/blob/master/CHANGELOG.md
......
# dp3t-app-android
......@@ -2,16 +2,17 @@
## Changelog
| Date | Author | Description |
| ---------- | ---------------- | ------------------------------------------------------------- |
| 22.05.2020 | Harri Kirik | First draft. Signing setup. |
| Date | Author | Description |
| ---------- | ---------------- | ------------------------------------------------------------ |
| 22.05.2020 | Harri Kirik | First draft. Signing setup. |
| 27.05.2020 | Harri Kirik | Updated the document to be a more generic readme for developers of the application. |
| 29.05.2020 | Harri Kirik | Added a section about dependency repositories. |
| 15.06.2020 | Harri Kirik | Added a section about clean builds from command line. |
| 08.07.2020 | Kelian Kaio | Added a section about agreed code style. |
| 09.07.2020 | Lauris Kruusamäe | Added a section about SSL pinning |
| 29.05.2020 | Harri Kirik | Added a section about dependency repositories. |
| 15.06.2020 | Harri Kirik | Added a section about clean builds from command line. |
| 08.07.2020 | Kelian Kaio | Added a section about agreed code style. |
| 09.07.2020 | Lauris Kruusamäe | Added a section about SSL pinning |
| 16.07.2020 | Lauris Kruusamäe | Added a section about application flavour based configuration |
| 24.07.2020 | Lauris Kruusamäe | Added a section about close contact calculation configuration |
| 16.09.2020 | Harri Kirik | Updated the information about environments. |
## Goal
......@@ -37,9 +38,17 @@ NOTE: The `keystore.properties` file should never be committed to the repository
Use the `buildAll` task to fully clean and build the application:
```bash
.\gradlew buildAll
./gradlew buildAll
```
If you get an issue where your builder runs out of memory then try the following optimized command:
```bash
./gradlew -Dorg.gradle.parallel=false -Dorg.gradle.daemon=false "-Dorg.gradle.jvmargs=-Xmx2500m" --max-workers 4 -Pkotlin.incremental=false buildAll
```
NOTE: Depending on your platform you may need to change the way how the different parameters are escaped in the command.
## Logging
### Usage
......@@ -87,7 +96,7 @@ DP-3T SDK uses its own Logger class for logs. Levels depend on the type of the b
## Dependencies
All external dependencies must be compliant with EUPL (https://tldrlegal.com/license/european-union-public-licence).
All dependencies used in this project must be listed in the [LIBRARIES](LIBRARIES.md) file together with their licence, version information and a changelog link.
All dependencies used in this project must be listed in the [LIBRARIES](LIBRARIES.md) file together with their license, version information and a changelog link.
Whenever someone adds a new dependency to the project it is their responsibility to make sure that its license is compliant and the information about the dependency is added to the [LIBRARIES](LIBRARIES.md).
### When building in TEHIK's GitLab CI
......@@ -123,17 +132,24 @@ Steps to update the pins:
The application uses different build flavours to target different environments.
We currently have the following environments:
1. icefire
1. icefire - Used by Icefire for internal dev. Usually IP blocked.
2. tehikdev - Development enviroment. Used by app devs, designers and testers. Can be used with TARA test users, see the wiki for the list of users.
2. tehiktest - Test environment. More stable than tehikdev. Used for testing.
3. tehikprod - Live production environment. Requires logging to the live Patient Portal. Can't be used with test users.
There are 2 main configurations to define for a flavour:
1. Environment interface -> This holds application and SDK configuration variables, urls, etc
2. Network Security Configuration -> SSL pinning setup. See the previous section about this
1. Environment interface -> This holds application and SDK configuration variables, urls, etc. See:
1. `IcefireEnvironment.kt`
2. `TehikdevEnvironment.kt`
3. `TehiktestEnvironment.kt`
4. `TehikprodEnvironment.kt`
2. Network Security Configuration -> SSL pinning setup. See the previous section about this.
## Close contact configuration
As the app/user's device is the one that calculates the close contact risk and decides if a notification should be displayed we can configure the calculation values. Contact detection params are set via DP3T.setMatchingParameters() method.
As the app/user's device is the one that calculates the close contact risk and decides if a notification should be displayed we can configure the calculation values. Contact detection parameters are set via `DP3T.setMatchingParameters()` method.
`Environment` implementation optionally provides a `CloseContactConfiguration` class. If that value is `null` then the default SDK configuration is used.
......@@ -143,8 +159,7 @@ The calculation is the following:
(attenuationThresholdLow * attenuationFactorLow + attenuationThresholdMedium * attenuationFactorMedium) >= minDurationForExposure
```
**NB! [SEE SDK EXPLANATION](https://github.com/DP-3T/dp3t-sdk-android/blob/master/EXPOSURE_NOTIFICATION_API_USAGE.md)**
**NB! [SEE the Swiss EXPLANATION and their current values](https://github.com/admin-ch/PT-System-Documents/blob/master/SwissCovid-ExposureScore.pdf)**
## Adding a new flavour
......
......@@ -2,10 +2,11 @@
## Changelog
| Date | Author | Description |
| ---------- | ----------- | ------------------------------- |
| 28.07.2020 | Harri Kirik | First draft. |
| 30.07.2020 | Harri Kirik | Updated as per review feedback. |
| Date | Author | Description |
| ---------- | ----------- | ------------------------------------------------------ |
| 28.07.2020 | Harri Kirik | First draft. |
| 30.07.2020 | Harri Kirik | Updated as per review feedback. |
| 30.09.2020 | Harri Kirik | Added a note about the link to release build binaries. |
## Goal
......@@ -95,12 +96,14 @@ This document contains the release procedure of the Hoia Android application. De
1. After the build navigate to the artifacts section at the CI and press the "Keep" button. This makes sure that release binaries are kept and not deleted after N days like develop ones. See https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html#browsing-artifacts for more.
6. Download the public release APK from TEHIK along with the matching ProGuard mapping file. See https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html#browsing-artifacts for more.
6. Add the link of the TEHIK CI `master` branch release build to the JIRA release task.
7. Download the public release APK from TEHIK along with the matching ProGuard mapping file. See https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html#browsing-artifacts for more.
1. The release APK can be found from the `Artifacts/app/build/outputs/apk/tehikrelease/` folder
2. The release APK ProGuard mapping can be found from the `Artifacts/app/build/outputs/mapping/tehikreleaseRelease/` folder
7. Test the release binary that will be uploaded to Play Store. Including, but not limited to:
8. Test the release binary that will be uploaded to Play Store. Including, but not limited to:
1. New features that were added since the last release
......@@ -154,7 +157,7 @@ This document contains the release procedure of the Hoia Android application. De
3. Clean install & onboarding with the new release
4. Infection Confirmation flow
4. Infection Confirmation flow (with the "not sick" result if non other is possible)
5. My Data delete data flow
......@@ -162,11 +165,11 @@ This document contains the release procedure of the Hoia Android application. De
7. Turning off BLE from system settings and re-enabling it from app settings
8. Add a comment to the release JIRA task, write up all the tests you did and the results of these tests
9. Add a comment to the release JIRA task, write up all the tests you did and the results of these tests
1. If any of the tests fail then create fix tasks for these and discuss with the team on how to proceed
9. If everything is ready then upload the release APK, Proguard mapping and release notes to Play Store to the appropriate track (depending if this is a public or a private release) and submit these for a review
10. If everything is ready then upload the release APK, Proguard mapping and release notes to Play Store to the appropriate track (depending if this is a public or a private release) and submit these for a review
1. If you personally do not have access then delegate to TEHIK DevOps. Also forward them the JIRA release task with all the collected information.
......
......@@ -31,7 +31,7 @@ ext {
*/
versionMajor = 1
versionMinor = 0
versionPatch = 2
versionPatch = 7
versionBuild = 0 // Use this when builds with the same version are needed. Change to once done
initVersioning()
}
......@@ -64,19 +64,16 @@ android {
flavorDimensions "environment"
productFlavors {
icefire {
// Flavor based configuration is in Environment implementation
// Flavor based configuration is in Environment implementation - IcefireEnvironment.kt
}
tehikdev {
// Flavor based configuration is in Environment implementation
// Flavor based configuration is in Environment implementation - TehikdevEnvironment.kt
}
tehiktest {
// Flavor based configuration is in Environment implementation
}
tehiktest2 {
// Flavor based configuration is in Environment implementation
// Flavor based configuration is in Environment implementation - TehiktestEnvironment.kt
}
tehikprod {
// Flavor based configuration is in Environment implementation
// Flavor based configuration is in Environment implementation - TehikprodEnvironment.kt
}
}
......@@ -159,6 +156,7 @@ dependencies {
implementation deps.material
implementation deps.appCompat
implementation deps.constraintLayout
implementation deps.swipeRefreshLayout
implementation deps.fragment
implementation deps.lifecycleViewmodel
implementation deps.lifecycleLivedata
......
package org.dpppt.android.app.domain.usecase.contacts
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.dpppt.android.app.STAY_HOME_DAYS
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import java.time.LocalDate
@RunWith(AndroidJUnit4::class)
class GetContactsUseCaseTest {
@Test
fun testCalculateStayHomeDate_WHEN_TODAY_IS_EXPOSURE() {
val useCase = GetContactsUseCase()
val stayAtHomeDays = STAY_HOME_DAYS
val daysSinceExposure = 0L
val dateNow = LocalDate.now()
val dateExpectedStayAtHome = dateNow.plusDays(stayAtHomeDays)
val date = useCase.calculateStayHomeDate(dateNow, daysSinceExposure, stayAtHomeDays)
Assert.assertEquals(dateExpectedStayAtHome, date)
println("daysSinceExposure $daysSinceExposure is $date")
}
@Test
fun testCalculateStayHomeDate_WHEN_YESTERDAY_WAS_EXPOSURE() {
val useCase = GetContactsUseCase()
val stayAtHomeDays = STAY_HOME_DAYS
val daysSinceExposure = 1L
val dateAtExposure = LocalDate.now()
val dateNow = dateAtExposure.plusDays(daysSinceExposure)
val dateExpectedStayAtHome = dateAtExposure.plusDays(stayAtHomeDays)
val date = useCase.calculateStayHomeDate(dateNow, daysSinceExposure, stayAtHomeDays)
Assert.assertEquals(dateExpectedStayAtHome, date)
println("daysSinceExposure $daysSinceExposure is $date")
}
@Test
fun testCalculateStayHomeDate_WHEN_13_DAYS_AGO_WAS_EXPOSURE() {
val useCase = GetContactsUseCase()
val stayAtHomeDays = STAY_HOME_DAYS
val daysSinceExposure = 13L
val dateAtExposure = LocalDate.now()
val dateNow = dateAtExposure.plusDays(daysSinceExposure)
val dateExpectedStayAtHome = dateAtExposure.plusDays(stayAtHomeDays)
val date = useCase.calculateStayHomeDate(dateNow, daysSinceExposure, stayAtHomeDays)
Assert.assertEquals(dateExpectedStayAtHome, date)
println("daysSinceExposure $daysSinceExposure is $date")
}
@Test
fun testCalculateStayHomeDate_WHEN_STAY_AT_HOME_DAYS_AGO_WAS_EXPOSURE() {
val useCase = GetContactsUseCase()
val stayAtHomeDays = STAY_HOME_DAYS
val daysSinceExposure = STAY_HOME_DAYS
val dateAtExposure = LocalDate.now()
val dateNow = dateAtExposure.plusDays(daysSinceExposure)
val dateExpectedStayAtHome = dateAtExposure.plusDays(stayAtHomeDays)
val date = useCase.calculateStayHomeDate(dateNow, daysSinceExposure, stayAtHomeDays)
Assert.assertEquals(dateExpectedStayAtHome, date)
println("daysSinceExposure $daysSinceExposure is $date")
}
@Test
fun testCalculateStayHomeDate_WHEN_STAY_AT_HOME_PLUS_1_DAYS_AGO_WAS_EXPOSURE() {
val useCase = GetContactsUseCase()
val stayAtHomeDays = STAY_HOME_DAYS
val daysSinceExposure = STAY_HOME_DAYS + 1L
val dateAtExposure = LocalDate.now()
val dateNow = dateAtExposure.plusDays(daysSinceExposure)
val dateExpectedStayAtHome = dateAtExposure.plusDays(stayAtHomeDays)
val date = useCase.calculateStayHomeDate(dateNow, daysSinceExposure, stayAtHomeDays)
Assert.assertEquals(dateExpectedStayAtHome, date)
println("daysSinceExposure $daysSinceExposure is $date")
}
@Test
fun testCalculateStayHomeDate_WHEN_STAY_AT_HOME_PLUS_6_AGO_WAS_EXPOSURE() {
val useCase = GetContactsUseCase()
val stayAtHomeDays = STAY_HOME_DAYS
val daysSinceExposure = STAY_HOME_DAYS + 6
val dateAtExposure = LocalDate.now()
val dateNow = dateAtExposure.plusDays(daysSinceExposure)
val dateExpectedStayAtHome = dateAtExposure.plusDays(stayAtHomeDays)
val date = useCase.calculateStayHomeDate(dateNow, daysSinceExposure, stayAtHomeDays)
Assert.assertEquals(dateExpectedStayAtHome, date)
println("daysSinceExposure $daysSinceExposure is $date")
}
@Test
fun testCalculateStayHomeDate_WHEN_STAY_AT_HOME_PLUS_367_DAYS_AGO_WAS_EXPOSURE() {
val useCase = GetContactsUseCase()
val stayAtHomeDays = STAY_HOME_DAYS
val daysSinceExposure = STAY_HOME_DAYS + 367
val dateAtExposure = LocalDate.now()
val dateNow = dateAtExposure.plusDays(daysSinceExposure)
val dateExpectedStayAtHome = dateAtExposure.plusDays(stayAtHomeDays)
val date = useCase.calculateStayHomeDate(dateNow, daysSinceExposure, stayAtHomeDays)
Assert.assertEquals(dateExpectedStayAtHome, date)
println("daysSinceExposure $daysSinceExposure is $date")
}
}
package org.dpppt.android.app.domain.usecase.data
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.nhaarman.mockitokotlin2.doReturn
import com.nhaarman.mockitokotlin2.mock
import org.dpppt.android.app.domain.entity.MyDataState
import org.dpppt.android.app.storage.SecureStorage
import org.junit.Test
import org.junit.runner.RunWith
import java.time.LocalDateTime
import kotlin.test.assertEquals
@RunWith(AndroidJUnit4::class)
class CheckIsMyDataDeletableUseCaseTest {
@Test
fun execute_SHOULD_BE_SAFE_TO_DELETE_MY_DATA_WHEN_TIMESTAMP_IS_NULL() {
val secureStorage: SecureStorage = mock {
on { confirmInfectionResultTimestamp } doReturn null
}
val useCase = CheckIsMyDataDeletableUseCase(secureStorage)
assertEquals(MyDataState.SafeToDelete, useCase.execute())
}
@Test
fun execute_SHOULD_BE_MARKED_AS_DATA_SENT_WHEN_24_HOURS_HAVE_PASSED() {
val secureStorage: SecureStorage = mock {
on { confirmInfectionResultTimestamp } doReturn LocalDateTime.now().minusDays(2)
}
val useCase = CheckIsMyDataDeletableUseCase(secureStorage)
assertEquals(MyDataState.DataSent, useCase.execute())
}
@Test
fun execute_SHOULD_NOT_BE_SAFE_TO_DELETE_MY_DATA_WHEN_LESS_THAN_24_HOURS_HAVE_PASSED() {
val secureStorage: SecureStorage = mock {
on { confirmInfectionResultTimestamp } doReturn LocalDateTime.now().minusDays(1).plusMinutes(1)
}
val useCase = CheckIsMyDataDeletableUseCase(secureStorage)
assertEquals(MyDataState.NotSafeToDelete, useCase.execute())
}
}
package org.dpppt.android.app.domain.usecase.dp3t
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.argumentCaptor
import com.nhaarman.mockitokotlin2.doAnswer
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.verify
import org.dpppt.android.app.ActivityService
import org.dpppt.android.app.CONFIRM_INFECTION_ALLOWED_PAST_DAYS
import org.dpppt.android.app.CONFIRM_INFECTION_EXTRA_ALLOWED_PAST_DAYS
import org.dpppt.android.app.common.toEpochMilliUtc
import org.dpppt.android.app.domain.entity.ConfirmInfectionRequest
import org.dpppt.android.app.domain.gateway.Dp3tGateway
import org.dpppt.android.sdk.backend.ResponseCallback
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import java.time.LocalDate
import java.util.Date
import kotlin.test.assertEquals
@RunWith(AndroidJUnit4::class)
class GaenSendIAmInfectedUseCaseTest {
private lateinit var activityService: ActivityService
private lateinit var dp3TGateway: Dp3tGateway
@Before
fun setup() {
activityService = ActivityService()
activityService.onCreate(mock())
dp3TGateway = mock {
on { sendIAmInfected(any(), any(), any(), any()) } doAnswer {
(it.arguments.last() as ResponseCallback<*>).onSuccess(null)
}
}
}
@Test
fun execute_SHOULD_USE_MAX_ALLOWED_DATE_FOR_DATE_ONSET() {
val maxAllowedDate = LocalDate.now().minusDays(CONFIRM_INFECTION_ALLOWED_PAST_DAYS)
val selectedDate = maxAllowedDate.plusDays(1)
val selectedTimestamp = selectedDate.toEpochMilliUtc()
executeUseCase(selectedTimestamp)
val expected = Date(maxAllowedDate.toEpochMilliUtc())
argumentCaptor<Date> {
verify(dp3TGateway).sendIAmInfected(any(), any(), capture(), any())
assertEquals(expected, firstValue)
}
}
@Test
fun execute_SHOULD_USE_EXTRA_ALLOWED_DAYS_FOR_DATE_ONSET() {
val maxAllowedDate = LocalDate.now().minusDays(CONFIRM_INFECTION_ALLOWED_PAST_DAYS)
val selectedDate = maxAllowedDate.plusDays(5)
val selectedTimestamp = selectedDate.toEpochMilliUtc()
executeUseCase(selectedTimestamp)
val expected = Date(selectedDate.minusDays(2).toEpochMilliUtc())
argumentCaptor<Date> {
verify(dp3TGateway).sendIAmInfected(any(), any(), capture(), any())
assertEquals(expected, firstValue)
}
}
private fun executeUseCase(selectedTimestamp: Long) {
val request = ConfirmInfectionRequest(
key = "123",
infectionTimestamp = selectedTimestamp
)
val useCase = GaenSendIAmInfectedUseCase(
activityService = activityService,
dp3TGateway = dp3TGateway,
confirmInfectionAllowedPastDays = CONFIRM_INFECTION_ALLOWED_PAST_DAYS,
confirmInfectionExtraAllowedPastDays = CONFIRM_INFECTION_EXTRA_ALLOWED_PAST_DAYS
)
useCase.execute(request).test().onComplete()
}
}
package org.dpppt.android.app.domain.usecase.dp3t
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.nhaarman.mockitokotlin2.doReturn
import com.nhaarman.mockitokotlin2.mock
import org.dpppt.android.app.domain.entity.AppTracingStatus
import org.dpppt.android.app.main.model.TracingState
import org.dpppt.android.app.main.model.TracingStatusInterface
import org.dpppt.android.sdk.TracingStatus
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class IsTracingWorkingUseCaseTest {
@Test
fun testGetInterpretedTracingStatus_WHEN_TRACING_ACTIVE() {
val useCase = IsTracingWorkingUseCase(IsGaenWorkingUseCase())
val tracingStatus: TracingStatusInterface = mock {
on { tracingState } doReturn TracingState.ACTIVE
on { isReportedAsInfected } doReturn false
}
val compositeStatus = useCase.getInterpretedTracingStatus(tracingStatus)
Assert.assertEquals(AppTracingStatus.Active, compositeStatus)