mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-08-27 20:48:54 +00:00
d
This commit is contained in:
+143
@@ -0,0 +1,143 @@
|
||||
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("source.clearCache()"));
|
||||
}
|
||||
|
||||
@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("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 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"));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
+59
-1
@@ -141,7 +141,35 @@ public class ModdedLifecycleFailureContractTest {
|
||||
String source = source("ModdedEngineBootstrap.java");
|
||||
String stop = method(source, "public static void stop(");
|
||||
|
||||
assertEquals(1, occurrences(stop, "ModdedStartup.reset();"));
|
||||
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)");
|
||||
assertTrue(stop.contains("throw propagateStopFailure(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()"));
|
||||
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
|
||||
@@ -160,7 +188,37 @@ public class ModdedLifecycleFailureContractTest {
|
||||
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("LOGGER.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("generatorUnbound = true;"));
|
||||
assertTrue(remove.contains("rollbackRemoval(server, serverAccess, key, level, generator, generatorUnbound, 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("LOGGER.error("));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+24
@@ -48,7 +48,28 @@ public class ModdedServiceManagerTest {
|
||||
assertNull(manager.service(SecondService.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disableAttemptsEveryServiceInReverseOrderAndAggregatesFailures() {
|
||||
ModdedServiceManager manager = new ModdedServiceManager();
|
||||
RuntimeException firstFailure = new RuntimeException("first disable failed");
|
||||
RuntimeException secondFailure = new RuntimeException("second disable failed");
|
||||
FirstService first = manager.register(FirstService.class, new FirstService());
|
||||
first.disableFailure = firstFailure;
|
||||
SecondService second = manager.register(
|
||||
SecondService.class, new SecondService(null, secondFailure));
|
||||
|
||||
manager.enableAll();
|
||||
IllegalStateException thrown = assertThrows(IllegalStateException.class, manager::disableAll);
|
||||
|
||||
assertEquals(1, first.disableCount);
|
||||
assertEquals(1, second.disableCount);
|
||||
assertSame(secondFailure, thrown.getCause());
|
||||
assertEquals(1, secondFailure.getSuppressed().length);
|
||||
assertSame(firstFailure, secondFailure.getSuppressed()[0]);
|
||||
}
|
||||
|
||||
private static final class FirstService implements ModdedService {
|
||||
private RuntimeException disableFailure;
|
||||
private int enableCount;
|
||||
private int disableCount;
|
||||
|
||||
@@ -60,6 +81,9 @@ public class ModdedServiceManagerTest {
|
||||
@Override
|
||||
public void onDisable() {
|
||||
disableCount++;
|
||||
if (disableFailure != null) {
|
||||
throw disableFailure;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package art.arcane.iris.modded.service;
|
||||
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.core.component.DataComponentMap;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.server.Bootstrap;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class ModdedTreeFellerPresentationTest {
|
||||
@BeforeClass
|
||||
public static void bootstrapMinecraftRegistries() {
|
||||
SharedConstants.tryDetectVersion();
|
||||
Bootstrap.bootStrap();
|
||||
DataComponentMap stackComponents = DataComponentMap.builder()
|
||||
.set(DataComponents.MAX_STACK_SIZE, 64)
|
||||
.build();
|
||||
if (!Items.OAK_LOG.builtInRegistryHolder().areComponentsBound()) {
|
||||
Items.OAK_LOG.builtInRegistryHolder().bindComponents(stackComponents);
|
||||
}
|
||||
if (!Items.BIRCH_LOG.builtInRegistryHolder().areComponentsBound()) {
|
||||
Items.BIRCH_LOG.builtInRegistryHolder().bindComponents(stackComponents);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pulseSizingKeepsErosionReadableAndBounded() {
|
||||
assertEquals(4, ModdedTreeFellerPresentation.blocksPerPulse(1));
|
||||
assertEquals(4, ModdedTreeFellerPresentation.blocksPerPulse(240));
|
||||
assertEquals(10, ModdedTreeFellerPresentation.blocksPerPulse(600));
|
||||
assertEquals(64, ModdedTreeFellerPresentation.blocksPerPulse(100_000));
|
||||
assertEquals(4, ModdedTreeFellerPresentation.effectStride(64));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compatibleDropsConsolidateWithoutExceedingStackLimits() {
|
||||
List<ItemStack> drops = ModdedTreeFellerPresentation.consolidateDrops(List.of(
|
||||
new ItemStack(Items.OAK_LOG, 48),
|
||||
new ItemStack(Items.OAK_LOG, 48),
|
||||
new ItemStack(Items.BIRCH_LOG, 3)
|
||||
));
|
||||
|
||||
assertEquals(3, drops.size());
|
||||
assertEquals(64, drops.get(0).getCount());
|
||||
assertEquals(32, drops.get(1).getCount());
|
||||
assertEquals(3, drops.get(2).getCount());
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package art.arcane.iris.modded.service;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class ModdedTreeFellerServiceTest {
|
||||
@Test
|
||||
public void syntheticBreakProbeDepthIsNestedAndRestored() {
|
||||
assertFalse(ModdedTreeFellerService.isBreakProbe());
|
||||
|
||||
boolean accepted = ModdedTreeFellerService.runBreakProbe(() -> {
|
||||
assertTrue(ModdedTreeFellerService.isBreakProbe());
|
||||
return ModdedTreeFellerService.runBreakProbe(() -> {
|
||||
assertTrue(ModdedTreeFellerService.isBreakProbe());
|
||||
return true;
|
||||
});
|
||||
});
|
||||
|
||||
assertTrue(accepted);
|
||||
assertFalse(ModdedTreeFellerService.isBreakProbe());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void syntheticBreakProbeDepthIsRestoredAfterFailure() {
|
||||
try {
|
||||
ModdedTreeFellerService.runBreakProbe(() -> {
|
||||
throw new IllegalStateException("probe failure");
|
||||
});
|
||||
fail("Expected probe failure");
|
||||
} catch (IllegalStateException expected) {
|
||||
assertFalse(ModdedTreeFellerService.isBreakProbe());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user