Retire source-text tests

- Delete 22 test classes whose assertions only read production .java text and check call ordering or literal presence
- Remove 77 source-text assertion methods from 34 test classes that keep real behavioural coverage
- Replace the core process-stream source grep with an ASM gate over compiled core classes in CoreProcessStreamPurityGateTest
- Replace the packs-root source grep in PacksFolderContractTest with an ASM call-site gate over compiled core classes
- Replace the IrisData registered-root regex in PackTypeBukkitPurityGateTest with an ASM scan of the registerLoader class constants
- Trim six mixed tests down to their behavioural assertions and drop their source-text tails
- Drop the eight iris.*Source and three iris.moddedCommonSources test system properties now that nothing reads them
This commit is contained in:
Brian Neumann-Fopiano
2026-09-08 04:01:33 -04:00
parent 7841efed54
commit c75cfd387e
65 changed files with 245 additions and 4273 deletions
-8
View File
@@ -59,12 +59,4 @@ tasks.named('jar', Jar).configure {
}
tasks.named('test').configure {
systemProperty('iris.pregeneratorJobSource', rootProject.file('core/src/main/java/art/arcane/iris/core/gui/PregeneratorJob.java').absolutePath)
systemProperty('iris.bukkitEnginePlatformHooksSource', file('src/main/java/art/arcane/iris/core/runtime/BukkitEnginePlatformHooks.java').absolutePath)
systemProperty('iris.engineSvcSource', file('src/main/java/art/arcane/iris/core/service/IrisEngineSVC.java').absolutePath)
systemProperty('iris.terrainSvcSource', file('src/main/java/art/arcane/iris/core/service/IrisTerrainSVC.java').absolutePath)
systemProperty('iris.apiEventSvcSource', file('src/main/java/art/arcane/iris/core/service/IrisApiEventSVC.java').absolutePath)
systemProperty('iris.worldInfoFactorySource', file('src/main/java/art/arcane/iris/core/service/terrain/IrisWorldInfoFactory.java').absolutePath)
systemProperty('iris.startupSource', file('src/main/java/art/arcane/iris/Iris.java').absolutePath)
systemProperty('iris.readmeSource', rootProject.file('README.md').absolutePath)
}
@@ -3,14 +3,10 @@ package art.arcane.iris;
import art.arcane.iris.spi.LogLevel;
import org.junit.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.logging.Level;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
* Core states a severity on every message it logs and the modded adapters honour it. Bukkit must preserve
@@ -33,58 +29,4 @@ public class IrisDiagnosticLogLevelTest {
public void lifecycleNoticesReachThePluginLoggerAtInfo() {
assertEquals(Level.INFO, Iris.diagnosticLevel(LogLevel.NOTICE));
}
@Test
public void adapterSideWarningsCarryTheSameSeverityAsCoreWarnings() throws Exception {
String source = Files.readString(Path.of("src/main/java/art/arcane/iris/Iris.java")).replace("\r\n", "\n");
String warn = method(source, "public static void warn(String format, Object... objs)");
assertTrue(warn, warn.contains("diagnostic(Level.WARNING"));
assertFalse(warn, warn.contains("msg("));
String error = method(source, "public static void error(String format, Object... objs)");
assertTrue(error, error.contains("diagnostic(Level.SEVERE"));
assertFalse(error, error.contains("msg("));
}
@Test
public void theCoreLogBridgeRoutesDiagnosticsToThePluginLogger() throws Exception {
String source = Files.readString(Path.of("src/main/java/art/arcane/iris/Iris.java")).replace("\r\n", "\n");
String bridge = method(source, "private static void bridgeLog(LogLevel level, String message)");
assertTrue(bridge, bridge.contains("diagnosticLevel(target)"));
assertTrue(bridge, bridge.contains("diagnostic(diagnostic, message)"));
String diagnostic = method(source, "private static void diagnostic(Level level, String message)");
assertTrue(diagnostic, diagnostic.contains("ComponentLog.log("));
assertTrue(diagnostic, diagnostic.contains("ComponentText.literal(line)"));
}
@Test
public void informationalMessagesUseTheSharedComponentLogger() throws Exception {
String source = Files.readString(Path.of("src/main/java/art/arcane/iris/Iris.java")).replace("\r\n", "\n");
String message = method(source, "public static void msg(String string)");
assertTrue(message, message.contains("ComponentLog.logMarkup("));
assertTrue(message, message.contains("logPrefix(plugin)"));
assertFalse(message, message.contains("getSender().sendMessage"));
}
private static String method(String source, String signature) {
int start = source.indexOf(signature);
assertTrue("method not found: " + signature, start >= 0);
int open = source.indexOf('{', start);
int depth = 0;
for (int i = open; i < source.length(); i++) {
char c = source.charAt(i);
if (c == '{') {
depth++;
} else if (c == '}') {
depth--;
if (depth == 0) {
return source.substring(start, i + 1);
}
}
}
throw new AssertionError("unterminated method: " + signature);
}
}
@@ -1,72 +0,0 @@
package art.arcane.iris.core;
import org.junit.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertTrue;
public class IrisStartupOrderingTest {
@Test
public void admissionGateIsRegisteredBeforeStartupValidationBegins() throws Exception {
String source = Files.readString(Path.of(System.getProperty("iris.startupSource")));
String onEnable = section(source, "public void onEnable()", "public void onDisable()");
assertOrdered(onEnable,
"IrisStartupValidation.begin();",
"registerEvents(new IrisStartupAdmissionListener(), this);",
"enable();");
}
@Test
public void externalDatapacksValidateBeforeDimensionPacks() throws Exception {
String source = Files.readString(Path.of(System.getProperty("iris.startupSource")));
String enable = section(source, "private boolean enable()", "public void addShutdownHook()");
assertOrdered(enable,
"DatapackIngestService.validateOnStartup();",
"generatorResolver.validateAllPacks();");
}
@Test
public void externalProvidersEnableBeforePackValidation() throws Exception {
String source = Files.readString(Path.of(System.getProperty("iris.startupSource")));
String enable = section(source, "private boolean enable()", "public void addShutdownHook()");
assertOrdered(enable,
"service.onEnable();",
"setContentChangeListener(generatorResolver::requestExternalContentRefresh)",
"generatorResolver.validateAllPacks();");
}
@Test
public void restartRequiredStartupTerminatesAfterPluginInitialization() throws Exception {
String source = Files.readString(Path.of(System.getProperty("iris.startupSource")));
String onEnable = section(source, "public void onEnable()", "public void onDisable()");
assertOrdered(onEnable,
"BukkitGuiHost.install();",
"super.onEnable();",
"IrisStartupValidation.isRestartRequired()",
"ServerConfigurator.restartAtStartupBoundary(restartReason);");
}
private static String section(String source, String startMarker, String endMarker) {
int start = source.indexOf(startMarker);
int end = source.indexOf(endMarker, start);
assertTrue("Missing source section starting with " + startMarker, start >= 0);
assertTrue("Missing source section ending with " + endMarker, end > start);
return source.substring(start, end);
}
private static void assertOrdered(String source, String... markers) {
int previous = -1;
for (String marker : markers) {
int current = source.indexOf(marker);
assertTrue("Missing source marker " + marker, current >= 0);
assertTrue("Source marker is out of order: " + marker, current > previous);
previous = current;
}
}
}
@@ -140,23 +140,6 @@ public class IrisWorldGeneratorResolverTest {
}
}
@Test
public void startupValidationPublishesFingerprintBoundExactRootResults() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/IrisWorldGeneratorResolver.java")).replace("\r\n", "\n");
int validateAll = source.indexOf("public void validateAllPacks()");
int snapshot = source.indexOf("ServerConfigurator.computePackContentSnapshot(packsRoot)", validateAll);
int perPackFingerprint = source.indexOf("contentSnapshot.packContents()", snapshot);
int exactRootPublish = source.indexOf(
"PackValidationRegistry.publish(packDirectory.toPath(), result, packFingerprint)",
perPackFingerprint);
assertTrue(validateAll >= 0);
assertTrue(snapshot > validateAll);
assertTrue(perPackFingerprint > snapshot);
assertTrue(exactRootPublish > perPackFingerprint);
}
@Test
public void paperStartupAliasResolvesToCanonicalRuntimeKey() throws Exception {
File levelRoot = ownedLevelRoot("startup-alias", "moon");
@@ -251,87 +234,6 @@ public class IrisWorldGeneratorResolverTest {
return levelRoot;
}
@Test
public void configuredWorldResolutionUsesOnlyActiveImmutableGenerationPack() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/IrisWorldGeneratorResolver.java")).replace("\r\n", "\n");
int resolverStart = source.indexOf("private ChunkGenerator resolveFrozenWorldGenerator(");
int resolverEnd = source.indexOf("private record FreshValidation", resolverStart);
String resolver = source.substring(resolverStart, resolverEnd);
int dimensionRoot = resolver.indexOf("IrisWorldStorage.requireFrozenDimensionRoot(");
int currentPlatformRoot = resolver.indexOf("WorldCreatorCompat.persistentDimensionRoot(worldKey)");
int layoutRefusal = resolver.indexOf(
"Frozen Iris world storage does not match the current platform layout",
currentPlatformRoot
);
int history = resolver.indexOf("requireGenerationHistory(dimensionRoot, id, worldSeed)");
int snapshotRoot = resolver.indexOf("requireActivePack(history)", history);
int validation = resolver.indexOf("requireSnapshotLoadable(snapshotRoot)");
int exactLoad = resolver.indexOf("requireHistoricalDimension(history, snapshotRoot, id)");
int canonicalIdentity = resolver.indexOf(".platformIdentity(worldKey.toString())");
int historicalSeed = resolver.indexOf(".seed(history.activeEpoch().worldSeed())");
int resolvedStorage = resolver.indexOf(".worldFolder(dimensionRoot)");
assertTrue(dimensionRoot >= 0);
assertTrue(currentPlatformRoot > dimensionRoot);
assertTrue(layoutRefusal > currentPlatformRoot);
assertTrue(history > layoutRefusal);
assertTrue(snapshotRoot > history);
assertTrue(validation > snapshotRoot);
assertTrue(exactLoad > validation);
assertTrue(canonicalIdentity > exactLoad);
assertTrue(historicalSeed > canonicalIdentity);
assertTrue(resolvedStorage > historicalSeed);
assertFalse(resolver.contains("loadDimension("));
assertFalse(resolver.contains("loadAnyDimension("));
assertFalse(resolver.contains("replaceIntoWorld("));
assertFalse(resolver.contains("installIntoWorld("));
assertFalse(resolver.contains(".seed(1337)"));
assertTrue(resolver.contains("GenerationHistory.openIfPresent(root, worldSeed)"));
assertTrue(resolver.contains("GenerationHistory.adoptLegacyPack("));
assertTrue(resolver.contains("GenerationRegistryContractFactory.captureRequiredDefinitions("));
}
@Test
public void ownedWorldSnapshotFailureStopsStartupAndRethrows() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/IrisWorldGeneratorResolver.java")).replace("\r\n", "\n");
int resolverStart = source.indexOf("public ChunkGenerator resolveDefaultWorldGenerator(");
int resolverEnd = source.indexOf("private ChunkGenerator resolveFrozenWorldGenerator(", resolverStart);
String resolver = source.substring(resolverStart, resolverEnd);
int plotSquaredProbe = resolver.indexOf("isPlotSquaredGeneratorDiscoveryProbe(worldName, id)");
int probe = resolver.indexOf("isGeneratorDiscoveryProbe(worldName, id)", plotSquaredProbe);
int denial = resolver.indexOf("IrisStartupValidation.denialReason()", probe);
int failClosed = resolver.indexOf("IrisFailClosedChunkGenerator.startupLock(", denial);
int staged = resolver.indexOf("WorldLifecycleStaging.consumeGenerator(worldName)", failClosed);
int duplicateGuard = resolver.indexOf("requireWorldKeyAvailable(worldName, worldKey)");
int ownership = resolver.indexOf("requireOwnedWorld(worldName, levelRoot, worldKey)");
int frozen = resolver.indexOf("return resolveFrozenWorldGenerator(", ownership);
int failureCapture = resolver.indexOf("catch (RuntimeException failure)", frozen);
int report = resolver.indexOf("Iris.reportError(", failureCapture);
int shutdown = resolver.indexOf("Bukkit.shutdown()", report);
int rethrow = resolver.indexOf("throw failure", shutdown);
assertTrue(plotSquaredProbe >= 0);
assertTrue(probe > plotSquaredProbe);
assertTrue(denial > probe);
assertTrue(failClosed > denial);
assertTrue(staged > failClosed);
assertTrue(duplicateGuard > staged);
assertTrue(ownership > duplicateGuard);
assertTrue(frozen > ownership);
assertTrue(failureCapture > frozen);
assertTrue(report > failureCapture);
assertTrue(shutdown > report);
assertTrue(rethrow > shutdown);
String shutdownScope = "the fail-fast shutdown must stay scoped to the frozen snapshot of an owned world";
assertEquals(shutdownScope, resolverStart + shutdown, source.indexOf("Bukkit.shutdown()"));
assertEquals(shutdownScope, resolverStart + shutdown, source.lastIndexOf("Bukkit.shutdown()"));
}
@Test
public void plotSquaredDiscoveryProbeIsIgnoredQuietly() {
try (MockedStatic<Bukkit> bukkit = mockStatic(Bukkit.class);
@@ -1,26 +0,0 @@
package art.arcane.iris.core.commands;
import org.junit.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public final class CommandDeveloperGenerationHistoryTest {
@Test
public void updateWorldStagesThePackWithTheLiveWorldSeed() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/commands/CommandDeveloper.java"
)).replace("\r\n", "\n");
int updateStart = source.indexOf("public void updateWorld(");
int updateEnd = source.indexOf("@Director(description = \"Test\"", updateStart);
String update = source.substring(updateStart, updateEnd);
assertTrue(update.contains(
"replaceIntoWorld(sender(), pack, folder, world.getSeed())"
));
assertFalse(update.contains("iris/pack"));
}
}
@@ -7,8 +7,6 @@ import org.junit.Test;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import static org.junit.Assert.assertEquals;
@@ -73,26 +71,4 @@ public class CommandIrisCreateOverwriteContractTest {
assertEquals(Long.valueOf(Long.MAX_VALUE), handler.parse(Long.toString(Long.MAX_VALUE), false));
assertThrows(DirectorParsingException.class, () -> handler.parse("9223372036854775808", false));
}
@Test
public void createAndReplaceUseLocalizedStyledMissingDimensionFeedback() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/commands/CommandIris.java"
)).replace("\r\n", "\n");
assertEquals(2, occurrences(source, "COMMAND_IRIS_DIMENSION_NOT_FOUND"));
assertEquals(2, occurrences(source, "COMMAND_IRIS_INSTALL_PACK_AND_RESTART"));
assertFalse(source.contains("sendMessage(\"Could not find dimension"));
assertFalse(source.contains("sendMessage(\"Install its pack with"));
}
private static int occurrences(String value, String match) {
int count = 0;
int offset = 0;
while ((offset = value.indexOf(match, offset)) >= 0) {
count++;
offset += match.length();
}
return count;
}
}
@@ -5,13 +5,10 @@ import org.junit.Test;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
@@ -47,20 +44,6 @@ public class CommandIrisDownloadContractTest {
assertThrows(Exception.class, () -> handler.parse("custom", false));
}
@Test
public void commandDelegatesAcceptedDownloadsWithoutRawPreamble() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/commands/CommandIris.java"
)).replace("\r\n", "\n");
String download = method(source, "public void download(");
assertTrue(download.contains("downloadBuiltIn(sender(), builtInPack)"));
assertTrue(download.contains("downloadUrl(sender(), directLink)"));
assertFalse(download.contains("Downloading built-in Iris pack"));
assertFalse(download.contains("Downloading Iris pack from"));
assertFalse(download.contains("sendMessage(directLink"));
}
private static String method(String source, String signature) {
int start = source.indexOf(signature);
assertTrue(start >= 0);
@@ -115,21 +115,6 @@ public class CommandJigsawContractTest {
new IllegalStateException("Unexpected Studio failure")));
}
@Test
public void committedActivationStartsInitialEvaluationBeforePlayerBinding() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/commands/CommandJigsaw.java")).replace("\r\n", "\n");
int commit = source.indexOf("JigsawStudioActivation.commit(staged)");
int evaluation = source.indexOf(
"studioService.activationCommitted(world, request.requestId())",
commit);
int binding = source.indexOf("PLAYER_PACKS.put", evaluation);
assertTrue(commit >= 0);
assertTrue(evaluation > commit);
assertTrue(binding > evaluation);
}
@Test
public void convertIsAddOnlyWorkflowWithAliasesAndDefaults() throws Exception {
Method convert = CommandJigsaw.class.getDeclaredMethod(
@@ -358,20 +343,6 @@ public class CommandJigsawContractTest {
.getAnnotation(Director.class));
}
@Test
public void pieceCreateUsesResolvedWorkcellCapacityInsteadOfLayoutDefault() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/commands/CommandJigsaw.java")).replace("\r\n", "\n");
int pieceCommands = source.indexOf("public static class CommandJigsawPiece");
int create = source.indexOf("public void create(", pieceCommands);
int add = source.indexOf("public void add(", create);
String createSource = source.substring(create, add);
assertTrue(createSource.contains("targetWorkcell = contextual;"));
assertTrue(createSource.contains("JigsawStudioCellDimensions dimensions = targetWorkcell.capacity();"));
assertFalse(createSource.contains("layout().cellDimensions()"));
}
@Test
public void pieceAddUsesCanonicalAxesForRotatedRectangularPlanarWorkcells() {
JigsawStudioLayout layout = nonuniformPlanarLayout();
@@ -510,25 +481,6 @@ public class CommandJigsawContractTest {
assertEquals(1, releases.get());
}
@Test
public void exportSourceAcquiresStudioLeaseBeforeStaticLeaseAndReleasesBothPaths() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/commands/CommandJigsaw.java")).replace("\r\n", "\n");
int serviceLease = source.indexOf("studioService.tryBeginExport(requestId, playerId)");
int staticLease = source.indexOf("beginExport(playerId, destination)", serviceLease);
int dispatch = source.indexOf("J.a(() -> runExport(operation))", staticLease);
int schedulingRelease = source.indexOf("operation.lease().release()", dispatch);
int exporter = source.indexOf("new VanillaJigsawDatapackExporter().export(operation.request())", dispatch);
int completionRelease = source.indexOf("operation.lease().release()", exporter);
assertTrue(serviceLease >= 0);
assertTrue(staticLease > serviceLease);
assertTrue(dispatch > staticLease);
assertTrue(schedulingRelease > dispatch);
assertTrue(exporter > schedulingRelease);
assertTrue(completionRelease > exporter);
}
private static void assertCommand(String name, Class<?>... parameterTypes) throws Exception {
Method method = CommandJigsaw.class.getDeclaredMethod(name, parameterTypes);
assertNotNull(method.getAnnotation(Director.class));
@@ -7,8 +7,6 @@ import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.junit.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
@@ -212,20 +210,6 @@ public class IrisPapiExpansionTest {
assertTrue(expansion.persist());
}
@Test
public void theReadmeDocumentsEveryPublishedKeyAndEveryRetiredOne() throws Exception {
String readme = Files.readString(Path.of(System.getProperty("iris.readmeSource")));
for (String key : PUBLISHED_KEYS) {
assertTrue("README must document %iris_" + key + "%", readme.contains("%iris_" + key + "%"));
}
for (String retired : RETIRED_KEYS) {
assertTrue("README must carry the migration row for %iris_" + retired + "%",
readme.contains("%iris_" + retired + "%"));
}
}
@Test
public void theTerrainServiceIsTheOnlyDoorIntoIris() {
IrisTerrainService service = new FakeIrisTerrainService();
@@ -1,137 +0,0 @@
package art.arcane.iris.core.link;
import org.junit.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class IrisPapiLifecycleTest {
private static final Path PLUGIN_SOURCE = Path.of("src/main/java/art/arcane/iris/Iris.java");
private static final String SETUP = "private void setupPapi() {";
private static final String TEARDOWN = "private void teardownPapi() {";
private static String source() throws Exception {
// The assertions below match against literals written with \n, so a CRLF checkout has to
// be folded first or every multi-line expectation misses.
return Files.readString(PLUGIN_SOURCE).replace("\r\n", "\n");
}
private static String body(String declaration) throws Exception {
String source = source();
int start = source.indexOf(declaration);
assertTrue("Iris.java must declare " + declaration, start >= 0);
int open = source.indexOf('{', start);
int depth = 0;
for (int index = open; index < source.length(); index++) {
char character = source.charAt(index);
if (character == '{') {
depth++;
continue;
}
if (character != '}') {
continue;
}
depth--;
if (depth == 0) {
return source.substring(open + 1, index);
}
}
throw new AssertionError(declaration + " is not brace balanced");
}
@Test
public void registrationIsGatedOnPlaceholderApiBeingEnabled() throws Exception {
assertTrue("setupPapi must bail out when PlaceholderAPI is absent",
body(SETUP).contains("if (!PlaceholderRegistration.isPlaceholderApiEnabled()) {"));
}
@Test
public void theRegistrationTheListenerAndTheStateAreAllRetained() throws Exception {
String source = source();
assertTrue(source.contains("private volatile PlaceholderRegistration papiRegistration;"));
assertTrue(source.contains("private volatile IrisPapiListener papiListener;"));
assertTrue(source.contains("private volatile IrisPapiState papiState;"));
}
@Test
public void teardownUnregistersTheExpansionTheListenerAndClearsTheState() throws Exception {
String teardown = body(TEARDOWN);
assertTrue("the retained registration must be unregistered inside teardownPapi",
teardown.contains("registration.unregister();"));
assertTrue("the retained listener must be detached inside teardownPapi",
teardown.contains("HandlerList.unregisterAll(listener);"));
assertTrue("the retained state must drop every held world reference inside teardownPapi",
teardown.contains("state.clear();"));
assertTrue("teardownPapi must drop the retained listener", teardown.contains("papiListener = null;"));
assertTrue("teardownPapi must drop the retained registration", teardown.contains("papiRegistration = null;"));
assertTrue("teardownPapi must drop the retained state", teardown.contains("papiState = null;"));
}
@Test
public void bothDisablePathsTearThePlaceholderSurfaceDown() throws Exception {
String disable = body("public void onDisable() {");
String preUnload = body("public void onPreUnload(ReloadAware.PreUnloadReason reason) {");
int disableTeardown = disable.indexOf("teardownPapi();");
int preUnloadTeardown = preUnload.indexOf("teardownPapi();");
assertTrue("onDisable must tear the expansion down before branching into runtime shutdown",
disableTeardown >= 0 && disableTeardown < disable.indexOf("IrisToolbelt.isServerStopping()"));
assertTrue("the BileTools pre-unload hook must tear the expansion down before any shutdown branch",
preUnloadTeardown >= 0 && preUnloadTeardown < preUnload.indexOf("IrisToolbelt.isServerStopping()"));
}
@Test
public void aFailedListenerAttachDoesNotLeaveTheExpansionRegistered() throws Exception {
String setup = body(SETUP);
int attach = setup.indexOf("registerEvents(listener, this)");
assertTrue("the listener must be attached inside setupPapi", attach >= 0);
int rescue = setup.indexOf("} catch (Throwable failure) {", attach);
assertTrue("the attach must be guarded inside setupPapi", rescue > attach);
int rollback = setup.indexOf("registration.unregister();", rescue);
assertTrue("a failed attach must roll the registration back inside setupPapi", rollback > rescue);
int bail = setup.indexOf("return;", rollback);
assertTrue("a failed attach must leave setupPapi", bail > rollback);
int retained = setup.indexOf("papiRegistration = registration;");
assertTrue("setupPapi must retain the registration", retained > 0);
assertTrue("the registration may only be retained after a successful attach", retained > bail);
}
@Test
public void theExpansionIsNeverConstructedFromAPluginStatic() throws Exception {
String setup = body(SETUP);
assertFalse("the plugin class must not construct the expansion: that forces PlaceholderExpansion to load during enable and crashes a server without PlaceholderAPI",
setup.contains("new IrisPapiExpansion("));
assertTrue("the expansion takes its state as a constructor argument, built inside the installer",
installerSource().contains("new IrisPapiExpansion(state, logger)"));
assertFalse("the hand rolled PlaceholderAPI presence check must be gone",
source().contains("isPluginEnabled(\"PlaceholderAPI\")"));
}
private static String installerSource() throws Exception {
return java.nio.file.Files.readString(java.nio.file.Path.of(
"src/main/java/art/arcane/iris/core/link/IrisPapiInstaller.java")).replace("\r\n", "\n");
}
}
@@ -1,53 +0,0 @@
package art.arcane.iris.core.runtime;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class StudioPlayerModeContractTest {
@Test
public void autoStartedStudioUsesSpectatorMode() throws IOException {
String plugin = Files.readString(Path.of("src/main/java/art/arcane/iris/Iris.java")).replace("\r\n", "\n");
String commands = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/commands/CommandStudio.java")).replace("\r\n", "\n");
assertFalse(plugin.contains("GameMode.CREATIVE"));
assertFalse(commands.contains("GameMode.CREATIVE"));
assertTrue(plugin.contains("GameMode.SPECTATOR"));
}
@Test
public void tpStudioUsesThePreparedCoordinatorEntry() throws IOException {
String commands = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/commands/CommandStudio.java")).replace("\r\n", "\n");
int methodStart = commands.indexOf("public void tpstudio()");
int methodEnd = commands.indexOf("\n @Director", methodStart);
String method = commands.substring(methodStart, methodEnd);
assertTrue(method.contains("StudioSVC studioService = Iris.service(StudioSVC.class)"));
assertTrue(method.contains("studioService.teleportToActiveProject(player)"));
assertFalse(method.contains("setGameMode("));
assertFalse(method.contains("getActiveProject()"));
assertFalse(method.contains("BukkitPlatform.teleportAsync"));
assertFalse(method.contains("BukkitWorldBinding.spawnLocation"));
}
@Test
public void editingStudiosRemainCreative() throws IOException {
String objectCommands = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/commands/CommandObject.java")).replace("\r\n", "\n");
String jigsawCommands = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/commands/CommandJigsaw.java")).replace("\r\n", "\n");
assertTrue(objectCommands.contains("GameMode.CREATIVE"));
assertTrue(objectCommands.contains("StudioOpenCoordinator.StudioOpenKind.OBJECT"));
assertTrue(jigsawCommands.contains("GameMode.CREATIVE"));
assertFalse(objectCommands.contains("GameMode.SPECTATOR"));
assertFalse(jigsawCommands.contains("GameMode.SPECTATOR"));
}
}
@@ -1,195 +0,0 @@
package art.arcane.iris.core.service;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class IrisApiWiringContractTest {
@Test
public void theTerrainServiceRegistersOnBothRegistriesAndReleasesBoth() throws IOException {
String source = source("iris.terrainSvcSource");
String onEnable = method(source, "public void onEnable()");
String onDisable = method(source, "public void onDisable()");
assertTrue(onEnable.contains("Bukkit.getServicesManager().register("));
assertTrue(onEnable.contains("IrisTerrainService.class"));
assertTrue(onEnable.contains("IrisServices.register(IrisTerrainService.class, this)"));
assertTrue(onDisable.contains("Bukkit.getServicesManager().unregister(IrisTerrainService.class, this)"));
assertTrue(onDisable.contains("IrisServices.remove(IrisTerrainService.class)"));
assertBefore(onDisable, "serviceEnabled.set(false)", "Bukkit.getServicesManager().unregister(");
}
@Test
public void theTerrainServiceNeverForcesEngineInitialisationOrLoadsTheMantle() throws IOException {
String source = source("iris.terrainSvcSource");
assertFalse("isIrisWorld must not touch the generator", source.contains("IrisToolbelt"));
assertFalse("isIrisWorld must not touch the generator", source.contains(".touch("));
assertFalse("terrain queries must not load mantle chunks", source.contains("getMantle()"));
assertFalse("terrain queries must not load mantle chunks", source.contains("getObjectsAt("));
assertFalse("terrain queries must not load mantle chunks", source.contains("getPOIsAt("));
assertFalse("terrain queries must not load mantle chunks", source.contains("getCaveOrMantleBiome("));
assertFalse("terrain queries must never block", source.contains(".join()"));
assertFalse("terrain queries must never block", source.contains("synchronized"));
assertFalse("terrain queries must never block", source.contains("J.sfut("));
}
@Test
public void sampleColumnsBoundsTheQueryBeforeItWalksAndTreatsAThrowingSinkAsARefusal() throws IOException {
String sampleColumns = method(source("iris.terrainSvcSource"),
"public boolean sampleColumns(World world, IrisColumnQuery query, IrisColumnSink sink)");
assertBefore(sampleColumns, "IrisSampleLimits.withinLimits(", "IrisColumnWalk.walk(");
assertBefore(sampleColumns, "IrisColumnWalk.walk(", "catch (Throwable error)");
assertTrue(sampleColumns.contains("reportSinkFault(world, error)"));
assertTrue(sampleColumns.contains("return false;"));
assertTrue("the walk must abort when the engine closes underneath it",
sampleColumns.contains("engine.isClosed()"));
}
@Test
public void thePregeneratorDispatchesPhasesFromItsExistingTickAndNeverBlocksOnTheSink() throws IOException {
String source = source("iris.pregeneratorJobSource");
String dispatch = method(source, "private void dispatchApiPhases(List<PregenApiPhase> phases)");
assertTrue(dispatch.contains("IrisServices.getOrNull(PregenApiSink.class)"));
assertTrue(dispatch.contains("catch (Throwable error)"));
assertBefore(dispatch, "sink.pregen(phase, progress)", "catch (Throwable error)");
assertFalse(dispatch.contains(".join()"));
assertTrue(method(source, "public void onTick(").contains("dispatchApiPhases(apiPhases.onTick(paused()))"));
assertTrue(method(source, "public void onSaving()").contains("dispatchApiPhases(apiPhases.onSaving())"));
assertTrue(method(source, "public void onClose()").contains("dispatchApiPhases(apiPhases.onClose(reachedTotal()))"));
}
@Test
public void worldPhasesAreFiredOutsideTheRegistrationLock() throws IOException {
String source = source("iris.engineSvcSource");
String add = method(source, "private void add(World world)");
assertBefore(add, "catch (RejectedExecutionException exception)", "phases.ready(world)");
assertBefore(add, "registered = true;", "phases.ready(world)");
String remove = method(source,
"private boolean remove(World world, CompletionStage<Boolean> unloadBoundary)");
assertBefore(remove, "registered = worlds.remove(world)", "phases.closing(world)");
assertBefore(remove, "phases.closing(world)",
"deferCloseUntilWorldUnload(world, registered, closing, unloadBoundary)");
}
@Test
public void everyRegisteredWorldIsAnnouncedClosingWhenTheServiceShutsDown() throws IOException {
String onDisable = method(source("iris.engineSvcSource"), "public void onDisable()");
assertTrue("service shutdown must announce ENGINE_CLOSING for every registered world",
onDisable.contains("phases.closing(teardown.world())"));
assertBefore(onDisable, "worlds.clear()", "phases.closing(teardown.world())");
assertBefore(onDisable, "phases.closing(teardown.world())", "shutdownAndDrain(activeService)");
assertBefore(onDisable, "phases.closing(teardown.world())",
"startClose(teardown.registered(), teardown.closing())");
}
@Test
public void aReplacedEngineIsAnnouncedClosingBeforeTheRetryReRegistersTheWorld() throws IOException {
String add = method(source("iris.engineSvcSource"), "private void add(World world)");
assertBefore(add, "catch (RejectedExecutionException exception)", "phases.closing(world)");
assertBefore(add, "phases.closing(world)", "retryRegistrationAfterClose(world, retryAfter)");
assertBefore(add, "phases.closing(world)", "startClose(replaced, replacementClose)");
}
@Test
public void aWorldPhaseIsNeverConditionalOnAnotherServicesRegistration() throws IOException {
String source = source("iris.apiEventSvcSource");
String fire = method(source, "public static void fireWorldPhase(World world, IrisWorldPhase phase)");
assertFalse("world lifecycle must not resolve a swappable service to build its payload",
fire.contains("IrisServices"));
assertFalse("world lifecycle must not resolve a swappable service to build its payload",
fire.contains("IrisTerrainService"));
assertTrue(fire.contains("deliver(new IrisWorldEngineEvent(world, phase, describe(world, phase)))"));
String describe = method(source, "private static IrisWorldInfo describe(World world, IrisWorldPhase phase)");
assertTrue(describe.contains("IrisWorldInfoFactory.forWorld(world)"));
assertTrue("an undescribable world must be reported, not swallowed",
describe.contains("IrisLogging.reportError("));
assertTrue("an undescribable world must still deliver the phase", describe.contains("return null;"));
}
@Test
public void aWorldPhaseRaisedFromAServerThreadIsDeliveredBeforeThatThreadMovesOn() throws IOException {
String deliver = method(source("iris.apiEventSvcSource"), "private static void deliver(Event event)");
assertBefore(deliver, "Bukkit.isPrimaryThread()", "Bukkit.getPluginManager().callEvent(event)");
assertBefore(deliver, "Bukkit.getPluginManager().callEvent(event)", "Iris.callEvent(event)");
}
@Test
public void theWorldInfoFactoryNeverForcesEngineInitialisationOrLoadsTheMantle() throws IOException {
String source = source("iris.worldInfoFactorySource");
assertFalse("the factory must not touch the generator", source.contains("IrisToolbelt"));
assertFalse("the factory must not touch the generator", source.contains(".touch("));
assertFalse("the factory must not load mantle chunks", source.contains("getMantle()"));
assertFalse("the factory must never block", source.contains(".join()"));
assertFalse("the factory must never block", source.contains("synchronized"));
assertTrue("the factory must refuse a closed engine", source.contains("engine.isClosed()"));
}
@Test
public void theHotloadHookStillFiresTheLegacyEventAlongsideTheApiEvent() throws IOException {
String hook = method(source("iris.bukkitEnginePlatformHooksSource"), "public void fireHotloadEvent(Engine engine)");
assertBefore(hook, "new IrisEngineHotloadEvent(engine)",
"IrisApiEventSVC.fireWorldPhase(BukkitWorldBinding.world(engine.getWorld()), IrisWorldPhase.ENGINE_HOTLOADED)");
}
@Test
public void theEventServiceNeverLetsAThirdPartyFailureEscapeALifecyclePath() throws IOException {
String fire = method(source("iris.apiEventSvcSource"),
"public static void fireWorldPhase(World world, IrisWorldPhase phase)");
assertTrue(fire.contains("catch (Throwable error)"));
assertTrue(fire.contains("IrisLogging.reportError("));
assertFalse(fire.contains("printStackTrace"));
}
private static String source(String property) throws IOException {
String path = System.getProperty(property);
assertTrue("missing source property " + property, path != null && !path.isBlank());
return Files.readString(Path.of(path));
}
private static void assertBefore(String source, String first, String second) {
int firstIndex = source.indexOf(first);
int secondIndex = source.indexOf(second);
assertTrue("Missing source contract token: " + first, firstIndex >= 0);
assertTrue("Missing source contract token: " + second, secondIndex >= 0);
assertTrue(first + " must occur before " + second, firstIndex < secondIndex);
}
private static String method(String source, String signature) {
int start = source.indexOf(signature);
assertTrue("Missing source contract signature: " + signature, start >= 0);
int openBrace = source.indexOf('{', start);
assertTrue("Missing source contract method body: " + signature, openBrace >= 0);
int depth = 0;
for (int index = openBrace; index < source.length(); index++) {
char current = source.charAt(index);
if (current == '{') {
depth++;
} else if (current == '}') {
depth--;
if (depth == 0) {
return source.substring(start, index + 1);
}
}
}
throw new IllegalArgumentException("Unclosed source contract method: " + signature);
}
}
-1
View File
@@ -207,7 +207,6 @@ tasks.named('compileJava', JavaCompile).configure {
}
tasks.named('test').configure {
systemProperty('iris.moddedCommonSources', file('../modded-common/src/main/java').absolutePath)
}
loom {
-1
View File
@@ -240,7 +240,6 @@ tasks.named('compileJava', JavaCompile).configure {
}
tasks.named('test').configure {
systemProperty('iris.moddedCommonSources', file('../modded-common/src/main/java').absolutePath)
}
processResources {
@@ -73,15 +73,9 @@ public class IrisModLanguageAssetsTest {
private Set<String> resourceFiles() throws Exception {
URL resource = IrisModLanguageAssetsTest.class.getClassLoader().getResource(ROOT);
Path directory;
if (resource != null && "file".equals(resource.getProtocol())) {
directory = Path.of(resource.toURI());
} else {
String sources = System.getProperty("iris.moddedCommonSources");
assertNotNull("Missing mod language resource directory and source root", sources);
directory = Path.of(sources).getParent()
.resolve("resources").resolve(ROOT);
}
assertNotNull("Missing mod language resource directory: " + ROOT, resource);
assertEquals("Mod language resources must resolve to a directory on disk", "file", resource.getProtocol());
Path directory = Path.of(resource.toURI());
try (Stream<Path> paths = Files.list(directory)) {
return paths
.filter(Files::isRegularFile)
@@ -9,13 +9,9 @@ import net.minecraft.world.level.biome.MobSpawnSettings;
import org.junit.Test;
import org.junit.BeforeClass;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class IrisModdedChunkGeneratorSpawnTest {
@BeforeClass
@@ -48,21 +44,4 @@ public class IrisModdedChunkGeneratorSpawnTest {
assertEquals(explicitCow, entries.get(2).value());
assertEquals(3, entries.get(2).weight());
}
@Test
public void vanillaChunkGenerationMobsUseTheVisibleBiomesVanillaDerivative() throws IOException {
Path sourcePath = Path.of(System.getProperty("iris.moddedCommonSources"),
"art/arcane/iris/modded/IrisModdedChunkGenerator.java");
String source = Files.readString(sourcePath);
int spawnStart = source.indexOf("public void spawnOriginalMobs");
int spawnEnd = source.indexOf("@Override", spawnStart + 1);
String spawn = source.substring(spawnStart, spawnEnd);
assertTrue(spawn.contains("spawnTables.initializeVanillaSpawnBiomes(registry)"));
assertTrue(spawn.contains("structureBiomeSource.getVisibleSurfaceBiome("));
assertTrue(spawn.contains("spawnTables.vanillaSpawnBiome(visibleBiome.value())"));
assertTrue(spawn.contains("NaturalSpawner.spawnMobsForChunkGeneration("));
assertTrue(spawn.contains("new LegacyRandomSource(RandomSupport.generateUniqueSeed())"));
assertTrue(spawn.contains("random.setDecorationSeed(region.getSeed()"));
}
}
@@ -14,9 +14,6 @@ import net.minecraft.server.Bootstrap;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Locale;
import java.util.Set;
@@ -64,16 +61,10 @@ public class IrisModdedStructureParityTest {
}
@Test
public void strongholdRingSearchSamplesOneQuartColumnPerChunk() throws IOException {
public void strongholdRingSearchSamplesOneQuartColumnPerChunk() {
assertEquals(4, IrisModdedBiomeSource.horizontalBiomeSearchQuartStep(0, 112));
assertEquals(1, IrisModdedBiomeSource.horizontalBiomeSearchQuartStep(1, 112));
assertEquals(1, IrisModdedBiomeSource.horizontalBiomeSearchQuartStep(0, 111));
String source = Files.readString(Path.of(
System.getProperty("iris.moddedCommonSources"),
"art/arcane/iris/modded/IrisModdedBiomeSource.java"));
assertTrue(source.contains("x, y, z, searchRadius, quartStep, allowed, random, false, sampler"));
assertTrue(source.contains(
"return super.findBiomeHorizontal(x, y, z, searchRadius, allowed, random, sampler)"));
}
@Test
@@ -130,126 +121,12 @@ public class IrisModdedStructureParityTest {
}
@Test
public void visibleBiomeResolutionSelectsStackOwnershipBeforeHostCaves() throws IOException {
String source = Files.readString(Path.of(
System.getProperty("iris.moddedCommonSources"),
"art/arcane/iris/modded/IrisModdedBiomeSource.java"));
int resolutionStart = source.indexOf("private BiomeResolution resolveBiomeResolution(");
int resolutionEnd = source.indexOf("private Holder<Biome> resolveRequiredStructureBiome(", resolutionStart);
assertTrue(resolutionStart >= 0);
assertTrue(resolutionEnd > resolutionStart);
String resolution = source.substring(resolutionStart, resolutionEnd);
assertTrue(resolution.contains("resolveDimensionStackLayer("));
assertTrue(resolution.contains("!stackLayer.terrainContext().isSelfReferencing()"));
assertTrue(resolution.indexOf("resolveDimensionStackLayer(")
< resolution.indexOf("boolean underground"));
assertTrue(resolution.contains("includeDimensionStack"));
assertTrue(resolution.contains(
"return resolveBiomeResolution(engine, quartX, quartY, quartZ, false)"));
assertTrue(source.contains("resolution.packName(), resolution.dimension(), customBiome.getId()"));
int helperStart = source.indexOf("private static IrisBiome resolveSurfaceStructureBiome(");
int helperEnd = source.indexOf("private static Set<String> registeredBiomeKeys(", helperStart);
String helper = source.substring(helperStart, helperEnd);
assertTrue(helper.contains("engine.getComplex().getTrueBiomeStream().get(blockX, blockZ)"));
assertFalse(helper.contains("getDimensionStackContext()"));
assertFalse(helper.contains("getSurfaceBiome("));
}
@Test
public void stackBiomesAreVisibleButExcludedFromStructureReachability() throws IOException {
String source = Files.readString(Path.of(
System.getProperty("iris.moddedCommonSources"),
"art/arcane/iris/modded/IrisModdedBiomeSource.java"));
assertTrue(source.contains("return biomeKeySets().structureRequired()"));
assertTrue(source.contains("generatedBiomeKeys.addAll(keys.visibleRequired())"));
assertTrue(source.contains("collectStructureBiomeKeys("));
assertTrue(source.contains("dimension.getReachableBiomes(() -> data)"));
}
@Test
public void biomeLocatorSearchesTheVisibleStack() throws IOException {
String source = Files.readString(Path.of(
System.getProperty("iris.moddedCommonSources"),
"art/arcane/iris/modded/IrisModdedBiomeSource.java"));
int start = source.indexOf("public Pair<BlockPos, Holder<Biome>> findClosestBiome3d(");
int end = source.indexOf("private Holder<Biome> getNoiseBiome(", start);
String method = source.substring(start, end);
assertTrue(method.contains("modded_locate_visible_biome"));
assertTrue(method.contains("return super.findClosestBiome3d("));
assertTrue(method.contains("collectVisibleBiomeHolders()"));
assertTrue(method.contains("QuartPos.toBlock(quartX), QuartPos.toBlock(quartZ)"));
assertTrue(method.contains("resolveVisibleBiome("));
assertFalse(method.contains("Holder<Biome> structureBiome = getNoiseBiome("));
assertTrue(method.indexOf("tryAcquireGenerationLease(engine, \"modded_locate_visible_biome\")")
< method.indexOf("engine.getDimensionStackContext()"));
}
@Test
public void surfaceSpawnBiomeUsesTheVisibleQuartCell() throws IOException {
String source = Files.readString(Path.of(
System.getProperty("iris.moddedCommonSources"),
"art/arcane/iris/modded/IrisModdedBiomeSource.java"));
int start = source.indexOf("Holder<Biome> getVisibleSurfaceBiome(");
int end = source.indexOf("boolean isStructureReachable(", start);
String method = source.substring(start, end);
assertTrue(method.contains("QuartPos.fromBlock(blockX)"));
assertTrue(method.contains("QuartPos.toBlock(quartX)"));
assertTrue(method.contains("QuartPos.fromBlock(internalY + engine.getMinHeight())"));
assertTrue(method.contains("stackContext.getLayout(sampleX, sampleZ).surfaceLayer()"));
assertTrue(method.contains("visibleBiomeCache"));
assertTrue(method.contains("isBiomeCacheable(engine, sampleX, sampleZ)"));
assertTrue(method.indexOf("boolean cacheable = isBiomeCacheable(engine, sampleX, sampleZ)")
< method.indexOf("Engine.hostHeight(engine, sampleX, sampleZ, true)"));
assertCacheGuarded(method, "visibleBiomeCache");
}
@Test
public void temporaryNaturalBiomeAnswersAreNotMemoized() throws IOException {
public void temporaryNaturalBiomeAnswersAreNotMemoized() {
Engine engine = mock(Engine.class);
when(engine.answersFromNaturalTerrain(12, -8)).thenReturn(true);
assertFalse(IrisModdedBiomeSource.isBiomeCacheable(engine, 12, -8));
when(engine.answersFromNaturalTerrain(12, -8)).thenReturn(false);
assertTrue(IrisModdedBiomeSource.isBiomeCacheable(engine, 12, -8));
String source = Files.readString(Path.of(
System.getProperty("iris.moddedCommonSources"),
"art/arcane/iris/modded/IrisModdedBiomeSource.java"));
int structureStart = source.indexOf("private Holder<Biome> getNoiseBiome(Engine engine");
int structureEnd = source.indexOf("Holder<Biome> getVisibleNoiseBiome(", structureStart);
String structure = source.substring(structureStart, structureEnd);
assertTrue(structure.contains("QuartPos.toBlock(quartX)"));
assertTrue(structure.contains("QuartPos.toBlock(quartZ)"));
assertCacheGuarded(structure, "structureBiomeCache");
int visibleStart = source.indexOf(
"private Holder<Biome> getVisibleNoiseBiomeWithActiveGenerationLease(");
int visibleEnd = source.indexOf("Holder<Biome> getVisibleSurfaceBiome(", visibleStart);
String visible = source.substring(visibleStart, visibleEnd);
assertTrue(visible.contains("QuartPos.toBlock(quartX)"));
assertTrue(visible.contains("QuartPos.toBlock(quartZ)"));
assertCacheGuarded(visible, "visibleBiomeCache");
int predicateStart = source.indexOf("static boolean isBiomeCacheable(");
int predicateEnd = source.indexOf("static boolean isMonumentSurfaceBiomeQuery(", predicateStart);
String predicate = source.substring(predicateStart, predicateEnd);
assertTrue(predicate.contains("return !engine.answersFromNaturalTerrain(blockX, blockZ)"));
assertFalse(predicate.contains("getDimensionStackContext()"));
}
@Test
public void importedFeaturesCollectOnlyHostOwnedStackCells() throws IOException {
String source = Files.readString(Path.of(
System.getProperty("iris.moddedCommonSources"),
"art/arcane/iris/modded/ModdedImportedFeatureStage.java"));
assertTrue(source.contains("stackContext.getLayerAt("));
assertTrue(source.contains("layer.terrainContext().isSelfReferencing()"));
assertTrue(source.contains("section.getBiomes().get(quartX, quartY, quartZ)"));
}
@Test
@@ -281,17 +158,6 @@ public class IrisModdedStructureParityTest {
assertTrue(recursiveKeys.contains("layers:sky/aurora"));
}
@Test
public void biomeWriterDerivativeFallbackMatchesCanonicalRecursiveKeys() throws IOException {
String source = Files.readString(Path.of(
System.getProperty("iris.moddedCommonSources"),
"art/arcane/iris/modded/ModdedBiomeWriter.java"));
assertTrue(source.contains(
"key.equalsIgnoreCase(dimension.getCustomBiomeKey(custom.getId()))"));
assertFalse(source.contains("String dimensionLoadKey = key.substring(0, colon)"));
}
@Test
public void structureStateRejectsBiomesOutsideThePackContract() {
Set<String> generated = Set.of("minecraft:deep_ocean", "minecraft:dark_forest");
@@ -410,21 +276,4 @@ public class IrisModdedStructureParityTest {
public void initialEntitySpawnsUseThePaperCompletionMarker() {
assertSame(MantleFlag.INITIAL_SPAWNED_MARKER, ModdedWorldManager.INITIAL_SPAWN_COMPLETION_FLAG);
}
private static void assertCacheGuarded(String method, String cacheName) {
int predicate = method.indexOf("boolean cacheable = isBiomeCacheable(");
int cache = method.indexOf("BiomeHolderTable cache = " + cacheName, predicate);
int read = method.indexOf("cache.get(", predicate);
int readGuard = method.lastIndexOf("if (cacheable)", read);
int write = method.indexOf("cache.put(", read);
int writeGuard = method.lastIndexOf("if (cacheable)", write);
assertTrue(predicate >= 0);
assertTrue(cache >= 0);
assertTrue(read > predicate);
assertTrue(readGuard >= predicate);
assertTrue(write > read);
assertTrue(writeGuard > read);
}
}
@@ -1,91 +0,0 @@
package art.arcane.iris.modded;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertTrue;
public class ModdedDynamicLevelLifecycleContractTest {
private static final String SOURCE_ROOT_PROPERTY = "iris.moddedCommonSources";
@Test
public void sharedManagerPublishesDynamicLoadAndUnloadAroundRegistration() throws IOException {
String manager = commonSource("ModdedDimensionManager.java");
String loader = commonSource("ModdedLoader.java");
String injection = method(manager, "private static Handle inject(");
String removal = method(manager, "public static boolean remove(");
String injectionRollback = method(manager, "private static void rollbackInjection(");
String removalRollback = method(manager, "private static void rollbackRemoval(");
assertTrue(loader.contains("void fireDynamicLevelLoad(MinecraftServer server, ServerLevel level);"));
assertTrue(loader.contains("void fireDynamicLevelUnload(MinecraftServer server, ServerLevel level);"));
assertBefore(injection, "serverAccess.putLevelIfAbsent(server, key, level);",
"fireDynamicLevelLoad(server, level);");
assertBefore(removal, "fireDynamicLevelUnload(server, level);",
"serverAccess.removeLevel(server, key);");
assertTrue(injectionRollback.contains("fireDynamicLevelUnload(server, level);"));
assertTrue(removalRollback.contains("fireDynamicLevelLoad(server, level);"));
}
@Test
public void everyLoaderUsesItsNativeLifecycleBus() throws IOException {
String fabric = loaderSource("fabric", "art/arcane/iris/fabric/FabricModdedLoader.java");
String forge = loaderSource("forge", "art/arcane/iris/forge/ForgeModdedLoader.java");
String neoForge = loaderSource("neoforge", "art/arcane/iris/neoforge/NeoForgeModdedLoader.java");
assertTrue(fabric.contains("ServerLevelEvents.LOAD.invoker().onLevelLoad(server, level);"));
assertTrue(fabric.contains("ServerLevelEvents.UNLOAD.invoker().onLevelUnload(server, level);"));
assertTrue(forge.contains("LevelEvent.Load.BUS.post(new LevelEvent.Load(level));"));
assertTrue(forge.contains("LevelEvent.Unload.BUS.post(new LevelEvent.Unload(level));"));
assertTrue(neoForge.contains("NeoForge.EVENT_BUS.post(new LevelEvent.Load(level));"));
assertTrue(neoForge.contains("NeoForge.EVENT_BUS.post(new LevelEvent.Unload(level));"));
}
private static String commonSource(String file) throws IOException {
return Files.readString(commonRoot().resolve("art/arcane/iris/modded").resolve(file))
.replace("\r\n", "\n");
}
private static String loaderSource(String loader, String relative) throws IOException {
Path adaptersRoot = commonRoot().getParent().getParent().getParent().getParent();
return Files.readString(adaptersRoot.resolve(loader).resolve("src/main/java").resolve(relative))
.replace("\r\n", "\n");
}
private static Path commonRoot() {
String root = System.getProperty(SOURCE_ROOT_PROPERTY);
if (root == null || root.isBlank()) {
throw new IllegalStateException("Missing test property " + SOURCE_ROOT_PROPERTY);
}
return Path.of(root);
}
private static String method(String source, String signature) {
int start = source.indexOf(signature);
if (start < 0) {
throw new IllegalArgumentException("Missing source method " + signature);
}
int open = source.indexOf('{', start);
int depth = 0;
for (int index = open; index < source.length(); index++) {
char current = source.charAt(index);
if (current == '{') {
depth++;
} else if (current == '}' && --depth == 0) {
return source.substring(start, index + 1);
}
}
throw new IllegalArgumentException("Unclosed source method " + signature);
}
private static void assertBefore(String source, String first, String second) {
int firstIndex = source.indexOf(first);
int secondIndex = source.indexOf(second);
assertTrue("Missing source token " + first, firstIndex >= 0);
assertTrue("Missing source token " + second, secondIndex >= 0);
assertTrue(first + " must precede " + second, firstIndex < secondIndex);
}
}
@@ -7,12 +7,8 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.ChunkGenerator;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
@@ -24,8 +20,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class ModdedGenerationBootstrapBindingTest {
private static final String SOURCE_ROOT_PROPERTY = "iris.moddedCommonSources";
@Test
public void publishedLevelRequiresCurrentGeneratorIdentity() {
IrisModdedChunkGenerator generator = mock(IrisModdedChunkGenerator.class, CALLS_REAL_METHODS);
@@ -89,62 +83,4 @@ public class ModdedGenerationBootstrapBindingTest {
assertSame(dynamicLevel, generator.resolveBoundLevel(server, List.of(dynamicLevel)));
verify(server, never()).getLevel(Level.OVERWORLD);
}
@Test
public void firstGenerationStagesProvideAuthoritativeLevelContext() throws IOException {
String source = source("IrisModdedChunkGenerator.java");
String structures = method(source, "public void createStructures(");
String references = method(source, "public void createReferences(");
assertTrue(structures.contains("Engine current = engine(levelKey);"));
assertTrue(references.contains("Engine current = engine(level.getLevel());"));
String publishedBinding = method(source, "private Engine engine(ResourceKey<Level> levelKey)");
assertTrue(publishedBinding.contains("requirePublishedLevel(ModdedEngineBootstrap.currentServer(), levelKey)"));
assertTrue(publishedBinding.contains("return bindGenerationLevel(level);"));
assertFalse(publishedBinding.contains("ModdedServerLevels.level("));
String fullBinding = method(source, "private Engine bindGenerationLevel(ServerLevel level)");
assertTrue(fullBinding.contains("bindLevel(level);"));
assertTrue(fullBinding.contains("Engine bound = readyEngine();"));
String genericBinding = method(source, "Engine engine()");
assertTrue(genericBinding.contains("return bindGenerationLevel(level);"));
}
@Test
public void constructorMixinIsNotPartOfGenerationBootstrap() throws IOException {
String sourceRoot = System.getProperty(SOURCE_ROOT_PROPERTY);
assertTrue(sourceRoot != null && !sourceRoot.isBlank());
Path root = Path.of(sourceRoot);
assertFalse(Files.exists(root.resolve(Path.of("art", "arcane", "iris", "modded", "mixin",
"ServerLevelBindingMixin.java"))));
String mixinConfig = Files.readString(root.getParent().resolve("resources/irisworldgen.entity.mixins.json"));
assertFalse(mixinConfig.contains("ServerLevelBindingMixin"));
}
private String source(String fileName) throws IOException {
String sourceRoot = System.getProperty(SOURCE_ROOT_PROPERTY);
assertTrue(sourceRoot != null && !sourceRoot.isBlank());
return Files.readString(Path.of(sourceRoot, "art", "arcane", "iris", "modded", fileName));
}
private String method(String source, String signature) {
int start = source.indexOf(signature);
assertTrue(start >= 0);
int body = source.indexOf('{', start);
assertTrue(body >= 0);
int depth = 0;
for (int index = body; index < source.length(); index++) {
char token = source.charAt(index);
if (token == '{') {
depth++;
} else if (token == '}') {
depth--;
if (depth == 0) {
return source.substring(start, index + 1);
}
}
}
throw new IllegalArgumentException("Unclosed source contract method: " + signature);
}
}
@@ -1,203 +0,0 @@
package art.arcane.iris.modded;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class ModdedGenerationHistoryRoutingContractTest {
private static final String SOURCE_ROOT_PROPERTY = "iris.moddedCommonSources";
@Test
public void startupPublishesOnlyAnImmutableHistoryBoundRuntime() throws IOException {
String source = source("ModdedWorldEngines.java");
String create = method(source, "private static Engine create(");
String createHistoryEngine = method(source, "private static Engine createHistoryEngine(");
String buildEngine = method(source, "private static IrisEngine buildEngine(");
assertTrue(create.contains("ModdedGenerationHistoryStorage.openOrAdopt("));
assertFalse(create.contains("resolvePack("));
assertTrue(createHistoryEngine.contains("candidate.attachGenerationHistory("));
assertTrue(createHistoryEngine.contains("IrisBoundarySignatureSampler.INSTANCE"));
assertTrue(createHistoryEngine.contains("getGenerationTransitionWidthBlocks()"));
assertTrue(createHistoryEngine.contains("router.preloadActiveRuntimes();"));
assertBefore(createHistoryEngine, "history.prepareCurrentGenerator(",
"opened = ModdedGenerationHistoryStorage.resolveActive(history)");
assertBefore(createHistoryEngine, "opened = ModdedGenerationHistoryStorage.resolveActive(history)",
"IrisEngine candidate = buildEngine(level, seed, opened)");
String promoted = method(createHistoryEngine,
"if (history.activeActivation().activationId() != openedActivationId)");
assertBefore(promoted, "close(candidate);", "ModdedGenerationHistoryStorage.resolveActive(history)");
assertBefore(promoted, "ModdedGenerationHistoryStorage.resolveActive(history)",
"candidate = buildEngine(level, seed, promoted)");
assertTrue(createHistoryEngine.contains("GenerationHistoryRuntimeRouter.attach("));
assertTrue(buildEngine.contains("active.packRoot().toFile()"));
assertTrue(buildEngine.contains("history.paths().activationMantleRoot(activation.activationId())"));
assertTrue(buildEngine.contains("epoch.kernelVersion()"));
assertTrue(buildEngine.contains("transitionPlan"));
}
@Test
public void onlyExplicitTransientStudioEnginesBypassHistory() throws IOException {
String manager = source("ModdedDimensionManager.java");
String transientCreate = method(manager, "public static Handle createTransientStudio(");
String persistentCreate = method(manager, "public static Handle createPersistent(");
String engines = source("ModdedWorldEngines.java");
String studio = method(engines, "private static IrisEngine createTransientStudioEngine(");
String generator = source("IrisModdedChunkGenerator.java");
String bypass = method(generator, "boolean allowsGenerationHistoryBypass(");
String route = method(generator, "private GenerationHistoryRuntimeRouter.RuntimeRoute openHistoryRoute(");
assertTrue(transientCreate.contains("ModdedGenerationMode.TRANSIENT_STUDIO"));
assertTrue(persistentCreate.contains("ModdedGenerationMode.PERSISTENT_CREATE"));
assertTrue(studio.contains("IrisData.openRuntime(packDir)"));
assertTrue(studio.contains("IrisEngine.InitializationMode.STUDIO"));
assertFalse(studio.contains("ModdedGenerationHistoryStorage"));
assertFalse(studio.contains("attachGenerationHistory("));
assertTrue(bypass.contains("generationMode != ModdedGenerationMode.TRANSIENT_STUDIO"));
assertTrue(bypass.contains("irisEngine.isStudio()"));
assertTrue(bypass.contains("Only an explicitly transient Iris Studio engine"));
assertBefore(route, "allowsGenerationHistoryBypass(current)", "requireHistoryRouter(current, operation)");
}
@Test
public void everyCoordinateBearingChunkStageOpensItsRoutedRuntime() throws IOException {
String source = source("IrisModdedChunkGenerator.java");
assertRuntimeRoute(source, "public Pair<BlockPos, Holder<Structure>> findNearestMapStructure(");
assertCoordinateRoute(source, "public WeightedList<MobSpawnSettings.SpawnerData> getMobsAt(");
assertRuntimeRoute(source, "public CompletableFuture<ChunkAccess> createBiomes(");
assertRuntimeRoute(source, "public void applyCarvers(");
assertRuntimeRoute(source, "public void buildSurface(");
assertRuntimeRoute(source, "public void applyBiomeDecoration(");
assertRuntimeRoute(source, "public void createStructures(");
assertRuntimeRoute(source, "public void createReferences(");
assertRuntimeRoute(source, "public void spawnOriginalMobs(");
assertCoordinateRoute(source, "public int getBaseHeight(");
assertCoordinateRoute(source, "public NoiseColumn getBaseColumn(");
}
@Test
public void asyncTerrainKeepsTheRouteUntilDurableSemanticClaim() throws IOException {
String source = source("IrisModdedChunkGenerator.java");
String fill = method(source, "public CompletableFuture<ChunkAccess> fillFromNoise(");
String terrain = method(source, "private ChunkAccess generateTerrain(");
String completion = method(source, "private static CompletableFuture<ChunkAccess> closeRouteOnCompletion(");
assertBefore(fill, "openHistoryRoute(", "CompletableFuture.supplyAsync(");
assertTrue(fill.contains("generateTerrain(chunk, generationEngine, pos, air, route)"));
assertTrue(fill.contains("return closeRouteOnCompletion(pipeline, route);"));
assertTrue(terrain.contains("openHistoryRuntimeScope(route)"));
assertBefore(terrain, "generationEngine.generate(", "writeBlocks(chunk, blocks, dimMinY, height)");
assertBefore(terrain, "writeBlocks(chunk, blocks, dimMinY, height)", "route.claimGeneratedSemantics(");
assertTrue(terrain.contains("chunk.getBlockState(position.set(x, dimMinY + y, z))"));
assertTrue(terrain.contains("state.isAir() || state.liquid()"));
assertBefore(terrain, "route.claimGeneratedSemantics(", "ModdedNativeTerrainReceipts.persist(chunk, route)");
assertBefore(terrain, "ModdedNativeTerrainReceipts.persist(chunk, route)", "return chunk;");
assertTrue(completion.contains("pipeline.whenComplete("));
assertTrue(completion.contains("route.close();"));
assertBefore(completion, "pipeline.whenComplete(", "route.detachThread()");
assertBefore(completion, "route.detachThread()", "return completion;");
}
@Test
public void biomeQueriesRouteEachCoordinateAndKeepRuntimeSpecificCaches() throws IOException {
String source = source("IrisModdedBiomeSource.java");
String structure = method(source, "public Holder<Biome> getNoiseBiome(");
String visible = method(source, "Holder<Biome> getVisibleNoiseBiome(");
String batch = method(source, "public Set<Holder<Biome>> getBiomesWithin(");
String resolution = method(source, "private Holder<Biome> resolveVisibleBiome(");
assertTrue(structure.contains("openHistoryCoordinateScope("));
assertTrue(visible.contains("openHistoryCoordinateScope("));
assertTrue(batch.contains("quartX << 2, quartZ << 2"));
assertTrue(source.contains("int runtimeIdentity = engine.getCacheID();"));
assertTrue(source.contains("cache.get(runtimeIdentity, key)"));
assertTrue(source.contains("cache.put(runtimeIdentity, key, resolved)"));
assertBefore(resolution, "historicalPhysicalBiomeKeyAt(", "ModdedWorldgenIds.biomeRef(engine");
}
@Test
public void pendingNativeStagesPreserveSavedStartsAndGuardNewFeatureFootprints() throws IOException {
String generator = source("IrisModdedChunkGenerator.java");
String discrete = method(generator, "private boolean allowsRoutedDiscreteGeneration(");
String decoration = method(generator, "public void applyBiomeDecoration(");
String structures = method(generator, "public void createStructures(");
String mobs = method(generator, "public void spawnOriginalMobs(");
String nativeStage = source("ModdedNativeStructureStage.java");
String adjust = method(nativeStage, "void adjustGeneratedStructures(");
String place = method(nativeStage, "void placeVanillaStructures(");
String savedStart = method(nativeStage, "private boolean isHistoricalStructureStart(");
assertTrue(discrete.contains("chunk.getPersistedStatus().isOrAfter(stage)"));
assertFalse(discrete.contains("router.history().activeActivation().activationId()"));
assertFalse(discrete.contains("return true;"));
assertTrue(discrete.contains("allowsNewGenerationChunk("));
assertTrue(discrete.contains("NativeGenerationWriteGuard.allowsPendingStage(current, chunk, stage)"));
assertTrue(decoration.contains("ChunkStatus.FEATURES"));
assertTrue(structures.contains("ChunkStatus.STRUCTURE_STARTS"));
assertTrue(mobs.contains("ChunkStatus.SPAWN"));
assertBefore(decoration, "chunk.getPersistedStatus().isOrAfter(ChunkStatus.FEATURES)",
"nativeStructures.placeVanillaStructures(");
assertBefore(decoration, "nativeStructures.placeVanillaStructures(", "allowsRoutedDiscreteGeneration(");
assertBefore(decoration, "allowsRoutedDiscreteGeneration(", "importedFeatures.run(");
assertBefore(decoration, "NativeGenerationWriteGuard.allowsDecoration(", "importedFeatures.run(");
assertBefore(structures, "allowsRoutedDiscreteGeneration(", "super.createStructures(");
assertBefore(mobs, "allowsRoutedDiscreteGeneration(", "NaturalSpawner.spawnMobsForChunkGeneration(");
assertBefore(adjust, "allowsNewGenerationFootprint(", "recordWorldCheckStructureShift(");
assertBefore(place, "!isHistoricalStructureStart(current, world, start)", "allowsNewGenerationFootprint(");
assertTrue(savedStart.contains("world.getChunk(origin.x(), origin.z(), ChunkStatus.EMPTY, false)"));
assertTrue(savedStart.contains("ModdedNativeTerrainReceipts.structureActivation(source)"));
assertBefore(structures, "super.createStructures(", "ModdedNativeTerrainReceipts.persistStructureActivation(");
}
private static void assertRuntimeRoute(String source, String signature) {
String body = method(source, signature);
assertTrue(signature + " must open a generation-history route", body.contains("openHistoryRoute("));
assertTrue(signature + " must open its routed runtime", body.contains("openHistoryRuntimeScope(route)"));
}
private static void assertCoordinateRoute(String source, String signature) {
String body = method(source, signature);
assertTrue(signature + " must route its coordinate", body.contains("openHistoryCoordinateScope("));
}
private static void assertBefore(String source, String first, String second) {
int firstIndex = source.indexOf(first);
int secondIndex = source.indexOf(second);
assertTrue("Missing source contract token: " + first, firstIndex >= 0);
assertTrue("Missing source contract token: " + second, secondIndex >= 0);
assertTrue(first + " must occur before " + second, firstIndex < secondIndex);
}
private static String source(String fileName) throws IOException {
String sourceRoot = System.getProperty(SOURCE_ROOT_PROPERTY);
assertTrue("Missing system property " + SOURCE_ROOT_PROPERTY,
sourceRoot != null && !sourceRoot.isBlank());
return Files.readString(Path.of(sourceRoot, "art", "arcane", "iris", "modded", fileName));
}
private static String method(String source, String signature) {
int start = source.indexOf(signature);
assertTrue("Missing source contract signature: " + signature, start >= 0);
int openBrace = source.indexOf('{', start);
assertTrue("Missing source contract method body: " + signature, openBrace >= 0);
int depth = 0;
for (int index = openBrace; index < source.length(); index++) {
char current = source.charAt(index);
if (current == '{') {
depth++;
} else if (current == '}') {
depth--;
if (depth == 0) {
return source.substring(start, index + 1);
}
}
}
throw new IllegalArgumentException("Unclosed source contract method: " + signature);
}
}
@@ -1,244 +0,0 @@
package art.arcane.iris.modded;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class ModdedGenerationLeaseContractTest {
private static final String SOURCE_ROOT_PROPERTY = "iris.moddedCommonSources";
@Test
public void biomeRuntimeReadsAreGenerationLeased() throws IOException {
String source = source("art/arcane/iris/modded/IrisModdedBiomeSource.java");
assertTrue(source.contains("tryAcquireGenerationLease(engine, \"modded_structure_biome\")"));
assertTrue(source.contains("tryAcquireGenerationLease(engine, \"modded_visible_biome\")"));
assertTrue(source.contains("tryAcquireGenerationLease(engine, \"modded_biomes_within\")"));
assertTrue(source.contains("tryAcquireGenerationLease(engine, \"modded_structure_reachability\")"));
assertTrue(source.contains("tryAcquireGenerationLease(engine, \"modded_structure_state_biome\")"));
assertTrue(source.contains("tryAcquireGenerationLease(engine, \"modded_structure_biome_keys\")"));
assertTrue(source.contains("engine == null || engine.isClosed()"));
assertTrue(source.contains("catch (GenerationSessionException e)"));
assertTrue(source.contains("e.isExpectedTeardown()"));
assertTrue(source.contains("Iris structure biome key lookup was rejected during an engine transition"));
assertTrue(source.contains("int runtimeIdentity = engine.getCacheID();"));
assertTrue(source.contains("cache.get(runtimeIdentity, key)"));
assertTrue(source.contains("cache.put(runtimeIdentity, key, resolved)"));
}
@Test
public void terrainAndHeightQueriesShareGenerationSessions() throws IOException {
String source = source("art/arcane/iris/modded/IrisModdedChunkGenerator.java");
assertTrue(source.contains("generationEngine.acquireGenerationLease(\"modded_chunk_pipeline\")"));
assertTrue(source.contains("current.acquireGenerationLease(\"modded_base_height\")"));
assertTrue(source.contains("current.acquireGenerationLease(\"modded_base_column\")"));
assertTrue(source.contains("current.acquireGenerationLease(\"modded_configured_biome_keys\")"));
assertTrue(source.contains("generationEngine.isClosing() || e.isExpectedTeardown()"));
String terrain = method(source, "private ChunkAccess generateTerrain(");
int sessionFailure = terrain.indexOf("catch (GenerationSessionException e)");
int generalFailure = terrain.indexOf("catch (Throwable e)", sessionFailure);
String sessionHandler = terrain.substring(sessionFailure, generalFailure);
assertTrue(sessionHandler.contains("throw new IllegalStateException"));
assertFalse(sessionHandler.contains("return chunk;"));
String references = method(source, "public void createReferences(");
assertTrue(references.contains("requireGenerationLease(current, \"modded_create_references\")"));
assertTrue(references.contains("IrisContext.open(current, lease.sessionId(), null)"));
assertTrue(references.contains("NativeStructureReferenceRepair.createReferences("));
assertFalse(references.contains("super.createReferences(level, structureManager, chunk);"));
}
@Test
public void preservationDereferencesSharedPackData() throws IOException {
String source = source("art/arcane/iris/modded/service/ModdedPreservationService.java");
int dereference = source.indexOf("public void dereference()");
int irisData = source.indexOf("IrisData.dereference();", dereference);
int trackedResources = source.indexOf("threads.removeIf", dereference);
assertTrue(dereference >= 0);
assertTrue(irisData > dereference);
assertTrue(trackedResources > irisData);
}
@Test
public void hotloadShutdownOnlyTargetsItsOwnWorld() throws IOException {
String source = source("art/arcane/iris/modded/service/ModdedStudioHotloadService.java");
int shutdown = source.indexOf("public void shutdownPregenerator(Engine engine)");
int nextMethod = source.indexOf("private boolean throttled", shutdown);
String method = source.substring(shutdown, nextMethod);
assertTrue(method.contains("ModdedPregenJob.shutdownForWorld(world.identity());"));
assertFalse(method.contains("PregeneratorJob.shutdownInstance();"));
}
@Test
public void maintenanceOwnsOneGenerationSessionUntilWorkCompletes() throws IOException {
String source = source("art/arcane/iris/modded/service/ModdedEngineMaintenanceService.java");
String maintain = method(source, "private void maintain(Engine engine, long scheduledAt)");
assertTrue(maintain.contains("engine.acquireGenerationLease(\"modded_engine_maintenance\")"));
assertTrue(maintain.contains("IrisContext.open(engine, lease.sessionId(), null)"));
assertTrue(maintain.contains("exception.isExpectedTeardown()"));
assertTrue(source.contains("active.awaitTermination(INTERRUPT_DRAIN_TIMEOUT_SECONDS, TimeUnit.SECONDS)"));
}
@Test
public void packDownloadAdmissionPrecedesAsyncDispatch() throws IOException {
String source = source("art/arcane/iris/modded/command/IrisModdedCommands.java");
String download = method(source, "static int download(CommandSourceStack source, String rawRequest)");
int admission = download.indexOf("LifecycleOperationCoordinator.get().acquire(");
int executionTracking = download.indexOf("new PackDownloadExecution(");
int dispatch = download.indexOf("scheduler.asyncIfRunning(execution, execution::cancel)");
assertTrue(admission >= 0);
assertTrue(executionTracking > admission);
assertTrue(dispatch > admission);
assertTrue(download.contains("execution.cancel();"));
String execution = method(source, "private static void executeDownload(");
assertTrue(execution.contains("PackDownloader.DownloadCancellation cancellation"));
assertTrue(execution.contains("catch (PackDownloader.PackDownloadCancelledException error)"));
assertTrue(execution.contains("dispatchDownloadFeedback(source,"));
assertFalse(execution.contains("scheduler.global("));
assertFalse(execution.contains("lease.close();"));
String feedback = method(source, "private static void dispatchDownloadFeedback(");
assertTrue(feedback.contains("source.getServer().execute(feedback);"));
}
@Test
public void packDownloadsDrainBeforeModdedSchedulerShutdown() throws IOException {
String commands = source("art/arcane/iris/modded/command/IrisModdedCommands.java");
String shutdownDownloads = method(commands, "public static void shutdownDownloads()");
assertTrue(shutdownDownloads.contains("downloadAdmissionOpen = false;"));
assertTrue(shutdownDownloads.contains("execution.cancel();"));
assertTrue(shutdownDownloads.contains("execution.await("));
String bootstrap = source("art/arcane/iris/modded/ModdedEngineBootstrap.java");
String stop = method(bootstrap, "public static void stop()");
int downloads = stop.indexOf("IrisModdedCommands::shutdownDownloads");
int scheduler = stop.indexOf("scheduler::shutdown");
assertTrue(downloads >= 0);
assertTrue(scheduler > downloads);
}
@Test
public void moddedSchedulerRejectsAndCancelsAbandonedDownloadSubmissions() throws IOException {
String scheduler = source("art/arcane/iris/modded/ModdedScheduler.java");
String dispatch = method(scheduler, "public boolean asyncIfRunning(Runnable task, Runnable rejection)");
assertTrue(dispatch.contains("RejectionAwareTask"));
assertTrue(dispatch.contains("Objects.requireNonNull(rejection"));
String shutdown = method(scheduler, "public void shutdown()");
assertTrue(shutdown.contains("asyncExecutor.shutdownNow()"));
assertTrue(shutdown.contains("rejectAbandonedTasks(abandonedTasks);"));
String reset = method(scheduler, "public void reset()");
assertTrue(reset.contains("asyncExecutor.getQueue().drainTo(abandonedTasks);"));
assertTrue(reset.contains("rejectAbandonedTasks(abandonedTasks);"));
String rejection = method(scheduler, "private static void rejectAbandonedTasks(");
assertTrue(rejection.contains("rejectionAwareTask.reject();"));
}
@Test
public void blockingPregenShutdownDefersItsFinalSaveToTheServerThread() throws IOException {
String jobSource = source("art/arcane/iris/modded/command/ModdedPregenJob.java");
String shutdown = method(jobSource, "private static boolean shutdownAndSave(");
assertTrue(shutdown.contains("deferFinalSaveToServerThread()"));
assertTrue(shutdown.contains("completeDeferredFinalSave()"));
assertTrue(shutdown.contains("cancelDeferredFinalSave()"));
String methodSource = source("art/arcane/iris/modded/command/ModdedPregenMethod.java");
String close = method(methodSource, "public void close()");
assertTrue(close.contains("deferFinalSaveIfRequested()"));
String await = method(methodSource, "private void awaitFinalSave(");
assertTrue(await.contains("FINAL_SAVE_POLL_MILLIS"));
assertTrue(await.contains("deferFinalSaveIfRequested()"));
String complete = method(methodSource, "void completeDeferredFinalSave()");
int cancel = complete.indexOf("cancelQueuedFinalSave();");
int directSave = complete.indexOf("saveLevelOnServerThread();");
assertTrue(cancel >= 0);
assertTrue(directSave > cancel);
String queuedSave = method(methodSource, "private void executeFinalSave(");
assertTrue(queuedSave.contains("if (!request.claim())"));
String cancelRequest = method(methodSource, "private void cancelQueuedFinalSave()");
assertTrue(cancelRequest.contains("request.cancel();"));
String pending = method(methodSource, "boolean hasPendingFinalSave()");
assertTrue(pending.contains("queuedFinalSave.get() != null"));
}
@Test
public void firstPregenChunkFailureRetainsItsFullCause() throws IOException {
String methodSource = source("art/arcane/iris/modded/command/ModdedPregenMethod.java");
String logFailure = method(methodSource, "private void logChunkFailure(");
assertTrue(methodSource.contains("AtomicBoolean failureDetailLogged"));
assertTrue(logFailure.contains("unwrap(failure)"));
assertTrue(logFailure.contains("failureDetailLogged.compareAndSet(false, true)"));
assertTrue(logFailure.contains("x, z, cause);"));
assertTrue(logFailure.contains("cause.toString()"));
}
@Test
public void pregenReportsOnlyCleanupCallbacksFromCoveredTargets() throws IOException {
String source = source("art/arcane/iris/modded/command/ModdedPregenMethod.java");
String cleanup = method(source, "private void cleanupMantleChunksCoveredBy(");
assertTrue(source.contains("cleanupMantleChunksCoveredBy(x, z, listener);"));
assertFalse(source.contains("cleanupMantleChunk(x, z);"));
assertTrue(cleanup.contains("cleanupChunksCoveredBy(x, z, true, listener::onChunkCleaned)"));
assertFalse(cleanup.contains("forceCleanupChunk"));
}
@Test
public void invalidPregenBoundsFailBeforeRuntimeMutation() throws IOException {
String jobSource = source("art/arcane/iris/modded/command/ModdedPregenJob.java");
String start = method(jobSource, "public static boolean start(");
int taskConstruction = start.indexOf("PregenTask task = PregenTask.builder()");
int profileMutation = start.indexOf("PregenPerformanceProfile.apply(engine)");
assertTrue(taskConstruction >= 0);
assertTrue(profileMutation > taskConstruction);
String commandSource = source("art/arcane/iris/modded/command/ModdedPregenCommands.java");
String command = method(commandSource, "static int pregenStart(");
assertTrue(command.contains("catch (IllegalArgumentException failure)"));
assertTrue(command.contains("IrisModdedCommands.fail(source, failure.getMessage())"));
}
private static String source(String relativePath) throws IOException {
String root = System.getProperty(SOURCE_ROOT_PROPERTY);
assertTrue("Missing system property " + SOURCE_ROOT_PROPERTY, root != null && !root.isBlank());
return Files.readString(Path.of(root, relativePath));
}
private static String method(String source, String signature) {
int start = source.indexOf(signature);
assertTrue("Missing source contract signature: " + signature, start >= 0);
int openBrace = source.indexOf('{', start);
assertTrue("Missing source contract method body: " + signature, openBrace >= 0);
int depth = 0;
for (int index = openBrace; index < source.length(); index++) {
char current = source.charAt(index);
if (current == '{') {
depth++;
} else if (current == '}') {
depth--;
if (depth == 0) {
return source.substring(start, index + 1);
}
}
}
throw new IllegalArgumentException("Unclosed source contract method: " + signature);
}
}
@@ -2,32 +2,9 @@ package art.arcane.iris.modded;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Stream;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* The level router is a switch statement, which the compiler does not check for exhaustiveness. A level added
* to {@link art.arcane.iris.spi.LogLevel} with no arm here would compile and then drop every message at that
* level without a trace, so the fallback arm is what keeps a new level visible on the modded loaders.
*/
public class ModdedIrisLogLevelCoverageTest {
@Test
public void everyLogLevelReachesTheLoggerIncludingOnesAddedLater() throws IOException {
String source = Files.readString(Path.of(System.getProperty("iris.moddedCommonSources"),
"art/arcane/iris/modded/ModdedIrisLog.java"));
int router = source.indexOf("public static void log(LogLevel level, String message)");
assertTrue("log(LogLevel, String) not found", router >= 0);
String body = source.substring(router, source.indexOf("public static void debug(", router));
assertTrue(body, body.contains("default -> info(message);"));
}
@Test
public void slf4jStyleArgumentsAndTrailingThrowableArePreserved() {
RuntimeException failure = new RuntimeException("broken");
@@ -37,39 +14,4 @@ public class ModdedIrisLogLevelCoverageTest {
assertEquals("chunk 4,9 failed", rendered.message());
assertEquals(failure, rendered.error());
}
@Test
public void formattedDebugThrowableUsesTheVisibleDebugRouteWhenEnabled() throws IOException {
String source = Files.readString(Path.of(System.getProperty("iris.moddedCommonSources"),
"art/arcane/iris/modded/ModdedIrisLog.java"));
int start = source.indexOf("public static void debug(String format, Object... arguments)");
int end = source.indexOf("public static void info(String message)", start);
assertTrue("formatted debug overload not found", start >= 0);
assertTrue("formatted debug overload boundary not found", end > start);
String body = source.substring(start, end);
assertTrue(body, body.contains("if (!debugEnabled())"));
assertTrue(body, body.contains("LOGGER.info(\"[Iris/DEBUG] \" + clean(rendered.message()), rendered.error())"));
}
@Test
public void moddedProductionUsesTheIrisLogFrontDoor() throws IOException {
Path root = Path.of(System.getProperty("iris.moddedCommonSources"));
try (Stream<Path> files = Files.walk(root)) {
List<Path> bypasses = files
.filter(path -> path.toString().endsWith(".java"))
.filter(path -> !path.getFileName().toString().equals("ModdedIrisLog.java"))
.filter(path -> {
try {
String source = Files.readString(path);
return source.contains("LoggerFactory.getLogger")
|| source.contains("private static final Logger LOGGER");
} catch (IOException unreadable) {
throw new IllegalStateException(unreadable);
}
})
.toList();
assertTrue(bypasses.toString(), bypasses.isEmpty());
}
}
}
@@ -2,10 +2,6 @@ package art.arcane.iris.modded;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
@@ -48,25 +44,6 @@ public class ModdedLevelDataAttachmentTest {
assertNull(failure.getCause());
}
@Test
public void initializesLevelDataBeforeBindingAndPublication() throws IOException {
String source = Files.readString(sourcePath("ModdedDimensionManager.java"));
int construction = source.indexOf("ServerLevel level = new ServerLevel(");
int initialization = source.indexOf("serverAccess.initializeLevelData(server, level);", construction);
int binding = source.indexOf("generator.bindLevel(level);", initialization);
int publication = source.indexOf("serverAccess.putLevelIfAbsent(server, key, level);", binding);
assertTrue(construction >= 0);
assertTrue(initialization > construction);
assertTrue(binding > initialization);
assertTrue(publication > binding);
}
private static Path sourcePath(String fileName) {
return Path.of(System.getProperty("iris.moddedCommonSources"),
"art/arcane/iris/modded", fileName);
}
public static final class AttachedLevelData {
private RootData rootData;
private DimensionKey dimensionKey;
@@ -1,436 +0,0 @@
package art.arcane.iris.modded;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class ModdedLifecycleFailureContractTest {
private static final String SOURCE_ROOT_PROPERTY = "iris.moddedCommonSources";
@Test
public void existingDimensionStagesWithoutReplacingTheLiveEngine() throws IOException {
String managerSource = source("ModdedDimensionManager.java");
String create = method(managerSource, "private static Handle create(");
int existingStart = requiredIndex(create, "if (existing != null");
int presentStart = requiredIndex(create, "if (serverAccess.hasLevel(server, key))", existingStart + 1);
int injectionStart = requiredIndex(create, "try {", presentStart);
assertFalse(create.substring(existingStart, presentStart).contains("repointAndBind("));
assertFalse(create.substring(presentStart, injectionStart).contains("repointAndBind("));
assertBefore(create, "ModdedGenerationHistoryStorage.createOrStage(", "if (existing != null");
String generatorSource = source("IrisModdedChunkGenerator.java");
String repointAndBind = method(generatorSource, "void repointAndBind(");
assertBefore(repointAndBind, "ModdedWorldEngines.prepareReplacement(",
"ModdedWorldEngines.installReplacement(");
assertBefore(repointAndBind, "ModdedWorldEngines.installReplacement(", "this.activePack = pack;");
String failure = catchBlock(repointAndBind);
assertTrue(failure.contains("ModdedWorldEngines.closeUnregistered(replacement);"));
assertTrue(failure.contains("addSuppressed("));
String worldEnginesSource = source("ModdedWorldEngines.java");
String installReplacement = method(worldEnginesSource, "static void installReplacement(");
assertTrue(installReplacement.contains("ENGINES.compute("));
assertBefore(installReplacement, "close(current);", "return activeReplacement;");
assertFalse(installReplacement.contains("catch ("));
}
@Test
public void persistentPackUpdatesUseAnExplicitRestartBoundPath() throws IOException {
String managerSource = source("ModdedDimensionManager.java");
String createPersistent = method(managerSource, "public static Handle createPersistent(");
String update = method(managerSource, "public static UpdateResult stagePersistentUpdate(");
assertBefore(createPersistent, "if (previous != null)", "ModdedDimensionRegistryStore.put(");
assertTrue(createPersistent.contains("Use the Iris world update command"));
assertTrue(update.contains("ModdedGenerationHistoryStorage.createOrStage("));
assertTrue(update.contains("active.history().pendingActivation()"));
assertTrue(update.contains("restartRequired()"));
assertFalse(update.contains("inject("));
assertFalse(update.contains("repointAndBind("));
assertBefore(update, "ModdedDimensionRegistryStore.put(server, updated);",
"ModdedGenerationHistoryStorage.createOrStage(");
assertTrue(update.contains("ModdedDimensionRegistryStore.put(server, previous);"));
String commandsSource = source("command/ModdedWorldCommands.java");
assertTrue(commandsSource.contains("root.then(updateTree());"));
String command = method(commandsSource, "private static int update(");
assertTrue(command.contains("ModdedDimensionManager.stagePersistentUpdate("));
assertTrue(command.contains("Restart the server to activate it"));
assertTrue(command.contains("running world remains on its current pack"));
}
@Test
public void injectionBindsBeforeRegistrationAndRollsBackEveryFailure() throws IOException {
String source = source("ModdedDimensionManager.java");
String injection = method(source, "private static Handle inject(");
assertBefore(injection, "generator.bindLevel(level);", "serverAccess.putLevelIfAbsent(server, key, level);");
assertBefore(injection, "serverAccess.putLevelIfAbsent(server, key, level);",
"server.getPlayerList().addWorldborderListener(level);");
assertFalse(injection.contains("serverAccess.putLevel(server, key, previous);"));
String failure = catchBlock(injection);
assertBefore(failure, "rollbackInjection(", "throw ");
String rollback = method(source, "void rollbackInjection(");
assertBefore(rollback, "serverAccess.hasLevel(server, key)", "serverAccess.removeLevel(server, key);");
assertTrue(rollback.contains("generator.unbindEngine("));
assertTrue(rollback.contains("level.close();"));
assertTrue(rollback.contains("addSuppressed("));
}
@Test
public void persistentReinjectionQuarantinesBrokenEntriesAndContinues() throws IOException {
String source = source("ModdedStartup.java");
String reinjection = method(source, "private static void reinjectPersistentDimensions(");
String failure = catchBlock(reinjection);
assertTrue(failure.contains("ModdedIrisLog.error("));
assertFalse(failure.contains("e.toString()"));
assertFalse(failure.contains("throw new IllegalStateException("));
assertTrue(reinjection.contains("injected++;"));
}
@Test
public void persistentReinjectionWaitsForPlayerServicesAndServerStarted() throws IOException {
String bootstrapSource = source("ModdedEngineBootstrap.java");
String start = method(bootstrapSource, "public static void start(");
String serverAboutToStart = method(bootstrapSource, "public static void serverAboutToStart(");
String serverStarted = method(bootstrapSource, "public static void serverStarted(");
assertFalse(start.contains("ModdedStartup.runOnce(server);"));
assertFalse(serverAboutToStart.contains("ModdedStartup.runOnce(server);"));
assertEquals(1, occurrences(serverStarted, "ModdedStartup.runOnce(server);"));
assertBefore(serverStarted, "bindWorldGenerators(server);", "ModdedStartup.runOnce(server);");
assertBefore(serverStarted, "ModdedStartup.runOnce(server);", "reconcileSpawn(server);");
String startupSource = source("ModdedStartup.java");
String runOnce = method(startupSource, "public static void runOnce(");
assertBefore(runOnce, "server.getPlayerList() == null", "STARTED.compareAndSet(false, true)");
}
@Test
public void dynamicLevelMutationsInvalidateLoaderTickCaches() throws IOException {
String levelsSource = source("ModdedServerLevels.java");
String put = method(levelsSource, "public ServerLevel putLevel(");
String putIfAbsent = method(levelsSource, "public ServerLevel putLevelIfAbsent(");
String remove = method(levelsSource, "public ServerLevel removeLevel(");
assertBefore(put, "server.levels.put(key, level);", "levelCacheInvalidator.accept(server);");
assertTrue(put.contains("if (previous != level)"));
assertBefore(putIfAbsent, "server.levels.putIfAbsent(key, level);", "levelCacheInvalidator.accept(server);");
assertTrue(putIfAbsent.contains("if (previous == null)"));
assertBefore(remove, "server.levels.remove(key);", "levelCacheInvalidator.accept(server);");
assertTrue(remove.contains("if (removed != null)"));
String loaderSource = source("ModdedLoader.java");
assertTrue(loaderSource.contains("void invalidateLevelCache(MinecraftServer server);"));
String bootstrapSource = source("ModdedEngineBootstrap.java");
assertTrue(bootstrapSource.contains("new ModdedServerLevels(boundLoader::invalidateLevelCache)"));
}
@Test
public void persistentRestoreOpensHistoryBeforeConsultingTheGlobalPack() throws IOException {
String source = source("ModdedGenerationHistoryStorage.java");
String restore = method(source, "static GenerationHistory restoreOrAdopt(");
assertBefore(restore, "GenerationHistory.openIfPresent(", "sourceSupplier\").get();");
assertTrue(restore.contains("if (existing.isPresent())"));
assertBefore(restore, "requireRegistryDefinitions(existing.get()", "return existing.get();");
}
@Test
public void productionPackResolutionNeverUsesTheParityProbeAsData() throws IOException {
String source = source("ModdedWorldEngines.java");
String resolvePack = method(source, "static File resolvePack(");
assertFalse(source.contains("System.getProperty(\"iris.parity\")"));
assertFalse(source.contains("parityPack"));
assertFalse(source.contains("falling back to parity pack"));
assertTrue(resolvePack.contains("throw new IllegalStateException("));
}
@Test
public void engineBootstrapResetsStartupExactlyOnceDuringStop() throws IOException {
String source = source("ModdedEngineBootstrap.java");
String stop = method(source, "public static void stop(");
assertEquals(1, occurrences(stop, "ModdedStartup::reset"));
}
@Test
public void engineBootstrapAttemptsEveryShutdownStageAndAggregatesFailures() throws IOException {
String source = source("ModdedEngineBootstrap.java");
String stop = method(source, "public static void stop(");
assertBefore(stop, "\"services\"", "\"world engines\"");
assertBefore(stop, "\"world engines\"", "\"dimension manager\"");
assertBefore(stop, "\"server state\"", "if (failure != null)");
assertFalse(stop.contains("throw"));
assertTrue(stop.contains("ModdedIrisLog.error(\"Iris modded shutdown completed with failures\", failure);"));
String runStage = method(source, "private static Throwable runStopStage(");
assertTrue(runStage.contains("catch (Throwable stageFailure)"));
assertTrue(runStage.contains("failure.addSuppressed(stageFailure);"));
}
@Test
public void worldShutdownRemovesOnlySuccessfullyClosedMappings() throws IOException {
String source = source("ModdedWorldEngines.java");
String shutdown = method(source, "public static void shutdown()");
assertTrue(shutdown.contains("new ArrayList<>(ENGINES.entrySet())"));
assertFalse(shutdown.contains("ENGINES.clear()"));
// Bound generators must go through unbindEngine (latch unloading, then strict evict) so a
// late chunk-system drain cannot rebuild an engine nothing closes again.
assertTrue(shutdown.contains("generator.unbindEngine(level);"));
assertBefore(shutdown, "close(engine);", "ENGINES.remove(level, engine)");
assertTrue(shutdown.contains("ENGINES.containsKey(level)"));
assertTrue(shutdown.contains("failure.addSuppressed(e);"));
assertTrue(shutdown.contains("failed mappings were retained"));
}
@Test
public void engineEvictionRetainsTheMappingUntilCloseSucceeds() throws IOException {
String source = source("ModdedWorldEngines.java");
String eviction = method(source, "static void evictOrThrow(");
assertTrue(eviction.contains("ENGINES.computeIfPresent("));
assertFalse(eviction.contains("ENGINES.remove("));
assertBefore(eviction, "close(current);", "return null;");
}
@Test
public void generatorUnbindRetainsOwnershipWhenEvictionFails() throws IOException {
String source = source("IrisModdedChunkGenerator.java");
String unbind = method(source, "synchronized void unbindEngine(ServerLevel level)");
assertFalse(unbind.contains("finally"));
assertBefore(unbind, "unloading = true;", "ModdedWorldEngines.evictOrThrow(level);");
assertBefore(unbind, "ModdedWorldEngines.evictOrThrow(level);", "clearEngineBinding();");
String binding = method(source, "private Engine bindEngine(ServerLevel level)");
assertTrue(binding.contains("requireBindingAllowed();"));
assertTrue(binding.contains("requireCompletedShutdown(cached);"));
String bindLevel = method(source, "synchronized void bindLevel(ServerLevel level)");
assertBefore(bindLevel, "requireCompletedShutdown(engine);", "unloading = false;");
String boundEngine = method(source, "public Engine engineIfBound()");
assertTrue(boundEngine.contains("unloading || current == null || current.isClosing() || current.isClosed()"));
}
@Test
public void loaderUnloadSurfacesCloseFailureAndDynamicRemovalUsesStrictEviction() throws IOException {
String bootstrapSource = source("ModdedEngineBootstrap.java");
String unload = method(bootstrapSource, "public static void levelUnloaded(ServerLevel level)");
String failure = catchBlock(unload);
assertTrue(failure.contains("ModdedIrisLog.error("));
assertTrue(failure.contains("throw "));
String managerSource = source("ModdedDimensionManager.java");
String remove = method(managerSource, "public static boolean remove(MinecraftServer server, String dimensionId, boolean wipeStorage)");
assertTrue(remove.contains("ModdedWorldEngines.evictOrThrow(level);"));
assertFalse(remove.contains("ModdedWorldEngines.evict(level);"));
assertTrue(remove.contains("unloadEventStarted = true;"));
assertTrue(remove.contains("rollbackRemoval(server, serverAccess, key, level, generator, unloadEventStarted, e);"));
String rollback = method(managerSource, "private static void rollbackRemoval(");
assertTrue(rollback.contains("serverAccess.hasLevel(server, key)"));
assertTrue(rollback.contains("generator.bindLevel(level);"));
assertTrue(rollback.contains("failure.addSuppressed(rollbackFailure);"));
assertTrue(rollback.contains("ModdedIrisLog.error("));
}
@Test
public void engineBootstrapRollsBackEveryPublishedBindingBeforeRethrowing() throws IOException {
String source = source("ModdedEngineBootstrap.java");
String bind = method(source, "public static ModdedPlatform bind(");
String failure = catchBlock(bind);
assertBefore(bind, "createdServices.enableAll();", "runtime = new BoundRuntime(");
assertTrue(bind.contains("rollback.add(() -> GuiHost.suppressDesktop("));
assertTrue(bind.contains("rollback.add(() -> restorePlatform("));
assertTrue(bind.contains("rollback.add(() -> ModdedDimensionManager.restoreAccess("));
assertTrue(bind.contains("rollback.add(() -> IrisObjectRotation.restorePlatformRotator("));
assertTrue(bind.contains("rollback.add(() -> BlockDataMergeSupport.restorePlatformMerger("));
assertTrue(bind.contains("rollback.add(() -> TileData.restorePlatformReader("));
assertTrue(bind.contains("rollback.add(() -> TileData.restorePlatformFactory("));
assertTrue(bind.contains("rollback.add(() -> GuiHost.set("));
assertTrue(bind.contains("rollback.add(() -> DecoratorPlatformHooks.restore("));
assertTrue(bind.contains("bindService(PreservationRegistry.class"));
assertTrue(bind.contains("bindService(EngineEffectsProvider.class"));
assertTrue(bind.contains("bindService(EnginePlatformHooks.class"));
assertTrue(bind.contains("bindService(EngineWorldManagerProvider.class"));
assertTrue(bind.contains("rollback.add(customContentDiscovery::rollback);"));
assertBefore(failure, "createdServices.rollback(failure);", "rollback.restore(failure);");
assertBefore(failure, "rollback.restore(failure);", "throw ");
}
private static void assertBefore(String source, String first, String second) {
int firstIndex = requiredIndex(source, first);
int secondIndex = requiredIndex(source, second);
assertTrue(first + " must occur before " + second, firstIndex < secondIndex);
}
private static int requiredIndex(String source, String needle) {
return requiredIndex(source, needle, 0);
}
private static int requiredIndex(String source, String needle, int start) {
int index = source.indexOf(needle, start);
assertTrue("Missing source contract token: " + needle, index >= 0);
return index;
}
private static String source(String fileName) throws IOException {
String sourceRoot = System.getProperty(SOURCE_ROOT_PROPERTY);
assertTrue("Missing system property " + SOURCE_ROOT_PROPERTY,
sourceRoot != null && !sourceRoot.isBlank());
Path sourcePath = Path.of(sourceRoot, "art", "arcane", "iris", "modded", fileName);
return Files.readString(sourcePath);
}
private static String method(String source, String signature) {
int start = requiredIndex(source, signature);
int openBrace = openingBrace(source, start);
return source.substring(start, matchingBrace(source, openBrace) + 1);
}
/**
* Returns the block of the shallowest catch in the method, i.e. the one attached to the
* method's outermost try. Textual first-match would return a nested catch instead, and a
* nested catch handles a different failure than the one these contracts pin.
*/
private static String catchBlock(String source) {
int bodyStart = openingBrace(source, 0);
int depth = 0;
int bestDepth = Integer.MAX_VALUE;
int catchIndex = -1;
int i = bodyStart;
while (i < source.length()) {
int skipped = skipNonCode(source, i);
if (skipped > i) {
i = skipped;
continue;
}
char current = source.charAt(i);
if (current == '{') {
depth++;
} else if (current == '}') {
depth--;
if (depth == 0) {
break;
}
} else if (current == 'c' && depth < bestDepth && source.startsWith("catch (", i)) {
bestDepth = depth;
catchIndex = i;
}
i++;
}
assertTrue("Missing source contract token: catch (", catchIndex >= 0);
return blockAt(source, openingBrace(source, catchIndex));
}
private static String blockAt(String source, int openBrace) {
return source.substring(openBrace, matchingBrace(source, openBrace) + 1);
}
private static int openingBrace(String source, int start) {
int i = start;
while (i < source.length()) {
int skipped = skipNonCode(source, i);
if (skipped > i) {
i = skipped;
continue;
}
if (source.charAt(i) == '{') {
return i;
}
i++;
}
throw new IllegalArgumentException("No source block after offset " + start);
}
private static int matchingBrace(String source, int openBrace) {
int depth = 0;
int i = openBrace;
while (i < source.length()) {
int skipped = skipNonCode(source, i);
if (skipped > i) {
i = skipped;
continue;
}
char current = source.charAt(i);
if (current == '{') {
depth++;
} else if (current == '}') {
depth--;
if (depth == 0) {
return i;
}
}
i++;
}
throw new IllegalArgumentException("Unclosed source block");
}
/**
* Advances past a comment, string, char or text block starting at the index, otherwise returns
* the index unchanged. Comments must be skipped: an apostrophe in prose ("generator's") would
* otherwise open a char literal and swallow the rest of the file.
*/
private static int skipNonCode(String source, int index) {
char current = source.charAt(index);
if (current == '/' && index + 1 < source.length()) {
char next = source.charAt(index + 1);
if (next == '/') {
int end = source.indexOf('\n', index);
return end < 0 ? source.length() : end + 1;
}
if (next == '*') {
int end = source.indexOf("*/", index + 2);
return end < 0 ? source.length() : end + 2;
}
return index;
}
if (current == '"' && source.startsWith("\"\"\"", index)) {
int end = source.indexOf("\"\"\"", index + 3);
return end < 0 ? source.length() : end + 3;
}
if (current == '"' || current == '\'') {
return endOfLiteral(source, index, current);
}
return index;
}
private static int endOfLiteral(String source, int index, char terminator) {
for (int i = index + 1; i < source.length(); i++) {
char current = source.charAt(i);
if (current == '\\') {
i++;
continue;
}
if (current == terminator) {
return i + 1;
}
}
return source.length();
}
private static int occurrences(String source, String needle) {
int count = 0;
int offset = 0;
while (true) {
int index = source.indexOf(needle, offset);
if (index < 0) {
return count;
}
count++;
offset = index + needle.length();
}
}
}
@@ -5,13 +5,9 @@ import art.arcane.iris.engine.object.IrisEntitySpawn;
import art.arcane.volmlib.util.collection.KList;
import org.junit.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class ModdedSpawnerRarityParityTest {
private static IrisEntitySpawn spawn(int rarity) {
@@ -39,37 +35,4 @@ public class ModdedSpawnerRarityParityTest {
assertEquals(1, IRare.get(spawn(-5)));
assertEquals(3, IRare.get(spawn(3)));
}
@Test
public void perPositionSpawnLoopsDoNotRerollEntryRarity() throws Exception {
String source = Files.readString(Path.of(System.getProperty("iris.moddedCommonSources"),
"art/arcane/iris/modded/ModdedWorldManager.java"));
for (String method : List.of("private int spawnEntry(", "private int spawnEntryAt(")) {
String body = methodBody(source, method);
assertFalse(method + " must not re-roll rarity per position; rarityPick already weighted the pool",
body.contains("getRarity()"));
assertTrue(method + " must keep the min/max spawn-count roll",
body.contains("LootResolver.inclusive("));
}
}
private static String methodBody(String source, String declaration) {
int start = source.indexOf(declaration);
assertTrue("ModdedWorldManager must declare " + declaration, start >= 0);
int open = source.indexOf('{', start);
int depth = 0;
for (int index = open; index < source.length(); index++) {
char character = source.charAt(index);
if (character == '{') {
depth++;
} else if (character == '}') {
depth--;
if (depth == 0) {
return source.substring(open + 1, index);
}
}
}
throw new AssertionError(declaration + " is not brace balanced");
}
}
@@ -1,30 +0,0 @@
package art.arcane.iris.modded;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class ModdedStructurePlacementFailureContractTest {
@Test
public void structurePlacementPropagatesRuntimeFailuresWithContext() throws IOException {
Path sourcePath = Path.of(System.getProperty("iris.moddedCommonSources"),
"art/arcane/iris/modded/ModdedStructureHooks.java");
String source = Files.readString(sourcePath);
int methodStart = source.indexOf("public int[] placeStructure(");
int methodEnd = source.indexOf("\n @Override", methodStart + 1);
String method = source.substring(methodStart, methodEnd);
int catchStart = method.indexOf("catch (RuntimeException error)");
assertTrue(catchStart >= 0);
String failurePath = method.substring(catchStart);
assertTrue(failurePath.contains("throw NativeStructureGenerationException.failure("));
assertTrue(failurePath.contains("\"capture placement\", structureKey, chunkX, chunkZ, error"));
assertFalse(failurePath.contains("return null;"));
assertFalse(failurePath.contains("catch (Throwable"));
}
}
@@ -4,8 +4,6 @@ import org.junit.Test;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
@@ -64,14 +62,9 @@ public class ModdedStructureTemplateCacheTest {
config = new String(input.readAllBytes(), StandardCharsets.UTF_8);
}
assertTrue(config.contains("\"StructureTemplatePaletteConcurrencyMixin\""));
Path source = Path.of(System.getProperty("iris.moddedCommonSources"))
.resolve("art/arcane/iris/modded/mixin/StructureTemplatePaletteConcurrencyMixin.java");
String mixin = Files.readString(source);
assertTrue(mixin.contains("@Mixin(StructureTemplate.Palette.class)"));
assertTrue(mixin.contains("@Shadow\n @Final\n @Mutable"));
assertTrue(mixin.contains("private Map<Block, List<StructureTemplate.StructureBlockInfo>> cache;"));
assertTrue(mixin.contains("@Inject(method = \"<init>(Ljava/util/List;)V\", at = @At(\"RETURN\"))"));
assertTrue(mixin.contains("cache = new ConcurrentHashMap<>();"));
assertNotNull(Class.forName(
"art.arcane.iris.modded.mixin.StructureTemplatePaletteConcurrencyMixin",
false,
ModdedStructureTemplateCacheTest.class.getClassLoader()));
}
}
@@ -5,9 +5,6 @@ import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -26,32 +23,6 @@ public class ModdedWorldCheckTest {
assertTrue(thread.isDaemon());
}
@Test
public void poiAuditRunsInASecondServerTaskAfterVillageGeneration() throws IOException {
Path sourceRoot = Path.of(System.getProperty("iris.moddedCommonSources"));
String source = Files.readString(sourceRoot.resolve("art/arcane/iris/modded/ModdedWorldCheck.java"));
String auditSource = Files.readString(
sourceRoot.resolve("art/arcane/iris/modded/WorldCheckStructureAudit.java"));
int preparationSubmit = source.indexOf(
"WorldCheckPreparation preparation = serverRef.submit(() -> run(serverRef))");
int completionSubmit = source.indexOf(
"exitCode = serverRef.submit(() -> runAndRequestStop(", preparationSubmit);
int completionMethod = source.indexOf("private static boolean completeWorldCheck");
int deferredAudit = source.indexOf(
"PoiAudit poi = WorldCheckStructureAudit.auditStructurePois", completionMethod);
int structureMethod = auditSource.indexOf("private static StructureCheckResult checkNativeStructure");
int structureMethodEnd = auditSource.indexOf("private static StructureStart resolveStructureStart",
structureMethod);
String structureSource = auditSource.substring(structureMethod, structureMethodEnd);
assertTrue(preparationSubmit >= 0);
assertTrue(completionSubmit > preparationSubmit);
assertTrue(deferredAudit > completionMethod);
assertFalse(structureSource.contains("auditStructurePois"));
assertFalse(source.contains("prepareDeferredAudits"));
assertFalse(auditSource.contains("prepareDeferredAudits"));
}
@Test
public void validStructureStartIsGenerationEvidence() {
assertTrue(WorldCheckPredicates.hasNativeStructureEvidence(true, 0));
@@ -6,11 +6,6 @@ import net.minecraft.server.Bootstrap;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
@@ -22,25 +17,6 @@ public class NativeStructureFailureContractTest {
Bootstrap.bootStrap();
}
@Test
public void structureLocateDoesNotCatchAndFallThroughToAnotherImplementation() throws IOException {
String source = moddedSource("IrisModdedChunkGenerator.java");
int locateStart = source.indexOf("public Pair<BlockPos, Holder<Structure>> findNearestMapStructure");
int locateEnd = source.indexOf("public boolean isNativeStructureReachable", locateStart);
String locate = source.substring(locateStart, locateEnd);
String stage = moddedSource("ModdedNativeStructureStage.java");
int filterStart = stage.indexOf("HolderSet<Structure> filterReachableNativeStructures");
int filterEnd = stage.indexOf("void adjustGeneratedStructures", filterStart);
String filter = stage.substring(filterStart, filterEnd);
assertTrue(locate.contains("Engine current = engine();"));
assertFalse(locate.contains("catch (Throwable"));
assertFalse(locate.contains("return null;\n } catch"));
assertTrue(filter.contains("unregistered structure holder"));
assertFalse(filter.contains("catch (Throwable"));
assertFalse(filter.contains("failed closed"));
}
@Test
public void globalStructureDisableRefusesGeneratorBinding() {
IrisModdedChunkGenerator.requireGlobalStructureGeneration(true, "overworld:overworld");
@@ -56,66 +32,6 @@ public class NativeStructureFailureContractTest {
assertTrue(error.getMessage().contains("importedStructures.disabledExact"));
}
@Test
public void structureVegetationCleanupPrecedesTerrainPreparationAndPlacement() throws IOException {
String source = moddedSource("ModdedNativeStructureStage.java");
int placementStart = source.indexOf("void placeVanillaStructures");
int placementEnd = source.indexOf("private static String nativeStructureBatchContext", placementStart);
String placement = source.substring(placementStart, placementEnd);
assertTrue(placement.contains("\"terrain integration\""));
assertTrue(placement.contains("\"terrain preparation\""));
assertTrue(placement.contains("\"foundation repair\""));
assertFalse(placement.contains("\"terrain carving\""));
assertTrue(placement.contains("visitExistingPois(chunk"));
assertTrue(placement.contains("level.updatePOIOnBlockStateChange("));
assertTrue(placement.contains("Blocks.AIR.defaultBlockState(), state"));
assertTrue(placement.indexOf("visitExistingPois(chunk")
< placement.indexOf("WorldgenTerrainHeightmaps.primeStructurePlacement("));
assertTrue(placement.contains("prepareSurfaceStructures"));
assertTrue(placement.contains("clearIntersectingVegetation"));
assertTrue(placement.indexOf("clearIntersectingVegetation")
< placement.indexOf("prepareSurfaceStructures"));
assertTrue(placement.indexOf("prepareSurfaceStructures")
< placement.indexOf("for (NativePlacementGroup group"));
assertTrue(placement.indexOf("repairVacuumFoundations")
> placement.indexOf("for (NativePlacementGroup group"));
}
@Test
public void structurePlacementPrimesNeighbourWorldgenHeightmapsBeforeTerrainPreparation() throws IOException {
String source = moddedSource("ModdedNativeStructureStage.java");
int placementStart = source.indexOf("void placeVanillaStructures");
int placementEnd = source.indexOf("private static String nativeStructureBatchContext", placementStart);
String placement = source.substring(placementStart, placementEnd);
assertTrue(source.contains("import art.arcane.iris.nativegen.WorldgenTerrainHeightmaps;"));
assertTrue(placement.contains("WorldgenTerrainHeightmaps.primeStructurePlacement("));
assertTrue(placement.contains("\"heightmap priming\""));
assertTrue(placement.contains("heightmapStarts.add(start);"));
assertTrue(placement.indexOf("WorldgenTerrainHeightmaps.primeStructurePlacement(")
< placement.indexOf("prepareSurfaceStructures"));
assertTrue(source.contains("Engine.hostHeight(generationEngine, x, z, false) + runtimeMinY + 1"));
assertTrue(source.contains("Engine.hostHeight(generationEngine, x, z, true) + runtimeMinY + 1"));
assertTrue(placement.contains("current.getDimensionStackContext() != null"));
assertTrue(source.contains("int minY = chunk.getMinY() + 1;"));
}
@Test
public void nativeStructurePostProcessingUsesBoundedWorldgenAccess() throws IOException {
String source = moddedSource("ModdedNativeStructureStage.java");
int placementStart = source.indexOf("void placeVanillaStructures");
int placementEnd = source.indexOf("private List<List<Structure>> structuresByStep", placementStart);
String placement = source.substring(placementStart, placementEnd);
assertTrue(placement.contains("ModdedNativeStructureWorldgenAccess.create("));
assertTrue(placement.contains("nativeStructureProtection(current, staticObjects)"));
assertTrue(placement.contains("Engine.hostHeight(current, x, z, true)"));
assertTrue(placement.contains("placeVanillaStructure(boundedWorld, structureManager"));
assertFalse(placement.contains("NativeStructurePostProcessor.place(world,"));
assertTrue(placement.contains("world.setCurrentlyGenerating(null);"));
}
@Test
public void structureFailurePreservesPhaseIdentityChunkAndCause() {
IllegalArgumentException cause = new IllegalArgumentException("broken placement");
@@ -128,10 +44,4 @@ public class NativeStructureFailureContractTest {
assertTrue(error.getMessage().contains("12,-8"));
assertTrue(error.getMessage().contains("aborted"));
}
private static String moddedSource(String fileName) throws IOException {
Path sourcePath = Path.of(System.getProperty("iris.moddedCommonSources"),
"art", "arcane", "iris", "modded", fileName);
return Files.readString(sourcePath);
}
}
@@ -7,9 +7,6 @@ import com.mojang.datafixers.util.Pair;
import net.minecraft.core.BlockPos;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
@@ -48,30 +45,6 @@ public class IrisModdedStructureCommandTest {
assertEquals(1, nativeReferences.get());
}
@Test
public void gotoStructureSupportsIrisAndNativeRegistryTargets() throws IOException {
String source = source("ModdedLocateCommands.java");
String suggestions = source("ModdedCommandSuggestions.java");
assertTrue(source.contains("IrisStructureLocator.hasLocatableEditablePlacement(engine, key)"));
assertTrue(source.contains("registry.get(identifier)"));
assertTrue(source.contains("getPlacementsForStructure(holder)"));
assertTrue(source.contains("generator.findNearestMapStructure("));
assertTrue(source.contains("NATIVE_STRUCTURE_LOCATE_RADIUS = 100"));
assertTrue(source.contains("HolderSet.direct(target.holder())"));
assertFalse(source.contains("NativeStructureLocateCapability"));
assertTrue(source.contains("boolean teleported = player.teleportTo("));
assertTrue(suggestions.contains("combineStructureKeys(unregisteredIrisKeys, nativeKeys)"));
assertTrue(source.contains("irisGenerator.isNativeStructureReachable(holder)"));
assertTrue(source.contains("LocateStatus.SEARCH_LIMIT_REACHED"));
assertTrue(source.contains("IRIS_MODDED_COMMANDS_UNABLE_LOCATE_IRIS_PLACED_STRUCTURE_DENSITY_SEARCH_SAFETY_LIMIT_WAS"));
assertTrue(source.contains("int targetX = result.originX()"));
assertTrue(source.contains("int targetY = result.baseY() + 2"));
assertTrue(source.contains("int targetZ = result.originZ()"));
assertFalse(source.contains("at[0] + 8"));
assertFalse(source.contains("at[2] + 8"));
}
@Test
public void registeredStructureEligibilityMatchesGotoAndSuggestions() {
IrisNativeStructureDecision nativeDecision = decision(NativeStructureGenerationStatus.GENERATE_NATIVE);
@@ -175,162 +148,6 @@ public class IrisModdedStructureCommandTest {
.contains("non-positive density or a Y band outside"));
}
@Test
public void unregisteredCommandUsesGotoEligibilityAndPrintsToConsole() throws IOException {
String command = source("ModdedUnregisteredStructures.java");
String tree = source("ModdedCommandTree.java");
assertTrue(tree.contains("Commands.literal(\"unregistered\")"));
assertTrue(tree.contains("ModdedUnregisteredStructures.print(context.getSource())"));
assertTrue(command.contains("ModdedCommandSuggestions.isEligibleRegisteredStructure("));
assertTrue(command.contains("ModdedLocateCommands.registeredStructureUnavailableMessage("));
assertTrue(command.contains("engine.getData().getStructureLoader().getPossibleKeys()"));
assertTrue(command.contains("IrisStructureLocator.hasLocatableEditablePlacement(engine, key)"));
assertTrue(command.contains("ModdedIrisLog.info(\"[Iris goto unregistered] [{}] {} - {}\""));
assertTrue(command.contains("UNREGISTERED(\"unregistered\")"));
assertFalse(command.contains("DatapackIngestService"));
}
@Test
public void structureSuggestionsUseActiveLevelAvailability() throws IOException {
String suggestions = source("ModdedCommandSuggestions.java");
int methodStart = suggestions.indexOf("static CompletableFuture<Suggestions> suggestStructureKeys(");
int methodEnd = suggestions.indexOf("static boolean isEligibleRegisteredStructure(", methodStart);
String method = suggestions.substring(methodStart, methodEnd);
assertTrue(method.contains("ServerLevel level = source.getLevel()"));
assertTrue(method.contains("Engine engine = IrisModdedCommands.engineFor(level)"));
assertFalse(method.contains("IrisStructureLocator.locatableKeys(engine)"));
assertTrue(method.contains("IrisStructureLocator.locatableEditableKeys(engine)"));
assertTrue(method.contains("StructureReachability.reachableKeys(engine)"));
assertTrue(method.contains("NativeStructureGenerationPolicy.resolve(engine, key, false)"));
assertTrue(method.contains("IrisStructureLocator.hasLocatableNativePlacement(engine, key)"));
assertTrue(method.contains("IrisStructureLocator.hasLocatableEditablePlacement(engine, key)"));
assertTrue(method.contains("reachableNativeKeys.contains(normalizeKey(key))"));
assertTrue(method.contains("nativeGenerationEnabled"));
assertTrue(method.contains("eligibleUnregisteredEditableKeys("));
assertTrue(method.contains("IrisStructureLocator.hasNativePlacement(engine, candidate)"));
assertFalse(method.contains("NativeStructureGenerationKeys.active(level)"));
assertFalse(method.contains("getPlacementsForStructure"));
}
@Test
public void generatorLocateUsesEveryIrisPlacedNativeStructure() throws IOException {
String source = moddedSource("ModdedNativeStructureStage.java");
int methodStart = source.indexOf("Pair<BlockPos, Holder<Structure>> findNearestIrisStructure(");
int methodEnd = source.indexOf("HolderSet<Structure> filterReachableNativeStructures(", methodStart);
String method = source.substring(methodStart, methodEnd);
int registryLookup = method.indexOf("level.registryAccess().lookupOrThrow(Registries.STRUCTURE)");
int placedCheck = method.indexOf(
"if (!IrisStructureLocator.hasNativePlacement(current, structureId))");
int irisLocate = method.indexOf("NativeStructureLocatePersistence.search(", placedCheck);
int nearestSelection = method.indexOf(
"NativeStructureLocateResults.nearest(pos, predicted, nativeLocated)", irisLocate);
int selectedVerification = method.indexOf("bestSearch.search().verify(bestResult)", nearestSelection);
int selectedReference = method.indexOf(
"selectedSearch.search().reference(selectedStart)", selectedVerification);
assertTrue(registryLookup >= 0);
assertTrue(placedCheck > registryLookup);
assertTrue(irisLocate > placedCheck);
assertTrue(nearestSelection > irisLocate);
assertTrue(selectedVerification > nearestSelection);
assertTrue(selectedReference > selectedVerification);
assertTrue(method.contains("NativeStructureLocatePersistence.probe("));
assertTrue(method.contains("findUnexplored"));
assertTrue(method.contains("LocateStatus.SEARCH_LIMIT_REACHED"));
assertTrue(method.contains("verified.ownership().locatorY()"));
assertTrue(method.contains("selectedSearch.search().reference(selectedStart)"));
assertTrue(method.contains("NativeStructureLocateResults.selectAndReference("));
assertFalse(method.contains("NativeStructureLocateCapability"));
assertTrue(source.contains("structureBiomeSource.isStructureReachable(holder)"));
assertFalse(source.contains("isPaperUnavailable"));
String generator = moddedSource("IrisModdedChunkGenerator.java");
assertTrue(generator.contains("NativeStructureVanillaLocator.predict("));
assertFalse(generator.contains("super.findNearestMapStructure(level, reachable"));
}
@Test
public void commandResolvesNativePolicyBeforeAnyVanillaAliasLookup() throws IOException {
String source = source("ModdedLocateCommands.java");
int methodStart = source.indexOf("static int gotoStructure(");
int methodEnd = source.indexOf("private static void locateIrisStructure(", methodStart);
String method = source.substring(methodStart, methodEnd);
int nativeResolution = method.indexOf("resolveNativeStructure(source, level, engine, key)");
int editableIrisLookup = method.indexOf(
"IrisStructureLocator.hasLocatableEditablePlacement(engine, key)", nativeResolution);
int policyResolution = method.indexOf(
"NativeStructureGenerationPolicy.resolve(engine, target.key(), false)", editableIrisLookup);
int eligibilityCheck = method.indexOf(
"ModdedCommandSuggestions.isEligibleRegisteredStructure(", policyResolution);
int replacementLocate = method.indexOf(
"locateIrisStructure(source, level, engine, player, target.key())", eligibilityCheck);
int nativeLocate = method.indexOf("runNativeStructureLocate(source, level, player, target)",
replacementLocate);
assertTrue(nativeResolution >= 0);
assertTrue(editableIrisLookup > nativeResolution);
assertTrue(policyResolution > editableIrisLookup);
assertTrue(eligibilityCheck > policyResolution);
assertTrue(replacementLocate > eligibilityCheck);
assertTrue(nativeLocate > replacementLocate);
assertTrue(method.contains("IrisStructureLocator.hasLocatableNativePlacement(engine, target.key())"));
assertTrue(method.contains("IrisStructureLocator.hasLocatableEditablePlacement(engine, target.key())"));
assertTrue(method.contains("!IrisStructureLocator.hasNativePlacement(engine, key)"));
assertTrue(method.contains("StructureReachability.isReachable(engine, target.key())"));
assertTrue(method.contains("getWorldGenSettings().options().generateStructures()"));
assertFalse(method.contains("IrisStructureLocator.isPlaced(engine, key)"));
}
@Test
public void verifyResolvesRegisteredNativeBeforeGenericIrisAliases() throws IOException {
String source = source("ModdedLocateCommands.java");
int methodStart = source.indexOf("private static int verifyStructure(");
int methodEnd = source.indexOf("private static Optional<NativeStructureTarget> resolveNativeStructure(",
methodStart);
String method = source.substring(methodStart, methodEnd);
int nativeResolution = method.indexOf("resolveNativeStructure(source, level, engine, key)");
int genericIrisLookup = method.indexOf("IrisStructureLocator.isPlaced(engine, key)", nativeResolution);
assertTrue(nativeResolution >= 0);
assertTrue(genericIrisLookup > nativeResolution);
assertTrue(method.contains("NativeStructureAvailability.IRIS_SUPPRESSED"));
}
@Test
public void structureVerificationNoLongerClaimsNativeGenerationIsMissing() throws IOException {
String source = source("ModdedStructureCommands.java");
assertTrue(source.contains("verifyTree(\"verify\")"));
assertTrue(source.contains("verifyTree(\"locateall\")"));
assertTrue(source.contains("IrisModdedCommands.verifyStructures("));
assertFalse(source.contains("Vanilla structure locate is meaningless here"));
}
private String source(String fileName) throws IOException {
Path source = commonSourceRoot().resolve("art/arcane/iris/modded/command/")
.resolve(fileName)
.normalize();
return Files.readString(source);
}
private String moddedSource(String fileName) throws IOException {
Path source = commonSourceRoot().resolve("art/arcane/iris/modded/")
.resolve(fileName)
.normalize();
return Files.readString(source);
}
private Path commonSourceRoot() {
String configuredRoot = System.getProperty("iris.moddedCommonSources");
if (configuredRoot != null && !configuredRoot.isBlank()) {
return Path.of(configuredRoot);
}
return Path.of(System.getProperty("user.dir"))
.resolve("../modded-common/src/main/java")
.normalize();
}
private IrisNativeStructureDecision decision(NativeStructureGenerationStatus status) {
return new IrisNativeStructureDecision(status, 0, null, false, null, null);
}
@@ -1,28 +0,0 @@
package art.arcane.iris.modded.command;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public final class ModdedRiverLocateContractTest {
@Test
public void riverLookupMergesRecordedAndEligibleActiveFeatures() throws IOException {
Path sourcePath = Path.of(System.getProperty("iris.moddedCommonSources"))
.resolve("art/arcane/iris/modded/command/ModdedLocateCommands.java");
String source = Files.readString(sourcePath);
int methodStart = source.indexOf("static int gotoRiver(");
int methodEnd = source.indexOf("static int gotoStructure(", methodStart);
String method = source.substring(methodStart, methodEnd);
assertTrue(method.contains("GenerationSemanticQueries.nearestRiver("));
assertTrue(method.contains("runtime == null"));
assertTrue(method.contains("feature.y() + 2"));
assertFalse(method.contains("runtime.nearestFeature("));
assertFalse(method.contains("feature.y() + engine.getDimension().getMinHeight()"));
}
}
@@ -1,34 +0,0 @@
package art.arcane.iris.modded.command;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public final class ModdedStructureHistoryContractTest {
@Test
public void retainedStructureNamesReachTheSemanticSearchOnBothAdmissionBranches() throws IOException {
Path root = Path.of(System.getProperty("iris.moddedCommonSources"));
String source = Files.readString(root.resolve("art/arcane/iris/modded/command/ModdedLocateCommands.java"));
int start = source.indexOf("static int gotoStructure(");
int end = source.indexOf("static String registeredStructureUnavailableMessage(", start);
String admission = source.substring(start, end);
String retainedCheck = "GenerationFindCatalog.hasRetainedStructurePlacement(engine, key)";
int firstCheck = admission.indexOf(retainedCheck);
assertTrue(firstCheck >= 0);
assertTrue(admission.indexOf(retainedCheck, firstCheck + retainedCheck.length()) >= 0);
int locateStart = source.indexOf("private static void locateIrisStructure(");
int locateEnd = source.indexOf("private static void runNativeStructureLocate(", locateStart);
String locate = source.substring(locateStart, locateEnd);
assertTrue(locate.contains("GenerationSemanticQueries.nearestStructure("));
assertFalse(locate.contains("IrisStructureLocator.locate("));
String suggestions = Files.readString(root.resolve("art/arcane/iris/modded/command/ModdedCommandSuggestions.java"));
assertTrue(suggestions.contains("GenerationFindCatalog.retainedStructureKeys(engine)"));
}
}
@@ -1,89 +0,0 @@
package art.arcane.iris.modded.command;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class ModdedStudioTeleportContractTest {
private static final String SOURCE_ROOT_PROPERTY = "iris.moddedCommonSources";
@Test
public void studioOpenSerializesReplacementAndWaitsForTheNativePath() throws IOException {
String source = source("command/ModdedStudioCommands.java");
String open = method(source, "private static int open(");
String execute = method(source, "private static void executeStudioOpen(");
assertTrue(open.contains("TRANSITIONS.submit("));
assertFalse(open.contains("orTimeout("));
assertFalse(open.contains("deadlineNanos"));
assertBefore(execute, "replaceExistingStudio(", "ModdedDimensionManager.createTransientStudio(");
assertBefore(execute, "ModdedDimensionManager.createTransientStudio(", "ModdedDimensionManager.teleportAsync(");
assertFalse(execute.contains("deadlineNanos"));
assertFalse(source.contains("player.teleportTo(studio"));
}
@Test
public void studioTeleportAndVisionShareWarmFutureSemantics() throws IOException {
String studio = source("command/ModdedStudioCommands.java");
String vision = source("command/ModdedVisionOverlay.java");
String dimensions = source("ModdedDimensionManager.java");
assertTrue(studio.contains("private static CompletableFuture<Void> teleportToStudio("));
assertTrue(studio.contains("ModdedDimensionManager.teleportAsync("));
assertTrue(dimensions.contains("TELEPORT_WARM_RADIUS = 0"));
assertTrue(dimensions.contains("addTicketAndLoadWithRadius(\n"
+ " TELEPORT_WARM_TICKET,\n"
+ " chunkPos,\n"
+ " TELEPORT_WARM_RADIUS)"));
assertTrue(dimensions.contains("removeTicketWithRadius(\n"
+ " TELEPORT_WARM_TICKET,\n"
+ " chunkPos,\n"
+ " TELEPORT_WARM_RADIUS)"));
assertTrue(vision.contains("Math.floor(worldX)"));
assertTrue(vision.contains("Math.floor(worldZ)"));
assertTrue(vision.contains("if (opener != null)"));
assertTrue(vision.contains("ModdedDimensionManager.teleportAsync("));
assertFalse(vision.contains("level.getHeight("));
assertFalse(vision.contains("player.teleportTo("));
}
private static String source(String relative) throws IOException {
String root = System.getProperty(SOURCE_ROOT_PROPERTY);
if (root == null || root.isBlank()) {
throw new IllegalStateException("Missing test property " + SOURCE_ROOT_PROPERTY);
}
return Files.readString(Path.of(root).resolve("art/arcane/iris/modded").resolve(relative))
.replace("\r\n", "\n");
}
private static String method(String source, String signature) {
int start = source.indexOf(signature);
if (start < 0) {
throw new IllegalArgumentException("Missing source method " + signature);
}
int open = source.indexOf('{', start);
int depth = 0;
for (int index = open; index < source.length(); index++) {
char current = source.charAt(index);
if (current == '{') {
depth++;
} else if (current == '}' && --depth == 0) {
return source.substring(start, index + 1);
}
}
throw new IllegalArgumentException("Unclosed source method " + signature);
}
private static void assertBefore(String source, String first, String second) {
int firstIndex = source.indexOf(first);
int secondIndex = source.indexOf(second);
assertTrue("Missing source token " + first, firstIndex >= 0);
assertTrue("Missing source token " + second, secondIndex >= 0);
assertTrue(first + " must precede " + second, firstIndex < secondIndex);
}
}
-1
View File
@@ -222,7 +222,6 @@ tasks.named('compileJava', JavaCompile).configure {
tasks.named('test').configure {
useJUnitPlatform()
systemProperty('iris.moddedCommonSources', file('../modded-common/src/main/java').absolutePath)
}
processResources {
@@ -1,182 +0,0 @@
package art.arcane.iris.core;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Stream;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Every core diagnostic keeps its severity through to the server log, so the level a call site picks is the
* level an operator scanning for WARN and SEVERE sees. This pins the two ends of that decision: conditions an
* operator must act on stay at WARN or ERROR, and conditions that repeat per block, per sample or per chunk -
* or that report designed backpressure, a probe on an optional dependency, or a success - do not.
* <p>
* The pin is on the source rather than on a live engine because most of these call sites need a running world
* to reach, and what is being fixed is the choice of level, not the condition that triggers it.
*/
public class DiagnosticSeverityPolicyTest {
@Test
public void perBlockAndPerSampleConditionsDoNotReachTheServerLogAtWarnLevel() {
assertLoggedWith("util/project/hunk/Hunk.java", "OUT OF BOUNDS ", "debug");
assertLoggedWith("engine/mantle/MantleWriter.java", "No set? ", "debug");
assertLoggedWith("engine/mantle/MantleWriter.java", "Mantle Writer Accessed chunk out of bounds", "debug");
assertLoggedWith("engine/object/IrisDecorator.java", "Empty Block Data for ", "warnOnce");
assertLoggedWith("engine/object/IrisCompat.java", "Can't find block data for ", "warnOnce");
assertLoggedWith("engine/data/cache/AtomicCache.java", "Atomic cache supplier failed: %s: %s", "warnOnce");
assertLoggedWith("engine/IrisComplex.java", "Failed to sample interpolated biome bounds", "warnOnce");
assertLoggedWith("engine/framework/placer/WorldObjectPlacer.java", "Tried to place custom block at", "warnOnce");
}
/**
* Backpressure pausing generation is the design working. It is reported every five seconds for the whole
* duration of a large pregen, so at WARN it would be the only thing a log scan finds.
*/
@Test
public void designedBackpressureIsReportedWithoutRaisingAWarning() {
assertLoggedWith("core/pregenerator/PregenMantleBackpressure.java", "Pregen mantle backpressure: ", "info");
assertLoggedWith("core/pregenerator/PregenMantleBackpressure.java", "Pregen heap pressure: pausing generation", "info");
assertLoggedWith("core/pregenerator/MantleHeapPressure.java", "Iris heap remained at", "info");
assertLoggedWith("core/pregenerator/methods/AsyncPregenMethod.java", "is still pending after", "debug");
}
@Test
public void generationTracingStaysAtDebugLevel() {
assertLoggedWith("engine/mantle/components/MantleObjectComponent.java", "Regen object layer start:", "debug");
assertLoggedWith("engine/mantle/components/MantleObjectComponent.java", "Goldendebug object attempt:", "debug");
assertLoggedWith("engine/mantle/components/GoldenDebugObjectPlacer.java", "Goldendebug query:", "debug");
assertLoggedWith("engine/mantle/components/IrisStructureComponent.java", "[StructTrace] ORIGIN", "debug");
}
@Test
public void coreProductionDoesNotWriteDirectlyToProcessStreams() throws IOException {
try (Stream<Path> files = Files.walk(Path.of("src/main/java"))) {
List<Path> bypasses = files
.filter(path -> path.toString().endsWith(".java"))
.filter(path -> {
try {
String source = Files.readString(path);
return source.contains("System.out")
|| source.contains("System.err")
|| source.contains(".printStackTrace();");
} catch (IOException unreadable) {
throw new IllegalStateException(unreadable);
}
})
.toList();
assertTrue(bypasses.toString(), bypasses.isEmpty());
}
}
@Test
public void probesOnOptionalDependenciesAreNotWarnings() throws IOException {
assertLoggedWith("core/link/MultiverseCoreLink.java", "is not reachable; Iris world settings", "info");
assertLoggedWith("core/link/MultiverseCoreLink.java", "Multiverse will record the live name", "info");
assertLoggedWith("core/gui/GuiHost.java", "Unable to install the Iris desktop quit guard", "info");
String slimJar = read("util/common/misc/SlimJar.java");
assertTrue(slimJar.contains("debug(plugin, \"Failed to inject the library loader"));
assertTrue(slimJar.contains("if (DEBUG)"));
assertTrue(slimJar.contains("plugin.getLogger().info(\"[DEBUG] \" + message)"));
}
/**
* A refused destructive command is the guard working, and the admin who typed it is told directly. The
* console record of it is not a warning about the server.
*/
@Test
public void aRefusedMultiverseCommandIsRecordedWithoutRaisingAWarning() throws IOException {
String guard = read("core/link/MultiverseGuardListener.java");
assertTrue("the console record of a refusal is kept", guard.contains("IrisLogging.info(\"%s %s\", reason, remedy)"));
assertFalse("the refusal is not a warning about the server", guard.contains("IrisLogging.warn(\"%s %s\""));
}
@Test
public void decorationAndBlankLinesAreNotEmittedAtAnySeverity() throws IOException {
String safeguard = read("core/safeguard/IrisSafeguard.java");
assertFalse("a blank record renders as an empty [WARN] line", safeguard.contains("IrisLogging.warn(\"\")"));
assertFalse("a blank record renders as an empty [SEVERE] line", safeguard.contains("IrisLogging.error(\"\")"));
assertFalse("a blank record renders as an empty [INFO] line", safeguard.contains("IrisLogging.info(\"\")"));
assertFalse("a separator rule is not a diagnostic", safeguard.contains("--==<"));
String configurator = read("core/ServerConfigurator.java");
assertFalse("a separator rule is not a diagnostic", configurator.contains("IrisLogging.error(\"===="));
assertFalse("a separator rule is not a diagnostic", configurator.contains("IrisLogging.error(\"----"));
}
/**
* A written debug image is a success, and the method that wrote it had no callers at all.
*/
@Test
public void theUnusedDebugImageWriterIsGone() throws IOException {
assertFalse(read("engine/object/IrisImage.java").contains("writeDebug"));
}
/**
* The other end of the policy. These are the conditions the promotion exists for.
*/
@Test
public void operatorActionableConditionsKeepTheirSeverity() {
assertLoggedWith("core/lifecycle/VanishedWorldStorage.java", "Iris world storage is gone at", "error");
assertLoggedWith("core/IrisWorlds.java", "has unusable world storage and is excluded", "error");
assertLoggedWith("engine/EngineDataStore.java", "Failed to setup Engine Data", "error");
assertLoggedWith("engine/IrisEngineMantle.java", "Failed to read chunk section, skipping it.", "error");
assertLoggedWith("engine/IrisEngineMantle.java", "Failed to read chunk, creating a new chunk instead.", "error");
assertLoggedWith("util/common/reflect/WrappedField.java", "Failed to created WrappedField", "error");
assertLoggedWith("core/datapack/DatapackIngestService.java", "Repairing modified or corrupt Iris-managed datapack", "warn");
assertLoggedWith("core/pregenerator/cache/PregenCacheImpl.java", "Pregen cache storage is gone at", "warn");
assertLoggedWith("core/pregenerator/PregenMantleBackpressure.java", "Pregen mantle backpressure exceeded ", "warn");
assertLoggedWith("core/pregenerator/PregenMantleBackpressure.java", "Pregen heap pressure wait exceeded ", "warn");
assertLoggedWith("core/pregenerator/IrisPregenerator.java", "failed chunk(s); failures are not cached", "warn");
assertLoggedWith("core/service/MultiverseSVC.java", "Multiverse world events are not bindable", "warn");
}
/**
* A handful of lifecycle lines an operator reads logs/latest.log to find. NOTICE is the level adapters
* route to the server's own logger rather than to the console sender.
*/
@Test
public void lifecycleLinesAreRaisedAtNoticeLevel() {
assertLoggedWith("engine/IrisEngine.java", "Engine init: ", "notice");
assertLoggedWith("core/link/MultiverseCoreLink.java", "Adopted %d live Iris world", "notice");
assertLoggedWith("core/pregenerator/IrisPregenerator.java", "Pregen finished: ", "notice");
}
private static void assertLoggedWith(String relativePath, String fragment, String expectedMethod) {
String source;
try {
source = read(relativePath);
} catch (IOException unreadable) {
throw new AssertionError("Cannot read " + relativePath, unreadable);
}
int occurrences = 0;
for (int at = source.indexOf(fragment); at >= 0; at = source.indexOf(fragment, at + 1)) {
occurrences++;
assertEquals(relativePath + " @ \"" + fragment + "\" occurrence " + occurrences,
expectedMethod, loggingMethodBefore(source, at, relativePath, fragment));
}
assertTrue(relativePath + " no longer contains \"" + fragment + "\"", occurrences > 0);
}
private static String loggingMethodBefore(String source, int at, String relativePath, String fragment) {
int call = source.lastIndexOf("IrisLogging.", at);
assertTrue(relativePath + " @ \"" + fragment + "\" is not logged through IrisLogging", call >= 0);
int start = call + "IrisLogging.".length();
int end = start;
while (end < source.length() && Character.isJavaIdentifierPart(source.charAt(end))) {
end++;
}
return source.substring(start, end);
}
private static String read(String relativePath) throws IOException {
return Files.readString(Path.of("src/main/java/art/arcane/iris").resolve(relativePath)).replace("\r\n", "\n");
}
}
@@ -95,28 +95,6 @@ public class IrisWorldsTest {
* asserted against the source: one unusable world folder used to throw out of {@code clean()}, through
* the constructor and into the cache, which returned null and NPE'd every caller.
*/
@Test
public void oneUnusableWorldIsExcludedInsteadOfFailingTheWholeRegistry() throws Exception {
String source = Files.readString(Path.of("src/main/java/art/arcane/iris/core/IrisWorlds.java")).replace("\r\n", "\n");
int accessor = source.indexOf("public static IrisWorlds get()");
int accessorEnd = source.indexOf("public synchronized void put(", accessor);
assertTrue("get() must not swallow a failure into a null return",
source.substring(accessor, accessorEnd).contains("cache.aquireOnceOrThrow("));
int clean = source.indexOf("public synchronized void clean()");
int cleanEnd = source.indexOf("public synchronized void save()", clean);
String cleanBody = source.substring(clean, cleanEnd);
assertTrue("clean() must isolate an unusable entry",
cleanBody.contains("catch (IllegalStateException e)"));
assertTrue("an unusable entry stays in the registry so /iris remove can still find it",
cleanBody.contains("warnUnusableStorage(entry.getKey(), e);"));
int loadDimension = source.indexOf("private IrisDimension loadDimension(");
assertTrue("loadDimension must exclude an unusable world rather than propagate",
source.substring(loadDimension).contains("catch (IllegalStateException unusableStorage)"));
}
@Test
public void bukkitWorldFilteringRecognizesCurrentCraftBukkitConfiguredStorage() throws Exception {
Path worldContainer = temporaryFolder.newFolder("configured-server").toPath();
@@ -3,9 +3,6 @@ package art.arcane.iris.core;
import art.arcane.iris.platform.bukkit.BukkitPlatform;
import org.junit.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
@@ -28,55 +25,6 @@ public class ProgressBossBarToggleTest {
() -> BukkitPlatform.showProgressLane(null, "iris:job", "Working", 0.5D, 4000L)));
}
@Test
public void studioOpenBossBarIsGatedBySettings() throws Exception {
assertGated("core/project/StudioOpenProgressReporter.java");
}
@Test
public void worldCreationAlwaysUsesTheActionBarInsteadOfABossBar() throws Exception {
String source = source("core/tools/WorldCreationProgressReporter.java");
assertFalse(source.contains("isProgressBossBar()"));
assertFalse(source.contains("Bukkit.createBossBar("));
assertTrue(source.contains("WORLD_CREATE_LIFECYCLE_ACTION"));
}
@Test
public void chunkJobBossBarIsGatedBySettings() throws Exception {
assertGated("core/runtime/ChunkJobReporter.java");
}
@Test
public void packDownloadLaneIsGatedWhileTheActionBarSurvives() throws Exception {
String source = source("core/service/PackDownloadProgressReporter.java");
assertTrue(source.contains("isProgressBossBar()"));
assertTrue("the action bar must keep reporting when boss bars are off",
source.contains("sender.sendAction(snapshot.line())"));
}
@Test
public void pregenLaneIsGatedWhileTheActionBarSurvives() throws Exception {
String source = source("core/tools/IrisCreator.java");
int lane = source.indexOf("\"iris:pregen\"");
int gate = source.lastIndexOf("isProgressBossBar()", lane);
assertTrue("the pregen boss bar lane must sit behind general.progressBossBar",
gate > 0 && lane - gate < 200);
assertTrue("the action bar must keep reporting when boss bars are off",
source.contains("RuntimeProgressMessages.WORLD_PREGEN_ACTION"));
}
private void assertGated(String relativePath) throws Exception {
assertTrue(relativePath + " must consult general.progressBossBar before creating a boss bar",
source(relativePath).contains("isProgressBossBar()"));
}
private String source(String relativePath) throws Exception {
return Files.readString(Path.of("src/main/java/art/arcane/iris").resolve(relativePath)).replace("\r\n", "\n");
}
private void withProgressBossBar(boolean enabled, Runnable body) {
IrisSettings previous = IrisSettings.settings;
try {
@@ -384,43 +384,6 @@ public class ServerConfiguratorDatapackFingerprintTest {
}
}
@Test
public void recoveryRunsBeforeRestoredFingerprintReuseHashFallbackAndCompilation() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/ServerConfigurator.java")).replace("\r\n", "\n");
int installIfChanged = source.indexOf("installDataPacksIfChanged(boolean fullInstall)");
int recovery = source.indexOf("DatapackIngestService.reapplyFromStaging", installIfChanged);
int restored = source.indexOf("restoredCompilerInputFingerprint()", recovery);
int fingerprint = source.indexOf("computeCurrentDatapackCompilerInputFingerprint", restored);
int earlyReturn = source.indexOf("resultForUnchangedFingerprint", fingerprint);
int compile = source.indexOf("compileDataPacksLocked(", earlyReturn);
int cache = source.indexOf("writeCompilerInputFingerprintCache(cacheFile.toPath(), current)", compile);
assertTrue(recovery >= 0);
assertTrue(restored > recovery);
assertTrue(fingerprint > restored);
assertTrue(earlyReturn > fingerprint);
assertTrue(compile > earlyReturn);
assertTrue(cache > compile);
}
@Test
public void studioTimingSeparatesRecoveryFingerprintCompilationAndTotal() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/ServerConfigurator.java")).replace("\r\n", "\n");
int timedInstall = source.indexOf("BiConsumer<String, Long> timingConsumer");
int recovery = source.indexOf("\"datapack_external_recovery\"", timedInstall);
int fingerprint = source.indexOf("\"datapack_compiler_input_fingerprint\"", recovery);
int compile = source.indexOf("\"datapack_compile_publish\"", fingerprint);
int total = source.indexOf("\"datapack_install_if_changed_total\"", compile);
assertTrue(timedInstall >= 0);
assertTrue(recovery > timedInstall);
assertTrue(fingerprint > recovery);
assertTrue(compile > fingerprint);
assertTrue(total > compile);
}
@Test
public void loadedRuntimeReuseRequiresAnExactPinnedCompilerInputFingerprint() {
assertTrue(ServerConfigurator.reusableRuntimeFingerprint("abc", "abc"));
@@ -9,8 +9,6 @@ import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.junit.Assert.assertFalse;
@@ -92,30 +90,6 @@ public class ServerConfiguratorStartupRestartTest {
assertFalse(directRestartInvocation.get());
}
@Test
public void startupRestartPathsPromoteTheValidationStateAndBypassTickQueues() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/ServerConfigurator.java"));
String configure = section(
source,
"public static void configure()",
"public static boolean isLoadedDatapackRuntimeReady");
String startupRestart = section(
source,
"public static void restartAtStartupBoundary",
"public static boolean verifyDataPackInstalled");
int restartResult = configure.indexOf("if (result.restartRequired())");
int validationRestart = configure.indexOf("requireDatapackRestart();", restartResult);
assertTrue(restartResult >= 0);
assertTrue(validationRestart > restartResult);
assertTrue(startupRestart.indexOf("invokeImmediateRestartIfSupported(Bukkit.class)")
< startupRestart.indexOf("Bukkit.shutdown();"));
assertFalse(startupRestart.contains("Bukkit.restart"));
assertFalse(startupRestart.contains("J.s("));
assertFalse(startupRestart.contains("dispatchCommand"));
}
public static final class RestartCapableApi {
private static boolean restarted;
@@ -126,12 +100,4 @@ public class ServerConfiguratorStartupRestartTest {
public static final class ShutdownOnlyApi {
}
private static String section(String source, String startMarker, String endMarker) {
int start = source.indexOf(startMarker);
int end = source.indexOf(endMarker, start);
assertTrue(start >= 0);
assertTrue(end > start);
return source.substring(start, end);
}
}
@@ -15,7 +15,6 @@ import java.io.File;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.FileTime;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -255,23 +254,6 @@ public class SettingsHotloadWatchTest {
assertEquals("Active " + PERMISSION, permissionMessage());
}
@Test
public void bukkitAndModdedUseTheSameCoreCoordinator() throws Exception {
String bukkit = Files.readString(Path.of(
"../adapters/bukkit/plugin/src/main/java/art/arcane/iris/Iris.java"
));
String modded = Files.readString(Path.of(
"../adapters/modded-common/src/main/java/art/arcane/iris/modded/service/ModdedSettingsHotloadService.java"
));
assertTrue(bukkit.contains("new SettingsHotloadWatch("));
assertTrue(modded.contains("new SettingsHotloadWatch("));
assertFalse(bukkit.contains("new ConfigHotloadEngine("));
assertFalse(modded.contains("new ConfigHotloadEngine("));
assertFalse(bukkit.contains("IrisLanguage.update()"));
assertFalse(modded.contains("IrisLanguage.update()"));
}
private void awaitPermissionMessage(String expected) throws Exception {
long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(6L);
while (System.nanoTime() < deadline) {
@@ -1,51 +0,0 @@
package art.arcane.iris.core.datapack;
import org.junit.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertTrue;
public class DatapackIngestRuntimeInvalidationTest {
@Test
public void everyPublicMutationInvalidatesLoadedRuntimeBeforeLocking() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/datapack/DatapackIngestService.java")).replace("\r\n", "\n");
assertInvalidatesBeforeLock(source, "public static Report ingest(");
assertInvalidatesBeforeLock(source, "public static ReapplyOutcome reapplyFromStaging(");
assertInvalidatesBeforeLock(source, "public static boolean remove(");
}
@Test
public void noChangeChecksRestoreWhileChangedIngestRemainsRestartBound() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/datapack/DatapackIngestService.java")).replace("\r\n", "\n");
int ingest = source.indexOf("public static Report ingest(");
int unlock = source.indexOf("TRANSACTION_LOCK.unlock();", ingest);
int restore = source.indexOf(
"ServerConfigurator.restoreLoadedDatapackRuntimeIfUnchanged(invalidation);",
unlock);
int changed = source.indexOf("else if (report.changed())", restore);
int restart = source.indexOf("ServerConfigurator.restart();", changed);
int restartRequired = source.indexOf("ServerConfigurator.requireDatapackRestart();", restart);
assertTrue(ingest >= 0);
assertTrue(unlock > ingest);
assertTrue(restore > unlock);
assertTrue(changed > restore);
assertTrue(restart > changed);
assertTrue(restartRequired > restart);
}
private void assertInvalidatesBeforeLock(String source, String signature) {
int method = source.indexOf(signature);
int invalidation = source.indexOf("ServerConfigurator.invalidateLoadedDatapackRuntime();", method);
int lock = source.indexOf("TRANSACTION_LOCK.lock();", method);
assertTrue("Missing datapack mutation entry point " + signature, method >= 0);
assertTrue("Loaded runtime must be invalidated before " + signature, invalidation > method);
assertTrue("Loaded runtime invalidation must precede the transaction lock", invalidation < lock);
}
}
@@ -246,39 +246,6 @@ public class DatapackIngestServiceTest {
validated, "26.2", 4000, true, true, validated.urls));
}
@Test
public void startupChecksCheapCacheContextBeforeHashingManagedDatapacks() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/datapack/DatapackIngestService.java")).replace("\r\n", "\n");
int validation = source.indexOf("public static StartupValidationOutcome validateOnStartup()");
int cacheRead = source.indexOf("readStartupValidationCache", validation);
int contextCheck = source.indexOf("startupValidationContextMatches(", cacheRead);
int fingerprint = source.indexOf("startupValidationFingerprint(", contextCheck);
int fullValidation = source.indexOf("if (autoIngest && !configured.isEmpty())", fingerprint);
assertTrue(validation >= 0);
assertTrue(cacheRead > validation);
assertTrue(contextCheck > cacheRead);
assertTrue(fingerprint > contextCheck);
assertTrue(fullValidation > fingerprint);
}
@Test
public void unchangedPostStartupMaintenanceReturnsBeforeFingerprinting() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/datapack/DatapackIngestService.java")).replace("\r\n", "\n");
int refresh = source.indexOf(
"refreshStartupValidationAfterMaintenance(boolean maintenanceChanged)");
int unchangedGuard = source.indexOf("if (!maintenanceChanged)", refresh);
int validatedState = source.indexOf("StartupValidationCache validated", refresh);
int fingerprint = source.indexOf("startupValidationFingerprint(", refresh);
assertTrue(refresh >= 0);
assertTrue(unchangedGuard > refresh);
assertTrue(validatedState > unchangedGuard);
assertTrue(fingerprint > unchangedGuard);
}
@Test
public void packMetadataMustContainAValidPackContract() throws Exception {
File valid = temporaryFolder.newFolder("valid");
@@ -894,27 +861,6 @@ public class DatapackIngestServiceTest {
assertEquals(expected, ownershipHash(managed));
}
@Test
public void directoryHashRestatsAttributesAndVolumeBeforeOpeningEachFile() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/datapack/DatapackIngestService.java")).replace("\r\n", "\n");
int method = source.indexOf("private static String directoryHash(File root)");
int entries = source.indexOf("List<Path> entries = new ArrayList<>()", method);
int loop = source.indexOf("for (Path entry : entries)", entries);
int attributes = source.indexOf("BasicFileAttributes attributes = Files.readAttributes(", loop);
int fileStore = source.indexOf("Files.getFileStore(entry)", attributes);
int open = source.indexOf("Files.newInputStream(", fileStore);
int digest = source.indexOf("return hex(digest.digest())", open);
assertTrue(method >= 0);
assertTrue(entries > method);
assertTrue(loop > entries);
assertTrue(attributes > loop);
assertTrue(fileStore > attributes);
assertTrue(open > fileStore);
assertTrue(digest > open);
}
@Test
public void failedUpdateStagingCannotBeAdoptedByTheCommittedManifest() throws Exception {
File staging = datapackDirectory("candidate-staging");
@@ -3880,8 +3826,6 @@ public class DatapackIngestServiceTest {
}
private static final class DeleteAttemptFile extends File {
private static final long serialVersionUID = 1L;
private final int successfulAttempt;
private int deleteAttempts;
@@ -10,8 +10,6 @@ import org.junit.Test;
import org.mockito.MockedStatic;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.CompletionStage;
@@ -59,40 +57,6 @@ public class WorldLifecycleUnloadAsyncTest {
}
}
@Test
public void paperLikeManualUnloadDetachesBeforeOffThreadChunkDrain() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/lifecycle/WorldLifecycleSupport.java"))
.replace("\r\n", "\n");
int unloadStart = source.indexOf("private static CompletableFuture<Boolean> unloadWorldWithoutAsyncApi(");
int unloadEnd = source.indexOf("static boolean announceManualWorldUnload", unloadStart);
String unloadMethod = source.substring(unloadStart, unloadEnd);
int capabilityFallback = unloadMethod.indexOf(
"capabilities.minecraftServer() == null || capabilities.removeLevelMethod() == null");
int bukkitUnload = unloadMethod.indexOf("Bukkit.unloadWorld(world, save)", capabilityFallback);
int detach = unloadMethod.indexOf("detachServerLevelAsync(capabilities, serverLevel, world)");
int drain = unloadMethod.indexOf("drainChunkTasksAsync(world, serverLevel)");
int close = unloadMethod.indexOf("closeServerLevelAsync(world, serverLevel)");
int closeStart = source.indexOf("private static CompletableFuture<Void> closeServerLevelAsync(");
int closeEnd = source.indexOf("private static CompletableFuture<Void> drainChunkTasksAsync(", closeStart);
String closeMethod = source.substring(closeStart, closeEnd);
int drainStart = closeEnd;
int drainEnd = source.indexOf("private static void removeWorldFromCraftServerMap", drainStart);
String drainMethod = source.substring(drainStart, drainEnd);
assertTrue(capabilityFallback >= 0);
assertTrue(bukkitUnload > capabilityFallback);
assertTrue(detach > bukkitUnload);
assertTrue(drain > detach);
assertTrue(close > drain);
assertTrue(drainMethod.contains("return J.afut(() ->"));
assertTrue(drainMethod.contains("\"moonrise$getChunkTaskScheduler\""));
assertTrue(drainMethod.contains("\"halt\""));
assertTrue(closeMethod.contains("return runGlobalAsync(closeTask)"));
assertFalse(closeMethod.contains("J.afut("));
assertFalse(closeMethod.contains("J.runRegion("));
}
@Test
public void reflectedAsyncUnloadWaitsForTrueCallback() throws Exception {
CallbackServer server = new CallbackServer();
@@ -18,8 +18,6 @@ import org.mvplugins.multiverse.external.vavr.control.Option;
import java.io.File;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -53,16 +51,6 @@ public class MultiverseCoreLinkTest {
&& method.getParameterCount() == 2));
}
@Test
public void registrationDoesNotRewriteTheRecordedMultiverseName() throws Exception {
String source = Files.readString(Path.of("src/main/java/art/arcane/iris/core/link/MultiverseCoreLink.java")).replace("\r\n", "\n");
assertFalse("worlds are created under the startup name, so the recorded name needs no correction",
source.contains("setLegacyWorldName"));
assertTrue("Multiverse still has to be told the live world name it will record",
source.contains("ImportWorldOptions.worldName(world.getName())"));
}
@Test
public void lookupNamesAddTheIrisKeyAndRuntimeNameForConfiguredStartupNames() {
assertEquals(
@@ -8,8 +8,6 @@ import art.arcane.iris.engine.object.IrisStaticObject;
import art.arcane.volmlib.util.collection.KList;
import org.junit.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
@@ -102,47 +100,4 @@ public class PackExportClosureTest {
* Source guard: both packagers must export the ambient-spawning graph. Spawner and marker
* folders were silently omitted from exports, leaving dangling entitySpawners references.
*/
@Test
public void bothPackagersExportSpawnersMarkersAndTheFullEntityGraph() throws Exception {
String bukkit = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/project/IrisPackageCompiler.java")).replace("\r\n", "\n");
assertTrue("Bukkit packager must write spawners/", bukkit.contains("\"spawners/\""));
assertTrue("Bukkit packager must write markers/", bukkit.contains("\"markers/\""));
assertTrue("Bukkit packager must export region objects alongside biome objects",
bukkit.contains("regions.forEach((r) -> allPlacements.addAll(r.getObjects()))"));
assertTrue("Bukkit packager must export static objects",
bukkit.contains("exportedDimension.getStaticObjects()"));
assertTrue("Bukkit obfuscation must rewrite static object references",
bukkit.contains("placement.setObject(renameObjects.get(placement.getObject()))"));
assertTrue("Bukkit packager must export entity loot tables", bukkit.contains("getLoot().getTables()"));
assertTrue("Bukkit packager must include dimension-stack resources",
bukkit.contains("PackExportClosure.collectDimensionKeys(dimension)"));
assertTrue("Bukkit packager must export expression-backed stack blend styles",
bukkit.contains("dm.getExpressionLoader().getPossibleKeys()")
&& bukkit.contains("\"expressions/\""));
int bukkitValidation = bukkit.indexOf("PackValidator.validateForPackaging(project.getPath())");
assertTrue("Bukkit packager must validate before opening or mutating package state",
bukkitValidation >= 0
&& bukkitValidation < bukkit.indexOf("IrisData.openRuntime(project.getPath())")
&& bukkitValidation < bukkit.indexOf("IO.delete(folder)"));
String modded = Files.readString(Path.of(
"../adapters/modded-common/src/main/java/art/arcane/iris/modded/command/ModdedStudioCommands.java")).replace("\r\n", "\n");
assertTrue("modded packager must write spawners/", modded.contains("\"spawners\""));
assertTrue("modded packager must write markers/", modded.contains("\"markers\""));
assertTrue("modded packager must include initial spawns", modded.contains("getInitialSpawns"));
assertTrue("modded packager must export region objects", modded.contains("region.getObjects()"));
assertTrue("modded packager must export static objects",
modded.contains("PackExportClosure.collectStaticObjectKeys(exportedDimension.getStaticObjects())"));
assertTrue("modded packager must include dimension-stack resources",
modded.contains("PackExportClosure.collectDimensionKeys(dimension)"));
assertTrue("modded packager must export expression-backed stack blend styles",
modded.contains("dm.getExpressionLoader().getPossibleKeys()")
&& modded.contains("\"expressions\""));
assertTrue("modded packager must retain referenced style snippets",
modded.contains("copyStyleSnippets(packFolder, folder)"));
int moddedValidation = modded.indexOf("PackValidator.validateForPackaging(packFolder)");
assertTrue("modded packager must validate before mutating package state",
moddedValidation >= 0 && moddedValidation < modded.indexOf("IO.delete(folder)"));
}
}
@@ -1,144 +0,0 @@
package art.arcane.iris.core.pregenerator.methods;
import org.junit.Test;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class PregenMantleCleanupContractTest {
@Test
public void normalEngineCleanupRetriesCandidatesCoveredByTheNewestRealChunk() throws IOException {
String source = read("art/arcane/iris/engine/framework/Engine.java");
String cleanup = method(source, "default void cleanupMantleChunk(int x, int z)");
assertTrue(cleanup.contains("cleanupChunksCoveredBy("));
assertTrue(cleanup.contains("EngineMantle.ChunkCleanupCallback.NONE"));
assertFalse(cleanup.contains(".cleanupChunk(x, z)"));
}
@Test
public void asyncPregenReportsOnlyCleanupCallbacksFromCoveredTargets() throws IOException {
String source = read("art/arcane/iris/core/pregenerator/methods/AsyncPregenMethod.java");
String completion = method(source, "private void completeChunk(");
String cleanup = method(source, "private void cleanupMantleChunksCoveredBy(");
assertTrue(completion.contains("cleanupMantleChunksCoveredBy(x, z, listener)"));
assertFalse(completion.contains("listener.onChunkCleaned"));
assertTrue(cleanup.contains("cleanupChunksCoveredBy(x, z, true, listener::onChunkCleaned)"));
assertFalse(cleanup.contains("forceCleanupChunk"));
}
@Test
public void finalChunkFlushUsesTargetedPersistenceWithoutFullWorldSave() throws IOException {
String source = read("art/arcane/iris/core/pregenerator/methods/AsyncPregenMethod.java");
String flush = method(source, "private void flushAllRemainingChunks()");
String medievalSource = read("art/arcane/iris/core/pregenerator/methods/MedievalPregenMethod.java");
String medievalFlush = method(medievalSource, "private void unloadAndSaveAllChunks(");
assertTrue(flush.contains("evictRegion(regionKey)"));
assertTrue(flush.contains("INMS.get().flushChunkIO(world)"));
assertFalse(flush.contains("world.save()"));
assertTrue(medievalFlush.contains("i.unload(true)"));
assertTrue(medievalFlush.contains("INMS.get().flushChunkIO(world)"));
assertFalse(medievalFlush.contains("world.save()"));
}
@Test
public void foliaFinalEvictionUsesAwaitableRegionOwnedTasks() throws IOException {
String source = read("art/arcane/iris/core/pregenerator/methods/AsyncPregenMethod.java");
String eviction = method(source, "private CompletableFuture<Void> evictFoliaRegion(");
assertTrue(eviction.contains("J.runRegionFuture("));
assertTrue(eviction.contains("CompletableFuture.allOf("));
assertFalse(eviction.contains("J.runRegion("));
}
@Test
public void shutdownReclaimsMantleBeforeReleasingTheJob() throws IOException {
String source = read("art/arcane/iris/core/pregenerator/IrisPregenerator.java");
String shutdown = method(source, "private void shutdown()");
int generator = shutdown.indexOf("shutdownStep(\"generator\"");
int interruptBoundary = shutdown.indexOf("Thread.interrupted()", generator);
int mantle = shutdown.indexOf("shutdownStep(\"mantle\"");
int protocol = shutdown.indexOf("shutdownStep(\"protocol\"");
int listener = shutdown.indexOf("shutdownStep(\"listener\"");
assertTrue(generator >= 0);
assertTrue(interruptBoundary > generator);
assertTrue(mantle > interruptBoundary);
assertTrue(protocol > mantle);
assertTrue(listener > protocol);
}
@Test
public void directStopDoesNotReleaseTheActiveJobBeforeWorkerCleanup() throws IOException {
String source = read("art/arcane/iris/core/gui/PregeneratorJob.java");
String stop = method(source, "public void stop()");
String close = method(source, "public void onClose()");
assertTrue(stop.contains("requestStop()"));
assertFalse(stop.contains("instance.compareAndSet"));
assertTrue(close.contains("instance.compareAndSet(this, null)"));
}
@Test
public void performanceProfilePreparationRunsOnThePregenWorker() throws IOException {
String source = read("art/arcane/iris/core/gui/PregeneratorJob.java");
String constructor = method(source, "public PregeneratorJob(Configuration configuration)");
String worker = method(source, "private void runWorker(Runnable preparation)");
assertTrue(constructor.contains("runWorker(configuration.preparation())"));
assertBefore(worker, "preparation.run()", "pregenerator.start()");
}
private static String read(String relativePath) throws IOException {
Path current;
try {
current = Path.of(PregenMantleCleanupContractTest.class.getProtectionDomain()
.getCodeSource()
.getLocation()
.toURI());
} catch (URISyntaxException e) {
throw new IOException("Unable to resolve the core source root", e);
}
while (current != null && !Files.isDirectory(current.resolve("src/main/java"))) {
current = current.getParent();
}
if (current == null) {
throw new IOException("Unable to locate the core source root");
}
return Files.readString(current.resolve("src/main/java").resolve(relativePath));
}
private static String method(String source, String signature) {
int start = source.indexOf(signature);
assertTrue("Missing source contract signature: " + signature, start >= 0);
int openBrace = source.indexOf('{', start);
assertTrue("Missing source contract method body: " + signature, openBrace >= 0);
int depth = 0;
for (int index = openBrace; index < source.length(); index++) {
char current = source.charAt(index);
if (current == '{') {
depth++;
} else if (current == '}') {
depth--;
if (depth == 0) {
return source.substring(start, index + 1);
}
}
}
throw new IllegalArgumentException("Unclosed source contract method: " + signature);
}
private static void assertBefore(String source, String first, String second) {
int firstIndex = source.indexOf(first);
int secondIndex = source.indexOf(second);
assertTrue(firstIndex >= 0);
assertTrue(secondIndex > firstIndex);
}
}
@@ -4,9 +4,6 @@ import art.arcane.iris.core.IrisSettings;
import art.arcane.iris.core.service.ObjectStudioSaveService;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import static org.junit.Assert.assertFalse;
@@ -18,32 +15,6 @@ public class StudioEntitySpawningTest {
assertTrue(new IrisSettings.IrisSettingsStudio().isEntitySpawning());
}
@Test
public void studioWorldRulesEnableVanillaMobSpawning() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/runtime/WorldRuntimeControlService.java")).replace("\r\n", "\n");
int helperStart = source.indexOf("static void enableStudioEntitySpawning");
int helperEnd = source.indexOf("public boolean applyNoonTimeLock", helperStart);
String helper = source.substring(helperStart, helperEnd);
assertTrue(source.contains("enableStudioEntitySpawning(world);"));
assertTrue(helper.contains("setBooleanGameRule(world, true, \"DO_MOB_SPAWNING\""));
assertTrue(helper.contains("setBooleanGameRule(world, true, \"DO_TRADER_SPAWNING\""));
assertTrue(helper.contains("setBooleanGameRule(world, true, \"DO_PATROL_SPAWNING\""));
assertTrue(helper.contains("setBooleanGameRule(world, true, \"DO_INSOMNIA\""));
assertTrue(helper.contains("setBooleanGameRule(world, true, \"DO_WARDEN_SPAWNING\""));
assertFalse(helper.contains("setBooleanGameRule(world, false, \"DO_MOB_SPAWNING\""));
}
@Test
public void standardStudioDefaultsToSpectatorMode() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/runtime/StudioOpenCoordinator.java")).replace("\r\n", "\n");
assertTrue(source.contains("request.openKind().teleportThroughStandardEntry()"));
assertTrue(source.contains("GameMode.SPECTATOR"));
}
@Test
public void objectStudioDoesNotCancelEntitySpawns() {
boolean hasSpawnCanceller = Arrays.stream(ObjectStudioSaveService.class.getDeclaredMethods())
@@ -5,9 +5,6 @@ import art.arcane.iris.core.tools.IrisCreator;
import org.junit.Test;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -86,210 +83,4 @@ public class StudioOpenCoordinatorOpenKindTest {
assertEquals(StudioOpenCoordinator.StudioOpenKind.JIGSAW, request.openKind());
assertTrue(request.requestedAtNanos() > 0L);
}
@Test
public void nativeTeleportWaitsForCompletionWithoutAnArrivalDeadline() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/runtime/StudioOpenCoordinator.java"))
.replace("\r\n", "\n");
int methodStart = source.indexOf("private void executeOpen(");
int delegation = source.indexOf("WorldRuntimeControlService.get().teleportInMode(", methodStart);
int completion = source.indexOf("nativeTeleportFuture.get();", delegation);
assertTrue(delegation >= 0);
assertTrue(completion > delegation);
assertFalse(source.substring(methodStart, completion).contains("orTimeout("));
assertFalse(source.substring(methodStart, completion).contains("deadlineNanos"));
}
@Test
public void activeStudioTeleportIsSerializedWithoutAnArrivalDeadline() throws Exception {
String coordinator = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/runtime/StudioOpenCoordinator.java"))
.replace("\r\n", "\n");
String service = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/service/StudioSVC.java"))
.replace("\r\n", "\n");
int coordinatorStart = coordinator.indexOf(
"public CompletableFuture<Boolean> teleportPlayerToProject(");
int coordinatorEnd = coordinator.indexOf("private void executeOpen", coordinatorStart);
String coordinatorMethod = coordinator.substring(coordinatorStart, coordinatorEnd);
int serviceStart = service.indexOf(
"public CompletableFuture<Boolean> teleportToActiveProject(Player player)");
int serviceEnd = service.indexOf("public void open(VolmitSender", serviceStart);
String serviceMethod = service.substring(serviceStart, serviceEnd);
int transitionAdmission = serviceMethod.indexOf("studioTransitions.submit(() ->");
int projectCapture = serviceMethod.indexOf("IrisProject project = activeProject");
int nativeDelegation = coordinatorMethod.indexOf(
"WorldRuntimeControlService.get().teleportInMode(player, entry, GameMode.SPECTATOR)");
assertTrue(transitionAdmission >= 0);
assertTrue(projectCapture > transitionAdmission);
assertFalse(serviceMethod.contains("orTimeout("));
assertFalse(serviceMethod.contains("deadlineNanos"));
assertTrue(coordinatorMethod.contains(
"WorldRuntimeControlService.get().resolveEntryAnchor(world, provider)"));
assertTrue(coordinatorMethod.contains(
"project.getActiveOpenKind().teleportThroughStandardEntry()"));
assertFalse(coordinatorMethod.contains("requestChunkAsync("));
assertFalse(coordinatorMethod.contains("getHighestBlockYAt("));
assertTrue(nativeDelegation >= 0);
assertFalse(coordinatorMethod.contains("orTimeout("));
assertFalse(coordinatorMethod.contains("deadlineNanos"));
}
@Test
public void standardEntryDelegatesWithoutAnExplicitChunkOrSurfaceLookup() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/runtime/StudioOpenCoordinator.java"))
.replace("\r\n", "\n");
assertTrue(source.contains("Location entryLocation = entryAnchor;"));
assertFalse(source.contains("prepareStudioEntryChunks("));
assertFalse(source.contains("findStudioEntryLocation"));
assertFalse(source.contains("EntryChunkResolution"));
assertFalse(source.contains("resolveSafeEntry(world, entryAnchor)"));
assertFalse(source.contains("getHighestBlockYAt("));
}
@Test
public void standardEntryBindsSpectatorToTheNativeTeleport() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/runtime/StudioOpenCoordinator.java"))
.replace("\r\n", "\n");
String runtime = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/runtime/WorldRuntimeControlService.java"))
.replace("\r\n", "\n");
int mode = runtime.indexOf("modeRestore.apply(gameMode)");
int teleport = runtime.indexOf("teleporter.teleport(player, location)", mode);
assertTrue(source.contains("WorldRuntimeControlService.get().teleportInMode("));
int openKind = source.indexOf("request.project().setActiveOpenKind(request.openKind())");
int provider = source.indexOf("request.project().setActiveProvider(provider)", openKind);
assertTrue(openKind >= 0);
assertTrue(provider > openKind);
assertTrue(source.contains("project.setActiveOpenKind(null)"));
assertTrue(mode >= 0);
assertTrue(teleport > mode);
assertTrue(runtime.contains("modeRestore.restore()"));
}
@Test
public void studioTimingSeparatesOrderedLifecyclePhases() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/runtime/StudioOpenCoordinator.java")).replace("\r\n", "\n");
int previous = -1;
for (String phase : List.of(
"resolve_dimension_and_cleanup",
"create_world_total",
"apply_world_rules",
"prepare_generator",
"resolve_entry_anchor",
"prepare_structure_rings",
"prepare_generation_caches",
"teleport_standard_entry",
"finalize_open")) {
int current = source.indexOf("\"" + phase + "\"", previous + 1);
assertTrue("Missing or out-of-order Studio timing phase " + phase, current > previous);
previous = current;
}
assertTrue(source.contains("long openStart = System.nanoTime();"));
}
@Test
public void structureStateCompletesBeforeImmediateNativeTeleport() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/runtime/StudioOpenCoordinator.java")).replace("\r\n", "\n");
int executeOpen = source.indexOf("private void executeOpen(");
int completionCall = source.indexOf("endStudioEntryBootstrap(entryWorld, entryProvider)", executeOpen);
int completionAwait = source.indexOf("entryBootstrap.get(", completionCall);
int cacheAwait = source.indexOf("irisEngine.awaitGenerationCacheWarm()", completionAwait);
int teleportStart = source.indexOf("WorldRuntimeControlService.get().teleportInMode(", cacheAwait);
int finalizeOpen = source.indexOf(
"updateStage(request, \"finalize_open\", 1.00D)", teleportStart);
int futureComplete = source.indexOf(
"future.complete(new StudioOpenResult(world, entryLocation))", finalizeOpen);
int methodStart = source.indexOf(
"private void endStudioEntryBootstrap(World world, PlatformChunkGenerator provider)");
int methodEnd = source.indexOf("private void abandonStudioEntryBootstrap", methodStart);
String method = source.substring(methodStart, methodEnd);
int scheduled = method.indexOf("J.sfut(() ->");
int claim = method.indexOf("activationClaim.compareAndSet(true, false)");
int activation = method.indexOf("INMS.get().completeStudioStructureBootstrap(world)");
int gateRelease = method.indexOf("bukkitGenerator::endStudioEntryBootstrap");
assertTrue(completionCall >= 0);
assertTrue(completionAwait > completionCall);
assertTrue(cacheAwait > completionAwait);
assertTrue(teleportStart > cacheAwait);
assertTrue(finalizeOpen > teleportStart);
assertTrue(futureComplete > finalizeOpen);
assertFalse(source.contains("requestChunkAsync("));
assertTrue(scheduled >= 0);
assertTrue(claim > scheduled);
assertTrue(activation > claim);
int ringCompletion = method.indexOf("thenCompose(nativeActivation -> nativeActivation)");
assertTrue(ringCompletion > activation);
assertTrue(gateRelease > ringCompletion);
assertTrue(source.contains("abandonStudioEntryBootstrap(world, e);"));
}
@Test
public void failedOpenMarshalsRetainedStateAbandonmentToTheServerScheduler() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/runtime/StudioOpenCoordinator.java")).replace("\r\n", "\n");
int methodStart = source.indexOf(
"private void abandonStudioEntryBootstrap(World world, Throwable failure)");
int methodEnd = source.indexOf("private CompletableFuture<Void> cleanupFailedOpen", methodStart);
String method = source.substring(methodStart, methodEnd);
assertTrue(method.contains("if (J.isPrimaryThread())"));
assertTrue(method.contains("CompletableFuture<Void> abandonment = J.sfut("));
assertTrue(method.contains("abandonment.get(STUDIO_STRUCTURE_ACTIVATION_TIMEOUT_SECONDS"));
}
@Test
public void queuedRestartDefersFailedOpenCleanupWithoutAcquiringALiveCloseLease() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/runtime/StudioOpenCoordinator.java")).replace("\r\n", "\n");
int openCatch = source.indexOf("} catch (Throwable e) {");
int restartCheck = source.indexOf(
".active(LifecycleOperationCoordinator.Domain.SERVER_LIFECYCLE)",
openCatch);
int restartDeferral = source.indexOf(
"deferFailedOpenCleanupToRestart(",
restartCheck);
int liveCleanup = source.indexOf("cleanupFailedOpen(", restartDeferral);
int methodStart = source.indexOf(
"private void deferFailedOpenCleanupToRestart(",
restartDeferral);
int methodEnd = source.indexOf("private boolean transientWorldStorageExists", methodStart);
String method = source.substring(methodStart, methodEnd);
assertTrue(restartCheck > openCatch);
assertTrue(restartDeferral > restartCheck);
assertTrue(liveCleanup > restartDeferral);
assertTrue(method.contains("queueStartupCleanup("));
assertFalse(method.contains("closeWorldCoordinated("));
}
@Test
public void openFinalizerReturnsToTheServerThreadBeforeCompletion() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/runtime/StudioOpenCoordinator.java")).replace("\r\n", "\n");
int finalizerCall = source.indexOf("runOpenFinalizer(request.onDone(), world);");
int futureCompletion = source.indexOf(
"future.complete(new StudioOpenResult(world, entryLocation))", finalizerCall);
int methodStart = source.indexOf(
"private void runOpenFinalizer(Consumer<World> finalizer, World world)");
int methodEnd = source.indexOf("private long elapsedMillis", methodStart);
String method = source.substring(methodStart, methodEnd);
assertTrue(finalizerCall >= 0);
assertTrue(futureCompletion > finalizerCall);
assertTrue(method.contains("if (J.isPrimaryThread())"));
assertTrue(method.contains("J.sfut(() -> finalizer.accept(world))"));
assertTrue(method.contains(
"completion.get(STUDIO_STRUCTURE_ACTIVATION_TIMEOUT_SECONDS, TimeUnit.SECONDS)"));
}
}
@@ -2,12 +2,9 @@ package art.arcane.iris.core.runtime;
import org.junit.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class StudioOpenCoordinatorSpawnStuckRegressionTest {
@Test
@@ -30,25 +27,4 @@ public class StudioOpenCoordinatorSpawnStuckRegressionTest {
.anyMatch(m -> m.getName().equals("waitForEntryChunk"));
assertFalse("waitForEntryChunk retry loop must be removed", found);
}
@Test
public void entryTeleportDoesNotIssueASecondChunkRequest() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/runtime/StudioOpenCoordinator.java")).replace("\r\n", "\n");
assertTrue(source.contains("WorldRuntimeControlService.get().teleportInMode("));
assertFalse(source.contains("prepareStudioEntryChunks("));
assertFalse(source.contains("requestChunkAsync("));
}
@Test
public void foliaEntryPathNeverReadsTerrainOnARegionThread() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/runtime/StudioOpenCoordinator.java")).replace("\r\n", "\n");
assertTrue(source.contains("resolveEntryAnchor(world, provider)"));
assertFalse(source.contains("findStudioEntryLocation"));
assertFalse(source.contains("getHighestBlockYAt("));
assertFalse(source.contains("resolveSafeEntry(world, entryAnchor)"));
}
}
@@ -23,9 +23,6 @@ import org.mockito.MockedStatic;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -84,23 +81,6 @@ public class JigsawStudioLifecycleTest {
CreatureSpawnEvent.SpawnReason.SPAWNER));
}
@Test
public void committedStudioActivationDisablesNaturalMobSpawning() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/service/JigsawStudioService.java")).replace("\r\n", "\n");
int registerStart = source.indexOf("public void register(");
int commitStart = source.indexOf("public void activationCommitted(", registerStart);
int commitEnd = source.indexOf("public void markChunkGenerated(", commitStart);
int helperStart = source.indexOf("static void disableNaturalStudioSpawning(", commitEnd);
String register = source.substring(registerStart, commitStart);
String commit = source.substring(commitStart, commitEnd);
String helper = source.substring(helperStart);
assertFalse(register.contains("disableNaturalStudioSpawning(world)"));
assertTrue(commit.contains("disableNaturalStudioSpawning(world)"));
assertTrue(helper.contains("setGameRule(GameRules.SPAWN_MOBS, false)"));
}
@Test
public void closeAuthorizationChecksOwnerDirtyStateAndSaveBarrierAtomically() {
assertTrue(JigsawStudioActivation.tryBeginOpen(OWNER));
@@ -7,8 +7,6 @@ import art.arcane.volmlib.util.format.Form;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import static org.junit.Assert.assertEquals;
@@ -182,24 +180,6 @@ public class PackDownloadProgressReporterTest {
verify(sender, times(1)).sendMessage(anyString());
}
@Test
public void playerHudAlwaysShowsLoaderLaneAndActionBarWithCleanup() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/service/PackDownloadProgressReporter.java"
)).replace("\r\n", "\n");
assertFalse(source.contains("HudSlotRequest"));
assertFalse(source.contains("HudSurface"));
assertTrue(source.contains("J.ar(this::pulseHud, HUD_PULSE_TICKS)"));
assertTrue(source.contains("BukkitPlatform.hudLanes().show("));
assertTrue(source.contains("sender.sendAction(snapshot.line())"));
assertTrue(source.contains("HUD_TERMINAL_TICKS, retiredCleanup"));
assertTrue(source.contains("BukkitPlatform.hudLanes().retire(playerId, hudLaneId)"));
assertTrue(source.contains("BukkitPlatform.hudLanes().hide(player, hudLaneId)"));
assertFalse(source.contains("J.runGlobal(cleanup)"));
assertTrue(source.contains("J.car(activeTaskId);"));
}
@Test
public void allDownloadPhasesHaveLocalizedLabels() {
for (PackDownloader.DownloadPhase phase : PackDownloader.DownloadPhase.values()) {
@@ -5,76 +5,9 @@ import art.arcane.iris.core.localization.IrisLanguage;
import art.arcane.iris.core.localization.PackDownloadMessages;
import org.junit.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class StudioSVCPackDownloadContractTest {
@Test
public void downloadsUseReporterCompletionWithoutMutatingLiveDatapacks() throws Exception {
String source = Files.readString(Path.of("src/main/java/art/arcane/iris/core/service/StudioSVC.java")).replace("\r\n", "\n");
assertTrue(source.contains("reporter.succeed(result);"));
assertFalse(method(source, "public void downloadBuiltIn(VolmitSender sender, String key)")
.contains("ServerConfigurator.restart()"));
assertFalse(method(source, "public void downloadUrl(VolmitSender sender, String url)")
.contains("installDataPacksIfChanged"));
}
@Test
public void downloadLeaseIsAcquiredBeforeUnconditionalIoDispatch() throws Exception {
String source = Files.readString(Path.of("src/main/java/art/arcane/iris/core/service/StudioSVC.java")).replace("\r\n", "\n");
int mutationStart = source.indexOf("private void runPackMutation(");
int mutationEnd = source.indexOf("private void executePackMutation(", mutationStart);
String runPackMutation = source.substring(mutationStart, mutationEnd);
int leaseAcquisition = runPackMutation.indexOf("LifecycleOperationCoordinator.get().acquire(");
int executionTracking = runPackMutation.indexOf("new PackDownloadExecution(");
int ioDispatch = runPackMutation.indexOf("MultiBurst.ioBurst.submit(");
assertTrue(leaseAcquisition >= 0);
assertTrue(executionTracking > leaseAcquisition);
assertTrue(ioDispatch > leaseAcquisition);
assertTrue(runPackMutation.contains("execution.bind(future);"));
assertTrue(runPackMutation.contains("execution.cancel();"));
assertTrue(runPackMutation.contains("finally"));
assertTrue(runPackMutation.contains("reporter.start();"));
assertTrue(runPackMutation.contains("reporter.executionComplete();"));
assertFalse(runPackMutation.contains("runOffPrimaryThread"));
}
@Test
public void acceptedDownloadsRouteFeedbackProgressAndTerminalStatesThroughReporter() throws Exception {
String source = Files.readString(Path.of("src/main/java/art/arcane/iris/core/service/StudioSVC.java")).replace("\r\n", "\n");
String builtIn = method(source, "public void downloadBuiltIn(VolmitSender sender, String key)");
String remote = method(source, "public void downloadUrl(VolmitSender sender, String url)");
String execute = method(source, "private void executePackMutation(");
assertTrue(builtIn.contains("PackDownloadProgressReporter reporter"));
assertTrue(remote.contains("PackDownloadProgressReporter reporter"));
assertTrue(remote.contains("reporter::detail"));
assertTrue(remote.contains("\"remote-zip\", reporter"));
assertTrue(remote.contains("cancellation,"));
assertTrue(remote.contains("reporter"));
assertTrue(execute.contains("reporter.cancel();"));
assertTrue(execute.contains("reporter.fail(e);"));
}
@Test
public void shutdownClosesAdmissionAndDrainsTrackedDownloadBeforeServiceTeardown() throws Exception {
String source = Files.readString(Path.of("src/main/java/art/arcane/iris/core/service/StudioSVC.java")).replace("\r\n", "\n");
String onDisable = method(source, "public void onDisable()");
String quiesce = method(source, "public void quiesceDownloadsForShutdown()");
assertTrue(onDisable.contains("quiesceDownloadsForShutdown();"));
assertTrue(quiesce.contains("downloadAdmissionOpen = false;"));
assertTrue(quiesce.contains("execution.cancel();"));
assertTrue(quiesce.contains("execution.await("));
assertTrue(quiesce.contains("while (!execution.isComplete())"));
}
@Test
public void stackedDownloadUsesLocalizedBusyMessage() {
LifecycleOperationCoordinator.ActiveOperation download = new LifecycleOperationCoordinator.ActiveOperation(
@@ -99,24 +32,4 @@ public class StudioSVCPackDownloadContractTest {
StudioSVC.packMutationBusyMessage(worldCreation)
);
}
private static String method(String source, String signature) {
int start = source.indexOf(signature);
assertTrue("Missing source contract signature: " + signature, start >= 0);
int openBrace = source.indexOf('{', start);
assertTrue("Missing source contract method body: " + signature, openBrace >= 0);
int depth = 0;
for (int index = openBrace; index < source.length(); index++) {
char current = source.charAt(index);
if (current == '{') {
depth++;
} else if (current == '}') {
depth--;
if (depth == 0) {
return source.substring(start, index + 1);
}
}
}
throw new IllegalArgumentException("Unclosed source contract method: " + signature);
}
}
@@ -1,35 +0,0 @@
package art.arcane.iris.core.service;
import org.junit.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
public class StudioSVCWorldPackFeedbackContractTest {
@Test
public void persistentPackCopyUsesLifecycleProgressWithoutLegacySnapshotFeedback() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/service/StudioSVC.java"
)).replace("\r\n", "\n");
assertEquals(2, occurrences(source, "STUDIO_S_V_C_PACK_COPY_REQUIRES_ASYNC_THREAD"));
assertEquals(3, occurrences(source, "STUDIO_S_V_C_PACK_INSTALL_FAILED"));
assertFalse(source.contains("STUDIO_S_V_C_INSTALLING_PACKAGE"));
assertFalse(source.contains("Publishing snapshot"));
assertFalse(source.contains("sender.sendMessage(\"Iris refused to copy a pack"));
assertFalse(source.contains("sender.sendMessage(\"Failed to install studio pack"));
}
private static int occurrences(String value, String match) {
int count = 0;
int offset = 0;
while ((offset = value.indexOf(match, offset)) >= 0) {
count++;
offset += match.length();
}
return count;
}
}
@@ -172,27 +172,6 @@ public class StudioSVCWorldPackPublishTest {
@Test
public void replaceExistingRejectsSymbolicTargetBeforePublication() throws Exception {
String sourceCode = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/service/StudioSVC.java")).replace("\r\n", "\n");
int install = sourceCode.indexOf("private IrisDimension installIntoDirectory(");
int initialTargetSafety = sourceCode.indexOf(
"requireSafePublicationTarget(target, replaceExisting)",
install);
int beginMutation = sourceCode.indexOf(
"PackValidationRegistry.beginRootMutation(target)",
initialTargetSafety);
int finalTargetSafety = sourceCode.indexOf(
"requireSafePublicationTarget(target, replaceExisting)",
beginMutation);
int publish = sourceCode.indexOf(
"AtomicDirectoryPublisher.publish(stage, target)",
finalTargetSafety);
assertTrue(install >= 0);
assertTrue(initialTargetSafety > install);
assertTrue(beginMutation > initialTargetSafety);
assertTrue(finalTargetSafety > beginMutation);
assertTrue(publish > finalTargetSafety);
Path root = temporaryFolder.newFolder("symbolic-replacement-target").toPath();
Path outside = root.resolve("outside-pack");
Path target = root.resolve("world/iris/pack");
@@ -305,27 +284,6 @@ public class StudioSVCWorldPackPublishTest {
@Test
public void replacementKeepsTargetUnauthorizedThroughPublishedFingerprintWindow() throws Exception {
String sourceCode = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/service/StudioSVC.java")).replace("\r\n", "\n");
int install = sourceCode.indexOf("private IrisDimension installIntoDirectory(");
int beginMutation = sourceCode.indexOf("PackValidationRegistry.beginRootMutation(target)", install);
int publish = sourceCode.indexOf("AtomicDirectoryPublisher.publish(stage, target)", beginMutation);
int fingerprint = sourceCode.indexOf(
"ServerConfigurator.computePackTreeFingerprint(target.toFile())",
publish);
int stageValidation = sourceCode.indexOf(
"validatePublishedPack(target, source, copiedFingerprint, validationMutation)",
fingerprint);
int publishCommit = sourceCode.indexOf("publication.commit()", stageValidation);
int validationCommit = sourceCode.indexOf("validationMutation.commit()", publishCommit);
assertTrue(install >= 0);
assertTrue(beginMutation > install);
assertTrue(publish > beginMutation);
assertTrue(fingerprint > publish);
assertTrue(stageValidation > fingerprint);
assertTrue(publishCommit > stageValidation);
assertTrue(validationCommit > publishCommit);
Path root = temporaryFolder.newFolder("validation-publication-window").toPath();
Path sourcePack = root.resolve("source");
Path target = root.resolve("world/iris/pack");
@@ -454,26 +412,6 @@ public class StudioSVCWorldPackPublishTest {
assertEquals("second", second.join());
}
@Test
public void productionWorldPublicationUsesImmutableGenerationHistory() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/service/StudioSVC.java"
)).replace("\r\n", "\n");
int productionStart = source.indexOf("private IrisDimension publishGenerationHistory(");
int transientStart = source.indexOf("private IrisDimension installIntoDirectory(", productionStart);
String production = source.substring(productionStart, transientStart);
assertTrue(production.contains("GenerationHistory.create("));
assertTrue(production.contains("GenerationHistory.openIfPresent(dimensionRoot, worldSeed)"));
assertTrue(production.contains("GenerationHistory.adoptLegacyPack("));
assertTrue(production.contains("history.stageUpdate("));
assertTrue(production.contains("getGenerationTransitionWidthBlocks()"));
assertTrue(production.contains("history.activePackRoot()"));
assertFalse(production.contains("AtomicDirectoryPublisher.publish("));
assertTrue(source.contains("installIntoTransientWorld("));
assertTrue(source.contains("new File(dimensionRoot, \"iris/pack\")"));
}
private static void writeValidPack(Path packRoot) throws Exception {
Files.createDirectories(packRoot.resolve("dimensions"));
Files.createDirectories(packRoot.resolve("regions"));
@@ -1,75 +0,0 @@
package art.arcane.iris.core.tools;
import org.junit.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class IrisPersistentWorldCreationContractTest {
@Test
public void productionCreateFreezesIntoCurrentPlatformStorageBeforeWorldCreation() throws Exception {
String source = Files.readString(Path.of("src/main/java/art/arcane/iris/core/tools/IrisCreator.java")).replace("\r\n", "\n");
int createStart = source.indexOf("private World createReserved(");
int createEnd = source.indexOf("static Player createTeleportTarget(", createStart);
String create = source.substring(createStart, createEnd);
int dimensionRoot = create.indexOf("WorldCreatorCompat.persistentDimensionRoot(worldKey)");
int levelRoot = create.indexOf("WorldCreatorCompat.persistentLevelRoot(worldKey)");
int existingStorage = create.indexOf("Files.exists(storageRoot.toPath())");
int freezePack = create.indexOf("studioService.installIntoWorld(sender, resolvedDimension, dimensionRoot, seed)");
int persistentCreator = create.indexOf(".persistent(!studio && !benchmark)");
int bukkitCreate = create.indexOf("INMS.get().createWorldAsync(wc, request)");
int rollbackStorage = create.indexOf(
"rollbackWorldCreation(worldKey, world, stagedGenerator, storageRoot, bukkitRegistered, failure)"
);
assertTrue(dimensionRoot >= 0);
assertTrue(levelRoot > dimensionRoot);
assertTrue(existingStorage > levelRoot);
assertTrue(freezePack > existingStorage);
assertTrue(persistentCreator > freezePack);
assertTrue(bukkitCreate > persistentCreator);
assertTrue(rollbackStorage > bukkitCreate);
assertFalse(create.contains("copySeed"));
assertFalse(create.contains("level.dat"));
}
@Test
public void persistentCreatorPreservesConfiguredNameAndCanonicalIdentity() throws Exception {
String source = Files.readString(Path.of("src/main/java/art/arcane/iris/core/tools/IrisWorldCreator.java")).replace("\r\n", "\n");
int createStart = source.indexOf("public WorldCreator create()");
int createEnd = source.indexOf("private World.Environment findEnvironment()", createStart);
String create = source.substring(createStart, createEnd);
int persistentCreator = create.indexOf("WorldCreatorCompat.ofPersistentKey(worldKey)");
int persistentStorage = create.indexOf("WorldCreatorCompat.persistentDimensionRoot(worldKey)");
int canonicalIdentity = create.indexOf(".platformIdentity(worldKey.toString())");
int configuredName = create.indexOf(".name(creator.name())");
int history = create.indexOf("requireGenerationHistory(w.worldFolder(), seed)");
int exactPack = create.indexOf("requireActivePack(generationHistory)");
assertTrue(persistentCreator >= 0);
assertTrue(persistentStorage > persistentCreator);
assertTrue(canonicalIdentity > persistentStorage);
assertTrue(configuredName > canonicalIdentity);
assertTrue(history > configuredName);
assertTrue(exactPack > history);
assertTrue(create.contains("new File(w.worldFolder(), \"iris/pack\")"));
}
@Test
public void publicBukkitBackendRebuildKeepsExactFallbackWorldName() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/lifecycle/WorldLifecycleRequest.java"
)).replace("\r\n", "\n");
int rebuildStart = source.indexOf("public WorldCreator toWorldCreator()");
int rebuildEnd = source.indexOf("return creator;", rebuildStart);
String rebuild = source.substring(rebuildStart, rebuildEnd);
assertTrue(rebuild.contains("WorldCreatorCompat.ofKey(worldKey, worldName)"));
assertFalse(rebuild.contains("WorldCreatorCompat.ofKey(worldKey)"));
}
}
@@ -4,11 +4,7 @@ import art.arcane.iris.core.localization.RuntimeProgressMessages;
import art.arcane.iris.util.common.format.C;
import org.junit.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
@@ -79,20 +75,6 @@ public class WorldCreationProgressReporterTest {
assertTrue(failed.contains("FAILED | Entering world"));
}
@Test
public void playerProgressUsesTheEntityScheduledActionBarWithoutABossBar() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/core/tools/WorldCreationProgressReporter.java"
)).replace("\r\n", "\n");
assertFalse(source.contains("Bukkit.createBossBar("));
assertFalse(source.contains("WORLD_CREATE_BOSSBAR_"));
assertFalse(source.contains("isProgressBossBar()"));
assertTrue(source.contains("RuntimeProgressMessages.WORLD_CREATE_LIFECYCLE_ACTION"));
assertTrue(source.contains("J.runEntity(sender.player(), guardedRender)"));
assertTrue(source.contains("J.runEntity(sender.player(), render)"));
}
private static int occurrences(String value, String match) {
int count = 0;
int offset = 0;
@@ -1,130 +0,0 @@
package art.arcane.iris.engine;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class EngineRuntimePublicationContractTest {
@Test
public void worldManagerStartsOnlyAfterTheRuntimeSessionIsReady() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/EngineRuntimeBuilder.java")).replace("\r\n", "\n");
int publishStart = source.indexOf("void publishRuntime(");
int publishEnd = source.indexOf("private void scheduleRuntimeTasks", publishStart);
String publish = source.substring(publishStart, publishEnd);
assertBefore(publish, "engine.runtime = next", "next.worldManager().start()");
assertBefore(publish, "activateNextSession()", "next.worldManager().start()");
assertBefore(publish, "engine.lifecycleState = LifecycleState.RUNNING", "next.worldManager().start()");
assertBefore(publish, "engine.getClosing().set(false)", "next.worldManager().start()");
assertBefore(publish, "openBackgroundTaskAdmission()", "next.worldManager().start()");
}
@Test
public void failedManagerStartClosesAdmissionBeforeRuntimeCleanup() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/EngineRuntimeBuilder.java")).replace("\r\n", "\n");
int publishStart = source.indexOf("void publishRuntime(");
int publishEnd = source.indexOf("private void scheduleRuntimeTasks", publishStart);
String publish = source.substring(publishStart, publishEnd);
assertBefore(publish, "engine.getClosing().set(true)", "cleanupFailure = engine.shutdownSequence.closeRuntime(next, null)");
assertBefore(publish, "closeBackgroundTaskAdmission()", "cleanupFailure = engine.shutdownSequence.closeRuntime(next, null)");
assertBefore(publish, "sealAndAwait(", "cleanupFailure = engine.shutdownSequence.closeRuntime(next, null)");
}
@Test
public void dimensionStackRegistrationRunsAfterHostStaticObjects() throws IOException {
String builderSource = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/EngineRuntimeBuilder.java")).replace("\r\n", "\n");
int buildStart = builderSource.indexOf("private EngineRuntime buildRuntime(");
int buildEnd = builderSource.indexOf("GenerationRuntime buildDetachedGenerationRuntime(", buildStart);
String build = builderSource.substring(buildStart, buildEnd);
assertBefore(build, "assembly.runtimeKernel.registerStaticObjects(engine, assembly.mode)",
"assembly.runtimeKernel.registerDimensionStack(");
String kernelSource = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/history/GenerationKernelV1.java")).replace("\r\n", "\n");
assertBefore(kernelSource, "staticObjects.apply(engine, x, z, blocks)",
"dimensionStack.actuate(x, z, blocks, multicore, chunkContext)");
assertBefore(kernelSource, "dimensionStack.actuate(x, z, blocks, multicore, chunkContext)",
"stackCustom.modify(x, z, blocks, multicore, chunkContext)");
}
@Test
public void detachedRuntimeBuildDoesNotCreateWorldOwnedServices() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/EngineRuntimeBuilder.java")).replace("\r\n", "\n");
int buildStart = source.indexOf("GenerationRuntime buildDetachedGenerationRuntime(");
int buildEnd = source.indexOf("void publishRuntime(", buildStart);
String build = source.substring(buildStart, buildEnd);
assertTrue(build.contains("assembly.runtimeKernel.createComplex(engine, assembly.transitionPlan)"));
assertTrue(build.contains("assembly.runtimeKernel.createMantle(engine, assembly.mantleStorageDirectory)"));
assertTrue(build.contains("assembly.mantle.hotload()"));
assertTrue(build.contains("assembly.runtimeKernel.createMode(engine)"));
assertTrue(build.contains("assembly.runtimeKernel.createUpperContext(engine)"));
assertTrue(build.contains("assembly.runtimeKernel.registerStaticObjects(engine, assembly.mode)"));
assertFalse(build.contains("EngineEffectsProvider"));
assertFalse(build.contains("EngineWorldManagerProvider"));
assertFalse(build.contains("worldManager().start()"));
}
@Test
public void runtimePublicationTransfersAnIdenticalMantleWithoutClosingIt() throws IOException {
String builderSource = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/EngineRuntimeBuilder.java")).replace("\r\n", "\n");
String shutdownSource = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/EngineShutdownSequence.java")).replace("\r\n", "\n");
assertTrue(builderSource.contains("next.generation().mantle()"));
assertTrue(shutdownSource.contains("generationRuntime.mantle() != retainedMantle"));
}
@Test
public void engineAndDetachedRuntimeAcceptExplicitMantleDirectories() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/IrisEngine.java")).replace("\r\n", "\n");
assertTrue(source.contains("InitializationMode initializationMode,\n Path mantleStorageDirectory"));
assertTrue(source.contains("EngineTarget runtimeTarget,\n Path mantleStorageDirectory"));
assertTrue(source.contains("exclusive mantle storage directory"));
}
@Test
public void mantleIoPinsTheRuntimeDataAcrossWorkerThreads() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/IrisEngineMantle.java")).replace("\r\n", "\n");
assertTrue(source.contains("runtimeData::get"));
assertTrue(source.contains("runtimeData.set(Objects.requireNonNull(engine.getData()"));
assertFalse(source.contains("createDataAdapter(engine::getData)"));
}
@Test
public void failedDetachedBuildReleasesTransferredTargetOwnership() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/IrisEngine.java")).replace("\r\n", "\n");
int buildStart = source.indexOf("public GenerationRuntimeBinding buildDetachedGenerationRuntime(");
int buildEnd = source.indexOf("public void closeDetachedGenerationRuntime(", buildStart);
String build = source.substring(buildStart, buildEnd);
assertTrue(build.contains("detachedData.registerEngine(this)"));
assertTrue(build.contains("shutdownSequence.closeDetachedTarget(requiredTarget, null)"));
assertTrue(build.contains("shutdownSequence.closeDetachedGenerationRuntime(detached, null)"));
}
private static void assertBefore(String source, String first, String second) {
int firstIndex = source.indexOf(first);
int secondIndex = source.indexOf(second);
assertTrue("Missing source contract token: " + first, firstIndex >= 0);
assertTrue("Missing source contract token: " + second, secondIndex >= 0);
assertTrue(first + " must occur before " + second, firstIndex < secondIndex);
}
}
@@ -1,74 +0,0 @@
package art.arcane.iris.engine;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertTrue;
public class EngineShutdownOwnershipContractTest {
@Test
public void attachedHistoryRouterClosesBeforeRuntimeOwnershipReleases() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/EngineShutdownSequence.java")).replace("\r\n", "\n");
int closeStart = source.indexOf("void close()");
int routerClose = source.indexOf("engine::closeAttachedGenerationHistoryRuntimeRouter", closeStart);
int runtimeRelease = source.indexOf("releaseRuntime(failure)", routerClose);
assertTrue(routerClose > closeStart);
assertTrue(runtimeRelease > routerClose);
}
@Test
public void ownershipCloseMustSucceedBeforeRuntimeRelease() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/EngineShutdownSequence.java")).replace("\r\n", "\n");
int ownershipClose = source.indexOf("NativeStructureOwnershipStore.close(engine)");
int ownershipGate = source.indexOf("if (ownershipFailure == null)", ownershipClose);
int runtimeRelease = source.indexOf("releaseRuntime(failure)", ownershipGate);
assertTrue(ownershipClose >= 0);
assertTrue(ownershipGate > ownershipClose);
assertTrue(runtimeRelease > ownershipGate);
}
@Test
public void failedConstructionKeepsMantleOpenWhileOwnershipWritesRemain() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/EngineShutdownSequence.java")).replace("\r\n", "\n");
int cleanupStart = source.indexOf("void cleanupFailedConstruction");
int cleanupEnd = source.indexOf("Throwable closeAssembly", cleanupStart);
String cleanup = source.substring(cleanupStart, cleanupEnd);
int ownershipClose = cleanup.indexOf("NativeStructureOwnershipStore.close(engine)");
int ownershipGate = cleanup.indexOf("if (ownershipFailure == null)", ownershipClose);
int runtimeRelease = cleanup.indexOf("releaseRuntime(cleanupFailure)", ownershipGate);
int targetRelease = cleanup.indexOf("releaseTarget(cleanupFailure)", runtimeRelease);
int closedPublication = cleanup.indexOf("engine.closed = true", ownershipGate);
assertTrue(ownershipClose >= 0);
assertTrue(ownershipGate > ownershipClose);
assertTrue(runtimeRelease > ownershipGate);
assertTrue(targetRelease > runtimeRelease);
assertTrue(closedPublication > ownershipGate);
}
@Test
public void detachedRuntimesCloseBeforeTheBaseRuntimeAndTarget() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/EngineShutdownSequence.java")).replace("\r\n", "\n");
int releaseStart = source.indexOf("private Throwable releaseRuntime(");
int releaseEnd = source.indexOf("private Throwable closeDetachedGenerationRuntimes(", releaseStart);
String release = source.substring(releaseStart, releaseEnd);
int detachedRelease = release.indexOf("closeDetachedGenerationRuntimes(null)");
int detachedGate = release.indexOf("if (detachedFailure != null)", detachedRelease);
int baseRelease = release.indexOf("closeRuntime(engine.runtime, null)", detachedGate);
int targetRelease = source.indexOf("engine.publishedTarget::close", releaseEnd);
assertTrue(detachedRelease >= 0);
assertTrue(detachedGate > detachedRelease);
assertTrue(baseRelease > detachedGate);
assertTrue(targetRelease > releaseEnd);
}
}
@@ -1,107 +0,0 @@
package art.arcane.iris.engine;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class NativeStructureBootstrapLifecycleContractTest {
@Test
public void closeWaitsBeforeLifecycleMutationAndGenerationSeal() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/EngineShutdownSequence.java")).replace("\r\n", "\n");
int closeStart = source.indexOf("void close()");
int closeEnd = source.indexOf("void cleanupFailedConstruction", closeStart);
String close = source.substring(closeStart, closeEnd);
assertBefore(close,
"engine.awaitNativeStructureBootstrap(\"close\")",
"engine.lifecycleState = LifecycleState.CLOSING");
assertBefore(close,
"engine.awaitNativeStructureBootstrap(\"close\")",
"sealAndAwait(\"close\"");
}
@Test
public void fullAndComplexHotloadWaitBeforeLifecycleMutationAndGenerationSeal() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/EngineHotloader.java")).replace("\r\n", "\n");
int complexStart = source.indexOf("void hotloadComplex()");
int fullStart = source.indexOf("void hotloadSilently()", complexStart);
String complex = source.substring(complexStart, fullStart);
int fullEnd = source.indexOf("private void broadcastStudioHotload", fullStart);
String full = source.substring(fullStart, fullEnd);
assertBefore(complex,
"engine.awaitNativeStructureBootstrap(\"complex hotload\")",
"engine.lifecycleState = LifecycleState.HOTLOADING");
assertBefore(complex,
"engine.awaitNativeStructureBootstrap(\"complex hotload\")",
"engine.sealForTransition(\"complex hotload\"");
assertBefore(full,
"engine.awaitNativeStructureBootstrap(\"hotload\")",
"engine.lifecycleState = LifecycleState.HOTLOADING");
assertBefore(full,
"engine.awaitNativeStructureBootstrap(\"hotload\")",
"engine.sealForTransition(\"hotload\"");
}
@Test
public void ringBootstrapStartsUnderTheSameLifecycleLock() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/IrisEngine.java")).replace("\r\n", "\n");
int start = source.indexOf("public CompletableFuture<Void> startNativeStructureBootstrap(");
int end = source.indexOf("void awaitNativeStructureBootstrap", start);
String method = source.substring(start, end);
assertBefore(method, "synchronized (lifecycleLock)",
"nativeStructureBootstrapBarrier.start(claim, starter)");
assertBefore(method, "requireRunning(\"prepare native structure placements\")",
"nativeStructureBootstrapBarrier.start(claim, starter)");
assertBefore(method, "nativeStructureBootstrapBarrier.start(claim, starter)",
"activation.run()");
}
@Test
public void studioVolumeQueriesStayOutsideCachesUntilTheBootstrapGateReleases() throws IOException {
String engineSource = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/IrisEngine.java")).replace("\r\n", "\n");
int queryStart = engineSource.indexOf(
"public KList<NativeStructureVolume> getNativeStructureVolumes(");
int queryEnd = engineSource.indexOf(
"public void setNativeStructureVolumeQueriesEnabled", queryStart);
String query = engineSource.substring(queryStart, queryEnd);
int setterEnd = engineSource.indexOf("public IrisEngineData getEngineData()", queryEnd);
String setter = engineSource.substring(queryEnd, setterEnd);
String generatorSource = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/platform/BukkitChunkGenerator.java")).replace("\r\n", "\n");
int releaseStart = generatorSource.indexOf("public void endStudioEntryBootstrap()");
int releaseEnd = generatorSource.indexOf(
"public boolean isStudioEntryBootstrapActive()", releaseStart);
String release = generatorSource.substring(releaseStart, releaseEnd);
assertTrue(engineSource.contains(
"new AtomicBoolean(!requiredMode.studio())"));
assertBefore(query,
"!nativeStructureVolumeQueriesEnabled.get()",
"nativeStructureVolumeMemo.volumes(");
assertBefore(setter,
"nativeStructureVolumeMemo.clear()",
"nativeStructureVolumeQueriesEnabled.set(true)");
assertBefore(release,
"irisEngine.setNativeStructureVolumeQueriesEnabled(shouldGenerateNativeStructures(",
"studioEntryBootstrapActive.set(false)");
}
private static void assertBefore(String source, String first, String second) {
int firstIndex = source.indexOf(first);
int secondIndex = source.indexOf(second);
assertTrue("Missing source contract token: " + first, firstIndex >= 0);
assertTrue("Missing source contract token: " + second, secondIndex >= 0);
assertTrue(first + " must occur before " + second, firstIndex < secondIndex);
}
}
@@ -11,11 +11,8 @@ import art.arcane.iris.engine.object.StudioMode;
import art.arcane.iris.engine.object.IrisDimension;
import org.junit.Test;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@@ -108,19 +105,6 @@ public class BukkitChunkGeneratorInitializationModeTest {
assertEquals(-64, BukkitChunkGenerator.authoringBaseHeight(-64, 0));
}
@Test
public void authoringStartupDoesNotPrefetchTerrainHydrology() throws IOException {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/engine/platform/BukkitChunkGenerator.java"));
int start = source.indexOf("private CompletableFuture<Void> prefetchSpawnHydrology(");
int end = source.indexOf("private void updateSpawnLocation(", start);
String prefetch = source.substring(start, end);
assertTrue(prefetch.indexOf("if (usesFlatStudioTerrain())") >= 0);
assertTrue(prefetch.indexOf("if (usesFlatStudioTerrain())")
< prefetch.indexOf("engine.getComplex()"));
}
@Test
public void runtimeAndOrdinaryStudioWarmGenerationCaches() {
IrisEngine.InitializationMode runtime =
@@ -180,5 +164,4 @@ public class BukkitChunkGeneratorInitializationModeTest {
assertFalse(BukkitChunkGenerator.shouldPersistWorldRegistration(true));
assertTrue(BukkitChunkGenerator.shouldPersistWorldRegistration(false));
}
}
@@ -0,0 +1,91 @@
package art.arcane.iris.purity;
import art.arcane.iris.core.loader.IrisData;
import org.junit.Test;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import static org.junit.Assert.assertTrue;
public class CoreProcessStreamPurityGateTest {
private static final String SYSTEM_OWNER = "java/lang/System";
private static final String STACK_TRACE_METHOD = "printStackTrace";
@Test
public void coreProductionBytecodeNeverTouchesTheProcessStreams() throws Exception {
Path classes = Path.of(IrisData.class.getProtectionDomain().getCodeSource().getLocation().toURI());
assertTrue("core classes must be a directory to scan, got " + classes, Files.isDirectory(classes));
List<String> violations = new ArrayList<>();
int scanned = 0;
try (Stream<Path> tree = Files.walk(classes)) {
for (Path file : tree.filter(candidate -> candidate.toString().endsWith(".class")).toList()) {
collectViolations(file, violations);
scanned++;
}
}
assertTrue("the gate scanned only " + scanned + " core classes, so it proves nothing", scanned > 1000);
assertTrue("Core production code must report through IrisLogging, never the process streams."
+ " printStackTrace(PrintStream)/printStackTrace(PrintWriter) write to a caller-supplied"
+ " sink and stay allowed:" + String.join("", violations), violations.isEmpty());
}
private static void collectViolations(Path classFile, List<String> violations) throws Exception {
ClassReader reader;
try (InputStream input = Files.newInputStream(classFile)) {
reader = new ClassReader(input);
}
String owner = reader.getClassName();
reader.accept(new ClassVisitor(Opcodes.ASM9) {
@Override
public MethodVisitor visitMethod(
int access,
String name,
String descriptor,
String signature,
String[] exceptions
) {
return new MethodVisitor(Opcodes.ASM9) {
@Override
public void visitFieldInsn(int opcode, String fieldOwner, String fieldName, String fieldDescriptor) {
if (opcode != Opcodes.GETSTATIC || !SYSTEM_OWNER.equals(fieldOwner)) {
return;
}
if ("out".equals(fieldName) || "err".equals(fieldName)) {
violations.add(report(owner, name, "System." + fieldName));
}
}
@Override
public void visitMethodInsn(
int opcode,
String methodOwner,
String methodName,
String methodDescriptor,
boolean isInterface
) {
if (STACK_TRACE_METHOD.equals(methodName) && "()V".equals(methodDescriptor)) {
violations.add(report(owner, name, methodOwner.replace('/', '.') + "#printStackTrace()"));
}
}
};
}
}, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
}
private static String report(String owner, String method, String detail) {
return "\n " + owner.replace('/', '.') + "#" + method + " -> " + detail;
}
}
@@ -2,6 +2,11 @@ package art.arcane.iris.purity;
import art.arcane.iris.engine.object.annotations.Snippet;
import org.junit.Test;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import java.io.File;
import java.lang.annotation.Annotation;
@@ -10,7 +15,6 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -22,8 +26,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -74,13 +76,12 @@ public class PackTypeBukkitPurityGateTest {
/** See {@link #theGateStillCatchesAClassThatNeedsBukkit()}. */
private static final String BUKKIT_DEPENDENT_CANARY = "art.arcane.iris.engine.object.IrisObjectRotation$Faces";
private static final String OBJECT_PACKAGE = "art/arcane/iris/engine/object";
private static final Path IRIS_DATA_SOURCE =
Paths.get("src", "main", "java", "art", "arcane", "iris", "core", "loader", "IrisData.java");
private static final String IRIS_DATA = "art.arcane.iris.core.loader.IrisData";
/**
* Every type handed to {@code registerLoader} in {@code IrisData.hotloaded()} - i.e. every root
* type Gson deserializes from a pack. Kept literal on purpose; {@link
* #registeredRootListMatchesIrisData()} fails if the source drifts away from it.
* #registeredRootListMatchesIrisData()} fails if the compiled registrations drift away from it.
*/
private static final List<String> GSON_REGISTERED_ROOTS = List.of(
"art.arcane.iris.engine.object.IrisLootTable",
@@ -140,21 +141,52 @@ public class PackTypeBukkitPurityGateTest {
@Test
public void registeredRootListMatchesIrisData() throws Exception {
if (!Files.isRegularFile(IRIS_DATA_SOURCE)) {
return;
}
String source = Files.readString(IRIS_DATA_SOURCE, StandardCharsets.UTF_8);
Matcher matcher = Pattern.compile("registerLoader\\((\\w+)\\.class").matcher(source);
Set<String> inSource = new TreeSet<>();
while (matcher.find()) {
inSource.add(matcher.group(1));
}
byte[] bytes = BukkitHidingClassLoader.readClassBytes(getClass().getClassLoader(), IRIS_DATA);
assertNotNull("no class bytes for " + IRIS_DATA, bytes);
Set<String> registered = new TreeSet<>();
new ClassReader(bytes).accept(new ClassVisitor(Opcodes.ASM9) {
@Override
public MethodVisitor visitMethod(
int access,
String name,
String descriptor,
String signature,
String[] exceptions
) {
return new MethodVisitor(Opcodes.ASM9) {
private String pendingRegistrant;
@Override
public void visitLdcInsn(Object value) {
if (value instanceof Type type && type.getSort() == Type.OBJECT) {
pendingRegistrant = type.getClassName();
}
}
@Override
public void visitMethodInsn(
int opcode,
String owner,
String methodName,
String methodDescriptor,
boolean isInterface
) {
if ("registerLoader".equals(methodName) && pendingRegistrant != null) {
registered.add(pendingRegistrant.substring(pendingRegistrant.lastIndexOf('.') + 1));
}
pendingRegistrant = null;
}
};
}
}, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
Set<String> inTest = new TreeSet<>();
for (String name : GSON_REGISTERED_ROOTS) {
inTest.add(name.substring(name.lastIndexOf('.') + 1));
}
assertEquals("IrisData registers a different set of pack roots than this gate covers - "
+ "add the new type to GSON_REGISTERED_ROOTS", inTest, inSource);
+ "add the new type to GSON_REGISTERED_ROOTS", inTest, registered);
}
@Test
@@ -1,21 +1,32 @@
package art.arcane.iris.spi;
import art.arcane.iris.core.service.StudioSVC;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Answers.CALLS_REAL_METHODS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class PacksFolderContractTest {
private static final String PLATFORM_OWNER = "art/arcane/iris/spi/IrisPlatform";
private static final String PACKS_ROOT_NAME = StudioSVC.WORKSPACE_NAME;
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
@@ -29,24 +40,92 @@ public class PacksFolderContractTest {
assertEquals(new File(data, "packs" + File.separator + "overworld"), platform.packsFolderNoCreate("overworld"));
}
/**
* Source guard: nothing outside the SPI defaults and platform overrides may spell the packs
* root by hand. New code goes through packsFolder()/packsFolderNoCreate().
*/
@Test
public void noCallSiteResolvesThePacksRootByHand() throws Exception {
List<Path> roots = List.of(
Path.of("src/main/java"),
Path.of("../adapters/bukkit/plugin/src/main/java"));
for (Path root : roots) {
try (var stream = Files.walk(root)) {
for (Path file : stream.filter(p -> p.toString().endsWith(".java")).toList()) {
String text = Files.readString(file);
assertFalse(file + " must use packsFolder() instead of dataFolder(\"packs\")",
text.contains("dataFolder(\"packs\")"));
assertFalse(file + " must use packsFolderNoCreate() instead of the WORKSPACE_NAME indirection",
text.contains("dataFolderNoCreate(StudioSVC.WORKSPACE_NAME"));
}
public void noCompiledCallSiteResolvesThePacksRootByHand() throws Exception {
Path classes = Path.of(StudioSVC.class.getProtectionDomain().getCodeSource().getLocation().toURI());
assertTrue("core classes must be a directory to scan, got " + classes, Files.isDirectory(classes));
List<String> violations = new ArrayList<>();
int scanned = 0;
try (Stream<Path> tree = Files.walk(classes)) {
for (Path file : tree.filter(candidate -> candidate.toString().endsWith(".class")).toList()) {
collectViolations(file, violations);
scanned++;
}
}
assertTrue("the gate scanned only " + scanned + " core classes, so it proves nothing", scanned > 1000);
assertTrue("These methods spell the packs root by hand instead of going through"
+ " IrisPlatform.packsFolder()/packsFolderNoCreate():" + String.join("", violations),
violations.isEmpty());
}
private static void collectViolations(Path classFile, List<String> violations) throws Exception {
ClassReader reader;
try (InputStream input = Files.newInputStream(classFile)) {
reader = new ClassReader(input);
}
String owner = reader.getClassName();
if (owner.equals(PLATFORM_OWNER)) {
return;
}
reader.accept(new ClassVisitor(Opcodes.ASM9) {
@Override
public MethodVisitor visitMethod(
int access,
String name,
String descriptor,
String signature,
String[] exceptions
) {
return new PacksRootCallSite(owner, name, violations);
}
}, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
}
private static final class PacksRootCallSite extends MethodVisitor {
private final String owner;
private final String method;
private final List<String> violations;
private boolean loadsPacksRootName;
private boolean resolvesDataFolder;
private PacksRootCallSite(String owner, String method, List<String> violations) {
super(Opcodes.ASM9);
this.owner = owner;
this.method = method;
this.violations = violations;
}
@Override
public void visitLdcInsn(Object value) {
if (PACKS_ROOT_NAME.equals(value)) {
loadsPacksRootName = true;
}
}
@Override
public void visitMethodInsn(
int opcode,
String methodOwner,
String methodName,
String methodDescriptor,
boolean isInterface
) {
if (!PLATFORM_OWNER.equals(methodOwner)) {
return;
}
if ("dataFolder".equals(methodName) || "dataFolderNoCreate".equals(methodName)) {
resolvesDataFolder = true;
}
}
@Override
public void visitEnd() {
if (loadsPacksRootName && resolvesDataFolder) {
violations.add("\n " + owner.replace('/', '.') + "#" + method);
}
}
}
@@ -21,9 +21,6 @@ import art.arcane.volmlib.util.collection.KList;
import art.arcane.volmlib.util.director.exceptions.DirectorParsingException;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -231,24 +228,6 @@ public class StructureHandlerTest {
}
}
@Test
public void completionUsesOneReachabilitySnapshotAndLocatableKeys() throws IOException {
Path sourcePath = Path.of(
"src/main/java/art/arcane/iris/util/common/director/specialhandlers/StructureHandler.java");
String source = Files.readString(sourcePath).replace("\r\n", "\n");
int methodStart = source.indexOf("public KList<String> getPossibilities()");
int methodEnd = source.indexOf("@Override\n public String toString", methodStart);
String method = source.substring(methodStart, methodEnd);
assertEquals(1, occurrences(method, "StructureReachability.reachableKeys(activeEngine)"));
assertEquals(0, occurrences(method, "IrisStructureLocator.locatableKeys(activeEngine)"));
assertEquals(1, occurrences(method, "IrisStructureLocator.locatableEditableKeys(activeEngine)"));
assertTrue(method.indexOf("if (activeEngine == null)")
< method.indexOf("IrisPlatforms.get().structureHooks()"));
assertFalse(method.contains("INMS"));
assertFalse(method.contains("catch ("));
}
private static IrisNativeStructureDecision decision(NativeStructureGenerationStatus status) {
return new IrisNativeStructureDecision(status, 0, null, false, null, null);
}
@@ -268,16 +247,6 @@ public class StructureHandlerTest {
return placement;
}
private static int occurrences(String source, String target) {
int count = 0;
int offset = 0;
while ((offset = source.indexOf(target, offset)) >= 0) {
count++;
offset += target.length();
}
return count;
}
private static final class TestStructureHandler extends StructureHandler {
private final Engine activeEngine;
private final boolean nativeGenerationEnabled;
@@ -1,24 +0,0 @@
package art.arcane.iris.util.common.scheduling;
import org.junit.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertTrue;
public class JRegionFutureContractTest {
@Test
public void regionFutureSettlesEverySchedulerPath() throws Exception {
String source = Files.readString(Path.of(
"src/main/java/art/arcane/iris/util/common/scheduling/J.java"))
.replace("\r\n", "\n");
int start = source.indexOf("public static CompletableFuture<Void> runRegionFuture(");
int end = source.indexOf("public static boolean runGlobal(", start);
String method = source.substring(start, end);
assertTrue(method.contains("settle(future, runnable)"));
assertTrue(method.contains("future.completeExceptionally("));
assertTrue(method.contains("return sfut(runnable);"));
}
}