From 9dcaed531552874d58259492778cb634b1d5ac58 Mon Sep 17 00:00:00 2001 From: Brian Neumann-Fopiano Date: Tue, 8 Sep 2026 04:55:29 -0400 Subject: [PATCH] Share test fixtures across modules - Move art.arcane.iris.testsupport into core/src/testFixtures and apply java-test-fixtures to core - Consume core test fixtures from the bukkit plugin, nms, probe and the three loader adapters - Delete the duplicate ProjectPaths copies in the bukkit-plugin and modded-common test trees - Point ModdedMessageContributorTest at the shared ProjectPaths - Guard CommandPackCompatTest, NativeTransitionColumnTest and StubPlatformStateTest with PlatformLeakGuard - Release the probe runtime state after DimensionStackSuperflatProbeTest opens a workspace - Keep core main classes ahead of the core jar on the test classpath so the bytecode gates still scan a directory --- .../nativegen/NativeTransitionColumnTest.java | 5 ++ adapters/bukkit/plugin/build.gradle | 1 + .../core/commands/CommandPackCompatTest.java | 24 +----- adapters/fabric/build.gradle | 1 + adapters/forge/build.gradle | 1 + .../ModdedMessageContributorTest.java | 2 +- .../iris/modded/testsupport/ProjectPaths.java | 82 ------------------- adapters/neoforge/build.gradle | 1 + build.gradle | 1 + core/build.gradle | 7 +- .../arcane/iris/testsupport/ProjectPaths.java | 82 ------------------- .../art/arcane/iris/testsupport/Await.java | 0 .../iris/testsupport/BukkitTestServer.java | 0 .../iris/testsupport/DurabilityMode.java | 0 .../iris/testsupport/IrisRuntimeState.java | 0 .../iris/testsupport/PlatformBinding.java | 0 .../iris/testsupport/PlatformLeakGuard.java | 0 .../arcane/iris/testsupport/ProjectPaths.java | 0 probe/build.gradle | 1 + .../DimensionStackSuperflatProbeTest.java | 7 ++ .../iris/probe/StubPlatformStateTest.java | 6 +- 21 files changed, 34 insertions(+), 187 deletions(-) delete mode 100644 adapters/modded-common/src/test/java/art/arcane/iris/modded/testsupport/ProjectPaths.java delete mode 100644 core/src/test/java/art/arcane/iris/testsupport/ProjectPaths.java rename core/src/{test => testFixtures}/java/art/arcane/iris/testsupport/Await.java (100%) rename core/src/{test => testFixtures}/java/art/arcane/iris/testsupport/BukkitTestServer.java (100%) rename core/src/{test => testFixtures}/java/art/arcane/iris/testsupport/DurabilityMode.java (100%) rename core/src/{test => testFixtures}/java/art/arcane/iris/testsupport/IrisRuntimeState.java (100%) rename core/src/{test => testFixtures}/java/art/arcane/iris/testsupport/PlatformBinding.java (100%) rename core/src/{test => testFixtures}/java/art/arcane/iris/testsupport/PlatformLeakGuard.java (100%) rename {adapters/bukkit/plugin/src/test => core/src/testFixtures}/java/art/arcane/iris/testsupport/ProjectPaths.java (100%) diff --git a/adapters/bukkit/nms/v26_2_R1/src/test/java/art/arcane/iris/nativegen/NativeTransitionColumnTest.java b/adapters/bukkit/nms/v26_2_R1/src/test/java/art/arcane/iris/nativegen/NativeTransitionColumnTest.java index 23b0e5fa8..82b350995 100644 --- a/adapters/bukkit/nms/v26_2_R1/src/test/java/art/arcane/iris/nativegen/NativeTransitionColumnTest.java +++ b/adapters/bukkit/nms/v26_2_R1/src/test/java/art/arcane/iris/nativegen/NativeTransitionColumnTest.java @@ -6,6 +6,7 @@ import art.arcane.iris.spi.IrisPlatform; import art.arcane.iris.spi.IrisPlatforms; import art.arcane.iris.spi.PlatformBlockState; import art.arcane.iris.spi.PlatformRegistries; +import art.arcane.iris.testsupport.PlatformLeakGuard; import net.minecraft.SharedConstants; import net.minecraft.core.Direction; import net.minecraft.server.Bootstrap; @@ -16,6 +17,7 @@ import net.minecraft.world.level.block.RotatedPillarBlock; import net.minecraft.world.level.block.LiquidBlock; import net.minecraft.world.level.levelgen.Heightmap; import org.junit.BeforeClass; +import org.junit.Rule; import org.junit.Test; import org.mockito.MockedStatic; @@ -30,6 +32,9 @@ import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.when; public final class NativeTransitionColumnTest { + @Rule + public final PlatformLeakGuard leakGuard = PlatformLeakGuard.clean(); + @BeforeClass public static void bootstrap() { SharedConstants.tryDetectVersion(); diff --git a/adapters/bukkit/plugin/build.gradle b/adapters/bukkit/plugin/build.gradle index f0a3df139..38793cded 100644 --- a/adapters/bukkit/plugin/build.gradle +++ b/adapters/bukkit/plugin/build.gradle @@ -22,6 +22,7 @@ dependencies { testImplementation(libs.paper.api) testImplementation(libs.bstats) testImplementation(project(':core')) + testImplementation(testFixtures(project(':core'))) testImplementation(volmLibCoordinate) { transitive = false } diff --git a/adapters/bukkit/plugin/src/test/java/art/arcane/iris/core/commands/CommandPackCompatTest.java b/adapters/bukkit/plugin/src/test/java/art/arcane/iris/core/commands/CommandPackCompatTest.java index c85d1ed66..5853c4966 100644 --- a/adapters/bukkit/plugin/src/test/java/art/arcane/iris/core/commands/CommandPackCompatTest.java +++ b/adapters/bukkit/plugin/src/test/java/art/arcane/iris/core/commands/CommandPackCompatTest.java @@ -7,10 +7,8 @@ import art.arcane.iris.core.pack.PackValidationResult; import art.arcane.volmlib.util.director.compat.DirectorAnnotationCompatibility; import art.arcane.volmlib.util.director.runtime.DirectorNodeDescriptor; import art.arcane.volmlib.util.director.runtime.DirectorParameterDescriptor; -import art.arcane.iris.spi.IrisPlatform; -import art.arcane.iris.spi.IrisPlatforms; -import org.junit.After; -import org.junit.Before; +import art.arcane.iris.testsupport.PlatformLeakGuard; +import org.junit.Rule; import org.junit.Test; import java.util.List; @@ -20,22 +18,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class CommandPackCompatTest { - private IrisPlatform previousPlatform; - - /** The persisted Minecraft version is only used when no platform is bound, so pin that here. */ - @Before - public void unbindPlatform() { - previousPlatform = IrisPlatforms.isBound() ? IrisPlatforms.get() : null; - IrisPlatforms.unbind(); - } - - @After - public void rebindPlatform() { - IrisPlatforms.unbind(); - if (previousPlatform != null) { - IrisPlatforms.bind(previousPlatform); - } - } + @Rule + public final PlatformLeakGuard leakGuard = PlatformLeakGuard.clean(); private static CompatFinding block(CompatAction action, String subjectKey) { return new CompatFinding( diff --git a/adapters/fabric/build.gradle b/adapters/fabric/build.gradle index 8725b0e34..db9b4e52b 100644 --- a/adapters/fabric/build.gradle +++ b/adapters/fabric/build.gradle @@ -141,6 +141,7 @@ dependencies { implementation("net.fabricmc:fabric-loader:${fabricLoaderVersion}") testImplementation('junit:junit:4.13.2') testImplementation('org.mockito:mockito-core:5.23.0') + testImplementation(testFixtures('art.arcane:core')) testImplementation(libs.spigot) { transitive = false } diff --git a/adapters/forge/build.gradle b/adapters/forge/build.gradle index 68d7280ae..2e509514e 100644 --- a/adapters/forge/build.gradle +++ b/adapters/forge/build.gradle @@ -158,6 +158,7 @@ dependencies { implementation minecraft.dependency("net.minecraftforge:forge:${forgeVersion}") testImplementation('junit:junit:4.13.2') testImplementation('org.mockito:mockito-core:5.23.0') + testImplementation(testFixtures('art.arcane:core')) testImplementation(libs.spigot) { transitive = false } diff --git a/adapters/modded-common/src/test/java/art/arcane/iris/modded/localization/ModdedMessageContributorTest.java b/adapters/modded-common/src/test/java/art/arcane/iris/modded/localization/ModdedMessageContributorTest.java index 55a0038a5..97873c1cb 100644 --- a/adapters/modded-common/src/test/java/art/arcane/iris/modded/localization/ModdedMessageContributorTest.java +++ b/adapters/modded-common/src/test/java/art/arcane/iris/modded/localization/ModdedMessageContributorTest.java @@ -2,7 +2,7 @@ package art.arcane.iris.modded.localization; import art.arcane.iris.core.localization.IrisLanguage; import art.arcane.iris.core.localization.IrisMessages; -import art.arcane.iris.modded.testsupport.ProjectPaths; +import art.arcane.iris.testsupport.ProjectPaths; import art.arcane.volmlib.util.localization.MessageKey; import art.arcane.volmlib.util.localization.VolmitLocales; import com.google.gson.JsonObject; diff --git a/adapters/modded-common/src/test/java/art/arcane/iris/modded/testsupport/ProjectPaths.java b/adapters/modded-common/src/test/java/art/arcane/iris/modded/testsupport/ProjectPaths.java deleted file mode 100644 index feab80d42..000000000 --- a/adapters/modded-common/src/test/java/art/arcane/iris/modded/testsupport/ProjectPaths.java +++ /dev/null @@ -1,82 +0,0 @@ -package art.arcane.iris.modded.testsupport; - -import java.io.File; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.CodeSource; -import java.security.ProtectionDomain; - -public final class ProjectPaths { - private static final Path MODULE_ROOT = resolveModuleRoot(); - private static final Path REPOSITORY_ROOT = resolveRepositoryRoot(MODULE_ROOT); - - private ProjectPaths() { - } - - public static Path moduleRoot() { - return MODULE_ROOT; - } - - public static Path repositoryRoot() { - return REPOSITORY_ROOT; - } - - public static Path moduleFile(String relative) { - return MODULE_ROOT.resolve(relative).normalize(); - } - - public static Path repositoryFile(String relative) { - return REPOSITORY_ROOT.resolve(relative).normalize(); - } - - public static File moduleFileAt(String relative) { - return moduleFile(relative).toFile(); - } - - public static File repositoryFileAt(String relative) { - return repositoryFile(relative).toFile(); - } - - private static Path resolveModuleRoot() { - ProtectionDomain domain = ProjectPaths.class.getProtectionDomain(); - CodeSource source = domain == null ? null : domain.getCodeSource(); - URL location = source == null ? null : source.getLocation(); - - if (location != null) { - try { - Path current = Path.of(location.toURI()).toAbsolutePath().normalize(); - - while (current != null) { - Path name = current.getFileName(); - - if (name != null && "build".equals(name.toString()) && current.getParent() != null) { - return current.getParent(); - } - - current = current.getParent(); - } - } catch (URISyntaxException | IllegalArgumentException ignored) { - return Path.of("").toAbsolutePath().normalize(); - } - } - - return Path.of("").toAbsolutePath().normalize(); - } - - private static Path resolveRepositoryRoot(Path moduleRoot) { - Path current = moduleRoot; - - while (current != null) { - if (Files.isRegularFile(current.resolve("settings.gradle")) - && Files.isDirectory(current.resolve("core/src/main/java"))) { - return current; - } - - current = current.getParent(); - } - - return moduleRoot; - } -} diff --git a/adapters/neoforge/build.gradle b/adapters/neoforge/build.gradle index ca7ea081c..90cb64c20 100644 --- a/adapters/neoforge/build.gradle +++ b/adapters/neoforge/build.gradle @@ -132,6 +132,7 @@ configurations.testRuntimeClasspath.extendsFrom(configurations.runtimeClasspath, dependencies { testImplementation('junit:junit:4.13.2') testImplementation('org.mockito:mockito-core:5.23.0') + testImplementation(testFixtures('art.arcane:core')) testImplementation(libs.spigot) { transitive = false } diff --git a/build.gradle b/build.gradle index cac409c7f..c5a95e685 100644 --- a/build.gradle +++ b/build.gradle @@ -164,6 +164,7 @@ nmsBindings.each { key, value -> testImplementation('junit:junit:4.13.2') testImplementation('org.mockito:mockito-core:5.23.0') testImplementation(project(':core')) + testImplementation(testFixtures(project(':core'))) testCompileOnly(volmLibCoordinate) { transitive = false } diff --git a/core/build.gradle b/core/build.gradle index 2ba42ad7b..326c988fc 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -29,6 +29,7 @@ import java.nio.charset.StandardCharsets plugins { id 'java' id 'java-library' + id 'java-test-fixtures' alias(libs.plugins.shadow) alias(libs.plugins.slimjar) } @@ -130,6 +131,10 @@ dependencies { slim(libs.dom4j) slim(libs.jaxen) + testFixturesImplementation('junit:junit:4.13.2') + testFixturesImplementation('org.mockito:mockito-core:5.23.0') + testFixturesCompileOnly(libs.paper.api) + testImplementation('junit:junit:4.13.2') testImplementation('org.mockito:mockito-core:5.23.0') testImplementation(libs.paper.api) @@ -232,7 +237,7 @@ tasks.named('compileJava', JavaCompile).configure { tasks.named('test', Test).configure { jvmArgs('--add-modules', 'jdk.incubator.vector') dependsOn(languageSourceManifestTask) - classpath = files(layout.buildDirectory.dir('generated/language-source')) + files('src/main/resources') + classpath + classpath = files(layout.buildDirectory.dir('generated/language-source')) + files('src/main/resources') + sourceSets.main.output + classpath } configurations.matching { it.name.startsWith('slim') }.all { } diff --git a/core/src/test/java/art/arcane/iris/testsupport/ProjectPaths.java b/core/src/test/java/art/arcane/iris/testsupport/ProjectPaths.java deleted file mode 100644 index 3617450f5..000000000 --- a/core/src/test/java/art/arcane/iris/testsupport/ProjectPaths.java +++ /dev/null @@ -1,82 +0,0 @@ -package art.arcane.iris.testsupport; - -import java.io.File; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.CodeSource; -import java.security.ProtectionDomain; - -public final class ProjectPaths { - private static final Path MODULE_ROOT = resolveModuleRoot(); - private static final Path REPOSITORY_ROOT = resolveRepositoryRoot(MODULE_ROOT); - - private ProjectPaths() { - } - - public static Path moduleRoot() { - return MODULE_ROOT; - } - - public static Path repositoryRoot() { - return REPOSITORY_ROOT; - } - - public static Path moduleFile(String relative) { - return MODULE_ROOT.resolve(relative).normalize(); - } - - public static Path repositoryFile(String relative) { - return REPOSITORY_ROOT.resolve(relative).normalize(); - } - - public static File moduleFileAt(String relative) { - return moduleFile(relative).toFile(); - } - - public static File repositoryFileAt(String relative) { - return repositoryFile(relative).toFile(); - } - - private static Path resolveModuleRoot() { - ProtectionDomain domain = ProjectPaths.class.getProtectionDomain(); - CodeSource source = domain == null ? null : domain.getCodeSource(); - URL location = source == null ? null : source.getLocation(); - - if (location != null) { - try { - Path current = Path.of(location.toURI()).toAbsolutePath().normalize(); - - while (current != null) { - Path name = current.getFileName(); - - if (name != null && "build".equals(name.toString()) && current.getParent() != null) { - return current.getParent(); - } - - current = current.getParent(); - } - } catch (URISyntaxException | IllegalArgumentException ignored) { - return Path.of("").toAbsolutePath().normalize(); - } - } - - return Path.of("").toAbsolutePath().normalize(); - } - - private static Path resolveRepositoryRoot(Path moduleRoot) { - Path current = moduleRoot; - - while (current != null) { - if (Files.isRegularFile(current.resolve("settings.gradle")) - && Files.isDirectory(current.resolve("core/src/main/java"))) { - return current; - } - - current = current.getParent(); - } - - return moduleRoot; - } -} diff --git a/core/src/test/java/art/arcane/iris/testsupport/Await.java b/core/src/testFixtures/java/art/arcane/iris/testsupport/Await.java similarity index 100% rename from core/src/test/java/art/arcane/iris/testsupport/Await.java rename to core/src/testFixtures/java/art/arcane/iris/testsupport/Await.java diff --git a/core/src/test/java/art/arcane/iris/testsupport/BukkitTestServer.java b/core/src/testFixtures/java/art/arcane/iris/testsupport/BukkitTestServer.java similarity index 100% rename from core/src/test/java/art/arcane/iris/testsupport/BukkitTestServer.java rename to core/src/testFixtures/java/art/arcane/iris/testsupport/BukkitTestServer.java diff --git a/core/src/test/java/art/arcane/iris/testsupport/DurabilityMode.java b/core/src/testFixtures/java/art/arcane/iris/testsupport/DurabilityMode.java similarity index 100% rename from core/src/test/java/art/arcane/iris/testsupport/DurabilityMode.java rename to core/src/testFixtures/java/art/arcane/iris/testsupport/DurabilityMode.java diff --git a/core/src/test/java/art/arcane/iris/testsupport/IrisRuntimeState.java b/core/src/testFixtures/java/art/arcane/iris/testsupport/IrisRuntimeState.java similarity index 100% rename from core/src/test/java/art/arcane/iris/testsupport/IrisRuntimeState.java rename to core/src/testFixtures/java/art/arcane/iris/testsupport/IrisRuntimeState.java diff --git a/core/src/test/java/art/arcane/iris/testsupport/PlatformBinding.java b/core/src/testFixtures/java/art/arcane/iris/testsupport/PlatformBinding.java similarity index 100% rename from core/src/test/java/art/arcane/iris/testsupport/PlatformBinding.java rename to core/src/testFixtures/java/art/arcane/iris/testsupport/PlatformBinding.java diff --git a/core/src/test/java/art/arcane/iris/testsupport/PlatformLeakGuard.java b/core/src/testFixtures/java/art/arcane/iris/testsupport/PlatformLeakGuard.java similarity index 100% rename from core/src/test/java/art/arcane/iris/testsupport/PlatformLeakGuard.java rename to core/src/testFixtures/java/art/arcane/iris/testsupport/PlatformLeakGuard.java diff --git a/adapters/bukkit/plugin/src/test/java/art/arcane/iris/testsupport/ProjectPaths.java b/core/src/testFixtures/java/art/arcane/iris/testsupport/ProjectPaths.java similarity index 100% rename from adapters/bukkit/plugin/src/test/java/art/arcane/iris/testsupport/ProjectPaths.java rename to core/src/testFixtures/java/art/arcane/iris/testsupport/ProjectPaths.java diff --git a/probe/build.gradle b/probe/build.gradle index 502539bc4..ac5eaf979 100644 --- a/probe/build.gradle +++ b/probe/build.gradle @@ -17,6 +17,7 @@ dependencies { implementation(project(':core')) compileOnly(libs.spigot) testImplementation('junit:junit:4.13.2') + testImplementation(testFixtures(project(':core'))) testImplementation(volmLibCoordinate) { transitive = false } diff --git a/probe/src/test/java/art/arcane/iris/probe/DimensionStackSuperflatProbeTest.java b/probe/src/test/java/art/arcane/iris/probe/DimensionStackSuperflatProbeTest.java index 7bcfd1a3c..36b8535ea 100644 --- a/probe/src/test/java/art/arcane/iris/probe/DimensionStackSuperflatProbeTest.java +++ b/probe/src/test/java/art/arcane/iris/probe/DimensionStackSuperflatProbeTest.java @@ -4,6 +4,8 @@ import art.arcane.iris.engine.DimensionStackContext; import art.arcane.iris.engine.DimensionStackLayout; import art.arcane.iris.engine.framework.Engine; import art.arcane.iris.spi.PlatformBlockState; +import art.arcane.iris.testsupport.IrisRuntimeState; +import org.junit.AfterClass; import org.junit.Test; import java.io.File; @@ -20,6 +22,11 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; public final class DimensionStackSuperflatProbeTest { + @AfterClass + public static void releaseProbeRuntime() { + IrisRuntimeState.reset(); + } + private static final long SEED = 1_337L; private static final long ALTERNATE_SEED = 8_675_309L; private static final int WORLD_HEIGHT = 128; diff --git a/probe/src/test/java/art/arcane/iris/probe/StubPlatformStateTest.java b/probe/src/test/java/art/arcane/iris/probe/StubPlatformStateTest.java index 41c4fa350..8c5ee1cfc 100644 --- a/probe/src/test/java/art/arcane/iris/probe/StubPlatformStateTest.java +++ b/probe/src/test/java/art/arcane/iris/probe/StubPlatformStateTest.java @@ -4,9 +4,11 @@ import art.arcane.iris.engine.decorator.IrisSpeleothems; import art.arcane.iris.engine.object.IrisObjectRotation; import art.arcane.iris.spi.IrisPlatforms; import art.arcane.iris.spi.PlatformBlockState; +import art.arcane.iris.testsupport.PlatformLeakGuard; import art.arcane.iris.util.project.hunk.Hunk; import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -15,9 +17,11 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; public final class StubPlatformStateTest { + @ClassRule + public static final PlatformLeakGuard LEAK_GUARD = PlatformLeakGuard.clean(); + @BeforeClass public static void bindPlatform() { - IrisPlatforms.unbind(); IrisPlatforms.bind(new StubPlatform()); StubPlatform.bindGenerationStateHandlers(); }