Files

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

160 lines
6.9 KiB
Groovy
Raw Permalink Normal View History

2026-08-14 17:27:18 +02:00
import org.gradle.api.tasks.GradleBuild
import groovy.xml.XmlSlurper
apply plugin: 'scala'
SourceSet functionalTestSet
sourceSets {
functionalTestSet = create("functionalTest") {
java {
srcDir("src/functionalTest/java")
compileClasspath += sourceSets.patchedMc.output + sourceSets.main.output
}
}
}
configurations {
named(functionalTestSet.compileClasspathConfigurationName).configure {
extendsFrom(named("compileClasspath").get())
}
named(functionalTestSet.runtimeClasspathConfigurationName).configure {
extendsFrom(named("runtimeClasspath").get())
}
named(functionalTestSet.annotationProcessorConfigurationName).configure {
extendsFrom(named("annotationProcessor").get())
}
}
// FML scans classpath jars for @Mod with an ASM that predates Java 9, so every JUnit jar logs a LoaderException
// stack trace for its module-info. Repackage them into the test mod jar and keep the originals off the classpath.
def junitArtifactPrefixes = ["junit-jupiter", "junit-platform", "opentest4j", "apiguardian"]
def isJunitArtifact = { File f -> junitArtifactPrefixes.any { f.name.startsWith(it) } }
def functionalTestRuntime = configurations.named(functionalTestSet.runtimeClasspathConfigurationName)
2026-08-14 17:27:18 +02:00
tasks.register(functionalTestSet.jarTaskName, Jar) {
from(functionalTestSet.output)
from(functionalTestRuntime.map { cfg -> cfg.files.findAll(isJunitArtifact).collect { zipTree(it) } }) {
// META-INF/versions is the Java 9+ half of the multi-release jars, never loaded on this Java 8 server.
// Signatures do not survive repackaging; the engine is still found through META-INF/services.
exclude(
"module-info.class",
"META-INF/versions/**",
"META-INF/*.SF",
"META-INF/*.DSA",
"META-INF/*.RSA")
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
2026-08-14 17:27:18 +02:00
archiveClassifier.set("functionalTests")
archiveVersion.set("1.0")
destinationDirectory.set(layout.buildDirectory.dir("tmp"))
}
// Compile the documented consumer surface against the packaged dev jar, not main/test class directories.
def compileJavaApiExamples = tasks.register("compileJavaApiExamples", JavaCompile) {
group = "verification"
description = "Compiles the Java API examples against the dev jar without Scala libraries"
source(fileTree("src/test/java") { include("codechicken/**/examples/*.java") })
source(fileTree("src/functionalTest/java") { include("codechicken/**/examples/*.java") })
classpath = files(tasks.named("jar")) + sourceSets.main.compileClasspath.filter {
!it.name.startsWith("scala-")
}
destinationDirectory = layout.buildDirectory.dir("classes/java/apiExamples")
javaCompiler = javaToolchains.compilerFor { languageVersion = JavaLanguageVersion.of(8) }
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
options.encoding = "UTF-8"
options.annotationProcessorPath = files()
options.sourcepath = files()
options.compilerArgs.add("-proc:none")
}
tasks.named("check") { dependsOn(compileJavaApiExamples) }
2026-08-14 17:27:18 +02:00
def functionalTestRunProperty = "forgemultipart.withFunctionalTests"
def withFunctionalTests = providers.gradleProperty(functionalTestRunProperty).map { it.toBoolean() }.orElse(false).get()
2026-08-27 20:51:57 +03:00
def profileRunProperty = "forgemultipart.profileFunctionalTests"
def profileFunctionalTests = providers.gradleProperty(profileRunProperty).map { it.toBoolean() }.orElse(false).get()
2026-08-14 17:27:18 +02:00
def functionalTestReportDirectory = layout.projectDirectory.dir("run/server/junit-out")
2026-08-27 20:51:57 +03:00
def functionalTestProfileRecording = layout.projectDirectory.file("run/server/forgemultipart-baseline.jfr")
def functionalTestProfileResults = layout.projectDirectory.file("run/server/forgemultipart-profile.txt")
2026-08-14 17:27:18 +02:00
def addFunctionalTestsToRun = { JavaExec task ->
task.dependsOn(functionalTestSet.jarTaskName)
task.classpath(
// JUnit is repackaged into the test mod jar above.
functionalTestRuntime.map { cfg -> cfg.files.findAll { !isJunitArtifact(it) } },
2026-08-14 17:27:18 +02:00
tasks.named(functionalTestSet.jarTaskName))
}
tasks.register("runFunctionalTestServer", GradleBuild) {
group = "verification"
description = "Runs the Java 8 Forge server with the ForgeMultipart functional test mod"
setTasks(["runServer"])
startParameter.projectProperties.put(functionalTestRunProperty, "true")
2026-08-27 20:51:57 +03:00
if (profileFunctionalTests) {
startParameter.projectProperties.put(profileRunProperty, "true")
}
2026-08-14 17:27:18 +02:00
doFirst {
delete(functionalTestReportDirectory)
2026-08-27 20:51:57 +03:00
if (profileFunctionalTests) {
delete(functionalTestProfileRecording, functionalTestProfileResults)
}
2026-08-14 17:27:18 +02:00
}
doLast {
def reports = fileTree(functionalTestReportDirectory).matching { include("TEST-*.xml") }.files
if (reports.isEmpty()) {
throw new GradleException("ForgeMultipart functional tests produced no JUnit XML report")
}
int tests = 0
int failures = 0
int errors = 0
int skipped = 0
def failed = []
2026-08-14 17:27:18 +02:00
reports.each { report ->
def suite = new XmlSlurper(false, false).parse(report)
tests += suite.@tests.toInteger()
failures += suite.@failures.toInteger()
errors += suite.@errors.toInteger()
skipped += suite.@skipped.toString().isEmpty() ? 0 : suite.@skipped.toInteger()
suite.testcase.each { testcase ->
if (!testcase.failure.isEmpty() || !testcase.error.isEmpty()) {
failed << "${testcase.@classname}.${testcase.@name}"
}
}
2026-08-14 17:27:18 +02:00
}
def summary = "Forge functional tests: ${tests} tests, ${tests - failures - errors - skipped} passed, " +
"${failures} failures, ${errors} errors, ${skipped} skipped"
logger.lifecycle(summary)
failed.each { logger.lifecycle(" FAILED ${it}") }
def stepSummary = System.getenv("GITHUB_STEP_SUMMARY")
if (stepSummary) {
new File(stepSummary) << "### ${summary}\n" + failed.collect { "- FAILED `${it}`\n" }.join()
}
2026-08-14 17:27:18 +02:00
if (tests == 0 || failures > 0 || errors > 0) {
throw new GradleException("ForgeMultipart functional tests failed: ${summary}")
2026-08-14 17:27:18 +02:00
}
2026-08-27 20:51:57 +03:00
if (profileFunctionalTests
&& (!functionalTestProfileRecording.asFile.isFile() || !functionalTestProfileResults.asFile.isFile())) {
throw new GradleException("ForgeMultipart profile produced incomplete output")
}
2026-08-14 17:27:18 +02:00
}
}
if (withFunctionalTests) {
tasks.withType(JavaExec).configureEach { task ->
if (task.name == "runServer") {
addFunctionalTestsToRun(task)
2026-08-27 20:51:57 +03:00
if (profileFunctionalTests) {
task.jvmArgs(
"-XX:+FlightRecorder",
"-XX:StartFlightRecording=filename=forgemultipart-baseline.jfr,settings=profile,dumponexit=true")
task.systemProperty(profileRunProperty, "true")
}
2026-08-14 17:27:18 +02:00
}
}
}