Skip to content

Commit

Permalink
Restructure Gradle Integration tests to use Java Test Suites
Browse files Browse the repository at this point in the history
- create a test suite for each project under test (helps with Gradle caching, task avoidance)
- update CI/CD tasks to run specific test-suite tasks
- disable integration test tasks due to dependency on Maven Local publishing (this will be fixed in an upcoming PR)
  • Loading branch information
adam-enko committed Jan 15, 2024
1 parent 7af0394 commit 10fe4b5
Show file tree
Hide file tree
Showing 37 changed files with 239 additions and 54 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/preview-publish-ga.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
uses: gradle/gradle-build-action@v2
with:
gradle-home-cache-cleanup: true
arguments: :dokka-integration-tests:gradle:integrationTest --tests org.jetbrains.dokka.it.gradle.kotlin.CoroutinesGradleIntegrationTest --stacktrace "-Dorg.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=500m"
arguments: :dokka-integration-tests:gradle:testExternalProjectKotlinxCoroutines --stacktrace "-Dorg.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=500m"
env:
DOKKA_TEST_OUTPUT_PATH: /home/runner/work/dokka/coroutines
- name: Copy files to GitHub Actions Artifacts
Expand Down Expand Up @@ -56,7 +56,7 @@ jobs:
uses: gradle/gradle-build-action@v2
with:
gradle-home-cache-cleanup: true
arguments: :dokka-integration-tests:gradle:integrationTest --tests org.jetbrains.dokka.it.gradle.kotlin.SerializationGradleIntegrationTest --stacktrace "-Dorg.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=500m"
arguments: :dokka-integration-tests:gradle:testExternalProjectKotlinxSerialization --stacktrace "-Dorg.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=500m"
env:
DOKKA_TEST_OUTPUT_PATH: /home/runner/work/dokka/serialization
- name: Copy files to GitHub Actions Artifacts
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/preview-publish-web-s3.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
uses: gradle/gradle-build-action@v2
with:
gradle-home-cache-cleanup: true
arguments: :dokka-integration-tests:gradle:integrationTest --tests org.jetbrains.dokka.it.gradle.kotlin.CoroutinesGradleIntegrationTest --stacktrace "-Dorg.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=500m"
arguments: :dokka-integration-tests:gradle:testExternalProjectKotlinxCoroutines --stacktrace "-Dorg.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=500m"
env:
DOKKA_TEST_OUTPUT_PATH: /home/runner/work/dokka/coroutines
- name: Configure AWS credentials for S3 access
Expand All @@ -38,7 +38,7 @@ jobs:
- name: Print link
run: echo https://dokka-snapshots.s3.eu-central-1.amazonaws.com/${{ env.branch-name }}/coroutines/${GITHUB_SHA::7}/index.html

