Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Commit

Permalink
Allow http client to receive empty response (#135)
Browse files Browse the repository at this point in the history
  • Loading branch information
boddissattva authored Feb 14, 2024
1 parent b327e84 commit 9c97741
Show file tree
Hide file tree
Showing 8 changed files with 502 additions and 29 deletions.
2 changes: 2 additions & 0 deletions dsl/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ dependencies {
testImplementation("org.mockito.kotlin:mockito-kotlin:4.1.0")
testImplementation("org.junit-pioneer:junit-pioneer:2.0.0")
testImplementation("org.wiremock:wiremock-standalone")
testImplementation("org.testcontainers:testcontainers")
testImplementation("org.testcontainers:junit-jupiter")

// JUnit5 engine dependencies
implementation("org.junit.platform:junit-platform-engine")
Expand Down
16 changes: 10 additions & 6 deletions dsl/src/main/kotlin/com/chutneytesting/kotlin/util/HttpClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,19 @@ import org.apache.hc.client5.http.auth.AuthScope
import org.apache.hc.client5.http.auth.CredentialsProvider
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials
import org.apache.hc.client5.http.classic.methods.*
import org.apache.hc.client5.http.impl.DefaultHttpRequestRetryStrategy
import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient
import org.apache.hc.client5.http.impl.classic.HttpClients
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder
import org.apache.hc.client5.http.protocol.HttpClientContext
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory
import org.apache.hc.core5.http.*
import org.apache.hc.core5.http.ClassicHttpRequest
import org.apache.hc.core5.http.ContentType
import org.apache.hc.core5.http.HttpHost
import org.apache.hc.core5.http.io.entity.StringEntity
import org.apache.hc.core5.http.protocol.HttpContext
import org.apache.hc.core5.ssl.SSLContextBuilder
import java.io.BufferedInputStream
import java.io.IOException
import java.io.InputStreamReader
import java.io.Reader

Expand Down Expand Up @@ -77,8 +76,13 @@ object HttpClient {
try {
val inputStream = BufferedInputStream(response.entity.content)
val reader: Reader = InputStreamReader(inputStream, Charsets.UTF_8)
val mapper = configureObjectMapper()
return mapper.readValue(reader, object : TypeReference<T>() {})
val text = reader.readText()
if (text.isNotBlank()) {
val mapper = configureObjectMapper()
return mapper.readValue(text, object : TypeReference<T>() {})
} else {
return T::class.java.getConstructor().newInstance()
}
} catch (e: Exception) {
throw HttpClientException(e)
}
Expand Down
165 changes: 165 additions & 0 deletions dsl/src/test/kotlin/blackbox/IntegrationTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package blackbox

import com.chutneytesting.kotlin.util.ChutneyServerInfo
import com.chutneytesting.kotlin.util.HttpClient
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import org.testcontainers.containers.BindMode
import org.testcontainers.containers.GenericContainer
import org.testcontainers.junit.jupiter.Testcontainers
import java.io.File
import java.nio.file.Files

@Testcontainers
class IntegrationTest {

companion object {
var chutneyServer: GenericContainer<Nothing>? = null
var adminServerInfo: ChutneyServerInfo? = null
var userServerInfo: ChutneyServerInfo? = null

@JvmStatic
@BeforeAll
fun setUp() {
val tempDirectory = Files.createTempDirectory("chutney-kotlin-blackbox")
val memAuthConfigFile = File(
IntegrationTest::class.java.getResource("/blackbox/application-mem-auth.yml")!!.path
)

// Copy mem-auth config
Files.copy(memAuthConfigFile.toPath(), tempDirectory.resolve("application-mem-auth.yml"))

// Start server
chutneyServer = GenericContainer<Nothing>("ghcr.io/chutney-testing/chutney/server:latest")
.apply {
//withStartupTimeout(Duration.ofSeconds(30))
withExposedPorts(8443)
withFileSystemBind(tempDirectory.toString(), "/config", BindMode.READ_WRITE)
}
chutneyServer!!.start()
adminServerInfo =
ChutneyServerInfo("https://${chutneyServer?.host}:${chutneyServer?.firstMappedPort}", "admin", "admin")
userServerInfo =
ChutneyServerInfo("https://${chutneyServer?.host}:${chutneyServer?.firstMappedPort}", "user", "user")

// Set authorizations
val roles = IntegrationTest::class.java.getResource("/blackbox/roles.json")!!.path
HttpClient.post<Any>(adminServerInfo!!, "/api/v1/authorizations", File(roles).readText())
}

@JvmStatic
@AfterAll
fun cleanUp() {
chutneyServer?.stop()
}
}

@Test
fun create_update_scenario_with_specific_ids() {
// Given
var body = """
{
"id": "1234",
"title": "My scenario",
"content": "{\"when\": {}}",
"description": "My scenario description",
"tags": [],
"defaultDataset": null
}
""".trimIndent()

// Create scenario
var result = HttpClient.post<String>(adminServerInfo!!, "/api/scenario/v2/raw", body)
assertThat(result).isEqualTo("1234")

// Update scenario
body = """
{
"id": "1234",
"title": "My new title",
"content": "{\"when\": {}}",
"description": "My new scenario description",
"tags": ["A_TAG"],
"defaultDataset": null,
"version": 1
}
""".trimIndent()
result = HttpClient.post<String>(adminServerInfo!!, "/api/scenario/v2/raw", body)
assertThat(result).isEqualTo("1234")

// Then
val resultRaw = HttpClient.get<Map<String, Any>>(userServerInfo!!, "/api/scenario/v2/raw/1234")
assertThat(resultRaw)
.containsEntry("id", "1234")
.containsEntry("title", "My new title")
.containsEntry("description", "My new scenario description")
.containsEntry("tags", listOf("A_TAG"))
}

@Test
fun create_update_campaign_with_specific_ids() {
// Given
val scenarioIdA = createEmptyScenario()
val scenarioIdB = createEmptyScenario()

// Create campaign
var body = """
{
"id": 1234,
"title": "My campaign",
"description": "",
"scenarioIds": ["$scenarioIdA"],
"environment": "DEFAULT",
"parallelRun": false,
"retryAuto": false,
"datasetId": null,
"tags": []
}
""".trimIndent()
var result = HttpClient.post<HashMap<String, Any>>(adminServerInfo!!, "/api/ui/campaign/v1", body)
assertThat(result)
.containsEntry("id", 1234)
.containsEntry("scenarioIds", listOf(scenarioIdA))

// Update campaign
body = """
{
"id": 1234,
"title": "My new campaign",
"description": "My new campaign description",
"scenarioIds": ["$scenarioIdB"],
"environment": "DEFAULT",
"parallelRun": false,
"retryAuto": false,
"datasetId": null,
"tags": ["A_TAG"]
}
""".trimIndent()
result = HttpClient.post<HashMap<String, Any>>(adminServerInfo!!, "/api/ui/campaign/v1", body)
assertThat(result)
.containsEntry("id", 1234)
.containsEntry("scenarioIds", listOf(scenarioIdB))

// Then
val resultRaw = HttpClient.get<Map<String, Any>>(userServerInfo!!, "/api/ui/campaign/v1/1234")
assertThat(resultRaw)
.containsEntry("id", 1234)
.containsEntry("title", "My new campaign")
.containsEntry("description", "My new campaign description")
.containsEntry("scenarioIds", listOf(scenarioIdB))
.containsEntry("tags", listOf("A_TAG"))
}

private fun createEmptyScenario(): String {
val body = """
{
"title": "Empty scenario",
"content": "{\"when\": {}}",
"tags": []
}
""".trimIndent()
return HttpClient.post<String>(adminServerInfo!!, "/api/scenario/v2/raw", body)
}
}
Loading

0 comments on commit 9c97741

Please sign in to comment.