mirror of
https://github.com/GTNewHorizons/ForgeMultipart.git
synced 2026-11-13 00:47:52 +00:00
test: characterize TNormalOcclusion
Extends the occlusion characterization to the parts of the area the port
will touch: the NormalOcclusionTest$ singleton and its MODULE$ field, the
TNormalOcclusion$class bridge, the super accessor the bridge calls back
through, NormallyOccludedPart's single-box constructor that AE2 links
against, and its null getType.
The generated codechicken$multipart$TNormalOcclusion$$super$occlusionTest
accessor is ACC_SYNTHETIC on the reference interface, so javac neither
sees nor allows implementing it. It is reached by reflection here, and the
port has to expose it as an ordinary method for any new implementor to be
able to satisfy it.
Adds a frozen Scala 2.11.5 consumer compiled against the reference dev jar
at cd6420f. It mixes in the trait without overriding occlusionTest, so
invoking it covers the whole bridge round trip: forwarder, $class,
singleton, and the callback through the accessor. ForgeRelocationFMP,
OpenComputers and ProjRed all depend on that path.
38 plain-JVM tests, all passing against the untouched Scala.
This commit is contained in:
1 parent
cd6420f7f2
commit
75900d0602
5 files changed
+177
No files matched your search
@@ -1,10 +1,16 @@
|
||||
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.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -100,6 +106,60 @@ class NormalOcclusionCharacterizationTest {
|
||||
assertTrue(NormalOcclusionTest.apply(origin, barePart));
|
||||
}
|
||||
|
||||
@Test
|
||||
void singletonAndStaticForwardersAgree() {
|
||||
Traversable<Cuboid6> left = scalaBoxes(box(0, 0, 0, 0.5, 1, 1));
|
||||
Traversable<Cuboid6> fits = scalaBoxes(box(0.5, 0, 0, 1, 1, 1));
|
||||
Traversable<Cuboid6> overlaps = scalaBoxes(box(0.25, 0, 0, 1, 1, 1));
|
||||
|
||||
assertTrue(NormalOcclusionTest$.MODULE$.apply(left, fits));
|
||||
assertFalse(NormalOcclusionTest$.MODULE$.apply(left, overlaps));
|
||||
|
||||
NormallyOccludedPart part = new NormallyOccludedPart(box(0, 0, 0, 0.5, 1, 1));
|
||||
NormallyOccludedPart neighbour = new NormallyOccludedPart(box(0.5, 0, 0, 1, 1, 1));
|
||||
assertEquals(NormalOcclusionTest.apply(part, neighbour), NormalOcclusionTest$.MODULE$.apply(part, neighbour));
|
||||
}
|
||||
|
||||
@Test
|
||||
void bridgeCombinesTheBoxTestWithTheSuperChain() {
|
||||
NormallyOccludedPart part = new NormallyOccludedPart(box(0, 0, 0, 0.5, 1, 1));
|
||||
TMultiPart fits = new NormallyOccludedPart(box(0.5, 0, 0, 1, 1, 1));
|
||||
TMultiPart overlaps = new NormallyOccludedPart(box(0.25, 0, 0, 1, 1, 1));
|
||||
|
||||
assertTrue(TNormalOcclusion$class.occlusionTest(part, fits));
|
||||
assertFalse(TNormalOcclusion$class.occlusionTest(part, overlaps));
|
||||
}
|
||||
|
||||
/**
|
||||
* The super accessor is ACC_SYNTHETIC in the reference, so javac hides it and only reflection can reach it. The
|
||||
* bridge calls it through invokeinterface, so its name and descriptor are part of the supported ABI.
|
||||
*/
|
||||
@Test
|
||||
void superAccessorExistsAndChainsToTheTMultiPartDefault() throws Exception {
|
||||
NormallyOccludedPart part = new NormallyOccludedPart(box(0, 0, 0, 0.5, 1, 1));
|
||||
Method accessor = TNormalOcclusion.class
|
||||
.getMethod("codechicken$multipart$TNormalOcclusion$$super$occlusionTest", TMultiPart.class);
|
||||
|
||||
assertEquals(Boolean.TRUE, accessor.invoke(part, new NormallyOccludedPart(box(0.25, 0, 0, 1, 1, 1))));
|
||||
assertNull(part.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
void singleBoxConstructorMatchesTheIterableConstructor() {
|
||||
Cuboid6 bound = box(0, 0, 0, 0.5, 1, 1);
|
||||
NormallyOccludedPart single = new NormallyOccludedPart(bound);
|
||||
TMultiPart overlaps = new NormallyOccludedPart(box(0.25, 0, 0, 1, 1, 1));
|
||||
|
||||
List<Cuboid6> boxes = new ArrayList<>();
|
||||
for (Cuboid6 box : single.getOcclusionBoxes()) {
|
||||
boxes.add(box);
|
||||
}
|
||||
|
||||
assertEquals(1, boxes.size());
|
||||
assertSame(bound, boxes.get(0));
|
||||
assertFalse(single.occlusionTest(overlaps));
|
||||
}
|
||||
|
||||
private static boolean compatible(Cuboid6 first, Cuboid6 second) {
|
||||
return NormalOcclusionTest.apply(scalaBoxes(first), scalaBoxes(second));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package codechicken.multipart;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
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;
|
||||
|
||||
import codechicken.lib.vec.Cuboid6;
|
||||
|
||||
/**
|
||||
* Loads a Scala class compiled against the reference dev jar. Its occlusionTest forwards to TNormalOcclusion$class,
|
||||
* which in turn calls back through the generated super accessor, so this covers the whole bridge contract.
|
||||
*/
|
||||
class TNormalOcclusionBinaryCompatibilityTest {
|
||||
|
||||
@Test
|
||||
void referenceScalaImplementorStillLinksThroughTheBridge() throws Exception {
|
||||
Class<?> fixtureClass = new FixtureClassLoader(TNormalOcclusion.class.getClassLoader()).define(loadFixture());
|
||||
Object fixture = fixtureClass.getDeclaredConstructor().newInstance();
|
||||
|
||||
assertTrue(fixture instanceof TNormalOcclusion);
|
||||
assertTrue(fixture instanceof JNormalOcclusion);
|
||||
TNormalOcclusion part = (TNormalOcclusion) fixture;
|
||||
|
||||
// The fixture occupies x 0.0 to 0.5, so a touching neighbour fits and an overlapping one does not.
|
||||
assertTrue(part.occlusionTest(new NormallyOccludedPart(new Cuboid6(0.5, 0, 0, 1, 1, 1))));
|
||||
assertFalse(part.occlusionTest(new NormallyOccludedPart(new Cuboid6(0.25, 0, 0, 1, 1, 1))));
|
||||
}
|
||||
|
||||
private static byte[] loadFixture() {
|
||||
InputStream input = Objects.requireNonNull(
|
||||
TNormalOcclusionBinaryCompatibilityTest.class
|
||||
.getResourceAsStream("/compat/ReferenceScalaNormalOcclusion.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