mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-12 03:24:14 +00:00
Cover untested contract surfaces
- Add a test source set to spi with bind, service registry and platform value contracts - Prove the DataType probe contract, the ExternalDataProvider defaults and the string-only provider namespace claims - Prove Identifier parsing and rendering - Cover the data version, primitive and vector director handlers - Cover the vanilla export identifier, block state, orientation, request and settings values - Cover the structure adoption limits, diagnostics and result invariants - Cover the pregen mantle backpressure, heap reclaim urgency, empty cache, listener defaults and diagnostic descriptions
This commit is contained in:
@@ -11,6 +11,10 @@ java {
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation('junit:junit:4.13.2')
|
||||
}
|
||||
|
||||
tasks.named('jar', Jar).configure {
|
||||
archiveBaseName.set('iris-spi')
|
||||
}
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
package art.arcane.iris.spi;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class IrisPlatformsBindContractTest {
|
||||
@Before
|
||||
public void requireUnbound() {
|
||||
IrisPlatforms.unbind();
|
||||
}
|
||||
|
||||
@After
|
||||
public void releaseBinding() {
|
||||
IrisPlatforms.unbind();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unboundLookupsReportAbsenceInsteadOfImprovising() {
|
||||
assertFalse(IrisPlatforms.isBound());
|
||||
assertNull(IrisPlatforms.getOrNull());
|
||||
|
||||
IllegalStateException failure = assertThrows(IllegalStateException.class, IrisPlatforms::get);
|
||||
|
||||
assertTrue(failure.getMessage(), failure.getMessage().contains("No Iris platform is bound"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindingIsVisibleThroughEveryAccessor() {
|
||||
IrisPlatform platform = new StubPlatform();
|
||||
|
||||
IrisPlatforms.bind(platform);
|
||||
|
||||
assertTrue(IrisPlatforms.isBound());
|
||||
assertSame(platform, IrisPlatforms.get());
|
||||
assertSame(platform, IrisPlatforms.getOrNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rebindingTheSameInstanceIsAccepted() {
|
||||
IrisPlatform platform = new StubPlatform();
|
||||
|
||||
IrisPlatforms.bind(platform);
|
||||
IrisPlatforms.bind(platform);
|
||||
|
||||
assertSame(platform, IrisPlatforms.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aSecondPlatformCannotDisplaceTheBoundOne() {
|
||||
IrisPlatform first = new StubPlatform();
|
||||
IrisPlatforms.bind(first);
|
||||
|
||||
IllegalStateException failure = assertThrows(
|
||||
IllegalStateException.class, () -> IrisPlatforms.bind(new StubPlatform()));
|
||||
|
||||
assertTrue(failure.getMessage(), failure.getMessage().contains("already bound"));
|
||||
assertSame(first, IrisPlatforms.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unbindIsIdempotentAndClearsTheBinding() {
|
||||
IrisPlatforms.bind(new StubPlatform());
|
||||
|
||||
IrisPlatforms.unbind();
|
||||
IrisPlatforms.unbind();
|
||||
|
||||
assertFalse(IrisPlatforms.isBound());
|
||||
assertNull(IrisPlatforms.getOrNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unbindingClearsTheOnceKeysSoLaterRunsWarnAgain() {
|
||||
IrisPlatforms.bind(new StubPlatform());
|
||||
assertTrue(IrisLogging.warnOnce("spi-contract-once", "first"));
|
||||
assertFalse(IrisLogging.warnOnce("spi-contract-once", "second"));
|
||||
|
||||
IrisPlatforms.unbind();
|
||||
|
||||
assertTrue(IrisLogging.warnOnce("spi-contract-once", "third"));
|
||||
}
|
||||
|
||||
private static final class StubPlatform implements IrisPlatform {
|
||||
@Override
|
||||
public String platformName() {
|
||||
return "stub";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String minecraftVersion() {
|
||||
return "26.2";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformRegistries registries() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformScheduler scheduler() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformStructureHooks structureHooks() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformBiomeWriter biomeWriter() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File dataFolder() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File dataFile(String... path) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File pluginJar() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int irisVersionNumber() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int minecraftVersionNumber() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callEvent(Object event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchConsoleCommand(String command) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean spawnEntity(PlatformWorld world, String entityKey, double x, double y, double z) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(LogLevel level, String message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void msg(String message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportError(Throwable error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package art.arcane.iris.spi;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class IrisServicesRegistryContractTest {
|
||||
@Before
|
||||
public void requireEmptyRegistry() {
|
||||
IrisServices.clear();
|
||||
}
|
||||
|
||||
@After
|
||||
public void releaseRegistry() {
|
||||
IrisServices.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registeredServicesResolveThroughBothAccessors() {
|
||||
Greeter greeter = new Greeter();
|
||||
|
||||
IrisServices.register(Greeter.class, greeter);
|
||||
|
||||
assertSame(greeter, IrisServices.get(Greeter.class));
|
||||
assertSame(greeter, IrisServices.getOrNull(Greeter.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void anAbsentServiceNamesItselfInTheFailure() {
|
||||
assertNull(IrisServices.getOrNull(Greeter.class));
|
||||
|
||||
IllegalStateException failure = assertThrows(IllegalStateException.class, () -> IrisServices.get(Greeter.class));
|
||||
|
||||
assertTrue(failure.getMessage(), failure.getMessage().contains(Greeter.class.getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reregisteringATypeReplacesThePreviousImplementation() {
|
||||
Greeter first = new Greeter();
|
||||
Greeter second = new Greeter();
|
||||
|
||||
IrisServices.register(Greeter.class, first);
|
||||
IrisServices.register(Greeter.class, second);
|
||||
|
||||
assertSame(second, IrisServices.get(Greeter.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removingAServiceLeavesTheRegistryUsable() {
|
||||
IrisServices.register(Greeter.class, new Greeter());
|
||||
|
||||
IrisServices.remove(Greeter.class);
|
||||
IrisServices.remove(Greeter.class);
|
||||
|
||||
assertNull(IrisServices.getOrNull(Greeter.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearDropsEveryRegistration() {
|
||||
IrisServices.register(Greeter.class, new Greeter());
|
||||
IrisServices.register(Counter.class, new Counter());
|
||||
|
||||
IrisServices.clear();
|
||||
|
||||
assertNull(IrisServices.getOrNull(Greeter.class));
|
||||
assertNull(IrisServices.getOrNull(Counter.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aMismatchedImplementationIsRejectedBeforeItEntersTheRegistry() {
|
||||
assertThrows(ClassCastException.class, () -> IrisServices.register(Greeter.class, new Counter()));
|
||||
|
||||
assertNull(IrisServices.getOrNull(Greeter.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aNullImplementationIsRejectedBeforeItEntersTheRegistry() {
|
||||
assertThrows(NullPointerException.class, () -> IrisServices.register(Greeter.class, null));
|
||||
|
||||
assertNull(IrisServices.getOrNull(Greeter.class));
|
||||
}
|
||||
|
||||
private static final class Greeter {
|
||||
}
|
||||
|
||||
private static final class Counter {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
package art.arcane.iris.spi;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class PlatformValueContractTest {
|
||||
private static final String FINGERPRINT = "a".repeat(64);
|
||||
|
||||
@Test
|
||||
public void jigsawMetadataAcceptsTheWholeDocumentedRange() {
|
||||
PlatformStructureHooks.JigsawSourceMetadata smallest =
|
||||
new PlatformStructureHooks.JigsawSourceMetadata(1, 0, 0);
|
||||
PlatformStructureHooks.JigsawSourceMetadata largest =
|
||||
new PlatformStructureHooks.JigsawSourceMetadata(128, 7, 96);
|
||||
|
||||
assertEquals(1, smallest.maxDistanceHorizontal());
|
||||
assertEquals(128, largest.maxDistanceHorizontal());
|
||||
assertEquals(7, largest.referenceExpansion());
|
||||
assertEquals(96, largest.maxStartElementHorizontalSpan());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jigsawMetadataDefaultsTheStartElementSpanToZero() {
|
||||
PlatformStructureHooks.JigsawSourceMetadata metadata =
|
||||
new PlatformStructureHooks.JigsawSourceMetadata(64, 3);
|
||||
|
||||
assertEquals(0, metadata.maxStartElementHorizontalSpan());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jigsawMetadataRejectsOutOfRangeGeometry() {
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new PlatformStructureHooks.JigsawSourceMetadata(0, 0, 0));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new PlatformStructureHooks.JigsawSourceMetadata(129, 0, 0));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new PlatformStructureHooks.JigsawSourceMetadata(64, -1, 0));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new PlatformStructureHooks.JigsawSourceMetadata(64, 0, -1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unimplementedStructureHookDefaultsRefuseInsteadOfReturningNothing() {
|
||||
PlatformStructureHooks hooks = new MinimalStructureHooks();
|
||||
|
||||
assertEquals(List.of(), hooks.jigsawStructureKeys());
|
||||
assertEquals(List.of(), hooks.templatePoolKeys());
|
||||
assertThrows(UnsupportedOperationException.class, () -> hooks.jigsawSourceMetadata("iris:village"));
|
||||
assertThrows(UnsupportedOperationException.class, () -> hooks.templatePoolHorizontalSpan("iris:pool"));
|
||||
assertThrows(UnsupportedOperationException.class,
|
||||
() -> hooks.jigsawStartPoolHorizontalSpan("iris:village", "iris:pool"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void definitionFactoriesCarryTheirEncoding() {
|
||||
PlatformGenerationRegistry.Definition json = PlatformGenerationRegistry.Definition.exactJson("{}");
|
||||
PlatformGenerationRegistry.Definition identity =
|
||||
PlatformGenerationRegistry.Definition.conservativeIdentity("abc");
|
||||
|
||||
assertEquals(PlatformGenerationRegistry.Encoding.JSON, json.encoding());
|
||||
assertEquals("{}", json.value());
|
||||
assertEquals(PlatformGenerationRegistry.Encoding.CONSERVATIVE_IDENTITY, identity.encoding());
|
||||
assertEquals("abc", identity.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resourceIdentityTrimsItsPartsIntoAStableKey() {
|
||||
PlatformGenerationRegistry.Definition definition =
|
||||
PlatformGenerationRegistry.Definition.resourceIdentity(" worldgen/biome ", " iris:plains ");
|
||||
|
||||
assertEquals(PlatformGenerationRegistry.Encoding.CONSERVATIVE_IDENTITY, definition.encoding());
|
||||
assertEquals("registry-resource-key-v1|worldgen/biome|iris:plains", definition.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void definitionsRejectMissingAndBlankValues() {
|
||||
assertThrows(NullPointerException.class,
|
||||
() -> new PlatformGenerationRegistry.Definition(null, "value"));
|
||||
assertThrows(NullPointerException.class,
|
||||
() -> new PlatformGenerationRegistry.Definition(PlatformGenerationRegistry.Encoding.JSON, null));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new PlatformGenerationRegistry.Definition(PlatformGenerationRegistry.Encoding.JSON, " "));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> PlatformGenerationRegistry.Definition.resourceIdentity(" ", "iris:plains"));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> PlatformGenerationRegistry.Definition.resourceIdentity("worldgen/biome", " "));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customBiomeResourceKeysAreContentAddressed() {
|
||||
assertEquals("iris:biomes/" + FINGERPRINT,
|
||||
PlatformGenerationRegistry.contentAddressedCustomBiomeResourceKey(FINGERPRINT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customBiomeResourceKeysRejectAnythingButALowercaseSha256() {
|
||||
assertThrows(NullPointerException.class,
|
||||
() -> PlatformGenerationRegistry.contentAddressedCustomBiomeResourceKey(null));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> PlatformGenerationRegistry.contentAddressedCustomBiomeResourceKey(FINGERPRINT.toUpperCase()));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> PlatformGenerationRegistry.contentAddressedCustomBiomeResourceKey("a".repeat(63)));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> PlatformGenerationRegistry.contentAddressedCustomBiomeResourceKey("z".repeat(64)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void blockPropertiesReportWhetherTheyCarryANumericRange() {
|
||||
PlatformNumericRange range = new PlatformNumericRange(0D, 15D, false, true);
|
||||
PlatformBlockProperty numeric =
|
||||
new PlatformBlockProperty("level", "integer", 0, List.of(0, 15), range);
|
||||
PlatformBlockProperty enumerated =
|
||||
new PlatformBlockProperty("axis", "string", "y", List.of("x", "y", "z"), null);
|
||||
|
||||
assertTrue(numeric.hasNumericRange());
|
||||
assertEquals(range, numeric.numericRange());
|
||||
assertEquals(0D, range.minimum(), 0D);
|
||||
assertEquals(15D, range.maximum(), 0D);
|
||||
assertFalse(range.exclusiveMinimum());
|
||||
assertTrue(range.exclusiveMaximum());
|
||||
assertFalse(enumerated.hasNumericRange());
|
||||
assertEquals(List.of("x", "y", "z"), enumerated.allowedValues());
|
||||
}
|
||||
|
||||
private static final class MinimalStructureHooks implements PlatformStructureHooks {
|
||||
@Override
|
||||
public List<String> structureKeys() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> structureSetKeys() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> structureBiomeKeys(String structureKey) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> objectFeatureKeys() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> reachableStructureKeys(PlatformWorld world) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> possibleBiomeKeys(PlatformWorld world) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean placeFeature(PlatformWorld world, int x, int y, int z, String featureKey, long seed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] placeStructure(PlatformWorld world, int chunkX, int chunkZ, String structureKey, long seed, int maxSpan) {
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsStructurePlacement() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user