From 3ded0964c4282060ca9f50ef9db908d83b30e443 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Tue, 31 Aug 2021 11:48:58 +0100 Subject: [PATCH] Refactor and improve tests (#466) * Install and run a production server in tests * Small improvements * Add FabricAPI build test Create new GradleProjectTestTrait replacing the old trait Improve groovy code formatting. * Refactor tests * Fix MultiProjectTest + fix logging for fabric api test * Cleanup and fixes * Update fabric api + run in parallel for speed * Set server memory + fix error --- build.gradle | 1 + codenarc.groovy | 9 +- .../loom/build/MixinRefmapHelper.java | 10 +- .../MinecraftProcessedProvider.java | 14 +- ...sTrait.groovy => LoomTestConstants.groovy} | 28 +-- .../test/integration/AccessWidenerTest.groovy | 23 +- .../integration/CustomManifestTest.groovy | 48 ++-- .../test/integration/DecompileTest.groovy | 19 +- .../DependencyResolutionManagementTest.groovy | 22 +- .../ExperimentalVersionsTest.groovy | 42 ++-- .../test/integration/FabricAPITest.groovy | 69 ++++++ .../test/integration/Java16ProjectTest.groovy | 23 +- .../loom/test/integration/KotlinTest.groovy | 24 +- .../test/integration/LegacyProjectTest.groovy | 21 +- .../LocalFileDependencyTest.groovy | 23 +- .../test/integration/MavenProjectTest.groovy | 41 ++-- .../integration/MixinApAutoRefmapTest.groovy | 55 +++-- .../test/integration/MixinApSimpleTest.groovy | 40 ++-- .../MojangMappingsProjectTest.groovy | 23 +- .../test/integration/MultiProjectTest.groovy | 29 ++- .../test/integration/ParchmentTest.groovy | 21 +- .../integration/ReproducibleBuildTest.groovy | 29 ++- .../test/integration/RunConfigTest.groovy | 18 +- .../test/integration/SignedProjectTest.groovy | 25 +-- .../test/integration/SimpleProjectTest.groovy | 42 ++-- .../loom/test/integration/UnpickTest.groovy | 37 ++-- .../LayeredMappingsSpecification.groovy | 1 - .../LayeredMappingsTestConstants.groovy | 8 +- .../ParchmentMappingLayerTest.groovy | 1 - .../test/util/GradleProjectTestTrait.groovy | 203 +++++++++++++++++ .../test/util/MockMavenServerTrait.groovy | 3 +- .../loom/test/util/ProjectTestTrait.groovy | 126 ----------- .../loom/test/util/ServerRunner.groovy | 208 ++++++++++++++++++ .../java/net/fabricmc/example/ExampleMod.java | 2 +- 34 files changed, 807 insertions(+), 481 deletions(-) rename src/test/groovy/net/fabricmc/loom/test/{util/ArchiveAssertionsTrait.groovy => LoomTestConstants.groovy} (65%) create mode 100644 src/test/groovy/net/fabricmc/loom/test/integration/FabricAPITest.groovy create mode 100644 src/test/groovy/net/fabricmc/loom/test/util/GradleProjectTestTrait.groovy delete mode 100644 src/test/groovy/net/fabricmc/loom/test/util/ProjectTestTrait.groovy create mode 100644 src/test/groovy/net/fabricmc/loom/test/util/ServerRunner.groovy diff --git a/build.gradle b/build.gradle index 4d0502a..589c099 100644 --- a/build.gradle +++ b/build.gradle @@ -104,6 +104,7 @@ dependencies { exclude module: 'groovy-all' } testImplementation 'io.javalin:javalin:3.13.9' + testImplementation 'net.fabricmc:fabric-installer:0.7.4' compileOnly 'org.jetbrains:annotations:21.0.1' } diff --git a/codenarc.groovy b/codenarc.groovy index 9f15eb6..3ee57eb 100644 --- a/codenarc.groovy +++ b/codenarc.groovy @@ -24,7 +24,7 @@ ruleset { SpaceAfterSwitch SpaceAfterWhile SpaceAroundClosureArrow - SpaceAroundMapEntryColon + SpaceAroundMapEntryColon(characterAfterColonRegex: /\ /) SpaceAroundOperator SpaceBeforeClosingBrace SpaceBeforeOpeningBrace @@ -61,6 +61,13 @@ ruleset { FieldTypeRequired MethodParameterTypeRequired + // Imports + UnusedImport + UnnecessaryGroovyImport + NoWildcardImports(ignoreStaticImports: true) + ImportFromSamePackage + DuplicateImport + //Misc LongLiteralWithLowerCaseL } diff --git a/src/main/java/net/fabricmc/loom/build/MixinRefmapHelper.java b/src/main/java/net/fabricmc/loom/build/MixinRefmapHelper.java index 4fc8de8..7705321 100644 --- a/src/main/java/net/fabricmc/loom/build/MixinRefmapHelper.java +++ b/src/main/java/net/fabricmc/loom/build/MixinRefmapHelper.java @@ -29,6 +29,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.nio.file.Path; import java.util.Collection; +import java.util.Collections; import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -36,6 +37,7 @@ import java.util.stream.StreamSupport; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import org.gradle.api.Project; @@ -108,7 +110,13 @@ public final class MixinRefmapHelper { @NotNull private static Collection getMixinConfigurationFiles(JsonObject fabricModJson) { - return StreamSupport.stream(fabricModJson.getAsJsonArray("mixins").spliterator(), false) + JsonArray mixins = fabricModJson.getAsJsonArray("mixins"); + + if (mixins == null) { + return Collections.emptyList(); + } + + return StreamSupport.stream(mixins.spliterator(), false) .map(e -> { if (e instanceof JsonPrimitive str) { return str.getAsString(); diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/MinecraftProcessedProvider.java b/src/main/java/net/fabricmc/loom/configuration/processors/MinecraftProcessedProvider.java index 989c593..fc8aa86 100644 --- a/src/main/java/net/fabricmc/loom/configuration/processors/MinecraftProcessedProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/processors/MinecraftProcessedProvider.java @@ -54,7 +54,7 @@ public class MinecraftProcessedProvider extends MinecraftMappedProvider { protected void addDependencies(DependencyInfo dependency, Consumer postPopulationScheduler) { if (jarProcessorManager.isInvalid(projectMappedJar) || isRefreshDeps()) { getProject().getLogger().info(":processing mapped jar"); - invalidateJars(); + invalidateJar(); try { FileUtils.copyFile(super.getMappedJar(), projectMappedJar); @@ -69,16 +69,14 @@ public class MinecraftProcessedProvider extends MinecraftMappedProvider { getProject().getDependencies().module("net.minecraft:minecraft-" + projectMappedClassifier + ":" + getMinecraftProvider().minecraftVersion() + "/" + getExtension().getMappingsProvider().mappingsIdentifier())); } - private void invalidateJars() { - File dir = projectMappedJar.getParentFile(); - - if (dir.exists()) { - getProject().getLogger().warn("Invalidating project jars"); + private void invalidateJar() { + if (projectMappedJar.exists()) { + getProject().getLogger().warn("Invalidating project jar"); try { - FileUtils.cleanDirectory(dir); + FileUtils.forceDelete(projectMappedJar); } catch (IOException e) { - throw new RuntimeException("Failed to invalidate jars, try stopping gradle daemon or closing the game", e); + throw new RuntimeException("Failed to invalidate jar, try stopping gradle daemon or closing the game", e); } } } diff --git a/src/test/groovy/net/fabricmc/loom/test/util/ArchiveAssertionsTrait.groovy b/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy similarity index 65% rename from src/test/groovy/net/fabricmc/loom/test/util/ArchiveAssertionsTrait.groovy rename to src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy index fc8dba5..c63f614 100644 --- a/src/test/groovy/net/fabricmc/loom/test/util/ArchiveAssertionsTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2016-2021 FabricMC + * Copyright (c) 2021 FabricMC * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,25 +22,11 @@ * SOFTWARE. */ -package net.fabricmc.loom.test.util +package net.fabricmc.loom.test -import org.zeroturnaround.zip.ZipUtil +class LoomTestConstants { + public final static String DEFAULT_GRADLE = "7.0.1" + public final static String PRE_RELEASE_GRADLE = "7.3-20210827230026+0000" -trait ArchiveAssertionsTrait { - String getArchiveEntry(String name, String entry, String project = "") { - def file = getOutputFile(name, project) - - def bytes = ZipUtil.unpackEntry(file, entry) - - if (bytes == null) { - throw new FileNotFoundException("Could not find ${entry} in ${name}") - } - - new String(bytes as byte[]) - } - - boolean hasArchiveEntry(String name, String entry, String project = "") { - def file = getOutputFile(name, project) - ZipUtil.unpackEntry(file, entry) != null - } -} \ No newline at end of file + public final static String[] STANDARD_TEST_VERSIONS = [DEFAULT_GRADLE, PRE_RELEASE_GRADLE] +} diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/AccessWidenerTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/AccessWidenerTest.groovy index cf65dff..8fed624 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/AccessWidenerTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/AccessWidenerTest.groovy @@ -24,30 +24,25 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ArchiveAssertionsTrait -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait import spock.lang.Specification import spock.lang.Unroll +import static net.fabricmc.loom.test.LoomTestConstants.* import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -class AccessWidenerTest extends Specification implements ProjectTestTrait, ArchiveAssertionsTrait { - @Override - String name() { - "accesswidener" - } - +class AccessWidenerTest extends Specification implements GradleProjectTestTrait { @Unroll - def "accesswidener (gradle #gradle)"() { + def "accesswidener (gradle #version)"() { + setup: + def gradle = gradleProject(project: "accesswidener", version: version) when: - def result = create("build", gradle) + def result = gradle.run(task: "build") then: result.task(":build").outcome == SUCCESS - getArchiveEntry("fabric-example-mod-1.0.0.jar", "modid.accesswidener") == expected().replaceAll('\r', '') + gradle.getOutputZipEntry("fabric-example-mod-1.0.0.jar", "modid.accesswidener") == expected().replaceAll('\r', '') where: - gradle | _ - DEFAULT_GRADLE | _ - PRE_RELEASE_GRADLE | _ + version << STANDARD_TEST_VERSIONS } String expected() { diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/CustomManifestTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/CustomManifestTest.groovy index f6ee1f0..eb73270 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/CustomManifestTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/CustomManifestTest.groovy @@ -24,42 +24,36 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait import spock.lang.Specification import spock.lang.Unroll +import static net.fabricmc.loom.test.LoomTestConstants.* import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -class CustomManifestTest extends Specification implements ProjectTestTrait { - @Override - String name() { - "minimalBase" - } - - @Override - def filesReady() { - buildGradle() << ''' - loom { - customMinecraftManifest = "https://maven.fabricmc.net/net/minecraft/1_18_experimental-snapshot-1.json" - } - - dependencies { - minecraft "com.mojang:minecraft:1.18_experimental-snapshot-1" - mappings "net.fabricmc:yarn:1.18_experimental-snapshot-1+build.2:v2" - modImplementation "net.fabricmc:fabric-loader:0.11.6" - } - ''' - } - +class CustomManifestTest extends Specification implements GradleProjectTestTrait { @Unroll - def "customManifest (gradle #gradle)"() { + def "customManifest (gradle #version)"() { + setup: + def gradle = gradleProject(project: "minimalBase", version: version) + gradle.buildGradle << ''' + loom { + customMinecraftManifest = "https://maven.fabricmc.net/net/minecraft/1_18_experimental-snapshot-1.json" + } + + dependencies { + minecraft "com.mojang:minecraft:1.18_experimental-snapshot-1" + mappings "net.fabricmc:yarn:1.18_experimental-snapshot-1+build.2:v2" + modImplementation "net.fabricmc:fabric-loader:0.11.6" + } + ''' when: - def result = create("build", gradle) + def result = gradle.run(task: "build") + then: result.task(":build").outcome == SUCCESS + where: - gradle | _ - DEFAULT_GRADLE | _ - PRE_RELEASE_GRADLE | _ + version << STANDARD_TEST_VERSIONS } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/DecompileTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/DecompileTest.groovy index 4423091..239fa63 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/DecompileTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/DecompileTest.groovy @@ -24,28 +24,27 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait import spock.lang.Specification import spock.lang.Unroll +import static net.fabricmc.loom.test.LoomTestConstants.* import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -class DecompileTest extends Specification implements ProjectTestTrait { - @Override - String name() { - "decompile" - } - +class DecompileTest extends Specification implements GradleProjectTestTrait { @Unroll - def "#decompiler gradle #gradle"() { + def "#decompiler gradle #version"() { + setup: + def gradle = gradleProject(project: "decompile", version: version) + when: - def result = create(task, gradle) + def result = gradle.run(task: task) then: result.task(":${task}").outcome == SUCCESS where: - decompiler | task | gradle + decompiler | task | version 'fernflower' | "genSources" | DEFAULT_GRADLE 'fernflower' | "genSources" | PRE_RELEASE_GRADLE 'cfr' | "genSourcesWithExperimentalCfr" | DEFAULT_GRADLE diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/DependencyResolutionManagementTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/DependencyResolutionManagementTest.groovy index 7717c2a..fb49db3 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/DependencyResolutionManagementTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/DependencyResolutionManagementTest.groovy @@ -24,29 +24,27 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait import spock.lang.Specification import spock.lang.Unroll +import static net.fabricmc.loom.test.LoomTestConstants.* import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -class DependencyResolutionManagementTest extends Specification implements ProjectTestTrait { - @Override - String name() { - "dependencyResolutionManagement" - } - +class DependencyResolutionManagementTest extends Specification implements GradleProjectTestTrait { @Unroll - def "build (gradle #gradle)"() { + def "build (gradle #version)"() { + setup: + def gradle = gradleProject(project: "dependencyResolutionManagement", version: version) + when: - def result = create("build", gradle) + def result = gradle.run(task: "build") + then: result.task(":basic:build").outcome == SUCCESS result.task(":projmap:build").outcome == SUCCESS where: - gradle | _ - DEFAULT_GRADLE | _ - PRE_RELEASE_GRADLE | _ + version << STANDARD_TEST_VERSIONS } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/ExperimentalVersionsTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/ExperimentalVersionsTest.groovy index 553cbd7..a95073e 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/ExperimentalVersionsTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/ExperimentalVersionsTest.groovy @@ -24,38 +24,34 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait import spock.lang.Specification import spock.lang.Unroll +import static net.fabricmc.loom.test.LoomTestConstants.* import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -class ExperimentalVersionsTest extends Specification implements ProjectTestTrait { - @Override - String name() { - "minimalBase" - } - - @Override - def filesReady() { - buildGradle() << ''' - dependencies { - minecraft "com.mojang:minecraft:1.18_experimental-snapshot-1" - mappings "net.fabricmc:yarn:1.18_experimental-snapshot-1+build.2:v2" - modImplementation "net.fabricmc:fabric-loader:0.11.6" - } - ''' - } - +class ExperimentalVersionsTest extends Specification implements GradleProjectTestTrait { @Unroll - def "experimental versions (gradle #gradle)"() { + def "experimental versions (gradle #version)"() { + setup: + def gradle = gradleProject(project: "minimalBase", version: version) + + gradle.buildGradle << ''' + dependencies { + minecraft "com.mojang:minecraft:1.18_experimental-snapshot-1" + mappings "net.fabricmc:yarn:1.18_experimental-snapshot-1+build.2:v2" + modImplementation "net.fabricmc:fabric-loader:0.11.6" + } + ''' + when: - def result = create("build", gradle) + def result = gradle.run(task: "build") + then: result.task(":build").outcome == SUCCESS + where: - gradle | _ - DEFAULT_GRADLE | _ - PRE_RELEASE_GRADLE | _ + version << STANDARD_TEST_VERSIONS } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/FabricAPITest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/FabricAPITest.groovy new file mode 100644 index 0000000..dee1b8b --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/integration/FabricAPITest.groovy @@ -0,0 +1,69 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2021 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.test.integration + +import net.fabricmc.loom.test.util.GradleProjectTestTrait +import net.fabricmc.loom.test.util.ServerRunner +import spock.lang.Specification +import spock.lang.Timeout +import spock.lang.Unroll + +import java.util.concurrent.TimeUnit + +import static net.fabricmc.loom.test.LoomTestConstants.* +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +@Timeout(value = 30, unit = TimeUnit.MINUTES) +class FabricAPITest extends Specification implements GradleProjectTestTrait { + private static final String API_VERSION = "0.0.0+loom" + + @Unroll + def "build and run (gradle #version)"() { + setup: + def gradle = gradleProject( + repo: "https://github.com/modmuss50/fabric.git", + commit: "cb31cccd34cb91f70cae6bac80208f5ec3650f33", + version: version + ) + + // Set the version to something constant + gradle.buildGradle.text = gradle.buildGradle.text.replace('Globals.baseVersion + "+" + (ENV.GITHUB_RUN_NUMBER ? "" : "local-") + getBranch()', "\"$API_VERSION\"") + + def server = ServerRunner.create(gradle.projectDir, "1.17.1") + .withMod(gradle.getOutputFile("fabric-api-${API_VERSION}.jar")) + when: + def result = gradle.run(tasks: ["build", "publishToMavenLocal"], args: ["--parallel", "-x", "check"]) // Note: checkstyle does not appear to like being ran in a test runner + gradle.printOutputFiles() + + def serverResult = server.run() + then: + result.task(":build").outcome == SUCCESS + + serverResult.successful() + serverResult.output.contains("fabric@$API_VERSION") + where: + version << STANDARD_TEST_VERSIONS + } +} diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/Java16ProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/Java16ProjectTest.groovy index 90922f5..54f5296 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/Java16ProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/Java16ProjectTest.groovy @@ -24,27 +24,26 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait import spock.lang.Specification import spock.lang.Unroll +import static net.fabricmc.loom.test.LoomTestConstants.* import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -class Java16ProjectTest extends Specification implements ProjectTestTrait { - @Override - String name() { - "java16" - } - +class Java16ProjectTest extends Specification implements GradleProjectTestTrait { @Unroll - def "build (gradle #gradle)"() { + def "build (gradle #version)"() { + setup: + def gradle = gradleProject(project: "java16", version: version) + when: - def result = create("build", gradle) + def result = gradle.run(task: "build") + then: result.task(":build").outcome == SUCCESS + where: - gradle | _ - DEFAULT_GRADLE | _ - PRE_RELEASE_GRADLE | _ + version << STANDARD_TEST_VERSIONS } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/KotlinTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/KotlinTest.groovy index 2d0e7ad..91cf813 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/KotlinTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/KotlinTest.groovy @@ -24,28 +24,26 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ProjectTestTrait -import spock.lang.IgnoreIf +import net.fabricmc.loom.test.util.GradleProjectTestTrait import spock.lang.Specification import spock.lang.Unroll +import static net.fabricmc.loom.test.LoomTestConstants.* import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -class KotlinTest extends Specification implements ProjectTestTrait { - @Override - String name() { - "kotlin" - } - +class KotlinTest extends Specification implements GradleProjectTestTrait { @Unroll - def "kotlin build (gradle #gradle)"() { + def "kotlin build (gradle #version)"() { + setup: + def gradle = gradleProject(project: "kotlin", version: version) + when: - def result = create("build", gradle) + def result = gradle.run(task: "build") + then: result.task(":build").outcome == SUCCESS + where: - gradle | _ - DEFAULT_GRADLE | _ - PRE_RELEASE_GRADLE | _ + version << STANDARD_TEST_VERSIONS } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/LegacyProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/LegacyProjectTest.groovy index 3f2f913..d8eeb66 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/LegacyProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/LegacyProjectTest.groovy @@ -24,24 +24,27 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait import spock.lang.Specification import spock.lang.Unroll +import static net.fabricmc.loom.test.LoomTestConstants.* import static org.gradle.testkit.runner.TaskOutcome.SUCCESS // This test uses gradle 4.9 and 1.14.4 v1 mappings -class LegacyProjectTest extends Specification implements ProjectTestTrait { - @Override - String name() { - "legacy" - } - +class LegacyProjectTest extends Specification implements GradleProjectTestTrait { @Unroll - def "build"() { + def "legacy build (gradle #version)"() { + setup: + def gradle = gradleProject(project: "legacy", version: version) + when: - def result = create("build", DEFAULT_GRADLE) + def result = gradle.run(task: "build") + then: result.task(":build").outcome == SUCCESS + + where: + version << STANDARD_TEST_VERSIONS } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/LocalFileDependencyTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/LocalFileDependencyTest.groovy index f6b8cc9..7102032 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/LocalFileDependencyTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/LocalFileDependencyTest.groovy @@ -24,27 +24,26 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait import spock.lang.Specification import spock.lang.Unroll +import static net.fabricmc.loom.test.LoomTestConstants.* import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -class LocalFileDependencyTest extends Specification implements ProjectTestTrait { - @Override - String name() { - "localFileDependency" - } - +class LocalFileDependencyTest extends Specification implements GradleProjectTestTrait { @Unroll - def "build (gradle #gradle)"() { + def "build (gradle #version)"() { + setup: + def gradle = gradleProject(project: "localFileDependency", version: version) + when: - def result = create("build", gradle) + def result = gradle.run(task: "build") + then: result.task(":build").outcome == SUCCESS + where: - gradle | _ - DEFAULT_GRADLE | _ - PRE_RELEASE_GRADLE | _ + version << STANDARD_TEST_VERSIONS } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/MavenProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/MavenProjectTest.groovy index 1a16d3b..f7aba96 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/MavenProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/MavenProjectTest.groovy @@ -24,13 +24,14 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ArchiveAssertionsTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait import net.fabricmc.loom.test.util.MockMavenServerTrait import spock.lang.Specification import spock.lang.Stepwise import spock.lang.Unroll import spock.util.environment.RestoreSystemProperties +import static net.fabricmc.loom.test.LoomTestConstants.* import static java.lang.System.setProperty import static org.gradle.testkit.runner.TaskOutcome.SUCCESS @@ -38,20 +39,23 @@ import static org.gradle.testkit.runner.TaskOutcome.SUCCESS * This tests publishing a range of versions and then tries to resolve and build against them */ @Stepwise -class MavenProjectTest extends Specification implements MockMavenServerTrait, ArchiveAssertionsTrait { +class MavenProjectTest extends Specification implements MockMavenServerTrait, GradleProjectTestTrait { @RestoreSystemProperties @Unroll - def "publish lib #version #gradle"() { - given: + def "publish lib #version #gradleVersion"() { + setup: setProperty('loom.test.version', version) - library = true + def gradle = gradleProject(project: "mavenLibrary", version: gradleVersion, sharedFiles: true) + when: - def result = create("publish", gradle) + def result = gradle.run(tasks: ["clean", "publish"]) + then: result.task(":publish").outcome == SUCCESS - hasArchiveEntry("fabric-example-lib-${version}.jar", "net/fabricmc/example/ExampleLib.class") + gradle.hasOutputZipEntry("fabric-example-lib-${version}.jar", "net/fabricmc/example/ExampleLib.class") + where: - version | gradle + version | gradleVersion '1.0.0' | DEFAULT_GRADLE '1.0.0' | PRE_RELEASE_GRADLE '1.1.0' | DEFAULT_GRADLE @@ -64,17 +68,20 @@ class MavenProjectTest extends Specification implements MockMavenServerTrait, Ar @RestoreSystemProperties @Unroll - def "resolve #version #gradle"() { + def "resolve #version #gradleVersion"() { given: setProperty('loom.test.resolve', "com.example:fabric-example-lib:${version}") - library = false + def gradle = gradleProject(project: "maven", version: gradleVersion, sharedFiles: true) + when: - def result = create("build", gradle) + def result = gradle.run(tasks: ["clean", "build"]) + then: result.task(":build").outcome == SUCCESS - hasArchiveEntry("fabric-example-mod-1.0.0.jar", "net/fabricmc/examplemod/ExampleMod.class") + gradle.hasOutputZipEntry("fabric-example-mod-1.0.0.jar", "net/fabricmc/examplemod/ExampleMod.class") + where: - version | gradle + version | gradleVersion '1.0.0' | DEFAULT_GRADLE '1.0.0' | PRE_RELEASE_GRADLE '1.1.+' | DEFAULT_GRADLE @@ -87,12 +94,4 @@ class MavenProjectTest extends Specification implements MockMavenServerTrait, Ar '2.0.0-SNAPSHOT:classifier' | DEFAULT_GRADLE 'master-SNAPSHOT:classifier' | DEFAULT_GRADLE } - - // Set to true when to build and publish the mavenLibrary - private boolean library = false - - @Override - String name() { - library ? "mavenLibrary" : "maven" - } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/MixinApAutoRefmapTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/MixinApAutoRefmapTest.groovy index acd16c5..f8b5b6d 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/MixinApAutoRefmapTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/MixinApAutoRefmapTest.groovy @@ -24,53 +24,50 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait import spock.lang.Specification import spock.lang.Unroll import com.google.gson.JsonParser; import java.util.jar.JarFile +import static net.fabricmc.loom.test.LoomTestConstants.STANDARD_TEST_VERSIONS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -class MixinApAutoRefmapTest extends Specification implements ProjectTestTrait { - @Override - String name() { - "mixinApAutoRefmap" - } - +class MixinApAutoRefmapTest extends Specification implements GradleProjectTestTrait { @Unroll - def "build (gradle #gradle)"() { + def "build (gradle #version)"() { + setup: + def gradle = gradleProject(project: "mixinApAutoRefmap", version: version) + when: - def result = create("build", gradle) + def result = gradle.run(task: "build") then: - result.task(":build").outcome == SUCCESS + result.task(":build").outcome == SUCCESS - // verify the ref-map name is correctly generated - def jar = new JarFile(getOutputFile("fabric-example-mod-1.0.0-universal.jar").absoluteFile) - jar.getEntry("refmap0000.json") == null - jar.getEntry("refmap0001.json") != null - jar.getEntry("refmap0002.json") != null - jar.getEntry("refmap0003.json") != null + // verify the ref-map name is correctly generated + def jar = new JarFile(gradle.getOutputFile("fabric-example-mod-1.0.0-universal.jar").absoluteFile) + jar.getEntry("refmap0000.json") == null + jar.getEntry("refmap0001.json") != null + jar.getEntry("refmap0002.json") != null + jar.getEntry("refmap0003.json") != null - def j1 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("main.mixins.json")))) - j1.asJsonObject.getAsJsonPrimitive("refmap").getAsString() == "refmap0001.json" + def j1 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("main.mixins.json")))) + j1.asJsonObject.getAsJsonPrimitive("refmap").getAsString() == "refmap0001.json" - def j2 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("blabla.json")))) - j2.asJsonObject.getAsJsonPrimitive("refmap").getAsString() == "refmap0002.json" + def j2 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("blabla.json")))) + j2.asJsonObject.getAsJsonPrimitive("refmap").getAsString() == "refmap0002.json" - def j3 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("m1_1.mixins.json")))) - j3.asJsonObject.getAsJsonPrimitive("refmap").getAsString() == "refmap0003.json" + def j3 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("m1_1.mixins.json")))) + j3.asJsonObject.getAsJsonPrimitive("refmap").getAsString() == "refmap0003.json" - def j4 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("m1_2.mixins.json")))) - !j4.asJsonObject.has("refmap") + def j4 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("m1_2.mixins.json")))) + !j4.asJsonObject.has("refmap") - def j5 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("irrelevant.mixins.json")))) - !j5.asJsonObject.has("refmap") + def j5 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("irrelevant.mixins.json")))) + !j5.asJsonObject.has("refmap") where: - gradle | _ - DEFAULT_GRADLE | _ - PRE_RELEASE_GRADLE | _ + version << STANDARD_TEST_VERSIONS } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/MixinApSimpleTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/MixinApSimpleTest.groovy index 793915e..831e226 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/MixinApSimpleTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/MixinApSimpleTest.groovy @@ -24,40 +24,38 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait + import spock.lang.Specification import spock.lang.Unroll import java.util.jar.JarFile +import static net.fabricmc.loom.test.LoomTestConstants.* import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -class MixinApSimpleTest extends Specification implements ProjectTestTrait { - @Override - String name() { - "mixinApSimple" - } - +class MixinApSimpleTest extends Specification implements GradleProjectTestTrait { @Unroll - def "build (gradle #gradle)"() { + def "build (gradle #version)"() { + setup: + def gradle = gradleProject(project: "mixinApSimple", version: version) + when: - def result = create("build", gradle) + def result = gradle.run(task: "build") then: - result.task(":build").outcome == SUCCESS + result.task(":build").outcome == SUCCESS - // verify the ref-map name is correctly generated - def main = new JarFile(getOutputFile("fabric-example-mod-1.0.0-dev.jar").absoluteFile) - main.getEntry("main-refmap0000.json") != null - def mixin = new JarFile(getOutputFile("fabric-example-mod-1.0.0-mixin.jar").absoluteFile) - mixin.getEntry("default-refmap0000.json") != null - def mixin1 = new JarFile(getOutputFile("fabric-example-mod-1.0.0-mixin1.jar").absoluteFile) - mixin1.getEntry("main-refmap0000.json") == null - mixin1.getEntry("default-refmap0000.json") == null + // verify the ref-map name is correctly generated + def main = new JarFile(gradle.getOutputFile("fabric-example-mod-1.0.0-dev.jar").absoluteFile) + main.getEntry("main-refmap0000.json") != null + def mixin = new JarFile(gradle.getOutputFile("fabric-example-mod-1.0.0-mixin.jar").absoluteFile) + mixin.getEntry("default-refmap0000.json") != null + def mixin1 = new JarFile(gradle.getOutputFile("fabric-example-mod-1.0.0-mixin1.jar").absoluteFile) + mixin1.getEntry("main-refmap0000.json") == null + mixin1.getEntry("default-refmap0000.json") == null where: - gradle | _ - DEFAULT_GRADLE | _ - PRE_RELEASE_GRADLE | _ + version << STANDARD_TEST_VERSIONS } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/MojangMappingsProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/MojangMappingsProjectTest.groovy index 08369a7..065a005 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/MojangMappingsProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/MojangMappingsProjectTest.groovy @@ -24,27 +24,26 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait import spock.lang.Specification import spock.lang.Unroll +import static net.fabricmc.loom.test.LoomTestConstants.* import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -class MojangMappingsProjectTest extends Specification implements ProjectTestTrait { - @Override - String name() { - "mojangMappings" - } - +class MojangMappingsProjectTest extends Specification implements GradleProjectTestTrait { @Unroll - def "build (gradle #gradle)"() { + def "build (gradle #version)"() { + setup: + def gradle = gradleProject(project: "mojangMappings", version: version) + when: - def result = create("build", gradle) + def result = gradle.run(task: "build") + then: result.task(":build").outcome == SUCCESS + where: - gradle | _ - DEFAULT_GRADLE | _ - PRE_RELEASE_GRADLE | _ + version << STANDARD_TEST_VERSIONS } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/MultiProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/MultiProjectTest.groovy index ecb6cd5..11de0ef 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/MultiProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/MultiProjectTest.groovy @@ -24,23 +24,22 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ArchiveAssertionsTrait -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait import spock.lang.Specification import spock.lang.Unroll +import static net.fabricmc.loom.test.LoomTestConstants.STANDARD_TEST_VERSIONS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -class MultiProjectTest extends Specification implements ProjectTestTrait, ArchiveAssertionsTrait { - @Override - String name() { - "multiproject" - } - +class MultiProjectTest extends Specification implements GradleProjectTestTrait { @Unroll - def "build (gradle #gradle)"() { + def "build (gradle #version)"() { + setup: + def gradle = gradleProject(project: "multiproject", version: version) + when: - def result = create("build", gradle) + def result = gradle.run(task: "build") + then: result.task(":build").outcome == SUCCESS result.task(":core:build").outcome == SUCCESS @@ -49,13 +48,11 @@ class MultiProjectTest extends Specification implements ProjectTestTrait, Archiv result.task(":remapAllJars").outcome == SUCCESS result.task(":remapAllSources").outcome == SUCCESS - hasArchiveEntry("multiproject-1.0.0.jar", "META-INF/jars/example-1.0.0.jar") - hasArchiveEntry("multiproject-1.0.0.jar", "META-INF/jars/core-1.0.0.jar") - hasArchiveEntry("multiproject-1.0.0.jar", "META-INF/jars/fabric-api-base-0.2.1+9354966b7d.jar") + gradle.hasOutputZipEntry("multiproject-1.0.0.jar", "META-INF/jars/example-1.0.0.jar") + gradle.hasOutputZipEntry("multiproject-1.0.0.jar", "META-INF/jars/core-1.0.0.jar") + gradle.hasOutputZipEntry("multiproject-1.0.0.jar", "META-INF/jars/fabric-api-base-0.2.1+9354966b7d.jar") where: - gradle | _ - DEFAULT_GRADLE | _ - PRE_RELEASE_GRADLE | _ + version << STANDARD_TEST_VERSIONS } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/ParchmentTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/ParchmentTest.groovy index 6390c1b..bbbb382 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/ParchmentTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/ParchmentTest.groovy @@ -24,29 +24,26 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait import spock.lang.Specification import spock.lang.Unroll +import static net.fabricmc.loom.test.LoomTestConstants.STANDARD_TEST_VERSIONS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -class ParchmentTest extends Specification implements ProjectTestTrait { - @Override - String name() { - "parchment" - } - +class ParchmentTest extends Specification implements GradleProjectTestTrait { @Unroll - def "parchment #gradle"() { + def "parchment #version"() { + setup: + def gradle = gradleProject(project: "parchment", version: version) + when: - def result = create("build", gradle) + def result = gradle.run(task: "build") then: result.task(":build").outcome == SUCCESS where: - gradle | _ - DEFAULT_GRADLE | _ - PRE_RELEASE_GRADLE | _ + version << STANDARD_TEST_VERSIONS } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/ReproducibleBuildTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/ReproducibleBuildTest.groovy index 874901d..ff4af2c 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/ReproducibleBuildTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/ReproducibleBuildTest.groovy @@ -27,40 +27,37 @@ package net.fabricmc.loom.test.integration import com.google.common.hash.HashCode import com.google.common.hash.Hashing import com.google.common.io.Files -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait import spock.lang.Specification import spock.lang.Unroll import spock.util.environment.RestoreSystemProperties +import static net.fabricmc.loom.test.LoomTestConstants.* import static java.lang.System.setProperty import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -class ReproducibleBuildTest extends Specification implements ProjectTestTrait { - @Override - String name() { - "reproducible" - } - +class ReproducibleBuildTest extends Specification implements GradleProjectTestTrait { @RestoreSystemProperties @Unroll - def "build (gradle #gradle)"() { + def "build (gradle #version)"() { + setup: + def gradle = gradleProject(project: "reproducible", version: version) + when: setProperty('loom.test.reproducible', 'true') - def result = create("build", gradle) + def result = gradle.run(task: "build") + then: result.task(":build").outcome == SUCCESS - getOutputHash("fabric-example-mod-1.0.0.jar") == modHash - getOutputHash("fabric-example-mod-1.0.0-sources.jar") in sourceHash // Done for different line endings. + generateMD5(gradle.getOutputFile("fabric-example-mod-1.0.0.jar")) == modHash + generateMD5(gradle.getOutputFile("fabric-example-mod-1.0.0-sources.jar")) in sourceHash // Done for different line endings. + where: - gradle | modHash | sourceHash + version | modHash | sourceHash DEFAULT_GRADLE | "ed3306ef60f434c55048cba8de5dab95" | ["be31766e6cafbe4ae3bca9e35ba63169", "7348b0bd87d36d7ec6f3bca9c2b66062"] PRE_RELEASE_GRADLE | "ed3306ef60f434c55048cba8de5dab95" | ["be31766e6cafbe4ae3bca9e35ba63169", "7348b0bd87d36d7ec6f3bca9c2b66062"] } - String getOutputHash(String name) { - generateMD5(getOutputFile(name)) - } - String generateMD5(File file) { HashCode hash = Files.asByteSource(file).hash(Hashing.md5()) return hash.asBytes().encodeHex() as String diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/RunConfigTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/RunConfigTest.groovy index f5d337a..e893c35 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/RunConfigTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/RunConfigTest.groovy @@ -24,25 +24,25 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait import spock.lang.Specification import spock.lang.Unroll import static org.gradle.testkit.runner.TaskOutcome.SUCCESS // This test runs a mod that exits on mod init -class RunConfigTest extends Specification implements ProjectTestTrait { - @Override - String name() { - "runconfigs" - } - +class RunConfigTest extends Specification implements GradleProjectTestTrait { @Unroll - def "#task"() { + def "Run config #task"() { + setup: + def gradle = gradleProject(project: "runconfigs", sharedFiles: true) + when: - def result = create(task) + def result = gradle.run(task: task) + then: result.task(":${task}").outcome == SUCCESS + where: task | _ 'runClient' | _ diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/SignedProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/SignedProjectTest.groovy index 8088992..2e34a16 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/SignedProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/SignedProjectTest.groovy @@ -24,14 +24,14 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ArchiveAssertionsTrait - +import net.fabricmc.loom.test.util.GradleProjectTestTrait import net.fabricmc.loom.test.util.MockMavenServerTrait import spock.lang.Specification import spock.lang.Stepwise import spock.lang.Unroll import spock.util.environment.RestoreSystemProperties +import static net.fabricmc.loom.test.LoomTestConstants.* import static java.lang.System.setProperty import static org.gradle.testkit.runner.TaskOutcome.SUCCESS @@ -39,25 +39,22 @@ import static org.gradle.testkit.runner.TaskOutcome.SUCCESS * This tests publishing signed artifacts to a maven server */ @Stepwise -class SignedProjectTest extends Specification implements MockMavenServerTrait, ArchiveAssertionsTrait { +class SignedProjectTest extends Specification implements MockMavenServerTrait, GradleProjectTestTrait { @Unroll @RestoreSystemProperties - def "sign and publish lib #gradle"() { - given: + def "sign and publish lib #version"() { + setup: setProperty('loom.test.secretKey', PRIVATE_KEY) + def gradle = gradleProject(project: "signed", version: version) + when: - def result = create("publish", gradle) + def result = gradle.run(task: "publish") + then: result.task(":publish").outcome == SUCCESS - where: - gradle | _ - DEFAULT_GRADLE | _ - PRE_RELEASE_GRADLE | _ - } - @Override - String name() { - "signed" + where: + version << STANDARD_TEST_VERSIONS } static final String PRIVATE_KEY = """ diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/SimpleProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/SimpleProjectTest.groovy index b5af208..5adf4ae 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/SimpleProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/SimpleProjectTest.groovy @@ -24,36 +24,48 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ArchiveAssertionsTrait -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait +import net.fabricmc.loom.test.util.ServerRunner import spock.lang.Specification +import spock.lang.Timeout import spock.lang.Unroll +import java.util.concurrent.TimeUnit + import static org.gradle.testkit.runner.TaskOutcome.SUCCESS +import static net.fabricmc.loom.test.LoomTestConstants.* -class SimpleProjectTest extends Specification implements ProjectTestTrait, ArchiveAssertionsTrait { - @Override - String name() { - "simple" - } - +@Timeout(value = 20, unit = TimeUnit.MINUTES) +class SimpleProjectTest extends Specification implements GradleProjectTestTrait { @Unroll - def "build (gradle #gradle)"() { + def "build and run (gradle #version)"() { + setup: + def gradle = gradleProject(project: "simple", version: version) + + def server = ServerRunner.create(gradle.projectDir, "1.16.5") + .withMod(gradle.getOutputFile("fabric-example-mod-1.0.0.jar")) + .withFabricApi() when: - def result = create("build", gradle) + def result = gradle.run(task: "build") + def serverResult = server.run() then: result.task(":build").outcome == SUCCESS - getArchiveEntry("fabric-example-mod-1.0.0.jar", "META-INF/MANIFEST.MF").contains("Fabric-Loom-Version: 0.0.0+unknown") + gradle.getOutputZipEntry("fabric-example-mod-1.0.0.jar", "META-INF/MANIFEST.MF").contains("Fabric-Loom-Version: 0.0.0+unknown") + + serverResult.successful() + serverResult.output.contains("Hello simple Fabric mod") // A check to ensure our mod init was actually called where: - gradle | _ - DEFAULT_GRADLE | _ - PRE_RELEASE_GRADLE | _ + version | _ + DEFAULT_GRADLE | _ + PRE_RELEASE_GRADLE | _ } @Unroll def "#ide config generation"() { + setup: + def gradle = gradleProject(project: "simple", sharedFiles: true) when: - def result = create(ide) + def result = gradle.run(task: ide) then: result.task(":${ide}").outcome == SUCCESS where: diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/UnpickTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/UnpickTest.groovy index 6254f44..2b285fb 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/UnpickTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/UnpickTest.groovy @@ -24,47 +24,48 @@ package net.fabricmc.loom.test.integration -import net.fabricmc.loom.test.util.ProjectTestTrait +import net.fabricmc.loom.test.util.GradleProjectTestTrait + import org.zeroturnaround.zip.ZipUtil import spock.lang.Specification import java.nio.charset.StandardCharsets +import static net.fabricmc.loom.test.LoomTestConstants.* import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -class UnpickTest extends Specification implements ProjectTestTrait { +class UnpickTest extends Specification implements GradleProjectTestTrait { static final String MAPPINGS = "21w13a/net.fabricmc.yarn.21w13a.21w13a+build.30-v2" - @Override - String name() { - "unpick" - } - def "unpick decompile"() { + setup: + def gradle = gradleProject(project: "unpick", version: version) + when: - def result = create("genSources", gradle) + def result = gradle.run(task: "genSources") then: result.task(":genSources").outcome == SUCCESS - getClassSource("net/minecraft/block/CakeBlock.java").contains("Block.DEFAULT_SET_BLOCK_STATE_FLAG") + getClassSource(gradle, "net/minecraft/block/CakeBlock.java").contains("Block.DEFAULT_SET_BLOCK_STATE_FLAG") where: - gradle | _ - DEFAULT_GRADLE | _ - PRE_RELEASE_GRADLE | _ + version << STANDARD_TEST_VERSIONS } def "unpick build"() { + setup: + def gradle = gradleProject(project: "unpick", version: version) + when: - def result = create("build", gradle) + def result = gradle.run(task: "build") + then: result.task(":build").outcome == SUCCESS + where: - gradle | _ - DEFAULT_GRADLE | _ - PRE_RELEASE_GRADLE | _ + version << STANDARD_TEST_VERSIONS } - String getClassSource(String classname, String mappings = MAPPINGS) { - File sourcesJar = getGeneratedSources(mappings) + private static String getClassSource(GradleProject gradle, String classname, String mappings = MAPPINGS) { + File sourcesJar = gradle.getGeneratedSources(mappings) return new String(ZipUtil.unpackEntry(sourcesJar, classname), StandardCharsets.UTF_8) } } diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsSpecification.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsSpecification.groovy index 64a37b5..814f0f4 100644 --- a/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsSpecification.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsSpecification.groovy @@ -33,7 +33,6 @@ import net.fabricmc.loom.configuration.providers.mappings.MappingLayer import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec import net.fabricmc.mappingio.format.Tiny2Writer -import net.fabricmc.mappingio.tree.MappingTree import net.fabricmc.mappingio.tree.MemoryMappingTree import org.gradle.api.logging.Logger import spock.lang.Specification diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsTestConstants.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsTestConstants.groovy index 74158b1..45a4a9c 100644 --- a/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsTestConstants.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsTestConstants.groovy @@ -31,14 +31,14 @@ interface LayeredMappingsTestConstants { public static final String INTERMEDIARY_1_16_5_URL = "https://maven.fabricmc.net/net/fabricmc/intermediary/1.16.5/intermediary-1.16.5-v2.jar" public static final Map DOWNLOADS_1_17 = [ - client_mappings:new MinecraftVersionMeta.Download(null, "227d16f520848747a59bef6f490ae19dc290a804", 6431705, "https://launcher.mojang.com/v1/objects/227d16f520848747a59bef6f490ae19dc290a804/client.txt"), - server_mappings:new MinecraftVersionMeta.Download(null, "84d80036e14bc5c7894a4fad9dd9f367d3000334", 4948536, "https://launcher.mojang.com/v1/objects/84d80036e14bc5c7894a4fad9dd9f367d3000334/server.txt") + client_mappings: new MinecraftVersionMeta.Download(null, "227d16f520848747a59bef6f490ae19dc290a804", 6431705, "https://launcher.mojang.com/v1/objects/227d16f520848747a59bef6f490ae19dc290a804/client.txt"), + server_mappings: new MinecraftVersionMeta.Download(null, "84d80036e14bc5c7894a4fad9dd9f367d3000334", 4948536, "https://launcher.mojang.com/v1/objects/84d80036e14bc5c7894a4fad9dd9f367d3000334/server.txt") ] public static final MinecraftVersionMeta VERSION_META_1_17 = new MinecraftVersionMeta(null, null, null, 0, DOWNLOADS_1_17, null, null, null, null, 0, null, null, null) public static final Map DOWNLOADS_1_16_5 = [ - client_mappings:new MinecraftVersionMeta.Download(null, "e3dfb0001e1079a1af72ee21517330edf52e6192", 5746047, "https://launcher.mojang.com/v1/objects/e3dfb0001e1079a1af72ee21517330edf52e6192/client.txt"), - server_mappings:new MinecraftVersionMeta.Download(null, "81d5c793695d8cde63afddb40dde88e3a88132ac", 4400926, "https://launcher.mojang.com/v1/objects/81d5c793695d8cde63afddb40dde88e3a88132ac/server.txt") + client_mappings: new MinecraftVersionMeta.Download(null, "e3dfb0001e1079a1af72ee21517330edf52e6192", 5746047, "https://launcher.mojang.com/v1/objects/e3dfb0001e1079a1af72ee21517330edf52e6192/client.txt"), + server_mappings: new MinecraftVersionMeta.Download(null, "81d5c793695d8cde63afddb40dde88e3a88132ac", 4400926, "https://launcher.mojang.com/v1/objects/81d5c793695d8cde63afddb40dde88e3a88132ac/server.txt") ] public static final MinecraftVersionMeta VERSION_META_1_16_5 = new MinecraftVersionMeta(null, null, null, 0, DOWNLOADS_1_16_5, null, null, null, null, 0, null, null, null) diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/ParchmentMappingLayerTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/ParchmentMappingLayerTest.groovy index d7daff2..76bea3b 100644 --- a/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/ParchmentMappingLayerTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/ParchmentMappingLayerTest.groovy @@ -27,7 +27,6 @@ package net.fabricmc.loom.test.unit.layeredmappings import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpec import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMappingsSpec -import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta class ParchmentMappingLayerTest extends LayeredMappingsSpecification { def "Read parchment mappings" () { diff --git a/src/test/groovy/net/fabricmc/loom/test/util/GradleProjectTestTrait.groovy b/src/test/groovy/net/fabricmc/loom/test/util/GradleProjectTestTrait.groovy new file mode 100644 index 0000000..a04d8b5 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/util/GradleProjectTestTrait.groovy @@ -0,0 +1,203 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2021 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.test.util + +import groovy.transform.Immutable +import net.fabricmc.loom.test.LoomTestConstants +import org.gradle.testkit.runner.BuildResult +import org.gradle.testkit.runner.GradleRunner +import org.zeroturnaround.zip.ZipUtil +import spock.lang.Shared + +trait GradleProjectTestTrait { + @Lazy + @Shared + private static File sharedProjectDir = File.createTempDir() + @Lazy + @Shared + private static File sharedGradleHomeDir = File.createTempDir() + + GradleProject gradleProject(Map options) { + String gradleVersion = options.version as String ?: LoomTestConstants.DEFAULT_GRADLE + String warningMode = options.warningMode as String ?: "fail" + File projectDir = options.projectDir as File ?: options.sharedFiles ? sharedProjectDir : File.createTempDir() + File gradleHomeDir = options.gradleHomeDir as File ?: options.sharedFiles ? sharedGradleHomeDir : File.createTempDir() + + setupProject(options, projectDir) + + return new GradleProject( + gradleVersion: gradleVersion, + projectDir: projectDir.absolutePath, + gradleHomeDir: gradleHomeDir.absolutePath, + warningMode: warningMode + ) + } + + private void setupProject(Map options, File projectDir) { + if (options.project) { + copyProjectFromResources(options.project as String, projectDir) + return + } + + if (options["repo"]) { + String repo = options.repo + String commit = options.commit + + exec(projectDir, "git", "clone", repo, ".") + exec(projectDir, "git", "checkout", commit) + + return + } + + throw new UnsupportedOperationException("No project setup method was supplied") + } + + private void exec(File projectDir, String... args) { + def process = args.execute([], projectDir) + process.consumeProcessOutput(System.out, System.err) + + def exitCode = process.waitFor() + + if (exitCode != 0) { + throw new RuntimeException("Command failed with exit code: $exitCode") + } + } + + private void copyProjectFromResources(String project, File projectDir) { + def projectSourceDir = new File("src/test/resources/projects/$project") + + if (!projectSourceDir.exists()) { + throw new FileNotFoundException("Failed to find project directory at: $projectSourceDir.absolutePath") + } + + // Cleanup some basic things if they already exists + new File(projectDir, "src").deleteDir() + new File(projectDir, "build.gradle").delete() + new File(projectDir, "settings.gradle").delete() + + projectSourceDir.eachFileRecurse { file -> + if (file.isDirectory()) { + return + } + + def path = file.path.replace(projectSourceDir.path, "") + + File tempFile = new File(projectDir, path) + + if (tempFile.exists()) { + tempFile.delete() + } + + tempFile.parentFile.mkdirs() + tempFile.bytes = file.bytes + } + } + + @Immutable + static class GradleProject { + private String gradleVersion + private String projectDir + private String gradleHomeDir + + private String warningMode + + BuildResult run(Map options) { + // Setup the system props to tell loom that its running in a test env + // And override the CI check to ensure that everything is ran + System.setProperty("fabric.loom.test", "true") + System.setProperty("fabric.loom.ci", "false") + System.setProperty("maven.repo.local", new File(getGradleHomeDir(), "m2").absolutePath) + + def runner = this.runner + def args = [] + + if (options.task) { + args << options.task + } + + args.addAll(options.tasks ?: []) + + args << "--stacktrace" + args << "--warning-mode" << warningMode + args << "--gradle-user-home" << gradleHomeDir + args.addAll(options.args ?: []) + + runner.withArguments(args as String[]) + + return runner.build() + } + + private GradleRunner getRunner() { + return GradleRunner.create() + .withProjectDir(getProjectDir()) + .withPluginClasspath() + .withGradleVersion(gradleVersion) + .forwardOutput() + .withDebug(true) + } + + File getProjectDir() { + return new File(projectDir) + } + + File getGradleHomeDir() { + return new File(gradleHomeDir) + } + + File getOutputFile(String filename) { + return new File(getProjectDir(), "build/libs/$filename") + } + + void printOutputFiles() { + new File(getProjectDir(), "build/libs/").listFiles().each { + println(it.name) + } + } + + File getBuildGradle() { + return new File(getProjectDir(), "build.gradle") + } + + String getOutputZipEntry(String filename, String entryName) { + def file = getOutputFile(filename) + def bytes = ZipUtil.unpackEntry(file, entryName) + + if (bytes == null) { + throw new FileNotFoundException("Could not find ${entryName} in ${entryName}") + } + + new String(bytes as byte[]) + } + + boolean hasOutputZipEntry(String filename, String entryName) { + def file = getOutputFile(filename) + return ZipUtil.unpackEntry(file, entryName) != null + } + + File getGeneratedSources(String mappings) { + return new File(getGradleHomeDir(), "caches/fabric-loom/${mappings}/minecraft-mapped-sources.jar") + } + } +} \ No newline at end of file diff --git a/src/test/groovy/net/fabricmc/loom/test/util/MockMavenServerTrait.groovy b/src/test/groovy/net/fabricmc/loom/test/util/MockMavenServerTrait.groovy index 98137a8..7021c58 100644 --- a/src/test/groovy/net/fabricmc/loom/test/util/MockMavenServerTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/util/MockMavenServerTrait.groovy @@ -27,7 +27,7 @@ package net.fabricmc.loom.test.util import io.javalin.Javalin import org.apache.commons.io.IOUtils -trait MockMavenServerTrait extends ProjectTestTrait { +trait MockMavenServerTrait { public final int mavenServerPort = 9876 public final File testMavenDir = File.createTempDir() private Javalin server @@ -74,7 +74,6 @@ trait MockMavenServerTrait extends ProjectTestTrait { @SuppressWarnings('unused') def cleanupSpec() { server.stop() - super.cleanupSpec() } File getMavenDirectory() { diff --git a/src/test/groovy/net/fabricmc/loom/test/util/ProjectTestTrait.groovy b/src/test/groovy/net/fabricmc/loom/test/util/ProjectTestTrait.groovy deleted file mode 100644 index f48b95b..0000000 --- a/src/test/groovy/net/fabricmc/loom/test/util/ProjectTestTrait.groovy +++ /dev/null @@ -1,126 +0,0 @@ -/* - * This file is part of fabric-loom, licensed under the MIT License (MIT). - * - * Copyright (c) 2016-2021 FabricMC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.fabricmc.loom.test.util - -import org.gradle.testkit.runner.BuildResult -import org.gradle.testkit.runner.GradleRunner - -trait ProjectTestTrait { - final static String DEFAULT_GRADLE = "7.0.1" - final static String PRE_RELEASE_GRADLE = "7.3-20210724022245+0000" - - static File gradleHome = File.createTempDir() - File testProjectDir = File.createTempDir() - - abstract String name() - - def copyInputFiles() { - println "Project directory: ${testProjectDir}" - - def baseProjectDir = new File("src/test/resources/projects/" + name()) - - if (!baseProjectDir.exists()) { - throw new FileNotFoundException("Failed to find project directory at:" + baseProjectDir.absolutePath) - } - - baseProjectDir.eachFileRecurse { file -> - if (file.isDirectory()) { - return - } - - def path = file.path.replace(baseProjectDir.path, "") - - File tempFile = new File(testProjectDir, path) - - if (tempFile.exists()) { - tempFile.delete() - } - - tempFile.parentFile.mkdirs() - tempFile.bytes = file.bytes - } - - // Disable the CI checks to ensure nothing is skipped - System.setProperty("fabric.loom.ci", "false") - } - - @SuppressWarnings('unused') - def cleanup() { - // Clean after each test - new File(testProjectDir, "build").deleteDir() - new File(testProjectDir, ".gradle").deleteDir() - } - - @SuppressWarnings('unused') - def cleanupSpec() { - testProjectDir.deleteDir() - gradleHome.deleteDir() - } - - File buildGradle() { - return new File(testProjectDir, "build.gradle") - } - - def filesReady() { - } - - BuildResult create(String task, String gradleVersion = DEFAULT_GRADLE) { - System.setProperty("fabric.loom.test", "true") - copyInputFiles() - filesReady() - - GradleRunner.create() - .withProjectDir(testProjectDir) - .withArguments(task, "--stacktrace", "--warning-mode", warningMode(gradleVersion), "--gradle-user-home", gradleHomeDirectory(gradleVersion)) - .withPluginClasspath() - .withGradleVersion(gradleVersion) - .forwardOutput() - .withDebug(true) - .build() - } - - String warningMode(String gradleVersion) { - 'fail' - } - - String gradleHomeDirectory(String gradleVersion) { - // Each gradle version gets its own dir to run on, to ensure that a full run is done. - new File(gradleHome, gradleVersion).absolutePath - } - - File getOutputFile(String name, String project = "") { - def file = new File(testProjectDir, "${project}build/libs/${name}") - - if (!file.exists()) { - throw new FileNotFoundException("Could not find ${name} at ${file.absolutePath}") - } - - return file - } - - File getGeneratedSources(String mappings, String gradleVersion = DEFAULT_GRADLE) { - return new File(gradleHomeDirectory(gradleVersion), "caches/fabric-loom/${mappings}/minecraft-mapped-sources.jar") - } -} \ No newline at end of file diff --git a/src/test/groovy/net/fabricmc/loom/test/util/ServerRunner.groovy b/src/test/groovy/net/fabricmc/loom/test/util/ServerRunner.groovy new file mode 100644 index 0000000..d3a6876 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/util/ServerRunner.groovy @@ -0,0 +1,208 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016-2021 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.test.util + +import groovy.transform.Immutable + +import java.util.concurrent.TimeUnit + +class ServerRunner { + static final String LOADER_VERSION = "0.11.6" + static final Map FABRIC_API_URLS = [ + "1.16.5": "https://github.com/FabricMC/fabric/releases/download/0.37.1%2B1.16/fabric-api-0.37.1+1.16.jar", + "1.17.1": "https://github.com/FabricMC/fabric/releases/download/0.37.1%2B1.17/fabric-api-0.37.1+1.17.jar" + ] + + final File serverDir + final String minecraftVersion + + final List mods = [] + + private ServerRunner(File serverDir, String minecraftVersion) { + this.serverDir = serverDir + this.minecraftVersion = minecraftVersion + + this.serverDir.mkdirs() + } + + static ServerRunner create(File testProjectDir, String minecraftVersion) { + return new ServerRunner(new File(testProjectDir, "server"), minecraftVersion) + } + + def install() { + def args = [ + "server", + "-dir", + serverDir.absolutePath, + "-mcversion", + minecraftVersion, + "-loader", + LOADER_VERSION, + "-downloadMinecraft" + ] + + //noinspection UnnecessaryQualifiedReference + net.fabricmc.installer.Main.main(args as String[]) + + def eulaFile = new File(serverDir, "eula.txt") + eulaFile << "eula=true" + + def serverPropsFile = new File(serverDir, "server.properties") + serverPropsFile << "level-type=FLAT" // Generates the world faster + } + + ServerRunner withMod(File file) { + mods << file + return this + } + + ServerRunner downloadMod(String url, String filename) { + File modFile = new File(serverDir, "downloadedMods/" + filename) + modFile.parentFile.mkdirs() + + println("Downloading " + url) + modFile.bytes = new URL(url).bytes + + return withMod(modFile) + } + + ServerRunner withFabricApi() { + if (!FABRIC_API_URLS[minecraftVersion]) { + throw new UnsupportedOperationException("No Fabric api url for " + minecraftVersion) + } + + return downloadMod(FABRIC_API_URLS[minecraftVersion], "fabricapi.jar") + } + + ServerRunResult run() { + install() + + // Copy the mods here so we can + mods.each { + if (!it.exists()) { + throw new FileNotFoundException(it.absolutePath) + } + + File modFile = new File(serverDir, "mods/" + it.name) + modFile.parentFile.mkdirs() + modFile.bytes = it.bytes + } + + String javaExecutablePath = ProcessHandle.current() + .info() + .command() + .orElseThrow() + + var builder = new ProcessBuilder() + builder.directory(serverDir) + builder.command(javaExecutablePath, "-Xmx1G", "-jar", "fabric-server-launch.jar", "nogui") + + Process process = builder.start() + def out = new StringBuffer() + def isStopping = false + + process.consumeProcessOutput( + new ForwardingAppendable([System.out, out], { + if (!isStopping && out.contains("Done ") && out.contains("For help, type \"help\"")) { + isStopping = true + + Thread.start { + println("Stopping server in 5 seconds") + sleep(5000) + + println("Sending stop command") + process.outputStream.withCloseable { + it.write("stop\n".bytes) + } + } + } + }), + new ForwardingAppendable([System.err, out]) + ) + + addShutdownHook { + if (process.alive) { + process.destroy() + } + } + + assert process.waitFor(10, TimeUnit.MINUTES) + int exitCode = process.exitValue() + + println("Sever closed with exit code: " + exitCode) + + return new ServerRunResult(exitCode, out.toString()) + } + + @Immutable + class ServerRunResult { + int exitCode + String output + + boolean successful() { + return exitCode == 0 && output.contains("Done ") + } + } + + private class ForwardingAppendable implements Appendable { + final List appendables + final Closure onAppended + + ForwardingAppendable(List appendables, Closure onAppended = {}) { + this.appendables = appendables + this.onAppended = onAppended + } + + @Override + Appendable append(CharSequence csq) throws IOException { + appendables.each { + it.append(csq) + } + + onAppended.run() + return this + } + + @Override + Appendable append(CharSequence csq, int start, int end) throws IOException { + appendables.each { + it.append(csq, start, end) + } + + onAppended.run() + return this + } + + @Override + Appendable append(char c) throws IOException { + appendables.each { + it.append(c) + } + + onAppended.run() + return this + } + } +} diff --git a/src/test/resources/projects/simple/src/main/java/net/fabricmc/example/ExampleMod.java b/src/test/resources/projects/simple/src/main/java/net/fabricmc/example/ExampleMod.java index e5ed082..e698549 100644 --- a/src/test/resources/projects/simple/src/main/java/net/fabricmc/example/ExampleMod.java +++ b/src/test/resources/projects/simple/src/main/java/net/fabricmc/example/ExampleMod.java @@ -9,6 +9,6 @@ public class ExampleMod implements ModInitializer { // However, some things (like resources) may still be uninitialized. // Proceed with mild caution. - System.out.println("Hello Fabric world!"); + System.out.println("Hello simple Fabric mod"); } }