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 @@ -9,6 +9,9 @@ import aws.smithy.kotlin.runtime.http.engine.DefaultHttpEngine
import aws.smithy.kotlin.runtime.http.engine.crt.CrtHttpEngine
import aws.smithy.kotlin.runtime.http.engine.okhttp4.OkHttp4Engine
import aws.smithy.kotlin.runtime.net.url.Url
import java.nio.file.Paths
import java.util.Properties
import kotlin.io.path.exists

internal actual fun engineFactories(): List<TestEngineFactory> =
// FIXME Move DefaultHttpEngine and CrtHttpEngine to `jvmAndNative`
Expand All @@ -18,13 +21,20 @@ internal actual fun engineFactories(): List<TestEngineFactory> =
TestEngineFactory("OkHttp4Engine") { OkHttp4Engine(it) },
)

internal actual val testServers = mapOf(
ServerType.DEFAULT to Url.parse("http://127.0.0.1:8082"),
private fun loadTestServerPorts(): Map<ServerType, Url> {
val sslConfigPath = System.getProperty("SSL_CONFIG_PATH")
val portsConfigPath = Paths.get(sslConfigPath).parent.resolve("test-server-ports.properties")
check(portsConfigPath.exists()) { "Failed to find ports configuration at $portsConfigPath" }
val properties = Properties()
portsConfigPath.toFile().inputStream().use { input ->
properties.load(input)
}

// FIXME Enable once we figure out how to get TLS1 and TLS1.1 working
// ServerType.TLS_1_0 to Url.parse("https://127.0.0.1:8090"),
return ServerType.entries.mapNotNull { serverType ->
properties.getProperty(serverType.name)?.let { url ->
serverType to Url.parse(url)
}
}.toMap()
}

ServerType.TLS_1_1 to Url.parse("https://127.0.0.1:8091"),
ServerType.TLS_1_2 to Url.parse("https://127.0.0.1:8092"),
ServerType.TLS_1_3 to Url.parse("https://127.0.0.1:8093"),
)
internal actual val testServers = loadTestServerPorts()
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,55 @@ import io.ktor.server.jetty.jakarta.Jetty
import io.ktor.server.jetty.jakarta.JettyApplicationEngineBase
import redirectTests
import java.io.Closeable
import java.net.ServerSocket
import java.nio.file.Path
import java.nio.file.Paths
import java.util.concurrent.TimeUnit
import kotlin.io.path.exists
import kotlin.time.Duration.Companion.seconds

private data class TestServer(
val port: Int,
val type: ConnectorType,
val protocolName: String?,
val initializer: Application.() -> Unit,
val port: Int = ServerSocket(0).use { it.localPort },
)

private fun testServer(serverType: ServerType): TestServer = when (serverType) {
ServerType.DEFAULT -> TestServer(8082, ConnectorType.HTTP, null, Application::testRoutes)
ServerType.DEFAULT -> TestServer(ConnectorType.HTTP, null, Application::testRoutes)

// FIXME Enable once we figure out how to get TLS1 and TLS1.1 working
// ServerType.TLS_1_0 -> TestServer(8090, ConnectorType.HTTPS, "TLSv1", Application::tlsRoutes)
// ServerType.TLS_1_0 -> TestServer(ConnectorType.HTTPS, "TLSv1", Application::tlsRoutes)

ServerType.TLS_1_1 -> TestServer(8091, ConnectorType.HTTPS, "TLSv1.1", Application::tlsRoutes)
ServerType.TLS_1_2 -> TestServer(8092, ConnectorType.HTTPS, "TLSv1.2", Application::tlsRoutes)
ServerType.TLS_1_3 -> TestServer(8093, ConnectorType.HTTPS, "TLSv1.3", Application::tlsRoutes)
ServerType.TLS_1_1 -> TestServer(ConnectorType.HTTPS, "TLSv1.1", Application::tlsRoutes)
ServerType.TLS_1_2 -> TestServer(ConnectorType.HTTPS, "TLSv1.2", Application::tlsRoutes)
ServerType.TLS_1_3 -> TestServer(ConnectorType.HTTPS, "TLSv1.3", Application::tlsRoutes)
}

private class Resources : Closeable {
private val resources = mutableListOf<Closeable>()
private val filesToDelete = mutableListOf<Path>()

fun add(resource: Closeable) {
resources.add(resource)
}

fun addFileToDelete(file: Path) {
filesToDelete.add(file)
}

override fun close() {
resources.forEach(Closeable::close)
filesToDelete.forEach { file ->
try {
if (file.exists()) {
file.toFile().delete()
println("Deleted file $file")
}
} catch (e: Exception) {
println("Failed to delete file $file: ${e.message}")
}
}
}

val size: Int get() = resources.size
Expand All @@ -57,25 +75,30 @@ private class Resources : Closeable {
* @param sslConfigPath The path at which to write the generated SSL config
*/
internal fun startServers(sslConfigPath: String): Closeable {
val servers = Resources()

val sslConfig = SslConfig.generate()
println("Persisting custom SSL config to $sslConfigPath...")
sslConfig.persist(Paths.get(sslConfigPath))
servers.addFileToDelete(Paths.get(sslConfigPath))

val servers = Resources()
println("Starting local servers for HTTP client engine test suite...")
println("Setting JKS path ${sslConfig.keyStoreFile.absolutePath}")

try {
ServerType
.entries
.map(::testServer)
.forEach { testServer ->
val runningInstance = tlsServer(testServer, sslConfig)
servers.add {
println("Stopping server on port ${testServer.port}...")
runningInstance.stop(0L, 0L, TimeUnit.MILLISECONDS)
}
val testServers = ServerType.entries.associateWith(::testServer)
testServers.values.forEach { testServer ->
val runningInstance = tlsServer(testServer, sslConfig)
servers.add {
println("Stopping server on port ${testServer.port}...")
runningInstance.stop(0L, 0L, TimeUnit.MILLISECONDS)
}
}

val portsConfigPath = Paths.get(sslConfigPath).parent.resolve("test-server-ports.properties")
println("Persisting test servers port configuration to $portsConfigPath...")
persistPortConfig(testServers, portsConfigPath)
servers.addFileToDelete(portsConfigPath)

// ensure servers are up and listening before tests run
Thread.sleep(1000)
Expand All @@ -90,6 +113,23 @@ internal fun startServers(sslConfigPath: String): Closeable {
return servers
}

private fun persistPortConfig(testServers: Map<ServerType, TestServer>, path: java.nio.file.Path) {
val properties = java.util.Properties()

testServers.forEach { (serverType, testServer) ->
val protocol = if (testServer.type == ConnectorType.HTTPS) {
"https"
} else {
"http"
}
properties.setProperty(serverType.name, "$protocol://127.0.0.1:${testServer.port}")
}

path.toFile().outputStream().use { output ->
properties.store(output, "Test server port configuration")
}
}

private fun tlsServer(instance: TestServer, sslConfig: SslConfig): EmbeddedServer<*, *> {
val description = "${instance.type.name} server on port ${instance.port}"
println("Starting $description...")
Expand Down
Loading