kotilnx-serialization:
kotlinx-serialization:
runs-on: ubuntu-latest
if: github.repository == 'Kotlin/dokka'
steps:
Expand All @@ -55,7 +55,7 @@ jobs:
uses: gradle/gradle-build-action@v2
with:
gradle-home-cache-cleanup: true
arguments: :dokka-integration-tests:gradle:integrationTest --tests org.jetbrains.dokka.it.gradle.kotlin.SerializationGradleIntegrationTest --stacktrace "-Dorg.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=500m"
arguments: :dokka-integration-tests:gradle:testExternalProjectKotlinxSerialization --stacktrace "-Dorg.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=500m"
env:
DOKKA_TEST_OUTPUT_PATH: /home/runner/work/dokka/serialization
- name: Configure AWS credentials for S3 access
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ jobs:
# Running tests with the Gradle daemon on windows agents leads to some very strange
# JVM crashes for some reason. Most likely a problem of Gradle/GitHub/Windows server
run: >
./gradlew test --stacktrace --no-daemon --no-parallel
./gradlew check --stacktrace --no-daemon --no-parallel
"-Dorg.gradle.jvmargs=-Xmx1g -XX:MaxMetaspaceSize=500m"
"-Porg.jetbrains.dokka.javaToolchain.testLauncher=${{ env.JAVA_TEST_VERSION }}"
- name: Run tests under Ubuntu
if: matrix.os != 'windows-latest'
run: >
./gradlew test --stacktrace
./gradlew check --stacktrace
"-Porg.jetbrains.dokka.javaToolchain.testLauncher=${{ env.JAVA_TEST_VERSION }}"
4 changes: 2 additions & 2 deletions .github/workflows/tests-thorough.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ jobs:
# Running tests with the Gradle daemon on windows agents leads to some very strange
# JVM crashes for some reason. Most likely a problem of Gradle/GitHub/Windows server
run: >
./gradlew test --stacktrace --no-daemon --no-parallel
./gradlew check --stacktrace --no-daemon --no-parallel --continue
"-Dorg.gradle.jvmargs=-Xmx1g -XX:MaxMetaspaceSize=500m"
"-Porg.jetbrains.dokka.javaToolchain.testLauncher=${{ matrix.javaVersion }}"
- name: Run tests under Ubuntu/Macos
if: matrix.os != 'windows-latest'
run: >
./gradlew test --stacktrace
./gradlew check --stacktrace --continue
"-Porg.jetbrains.dokka.javaToolchain.testLauncher=${{ matrix.javaVersion }}"
1 change: 0 additions & 1 deletion build-logic/src/main/kotlin/dokkabuild.base.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/*
* Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

import dokkabuild.DokkaBuildProperties
import org.gradle.language.base.plugins.LifecycleBasePlugin.VERIFICATION_GROUP

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ val installMavenBinary by tasks.registering(Sync::class) {
val archives = serviceOf<ArchiveOperations>()
from(
mavenBinary.flatMap { conf ->
@Suppress("UnstableApiUsage")
val resolvedArtifacts = conf.incoming.artifacts.resolvedArtifacts

resolvedArtifacts.map { artifacts ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ abstract class DokkaBuildProperties @Inject constructor(
private val providers: ProviderFactory,
) {

val isCI: Provider<Boolean> =
providers.environmentVariable("CI").map(String::toBoolean).orElse(false)

/**
* The main version of Java that should be used to build Dokka source code.
*
Expand Down
4 changes: 4 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ plugins {
id("dokkabuild.base")
}

tasks.check {
dependsOn(gradle.includedBuild("dokka-integration-tests").task(":gradle:check"))
}

val publishedIncludedBuilds = listOf("runner-cli", "runner-gradle-plugin-classic", "runner-maven-plugin")
val gradlePluginIncludedBuilds = listOf("runner-gradle-plugin-classic")

Expand Down
4 changes: 2 additions & 2 deletions dokka-integration-tests/gradle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Integration tests have fixed git revision number, with the diff patch applied fr

In order to update:

* Checkout the project with the requered revision
* Checkout the project with the required revision
- It's some state of the `master`
* Manually write the diff (or apply the existing one and tweak) to have the project buildable against locally published Dokka of version `for-integration-tests-SNAPSHOT`
* `git diff > $pathToProjectInDokka/project.diff`
Expand All @@ -26,4 +26,4 @@ In order to update:
### Run integration tests with K2 (symbols)

To run integration tests with K2, the property `org.jetbrains.dokka.integration_test.useK2` should be set to `true`.
By default, the task `integrationTest` is run with K1 (descriptors).
By default, the integration tests are run with K1 (descriptors).
206 changes: 188 additions & 18 deletions dokka-integration-tests/gradle/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,43 +1,213 @@
import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode

/*
* Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
import org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
import org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED
import org.gradle.api.tasks.testing.logging.TestLogEvent.SKIPPED
import org.gradle.language.base.plugins.LifecycleBasePlugin.VERIFICATION_GROUP
import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode.Disabled

plugins {
id("dokkabuild.test-integration")
id("dokkabuild.kotlin-jvm")
`test-suite-base`
`java-test-fixtures`
}

dependencies {
implementation(projects.utilities)
api(projects.utilities)

api(libs.jsoup)

implementation(kotlin("test-junit5"))
implementation(libs.junit.jupiterApi)
implementation(libs.junit.jupiterParams)
api(libs.kotlin.test)
api(libs.junit.jupiterApi)
api(libs.junit.jupiterParams)

implementation(gradleTestKit())
api(gradleTestKit())
}

kotlin {
explicitApi = Disabled

implementation(libs.jsoup)
compilerOptions {
allWarningsAsErrors = false
optIn.add("kotlin.io.path.ExperimentalPathApi")
}
}

kotlin {
// this project only contains test utils and isn't published, so it doesn't matter about explicit API
explicitApi = ExplicitApiMode.Disabled
explicitApi = Disabled
}

val aggregatingProject = gradle.includedBuild("dokka")

tasks.integrationTest {
tasks.integrationTestPreparation {
dependsOn(aggregatingProject.task(":publishToMavenLocal"))
}

tasks.withType<Test>().configureEach {
dependsOn(tasks.integrationTestPreparation)

environment("DOKKA_VERSION", project.version)

inputs.dir(file("projects"))
maxHeapSize = "2G"

val useK2 = dokkaBuild.integrationTestUseK2.get()

useJUnitPlatform {
if (useK2) excludeTags("onlyDescriptors", "onlyDescriptorsMPP")
}

systemProperty("org.jetbrains.dokka.experimental.tryK2", useK2)

setForkEvery(1)
dokkaBuild.integrationTestParallelism.orNull?.let {
maxParallelForks = it
}

environment("isExhaustive", dokkaBuild.integrationTestExhaustive)

// allow inspecting projects in temporary dirs after a test fails
systemProperty(
"junit.jupiter.tempdir.cleanup.mode.default",
dokkaBuild.isCI.map { isCi -> if (isCi) "ALWAYS" else "ON_SUCCESS" }.get(),
)

testLogging {
exceptionFormat = FULL
events(SKIPPED, FAILED)
showExceptions = true
showCauses = true
showStackTraces = true
}

doNotTrackState("uses artifacts from Maven Local")
}

val templateProjectsDir = layout.projectDirectory.dir("projects")

@Suppress("UnstableApiUsage")
testing {
suites {
withType<JvmTestSuite>().configureEach {
useJUnitJupiter()

dependencies {
implementation(project())
}

targets.configureEach {
testTask.configure {
doFirst {
logger.lifecycle("running $path with javaLauncher:${javaLauncher.orNull?.metadata?.javaRuntimeVersion}")
}
}
}
}

/**
* Create a new [JvmTestSuite] for a Gradle project.
*
* @param[projectPath] path to the Gradle project that will be tested by this suite, relative to [templateProjectsDir].
* The directory will be passed as a system property, `templateProjectDir`.
*/
fun registerTestProjectSuite(
name: String,
projectPath: String,
jvm: JavaLanguageVersion? = null,
configure: JvmTestSuite.() -> Unit = {},
) {
val templateProjectDir = templateProjectsDir.dir(projectPath)

register<JvmTestSuite>(name) {
targets.configureEach {
testTask.configure {
// Register the project dir as a specific input, so changes in other projects don't affect the caching of this test
inputs.dir(templateProjectDir)
// Pass the template dir in as a property, it is accessible in tests.
systemProperty("templateProjectDir", templateProjectDir.asFile.invariantSeparatorsPath)

if (jvm != null) {
javaLauncher = javaToolchains.launcherFor { languageVersion = jvm }
}
}
}
configure()
}
}

