Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ser/de): focus on creating an abstraction #651

Merged
merged 1 commit into from
Nov 27, 2024
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
Expand Up @@ -10,7 +10,7 @@ import io.kotest.core.extensions.Extension
import io.kotest.extensions.system.SystemEnvironmentProjectListener
import stove.ktor.example.app.objectMapperRef

class TestSystemConfig : AbstractProjectConfig() {
class Stove : AbstractProjectConfig() {
companion object {
init {
stoveKafkaBridgePortDefault = "50053"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import com.trendyol.stove.testing.e2e.wiremock.*
import io.kotest.core.config.AbstractProjectConfig
import org.slf4j.*

class TestSystemConfig : AbstractProjectConfig() {
class Stove : AbstractProjectConfig() {
private val logger: Logger = LoggerFactory.getLogger("WireMockMonitor")

@Suppress("LongMethod")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import io.kotest.core.config.AbstractProjectConfig
import org.slf4j.*
import stove.spring.standalone.example.infrastructure.ObjectMapperConfig

class TestSystemConfig : AbstractProjectConfig() {
class Stove : AbstractProjectConfig() {
private val logger: Logger = LoggerFactory.getLogger("WireMockMonitor")

@Suppress("LongMethod")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import com.trendyol.stove.testing.e2e.system.TestSystem.Companion.validate
import io.kotest.core.config.AbstractProjectConfig
import org.apache.kafka.clients.admin.NewTopic

class TestSystemConfig : AbstractProjectConfig() {
class Stove : AbstractProjectConfig() {
@Suppress("LongMethod")
override suspend fun beforeProject(): Unit = TestSystem()
.also {
Expand Down
7 changes: 7 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ kotlinx-slf4j = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-slf4j", ver
kotlinx-knit = { module = "org.jetbrains.kotlinx:kotlinx-knit", version.ref = "knit" }
kotlinx-io-reactor = { module = "io.projectreactor:reactor-core", version.ref = "io-reactor" }
kotlinx-io-reactor-extensions = { module = "io.projectreactor.kotlin:reactor-kotlin-extensions", version.ref = "io-reactor-extensions" }
kotlinx-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm", version = "1.7.3" }

# Arrow
arrow-core = { module = "io.arrow-kt:arrow-core", version.ref = "arrow" }
Expand Down Expand Up @@ -131,10 +132,13 @@ elastic = { module = "co.elastic.clients:elasticsearch-java", version.ref = "ela

# mongo
mongodb-kotlin-coroutine = { module = "org.mongodb:mongodb-driver-kotlin-coroutine", version.ref = "mongodb" }
mongojack = { module = "org.mongojack:mongojack", version = "5.0.0" }

# misc
lettuce-core = { module = "io.lettuce:lettuce-core", version = "6.5.0.RELEASE" }
logback-classic = { module = "ch.qos.logback:logback-classic", version = "1.5.12" }
logback-core = { module = "ch.qos.logback:logback-core", version = "1.5.12" }
log4j-slf4j2-impl = { module = "org.apache.logging.log4j:log4j-slf4j2-impl", version = "2.24.2" }
r2dbc-mssql = { module = "io.r2dbc:r2dbc-mssql", version.ref = "r2dbc-mssql" }
microsoft-sqlserver-jdbc = { module = "com.microsoft.sqlserver:mssql-jdbc", version = "12.8.1.jre11" }
exposed-core = { module = "org.jetbrains.exposed:exposed-core", version.ref = "exposed" }
Expand Down Expand Up @@ -186,6 +190,8 @@ google-protobuf-kotlin = { module = "com.google.protobuf:protobuf-kotlin", versi
protoc = { module = "com.google.protobuf:protoc", version.ref = "google-protobuf" }
hoplite = { module = "com.sksamuel.hoplite:hoplite-core", version.ref = "hoplite" }
hoplite-yaml = { module = "com.sksamuel.hoplite:hoplite-yaml", version.ref = "hoplite" }
google-gson = { module = "com.google.code.gson:gson", version = "2.11.0" }


caffeine = { module = "com.github.ben-manes.caffeine:caffeine", version = "3.1.8" }
pprint = { module = "io.exoquery:pprint-kotlin", version = "2.0.2" }
Expand Down Expand Up @@ -237,5 +243,6 @@ gradle-release = { id = "net.researchgate.release", version.ref = "gradle-releas
nexusPublish = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexusPublish" }
testLogger = { id = "com.adarshr.test-logger", version = "4.0.0" }
protobuf = { id = "com.google.protobuf", version = "0.9.4" }
kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }


Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package com.trendyol.stove.testing.e2e.couchbase

import com.couchbase.client.kotlin.*
import com.couchbase.client.kotlin.Collection
import com.couchbase.client.kotlin.codec.*
import com.couchbase.client.kotlin.codec.typeRef
import com.couchbase.client.kotlin.query.*
import com.fasterxml.jackson.databind.ObjectMapper
import com.trendyol.stove.functional.*
import com.trendyol.stove.testing.e2e.system.TestSystem
import com.trendyol.stove.testing.e2e.system.abstractions.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking
import org.slf4j.*

Expand All @@ -20,10 +19,7 @@ class CouchbaseSystem internal constructor(
internal lateinit var cluster: Cluster

@PublishedApi
internal lateinit var collection: Collection

@PublishedApi
internal val objectMapper: ObjectMapper = context.options.objectMapper
internal lateinit var collection: com.couchbase.client.kotlin.Collection

private lateinit var exposedConfiguration: CouchbaseExposedConfiguration
private val logger: Logger = LoggerFactory.getLogger(javaClass)
Expand Down Expand Up @@ -55,21 +51,19 @@ class CouchbaseSystem internal constructor(
override fun configuration(): List<String> = context.options.configureExposedConfiguration(exposedConfiguration)

@CouchbaseDsl
suspend inline fun <reified T : Any> shouldQuery(
suspend inline fun <reified T> shouldQuery(
query: String,
assertion: (List<T>) -> Unit
crossinline assertion: (List<T>) -> Unit
): CouchbaseSystem {
val result = cluster.query(
statement = query,
metrics = false,
consistency = QueryScanConsistency.requestPlus()
).execute().rows.map { it.contentAs<T>() }
val objects = result
.map { objectMapper.writeValueAsString(it) }
.map { objectMapper.readValue(it, T::class.java) }

assertion(objects)
return this
val typeRef = typeRef<T>()
return flow {
cluster.query(
statement = query,
metrics = false,
consistency = QueryScanConsistency.requestPlus(),
serializer = context.options.clusterSerDe
).execute { row -> emit(context.options.clusterSerDe.deserialize(row.content, typeRef)) }
}.toList().also(assertion).let { this }
}

@CouchbaseDsl
Expand Down Expand Up @@ -174,16 +168,13 @@ class CouchbaseSystem internal constructor(
}
}

private fun createCluster(exposedConfiguration: CouchbaseExposedConfiguration): Cluster {
val jackson = JacksonJsonSerializer(objectMapper)
return Cluster.connect(
exposedConfiguration.hostsWithPort,
exposedConfiguration.username,
exposedConfiguration.password
) {
jsonSerializer = jackson
transcoder = JsonTranscoder(jackson)
}
private fun createCluster(exposedConfiguration: CouchbaseExposedConfiguration): Cluster = Cluster.connect(
exposedConfiguration.hostsWithPort,
exposedConfiguration.username,
exposedConfiguration.password
) {
jsonSerializer = context.options.clusterSerDe
transcoder = context.options.clusterTranscoder
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package com.trendyol.stove.testing.e2e.couchbase

import arrow.core.getOrElse
import com.couchbase.client.kotlin.Cluster
import com.fasterxml.jackson.databind.ObjectMapper
import com.couchbase.client.kotlin.codec.*
import com.trendyol.stove.testing.e2e.containers.*
import com.trendyol.stove.testing.e2e.database.migrations.*
import com.trendyol.stove.testing.e2e.serialization.StoveObjectMapper
import com.trendyol.stove.testing.e2e.serialization.E2eObjectMapperConfig
import com.trendyol.stove.testing.e2e.system.*
import com.trendyol.stove.testing.e2e.system.abstractions.*
import com.trendyol.stove.testing.e2e.system.annotations.StoveDsl
Expand All @@ -22,7 +22,8 @@ data class CouchbaseExposedConfiguration(
data class CouchbaseSystemOptions(
val defaultBucket: String,
val containerOptions: CouchbaseContainerOptions = CouchbaseContainerOptions(),
val objectMapper: ObjectMapper = StoveObjectMapper.Default,
val clusterSerDe: JsonSerializer = JacksonJsonSerializer(E2eObjectMapperConfig.createObjectMapperWithDefaults()),
val clusterTranscoder: Transcoder = JsonTranscoder(clusterSerDe),
override val configureExposedConfiguration: (CouchbaseExposedConfiguration) -> List<String>
) : SystemOptions, ConfiguresExposedConfiguration<CouchbaseExposedConfiguration> {
internal val migrationCollection: MigrationCollection<Cluster> = MigrationCollection()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import co.elastic.clients.elasticsearch.ElasticsearchClient
import co.elastic.clients.elasticsearch._types.Refresh
import co.elastic.clients.elasticsearch._types.query_dsl.Query
import co.elastic.clients.elasticsearch.core.*
import co.elastic.clients.json.jackson.JacksonJsonpMapper
import co.elastic.clients.transport.rest_client.RestClientTransport
import com.trendyol.stove.functional.*
import com.trendyol.stove.testing.e2e.system.TestSystem
Expand Down Expand Up @@ -177,7 +176,7 @@ class ElasticsearchSystem internal constructor(
private fun createEsClient(exposedConfiguration: ElasticSearchExposedConfiguration): ElasticsearchClient =
context.options.clientConfigurer.restClientOverrideFn
.getOrElse { { cfg -> restClient(cfg) } }
.let { RestClientTransport(it(exposedConfiguration), JacksonJsonpMapper(context.options.objectMapper)) }
.let { RestClientTransport(it(exposedConfiguration), context.options.jsonpMapper) }
.let { ElasticsearchClient(it) }

private fun restClient(cfg: ElasticSearchExposedConfiguration): RestClient =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.trendyol.stove.testing.e2e.elasticsearch

import arrow.core.getOrElse
import arrow.integrations.jackson.module.registerArrowModule
import com.trendyol.stove.testing.e2e.containers.withProvidedRegistry
import com.trendyol.stove.testing.e2e.system.*
import com.trendyol.stove.testing.e2e.system.abstractions.SystemNotRegisteredException
Expand All @@ -13,26 +12,22 @@ import com.trendyol.stove.testing.e2e.system.annotations.StoveDsl
* Provides an [options] class to configure the Elasticsearch container.
* You can configure it by changing the implementation of migrator.
*/
internal fun TestSystem.withElasticsearch(options: ElasticsearchSystemOptions): TestSystem {
options.objectMapper.registerArrowModule()

return withProvidedRegistry(
imageName = options.container.imageWithTag,
registry = options.container.registry,
compatibleSubstitute = options.container.compatibleSubstitute
) { StoveElasticSearchContainer(it) }
.apply {
addExposedPorts(*options.container.exposedPorts.toIntArray())
withPassword(options.container.password)
if (options.container.disableSecurity) {
withEnv("xpack.security.enabled", "false")
}
withReuse([email protected])
options.container.containerFn(this)
internal fun TestSystem.withElasticsearch(options: ElasticsearchSystemOptions): TestSystem = withProvidedRegistry(
imageName = options.container.imageWithTag,
registry = options.container.registry,
compatibleSubstitute = options.container.compatibleSubstitute
) { StoveElasticSearchContainer(it) }
.apply {
addExposedPorts(*options.container.exposedPorts.toIntArray())
withPassword(options.container.password)
if (options.container.disableSecurity) {
withEnv("xpack.security.enabled", "false")
}
.let { getOrRegister(ElasticsearchSystem(this, ElasticsearchContext(it, options))) }
.let { this }
}
withReuse([email protected])
options.container.containerFn(this)
}
.let { getOrRegister(ElasticsearchSystem(this, ElasticsearchContext(it, options))) }
.let { this }

internal fun TestSystem.elasticsearch(): ElasticsearchSystem =
getOrNone<ElasticsearchSystem>().getOrElse {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package com.trendyol.stove.testing.e2e.elasticsearch

import arrow.core.*
import co.elastic.clients.elasticsearch.ElasticsearchClient
import com.fasterxml.jackson.databind.ObjectMapper
import co.elastic.clients.json.JsonpMapper
import co.elastic.clients.json.jackson.JacksonJsonpMapper
import com.trendyol.stove.testing.e2e.containers.*
import com.trendyol.stove.testing.e2e.database.migrations.*
import com.trendyol.stove.testing.e2e.serialization.StoveObjectMapper
import com.trendyol.stove.testing.e2e.serialization.*
import com.trendyol.stove.testing.e2e.system.abstractions.*
import com.trendyol.stove.testing.e2e.system.annotations.StoveDsl
import org.apache.http.client.config.RequestConfig
Expand All @@ -19,7 +20,7 @@ import kotlin.time.Duration.Companion.minutes
data class ElasticsearchSystemOptions(
val clientConfigurer: ElasticClientConfigurer = ElasticClientConfigurer(),
val container: ElasticContainerOptions = ElasticContainerOptions(),
val objectMapper: ObjectMapper = StoveObjectMapper.Default,
val jsonpMapper: JsonpMapper = JacksonJsonpMapper(StoveSerde.jackson.default),
override val configureExposedConfiguration: (ElasticSearchExposedConfiguration) -> List<String>
) : SystemOptions, ConfiguresExposedConfiguration<ElasticSearchExposedConfiguration> {
internal val migrationCollection: MigrationCollection<ElasticsearchClient> = MigrationCollection()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package com.trendyol.stove.testing.e2e.elasticsearch

import arrow.integrations.jackson.module.registerArrowModule
import com.fasterxml.jackson.module.kotlin.readValue
import com.trendyol.stove.functional.get
import com.trendyol.stove.testing.e2e.serialization.StoveObjectMapper
import com.trendyol.stove.testing.e2e.serialization.*
import com.trendyol.stove.testing.e2e.system.abstractions.StateWithProcess
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.*
Expand All @@ -25,7 +24,7 @@ class ElasticsearchExposedCertificateTest : FunSpec({
"processId": 10496
}
""".trimIndent()
val j = StoveObjectMapper.byConfiguring { this.registerArrowModule() }
val j = StoveSerde.jackson.default
val stateWithProcess = j.readValue<StateWithProcess<ElasticSearchExposedConfiguration>>(state)
val serialize = j.writeValueAsString(stateWithProcess)
val stateWithProcess2 = j.readValue<StateWithProcess<ElasticSearchExposedConfiguration>>(serialize)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
package com.trendyol.stove.testing.e2e.http

import arrow.core.*
import com.fasterxml.jackson.databind.ObjectMapper
import com.trendyol.stove.testing.e2e.serialization.StoveObjectMapper
import com.trendyol.stove.testing.e2e.serialization.*
import com.trendyol.stove.testing.e2e.system.*
import com.trendyol.stove.testing.e2e.system.abstractions.*
import com.trendyol.stove.testing.e2e.system.annotations.StoveDsl
Expand All @@ -17,6 +16,7 @@ import io.ktor.client.plugins.logging.*
import io.ktor.client.request.*
import io.ktor.client.request.forms.*
import io.ktor.http.*
import io.ktor.serialization.*
import io.ktor.serialization.jackson.*
import io.ktor.util.*
import org.slf4j.LoggerFactory
Expand All @@ -29,14 +29,14 @@ private val httpSystemLogger = LoggerFactory.getLogger(HttpSystem::class.java)
@HttpDsl
data class HttpClientSystemOptions(
val baseUrl: String,
val objectMapper: ObjectMapper = StoveObjectMapper.Default,
val contentConverter: ContentConverter = JacksonConverter(StoveSerde.jackson.default),
val timeout: Duration = 30.seconds,
val createClient: () -> io.ktor.client.HttpClient = { jsonHttpClient(timeout, objectMapper) }
val createClient: () -> io.ktor.client.HttpClient = { jsonHttpClient(timeout, contentConverter) }
) : SystemOptions {
companion object {
internal fun jsonHttpClient(
timeout: Duration,
objectMapper: ObjectMapper
converter: ContentConverter
): io.ktor.client.HttpClient = HttpClient(OkHttp) {
engine {
config {
Expand All @@ -57,9 +57,9 @@ data class HttpClientSystemOptions(
}

install(ContentNegotiation) {
register(ContentType.Application.Json, JacksonConverter(objectMapper))
register(ContentType.Application.ProblemJson, JacksonConverter(objectMapper))
register(ContentType.parse("application/x-ndjson"), JacksonConverter(objectMapper))
register(ContentType.Application.Json, converter)
register(ContentType.Application.ProblemJson, converter)
register(ContentType.parse("application/x-ndjson"), converter)
}

defaultRequest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import com.github.tomakehurst.wiremock.client.WireMock.*
import com.github.tomakehurst.wiremock.matching.MultipartValuePattern
import com.trendyol.stove.ConsoleSpec
import com.trendyol.stove.testing.e2e.http.HttpSystem.Companion.client
import com.trendyol.stove.testing.e2e.serialization.StoveObjectMapper
import com.trendyol.stove.testing.e2e.system.TestSystem
import com.trendyol.stove.testing.e2e.system.abstractions.ApplicationUnderTest
import com.trendyol.stove.testing.e2e.wiremock.*
Expand Down Expand Up @@ -36,10 +35,7 @@ class TestConfig : AbstractProjectConfig() {
.with {
httpClient {
HttpClientSystemOptions(
baseUrl = "http://localhost:8086",
objectMapper = StoveObjectMapper.byConfiguring {
findAndRegisterModules()
}
baseUrl = "http://localhost:8086"
)
}

Expand Down Expand Up @@ -343,7 +339,7 @@ class HttpSystemTests : FunSpec({
aResponse()
.withHeader("Content-Type", "application/json")
.withStatus(200)
.withBody(it.writeValueAsString(TestDto(expectedGetDtoName)))
.withBody(it.serialize(TestDto(expectedGetDtoName)))
}
}
}
Expand All @@ -369,7 +365,7 @@ class HttpSystemTests : FunSpec({
aResponse()
.withHeader("Content-Type", "application/json")
.withStatus(200)
.withBody(it.writeValueAsString(TestDto(UUID.randomUUID().toString())))
.withBody(it.serialize(TestDto(UUID.randomUUID().toString())))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import arrow.core.*
import com.fasterxml.jackson.databind.ObjectMapper
import com.trendyol.stove.functional.*
import com.trendyol.stove.testing.e2e.messaging.*
import com.trendyol.stove.testing.e2e.serialization.StoveObjectMapper
import com.trendyol.stove.testing.e2e.serialization.*
import com.trendyol.stove.testing.e2e.standalone.kafka.intercepting.*
import com.trendyol.stove.testing.e2e.system.TestSystem
import com.trendyol.stove.testing.e2e.system.abstractions.*
Expand All @@ -24,7 +24,7 @@ import kotlin.time.*
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds

var stoveKafkaObjectMapperRef: ObjectMapper = StoveObjectMapper.Default
var stoveKafkaObjectMapperRef: ObjectMapper = StoveSerde.jackson.default
var stoveKafkaBridgePortDefault = "50051"
const val STOVE_KAFKA_BRIDGE_PORT = "STOVE_KAFKA_BRIDGE_PORT"
internal val StoveKafkaCoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
Expand Down
Loading