Skip to content

Commit

Permalink
m7l1 - InMemory repo: Ktor
Browse files Browse the repository at this point in the history
  • Loading branch information
svok authored and phaeton03 committed Sep 19, 2024
1 parent 239140f commit 74d1eb5
Show file tree
Hide file tree
Showing 15 changed files with 334 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.MapperFeature
import com.fasterxml.jackson.databind.json.JsonMapper
import ru.otus.otuskotlin.marketplace.api.v1.models.IRequest
import ru.otus.otuskotlin.marketplace.api.v1.models.IResponse

val apiV1Mapper = JsonMapper.builder().run {
// configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
enable(MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,14 @@ private fun MkplAdPermissionClient.toTransportAd() = when (this) {
MkplAdPermissionClient.DELETE -> AdPermissions.DELETE
}

private fun MkplVisibility.toTransportAd(): AdVisibility? = when (this) {
fun MkplVisibility.toTransportAd(): AdVisibility? = when (this) {
MkplVisibility.VISIBLE_PUBLIC -> AdVisibility.PUBLIC
MkplVisibility.VISIBLE_TO_GROUP -> AdVisibility.REGISTERED_ONLY
MkplVisibility.VISIBLE_TO_OWNER -> AdVisibility.OWNER_ONLY
MkplVisibility.NONE -> null
}

private fun MkplDealSide.toTransportAd(): DealSide? = when (this) {
fun MkplDealSide.toTransportAd(): DealSide? = when (this) {
MkplDealSide.DEMAND -> DealSide.DEMAND
MkplDealSide.SUPPLY -> DealSide.SUPPLY
MkplDealSide.NONE -> null
Expand Down
5 changes: 5 additions & 0 deletions ok-marketplace-be/ok-marketplace-app-ktor/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ kotlin {
implementation(libs.kotlinx.serialization.json)
implementation(libs.ktor.serialization.json)

// DB
implementation(projects.okMarketplaceRepoCommon)
implementation(projects.okMarketplaceRepoStubs)
implementation(projects.okMarketplaceRepoInmemory)

// logging
implementation(project(":ok-marketplace-api-log1"))
implementation("ru.otus.otuskotlin.marketplace.libs:ok-marketplace-lib-logging-common")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ data class MkplAppSettings(
val appUrls: List<String> = emptyList(),
override val corSettings: MkplCorSettings = MkplCorSettings(),
override val processor: MkplAdProcessor = MkplAdProcessor(corSettings),
): IMkplAppSettings
) : IMkplAppSettings
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@ package ru.otus.otuskotlin.marketplace.app.ktor.plugins
import io.ktor.server.application.*
import ru.otus.otuskotlin.marketplace.app.ktor.MkplAppSettings
import ru.otus.otuskotlin.marketplace.app.ktor.base.KtorWsSessionRepo
import ru.otus.otuskotlin.marketplace.backend.repository.inmemory.AdRepoStub
import ru.otus.otuskotlin.marketplace.biz.MkplAdProcessor
import ru.otus.otuskotlin.marketplace.common.MkplCorSettings
import ru.otus.otuskotlin.marketplace.repo.inmemory.AdRepoInMemory

fun Application.initAppSettings(): MkplAppSettings {
val corSettings = MkplCorSettings(
loggerProvider = getLoggerProviderConf(),
wsSessions = KtorWsSessionRepo(),
repoTest = AdRepoInMemory(),
repoProd = AdRepoInMemory(),
repoStub = AdRepoStub(),
)
return MkplAppSettings(
appUrls = environment.config.propertyOrNull("ktor.urls")?.getList() ?: emptyList(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
package ru.otus.otuskotlin.marketplace.app.ktor.repo

import io.ktor.client.call.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.testing.*
import ru.otus.otuskotlin.marketplace.api.v2.apiV2Mapper
import ru.otus.otuskotlin.marketplace.api.v2.mappers.toTransportAd
import ru.otus.otuskotlin.marketplace.api.v2.models.*
import ru.otus.otuskotlin.marketplace.app.ktor.MkplAppSettings
import ru.otus.otuskotlin.marketplace.app.ktor.module
import ru.otus.otuskotlin.marketplace.common.models.MkplAdId
import ru.otus.otuskotlin.marketplace.common.models.MkplAdLock
import ru.otus.otuskotlin.marketplace.common.models.MkplDealSide
import ru.otus.otuskotlin.marketplace.stubs.MkplAdStub
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals

abstract class V2AdRepoBaseTest {
abstract val workMode: AdRequestDebugMode
abstract val appSettingsCreate: MkplAppSettings
abstract val appSettingsRead: MkplAppSettings
abstract val appSettingsUpdate: MkplAppSettings
abstract val appSettingsDelete: MkplAppSettings
abstract val appSettingsSearch: MkplAppSettings
abstract val appSettingsOffers: MkplAppSettings

protected val uuidOld = "10000000-0000-0000-0000-000000000001"
protected val uuidNew = "10000000-0000-0000-0000-000000000002"
protected val uuidSup = "10000000-0000-0000-0000-000000000003"
protected val initAd = MkplAdStub.prepareResult {
id = MkplAdId(uuidOld)
adType = MkplDealSide.DEMAND
lock = MkplAdLock(uuidOld)
}
protected val initAdSupply = MkplAdStub.prepareResult {
id = MkplAdId(uuidSup)
adType = MkplDealSide.SUPPLY
}


@Test
fun create() {
val createAd = AdCreateObject(
title = initAd.title,
description = initAd.description,
adType = initAd.adType.toTransportAd(),
visibility = initAd.visibility.toTransportAd(),
)
v2TestApplication(
conf = appSettingsCreate,
func = "create",
request = AdCreateRequest(
ad = createAd,
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<IResponse>() as AdCreateResponse
assertEquals(200, response.status.value)
assertEquals(uuidNew, responseObj.ad?.id)
assertEquals(createAd.title, responseObj.ad?.title)
assertEquals(createAd.description, responseObj.ad?.description)
assertEquals(createAd.adType, responseObj.ad?.adType)
assertEquals(createAd.visibility, responseObj.ad?.visibility)
}
}

@Test
fun read() = v2TestApplication(
conf = appSettingsRead,
func = "read",
request = AdReadRequest(
ad = AdReadObject(uuidOld),
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<IResponse>() as AdReadResponse
assertEquals(200, response.status.value)
assertEquals(uuidOld, responseObj.ad?.id)
}

@Test
fun update() {
val adUpdate = AdUpdateObject(
id = uuidOld,
title = initAd.title,
description = initAd.description,
adType = initAd.adType.toTransportAd(),
visibility = initAd.visibility.toTransportAd(),
lock = initAd.lock.asString(),
)
v2TestApplication(
conf = appSettingsUpdate,
func = "update",
request = AdUpdateRequest(
ad = adUpdate,
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<IResponse>() as AdUpdateResponse
assertEquals(200, response.status.value)
assertEquals(adUpdate.id, responseObj.ad?.id)
assertEquals(adUpdate.title, responseObj.ad?.title)
assertEquals(adUpdate.description, responseObj.ad?.description)
assertEquals(adUpdate.adType, responseObj.ad?.adType)
assertEquals(adUpdate.visibility, responseObj.ad?.visibility)
}
}
@Test
fun delete() = v2TestApplication(
conf = appSettingsDelete,
func = "delete",
request = AdDeleteRequest(
ad = AdDeleteObject(
id = uuidOld,
lock = initAd.lock.asString(),
),
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<IResponse>() as AdDeleteResponse
assertEquals(200, response.status.value)
assertEquals(uuidOld, responseObj.ad?.id)
}

@Test
fun search() = v2TestApplication(
conf = appSettingsSearch,
func = "search",
request = AdSearchRequest(
adFilter = AdSearchFilter(),
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<IResponse>() as AdSearchResponse
assertEquals(200, response.status.value)
assertNotEquals(0, responseObj.ads?.size)
assertEquals(uuidOld, responseObj.ads?.first()?.id)
}

@Test
fun offers() = v2TestApplication(
conf = appSettingsOffers,
func = "offers",
request = AdOffersRequest(
ad = AdReadObject(
id = uuidOld,
),
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<IResponse>() as AdOffersResponse
assertEquals(200, response.status.value)
assertNotEquals(0, responseObj.ads?.size)
assertEquals(uuidSup, responseObj.ads?.first()?.id)
}

private inline fun <reified T: IRequest> v2TestApplication(
conf: MkplAppSettings,
func: String,
request: T,
crossinline function: suspend (HttpResponse) -> Unit,
): Unit = testApplication {
application { module(appSettings = conf) }
val client = createClient {
install(ContentNegotiation) {
json(apiV2Mapper)
}
}
val response = client.post("/v2/ad/$func") {
contentType(ContentType.Application.Json)
header("X-Trace-Id", "12345")
setBody(request)
}
function(response)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package ru.otus.otuskotlin.marketplace.app.ktor.repo

import ru.otus.otuskotlin.marketplace.api.v2.models.AdRequestDebugMode
import ru.otus.otuskotlin.marketplace.app.ktor.MkplAppSettings
import ru.otus.otuskotlin.marketplace.common.MkplCorSettings
import ru.otus.otuskotlin.marketplace.common.repo.IRepoAd
import ru.otus.otuskotlin.marketplace.repo.common.AdRepoInitialized
import ru.otus.otuskotlin.marketplace.repo.inmemory.AdRepoInMemory

class V2AdRepoInmemoryTest : V2AdRepoBaseTest() {
override val workMode: AdRequestDebugMode = AdRequestDebugMode.TEST
private fun mkAppSettings(repo: IRepoAd) = MkplAppSettings(
corSettings = MkplCorSettings(
repoTest = repo
)
)

override val appSettingsCreate: MkplAppSettings = mkAppSettings(
repo = AdRepoInitialized(AdRepoInMemory(randomUuid = { uuidNew }))
)
override val appSettingsRead: MkplAppSettings = mkAppSettings(
repo = AdRepoInitialized(
AdRepoInMemory(randomUuid = { uuidNew }),
initObjects = listOf(initAd),
)
)
override val appSettingsUpdate: MkplAppSettings = mkAppSettings(
repo = AdRepoInitialized(
AdRepoInMemory(randomUuid = { uuidNew }),
initObjects = listOf(initAd),
)
)
override val appSettingsDelete: MkplAppSettings = mkAppSettings(
repo = AdRepoInitialized(
AdRepoInMemory(randomUuid = { uuidNew }),
initObjects = listOf(initAd),
)
)
override val appSettingsSearch: MkplAppSettings = mkAppSettings(
repo = AdRepoInitialized(
AdRepoInMemory(randomUuid = { uuidNew }),
initObjects = listOf(initAd),
)
)
override val appSettingsOffers: MkplAppSettings = mkAppSettings(
repo = AdRepoInitialized(
AdRepoInMemory(randomUuid = { uuidNew }),
initObjects = listOf(initAd, initAdSupply),
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package ru.otus.otuskotlin.marketplace.biz.validation
import ru.otus.otuskotlin.marketplace.biz.MkplAdProcessor
import ru.otus.otuskotlin.marketplace.common.MkplCorSettings
import ru.otus.otuskotlin.marketplace.common.models.*
import ru.otus.otuskotlin.marketplace.repo.common.AtRepoInitialized
import ru.otus.otuskotlin.marketplace.repo.common.AdRepoInitialized
import ru.otus.otuskotlin.marketplace.repo.inmemory.AdRepoInMemory
import ru.otus.otuskotlin.marketplace.stubs.MkplAdStub

abstract class BaseBizValidationTest {
protected abstract val command: MkplCommand
private val repo = AtRepoInitialized(
private val repo = AdRepoInitialized(
repo = AdRepoInMemory(),
initObjects = listOf(
MkplAdStub.get(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import ru.otus.otuskotlin.marketplace.common.models.MkplAd
/**
* Делегат для всех репозиториев, позволяющий инициализировать базу данных предзагруженными данными
*/
class AtRepoInitialized(
class AdRepoInitialized(
private val repo: IRepoAdInitializable,
private val initObjects: Collection<MkplAd> = emptyList(),
initObjects: Collection<MkplAd> = emptyList(),
) : IRepoAdInitializable by repo {
@Suppress("unused")
val initializedObjects: List<MkplAd> = save(initObjects).toList()
}
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
import ru.otus.otuskotlin.marketplace.backend.repo.tests.*
import ru.otus.otuskotlin.marketplace.repo.common.AtRepoInitialized
import ru.otus.otuskotlin.marketplace.repo.common.AdRepoInitialized
import ru.otus.otuskotlin.marketplace.repo.inmemory.AdRepoInMemory

class AdRepoInMemoryCreateTest : RepoAdCreateTest() {
override val repo = AtRepoInitialized(
override val repo = AdRepoInitialized(
AdRepoInMemory(),
initObjects = initObjects,
)
}

class AdRepoInMemoryDeleteTest : RepoAdDeleteTest() {
override val repo = AtRepoInitialized(
override val repo = AdRepoInitialized(
AdRepoInMemory(),
initObjects = initObjects,
)
}

class AdRepoInMemoryReadTest : RepoAdReadTest() {
override val repo = AtRepoInitialized(
override val repo = AdRepoInitialized(
AdRepoInMemory(),
initObjects = initObjects,
)
}

class AdRepoInMemorySearchTest : RepoAdSearchTest() {
override val repo = AtRepoInitialized(
override val repo = AdRepoInitialized(
AdRepoInMemory(),
initObjects = initObjects,
)
}

class AdRepoInMemoryUpdateTest : RepoAdUpdateTest() {
override val repo = AtRepoInitialized(
override val repo = AdRepoInitialized(
AdRepoInMemory(),
initObjects = initObjects,
)
Expand Down
4 changes: 4 additions & 0 deletions ok-marketplace-be/ok-marketplace-repo-stubs/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Модуль `ok-marketplace-repo-stubs`


Модуль реализует интерфейс репозитария в виде стабов.
Loading

0 comments on commit 74d1eb5

Please sign in to comment.