feat: [NETWORK] mocks can throw errors (#133)

* feat: [NETWORK] mocks can throw errors

* added into android

* added on ktor

---------

Co-authored-by: Florent Champigny <florent@bere.al>
This commit is contained in:
Florent CHAMPIGNY 2025-08-21 16:44:07 +02:00 committed by GitHub
parent a50169189e
commit 3cb5abd33f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 640 additions and 339 deletions

View file

@ -11,7 +11,6 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.serialization.json.Json
import java.util.UUID
import kotlin.time.Instant
class BadQualityConfigLocalDataSourceImpl(

View file

@ -16,7 +16,7 @@ import kotlinx.coroutines.withContext
class NetworkLocalDataSourceRoom(
private val dispatcherProvider: DispatcherProvider,
private val floconNetworkDao: FloconNetworkDao
private val floconNetworkDao: FloconNetworkDao,
) : NetworkLocalDataSource {
override fun observeRequests(

View file

@ -8,17 +8,23 @@ import io.github.openflocon.domain.device.models.DeviceIdAndPackageNameDomainMod
import io.github.openflocon.domain.network.models.MockNetworkDomainModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.serialization.json.Json
class NetworkMocksLocalDataSourceImpl(
private val dao: NetworkMocksDao,
private val json: Json,
) : NetworkMocksLocalDataSource {
override suspend fun addMock(
deviceIdAndPackageName: DeviceIdAndPackageNameDomainModel,
mock: MockNetworkDomainModel,
) {
val mockEntity = toEntity(mock, deviceIdAndPackageName)
dao.addMock(mockEntity)
mock.toEntity(
json = json,
deviceInfo = deviceIdAndPackageName
)?.let {
dao.addMock(it)
}
}
override suspend fun getMock(
@ -29,9 +35,9 @@ class NetworkMocksLocalDataSourceImpl(
deviceIdAndPackageName.deviceId,
deviceIdAndPackageName.packageName,
id
)?.let {
toDomain(it)
}
)?.toDomain(
json = json,
)
}
override suspend fun getAllEnabledMocks(
@ -40,8 +46,10 @@ class NetworkMocksLocalDataSourceImpl(
return dao.getAllEnabledMocks(
deviceIdAndPackageName.deviceId,
deviceIdAndPackageName.packageName
).map {
toDomain(it)
).mapNotNull {
it.toDomain(
json = json,
)
}
}
@ -52,8 +60,10 @@ class NetworkMocksLocalDataSourceImpl(
deviceIdAndPackageName.deviceId,
deviceIdAndPackageName.packageName
).map { entities ->
entities.map {
toDomain(it)
entities.mapNotNull {
it.toDomain(
json = json,
)
}
}
}

View file

@ -5,45 +5,80 @@ import io.github.openflocon.data.local.network.models.mock.MockNetworkResponseEm
import io.github.openflocon.data.local.network.models.mock.MockNetworkEntity
import io.github.openflocon.domain.device.models.DeviceIdAndPackageNameDomainModel
import io.github.openflocon.domain.network.models.MockNetworkDomainModel
import kotlinx.serialization.json.Json
fun toEntity(
domainModel: MockNetworkDomainModel,
fun MockNetworkDomainModel.toEntity(
json: Json,
deviceInfo: DeviceIdAndPackageNameDomainModel
): MockNetworkEntity {
): MockNetworkEntity? {
val response = try {
json.encodeToString(response.toEntity())
} catch (t: Throwable) {
t.printStackTrace()
return null
}
return MockNetworkEntity(
deviceId = deviceInfo.deviceId,
packageName = deviceInfo.packageName,
mockId = domainModel.id,
isEnabled = domainModel.isEnabled,
mockId = id,
isEnabled = isEnabled,
expectation = MockNetworkExpectationEmbedded(
urlPattern = domainModel.expectation.urlPattern,
method = domainModel.expectation.method,
urlPattern = expectation.urlPattern,
method = expectation.method,
),
response = MockNetworkResponseEmbedded(
httpCode = domainModel.response.httpCode,
body = domainModel.response.body,
mediaType = domainModel.response.mediaType,
delay = domainModel.response.delay,
headers = domainModel.response.headers,
)
response = response,
)
}
fun toDomain(entity: MockNetworkEntity): MockNetworkDomainModel {
return MockNetworkDomainModel(
id = entity.mockId,
isEnabled = entity.isEnabled,
expectation = MockNetworkDomainModel.Expectation(
urlPattern = entity.expectation.urlPattern,
method = entity.expectation.method,
),
response = MockNetworkDomainModel.Response(
httpCode = entity.response.httpCode,
body = entity.response.body,
mediaType = entity.response.mediaType,
delay = entity.response.delay,
headers = entity.response.headers,
)
private fun MockNetworkDomainModel.Response.toEntity() : MockNetworkResponseEmbedded {
return MockNetworkResponseEmbedded(
delay = delay,
type = when(this) {
is MockNetworkDomainModel.Response.Body -> MockNetworkResponseEmbedded.Type.Body(
httpCode = httpCode,
body = body,
mediaType = mediaType,
headers = headers,
)
is MockNetworkDomainModel.Response.Exception -> MockNetworkResponseEmbedded.Type.Exception(
classPath = classPath,
)
}
)
}
fun MockNetworkEntity.toDomain(
json: Json
): MockNetworkDomainModel? {
val response = try {
json.decodeFromString<MockNetworkResponseEmbedded>(response).toDomain()
} catch (t: Throwable) {
t.printStackTrace()
return null
}
return MockNetworkDomainModel(
id = mockId,
isEnabled = isEnabled,
expectation = MockNetworkDomainModel.Expectation(
urlPattern = expectation.urlPattern,
method = expectation.method,
),
response = response,
)
}
private fun MockNetworkResponseEmbedded.toDomain() : MockNetworkDomainModel.Response {
return when(this.type) {
is MockNetworkResponseEmbedded.Type.Body -> MockNetworkDomainModel.Response.Body(
httpCode = this.type.httpCode,
body = this.type.body,
mediaType = this.type.mediaType,
headers = this.type.headers,
delay = this.delay,
)
is MockNetworkResponseEmbedded.Type.Exception -> MockNetworkDomainModel.Response.Exception(
delay = this.delay,
classPath = this.type.classPath,
)
}
}

View file

@ -18,19 +18,10 @@ data class MockNetworkEntity(
val isEnabled: Boolean,
@Embedded(prefix = "expectation_")
val expectation: MockNetworkExpectationEmbedded,
@Embedded(prefix = "response_")
val response: MockNetworkResponseEmbedded,
val response: String, // saved as json
)
data class MockNetworkExpectationEmbedded(
val urlPattern: String,
val method: String,
)
data class MockNetworkResponseEmbedded(
val httpCode: Int,
val body: String,
val mediaType: String,
val delay: Long,
val headers: Map<String, String>,
)

View file

@ -0,0 +1,24 @@
package io.github.openflocon.data.local.network.models.mock
import kotlinx.serialization.Serializable
@Serializable
data class MockNetworkResponseEmbedded(
val delay: Long,
val type: Type,
) {
@Serializable
sealed interface Type {
@Serializable
data class Body(
val httpCode: Int,
val body: String,
val mediaType: String,
val headers: Map<String, String>,
) : Type
@Serializable
data class Exception(
val classPath: String,
) : Type
}
}