Skip to content

Commit

Permalink
Add tests against MockServer and a SOCKS5 proxy (#8057)
Browse files Browse the repository at this point in the history
  • Loading branch information
yschimke committed Jan 20, 2024
1 parent 61d91f9 commit a990f78
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 0 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/containers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: containers

on:
push:
branches:
- master
pull_request:
types: [opened, labeled, unlabeled, synchronize]

permissions:
contents: read

env:
GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx4g -Dorg.gradle.daemon=false -Dkotlin.incremental=false"

jobs:
test_containers:
permissions:
checks: write # for actions/upload-artifact
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master' || contains(github.event.pull_request.labels.*.name, 'containers')

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Configure JDK
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: 17

- name: Run Container Tests
uses: gradle/gradle-build-action@v2
with:
arguments: container-tests:test -PcontainerTests=true
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ subprojects {
if (project.name == "android-test") return@subprojects
if (project.name == "regression-test") return@subprojects
if (project.name == "android-test-app") return@subprojects
if (project.name == "container-tests") return@subprojects

apply(plugin = "checkstyle")
apply(plugin = "ru.vyarus.animalsniffer")
Expand Down
5 changes: 5 additions & 0 deletions container-tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
OkHttp Container Tests
======================

This module contains tests against other services
via containers.
25 changes: 25 additions & 0 deletions container-tests/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
plugins {
kotlin("jvm")
}

tasks.withType<Test> {
useJUnitPlatform()
onlyIf("By default not in CI") {
System.getenv("CI") == null
|| (project.hasProperty("containerTests") && project.property("containerTests").toString().toBoolean())
}
}

dependencies {
api(projects.okhttp)

testImplementation(projects.okhttpTestingSupport)
testImplementation(libs.junit.jupiter.api)
testImplementation(libs.junit.jupiter.params)
testImplementation(libs.junit.jupiter.engine)
testImplementation(libs.assertk)
testImplementation(libs.testcontainers)
testImplementation(libs.mockserver)
testImplementation(libs.mockserver.client)
testImplementation(libs.testcontainers.junit5)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package okhttp3.containers

import assertk.assertThat
import assertk.assertions.contains
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509TrustManager
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import org.junit.jupiter.api.Test
import org.mockserver.client.MockServerClient
import org.mockserver.configuration.Configuration
import org.mockserver.logging.MockServerLogger
import org.mockserver.model.HttpRequest.request
import org.mockserver.model.HttpResponse.response
import org.mockserver.socket.tls.KeyStoreFactory
import org.testcontainers.containers.MockServerContainer
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers
import org.testcontainers.utility.DockerImageName

@Testcontainers
class BasicMockServerTest {
@Container
val mockServer: MockServerContainer = MockServerContainer(MOCKSERVER_IMAGE)

val client =
OkHttpClient.Builder()
.trustMockServer()
.build()

@Test
fun testRequest() {
MockServerClient(mockServer.host, mockServer.serverPort).use { mockServerClient ->
mockServerClient
.`when`(
request().withPath("/person")
.withQueryStringParameter("name", "peter"),
)
.respond(response().withBody("Peter the person!"))

val response = client.newCall(Request((mockServer.endpoint + "/person?name=peter").toHttpUrl())).execute()

assertThat(response.body.string()).contains("Peter the person")
}
}

@Test
fun testHttpsRequest() {
MockServerClient(mockServer.host, mockServer.serverPort).use { mockServerClient ->
mockServerClient
.`when`(
request().withPath("/person")
.withQueryStringParameter("name", "peter"),
)
.respond(response().withBody("Peter the person!"))

val response = client.newCall(Request((mockServer.secureEndpoint + "/person?name=peter").toHttpUrl())).execute()

assertThat(response.body.string()).contains("Peter the person")
}
}

companion object {
val MOCKSERVER_IMAGE: DockerImageName =
DockerImageName
.parse("mockserver/mockserver")
.withTag("mockserver-5.15.0")

fun OkHttpClient.Builder.trustMockServer(): OkHttpClient.Builder =
apply {
val keyStoreFactory = KeyStoreFactory(Configuration.configuration(), MockServerLogger())

val socketFactory = keyStoreFactory.sslContext().socketFactory

val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
trustManagerFactory.init(keyStoreFactory.loadOrCreateKeyStore())
val trustManager = trustManagerFactory.trustManagers.first() as X509TrustManager

sslSocketFactory(socketFactory, trustManager)
}
}
}
69 changes: 69 additions & 0 deletions container-tests/src/test/java/okhttp3/containers/SocksProxyTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package okhttp3.containers

import assertk.assertThat
import assertk.assertions.contains
import java.net.InetSocketAddress
import java.net.Proxy
import java.net.Proxy.Type.SOCKS
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.containers.BasicMockServerTest.Companion.MOCKSERVER_IMAGE
import org.junit.jupiter.api.Test
import org.mockserver.client.MockServerClient
import org.mockserver.model.HttpRequest.request
import org.mockserver.model.HttpResponse.response
import org.testcontainers.containers.GenericContainer
import org.testcontainers.containers.MockServerContainer
import org.testcontainers.containers.Network
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers
import org.testcontainers.utility.DockerImageName

@Testcontainers
class SocksProxyTest {
val network: Network = Network.newNetwork()

@Container
val mockServer: MockServerContainer =
MockServerContainer(MOCKSERVER_IMAGE)
.withNetwork(network)
.withNetworkAliases("mockserver")

@Container
val socks5Proxy =
GenericContainer(SOCKS5_PROXY)
.withNetwork(network)
.withExposedPorts(1080)

@Test
fun testLocal() {
MockServerClient(mockServer.host, mockServer.serverPort).use { mockServerClient ->
mockServerClient
.`when`(
request().withPath("/person")
.withQueryStringParameter("name", "peter"),
)
.respond(response().withBody("Peter the person!"))

val client =
OkHttpClient.Builder()
.proxy(Proxy(SOCKS, InetSocketAddress(socks5Proxy.host, socks5Proxy.firstMappedPort)))
.build()

val response =
client.newCall(
Request("http://mockserver:1080/person?name=peter".toHttpUrl()),
).execute()

assertThat(response.body.string()).contains("Peter the person")
}
}

companion object {
val SOCKS5_PROXY: DockerImageName =
DockerImageName
.parse("serjs/go-socks5-proxy")
.withTag("v0.0.3")
}
}
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ kotlin.incremental.js.ir=true
androidBuild=false
graalBuild=false
loomBuild=false
containerTests=false
android.experimental.lint.version=8.2.0
7 changes: 7 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ com-squareup-okio = "3.7.0"
de-mannodermaus-junit5 = "1.4.0"
graalvm = "22.3.2"
kotlinx-serialization = "1.6.2"
mockserverClient = "5.15.0"
org-bouncycastle = "1.76"
org-conscrypt = "2.5.2"
org-jetbrains-coroutines = "1.7.3"
org-jetbrains-kotlin = "1.9.21"
org-junit-jupiter = "5.10.1"
testcontainers = "1.19.3"

[libraries]
amazonCorretto = "software.amazon.cryptools:AmazonCorrettoCryptoProvider:2.3.1"
Expand Down Expand Up @@ -74,6 +76,8 @@ kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-c
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "org-jetbrains-coroutines" }
kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "kotlinx-serialization" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
mockserver = { module = "org.testcontainers:mockserver", version.ref = "testcontainers" }
mockserver-client = { module = "org.mock-server:mockserver-client-java-no-dependencies", version.ref = "mockserverClient" }
nativeImageSvm = { module = "org.graalvm.nativeimage:svm", version.ref = "graalvm" }
openjsse = "org.openjsse:openjsse:1.1.14"
playservices-safetynet = "com.google.android.gms:play-services-safetynet:18.0.1"
Expand All @@ -88,3 +92,6 @@ squareup-okhttp-icu = "com.squareup.okhttpicu:okhttp-icu:0.2.0"
squareup-kotlinPoet = "com.squareup:kotlinpoet:1.15.3"
squareup-okio = { module = "com.squareup.okio:okio", version.ref = "com-squareup-okio" }
squareup-okio-fakefilesystem = { module = "com.squareup.okio:okio-fakefilesystem", version.ref = "com-squareup-okio" }
squareup-okio-nodefilesystem = { module = "com.squareup.okio:okio-nodefilesystem", version.ref = "com-squareup-okio" }
testcontainers = { module = "org.testcontainers:testcontainers", version.ref = "testcontainers" }
testcontainers-junit5 = { module = "org.testcontainers:junit-jupiter", version.ref = "testcontainers" }
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ include(":samples:slack")
include(":samples:static-server")
include(":samples:tlssurvey")
include(":samples:unixdomainsockets")
include(":container-tests")

project(":okhttp-logging-interceptor").name = "logging-interceptor"

Expand Down

0 comments on commit a990f78

Please sign in to comment.