Merge branch 'fail-closed' into review

This commit is contained in:
Brian Neumann-Fopiano committed 2026-09-29 06:34:18 -04:00
commit a9f07ce5c6
25 files changed
+1670 -161

No files matched your search

@@ -53,6 +53,33 @@ public class BukkitWorldConfigurationTest {
)), bindings);
}
/**
* CraftServer only asks a plugin for a generator when bukkit.yml names it, so any world bound to Iris - a vanilla
* slot included - is one a disabled Iris would hand to the vanilla generator.
*/
@Test
public void detectsAnyWorldBoundToIrisIncludingVanillaSlots() throws Exception {
File overworld = temporaryFolder.newFile("iris-overworld.yml");
YamlConfiguration yaml = new YamlConfiguration();
yaml.set("worlds.world.generator", "iris:overworld");
yaml.set("worlds.world_nether.generator", "Other:generator");
yaml.save(overworld);
File bare = temporaryFolder.newFile("iris-bare.yml");
yaml = new YamlConfiguration();
yaml.set("worlds.world_the_end.generator", "Iris");
yaml.save(bare);
File other = temporaryFolder.newFile("other-only.yml");
yaml = new YamlConfiguration();
yaml.set("worlds.world.generator", "Irish:overworld");
yaml.set("worlds.world_nether.seed", 1337L);
yaml.save(other);
assertTrue(BukkitWorldConfiguration.configuresIrisGenerator(overworld));
assertTrue(BukkitWorldConfiguration.configuresIrisGenerator(bare));
assertFalse(BukkitWorldConfiguration.configuresIrisGenerator(other));
assertFalse(BukkitWorldConfiguration.configuresIrisGenerator(new File(temporaryFolder.getRoot(), "absent.yml")));
}
@Test
public void rejectsCustomIrisBindingWithoutSelectedDimension() throws Exception {
File configuration = temporaryFolder.newFile("missing-binding-dimension.yml");
@@ -0,0 +1,68 @@
package art.arcane.iris.world.safeguard;
import org.junit.Test;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CompletionException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class GenerationRefusalNoticeTest {
@Test
public void causesListEveryDistinctMessageOutermostFirst() {
IllegalStateException failure = new IllegalStateException("Iris generation history is unusable at /srv/moon.",
new IOException("Historical generated registry definition changed",
new IllegalArgumentException()));
assertEquals(List.of(
"Iris generation history is unusable at /srv/moon.",
"Historical generated registry definition changed",
"IllegalArgumentException"
), GenerationRefusalNotice.causes(failure));
}
@Test
public void wrappersThatOnlyRepeatTheirCauseAreSkipped() {
IllegalStateException root = new IllegalStateException("history drifted");
CompletionException wrapper = new CompletionException(root);
assertEquals(List.of("history drifted"), GenerationRefusalNotice.causes(wrapper));
assertEquals(List.of("history drifted"), GenerationRefusalNotice.causes(
new IllegalStateException("history drifted", root)));
}
@Test
public void aCyclicCauseChainTerminates() {
IllegalStateException first = new IllegalStateException("first");
IllegalStateException second = new IllegalStateException("second", first);
first.initCause(second);
assertEquals(List.of("first", "second"), GenerationRefusalNotice.causes(first));
}
@Test
public void summaryJoinsTheCausesOnOneLine() {
assertEquals("outer; inner", GenerationRefusalNotice.summary(
new IllegalStateException("outer", new IOException("inner"))));
}
@Test
public void noticeIsFramedAndNamesCauseChainAndConsequences() {
List<String> lines = GenerationRefusalNotice.compose(
"Iris refused to generate world 'moon' (iris:moon)",
List.of("outer", "inner"),
List.of("No chunks are written to it.", "Server startup stops before this world loads."));
assertEquals(lines.getFirst(), lines.getLast());
assertTrue(lines.getFirst(), lines.getFirst().chars().allMatch(character -> character == '='));
assertEquals(List.of(
"Iris refused to generate world 'moon' (iris:moon)",
"Cause: outer",
"Caused by: inner",
"No chunks are written to it.",
"Server startup stops before this world loads."
), lines.subList(1, lines.size() - 1));
}
}
@@ -10,8 +10,8 @@ import static org.junit.Assert.assertTrue;
/**
* A boot that ends in Danger Mode used to say so only in the banner. The server then ran on with every
* configured Iris world bound to a generator that throws on the first chunk, and nothing after the banner
* said that out loud. {@code refuseVanillaFallback} never covers this case because it only runs when enable
* itself fails.
* said that out loud. The failed-enable lock never covers this case because it only runs when enable itself
* fails.
*/
public class RuntimeLockNoticeTest {
@Test