Skip to content

Commit

Permalink
Improve Windows tests on GitHub Workflow (#33)
Browse files Browse the repository at this point in the history
Improvements focused on improving Windows Test performance in GitHub Workflows, because currently they always fail due to OOM or weird Gradle errors (see #10)

* Update to Gradle 8.3
* Add `-XX:+AlwaysPreTouch` - see gradle/gradle#3093 (comment)
* Add 'Validate Gradle Wrapper' to GitHub Workflow
* Add `--no-parallel --no-configuration-cache --no-daemon --max-workers=1 -Dorg.gradle.workers.max=1` to Windows test to try to limit memory usage
* Update config-cache assertions to be compatible with new config-cache log messages
* (unrelated tests refactoring) use `build {}` util and refactor `dokka-worker.log` assertions
  • Loading branch information
aSemy authored Aug 20, 2023
1 parent 7660707 commit 0850e6e
Show file tree
Hide file tree
Showing 21 changed files with 526 additions and 517 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/gradle_task.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ jobs:
- name: Checkout the repo
uses: actions/checkout@v3

- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1

- name: Setup JDK 11
uses: actions/setup-java@v3
with:
Expand Down
13 changes: 11 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,17 @@ jobs:
- os: ubuntu-latest
task: "check --continue"
- os: windows-latest
# don't run integration tests on Windows because Gradle OOMs https://github.com/adamko-dev/dokkatoo/issues/10
task: "check --continue -x :modules:dokkatoo-plugin-integration-tests:check"
# don't run integration/functional tests on Windows because Gradle OOMs https://github.com/adamko-dev/dokkatoo/issues/10
task: >-
check
--continue
-x :modules:dokkatoo-plugin-integration-tests:check
-x :modules:dokkatoo-plugin:testFunctional
--no-parallel
--no-configuration-cache
--no-daemon
--max-workers=1
-Dorg.gradle.workers.max=1
fail-fast: false
uses: ./.github/workflows/gradle_task.yml
with:
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# memory is set quite high because the tests launch a lot of processes
org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Xmx4g -XX:MaxMetaspaceSize=2g -XX:+HeapDumpOnOutOfMemoryError
org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Xmx4g -XX:MaxMetaspaceSize=2g -XX:+HeapDumpOnOutOfMemoryError -XX:+AlwaysPreTouch

org.gradle.caching=true

Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
3 changes: 2 additions & 1 deletion gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
Expand Down
10 changes: 10 additions & 0 deletions modules/dokkatoo-plugin-integration-tests/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,16 @@ tasks.setupDokkaTemplateProjects.configure {
}
}

tasks.withType<Test>().configureEach {
// this seems to help OOM errors in the Worker Daemons
//setForkEvery(1)
jvmArgs(
"-Xmx1g",
"-XX:MaxMetaspaceSize=512m",
"-XX:+AlwaysPreTouch", // https://github.com/gradle/gradle/issues/3093#issuecomment-387259298
)
}

dokkaSourceDownload {
dokkaVersion.set(libs.versions.kotlin.dokka)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import io.kotest.matchers.file.shouldBeAFile
import io.kotest.matchers.file.shouldHaveSameStructureAndContentAs
import io.kotest.matchers.file.shouldHaveSameStructureAs
import io.kotest.matchers.nulls.shouldNotBeNull
import io.kotest.matchers.sequences.shouldHaveCount
import io.kotest.matchers.should
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldContain
import io.kotest.matchers.string.shouldNotContain
Expand All @@ -27,38 +25,39 @@ class CustomFormatExampleTest : FunSpec({

context("compare dokka and dokkatoo HTML generators") {
test("expect dokka can generate HTML") {
val dokkaBuild = dokkaProject.runner
dokkaProject.runner
.addArguments(
"clean",
"dokkaHtml",
"--stacktrace",
"--info",
)
.forwardOutput()
.build()

dokkaBuild.output shouldContain "BUILD SUCCESSFUL"
dokkaBuild.output shouldContain "Generation completed successfully"
.build {
output shouldContain "BUILD SUCCESSFUL"
output shouldContain "Generation completed successfully"
}
}

test("expect dokkatoo can generate HTML") {
val dokkatooBuild = dokkatooProject.runner
dokkatooProject.runner
.addArguments(
"clean",
":dokkatooGeneratePublicationHtml",
"--stacktrace",
"--info",
)
.forwardOutput()
.build()

dokkatooBuild.output shouldContain "BUILD SUCCESSFUL"

val dokkaWorkerLogs = dokkatooProject.findFiles { it.name == "dokka-worker.log" }
dokkaWorkerLogs shouldHaveCount 1
val dokkaWorkerLog = dokkaWorkerLogs.first()
dokkaWorkerLog.shouldNotBeNull().shouldBeAFile()
dokkaWorkerLog.readText() shouldContain "Generation completed successfully"
.build {
output shouldContain "BUILD SUCCESSFUL"

dokkatooProject
.findFiles { it.name == "dokka-worker.log" }
.shouldBeSingleton { dokkaWorkerLog ->
dokkaWorkerLog.shouldNotBeNull().shouldBeAFile()
dokkaWorkerLog.readText() shouldContain "Generation completed successfully"
}
}
}

context("expect dokka and dokkatoo HTML is the same") {
Expand All @@ -83,23 +82,24 @@ class CustomFormatExampleTest : FunSpec({

context("Gradle caching") {
test("expect Dokkatoo is compatible with Gradle Build Cache") {
val dokkatooBuild = dokkatooProject.runner
dokkatooProject.runner
.addArguments(
"clean",
":dokkatooGeneratePublicationHtml",
"--stacktrace",
"--info",
)
.forwardOutput()
.build()

dokkatooBuild.output shouldContain "BUILD SUCCESSFUL"

val dokkaWorkerLogs = dokkatooProject.findFiles { it.name == "dokka-worker.log" }
dokkaWorkerLogs shouldHaveCount 1
val dokkaWorkerLog = dokkaWorkerLogs.first()
dokkaWorkerLog.shouldNotBeNull().shouldBeAFile()
dokkaWorkerLog.readText() shouldContain "Generation completed successfully"
.build {
output shouldContain "BUILD SUCCESSFUL"

dokkatooProject
.findFiles { it.name == "dokka-worker.log" }
.shouldBeSingleton { dokkaWorkerLog ->
dokkaWorkerLog.shouldNotBeNull().shouldBeAFile()
dokkaWorkerLog.readText() shouldContain "Generation completed successfully"
}
}

dokkatooProject.runner
.addArguments(
Expand All @@ -109,15 +109,14 @@ class CustomFormatExampleTest : FunSpec({
"--info",
)
.forwardOutput()
.build().should { dokkatooBuildCache ->

dokkatooBuildCache.output shouldContainAll listOf(
.build {
output shouldContainAll listOf(
"> Task :dokkatooGeneratePublicationHtml UP-TO-DATE",
"BUILD SUCCESSFUL",
"1 actionable task: 1 up-to-date",
)
withClue("Dokka Generator should not be triggered, so check it doesn't log anything") {
dokkatooBuildCache.output shouldNotContain "Generation completed successfully"
output shouldNotContain "Generation completed successfully"
}
}
}
Expand All @@ -138,16 +137,17 @@ class CustomFormatExampleTest : FunSpec({
.forwardOutput()

test("first build should store the configuration cache") {
configCacheRunner.build().should { buildResult ->
buildResult.output shouldContain "BUILD SUCCESSFUL"
buildResult.output shouldContain "0 problems were found storing the configuration cache"
configCacheRunner.build {
output shouldContain "BUILD SUCCESSFUL"
output shouldContain "Configuration cache entry stored"
output shouldNotContain "problems were found storing the configuration cache"
}
}

test("second build should reuse the configuration cache") {
configCacheRunner.build().should { buildResult ->
buildResult.output shouldContain "BUILD SUCCESSFUL"
buildResult.output shouldContain "Configuration cache entry reused"
configCacheRunner.build {
output shouldContain "BUILD SUCCESSFUL"
output shouldContain "Configuration cache entry reused"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import io.kotest.matchers.file.shouldBeAFile
import io.kotest.matchers.file.shouldHaveSameStructureAndContentAs
import io.kotest.matchers.file.shouldHaveSameStructureAs
import io.kotest.matchers.nulls.shouldNotBeNull
import io.kotest.matchers.sequences.shouldHaveCount
import io.kotest.matchers.should
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldContain
import io.kotest.matchers.string.shouldNotContain
Expand All @@ -29,39 +27,39 @@ class GradleExampleTest : FunSpec({

context("compare dokka and dokkatoo HTML generators") {
test("expect dokka can generate HTML") {
val dokkaBuild = dokkaProject.runner
dokkaProject.runner
.addArguments(
"clean",
"dokkaHtml",
"--stacktrace",
"--info",
)
.forwardOutput()
.build()

dokkaBuild.output shouldContain "BUILD SUCCESSFUL"
dokkaBuild.output shouldContain "Generation completed successfully"
.build {
output shouldContain "BUILD SUCCESSFUL"
output shouldContain "Generation completed successfully"
}
}

test("expect dokkatoo can generate HTML") {
val dokkatooBuild = dokkatooProject.runner
dokkatooProject.runner
.addArguments(
"clean",
":dokkatooGeneratePublicationHtml",
"--stacktrace",
"--info",
)
.forwardOutput()
.build()


dokkatooBuild.output shouldContain "BUILD SUCCESSFUL"

val dokkaWorkerLogs = dokkatooProject.findFiles { it.name == "dokka-worker.log" }
dokkaWorkerLogs shouldHaveCount 1
val dokkaWorkerLog = dokkaWorkerLogs.first()
dokkaWorkerLog.shouldNotBeNull().shouldBeAFile()
dokkaWorkerLog.readText() shouldContain "Generation completed successfully"
.build {
output shouldContain "BUILD SUCCESSFUL"

dokkatooProject
.findFiles { it.name == "dokka-worker.log" }
.shouldBeSingleton { dokkaWorkerLog ->
dokkaWorkerLog.shouldNotBeNull().shouldBeAFile()
dokkaWorkerLog.readText() shouldContain "Generation completed successfully"
}
}
}

context("expect dokka and dokkatoo HTML is the same") {
Expand All @@ -85,23 +83,25 @@ class GradleExampleTest : FunSpec({

context("Gradle caching") {
test("expect Dokkatoo is compatible with Gradle Build Cache") {
val dokkatooBuild = dokkatooProject.runner
dokkatooProject.runner
.addArguments(
"clean",
":dokkatooGeneratePublicationHtml",
"--stacktrace",
"--info",
)
.forwardOutput()
.build()
.build {
output shouldContain "BUILD SUCCESSFUL"

dokkatooBuild.output shouldContain "BUILD SUCCESSFUL"

val dokkaWorkerLogs = dokkatooProject.findFiles { it.name == "dokka-worker.log" }
dokkaWorkerLogs shouldHaveCount 1
val dokkaWorkerLog = dokkaWorkerLogs.first()
dokkaWorkerLog.shouldNotBeNull().shouldBeAFile()
dokkaWorkerLog.readText() shouldContain "Generation completed successfully"
dokkatooProject
.findFiles { it.name == "dokka-worker.log" }
.shouldBeSingleton { dokkaWorkerLog ->
dokkaWorkerLog.shouldNotBeNull().shouldBeAFile()
dokkaWorkerLog.readText() shouldContain "Generation completed successfully"
}
}

dokkatooProject.runner
.addArguments(
Expand All @@ -111,15 +111,14 @@ class GradleExampleTest : FunSpec({
"--build-cache",
)
.forwardOutput()
.build().should { dokkatooBuildCache ->

dokkatooBuildCache.output shouldContainAll listOf(
.build {
output shouldContainAll listOf(
"> Task :dokkatooGeneratePublicationHtml UP-TO-DATE",
"BUILD SUCCESSFUL",
"1 actionable task: 1 up-to-date",
)
withClue("Dokka Generator should not be triggered, so check it doesn't log anything") {
dokkatooBuildCache.output shouldNotContain "Generation completed successfully"
output shouldNotContain "Generation completed successfully"
}
}
}
Expand All @@ -140,16 +139,17 @@ class GradleExampleTest : FunSpec({
.forwardOutput()

test("first build should store the configuration cache") {
configCacheRunner.build().should { buildResult ->
buildResult.output shouldContain "BUILD SUCCESSFUL"
buildResult.output shouldContain "0 problems were found storing the configuration cache"
configCacheRunner.build {
output shouldContain "BUILD SUCCESSFUL"
output shouldContain "Configuration cache entry stored"
output shouldNotContain "problems were found storing the configuration cache"
}
}

test("second build should reuse the configuration cache") {
configCacheRunner.build().should { buildResult ->
buildResult.output shouldContain "BUILD SUCCESSFUL"
buildResult.output shouldContain "Configuration cache entry reused"
configCacheRunner.build {
output shouldContain "BUILD SUCCESSFUL"
output shouldContain "Configuration cache entry reused"
}
}
}
Expand Down
Loading

0 comments on commit 0850e6e

Please sign in to comment.