Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KTOR-7812 Use default JDK for running tests on CI #4342

Merged
merged 10 commits into from
Nov 22, 2024
1 change: 1 addition & 0 deletions buildSrc/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pluginManagement {
}

plugins {
id("org.gradle.toolchains.foojay-resolver-convention")
id("conventions-dependency-resolution-management")
}

Expand Down
38 changes: 27 additions & 11 deletions buildSrc/src/main/kotlin/JvmConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import org.gradle.kotlin.dsl.*
import org.jetbrains.kotlin.gradle.targets.jvm.tasks.*

fun Project.configureJvm() {
val jdk = when (name) {
val compileJdk = when (name) {
in jdk11Modules -> 11
else -> 8
}
Expand Down Expand Up @@ -56,7 +56,7 @@ fun Project.configureJvm() {
maxHeapSize = "2g"
exclude("**/*StressTest*")
useJUnitPlatform()
configureJavaLauncher(jdk)
configureJavaToolchain(compileJdk)
}

tasks.register<Test>("stressTest") {
Expand All @@ -69,7 +69,7 @@ fun Project.configureJvm() {
systemProperty("enable.stress.tests", "true")
include("**/*StressTest*")
useJUnitPlatform()
configureJavaLauncher(jdk)
configureJavaToolchain(compileJdk)
}

val configuredVersion: String by rootProject.extra
Expand All @@ -86,15 +86,31 @@ fun Project.configureJvm() {
}

/**
* JUnit 5 requires Java 11+
* On local machine use for tests the JDK used for compilation.
* On CI use the default JDK.
*/
fun Test.configureJavaLauncher(jdk: Int) {
if (jdk < 11) {
val javaToolchains = project.extensions.getByType<JavaToolchainService>()
val customLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of("11")
}
javaLauncher = customLauncher
private fun Test.configureJavaToolchain(compileJdk: Int) {
// JUnit 5 requires JDK 11+
val testJdk = (if (CI) currentJdk else compileJdk).coerceAtLeast(11)
val javaToolchains = project.the<JavaToolchainService>()

javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(testJdk)
}

if (testJdk >= 16) {
// Allow reflective access from tests
jvmArgs(
"--add-opens=java.base/java.net=ALL-UNNAMED",
"--add-opens=java.base/java.time=ALL-UNNAMED",
"--add-opens=java.base/java.util=ALL-UNNAMED",
)
}

if (testJdk >= 21) {
// coroutines-debug use dynamic agent loading under the hood.
// Remove as soon as the issue is fixed: https://youtrack.jetbrains.com/issue/KT-62096/
jvmArgs("-XX:+EnableDynamicAgentLoading")
}
}

Expand Down
28 changes: 1 addition & 27 deletions buildSrc/src/main/kotlin/KtorBuildProperties.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,6 @@
*/

import org.gradle.api.*
import org.gradle.api.tasks.testing.*
import org.gradle.jvm.toolchain.*
import org.gradle.kotlin.dsl.*

/*
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

private val java_version: String = System.getProperty("java.version", "8.0.0")

private val versionComponents = java_version
.split(".")
.take(2)
.filter { it.isNotBlank() }
.map { Integer.parseInt(it) }

val IDEA_ACTIVE: Boolean = System.getProperty("idea.active") == "true"

Expand All @@ -30,7 +15,7 @@ val HOST_NAME = when {
else -> error("Unknown os name `$OS_NAME`")
}

val currentJdk = if (versionComponents[0] == 1) versionComponents[1] else versionComponents[0]
val currentJdk = JavaVersion.current().majorVersion.toInt()

val jdk11Modules = listOf(
"ktor-client-java",
Expand All @@ -40,14 +25,3 @@ val jdk11Modules = listOf(
"ktor-server-jetty-test-http2-jakarta",
"ktor-server-tomcat-jakarta",
)

fun Project.useJdkVersionForJvmTests(version: Int) {
tasks.named<Test>("jvmTest") {
val javaToolchains = project.extensions.getByType<JavaToolchainService>()
javaLauncher.set(
javaToolchains.launcherFor {
languageVersion.set(JavaLanguageVersion.of(version))
}
)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.client.engine.cio
Expand All @@ -11,26 +11,26 @@ import io.ktor.client.plugins.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.junit.*
import io.ktor.network.tls.certificates.*
import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.utils.io.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.junit5.*
import org.junit.jupiter.api.extension.*
import java.io.*
import java.net.*
import java.util.concurrent.*
import javax.net.ssl.*
import kotlin.concurrent.*
import kotlinx.coroutines.debug.junit5.CoroutinesTimeout
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout
import java.io.File
import java.net.ConnectException
import java.net.ServerSocket
import java.net.SocketException
import java.util.concurrent.TimeUnit
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509TrustManager
import kotlin.concurrent.thread
import kotlin.test.*

@CoroutinesTimeout(5 * 60 * 1000)
@ExtendWith(RetrySupport::class)
class ConnectErrorsTest {

private val serverSocket = ServerSocket(0, 1)
Expand All @@ -40,7 +40,7 @@ class ConnectErrorsTest {
serverSocket.close()
}

@RetryableTest(3)
@Test
fun testConnectAfterConnectionErrors(): Unit = runBlocking {
val client = HttpClient(CIO) {
engine {
Expand Down Expand Up @@ -84,7 +84,7 @@ class ConnectErrorsTest {
}
}

@RetryableTest(3)
@Test
fun testResponseWithNoLengthChunkedAndConnectionClosedWithHttp10(): Unit = runBlocking {
val client = HttpClient(CIO)

Expand All @@ -110,7 +110,7 @@ class ConnectErrorsTest {
}
}

@RetryableTest(3)
@Test
fun testResponseErrorWithNoLengthChunkedAndConnectionClosedWithHttp11(): Unit = runBlocking {
val client = HttpClient(CIO)

Expand Down Expand Up @@ -183,7 +183,7 @@ class ConnectErrorsTest {
}
}

@RetryableTest(3)
@Test
fun testLateServerStart(): Unit = runBlocking {
val keyStoreFile = File("build/temp.jks")
val keyStore = generateCertificate(keyStoreFile, algorithm = "SHA256withECDSA", keySizeInBits = 256)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import test.server.*

/*
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

import test.server.*

description = "Ktor client Auth support"

apply<TestServerPlugin>()

useJdkVersionForJvmTests(11)
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
/*
* Copyright 2014-2020 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

description = "Ktor client Byte Order Mark support"

useJdkVersionForJvmTests(11)
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/*
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

useJdkVersionForJvmTests(11)

apply<test.server.TestServerPlugin>()

kotlin.sourceSets {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

description = "Ktor client JSON support"

Expand Down Expand Up @@ -29,5 +29,3 @@ kotlin {
}
}
}

useJdkVersionForJvmTests(11)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

kotlin.sourceSets {
commonTest {
Expand All @@ -9,5 +9,3 @@ kotlin.sourceSets {
}
}
}

useJdkVersionForJvmTests(11)
8 changes: 0 additions & 8 deletions ktor-client/ktor-client-tests/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@

import test.server.*

/*
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

description = "Common tests for client"

plugins {
Expand All @@ -16,8 +12,6 @@ plugins {

apply<TestServerPlugin>()

val osName = System.getProperty("os.name")

kotlin.sourceSets {
commonMain {
dependencies {
Expand Down Expand Up @@ -105,5 +99,3 @@ kotlin.sourceSets {
}
}
}

useJdkVersionForJvmTests(11)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.client.tests.plugins

Expand Down Expand Up @@ -186,7 +186,7 @@ class CookiesIntegrationTests : ClientLoader() {
}

@Test
fun testCookiesWithWrongValue() = clientTests(listOf("js", "Darwin", "DarwinLegacy", "WinHttp")) {
fun testCookiesWithWrongValue() = clientTests(listOf("Js", "Darwin", "DarwinLegacy", "WinHttp", "Java")) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

openjdk/jdk16@1c47244: Java 16 adds validation for header values, so this test doesn't pass on Java engine anymore

config {
install(HttpCookies)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import io.ktor.client.*
import io.ktor.client.engine.*
import io.ktor.util.reflect.*
import io.ktor.utils.io.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.debug.CoroutineInfo
import kotlinx.coroutines.debug.DebugProbes
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout
import java.util.*
import kotlin.time.Duration.Companion.seconds

Expand Down Expand Up @@ -44,10 +47,17 @@ actual abstract class ClientLoader actual constructor(val timeoutSeconds: Int) {
}
}

fun shouldSkip(engine: HttpClientEngineContainer, skipEngines: List<String>, onlyWithEngine: String?): Boolean =
skipEngines.any { shouldSkip(engine.toString(), it, onlyWithEngine) }
private fun shouldSkip(
engine: HttpClientEngineContainer,
skipEngines: List<String>,
onlyWithEngine: String?
): Boolean {
val engineName = engine.toString()
return onlyWithEngine != null && !onlyWithEngine.equals(engineName, ignoreCase = true) ||
skipEngines.any { shouldSkip(engineName, it) }
}

fun shouldSkip(engineName: String, skipEngine: String, onlyWithEngine: String?): Boolean {
private fun shouldSkip(engineName: String, skipEngine: String): Boolean {
val locale = Locale.getDefault()
val skipEngineArray = skipEngine.lowercase(locale).split(":")

Expand All @@ -61,9 +71,8 @@ actual abstract class ClientLoader actual constructor(val timeoutSeconds: Int) {
val engineShouldBeSkipped = "*" == skipEngineName || engineName.lowercase(locale) == skipEngineName.lowercase(
locale
)
val notOnlyEngine = onlyWithEngine != null && engineName.lowercase(locale) != onlyWithEngine.lowercase(locale)

return (engineShouldBeSkipped && platformShouldBeSkipped) || notOnlyEngine
return engineShouldBeSkipped && platformShouldBeSkipped
}

@OptIn(ExperimentalCoroutinesApi::class)
Expand Down
13 changes: 4 additions & 9 deletions ktor-java-modules-test/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,18 @@ tasks.named<JavaCompile>("compileJava") {
classpath = emptyClasspath
}
}

// Here should be specified the latest LTS version
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
languageVersion = JavaLanguageVersion.of(21)
}
}

dependencies {
rootProject.subprojects
.filter { it.hasJavaModule }
.map {
generateSequence(it) { it.parent }
.toList()
.dropLast(1)
.reversed()
.joinToString(":", prefix = ":") { it.name }
}
.forEach { api(project(it)) }
.forEach { implementation(project(it.path)) }
}

internal val Project.hasJavaModule: Boolean
Expand Down
Loading