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
1 change: 1 addition & 0 deletions face/infra/bio-sdk-resolver/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/build
!/src/release/java
3 changes: 2 additions & 1 deletion face/infra/bio-sdk-resolver/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ dependencies {
implementation(project(":face:infra:base-bio-sdk"))
implementation(project(":face:infra:roc-v1"))
api(project(":face:infra:roc-v3"))
implementation(project(":face:infra:simface"))

debugImplementation(project(":face:infra:simface"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.simprints.face.infra.biosdkresolver

import javax.inject.Inject

/**
* At the moment this is just a wrapper to make it simpler to stub it in different source sets.
* In future we could actually need custom resolution logic.
*/
internal class ResolveSimFaceVersionUseCase @Inject constructor(
private val simFaceBioSdk: SimFaceBioSdk,
) {
operator fun invoke(): FaceBioSDK = simFaceBioSdk
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,16 @@
package com.simprints.face.infra.biosdkresolver

import com.simprints.infra.config.store.ConfigRepository
import com.simprints.infra.config.store.models.FaceConfiguration
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class ResolveFaceBioSdkUseCase @Inject constructor(
private val configRepository: ConfigRepository,
private val rocV1BioSdk: RocV1BioSdk,
private val rocV3BioSdk: RocV3BioSdk,
private val simFaceBioSdk: SimFaceBioSdk,
class ResolveFaceBioSdkUseCase @Inject internal constructor(
private val resolveRankOneVersionUseCase: ResolveRankOneVersionUseCase,
private val resolveSimFaceVersionUseCase: ResolveSimFaceVersionUseCase,
) {
suspend operator fun invoke(bioSdk: FaceConfiguration.BioSdk): FaceBioSDK = when (bioSdk) {
FaceConfiguration.BioSdk.SIM_FACE -> simFaceBioSdk
FaceConfiguration.BioSdk.RANK_ONE -> {
val version = configRepository
.getProjectConfiguration()
.face
?.rankOne
?.version
?.takeIf { it.isNotBlank() } // Ensures version is not null or empty
requireNotNull(version) { "FaceBioSDK version is null or empty" }
if (version == rocV3BioSdk.version) rocV3BioSdk else rocV1BioSdk
}
FaceConfiguration.BioSdk.SIM_FACE -> resolveSimFaceVersionUseCase()
FaceConfiguration.BioSdk.RANK_ONE -> resolveRankOneVersionUseCase()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a matter of preference but do we really need to extract something as simple as the version resolving? It seems the overhead is higher than the code itself.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not necessary, but it has the benefit of isolating each SDK's logic.

Honestly, I was just trying a lot of things to minimise the amount of classes that we would need to duplicate per build type and this is a by-product of the experimentation. We can simplify it when the need for build types is gone.

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.simprints.face.infra.biosdkresolver

import com.simprints.infra.config.store.ConfigRepository
import javax.inject.Inject

internal class ResolveRankOneVersionUseCase @Inject constructor(
private val configRepository: ConfigRepository,
private val rocV1BioSdk: RocV1BioSdk,
private val rocV3BioSdk: RocV3BioSdk,
) {
suspend operator fun invoke(): FaceBioSDK {
val version = configRepository
.getProjectConfiguration()
.face
?.rankOne
?.version
?.takeIf { it.isNotBlank() } // Ensures version is not null or empty
requireNotNull(version) { "FaceBioSDK version is null or empty" }
return if (version == rocV3BioSdk.version) rocV3BioSdk else rocV1BioSdk
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.simprints.face.infra.biosdkresolver

import javax.inject.Inject

/**
* Class interfaces in the different build types must be identical for it to work,
* therefore we have to stub the whole class for now.
*/
@ExcludedFromGeneratedTestCoverageReports("Stubs for build types")
internal class ResolveSimFaceVersionUseCase @Inject constructor(
private val simFaceBioSdk: SimFaceBioSdk,
) {
operator fun invoke(): FaceBioSDK = TODO("SimFace is not available in release build")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.simprints.face.infra.biosdkresolver

import com.simprints.face.infra.basebiosdk.matching.FaceMatcher
import com.simprints.face.infra.basebiosdk.matching.FaceSample
import javax.inject.Inject

/**
* Class interfaces in the different build types must be identical for it to work,
* therefore we have to stub the whole class for now.
*/
@ExcludedFromGeneratedTestCoverageReports("Stubs for build types")
@Singleton
class SimFaceBioSdk @Inject constructor() : FaceBioSDK {
override val initializer: FaceBioSdkInitializer
get() = TODO()
override val detector: FaceDetector
get() = TODO()
override val version: String
get() = TODO()
override val templateFormat: String
get() = TODO()
override val matcherName: String
get() = TODO()

override fun createMatcher(probeSamples: List<FaceSample>): FaceMatcher = TODO()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.simprints.face.infra.biosdkresolver

import com.simprints.core.ExcludedFromGeneratedTestCoverageReports
import javax.inject.Inject

/**
* Class interfaces in the different build types must be identical for it to work,
* therefore we have to stub the whole class for now.
*/
@ExcludedFromGeneratedTestCoverageReports("Stubs for build types")
internal class ResolveSimFaceVersionUseCase @Inject constructor(
private val simFaceBioSdk: SimFaceBioSdk,
) {
operator fun invoke(): FaceBioSDK = TODO("SimFace is not available in staging build")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.simprints.face.infra.biosdkresolver

import com.simprints.core.ExcludedFromGeneratedTestCoverageReports
import com.simprints.face.infra.basebiosdk.detection.FaceDetector
import com.simprints.face.infra.basebiosdk.initialization.FaceBioSdkInitializer
import com.simprints.face.infra.basebiosdk.matching.FaceMatcher
import com.simprints.face.infra.basebiosdk.matching.FaceSample
import javax.inject.Inject
import javax.inject.Singleton

/**
* Class interfaces in the different build types must be identical for it to work,
* therefore we have to stub the whole class for now.
*/
@ExcludedFromGeneratedTestCoverageReports("Stubs for build types")
@Singleton
class SimFaceBioSdk @Inject constructor() : FaceBioSDK {
override val initializer: FaceBioSdkInitializer
get() = TODO()
override val detector: FaceDetector
get() = TODO()
override val version: String
get() = TODO()
override val templateFormat: String
get() = TODO()
override val matcherName: String
get() = TODO()

override fun createMatcher(probeSamples: List<FaceSample>): FaceMatcher = TODO()
}
Original file line number Diff line number Diff line change
@@ -1,108 +1,48 @@
package com.simprints.face.infra.biosdkresolver

import com.google.common.truth.Truth.*
import com.simprints.infra.config.store.ConfigRepository
import com.simprints.infra.config.store.models.FaceConfiguration
import io.mockk.*
import io.mockk.impl.annotations.MockK
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test

class ResolveFaceBioSdkUseCaseTest {
private lateinit var resolveFaceBioSdkUseCase: ResolveFaceBioSdkUseCase
private val configRepository: ConfigRepository = mockk()
private lateinit var rocV1BioSdk: RocV1BioSdk
private lateinit var rocV3BioSdk: RocV3BioSdk
private lateinit var simFaceBioSdk: SimFaceBioSdk

@Before
fun setUp() {
rocV1BioSdk = RocV1BioSdk(mockk(), mockk())
rocV3BioSdk = RocV3BioSdk(mockk(), mockk())
simFaceBioSdk = SimFaceBioSdk(mockk(), mockk(), mockk(relaxed = true))
@MockK
private lateinit var resolveRankOneVersionUseCase: ResolveRankOneVersionUseCase

resolveFaceBioSdkUseCase = ResolveFaceBioSdkUseCase(configRepository, rocV1BioSdk, rocV3BioSdk, simFaceBioSdk)
}

@Test
fun `return SimFace SDK when requested`() = runTest {
// When
val result = resolveFaceBioSdkUseCase.invoke(FaceConfiguration.BioSdk.SIM_FACE)

// Then
assertThat(result).isEqualTo(simFaceBioSdk)
}
@MockK
private lateinit var rocBioSdk: RocV1BioSdk

@Test(expected = IllegalArgumentException::class)
fun `throw exception when RankOne version is null`() = runTest {
// Given
coEvery {
configRepository
.getProjectConfiguration()
.face
?.rankOne
?.version
} returns null
@MockK
private lateinit var resolveSimFaceVersionUseCase: ResolveSimFaceVersionUseCase

// When
resolveFaceBioSdkUseCase.invoke(FaceConfiguration.BioSdk.RANK_ONE)
@MockK
private lateinit var simFaceBioSdk: SimFaceBioSdk

// Then: Expect IllegalArgumentException to be thrown
}
private lateinit var resolveFaceBioSdkUseCase: ResolveFaceBioSdkUseCase

@Test(expected = IllegalArgumentException::class)
fun `throw exception when RankOne version is empty`() = runTest {
// Given
coEvery {
configRepository
.getProjectConfiguration()
.face
?.rankOne
?.version
} returns ""
@Before
fun setUp() {
MockKAnnotations.init(this, relaxed = true)

// When
resolveFaceBioSdkUseCase.invoke(FaceConfiguration.BioSdk.RANK_ONE)
coEvery { resolveRankOneVersionUseCase() } returns rocBioSdk
coEvery { resolveSimFaceVersionUseCase() } returns simFaceBioSdk

// Then: Expect IllegalArgumentException to be thrown
resolveFaceBioSdkUseCase = ResolveFaceBioSdkUseCase(
resolveRankOneVersionUseCase,
resolveSimFaceVersionUseCase,
)
}

// Given that version is valid and matches ROC V3
@Test
fun `return ROC V3 SDK when version is valid and matches ROC V3`() = runTest {
// Given

coEvery {
configRepository
.getProjectConfiguration()
.face
?.rankOne
?.version
} returns rocV3BioSdk.version

// When
val result = resolveFaceBioSdkUseCase.invoke(FaceConfiguration.BioSdk.RANK_ONE)

// Then
assertThat(result).isEqualTo(rocV3BioSdk)
fun `return SimFace SDK when requested`() = runTest {
assertThat(resolveFaceBioSdkUseCase.invoke(FaceConfiguration.BioSdk.SIM_FACE)).isEqualTo(simFaceBioSdk)
}

// Given that version is valid and does not match ROC V3 (should match ROC V1)
@Test
fun `return ROC V1 SDK when version is valid and does not match ROC V3`() = runTest {
// Given
coEvery {
configRepository
.getProjectConfiguration()
.face
?.rankOne
?.version
} returns rocV1BioSdk.version

// When
val result = resolveFaceBioSdkUseCase.invoke(FaceConfiguration.BioSdk.RANK_ONE)

// Then
assertThat(result).isEqualTo(rocV1BioSdk)
fun `return RankOne SDK when requested`() = runTest {
assertThat(resolveFaceBioSdkUseCase.invoke(FaceConfiguration.BioSdk.RANK_ONE)).isEqualTo(rocBioSdk)
}
}
Loading