mirror of
https://github.com/GTNewHorizons/ForgeMultipart.git
synced 2026-11-13 00:47:52 +00:00
Freezes the registry lifecycle before the port: setupIDMap sorts the type
map by name into the id array, ids are the index into it, materialID and
materialName round trip, remapName resolves on both getMaterial(String)
and materialID, getMissingId points at the registered placeholder rather
than falling back to zero, ids round trip through the shared IDWriter, and
a highlight renderer that claims the highlight short-circuits the default
client renderer.
Also freezes the two members IMicroMaterial supplies. A Java class cannot
inherit them today, so they are observed through MissingMicroMaterial,
which overrides only isTransparent and loadIcons.
Two limits are deliberate and recorded in the test. The registry is global
mutable state, so both test classes guard their registrations and assert
only relative facts. The error paths are not covered at all: they call the
microblock logger, which is null until MicroblockProxy.preInit runs.
Adds a frozen Scala 2.11.5 consumer compiled against the reference dev jar
at 52ff8ff, reading MODULE$ and the raw scala.Tuple2 array.
73 plain-JVM tests, all passing against the untouched Scala.
76 lines
3.1 KiB
Java
76 lines
3.1 KiB
Java
package codechicken.microblock;
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
import static org.junit.jupiter.api.Assertions.assertSame;
|
|
|
|
import java.io.InputStream;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.Base64;
|
|
import java.util.Objects;
|
|
import java.util.Scanner;
|
|
|
|
import org.junit.jupiter.api.BeforeAll;
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
import codechicken.microblock.MicroMaterialRegistry.IMicroMaterial;
|
|
|
|
/**
|
|
* Loads a Scala class compiled against the reference dev jar. It reads MicroMaterialRegistry$.MODULE$ and calls the
|
|
* instance methods ProjRed links against, plus the scala.Tuple2 array getIdMap that extrautilities links against.
|
|
*
|
|
* Registration is global, so this registers its own uniquely named material and only asserts facts about it.
|
|
*/
|
|
class MicroMaterialRegistryBinaryCompatibilityTest {
|
|
|
|
private static final String NAME = "test:binarycompat";
|
|
|
|
@BeforeAll
|
|
static void register() {
|
|
// The other test class may already have registered the placeholder; re-registering would hit the error path.
|
|
if (MicroMaterialRegistry.getMaterial(MissingMicroMaterial.key()) == null) {
|
|
MicroMaterialRegistry.registerMaterial(MissingMicroMaterial$.MODULE$, MissingMicroMaterial.key());
|
|
}
|
|
if (MicroMaterialRegistry.getMaterial(NAME) == null) {
|
|
MicroMaterialRegistry.registerMaterial(MissingMicroMaterial$.MODULE$, NAME);
|
|
}
|
|
MicroMaterialRegistry$.MODULE$.setupIDMap();
|
|
}
|
|
|
|
@Test
|
|
void referenceScalaConsumerStillLinksAgainstTheSingletonAndIdMap() throws Exception {
|
|
Class<?> fixtureClass = new FixtureClassLoader(MicroMaterialRegistry.class.getClassLoader())
|
|
.define(loadFixture());
|
|
Object fixture = fixtureClass.getDeclaredConstructor().newInstance();
|
|
|
|
int id = (Integer) fixtureClass.getMethod("idOf", String.class).invoke(fixture, NAME);
|
|
assertEquals(NAME, fixtureClass.getMethod("nameOf", int.class).invoke(fixture, id));
|
|
|
|
Object material = fixtureClass.getMethod("materialAt", int.class).invoke(fixture, id);
|
|
assertSame(MicroMaterialRegistry.getMaterial(id), material);
|
|
assertSame(MicroMaterialRegistry.getMaterial(id), (IMicroMaterial) material);
|
|
|
|
// Reads the raw scala.Tuple2 array rather than the accessors.
|
|
assertEquals(NAME + "=true", fixtureClass.getMethod("idMapEntry", int.class).invoke(fixture, id));
|
|
}
|
|
|
|
private static byte[] loadFixture() {
|
|
InputStream input = Objects.requireNonNull(
|
|
MicroMaterialRegistryBinaryCompatibilityTest.class
|
|
.getResourceAsStream("/compat/ReferenceScalaMicroMaterialConsumer.class.b64"));
|
|
try (Scanner scanner = new Scanner(input, StandardCharsets.US_ASCII.name()).useDelimiter("\\A")) {
|
|
return Base64.getMimeDecoder().decode(scanner.next());
|
|
}
|
|
}
|
|
|
|
private static final class FixtureClassLoader extends ClassLoader {
|
|
|
|
private FixtureClassLoader(ClassLoader parent) {
|
|
super(parent);
|
|
}
|
|
|
|
private Class<?> define(byte[] bytecode) {
|
|
return defineClass(null, bytecode, 0, bytecode.length);
|
|
}
|
|
}
|
|
}
|