package com.oracle.truffle.llvm.tests.interop;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import java.math.BigInteger;
import java.util.HashMap;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.TruffleOptions;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.llvm.runtime.except.LLVMPolyglotException;
import com.oracle.truffle.llvm.tests.interop.values.ArrayObject;
import com.oracle.truffle.llvm.tests.interop.values.BoxedIntValue;
import com.oracle.truffle.llvm.tests.interop.values.NullValue;
import com.oracle.truffle.llvm.tests.interop.values.StructObject;
import com.oracle.truffle.llvm.tests.interop.values.TestConstructor;
import com.oracle.truffle.tck.TruffleRunner;
import com.oracle.truffle.tck.TruffleRunner.Inject;
@RunWith(TruffleRunner.class)
public class PolyglotBuiltinTest extends InteropTestBase {
private static Object testLibrary;
@BeforeClass
public static void loadTestBitcode() {
testLibrary = loadTestBitcodeInternal("polyglotBuiltinTest.c");
}
public static class TestNewNode extends SulongTestNode {
public TestNewNode() {
super(testLibrary, "test_new");
}
}
@Test
public void testNew(@Inject(TestNewNode.class) CallTarget testNew) {
Object ret = testNew.call(new TestConstructor(1, args -> {
try {
int arg = InteropLibrary.getFactory().getUncached().asInt(args[0]);
return new BoxedIntValue(arg);
} catch (UnsupportedMessageException ex) {
throw new AssertionError(ex);
}
}));
Assert.assertThat(ret, is(instanceOf(BoxedIntValue.class)));
BoxedIntValue value = (BoxedIntValue) ret;
Assert.assertEquals(42, value.asInt());
}
public static class TestRemoveMemberNode extends SulongTestNode {
public TestRemoveMemberNode() {
super(testLibrary, "test_remove_member");
}
}
@Test
public void testRemoveMember(@Inject(TestRemoveMemberNode.class) CallTarget testRemoveMember) {
HashMap<String, Object> map = new HashMap<>();
map.put("test", new NullValue());
Object ret = testRemoveMember.call(new StructObject(map));
Assert.assertEquals("ret", true, ret);
Assert.assertFalse("containsKey(test)", map.containsKey("test"));
}
public static class TestRemoveArrayElementNode extends SulongTestNode {
public TestRemoveArrayElementNode() {
super(testLibrary, "test_remove_array_element");
}
}
@Test
public void testRemoveIndex(@Inject(TestRemoveArrayElementNode.class) CallTarget testRemoveArrayElement) {
Object[] arr = new Object[5];
Object ret = testRemoveArrayElement.call(new ArrayObject(arr));
Assert.assertEquals("ret", true, ret);
Assert.assertEquals("arr[3]", "<removed>", arr[3]);
}
public static class TestHasMemberNode extends SulongTestNode {
public TestHasMemberNode() {
super(testLibrary, "test_has_member");
}
}
@Test
public void testHasMemberExisting(@Inject(TestHasMemberNode.class) CallTarget testHasMember) {
HashMap<String, Object> map = new HashMap<>();
map.put("test", new NullValue());
Object ret = testHasMember.call(new StructObject(map));
Assert.assertEquals("ret", true, ret);
}
@Test
public void testHasMemberNotExisting(@Inject(TestHasMemberNode.class) CallTarget testHasMember) {
HashMap<String, Object> map = new HashMap<>();
Object ret = testHasMember.call(new StructObject(map));
Assert.assertEquals("ret", false, ret);
}
@Test
public void testHasMemberNotAnObject(@Inject(TestHasMemberNode.class) CallTarget testHasMember) {
Object ret = testHasMember.call(new NullValue());
Assert.assertEquals("ret", false, ret);
}
public static class TestHostInteropNode extends SulongTestNode {
public TestHostInteropNode() {
super(testLibrary, "test_host_interop");
}
}
@Test
public void testHostInterop(@Inject(TestHostInteropNode.class) CallTarget testHostInterop) {
Assume.assumeFalse("skipping host interop test in native mode", TruffleOptions.AOT);
Object ret = testHostInterop.call();
Assert.assertTrue("isHostObject", runWithPolyglot.getTruffleTestEnv().isHostObject(ret));
Assert.assertSame("ret", BigInteger.class, runWithPolyglot.getTruffleTestEnv().asHostObject(ret));
}
public static class TestEvalNoLang extends SulongTestNode {
public TestEvalNoLang() {
super(testLibrary, "test_eval_no_lang");
}
}
@Test
public void testHasEvalNoLang(@Inject(TestEvalNoLang.class) CallTarget testEvalNolang) {
try {
testEvalNolang.call();
Assert.fail("Should have thrown an exception.");
} catch (LLVMPolyglotException e) {
Assert.assertEquals("err_eval_no_lang", "Language 'not_impl_lang' not found.", e.getMessage());
}
}
public static class TestEvalNoInternal extends SulongTestNode {
public TestEvalNoInternal() {
super(testLibrary, "test_eval_internal_lang");
}
}
@Test
public void testHasEvalNoInternal(@Inject(TestEvalNoInternal.class) CallTarget testEvalNoInternal) {
try {
testEvalNoInternal.call();
Assert.fail("Should have thrown an exception.");
} catch (LLVMPolyglotException e) {
Assert.assertEquals("err_eval_no_lang", "Language 'nfi' not found.", e.getMessage());
}
}
}