// register a separate test suite for each template project, to help with Gradle caching
registerTestProjectSuite(
"testTemplateProjectAndroid",
"it-android-0",
jvm = JavaLanguageVersion.of(11), // AGP requires JVM 11+
)
registerTestProjectSuite("testTemplateProjectBasic", "it-basic")
registerTestProjectSuite("testTemplateProjectBasicGroovy", "it-basic-groovy")
registerTestProjectSuite("testTemplateProjectCollector", "it-collector-0")
registerTestProjectSuite("testTemplateProjectConfiguration", "it-configuration")
registerTestProjectSuite("testTemplateProjectJsIr", "it-js-ir-0")
registerTestProjectSuite("testTemplateProjectMultimodule0", "it-multimodule-0")
registerTestProjectSuite("testTemplateProjectMultimodule1", "it-multimodule-1")
registerTestProjectSuite("testTemplateProjectMultimoduleVersioning", "it-multimodule-versioning-0")
registerTestProjectSuite("testTemplateProjectMultiplatform", "it-multiplatform-0")
registerTestProjectSuite("testTemplateProjectTasksExecutionStress", "it-sequential-tasks-execution-stress")
registerTestProjectSuite("testTemplateProjectWasmBasic", "it-wasm-basic")
registerTestProjectSuite("testTemplateProjectWasmJsWasiBasic", "it-wasm-js-wasi-basic")

