Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.simprints.face.capture

import androidx.annotation.Keep
import com.simprints.core.ExcludedFromGeneratedTestCoverageReports
import com.simprints.core.domain.step.StepResult
import com.simprints.infra.images.model.SecuredImageRef

Expand All @@ -22,5 +23,29 @@ data class FaceCaptureResult(
val template: ByteArray,
val imageRef: SecuredImageRef?,
val format: String,
) : StepResult
) : StepResult {
@ExcludedFromGeneratedTestCoverageReports("Generated code")
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as Sample

if (faceId != other.faceId) return false
if (!template.contentEquals(other.template)) return false
if (imageRef != other.imageRef) return false
if (format != other.format) return false

return true
}

@ExcludedFromGeneratedTestCoverageReports("Generated code")
override fun hashCode(): Int {
var result = faceId.hashCode()
result = 31 * result + template.contentHashCode()
result = 31 * result + (imageRef?.hashCode() ?: 0)
result = 31 * result + format.hashCode()
return result
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ abstract class StepResultMixin : StepResult
)
abstract class StepParamsMixin : StepParams

/**
* Step contains all of the information required to execute an orchestration step and the result of the execution.
*
* All classes used in the params structure must implement [StepParams] interface and added to [StepParamsMixin].
* All classes used in the result structure must implement [StepResult] interface and added to [StepResultMixin].
*
* Additionally, [StepParams] and [StepResult] subclasses can only have fields of primitives, enums and serializeables classes.
*/
@Keep
internal data class Step(
val id: Int,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,57 @@
package com.simprints.feature.orchestrator.cache

import android.content.SharedPreferences
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import androidx.test.ext.junit.runners.*
import com.google.common.truth.Truth.*
import com.simprints.core.domain.common.FlowType
import com.simprints.core.domain.fingerprint.IFingerIdentifier
import com.simprints.core.domain.response.AppErrorReason
import com.simprints.core.domain.tokenization.TokenizableString
import com.simprints.core.tools.json.JsonHelper
import com.simprints.face.capture.FaceCaptureParams
import com.simprints.face.capture.FaceCaptureResult
import com.simprints.feature.alert.AlertResult
import com.simprints.feature.consent.ConsentParams
import com.simprints.feature.consent.ConsentResult
import com.simprints.feature.consent.ConsentType
import com.simprints.feature.enrollast.EnrolLastBiometricParams
import com.simprints.feature.enrollast.EnrolLastBiometricStepResult
import com.simprints.feature.enrollast.FaceTemplateCaptureResult
import com.simprints.feature.enrollast.FingerTemplateCaptureResult
import com.simprints.feature.enrollast.MatchResult
import com.simprints.feature.exitform.ExitFormOption
import com.simprints.feature.exitform.ExitFormResult
import com.simprints.feature.fetchsubject.FetchSubjectParams
import com.simprints.feature.fetchsubject.FetchSubjectResult
import com.simprints.feature.login.LoginError
import com.simprints.feature.login.LoginParams
import com.simprints.feature.login.LoginResult
import com.simprints.feature.orchestrator.steps.Step
import com.simprints.feature.orchestrator.steps.StepId
import com.simprints.feature.orchestrator.steps.StepStatus
import com.simprints.feature.selectagegroup.SelectSubjectAgeGroupResult
import com.simprints.feature.selectsubject.SelectSubjectParams
import com.simprints.feature.selectsubject.SelectSubjectResult
import com.simprints.feature.setup.SetupResult
import com.simprints.feature.validatepool.ValidateSubjectPoolFragmentParams
import com.simprints.feature.validatepool.ValidateSubjectPoolResult
import com.simprints.fingerprint.capture.FingerprintCaptureParams
import com.simprints.fingerprint.capture.FingerprintCaptureResult
import com.simprints.infra.config.store.models.AgeGroup
import com.simprints.infra.config.store.models.FaceConfiguration
import com.simprints.infra.config.store.models.Finger
import com.simprints.infra.config.store.models.FingerprintConfiguration
import com.simprints.infra.enrolment.records.repository.domain.models.BiometricDataSource
import com.simprints.infra.enrolment.records.repository.domain.models.SubjectQuery
import com.simprints.infra.events.sampledata.SampleDefaults.GUID1
import com.simprints.infra.images.model.Path
import com.simprints.infra.images.model.SecuredImageRef
import com.simprints.infra.security.SecurityManager
import io.mockk.MockKAnnotations
import io.mockk.every
import com.simprints.matcher.FaceMatchResult
import com.simprints.matcher.FingerprintMatchResult
import com.simprints.matcher.MatchParams
import io.mockk.*
import io.mockk.impl.annotations.MockK
import io.mockk.justRun
import io.mockk.slot
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
Expand Down Expand Up @@ -52,40 +86,263 @@ class OrchestratorCacheIntegrationTest {
}

@Test
fun `Stores and restores steps`() {
fun `Stores and restores common steps`() {
val expected = listOf(
Step(
id = StepId.SETUP,
navigationActionId = 5,
destinationId = 6,
params = null,
status = StepStatus.IN_PROGRESS,
result = SetupResult(true),
),
Step(
id = StepId.FETCH_GUID,
navigationActionId = 5,
destinationId = 6,
params = FetchSubjectParams("projectId", "subjectId", ""),
status = StepStatus.COMPLETED,
result = FetchSubjectResult(false),
),
Step(
id = StepId.CONSENT,
navigationActionId = 5,
destinationId = 6,
params = ConsentParams(type = ConsentType.ENROL),
status = StepStatus.COMPLETED,
result = ConsentResult(true),
),
Step(
id = StepId.ENROL_LAST_BIOMETRIC,
navigationActionId = 5,
destinationId = 6,
params = EnrolLastBiometricParams(
projectId = "projectId",
userId = TokenizableString.Raw("value"),
moduleId = TokenizableString.Raw("value"),
steps = listOf(
EnrolLastBiometricStepResult.FingerprintCaptureResult(
"referenceId",
listOf(
FingerTemplateCaptureResult(
Finger.LEFT_4TH_FINGER,
byteArrayOf(1, 2, 3),
10,
"NEC",
),
),
),
EnrolLastBiometricStepResult.FingerprintMatchResult(
listOf(MatchResult("subjectId", 0.5f)),
FingerprintConfiguration.BioSdk.SECUGEN_SIM_MATCHER,
),
EnrolLastBiometricStepResult.FaceCaptureResult(
"referenceId",
listOf(
FaceTemplateCaptureResult(byteArrayOf(1, 2, 3), "RankOne"),
),
),
EnrolLastBiometricStepResult.FaceMatchResult(
listOf(MatchResult("subjectId", 0.5f)),
FaceConfiguration.BioSdk.RANK_ONE,
),
EnrolLastBiometricStepResult.EnrolLastBiometricsResult("subjectId"),
),
),
status = StepStatus.COMPLETED,
result = ValidateSubjectPoolResult(true),
),
Step(
id = StepId.CONFIRM_IDENTITY,
navigationActionId = 5,
destinationId = 6,
params = SelectSubjectParams("projectId", "subjectId"),
status = StepStatus.COMPLETED,
result = SelectSubjectResult(true),
),
Step(
id = StepId.VALIDATE_ID_POOL,
navigationActionId = 5,
destinationId = 6,
params = ValidateSubjectPoolFragmentParams(SubjectQuery()),
status = StepStatus.COMPLETED,
result = ValidateSubjectPoolResult(true),
),
Step(
id = StepId.SELECT_SUBJECT_AGE,
navigationActionId = 5,
destinationId = 6,
params = null,
status = StepStatus.COMPLETED,
result = SelectSubjectAgeGroupResult(AgeGroup(10, null)),
),
)

cache.steps = expected
val actual = cache.steps

assertThat(actual).hasSize(expected.size)
for (i in expected.indices) {
compareStubs(expected[i], actual[i])
}
}

@Test
fun `Stores and restores fingerprint modality steps`() {
val expected = listOf(
Step(
id = StepId.FINGERPRINT_CAPTURE,
navigationActionId = 3,
destinationId = 4,
params = FingerprintCaptureParams(
flowType = FlowType.ENROL,
fingerprintsToCapture = listOf(IFingerIdentifier.LEFT_4TH_FINGER),
fingerprintSDK = FingerprintConfiguration.BioSdk.SECUGEN_SIM_MATCHER,
),
status = StepStatus.COMPLETED,
result = FingerprintCaptureResult(
"",
results = listOf(
FingerprintCaptureResult.Item(
captureEventId = GUID1,
identifier = IFingerIdentifier.LEFT_THUMB,
sample = null,
sample = FingerprintCaptureResult.Sample(
fingerIdentifier = IFingerIdentifier.LEFT_4TH_FINGER,
template = byteArrayOf(1, 2, 3),
templateQualityScore = 10,
imageRef = SecuredImageRef(Path("file/path")),
format = "NEC",
),
),
),
),
),
Step(
id = StepId.FINGERPRINT_MATCHER,
navigationActionId = 3,
destinationId = 4,
params = MatchParams(
probeReferenceId = GUID1,
flowType = FlowType.IDENTIFY,
queryForCandidates = SubjectQuery(),
biometricDataSource = BiometricDataSource.CommCare("name"),
probeFingerprintSamples = listOf(
MatchParams.FingerprintSample(
fingerId = IFingerIdentifier.LEFT_4TH_FINGER,
format = "NEC",
template = byteArrayOf(1, 2, 3),
),
),
),
status = StepStatus.COMPLETED,
result = FingerprintMatchResult(
listOf(FingerprintMatchResult.Item("subjectId", 0.5f)),
FingerprintConfiguration.BioSdk.SECUGEN_SIM_MATCHER,
),
),
)

cache.steps = expected
val actual = cache.steps

assertThat(actual).hasSize(expected.size)
for (i in expected.indices) {
compareStubs(expected[i], actual[i])
}
}

@Test
fun `Stores and restores face modality steps`() {
val expected = listOf(
Step(
id = StepId.FACE_CAPTURE,
navigationActionId = 5,
destinationId = 6,
params = FaceCaptureParams(3, FaceConfiguration.BioSdk.RANK_ONE),
status = StepStatus.COMPLETED,
result = null,
result = FaceCaptureResult(
"",
results = listOf(
FaceCaptureResult.Item(
captureEventId = "event",
index = 0,
sample = FaceCaptureResult.Sample(
faceId = "faceId",
template = byteArrayOf(1, 2, 3),
imageRef = SecuredImageRef(Path("file/path")),
format = "ROC",
),
),
),
),
),
Step(
id = StepId.FACE_MATCHER,
navigationActionId = 3,
destinationId = 4,
params = MatchParams(
probeReferenceId = GUID1,
flowType = FlowType.IDENTIFY,
queryForCandidates = SubjectQuery(),
biometricDataSource = BiometricDataSource.Simprints,
probeFaceSamples = listOf(
MatchParams.FaceSample(
faceId = "faceId",
template = byteArrayOf(1, 2, 3),
),
),
),
status = StepStatus.COMPLETED,
result = FaceMatchResult(
listOf(FaceMatchResult.Item("subjectId", 0.5f)),
FaceConfiguration.BioSdk.RANK_ONE,
),
),
)

cache.steps = expected
val actual = cache.steps

assertThat(actual).hasSize(expected.size)
for (i in expected.indices) {
compareStubs(expected[i], actual[i])
}
}

@Test
fun `Stores and restores exception steps`() {
val expected = listOf(
Step(
id = 1,
navigationActionId = 5,
destinationId = 6,
params = LoginParams("projectId", TokenizableString.Tokenized("value")),
status = StepStatus.NOT_STARTED,
result = LoginResult(false, LoginError.LoginNotCompleted),
),
Step(
id = 2,
navigationActionId = 5,
destinationId = 6,
status = StepStatus.NOT_STARTED,
result = AlertResult("key", AppErrorReason.UNEXPECTED_ERROR),
),
Step(
id = 3,
navigationActionId = 5,
destinationId = 6,
status = StepStatus.NOT_STARTED,
result = ExitFormResult(true, ExitFormOption.DataConcerns),
),
)

cache.steps = expected
val actual = cache.steps

assertThat(actual).hasSize(2)
compareStubs(expected[0], actual[0])
compareStubs(expected[1], actual[1])
assertThat(actual).hasSize(expected.size)
for (i in expected.indices) {
compareStubs(expected[i], actual[i])
}
}

private fun compareStubs(
Expand Down
Loading