Skip to content

Commit

Permalink
KTOR-7846 Fix running tests against JDK 8 (#4502)
Browse files Browse the repository at this point in the history
* Use CoroutinesTimeout version compatible with Java 8
* Ignore clients compiled for newer Java versions
* Downgrade logback when running tests against Java 8
* Fix JDK version for ktor-server-jte
* Fix JDK version for ktor-server-openapi
* Fix Path.combineSafe on JVM 8
* Fix i18n test on JVM 8
  • Loading branch information
osipxd authored Dec 4, 2024
1 parent b049285 commit 9df87a0
Show file tree
Hide file tree
Showing 28 changed files with 646 additions and 114 deletions.
7 changes: 1 addition & 6 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,8 @@ fun configureDokka() {
configureDokka()

fun Project.setupJvmToolchain() {
val jdk = when (project.name) {
in jdk11Modules -> 11
else -> 8
}

kotlin {
jvmToolchain(jdk)
jvmToolchain(project.requiredJdkVersion)
}
}

Expand Down
21 changes: 9 additions & 12 deletions buildSrc/src/main/kotlin/JvmConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,17 @@
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

import internal.*
import org.gradle.api.*
import org.gradle.api.tasks.testing.*
import org.gradle.jvm.tasks.*
import org.gradle.jvm.toolchain.*
import internal.libs
import org.gradle.api.Project
import org.gradle.api.tasks.testing.Test
import org.gradle.jvm.tasks.Jar
import org.gradle.jvm.toolchain.JavaLanguageVersion
import org.gradle.jvm.toolchain.JavaToolchainService
import org.gradle.kotlin.dsl.*
import org.jetbrains.kotlin.gradle.targets.jvm.tasks.*
import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmTest

fun Project.configureJvm() {
val compileJdk = when (name) {
in jdk11Modules -> 11
else -> 8
}
val compileJdk = project.requiredJdkVersion

kotlin {
jvm()
Expand Down Expand Up @@ -90,8 +88,7 @@ fun Project.configureJvm() {
* On CI use the default JDK.
*/
private fun Test.configureJavaToolchain(compileJdk: Int) {
// JUnit 5 requires JDK 11+
val testJdk = (if (CI) currentJdk else compileJdk).coerceAtLeast(11)
val testJdk = if (CI) currentJdk else compileJdk
val javaToolchains = project.the<JavaToolchainService>()

javaLauncher = javaToolchains.launcherFor {
Expand Down
19 changes: 16 additions & 3 deletions buildSrc/src/main/kotlin/KtorBuildProperties.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

import org.gradle.api.*
import org.gradle.api.JavaVersion
import org.gradle.api.Project

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

Expand All @@ -17,11 +18,23 @@ val HOST_NAME = when {

val currentJdk = JavaVersion.current().majorVersion.toInt()

val jdk11Modules = listOf(
val Project.requiredJdkVersion: Int
get() = when {
name in jdk17Modules -> 17
name in jdk11Modules -> 11
else -> 8
}

private val jdk17Modules = setOf(
"ktor-server-jte",
)

private val jdk11Modules = setOf(
"ktor-client-java",
"ktor-server-servlet-jakarta",
"ktor-client-jetty-jakarta",
"ktor-server-jetty-jakarta",
"ktor-server-jetty-test-http2-jakarta",
"ktor-server-openapi",
"ktor-server-servlet-jakarta",
"ktor-server-tomcat-jakarta",
)
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ dependencyResolutionManagement {
} else if (kotlinVersion != null) {
version("kotlin", kotlinVersion)
}

downgradeTestDependencies()
}
}
}

fun VersionCatalogBuilder.downgradeTestDependencies() {
val testJdk = JavaVersion.current().majorVersion.toInt()

if (testJdk < 11) version("logback", "1.3.14") // Java 8 support dropped in Logback 1.4.x
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@ import io.ktor.client.statement.*
import io.ktor.client.tests.utils.*
import io.ktor.http.*
import io.ktor.http.content.*
import io.ktor.junit.coroutines.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.mockk.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.junit5.*
import java.net.*
import java.nio.channels.*
import io.mockk.mockkStatic
import io.mockk.verify
import kotlinx.coroutines.delay
import java.net.InetAddress
import java.nio.channels.UnresolvedAddressException
import kotlin.test.*

@CoroutinesTimeout(60_000)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import io.ktor.client.plugins.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.junit.coroutines.*
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 kotlinx.coroutines.debug.junit5.CoroutinesTimeout
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout
import java.io.File
Expand Down
5 changes: 2 additions & 3 deletions ktor-client/ktor-client-tests/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* 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.*
import test.server.TestServerPlugin

description = "Common tests for client"

Expand Down Expand Up @@ -46,9 +46,8 @@ kotlin.sourceSets {
api(project(":ktor-server:ktor-server-plugins:ktor-server-auth"))
api(project(":ktor-server:ktor-server-plugins:ktor-server-websockets"))
api(project(":ktor-shared:ktor-serialization:ktor-serialization-kotlinx"))
api(project(":ktor-shared:ktor-junit"))
api(libs.logback.classic)
api(libs.junit)
api(libs.kotlin.test.junit5)
implementation(libs.kotlinx.coroutines.debug)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import kotlin.time.Duration.Companion.seconds
*/
actual abstract class ClientLoader actual constructor(val timeoutSeconds: Int) {

@OptIn(InternalAPI::class)
private val engines: List<HttpClientEngineContainer> by lazy { loadServices<HttpClientEngineContainer>() }
private val engines: List<HttpClientEngineContainer>
get() = supportedEngines

/**
* Perform test against all clients from dependencies.
Expand Down Expand Up @@ -115,6 +115,21 @@ actual abstract class ClientLoader actual constructor(val timeoutSeconds: Int) {
}
}

@OptIn(InternalAPI::class)
private val supportedEngines by lazy {
val enginesIterator = loadServicesAsSequence<HttpClientEngineContainer>().iterator()

buildList {
while (enginesIterator.hasNext()) {
try {
add(enginesIterator.next())
} catch (_: UnsupportedClassVersionError) {
// Ignore clients compiled against newer JVM
}
}
}
}

private val OS_NAME: String
get() {
val os = System.getProperty("os.name", "unknown").lowercase(Locale.getDefault())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
/*
* Copyright 2014-2022 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.utils

import ch.qos.logback.classic.*
import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger
import io.ktor.junit.coroutines.*
import io.ktor.server.engine.*
import kotlinx.coroutines.debug.junit5.*
import org.junit.jupiter.api.*
import org.slf4j.*
import java.net.*
import java.util.concurrent.*
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.slf4j.LoggerFactory
import java.net.ServerSocket
import java.net.Socket
import java.util.concurrent.TimeUnit

@CoroutinesTimeout(5 * 60 * 1000)
abstract class TestWithKtor {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
/*
* 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.network.sockets.tests

import io.ktor.junit.*
import io.ktor.network.*
import io.ktor.junit.coroutines.*
import io.ktor.network.selector.*
import io.ktor.network.sockets.*
import io.ktor.network.sockets.Socket
import io.ktor.network.sockets.SocketImpl
import io.ktor.utils.io.*
import io.mockk.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.junit5.*
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.runBlocking
import java.net.InetSocketAddress
import java.net.ServerSocket
import java.net.SocketAddress
import java.nio.*
import java.nio.channels.*
import java.util.concurrent.*
import kotlin.concurrent.*
import kotlin.test.*
import java.nio.ByteBuffer
import java.nio.channels.ClosedChannelException
import java.nio.channels.SocketChannel
import java.util.concurrent.Executors
import kotlin.concurrent.thread
import kotlin.test.AfterTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith

@CoroutinesTimeout(5 * 60 * 1000)
@ErrorCollectorTest
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
/*
* 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.network.sockets.tests

import io.ktor.junit.coroutines.*
import io.ktor.network.selector.*
import io.ktor.network.sockets.*
import io.ktor.utils.io.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.junit5.*
import java.io.*
import java.nio.channels.*
import java.util.concurrent.*
import java.io.IOException
import java.nio.channels.CancelledKeyException
import java.nio.channels.ClosedChannelException
import java.util.concurrent.CancellationException
import kotlin.concurrent.*
import kotlin.coroutines.*
import kotlin.test.*
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors
import kotlin.concurrent.Volatile
import kotlin.concurrent.thread
import kotlin.coroutines.CoroutineContext
import kotlin.test.AfterTest
import kotlin.test.Test
import kotlin.test.assertEquals

@CoroutinesTimeout(15_000)
class ServerSocketTest : CoroutineScope {
Expand Down
5 changes: 5 additions & 0 deletions ktor-network/ktor-network-tls/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/*
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

kotlin.sourceSets {
jvmAndPosixMain {
dependencies {
Expand All @@ -8,6 +12,7 @@ kotlin.sourceSets {
}
jvmTest {
dependencies {
api(project(":ktor-shared:ktor-junit"))
api(project(":ktor-network:ktor-network-tls:ktor-network-tls-certificates"))
api(libs.netty.handler)
api(libs.mockk)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,37 @@
/*
* Copyright 2014-2023 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.
*/

// ktlint-disable experimental:argument-list-wrapping
package io.ktor.network.tls

import io.ktor.junit.coroutines.*
import io.ktor.network.selector.*
import io.ktor.network.sockets.*
import io.ktor.network.sockets.InetSocketAddress
import io.ktor.network.tls.certificates.*
import io.ktor.util.cio.*
import io.ktor.utils.io.*
import io.netty.bootstrap.*
import io.netty.channel.*
import io.netty.channel.nio.*
import io.netty.channel.socket.*
import io.netty.channel.socket.nio.*
import io.netty.handler.ssl.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.junit5.*
import java.io.*
import io.netty.bootstrap.ServerBootstrap
import io.netty.channel.ChannelInitializer
import io.netty.channel.EventLoopGroup
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.SocketChannel
import io.netty.channel.socket.nio.NioServerSocketChannel
import io.netty.handler.ssl.SslContextBuilder
import io.netty.handler.ssl.SslHandler
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import java.io.File
import java.io.IOException
import java.net.ServerSocket
import java.security.*
import java.security.cert.*
import javax.net.ssl.*
import kotlin.test.*
import java.security.KeyStore
import java.security.PrivateKey
import java.security.cert.X509Certificate
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509TrustManager
import kotlin.test.Ignore
import kotlin.test.Test
import kotlin.test.fail

@Suppress("UNCHECKED_CAST")
@CoroutinesTimeout(20_000)
Expand Down
5 changes: 5 additions & 0 deletions ktor-server/ktor-server-cio/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/*
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

description = ""

kotlin.sourceSets {
Expand All @@ -21,6 +25,7 @@ kotlin.sourceSets {
api(project(":ktor-server:ktor-server-test-base"))
api(project(":ktor-server:ktor-server-core", configuration = "testOutput"))
api(libs.logback.classic)
implementation(libs.kotlinx.coroutines.debug)
}
}
}
Loading

0 comments on commit 9df87a0

Please sign in to comment.