mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-22 16:17:44 +00:00
Faster green test suite
- Removed the core processResources skip that fired on test-only invocations, which packaged a core jar with no generation kernel catalog and made all 10 probe and bukkit-plugin tests that reach GenerationKernelRegistry fail on every ./gradlew test - Set maxParallelForks on :core:test to half the available processors, overridable with -PtestForks, and left the small modules single-forked so they do not re-pay the Minecraft bootstrap per fork or steal worker leases from core - Resolved B.registries() per bound platform instead of latching the first one for the JVM lifetime, keeping the previous unbound behaviour, so a test that binds its own platform no longer reads a foreign platform's block states - Resolved IrisObject.States per bound platform through accessors instead of static finals fixed at class-init, removing the NoClassDefFoundError and null material-key failures that appeared whenever class partitioning changed - Bound an explicit platform in EngineMantleCoverageTest and IrisDimensionStackActuatorMetadataTest so they no longer depend on another class leaking a binding first - Gated BukkitSpiConformanceTest registry probes on a live RegistryAccess and restored the IrisPlatforms binding it leaked, which was silently swallowing the stderr two SettingsHotloadWatchTest assertions read - Initialised org.bukkit.Registry and Biome inside the RegistryAccess mock scope in ObjectStudioGeometryTest so Mockito no longer instruments Registry mid-clinit - Replaced the SettingsHotloadWatchTest fixed 1200ms diagnostic window with a 10ms condition poll bounded at 4s - Replaced the IrisCaveCarver3DNearParityTest wall-clock speedup benchmark with a deterministic density-sample count, cutting 28 carves to 2 - Cut HydrologyPlannerTest cold-owner parity from 12 tile plans to 4 and shared the immutable baseline plan across the early-owner tests - Built one prototype project or staged history per class in the jigsaw studio and world replacement tests and copied it per test, replacing repeated fsync-bound fixture construction - Replaced Mockito block-state fixtures with concrete implementations in the object IO, deposit modifier and nearest-block-index tests, removing about 2.5 million interceptions - Replaced Thread.sleep with bounded condition polling in HydrologyTileCacheTest - Deleted 19 test classes and 60 further test methods that asserted on production .java source text rather than behaviour, and removed the 19 now-unread iris.*Source system properties that fed them
This commit is contained in:
1 parent
d3245aa1c2
commit
266fe0d71c
66 files changed
+1481
-3238
No files matched your search
@@ -1,222 +0,0 @@
|
||||
package art.arcane.iris;
|
||||
|
||||
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 IrisShutdownOrderingTest {
|
||||
@Test
|
||||
public void serverStopHoldsThePluginLoaderUntilTerminalCleanupCompletes() throws Exception {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.startupSource")));
|
||||
String quiesce = section(source, "private void quiesceRuntimeForServerShutdown", "private void startPostStopFinisher");
|
||||
String cleanup = section(source, "private void finishTerminalCleanup()", "private void drainWorldGenerators");
|
||||
String teardown = section(source, "private void teardownRuntime", "private void quiesceRuntimeForServerShutdown");
|
||||
String deferred = section(source, "private void finishDeferredRuntimeTeardown", "private void finishTerminalCleanup");
|
||||
|
||||
assertOrdered(quiesce, "serverStopTeardownDeferred.set(true)", "deferPluginClassLoaderClose()",
|
||||
"jigsawStudioService.quiesceForServerShutdown()");
|
||||
assertOrdered(cleanup, "runPostShutdown()", "hasActiveShutdownResources()", "IrisPlatforms.unbind()",
|
||||
"runtimeTeardownFailed.get()", "releasePluginClassLoaderClose()");
|
||||
assertTrue(cleanup.contains("!MultiBurst.burst.isTerminated() || !MultiBurst.ioBurst.isTerminated()"));
|
||||
assertTrue(cleanup.contains("preservation.hasActiveResources()"));
|
||||
assertOrdered(teardown, "drainWorldGenerators(reason, timeoutSeconds)", "!generatorDrainCompleted",
|
||||
"return;", "service.onDisable()");
|
||||
assertOrdered(deferred, "teardownRuntime(reason, timeoutSeconds)", "!generatorDrainCompleted",
|
||||
"SHUTDOWN_ERRORS.println", "return;", "finishTerminalCleanup()");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deferredShutdownErrorsBypassClosedLoggingServices() throws Exception {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.startupSource")));
|
||||
String throwableReport = section(source, "public static void reportError(Throwable e)",
|
||||
"public static void reportError(String context, Throwable e)");
|
||||
String contextualReport = section(source, "public static void reportError(String context, Throwable e)",
|
||||
"public static void dump()");
|
||||
|
||||
assertOrdered(throwableReport, "serverStopTeardownDeferred.get()",
|
||||
"e.printStackTrace(SHUTDOWN_ERRORS)", "boolean debug = false");
|
||||
assertOrdered(contextualReport, "serverStopTeardownDeferred.get()",
|
||||
"SHUTDOWN_ERRORS.println(", "error.printStackTrace(SHUTDOWN_ERRORS)", "Iris.error(message)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void drainWorldGenerators_closesGeneratorsWithoutEagerMantleSave() throws Exception {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.startupSource")));
|
||||
String drain = section(source, "private void drainWorldGenerators", "private void setupPapi");
|
||||
|
||||
assertTrue("Shutdown must close each Iris generator", drain.contains("generator.closeAsync()"));
|
||||
assertFalse("Shutdown must not close Mantle plates before generation drains", drain.contains("saveAllNow()"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shutdownBoundaryIsPreparedBeforeHookRegistrationAndDoesNotUseClosedBindings() throws Exception {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.startupSource")));
|
||||
String registration = section(source, "public void addShutdownHook()", "public void removeShutdownHook()");
|
||||
String boundary = section(source, "private boolean awaitServerShutdownBoundary()",
|
||||
"private void finishDeferredRuntimeTeardown");
|
||||
|
||||
assertOrdered(registration, "createServerShutdownBoundary()", "new Thread(this::runShutdownHook",
|
||||
"Runtime.getRuntime().addShutdownHook");
|
||||
assertTrue(boundary.contains("boundary.await("));
|
||||
assertFalse(boundary.contains("INMS.get()"));
|
||||
assertFalse(boundary.contains("Iris.reportError"));
|
||||
assertTrue(source.contains("new FileOutputStream(FileDescriptor.err)"));
|
||||
assertOrdered(boundary, "SHUTDOWN_ERRORS.println(", "e.printStackTrace(SHUTDOWN_ERRORS)", "return false;");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serverStop_defersRuntimeTeardownUntilPaperShutdownBoundary() throws Exception {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.startupSource")));
|
||||
String onDisable = section(source, "public void onDisable()", "public void onPreUnload");
|
||||
String quiesce = section(source, "private void quiesceRuntimeForServerShutdown", "private void startPostStopFinisher");
|
||||
String shutdownHook = section(source, "private void runShutdownHook()", "private boolean awaitServerShutdownBoundary");
|
||||
String finisher = section(source, "private void startPostStopFinisher()", "static boolean awaitServerThreadTermination");
|
||||
String serverJoin = section(source, "static boolean awaitServerThreadTermination", "private void runShutdownHook");
|
||||
String generatorSource = Files.readString(Path.of(System.getProperty("iris.bukkitChunkGeneratorSource")));
|
||||
String generatorQuiesce = section(generatorSource,
|
||||
"public void quiesceForServerShutdown()", "public boolean isStudio()");
|
||||
|
||||
assertOrdered(onDisable,
|
||||
"startupBoundaryRestart.get()",
|
||||
"teardownRuntime(\"startup-boundary-restart\", 30L)",
|
||||
"else if (serverStopping)",
|
||||
"quiesceRuntimeForServerShutdown(\"onDisable\")",
|
||||
"startPostStopFinisher()",
|
||||
"} else {",
|
||||
"teardownRuntime(\"onDisable\", 30L)");
|
||||
assertOrdered(shutdownHook,
|
||||
"startupBoundaryRestart.get()",
|
||||
"finishDeferredRuntimeTeardown(\"startup-boundary-restart-hook\", 30L)",
|
||||
"return;",
|
||||
"awaitServerShutdownBoundary()",
|
||||
"SHUTDOWN_ERRORS.println",
|
||||
"finishDeferredRuntimeTeardown(\"shutdown-hook\", 30L)");
|
||||
assertOrdered(finisher,
|
||||
"finisher.setDaemon(false)",
|
||||
"finisher.start()");
|
||||
assertOrdered(finisher,
|
||||
"awaitServerThreadTermination(activeServerThread)",
|
||||
"finishDeferredRuntimeTeardown(\"post-server-stop\", 30L)");
|
||||
assertOrdered(serverJoin,
|
||||
"serverThread == Thread.currentThread()",
|
||||
"serverThread.join()");
|
||||
assertTrue("Server-stop quiescence must leave queued Paper generation admitted",
|
||||
quiesce.contains("generator.quiesceForServerShutdown()"));
|
||||
assertOrdered(quiesce,
|
||||
"jigsawStudioService.quiesceForServerShutdown()",
|
||||
"PregeneratorJob.shutdownAndWait",
|
||||
"generator.quiesceForServerShutdown()");
|
||||
assertOrdered(onDisable,
|
||||
"quiesceRuntimeForServerShutdown(\"onDisable\")",
|
||||
"super.onDisable()");
|
||||
assertFalse("Server-stop quiescence must not begin generator close before Paper's boundary",
|
||||
generatorQuiesce.contains("closing = true"));
|
||||
assertFalse("Server-stop quiescence must not dispatch generator close before Paper's boundary",
|
||||
generatorQuiesce.contains("closeAsync()"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deferredTeardown_keepsGeneratorClosingServicesBehindGeneratorDrain() throws Exception {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.startupSource")));
|
||||
String engineService = Files.readString(Path.of(System.getProperty("iris.engineSvcSource")));
|
||||
String studioService = Files.readString(Path.of(System.getProperty("iris.studioSvcSource")));
|
||||
String generatorSource = Files.readString(Path.of(System.getProperty("iris.bukkitChunkGeneratorSource")));
|
||||
String teardown = section(source, "private void teardownRuntime", "private void quiesceRuntimeForServerShutdown");
|
||||
String engineDisable = section(engineService, "public void onDisable()", "public void engineStatus");
|
||||
String studioDisable = section(studioService, "public void onDisable()", "public IrisDimension installIntoWorld");
|
||||
String generatorClose = section(generatorSource,
|
||||
"public void close()", "public CompletableFuture<Void> closeAsync()");
|
||||
String generatorCloseAsync = section(generatorSource,
|
||||
"public CompletableFuture<Void> closeAsync()", "public void quiesceForServerShutdown()");
|
||||
|
||||
assertOrdered(teardown,
|
||||
"drainWorldGenerators(reason, timeoutSeconds)",
|
||||
"service.onDisable()",
|
||||
"MultiBurst.burst.close()",
|
||||
"MultiBurst.ioBurst.close()");
|
||||
assertTrue("Engine service must retain its generator close behind deferred service teardown",
|
||||
engineDisable.contains("startClose("));
|
||||
assertTrue("Studio service must retain its generator close behind deferred service teardown",
|
||||
studioDisable.contains("generator.close()"));
|
||||
assertTrue("Service-level generator close must delegate to the shared idempotent close future",
|
||||
generatorClose.contains("closeAsync()"));
|
||||
assertTrue("Repeated post-boundary closes must return the already-published close future",
|
||||
generatorCloseAsync.contains("return existing;"));
|
||||
assertFalse("A completed generator close must never be re-dispatched",
|
||||
generatorCloseAsync.contains("!existing.isDone()"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preUnload_doesNotDrainGeneratorsDuringServerStop() throws Exception {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.startupSource")));
|
||||
String preUnload = section(source, "public void onPreUnload", "private void drainOnce");
|
||||
|
||||
assertOrdered(preUnload,
|
||||
"IrisToolbelt.isServerStopping()",
|
||||
"quiesceRuntimeForServerShutdown",
|
||||
"startPostStopFinisher()",
|
||||
"return;",
|
||||
"drainOnce(");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jigsawStudio_quiescesOnceBeforeDeferredServiceTeardown() throws Exception {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.jigsawStudioSvcSource")));
|
||||
String enable = section(source, "public void onEnable()", "public void onDisable()");
|
||||
String disable = section(source, "public void onDisable()", "public void quiesceForServerShutdown()");
|
||||
String quiesce = section(source, "public void quiesceForServerShutdown()", "public void register(");
|
||||
String register = section(source, "public void register(", "public void activationCommitted(");
|
||||
String activation = section(source, "public void activationCommitted(", "public void markChunkGenerated(");
|
||||
String chunkGenerated = section(source, "public void markChunkGenerated(", "private void markChunkAvailable(");
|
||||
|
||||
assertOrdered(enable, "disableStarted.set(false)", "enabled = true");
|
||||
assertTrue("Deferred service teardown must reuse the idempotent early disable",
|
||||
disable.contains("quiesceForServerShutdown();"));
|
||||
assertOrdered(quiesce,
|
||||
"disableStarted.compareAndSet(false, true)",
|
||||
"finalizeAllJigsawTileWatches()",
|
||||
"drainAutosavesBeforeDisable()",
|
||||
"enabled = false",
|
||||
"activeMenuController.closeAll()",
|
||||
"previewRenderer.removeAll()",
|
||||
"studios.clear()");
|
||||
assertTrue("Registration must reject work after shutdown begins",
|
||||
occurrences(register, "!enabled || disableStarted.get()") >= 2);
|
||||
assertTrue("Activation must reject work after shutdown begins",
|
||||
activation.contains("!enabled || disableStarted.get()"));
|
||||
assertTrue("Chunk-generation callbacks must reject work after shutdown begins",
|
||||
occurrences(chunkGenerated, "!enabled || disableStarted.get()") >= 2);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
private static int occurrences(String source, String marker) {
|
||||
int count = 0;
|
||||
int offset = 0;
|
||||
while ((offset = source.indexOf(marker, offset)) >= 0) {
|
||||
count++;
|
||||
offset += marker.length();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
-157
@@ -15,12 +15,10 @@ import org.junit.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -132,125 +130,6 @@ public class PendingWorldReplacementThreadAffinityTest {
|
||||
assertTrue(irisEnvironmentFailure.getMessage().contains("requires a pack environment of NETHER"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bukkitAccessIsConfinedToTheGlobalCaptureStage() throws Exception {
|
||||
String managerSource = Files.readString(Path.of(
|
||||
"src/main/java/art/arcane/iris/core/PendingWorldReplacementManager.java")).replace("\r\n", "\n");
|
||||
String irisSource = Files.readString(Path.of("src/main/java/art/arcane/iris/Iris.java")).replace("\r\n", "\n");
|
||||
String startup = method(managerSource, "public void verifyLoadedPublishedWorlds()");
|
||||
String worldLoad = method(managerSource, "public void onWorldLoad(WorldLoadEvent event)");
|
||||
String discovery = method(managerSource, "private void discoverLoadedPublishedWorlds()");
|
||||
String capture = method(managerSource,
|
||||
"private void captureLoadedPublishedWorldOnGlobal(Transaction transaction)");
|
||||
String snapshot = method(managerSource, "static PublishedWorldRuntimeState capturePublishedWorldRuntime(World world)");
|
||||
String verification = method(managerSource,
|
||||
"private void verifyPublishedWorld(PublishedWorldRuntimeState runtimeState, Transaction transaction)");
|
||||
|
||||
assertTrue(startup.contains("J.a(this::discoverLoadedPublishedWorlds)"));
|
||||
assertTrue(worldLoad.contains("WorldIdentity.key(event.getWorld())"));
|
||||
assertTrue(worldLoad.contains("J.a(() -> discoverLoadedWorldTransaction(worldKey))"));
|
||||
assertTrue(capture.contains("WorldIdentity.resolve("));
|
||||
assertBefore(capture, "capturePublishedWorldRuntime(world)",
|
||||
"J.a(() -> runPublishedWorldVerification(runtimeState, transaction))");
|
||||
assertTrue(snapshot.contains("WorldIdentity.key(requiredWorld)"));
|
||||
assertTrue(snapshot.contains("IrisToolbelt.isIrisWorld(requiredWorld)"));
|
||||
assertTrue(snapshot.contains("requiredWorld.getSeed()"));
|
||||
assertTrue(snapshot.contains("requiredWorld.getEnvironment()"));
|
||||
assertTrue(snapshot.contains("IrisToolbelt.access(requiredWorld)"));
|
||||
assertNoBukkitRuntimeAccess(discovery);
|
||||
assertNoBukkitRuntimeAccess(verification);
|
||||
assertTrue(verification.contains("WorldReplacementFilesystem.fingerprintPack("));
|
||||
assertTrue(irisSource.contains("pendingWorldReplacements.verifyLoadedPublishedWorlds();"));
|
||||
assertFalse(irisSource.contains("J.a(pendingWorldReplacements::verifyLoadedPublishedWorlds)"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paperLoginHookIsIsolatedFromAlwaysLoadedSpigotClasses() throws Exception {
|
||||
String managerSource = Files.readString(Path.of(
|
||||
"src/main/java/art/arcane/iris/core/PendingWorldReplacementManager.java")).replace("\r\n", "\n");
|
||||
String irisSource = Files.readString(Path.of("src/main/java/art/arcane/iris/Iris.java")).replace("\r\n", "\n");
|
||||
String listenerSource = Files.readString(Path.of(
|
||||
"src/main/java/art/arcane/iris/core/PaperWorldReplacementEntryListener.java")).replace("\r\n", "\n");
|
||||
String registration = method(managerSource, "public void registerPlatformEntryListener()");
|
||||
|
||||
assertFalse(managerSource.contains("import io.papermc.paper.event.player.AsyncPlayerSpawnLocationEvent"));
|
||||
assertFalse(managerSource.contains("AsyncPlayerSpawnLocationEvent event"));
|
||||
assertFalse(irisSource.contains("AsyncPlayerSpawnLocationEvent"));
|
||||
assertTrue(registration.contains("Class.forName(\"io.papermc.paper.event.player.AsyncPlayerSpawnLocationEvent\""));
|
||||
assertTrue(registration.contains("Class.forName("));
|
||||
assertTrue(registration.contains("PaperWorldReplacementEntryListener"));
|
||||
assertTrue(irisSource.contains("pendingWorldReplacements.registerPlatformEntryListener();"));
|
||||
assertTrue(listenerSource.contains("onAsyncPlayerSpawnLocation(AsyncPlayerSpawnLocationEvent event)"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void redirectedPlayerReceiptSurvivesUntilTheMaterializedPositionIsSaved() throws Exception {
|
||||
String managerSource = Files.readString(Path.of(
|
||||
"src/main/java/art/arcane/iris/core/PendingWorldReplacementManager.java")).replace("\r\n", "\n");
|
||||
String listenerSource = Files.readString(Path.of(
|
||||
"src/main/java/art/arcane/iris/core/PaperWorldReplacementEntryListener.java")).replace("\r\n", "\n");
|
||||
String preparation = method(
|
||||
managerSource,
|
||||
"ReplacementEntryRedirect prepareReplacementEntry(UUID playerId, Location savedLocation, boolean newPlayer)"
|
||||
);
|
||||
String acknowledgement = method(
|
||||
managerSource,
|
||||
"void expectReplacementEntryAcknowledgement(UUID playerId, UUID transactionId)"
|
||||
);
|
||||
String join = method(managerSource, "public void onPlayerJoin(PlayerJoinEvent event)");
|
||||
String listener = method(
|
||||
listenerSource,
|
||||
"public void onAsyncPlayerSpawnLocation(AsyncPlayerSpawnLocationEvent event)"
|
||||
);
|
||||
|
||||
assertTrue(preparation.contains("return new ReplacementEntryRedirect(guard.transactionId(), prepared, pendingPlayer)"));
|
||||
assertFalse(preparation.substring(preparation.indexOf("CompletableFuture<Location> safeEntry"))
|
||||
.contains("completeOverworldEntry("));
|
||||
assertBefore(listener, "event.setSpawnLocation(location)",
|
||||
"manager.expectReplacementEntryAcknowledgement(playerId, redirect.transactionId())");
|
||||
assertTrue(acknowledgement.contains("pendingEntryAcknowledgements.put(playerId, transactionId)"));
|
||||
assertBefore(join, "event.getPlayer().saveData()", "completeOverworldEntry(playerId, transactionId)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replacementSpawnIsPersistedBeforeFinalMarkerRetirement() throws Exception {
|
||||
String managerSource = Files.readString(Path.of(
|
||||
"src/main/java/art/arcane/iris/core/PendingWorldReplacementManager.java")).replace("\r\n", "\n");
|
||||
String listenerSource = Files.readString(Path.of(
|
||||
"src/main/java/art/arcane/iris/core/PaperWorldReplacementEntryListener.java")).replace("\r\n", "\n");
|
||||
String preparation = method(managerSource, "private void prepareOverworldEntry(World world)");
|
||||
String persistence = method(managerSource, "public void onWorldSave(WorldSaveEvent event)");
|
||||
String retirement = method(
|
||||
managerSource,
|
||||
"private synchronized void retireOverworldEntryIfCompleteAsync(UUID transactionId)"
|
||||
);
|
||||
String listener = method(
|
||||
listenerSource,
|
||||
"public void onAsyncPlayerSpawnLocation(AsyncPlayerSpawnLocationEvent event)"
|
||||
);
|
||||
String generatorSource = Files.readString(Path.of(System.getProperty("iris.bukkitChunkGeneratorSource")));
|
||||
|
||||
assertBefore(preparation, "overworldSpawnPersistence = persistence",
|
||||
"targetFuture.complete(safeEntry.clone())");
|
||||
assertTrue(persistence.contains("event.getWorld() != replacementWorld"));
|
||||
assertTrue(persistence.contains("persistence.complete(null)"));
|
||||
assertTrue(retirement.contains("!current.pendingPlayers().isEmpty()"));
|
||||
assertTrue(retirement.contains("!persistence.isDone()"));
|
||||
assertTrue(retirement.contains("persistence.isCompletedExceptionally()"));
|
||||
assertTrue(listener.contains("event.isNewPlayer()"));
|
||||
assertTrue(generatorSource.contains("world.getHighestBlockYAt(initialSpawn) + 1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginCollisionInspectionDoesNotGenerateMissingReplacementChunks() throws Exception {
|
||||
String managerSource = Files.readString(Path.of(
|
||||
"src/main/java/art/arcane/iris/core/PendingWorldReplacementManager.java")).replace("\r\n", "\n");
|
||||
String inspection = method(managerSource, "private CompletableFuture<Boolean> inspectLoginCollision(Location location)");
|
||||
|
||||
assertTrue(inspection.contains("requestChunkAsync(world, chunkX, chunkZ, false, true)"));
|
||||
assertBefore(inspection, "chunk == null", "inspectLoadedLoginCollision(requiredLocation)");
|
||||
}
|
||||
|
||||
private static PendingWorldReplacementManager.PublishedWorldRuntimeState runtimeState(
|
||||
WorldSlotKey worldKey,
|
||||
long seed,
|
||||
@@ -281,40 +160,4 @@ public class PendingWorldReplacementThreadAffinityTest {
|
||||
Phase.PUBLISHED
|
||||
);
|
||||
}
|
||||
|
||||
private static void assertNoBukkitRuntimeAccess(String source) {
|
||||
assertFalse(source.contains("WorldIdentity."));
|
||||
assertFalse(source.contains("IrisToolbelt."));
|
||||
assertFalse(source.contains("getSeed()"));
|
||||
assertFalse(source.contains("getEnvironment()"));
|
||||
assertFalse(source.contains("Bukkit."));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
package art.arcane.iris.core.commands;
|
||||
|
||||
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 CommandFindRiverContractTest {
|
||||
@Test
|
||||
public void riverLookupMergesRecordedAndEligibleActiveFeatures() throws IOException {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.commandFindSource")));
|
||||
int methodStart = source.indexOf("public void river(");
|
||||
int methodEnd = source.indexOf("public void structure(", methodStart);
|
||||
String method = source.substring(methodStart, methodEnd);
|
||||
|
||||
assertTrue(method.contains("GenerationSemanticQueries.nearestRiver("));
|
||||
assertTrue(method.contains("runtime == null"));
|
||||
assertTrue(method.contains("feature.y()"));
|
||||
assertFalse(method.contains("runtime.nearestFeature("));
|
||||
assertFalse(method.contains("feature.y() + activeEngine.getDimension().getMinHeight()"));
|
||||
}
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
package art.arcane.iris.core.commands;
|
||||
|
||||
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 CommandFindStructureHistoryContractTest {
|
||||
@Test
|
||||
public void admitsRetainedStructuresBeforeActiveOnlyRejectionsAndUsesSemanticSearch() throws IOException {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.commandFindSource")));
|
||||
int structureStart = source.indexOf("public void structure(");
|
||||
int retainedAdmission = source.indexOf("GenerationFindCatalog.hasRetainedStructurePlacement(e, structureKey)", structureStart);
|
||||
int unknownRejection = source.indexOf("if (route == StructureLookupRoute.UNKNOWN)", structureStart);
|
||||
assertTrue(retainedAdmission > structureStart && retainedAdmission < unknownRejection);
|
||||
|
||||
int locateStart = source.indexOf("private void locateIrisStructure(");
|
||||
int locateEnd = source.indexOf("public void object(", locateStart);
|
||||
String locate = source.substring(locateStart, locateEnd);
|
||||
assertTrue(locate.contains("GenerationSemanticQueries.nearestStructure("));
|
||||
assertFalse(locate.contains("IrisStructureLocator.locate("));
|
||||
}
|
||||
}
|
||||
-35
@@ -1,35 +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 class CommandIrisFoliaCreateContractTest {
|
||||
@Test
|
||||
public void ordinaryFoliaCreateUsesTheSharedRuntimeCreationPath() throws Exception {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.commandIrisSource")));
|
||||
String create = source.substring(
|
||||
source.indexOf(" public void create("),
|
||||
source.indexOf(" @Director(", source.indexOf(" public void create("))
|
||||
);
|
||||
|
||||
assertTrue(create.contains("IrisToolbelt.createWorld()"));
|
||||
assertTrue(create.contains(".studio(false)"));
|
||||
assertTrue(create.contains(".create();"));
|
||||
assertFalse(create.contains("J.isFolia()"));
|
||||
assertFalse(create.contains("ServerConfigurator.restart("));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void obsoleteFoliaStagingSurfaceIsRemoved() throws Exception {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.commandIrisSource")));
|
||||
|
||||
assertFalse(source.contains("stageFoliaWorldCreation"));
|
||||
assertFalse(source.contains("writeCurrentPaperWorldData"));
|
||||
assertFalse(source.contains("COMMAND_IRIS_RUNTIME_WORLD_CREATION_IS_DISABLED_ON_FOLIA"));
|
||||
}
|
||||
}
|
||||
+1
-21
@@ -7,17 +7,13 @@ import org.junit.Test;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class CommandIrisLoadWorldContractTest {
|
||||
@Test
|
||||
public void commandUsesTypedAsyncReconciliationBeforeReportingSuccess() throws Exception {
|
||||
public void commandUsesTypedAsyncReconciliation() throws Exception {
|
||||
Method reconciliation = BukkitWorldReconciler.class.getDeclaredMethod(
|
||||
"loadWorld",
|
||||
File.class,
|
||||
@@ -27,21 +23,5 @@ public class CommandIrisLoadWorldContractTest {
|
||||
Parameter worldParameter = commandMethod.getParameters()[0];
|
||||
assertEquals(CommandIris.ManagedWorldNameHandler.class,
|
||||
worldParameter.getAnnotation(Param.class).customHandler());
|
||||
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.commandIrisSource")));
|
||||
String command = source.substring(
|
||||
source.indexOf("public void loadWorld("),
|
||||
source.indexOf("private void reportLoadWorldResult("));
|
||||
String reporter = source.substring(
|
||||
source.indexOf("private void reportLoadWorldResult("),
|
||||
source.indexOf("@Director(description = \"Evacuate an iris world\""));
|
||||
|
||||
assertTrue(command.contains("IrisWorldStorage.managedKeyFromName(world)"));
|
||||
assertTrue(command.contains(".loadWorld(BUKKIT_YML, worldKey.toString())"));
|
||||
assertTrue(command.contains(".whenComplete((result, failure) ->"));
|
||||
assertFalse(command.contains("checkForBukkitWorlds"));
|
||||
assertFalse(command.contains("COMMAND_IRIS_LOADED_SUCCESSFULLY"));
|
||||
assertTrue(reporter.contains("if (result.succeeded())"));
|
||||
assertTrue(reporter.contains("COMMAND_IRIS_LOADED_SUCCESSFULLY"));
|
||||
}
|
||||
}
|
||||
-26
@@ -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.assertTrue;
|
||||
|
||||
public class CommandIrisUnloadContractTest {
|
||||
@Test
|
||||
public void unloadAwaitsEvacuationAndHasATerminalLifecycleTimeout() throws Exception {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.commandIrisSource")));
|
||||
String command = source.substring(
|
||||
source.indexOf("public void unloadWorld("),
|
||||
source.indexOf("private void reportUnloadResult("));
|
||||
|
||||
assertTrue(command.contains("IrisToolbelt.evacuateAsync(world)"));
|
||||
assertTrue(command.indexOf("IrisToolbelt.evacuateAsync(world)")
|
||||
< command.indexOf("WorldLifecycleService.get().unloadAsync(world, true)"));
|
||||
assertTrue(command.contains("guardUnloadCompletion(sequence, terminalTimeout, world.getName())"));
|
||||
assertTrue(command.contains("ServerConfigurator.restart(\"World unload timed out"));
|
||||
assertTrue(command.indexOf("ServerConfigurator.restart(\"World unload timed out")
|
||||
< command.indexOf("guarded.completeExceptionally(timeout)"));
|
||||
}
|
||||
}
|
||||
-125
@@ -5,9 +5,6 @@ import art.arcane.iris.engine.object.IrisNativeStructureDecision;
|
||||
import art.arcane.iris.engine.object.NativeStructureGenerationStatus;
|
||||
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;
|
||||
|
||||
@@ -16,44 +13,6 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class IrisStructureLocateCommandContractTest {
|
||||
@Test
|
||||
public void findReportsDensityLimitAndUsesExactLocatedOrigin() throws IOException {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.commandFindSource")));
|
||||
|
||||
assertTrue(source.contains("LocateStatus.SEARCH_LIMIT_REACHED"));
|
||||
assertTrue(source.contains("the density search safety limit was reached"));
|
||||
assertTrue(source.contains("result.originX(), result.baseY(), result.originZ()"));
|
||||
assertFalse(source.contains("at[0] + 8"));
|
||||
assertFalse(source.contains("at[2] + 8"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findRoutesOnlyActiveWorldStructures() throws IOException {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.commandFindSource")));
|
||||
int methodStart = source.indexOf("public void structure(");
|
||||
int methodEnd = source.indexOf("static StructureLookupRoute selectStructureLookupRoute", methodStart);
|
||||
String method = source.substring(methodStart, methodEnd);
|
||||
int nativeResolution = method.indexOf("resolveNativeStructure(structureKey)");
|
||||
int policyResolution = method.indexOf("NativeStructureGenerationPolicy.resolve(", nativeResolution);
|
||||
int nativeLocatableCheck = method.indexOf(
|
||||
"IrisStructureLocator.hasLocatableNativePlacement(e, structureKey)", policyResolution);
|
||||
int editableLocatableCheck = method.indexOf(
|
||||
"IrisStructureLocator.hasLocatableEditablePlacement(e, structureKey)", nativeLocatableCheck);
|
||||
int worldGenerationCheck = method.indexOf("targetWorld.canGenerateStructures()", editableLocatableCheck);
|
||||
int routeResolution = method.indexOf("selectStructureLookupRoute(", editableLocatableCheck);
|
||||
int nativeLocate = method.indexOf("targetWorld.locateNearestStructure(", routeResolution);
|
||||
|
||||
assertTrue(nativeResolution >= 0);
|
||||
assertTrue(policyResolution > nativeResolution);
|
||||
assertTrue(nativeLocatableCheck > policyResolution);
|
||||
assertTrue(editableLocatableCheck > nativeLocatableCheck);
|
||||
assertTrue(worldGenerationCheck > editableLocatableCheck);
|
||||
assertTrue(routeResolution > editableLocatableCheck);
|
||||
assertTrue(nativeLocate > routeResolution);
|
||||
assertFalse(method.contains("IrisStructureLocator.isPlaced(e, structureKey)"));
|
||||
assertFalse(method.contains("NativeStructureLocateCapability"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findRejectsUnregisteredNativeAndDormantPlacements() {
|
||||
assertEquals(CommandFind.StructureLookupRoute.UNKNOWN,
|
||||
@@ -193,24 +152,6 @@ public class IrisStructureLocateCommandContractTest {
|
||||
"pack:editable", Set.of(), Set.of(), true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unregisteredDiagnosticPrintsDetailsOnlyToConsole() throws IOException {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.commandFindSource")));
|
||||
int methodStart = source.indexOf("public void unregistered()");
|
||||
int methodEnd = source.indexOf("private static StructureExclusionReport", methodStart);
|
||||
String method = source.substring(methodStart, methodEnd);
|
||||
|
||||
assertTrue(methodStart >= 0);
|
||||
assertTrue(source.contains("Iris.info(\"[%s] %s%s: %s\""));
|
||||
assertTrue(method.contains("non-generating structure candidate(s) and their reasons to the server console"));
|
||||
assertTrue(method.contains("no chunks were searched"));
|
||||
assertTrue(method.indexOf("DatapackIngestService.installed()") > method.indexOf("J.a(() ->"));
|
||||
assertTrue(source.contains("DatapackIngestService.configuredImports(engine.getDimension())"));
|
||||
assertTrue(source.contains("snapshot.configuredImportUrls().contains(importUrl)"));
|
||||
assertTrue(source.contains("engine.getData().getStructureLoader().getPossibleKeys()"));
|
||||
assertFalse(method.contains("commandSender.sendMessage(exclusion"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findNativePolicyMessagesMatchModdedDiagnostics() {
|
||||
assertEquals(
|
||||
@@ -227,72 +168,6 @@ public class IrisStructureLocateCommandContractTest {
|
||||
"minecraft:stronghold", NativeStructureGenerationStatus.GENERATE_NATIVE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void structureVerifyReportsDensityLimitAndUsesExactLocatedOrigin() throws IOException {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.commandStructureSource")));
|
||||
|
||||
assertTrue(source.contains("[iris-search-limit]"));
|
||||
assertTrue(source.contains("density searches safety-limited"));
|
||||
assertTrue(source.contains("result.originX() + \",\" + result.baseY() + \",\" + result.originZ()"));
|
||||
assertFalse(source.contains("at[0] + 8"));
|
||||
assertFalse(source.contains("at[2] + 8"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bulkStructureImportRestrictsCaptureWithoutChangingStandaloneCapture() throws IOException {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.commandStructureSource")));
|
||||
int importStart = source.indexOf("public void importAll(");
|
||||
int importEnd = source.indexOf("@Director(name = \"capture\"", importStart);
|
||||
int captureStart = source.indexOf("public void capture(", importEnd);
|
||||
int captureEnd = source.indexOf("@Director(description = \"Verify", captureStart);
|
||||
|
||||
assertTrue(importStart >= 0);
|
||||
assertTrue(importEnd > importStart);
|
||||
assertTrue(captureStart > importEnd);
|
||||
assertTrue(captureEnd > captureStart);
|
||||
String importMethod = source.substring(importStart, importEnd);
|
||||
String captureMethod = source.substring(captureStart, captureEnd);
|
||||
assertTrue(importMethod.contains("StructureCaptureImporter.importStructures("));
|
||||
assertTrue(importMethod.contains("jigsaws.captureCandidates()"));
|
||||
assertFalse(importMethod.contains("StructureCaptureImporter.importAllStructures("));
|
||||
assertTrue(captureMethod.contains("StructureCaptureImporter.importAllStructures("));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void structurePlaceSeparatesPackContentFromTargetWorldEngine() throws IOException {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.commandStructureSource")));
|
||||
int methodStart = source.indexOf("public void place(");
|
||||
assertTrue(methodStart >= 0);
|
||||
String method = source.substring(methodStart);
|
||||
assertTrue(method.contains("IrisData data = dimension.getLoader()"));
|
||||
assertTrue(method.contains("PlatformChunkGenerator targetGenerator = IrisToolbelt.access(targetWorld)"));
|
||||
assertTrue(method.contains("CommandObject.createPlacer(targetWorld, future, targetEngine)"));
|
||||
assertTrue(method.contains("if (blockChanges == 0)"));
|
||||
assertTrue(method.contains("COMMAND_STRUCTURE_PLACEMENT_CHANGED_NO_BLOCKS"));
|
||||
Path structureSource = Path.of(System.getProperty("iris.commandStructureSource"));
|
||||
String objectSource = Files.readString(structureSource.resolveSibling("CommandObject.java"));
|
||||
assertTrue(objectSource.contains("futureBlockChanges.putIfAbsent(block, block.getBlockData())"));
|
||||
assertFalse(method.contains("data.getEngine()"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void structureVerifyPartitionsPolicyBeforeNativeReachability() throws IOException {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.commandStructureSource")));
|
||||
int methodStart = source.indexOf("private void runVerification(");
|
||||
int methodEnd = source.indexOf("private void sendVerificationMessages(", methodStart);
|
||||
String method = source.substring(methodStart, methodEnd);
|
||||
int policyResolution = method.indexOf("NativeStructureGenerationPolicy.resolve(engine, keyName, false)");
|
||||
int nativeRequirement = method.indexOf(
|
||||
"requiresNativeReachability |= !IrisStructureLocator.isPlaced", policyResolution);
|
||||
int reachabilityGuard = method.indexOf("if (requiresNativeReachability)", nativeRequirement);
|
||||
int reachabilityLookup = method.indexOf("StructureReachability.reachableKeys(engine)", reachabilityGuard);
|
||||
|
||||
assertTrue(policyResolution >= 0);
|
||||
assertTrue(nativeRequirement > policyResolution);
|
||||
assertTrue(reachabilityGuard > nativeRequirement);
|
||||
assertTrue(reachabilityLookup > reachabilityGuard);
|
||||
}
|
||||
|
||||
private static IrisNativeStructureDecision decision(NativeStructureGenerationStatus status) {
|
||||
return new IrisNativeStructureDecision(
|
||||
status, 0, null, false, null, null);
|
||||
|
||||
-13
@@ -212,19 +212,6 @@ public class IrisPapiExpansionTest {
|
||||
assertTrue(expansion.persist());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void thePlaceholderPathNeverTouchesTheEngineOrAPluginStatic() throws Exception {
|
||||
for (String file : List.of("IrisPapiExpansion.java", "IrisPapiState.java", "IrisPapiWorldView.java")) {
|
||||
String source = Files.readString(Path.of("src/main/java/art/arcane/iris/core/link/" + file)).replace("\r\n", "\n");
|
||||
|
||||
assertFalse(file + " must not import the engine", source.contains("art.arcane.iris.engine."));
|
||||
assertFalse(file + " must not reach into the toolbelt", source.contains("IrisToolbelt"));
|
||||
assertFalse(file + " must not read the plugin static", source.contains("Iris.instance"));
|
||||
assertFalse(file + " must not derive metadata from the description", source.contains("getDescription()"));
|
||||
assertFalse(file + " must not take a lock", source.contains("synchronized"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void theReadmeDocumentsEveryPublishedKeyAndEveryRetiredOne() throws Exception {
|
||||
String readme = Files.readString(Path.of(System.getProperty("iris.readmeSource")));
|
||||
|
||||
-93
@@ -1,93 +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 BukkitEngineLifecycleContractTest {
|
||||
@Test
|
||||
public void closeFutureIsPublishedBeforeCloseWorkIsScheduled() throws IOException {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.bukkitChunkGeneratorSource")));
|
||||
String closeAsync = method(source, "public CompletableFuture<Void> closeAsync()");
|
||||
|
||||
assertBefore(closeAsync, "closeFuture.compareAndSet(null, future)", "withExclusiveControlFuture(");
|
||||
assertTrue(closeAsync.contains("while (!closeFuture.compareAndSet(null, future))"));
|
||||
assertTrue(closeAsync.contains("return existing;"));
|
||||
assertTrue(closeAsync.contains("operation.whenComplete("));
|
||||
assertFalse(closeAsync.contains("!existing.isDone()"));
|
||||
|
||||
String exclusiveFuture = method(source, "public CompletableFuture<Void> withExclusiveControlFuture(Runnable r)");
|
||||
assertTrue(exclusiveFuture.contains("J.a(() -> completeExclusiveControlFuture(loadLock, r, future))"));
|
||||
String exclusiveCompletion = method(source, "static void completeExclusiveControlFuture(");
|
||||
assertBefore(exclusiveCompletion, "activeGate.releaseExclusive();", "outward.complete(null);");
|
||||
assertBefore(exclusiveCompletion, "activeGate.releaseExclusive();", "outward.completeExceptionally(failure);");
|
||||
|
||||
String baseHeight = method(source, "public int getBaseHeight(");
|
||||
assertTrue(baseHeight.contains("currentEngine.acquireGenerationLease(\"bukkit_base_height\")"));
|
||||
assertTrue(baseHeight.contains("IrisContext.open(currentEngine, lease.sessionId(), null)"));
|
||||
assertTrue(baseHeight.contains("catch (GenerationSessionException | IOException e)"));
|
||||
|
||||
String generation = method(source, "public void generateNoise(");
|
||||
assertTrue(generation.contains("throw new IllegalStateException"));
|
||||
assertTrue(generation.contains("engine.acquireGenerationLease(\"bukkit_terrain_stage\")"));
|
||||
assertTrue(generation.contains("IrisContext.open(engine, lease.sessionId(), null)"));
|
||||
assertBefore(generation, "engine.acquireGenerationLease(\"bukkit_terrain_stage\")", "blocks.apply()");
|
||||
assertFalse(generation.contains("RED_GLAZED_TERRACOTTA"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void targetedPregeneratorShutdownChecksWorldIdentity() throws IOException {
|
||||
String jobSource = Files.readString(Path.of(System.getProperty("iris.pregeneratorJobSource")));
|
||||
String targetedShutdown = method(jobSource,
|
||||
"public static boolean shutdownInstanceForWorld(String worldIdentity)");
|
||||
|
||||
assertBefore(targetedShutdown, "inst.targetsWorldIdentity(worldIdentity)",
|
||||
"shutdownAndWait(inst, WORLD_SHUTDOWN_TIMEOUT_MILLIS)");
|
||||
|
||||
String waitedShutdown = method(jobSource,
|
||||
"private static boolean shutdownAndWait(PregeneratorJob inst, long timeoutMs)");
|
||||
assertBefore(waitedShutdown, "inst.requestStop()", "inst.worker.join(");
|
||||
assertBefore(waitedShutdown, "inst.worker.join(", "finishShutdown(inst, timeoutMs)");
|
||||
String finishedShutdown = method(jobSource,
|
||||
"private static boolean finishShutdown(PregeneratorJob inst, long timeoutMs)");
|
||||
assertBefore(finishedShutdown, "inst.worker.isAlive()", "instance.compareAndSet(inst, null)");
|
||||
|
||||
String hooksSource = Files.readString(Path.of(System.getProperty("iris.bukkitEnginePlatformHooksSource")));
|
||||
String hookShutdown = method(hooksSource, "public void shutdownPregenerator(Engine engine)");
|
||||
assertTrue(hookShutdown.contains("PregeneratorJob.shutdownInstanceForWorld(world.identity());"));
|
||||
assertFalse(hookShutdown.contains("PregeneratorJob.shutdownInstance();"));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
-72
@@ -6,9 +6,7 @@ import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -45,80 +43,10 @@ public class IrisEngineLifecycleContractTest {
|
||||
assertFalse(first.conflictsWith(distinct));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registrationRetryWaitsAsynchronouslyForClose() throws IOException {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.engineSvcSource")));
|
||||
String add = method(source, "private void add(World world)");
|
||||
String remove = method(source, "private boolean remove(World world, CompletionStage<Boolean> unloadBoundary)");
|
||||
String completeClose = method(source, "private void completeClose(");
|
||||
String retry = method(source, "private void retryRegistrationAfterClose(");
|
||||
String invokeClose = method(source, "private CompletableFuture<Void> invokeGeneratorClose()");
|
||||
|
||||
assertBefore(add, "findClosingGenerator(registrationIdentity)", "new Registered(");
|
||||
assertBefore(remove, "registered.close()", "reserveClose(registered)");
|
||||
assertBefore(remove, "reserveClose(registered)", "deferCloseUntilWorldUnload(");
|
||||
assertBefore(completeClose, "if (failure == null)", "closingGenerators.remove(closing)");
|
||||
assertBefore(completeClose, "closingGenerators.remove(closing)", "closing.completion().complete(null)");
|
||||
assertBefore(completeClose, "} else {", "closing.completion().completeExceptionally(failure)");
|
||||
assertTrue(retry.contains("completion.whenComplete("));
|
||||
assertTrue(retry.contains("J.s(() -> add(world), 1);"));
|
||||
assertBefore(retry, "if (failure != null)", "J.s(() -> add(world), 1);");
|
||||
assertFalse(retry.contains("completion.get("));
|
||||
assertFalse(retry.contains("completion.join("));
|
||||
assertTrue(invokeClose.contains("CompletableFuture.failedFuture("));
|
||||
assertTrue(invokeClose.contains("future.whenComplete("));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void worldUnloadDefersGeneratorCloseUntilTheRawBoundaryCompletesTrue() throws IOException {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.engineSvcSource")));
|
||||
String handler = method(source, "public void onWorldUnload(WorldUnloadEvent event)");
|
||||
String remove = method(source, "private boolean remove(World world, CompletionStage<Boolean> unloadBoundary)");
|
||||
String defer = method(source, "private void deferCloseUntilWorldUnload(");
|
||||
|
||||
assertBefore(handler, "WorldUnloadBoundaryRegistry.claim(", "remove(world, unloadBoundary)");
|
||||
assertBefore(remove, "registered.close()", "deferCloseUntilWorldUnload(");
|
||||
assertFalse(remove.contains("startClose(registered, closing)"));
|
||||
assertTrue(defer.contains("J.sfut(() -> startClose(registered, closing), 1)"));
|
||||
assertTrue(defer.contains("unloadBoundary.whenComplete("));
|
||||
String managedBoundary = defer.substring(defer.indexOf("unloadBoundary.whenComplete("));
|
||||
assertBefore(managedBoundary, "failure == null && Boolean.TRUE.equals(unloaded)",
|
||||
"startClose(registered, closing)");
|
||||
assertBefore(managedBoundary, "startClose(registered, closing)", "abandonClose(world, closing)");
|
||||
}
|
||||
|
||||
private static void assertMonitorUnloadHandler(Method method) {
|
||||
EventHandler eventHandler = method.getAnnotation(EventHandler.class);
|
||||
assertNotNull(eventHandler);
|
||||
assertEquals(EventPriority.MONITOR, eventHandler.priority());
|
||||
assertTrue(eventHandler.ignoreCancelled());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
-15
@@ -13,9 +13,6 @@ import art.arcane.iris.util.common.plugin.IrisService;
|
||||
import org.bukkit.World;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -61,18 +58,6 @@ public class IrisTerrainSVCTest {
|
||||
assertTrue(service.regionName(null, 0, 0).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void theDisplayNameAccessorsReadNamesRatherThanLoadKeys() throws IOException {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.terrainSvcSource")));
|
||||
|
||||
assertTrue("surfaceBiomeName must read the biome display name",
|
||||
source.contains("return name(engine.getSurfaceBiome(blockX, blockZ));"));
|
||||
assertTrue("the biome name helper must read getName()",
|
||||
source.contains("String name = biome == null ? null : biome.getName();"));
|
||||
assertTrue("regionName must read the region display name",
|
||||
source.contains("String name = region == null ? null : region.getName();"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void theServiceExposesDisplayNamesAlongsideLoadKeys() throws NoSuchMethodException {
|
||||
assertEquals(Optional.class,
|
||||
|
||||
Reference in new issue
Block a user