registerTestProjectSuite(
"testExternalProjectKotlinxCoroutines",
"coroutines/kotlinx-coroutines",
jvm = JavaLanguageVersion.of(11) // kotlinx.coroutines requires JVM 11+ https://github.com/Kotlin/kotlinx.coroutines/issues/3665
) {
targets.configureEach {
testTask.configure {
// register the whole directory as an input because it contains the git diff
inputs.dir(templateProjectsDir.file("coroutines"))
}
}
}
registerTestProjectSuite("testExternalProjectKotlinxSerialization", "serialization/kotlinx-serialization") {
targets.configureEach {
testTask.configure {
// register the whole directory as an input because it contains the git diff
inputs.dir(templateProjectsDir.file("serialization"))
}
}
}
}
tasks.check {
dependsOn(suites)
}
}

//region project tests management

// set up task ordering - template projects (which are generally faster) should be tested before external projects
val testTemplateProjectsTasks = tasks.withType<Test>().matching { it.name.startsWith("testTemplateProject") }
val testExternalProjectsTasks = tasks.withType<Test>().matching { it.name.startsWith("testExternalProject") }

testTemplateProjectsTasks.configureEach {
shouldRunAfter(tasks.test)
}
testExternalProjectsTasks.configureEach {
shouldRunAfter(tasks.test)
shouldRunAfter(testTemplateProjectsTasks)
}

// define lifecycle tasks for project tests
val testAllTemplateProjects by tasks.registering {
description = "Lifecycle task for running all template-project tests"
group = VERIFICATION_GROUP
dependsOn(testTemplateProjectsTasks)
doNotTrackState("lifecycle task, should always run")
}

javaLauncher.set(javaToolchains.launcherFor {
// kotlinx.coroutines requires Java 11+
languageVersion.set(dokkaBuild.testJavaLauncherVersion.map {
maxOf(it, JavaLanguageVersion.of(11))
})
})
val testAllExternalProjects by tasks.registering {
description = "Lifecycle task for running all external-project tests"
group = VERIFICATION_GROUP
shouldRunAfter(testAllTemplateProjects)
dependsOn(testExternalProjectsTasks)
doNotTrackState("lifecycle task, should always run")
}
//endregion
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ package org.jetbrains.dokka.it.gradle

import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.GradleRunner
import org.gradle.testkit.runner.internal.DefaultGradleRunner
import org.gradle.tooling.GradleConnectionException
import org.gradle.util.GradleVersion
import org.jetbrains.dokka.it.AbstractIntegrationTest
import org.jetbrains.dokka.it.withJvmArguments
import java.io.File
import java.net.URI
import kotlin.test.BeforeTest
Expand Down Expand Up @@ -50,8 +50,7 @@ abstract class AbstractGradleIntegrationTest : AbstractIntegrationTest() {

* arguments
)
).run { this as DefaultGradleRunner }
.withJvmArguments(jvmArgs)
).withJvmArguments(jvmArgs)
}

fun GradleRunner.buildRelaxed(): BuildResult {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.ArgumentsProvider
import java.util.stream.Stream

internal class LatestTestedVersionsArgumentsProvider : TestedVersionsArgumentsProvider(listOf(TestedVersions.LATEST))
internal open class AllSupportedTestedVersionsArgumentsProvider : TestedVersionsArgumentsProvider(TestedVersions.ALL_SUPPORTED)
class LatestTestedVersionsArgumentsProvider : TestedVersionsArgumentsProvider(listOf(TestedVersions.LATEST))
open class AllSupportedTestedVersionsArgumentsProvider : TestedVersionsArgumentsProvider(TestedVersions.ALL_SUPPORTED)

internal object TestedVersions {
object TestedVersions {

val LATEST = BuildVersions("7.6.2", "1.9.22")

Expand Down
Loading

0 comments on commit 10fe4b5

Please sign in to comment.