package com.oracle.truffle.llvm.tests.interop;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;
import com.oracle.truffle.api.utilities.TriState;
import com.oracle.truffle.llvm.tests.interop.values.NativeValue;
import com.oracle.truffle.tck.TruffleRunner;
import org.graalvm.polyglot.Value;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(TruffleRunner.class)
public class PointerCompareTest extends InteropTestBase {
static Value testPointerAdd;
@BeforeClass
public static void loadLibrary() {
Value testLibrary = loadTestBitcodeValue("pointerArithmetic.c");
testPointerAdd = testLibrary.getMember("test_pointer_add");
}
@ExportLibrary(InteropLibrary.class)
static class NotComparableObject implements TruffleObject {
@ExportMessage
void toNative() {
Assert.fail("unexpected toNative");
}
}
@ExportLibrary(InteropLibrary.class)
static class ComparableObject implements TruffleObject {
final int identity;
ComparableObject(int identity) {
this.identity = identity;
}
@ExportMessage
static class IsIdenticalOrUndefined {
@Specialization
static TriState doCompare(ComparableObject self, ComparableObject other) {
return TriState.valueOf(self.identity == other.identity);
}
@Fallback
static TriState doOther(@SuppressWarnings("unused") ComparableObject self, Object other) {
assert !(other instanceof ComparableObject);
return TriState.UNDEFINED;
}
}
@ExportMessage
int identityHashCode() {
return identity;
}
@ExportMessage
void toNative() {
Assert.fail("unexpected toNative");
}
}
@ExportLibrary(value = InteropLibrary.class, delegateTo = "delegate")
static class WrappedObject implements TruffleObject {
final Object delegate;
WrappedObject(Object delegate) {
this.delegate = delegate;
}
}
private static Object ptr(long v) {
return new NativeValue(v);
}
@Test
public void testSameObject() {
NotComparableObject obj = new NotComparableObject();
Value ptr1 = testPointerAdd.execute(obj, ptr(42));
Value ptr2 = testPointerAdd.execute(obj, ptr(42));
Assert.assertTrue("equals", ptr1.equals(ptr2));
}
@Test
public void testSameObjectDifferentOffset() {
NotComparableObject obj = new NotComparableObject();
Value ptr1 = testPointerAdd.execute(obj, ptr(42));
Value ptr2 = testPointerAdd.execute(obj, ptr(38));
Assert.assertFalse("!equals", ptr1.equals(ptr2));
}
@Test
public void testDifferentObject() {
Value ptr1 = testPointerAdd.execute(new NotComparableObject(), ptr(42));
Value ptr2 = testPointerAdd.execute(new NotComparableObject(), ptr(42));
Assert.assertFalse("!equals", ptr1.equals(ptr2));
}
@Test
public void testIdenticalObject() {
Value ptr1 = testPointerAdd.execute(new ComparableObject(1), ptr(42));
Value ptr2 = testPointerAdd.execute(new ComparableObject(1), ptr(42));
Assert.assertTrue("equals", ptr1.equals(ptr2));
}
@Test
public void testSameAndIdenticalObject() {
ComparableObject obj = new ComparableObject(2);
Value ptr1 = testPointerAdd.execute(obj, ptr(42));
Value ptr2 = testPointerAdd.execute(obj, ptr(42));
Assert.assertTrue("equals", ptr1.equals(ptr2));
}
@Test
public void testNotIdenticalObject() {
Value ptr1 = testPointerAdd.execute(new ComparableObject(3), ptr(42));
Value ptr2 = testPointerAdd.execute(new ComparableObject(4), ptr(42));
Assert.assertFalse("!equals", ptr1.equals(ptr2));
}
@Test
public void testDifferentTypes1() {
Value ptr1 = testPointerAdd.execute(new NotComparableObject(), ptr(42));
Value ptr2 = testPointerAdd.execute(new ComparableObject(5), ptr(42));
Assert.assertFalse("!equals", ptr1.equals(ptr2));
}
@Test
public void testDifferentTypes2() {
Value ptr1 = testPointerAdd.execute(new ComparableObject(6), ptr(42));
Value ptr2 = testPointerAdd.execute(new NotComparableObject(), ptr(42));
Assert.assertFalse("!equals", ptr1.equals(ptr2));
}
@Test
public void testWrappedObject1() {
Value ptr1 = testPointerAdd.execute(new WrappedObject(new ComparableObject(7)), ptr(42));
Value ptr2 = testPointerAdd.execute(new ComparableObject(7), ptr(42));
Assert.assertTrue("equals", ptr1.equals(ptr2));
}
@Test
public void testWrappedObject2() {
Value ptr1 = testPointerAdd.execute(new ComparableObject(8), ptr(42));
Value ptr2 = testPointerAdd.execute(new WrappedObject(new ComparableObject(8)), ptr(42));
Assert.assertTrue("equals", ptr1.equals(ptr2));
}
@Test
public void testWrappedObject3() {
Value ptr1 = testPointerAdd.execute(new WrappedObject(new ComparableObject(9)), ptr(42));
Value ptr2 = testPointerAdd.execute(new WrappedObject(new ComparableObject(9)), ptr(42));
Assert.assertTrue("equals", ptr1.equals(ptr2));
}
}