mirror of
https://github.com/GTNewHorizons/ForgeMultipart.git
synced 2026-11-13 00:47:52 +00:00
test: characterize TFacePart
Freezes the trait defaults before the port: solid returns true for every
side including out-of-range values, and redstoneConductionMap returns 0.
Also freezes that TFacePart extends TSlottedPart, and that the $class
statics hold the defaults rather than dispatching, so an overriding part
gets its own values from a direct call but the trait values from the
bridge.
Both members are abstract on the reference interface, so a Java class
cannot inherit them today; the test part mirrors the forwarders Scala
emits instead, which keeps the file compiling before and after the port.
Adds a frozen Scala 2.11.5 consumer compiled against the reference dev jar
at a1bf3c8, whose forwarders call all three statics. OpenComputers,
ProjRed and ProjectBlue depend on them.
43 plain-JVM tests, all passing against the untouched Scala.
This commit is contained in:
1 parent
a1bf3c8c86
commit
d71a4b893d
5 files changed
+191
No files matched your search
@@ -0,0 +1,88 @@
|
||||
package codechicken.multipart;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class FacePartCharacterizationTest {
|
||||
|
||||
@Test
|
||||
void defaultsAreSolidOnEverySideAndConductNothing() {
|
||||
ForwardingPart part = new ForwardingPart();
|
||||
|
||||
for (int side = 0; side < 6; side++) {
|
||||
assertTrue(part.solid(side));
|
||||
}
|
||||
assertTrue(part.solid(-1));
|
||||
assertTrue(part.solid(99));
|
||||
assertEquals(0, part.redstoneConductionMap());
|
||||
}
|
||||
|
||||
@Test
|
||||
void deprecatedBridgeMatchesTheDefaults() {
|
||||
ForwardingPart part = new ForwardingPart();
|
||||
|
||||
for (int side = 0; side < 6; side++) {
|
||||
assertTrue(TFacePart$class.solid(part, side));
|
||||
}
|
||||
assertEquals(0, TFacePart$class.redstoneConductionMap(part));
|
||||
}
|
||||
|
||||
/** The bridge holds the trait defaults rather than dispatching, so an override does not change what it returns. */
|
||||
@Test
|
||||
void deprecatedBridgeReturnsTheTraitDefaultsEvenWhenOverridden() {
|
||||
OverridingPart part = new OverridingPart();
|
||||
|
||||
assertFalse(part.solid(0));
|
||||
assertEquals(0x10, part.redstoneConductionMap());
|
||||
assertTrue(TFacePart$class.solid(part, 0));
|
||||
assertEquals(0, TFacePart$class.redstoneConductionMap(part));
|
||||
}
|
||||
|
||||
@Test
|
||||
void facePartIsASlottedPart() {
|
||||
ForwardingPart part = new ForwardingPart();
|
||||
|
||||
assertTrue(part instanceof TSlottedPart);
|
||||
assertEquals(0x3f, part.getSlotMask());
|
||||
}
|
||||
|
||||
/** Mirrors the forwarders Scala emits for a class mixing in the trait without overriding either member. */
|
||||
private static class ForwardingPart extends TMultiPart implements TFacePart {
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "test:face";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlotMask() {
|
||||
return 0x3f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean solid(int side) {
|
||||
return TFacePart$class.solid(this, side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int redstoneConductionMap() {
|
||||
return TFacePart$class.redstoneConductionMap(this);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class OverridingPart extends ForwardingPart {
|
||||
|
||||
@Override
|
||||
public boolean solid(int side) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int redstoneConductionMap() {
|
||||
return 0x10;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package codechicken.multipart;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
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.Test;
|
||||
|
||||
/**
|
||||
* Loads a Scala class compiled against the reference dev jar, whose forwarders call all three TFacePart$class statics.
|
||||
* Recompiling the fixture against the port would hide the linkage failure this exists to catch.
|
||||
*/
|
||||
class TFacePartBinaryCompatibilityTest {
|
||||
|
||||
@Test
|
||||
void referenceScalaImplementorStillLinksThroughTheBridge() throws Exception {
|
||||
Class<?> fixtureClass = new FixtureClassLoader(TFacePart.class.getClassLoader()).define(loadFixture());
|
||||
Object fixture = fixtureClass.getDeclaredConstructor().newInstance();
|
||||
|
||||
assertTrue(fixture instanceof TFacePart);
|
||||
assertTrue(fixture instanceof TSlottedPart);
|
||||
assertTrue(fixture instanceof TMultiPart);
|
||||
TFacePart part = (TFacePart) fixture;
|
||||
|
||||
for (int side = 0; side < 6; side++) {
|
||||
assertTrue(part.solid(side));
|
||||
}
|
||||
assertEquals(0, part.redstoneConductionMap());
|
||||
assertEquals(0x3f, part.getSlotMask());
|
||||
}
|
||||
|
||||
private static byte[] loadFixture() {
|
||||
InputStream input = Objects.requireNonNull(
|
||||
TFacePartBinaryCompatibilityTest.class.getResourceAsStream("/compat/ReferenceScalaFacePart.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user