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
Expand Up @@ -17,7 +17,6 @@ import org.prebid.cache.functional.util.getRandomLong
import org.prebid.cache.functional.util.getRandomString
import org.prebid.cache.functional.util.getRandomUuid
import org.springframework.http.HttpStatus.BAD_REQUEST
import org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR
import org.springframework.http.HttpStatus.UNSUPPORTED_MEDIA_TYPE

class GeneralCacheSpec : ShouldSpec({
Expand Down
279 changes: 279 additions & 0 deletions src/test/kotlin/org/prebid/cache/functional/ModuleStorageSpec.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
package org.prebid.cache.functional

import io.kotest.assertions.assertSoftly
import io.kotest.assertions.throwables.shouldThrowExactly
import io.kotest.core.spec.style.ShouldSpec
import io.kotest.matchers.nulls.beNull
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.beEmpty
import io.kotest.matchers.string.shouldContain
import java.util.Locale
import org.prebid.cache.functional.BaseSpec.Companion.prebidCacheConfig
import org.prebid.cache.functional.model.request.PayloadTransfer
import org.prebid.cache.functional.service.ApiException
import org.prebid.cache.functional.service.PrebidCacheApi
import org.prebid.cache.functional.util.getRandomString
import org.springframework.http.HttpStatus.BAD_REQUEST
import org.springframework.http.HttpStatus.NOT_FOUND
import org.springframework.http.HttpStatus.UNAUTHORIZED

class ModuleStorageSpec : ShouldSpec({

lateinit var apiKey: String
lateinit var applicationName: String
lateinit var cacheApi: PrebidCacheApi

beforeSpec {
apiKey = getRandomString()
applicationName = getRandomString().lowercase(Locale.getDefault())
val config = prebidCacheConfig.getBaseModuleStorageConfig(applicationName, apiKey)
cacheApi = BaseSpec.getPrebidCacheApi(config)
}

should("return the same text transfer value which was saved to module-storage") {
//given: default text payload with application
val payloadKey = getRandomString()
val payloadTransfer = PayloadTransfer.getDefaultTextPayloadTransfer().apply {
key = payloadKey
application = applicationName
}

// when: POST module-storage endpoint is called
cacheApi.postModuleStorageCache(payloadTransfer, apiKey)

// then: recorded payload should contain the same type and value
val savedPayload = cacheApi.getModuleStorageCache(payloadKey, applicationName, apiKey)
savedPayload.type shouldBe payloadTransfer.type
savedPayload.value shouldBe payloadTransfer.value

// and: shouldn't contain information about application
savedPayload.application?.should(beNull())
}

should("return the same xml transfer value which was saved to module-storage") {
//given: default xml payload with application
val payloadKey = getRandomString()
val payloadTransfer = PayloadTransfer.getDefaultXmlPayloadTransfer().apply {
key = payloadKey
application = applicationName
}

// when: POST module-storage endpoint is called
cacheApi.postModuleStorageCache(payloadTransfer, apiKey)

// then: recorded payload should contain the same type and value
val savedPayload = cacheApi.getModuleStorageCache(payloadKey, applicationName, apiKey)
savedPayload.type shouldBe payloadTransfer.type
savedPayload.value shouldBe payloadTransfer.value

// and: shouldn't contain information about application
savedPayload.application?.should(beNull())
}

should("return the same json transfer value which was saved to module-storage") {
//given: default json payload with application
val payloadKey = getRandomString()
val payloadTransfer = PayloadTransfer.getDefaultJsonPayloadTransfer().apply {
key = payloadKey
application = applicationName
}

// when: POST module-storage endpoint is called
cacheApi.postModuleStorageCache(payloadTransfer, apiKey)

// then: recorded payload should contain the same type and value
val savedPayload = cacheApi.getModuleStorageCache(payloadKey, applicationName, apiKey)
savedPayload.type shouldBe payloadTransfer.type
savedPayload.value shouldBe payloadTransfer.value

// and: shouldn't contain information about application
savedPayload.application?.should(beNull())
}

should("throw an exception when post request have nonexistent PBC application name") {
//given: default text payload with nonexistent application name
val payloadKey = getRandomString()
val randomApplication = getRandomString()
val payloadTransfer = PayloadTransfer.getDefaultTextPayloadTransfer().apply {
key = payloadKey
application = randomApplication
}

// when: POST module-storage endpoint is called
val exception = shouldThrowExactly<ApiException> {
cacheApi.postModuleStorageCache(payloadTransfer, apiKey) }

// then: Not found exception is thrown
assertSoftly {
exception.statusCode shouldBe NOT_FOUND.value()
exception.responseBody shouldContain "\"path\":\"/module-storage\""
exception.responseBody shouldContain "\"message\":\"Invalid application: ${randomApplication}\""
}
}

should("throw an exception when post request have null application name") {
//given: default text payload with null application name
val payloadKey = getRandomString()
val payloadTransfer = PayloadTransfer.getDefaultTextPayloadTransfer().apply {
key = payloadKey
application = null
}

// when: POST module-storage endpoint is called
val exception = shouldThrowExactly<ApiException> { cacheApi.postModuleStorageCache(payloadTransfer, apiKey) }

// then: Bad request exception is thrown
assertSoftly {
exception.statusCode shouldBe BAD_REQUEST.value()
exception.responseBody shouldContain "\"path\":\"/module-storage\""
exception.responseBody shouldContain "application must not be empty"
}
}

should("throw an exception when post request have empty application name") {
//given: default text payload with empty application name
val payloadKey = getRandomString()
val payloadTransfer = PayloadTransfer.getDefaultTextPayloadTransfer().apply {
key = payloadKey
application = ""
}

// when: POST module-storage endpoint is called
val exception = shouldThrowExactly<ApiException> { cacheApi.postModuleStorageCache(payloadTransfer, apiKey) }

// then: Bad request exception is thrown
assertSoftly {
exception.statusCode shouldBe BAD_REQUEST.value()
exception.responseBody shouldContain "\"path\":\"/module-storage\""
exception.responseBody shouldContain "application must not be empty"
}
}

should("throw an exception when post request have null key name") {
//given: default text payload with empty payloadKey
val payloadTransfer = PayloadTransfer.getDefaultTextPayloadTransfer().apply {
key = null
application = applicationName
}

// when: POST module-storage endpoint is called
val exception = shouldThrowExactly<ApiException> { cacheApi.postModuleStorageCache(payloadTransfer, apiKey) }

// then: Bad request exception is thrown
assertSoftly {
exception.statusCode shouldBe BAD_REQUEST.value()
exception.responseBody shouldContain "\"path\":\"/module-storage\""
exception.responseBody shouldContain "key must not be empty"
}
}

should("throw an exception when post request have empty key name") {
//given: default text payload with empty payloadKey
val payloadTransfer = PayloadTransfer.getDefaultTextPayloadTransfer().apply {
key = ""
application = applicationName
}

// when: POST module-storage endpoint is called
val exception = shouldThrowExactly<ApiException> { cacheApi.postModuleStorageCache(payloadTransfer, apiKey) }

// then: Bad request exception is thrown
assertSoftly {
exception.statusCode shouldBe BAD_REQUEST.value()
exception.responseBody shouldContain "\"path\":\"/module-storage\""
exception.responseBody shouldContain "key must not be empty"
}
}

should("throw an exception when post request have invalid PBC apiKey") {
//given: default text payload with application
val payloadKey = getRandomString()
val payloadTransfer = PayloadTransfer.getDefaultTextPayloadTransfer().apply {
key = payloadKey
application = applicationName
}

// when: POST module-storage endpoint is called
val exception =
shouldThrowExactly<ApiException> { cacheApi.postModuleStorageCache(payloadTransfer, getRandomString()) }

// then: Not found exception is thrown
assertSoftly {
exception.statusCode shouldBe UNAUTHORIZED.value()
exception.responseBody should beEmpty()
}
}

should("throw an exception when get request contain invalid payload key") {
//given: default text payload with application
val payloadTransfer = PayloadTransfer.getDefaultTextPayloadTransfer().apply {
key = getRandomString()
application = applicationName
}

// and: POST module-storage endpoint is called
cacheApi.postModuleStorageCache(payloadTransfer, apiKey)

// when: GET module-storage endpoint is called with invalid data
val exception = shouldThrowExactly<ApiException> {
cacheApi.getModuleStorageCache(getRandomString(), applicationName, apiKey)
}

// then: Not found exception is thrown
assertSoftly {
exception.statusCode shouldBe NOT_FOUND.value()
exception.responseBody shouldContain "\"path\":\"/module-storage\""
exception.responseBody shouldContain "Invalid application or key"
}
}

should("throw an exception when get request contain invalid application name") {
//given: default text payload with application
val payloadKey = getRandomString()
val payloadTransfer = PayloadTransfer.getDefaultTextPayloadTransfer().apply {
key = payloadKey
application = applicationName
}

// and: POST module-storage endpoint is called
cacheApi.postModuleStorageCache(payloadTransfer, apiKey)

//and: random application name
val randomApplication = getRandomString()

// when: GET module-storage endpoint is called with invalid data
val exception = shouldThrowExactly<ApiException> {
cacheApi.getModuleStorageCache(payloadKey, randomApplication, apiKey)
}

// then: Not found exception is thrown
assertSoftly {
exception.statusCode shouldBe NOT_FOUND.value()
exception.responseBody shouldContain "\"path\":\"/module-storage\""
exception.responseBody shouldContain "\"message\":\"Invalid application: ${randomApplication}\""
}
}

should("throw an exception when get request contain invalid apiKey") {
//given: default text payload with application
val payloadKey = getRandomString()
val payloadTransfer = PayloadTransfer.getDefaultTextPayloadTransfer().apply {
key = payloadKey
application = applicationName
}

// and: POST module-storage endpoint is called
cacheApi.postModuleStorageCache(payloadTransfer, apiKey)

// when: GET module-storage endpoint is called with invalid data
val exception = shouldThrowExactly<ApiException> {
cacheApi.getModuleStorageCache(payloadKey, applicationName, getRandomString())
}

// then: Not found exception is thrown
assertSoftly {
exception.statusCode shouldBe UNAUTHORIZED.value()
exception.responseBody should beEmpty()
}
}
})
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonValue

enum class MediaType {

JSON, XML, UNSUPPORTED;
JSON, XML, TEXT, UNSUPPORTED;

@JsonValue
fun getValue(): String = name.lowercase()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL
import org.prebid.cache.functional.mapper.objectMapper
import org.prebid.cache.functional.model.request.MediaType.JSON
import org.prebid.cache.functional.model.request.MediaType.TEXT
import org.prebid.cache.functional.model.request.MediaType.XML
import org.prebid.cache.functional.util.getRandomString

@JsonInclude(NON_NULL)
data class PayloadTransfer(
Expand All @@ -14,6 +16,7 @@ data class PayloadTransfer(
var expiry: Long? = null,
var ttlseconds: Long? = null,
var prefix: String? = null,
var application: String? = null,

//Fields not affected on PBC
var timestamp: Long? = null,
Expand All @@ -23,18 +26,18 @@ data class PayloadTransfer(
) {

companion object {
private const val DEFAULT_EXPIRY = 300L

private fun getDefaultPayloadTransfer(type: MediaType, value: String): PayloadTransfer =
PayloadTransfer(type = type, value = value, expiry = DEFAULT_EXPIRY, ttlseconds = 3000L)

fun getDefaultJsonPayloadTransfer(): PayloadTransfer =
PayloadTransfer(
type = JSON,
value = objectMapper.writeValueAsString(TransferValue.getDefaultJsonValue()),
expiry = 300
)
getDefaultPayloadTransfer(JSON, objectMapper.writeValueAsString(TransferValue.getDefaultJsonValue()))

fun getDefaultXmlPayloadTransfer(): PayloadTransfer =
PayloadTransfer(
type = XML,
value = objectMapper.writeValueAsString(TransferValue.getDefaultXmlValue()),
expiry = 300
)
getDefaultPayloadTransfer(XML, objectMapper.writeValueAsString(TransferValue.getDefaultXmlValue()))

fun getDefaultTextPayloadTransfer(): PayloadTransfer =
getDefaultPayloadTransfer(TEXT, getRandomString())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,8 @@ data class RequestObject(var puts: List<PayloadTransfer>) {

fun getDefaultXmlRequestObject(): RequestObject =
RequestObject(puts = listOf(PayloadTransfer.getDefaultXmlPayloadTransfer()))

fun getDefaultTextRequestObject(): RequestObject =
RequestObject(puts = listOf(PayloadTransfer.getDefaultTextPayloadTransfer()))
}
}
Loading