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
This commit is contained in:
Brian Neumann-Fopiano
2026-09-08 05:27:49 -04:00
parent fd146de1ad
commit 9dcaed5315
21 changed files with 34 additions and 187 deletions
@@ -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();
+1
View File
@@ -22,6 +22,7 @@ dependencies {
testImplementation(libs.paper.api)
testImplementation(libs.bstats)
testImplementation(project(':core'))
testImplementation(testFixtures(project(':core')))
testImplementation(volmLibCoordinate) {
transitive = false
}
@@ -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(
+1
View File
@@ -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
}
+1
View File
@@ -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
}
@@ -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;
@@ -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;
}
}
+1
View File
@@ -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
}
+1
View File
@@ -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
}
+6 -1
View File
@@ -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 { }
@@ -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;
}
}
+1
View File
@@ -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
}
@@ -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;
@@ -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();
}