/* * Copyright (c) 2016, Oracle and/or its affiliates. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials provided * with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors may be used to * endorse or promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.oracle.truffle.llvm.test.interop; import java.io.File; import java.io.IOException; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.nio.file.Path; import java.util.List; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.Message; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.java.JavaInterop; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.api.vm.PolyglotEngine.Builder; import com.oracle.truffle.api.vm.PolyglotEngine.Value; import com.oracle.truffle.llvm.runtime.LLVMTruffleAddress; import com.oracle.truffle.llvm.runtime.SulongRuntimeException; import com.oracle.truffle.llvm.runtime.options.LLVMOptions; @SuppressWarnings({"static-method"}) public final class LLVMInteropTest { @Test public void test001() { Runner runner = new Runner("interop001"); Assert.assertEquals(42, runner.run()); } @Test public void test002() { Runner runner = new Runner("interop002"); ClassA a = new ClassA(); TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "foreign"); Assert.assertEquals(42, runner.run()); } @Test public void test003() { Runner runner = new Runner("interop003"); ClassA a = new ClassA(); TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "foreign"); Assert.assertEquals(215, runner.run()); } @Test public void test004() { Runner runner = new Runner("interop004"); ClassB a = new ClassB(); TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "foreign"); Assert.assertEquals(73, runner.run()); } @Test public void test005() { Runner runner = new Runner("interop005"); ClassA a = new ClassA(); TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "foreign"); runner.run(); Assert.assertEquals(a.valueBool, false); Assert.assertEquals(a.valueI, 2); Assert.assertEquals(a.valueB, 3); Assert.assertEquals(a.valueL, 4); Assert.assertEquals(a.valueF, 5.5, 0.1); Assert.assertEquals(a.valueD, 6.5, 0.1); } @Test public void test006() { Runner runner = new Runner("interop006"); ClassB a = new ClassB(); TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "foreign"); runner.run(); Assert.assertEquals(a.valueI[0], 1); Assert.assertEquals(a.valueI[1], 2); Assert.assertEquals(a.valueL[0], 3); Assert.assertEquals(a.valueL[1], 4); Assert.assertEquals(a.valueB[0], 5); Assert.assertEquals(a.valueB[1], 6); Assert.assertEquals(a.valueF[0], 7.5, 0.1); Assert.assertEquals(a.valueF[1], 8.5, 0.1); Assert.assertEquals(a.valueD[0], 9.5, 0.1); Assert.assertEquals(a.valueD[1], 10.5, 0.1); } @Test public void test007() { Runner runner = new Runner("interop007"); ClassC a = new ClassC(); TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "foreign"); Assert.assertEquals(36, runner.run()); Assert.assertEquals(a.valueI, 4); Assert.assertEquals(a.valueB, 3); Assert.assertEquals(a.valueL, 7); Assert.assertEquals(a.valueF, 10, 0.1); Assert.assertEquals(a.valueD, 12, 0.1); } @Test public void test008() { Runner runner = new Runner("interop008"); TruffleObject to = JavaInterop.asTruffleFunction(FuncBInterface.class, (a, b) -> (byte) (a + b)); runner.export(to, "foreign"); Assert.assertEquals(42, runner.run()); } @Test public void test009() { Runner runner = new Runner("interop009"); TruffleObject to = JavaInterop.asTruffleFunction(FuncIInterface.class, (a, b) -> (a + b)); runner.export(to, "foreign"); Assert.assertEquals(42, runner.run()); } @Test public void test010() { Runner runner = new Runner("interop010"); TruffleObject to = JavaInterop.asTruffleFunction(FuncLInterface.class, (a, b) -> (a + b)); runner.export(to, "foreign"); Assert.assertEquals(42, runner.run()); } @Test public void test011() { Runner runner = new Runner("interop011"); TruffleObject to = JavaInterop.asTruffleFunction(FuncFInterface.class, (a, b) -> (a + b)); runner.export(to, "foreign"); Assert.assertEquals(42.0, runner.run(), 0.1); } @Test public void test012() { Runner runner = new Runner("interop012"); TruffleObject to = JavaInterop.asTruffleFunction(FuncDInterface.class, (a, b) -> (a + b)); runner.export(to, "foreign"); Assert.assertEquals(42.0, runner.run(), 0.1); } @Test public void test013() { Runner runner = new Runner("interop013"); TruffleObject to = JavaInterop.asTruffleObject(new MyBoxedInt()); runner.export(to, "foreign"); Assert.assertEquals(42, runner.run()); } @Test public void test014() { Runner runner = new Runner("interop014"); TruffleObject to = JavaInterop.asTruffleObject(new MyBoxedInt()); runner.export(to, "foreign"); Assert.assertEquals(42, runner.run(), 0.1); } @Test public void test015() { Runner runner = new Runner("interop015"); TruffleObject to = JavaInterop.asTruffleFunction(FuncDInterface.class, (a, b) -> (a + b)); runner.export(to, "foreign"); Assert.assertEquals(42, runner.run(), 0.1); } @Test public void test016() { Runner runner = new Runner("interop016"); TruffleObject to = JavaInterop.asTruffleObject(null); runner.export(to, "foreign"); Assert.assertEquals(42, runner.run(), 0.1); } @Test public void test017() { Runner runner = new Runner("interop017"); TruffleObject to = JavaInterop.asTruffleObject(new int[]{1, 2, 3}); runner.export(to, "foreign"); Assert.assertEquals(42, runner.run(), 0.1); } @Test public void test018() { Runner runner = new Runner("interop018"); TruffleObject to = JavaInterop.asTruffleObject(new int[]{1, 2, 3}); runner.export(to, "foreign"); Assert.assertEquals(3, runner.run()); } @Test public void test019() { Runner runner = new Runner("interop019"); TruffleObject to = JavaInterop.asTruffleObject(new int[]{40, 41, 42, 43, 44}); runner.export(to, "foreign"); Assert.assertEquals(210, runner.run()); } @Test public void test020() { Runner runner = new Runner("interop020"); int[] arr = new int[]{40, 41, 42, 43, 44}; TruffleObject to = JavaInterop.asTruffleObject(arr); runner.export(to, "foreign"); runner.run(); Assert.assertArrayEquals(new int[]{30, 31, 32, 33, 34}, arr); } @Test public void test021() { Runner runner = new Runner("interop021"); TruffleObject to = JavaInterop.asTruffleObject(new double[]{40, 41, 42, 43, 44}); runner.export(to, "foreign"); Assert.assertEquals(210, runner.run()); } @Test public void test022() { Runner runner = new Runner("interop022"); double[] arr = new double[]{40, 41, 42, 43, 44}; TruffleObject to = JavaInterop.asTruffleObject(arr); runner.export(to, "foreign"); runner.run(); Assert.assertArrayEquals(new double[]{30, 31, 32, 33, 34}, arr, 0.1); } @Test public void test023() { Runner runner = new Runner("interop023"); ClassA a = new ClassA(); ClassA b = new ClassA(); TruffleObject to = JavaInterop.asTruffleObject(a); TruffleObject to2 = JavaInterop.asTruffleObject(b); runner.export(to, "foreign"); runner.export(to2, "foreign2"); Assert.assertEquals(42, runner.run()); } @Test public void test024() { Runner runner = new Runner("interop024"); ClassA a = new ClassA(); ClassA b = new ClassA(); b.valueI = 55; TruffleObject to = JavaInterop.asTruffleObject(a); TruffleObject to2 = JavaInterop.asTruffleObject(b); runner.export(to, "foreign"); runner.export(to2, "foreign2"); Assert.assertEquals(55, runner.run()); } @Test public void test025() { Runner runner = new Runner("interop025"); ClassA a = new ClassA(); ClassA b = new ClassA(); ClassA c = new ClassA(); b.valueI = 55; c.valueI = 66; TruffleObject to = JavaInterop.asTruffleObject(a); TruffleObject to2 = JavaInterop.asTruffleObject(b); TruffleObject to3 = JavaInterop.asTruffleObject(c); runner.export(to, "foreign"); runner.export(to2, "foreign2"); runner.export(to3, "foreign3"); Assert.assertEquals(66, runner.run()); } @Test public void test026() { Runner runner = new Runner("interop026"); final Object[] result = new Object[]{null}; runner.export(JavaInterop.asTruffleFunction(FuncEInterface.class, x -> result[0] = x), "foo"); Assert.assertEquals(14, runner.run()); Assert.assertEquals("bar", result[0]); } @Test public void test027() { Runner runner = new Runner("interop027"); final Object[] result = new Object[]{null}; runner.export(JavaInterop.asTruffleFunction(FuncEInterface.class, x -> result[0] = x), "foo"); Assert.assertEquals(14, runner.run()); Assert.assertEquals("\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f" + "\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f" + "\u00a0\u00a1\u00a2\u00a3\u00a4\u00a5\u00a6\u00a7\u00a8\u00a9\u00aa\u00ab\u00ac\u00ad\u00ae\u00af" + "\u00b0\u00b1\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00b8\u00b9\u00ba\u00bb\u00bc\u00bd\u00be\u00bf" + "\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u00c6\u00c7\u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf" + "\u00d0\u00d1\u00d2\u00d3\u00d4\u00d5\u00d6\u00d7\u00d8\u00d9\u00da\u00db\u00dc\u00dd\u00de\u00df" + "\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u00e6\u00e7\u00e8\u00e9\u00ea\u00eb\u00ec\u00ed\u00ee\u00ef" + "\u00f0\u00f1\u00f2\u00f3\u00f4\u00f5\u00f6\u00f7\u00f8\u00f9\u00fa\u00fb\u00fc\u00fd\u00fe\u00ff", result[0]); } @Test public void test028() { Runner runner = new Runner("interop028"); final Object[] result = new Object[]{null}; runner.export(JavaInterop.asTruffleFunction(FuncEInterface.class, x -> result[0] = x), "foo"); Assert.assertEquals(72, runner.run()); Assert.assertEquals("foo\u0000 bar\u0080 ", result[0]); } @Test public void test029() { Runner runner = new Runner("interop029"); final Object[] result = new Object[]{null}; runner.export(JavaInterop.asTruffleFunction(FuncEInterface.class, x -> result[0] = x), "foo"); Assert.assertEquals(36, runner.run()); byte[] actualResult = (byte[]) (result[0]); Assert.assertArrayEquals(new byte[]{102, 111, 111, 0, 32, 98, 97, 114, -128, 32}, actualResult); } // implicit interop // structs not yet implemented @Test @Ignore public void test030() throws Exception { Runner runner = new Runner("interop030"); try { PolyglotEngine.Value get = runner.findGlobalSymbol("getValueI"); ClassA a = new ClassA(); Number result = (Number) get.execute(JavaInterop.asTruffleObject(a)).get(); Assert.assertEquals(42, result.intValue()); } finally { runner.dispose(); } } @Test @Ignore public void test031() throws Exception { Runner runner = new Runner("interop031"); try { PolyglotEngine.Value apply = runner.findGlobalSymbol("complexAdd"); ComplexNumber a = new ComplexNumber(32, 10); ComplexNumber b = new ComplexNumber(10, 32); apply.execute(JavaInterop.asTruffleObject(a), JavaInterop.asTruffleObject(b)); Assert.assertEquals(42.0, a.real, 0.1); Assert.assertEquals(42.0, a.imaginary, 0.1); } finally { runner.dispose(); } } // arrays: foreign array to llvm @Test public void test032() throws Exception { Runner runner = new Runner("interop032"); try { PolyglotEngine.Value get = runner.findGlobalSymbol("get"); int[] a = new int[]{1, 2, 3, 4, 5}; Number result = (Number) get.execute(JavaInterop.asTruffleObject(a), 2).get(); Assert.assertEquals(3, result.intValue()); } finally { runner.dispose(); } } @Test public void test033() throws Exception { Runner runner = new Runner("interop033"); try { PolyglotEngine.Value get = runner.findGlobalSymbol("get"); short[] a = new short[]{1, 2, 3, 4, 5}; Number result = (Number) get.execute(JavaInterop.asTruffleObject(a), 2).get(); Assert.assertEquals(3, result.intValue()); } finally { runner.dispose(); } } @Test public void test034() throws Exception { Runner runner = new Runner("interop034"); try { PolyglotEngine.Value get = runner.findGlobalSymbol("get"); byte[] a = new byte[]{1, 2, 3, 4, 5}; Number result = (Number) get.execute(JavaInterop.asTruffleObject(a), 2).get(); Assert.assertEquals(3, result.intValue()); } finally { runner.dispose(); } } @Test public void test035() throws Exception { Runner runner = new Runner("interop035"); try { PolyglotEngine.Value get = runner.findGlobalSymbol("get"); long[] a = new long[]{1, 2, 3, 4, 5}; Number result = (Number) get.execute(JavaInterop.asTruffleObject(a), 2).get(); Assert.assertEquals(3, result.intValue()); } finally { runner.dispose(); } } @Test public void test036() throws Exception { Runner runner = new Runner("interop036"); try { PolyglotEngine.Value get = runner.findGlobalSymbol("get"); float[] a = new float[]{1, 2, 3, 4, 5}; Number result = (Number) get.execute(JavaInterop.asTruffleObject(a), 2).get(); Assert.assertEquals(3, result.intValue()); } finally { runner.dispose(); } } @Test public void test037() throws Exception { Runner runner = new Runner("interop037"); try { PolyglotEngine.Value get = runner.findGlobalSymbol("get"); double[] a = new double[]{1, 2, 3, 4, 5}; Number result = (Number) get.execute(JavaInterop.asTruffleObject(a), 2).get(); Assert.assertEquals(3, result.intValue()); } finally { runner.dispose(); } } // foreign array with different type @Test public void test038() throws Exception { Runner runner = new Runner("interop038"); try { PolyglotEngine.Value get = runner.findGlobalSymbol("get"); long[] a = new long[]{1, 2, 3, 4, 5}; Number result = (Number) get.execute(JavaInterop.asTruffleObject(a), 2).get(); Assert.assertEquals(3, result.intValue()); } finally { runner.dispose(); } } @Test public void test039() throws Exception { Runner runner = new Runner("interop039"); try { PolyglotEngine.Value get = runner.findGlobalSymbol("get"); byte[] a = new byte[]{1, 2, 3, 4, 5}; Number result = (Number) get.execute(JavaInterop.asTruffleObject(a), 2).get(); Assert.assertEquals(3, result.intValue()); } finally { runner.dispose(); } } @Test public void test040() throws Exception { Runner runner = new Runner("interop040"); try { PolyglotEngine.Value get = runner.findGlobalSymbol("get"); TruffleObject result = get.execute().as(TruffleObject.class); @SuppressWarnings("unchecked") List<Integer> array = JavaInterop.asJavaObject(List.class, result); Assert.assertEquals(16, (int) array.get(4)); } finally { runner.dispose(); } } // llvm array to foreign language @Test public void test041() throws Exception { Runner runner = new Runner("interop041"); try { PolyglotEngine.Value get = runner.findGlobalSymbol("get"); PolyglotEngine.Value getval = runner.findGlobalSymbol("getval"); TruffleObject result = get.execute().as(TruffleObject.class); @SuppressWarnings("unchecked") List<Integer> array = JavaInterop.asJavaObject(List.class, result); array.set(3, 9); int value = (int) getval.execute(3).get(); Assert.assertEquals(9, value); } finally { runner.dispose(); } } @Test(expected = UnsupportedMessageException.class) public void test042() throws Exception { Runner runner = new Runner("interop042"); try { PolyglotEngine.Value get = runner.findGlobalSymbol("get"); TruffleObject result = get.execute().as(TruffleObject.class); @SuppressWarnings("unchecked") List<Integer> array = JavaInterop.asJavaObject(List.class, result); array.size(); // GET_SIZE is not supported Assert.fail("IllegalStateException expected"); } finally { runner.dispose(); } } @Test public void test043() { Runner runner = new Runner("interop043"); ClassA a = new ClassA(); TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "foreign"); Assert.assertEquals(0, runner.run()); } @Test public void test044() { Runner runner = new Runner("interop044"); runner.export(JavaInterop.asTruffleObject(new Object()), "a"); runner.export(JavaInterop.asTruffleObject(14), "b"); runner.export(JavaInterop.asTruffleObject(14.5), "c"); Assert.assertEquals(0, runner.run()); } @Test public void test045a() { Runner runner = new Runner("interop045"); runner.export(14, "a"); runner.export(15, "b"); Assert.assertEquals(1, runner.run()); } @Test public void test046a() { Runner runner = new Runner("interop046"); runner.export(14, "a"); runner.export(14, "b"); Assert.assertEquals(1, runner.run()); } @Test public void test046b() { Runner runner = new Runner("interop046"); runner.export(14, "a"); runner.export(15, "b"); Assert.assertEquals(1, runner.run()); } @Test public void test047a() { Runner runner = new Runner("interop047"); runner.export(14, "a"); runner.export(15, "b"); Assert.assertEquals(0, runner.run()); } @Test public void test048a() { Runner runner = new Runner("interop048"); runner.export(14, "a"); runner.export(15, "b"); Assert.assertEquals(0, runner.run()); } @Test public void test048b() { Runner runner = new Runner("interop048"); runner.export(14, "a"); runner.export(14, "b"); Assert.assertEquals(1, runner.run()); } @Test public void test049a() { Runner runner = new Runner("interop049"); runner.export(JavaInterop.asTruffleObject(14), "a"); runner.export(JavaInterop.asTruffleObject(14), "b"); Assert.assertEquals(0, runner.run()); } @Test public void test049b() { Runner runner = new Runner("interop049"); TruffleObject object = JavaInterop.asTruffleObject(new Object()); runner.export(object, "a"); runner.export(object, "b"); Assert.assertEquals(0, runner.run()); } @Test public void test050a() { Runner runner = new Runner("interop050"); runner.export(JavaInterop.asTruffleObject(14), "a"); runner.export(JavaInterop.asTruffleObject(14), "b"); Assert.assertEquals(1, runner.run()); } @Test public void test050b() { Runner runner = new Runner("interop050"); TruffleObject object = JavaInterop.asTruffleObject(new Object()); runner.export(object, "a"); runner.export(object, "b"); Assert.assertEquals(1, runner.run()); } static Object staticStorage; interface ReturnObject { void storeObject(Object o); } @Test public void test051a() { Runner runner = new Runner("interop051"); testGlobal(runner); } @Test public void test052a() { Runner runner = new Runner("interop052"); testGlobal(runner); } @Test public void test053a() { Runner runner = new Runner("interop053"); testGlobal(runner); } @Test public void test054a() { Runner runner = new Runner("interop054"); testGlobal(runner); } @Test public void test055a() { Runner runner = new Runner("interop055"); testGlobal(runner); } @Test public void test056a() { Runner runner = new Runner("interop056"); testGlobal(runner); } private void testGlobal(Runner runner) { TruffleObject returnObject = JavaInterop.asTruffleFunction(ReturnObject.class, new ReturnObject() { @Override public void storeObject(Object o) { staticStorage = o; } }); Object original = new Object(); TruffleObject object = JavaInterop.asTruffleObject(original); runner.export(object, "object"); runner.export(returnObject, "returnObject"); staticStorage = null; runner.run(); Assert.assertSame(original, staticStorage); } @Test public void test057() { Runner runner = new Runner("interop057"); Object[] a = new Object[]{0, 1, 2, 3, 4, 5, 6, 7, 8}; TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "foreign"); Assert.assertEquals(0, runner.run()); Assert.assertEquals(101, a[0]); Assert.assertEquals(102, a[1]); } @Test public void test058() { Runner runner = new Runner("interop058"); Object[] a = new Object[]{0, 1, 2, 3, 4, 5, 6, 7, 8}; TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "foreign"); Assert.assertEquals(0, runner.run()); Assert.assertEquals(101, a[0]); Assert.assertEquals(102, a[1]); } @Test public void test059() { Runner runner = new Runner("interop059"); Object[] a = new Object[]{0, 1, 2, 3, 4, 5, 6, 7, 8}; TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "foreign"); Assert.assertEquals(0, runner.run()); Assert.assertEquals(101, ((LLVMTruffleAddress) a[0]).getAddress().getVal()); Assert.assertEquals(102, ((LLVMTruffleAddress) a[1]).getAddress().getVal()); } @Test public void test060() { Runner runner = new Runner("interop060"); Object[] a = new Object[]{0, 1, 2, 3, 4, 5, 6, 7, 8}; TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "foreign"); Assert.assertEquals(0, runner.run()); Assert.assertEquals(101, ((LLVMTruffleAddress) a[0]).getAddress().getVal()); Assert.assertEquals(102, ((LLVMTruffleAddress) a[1]).getAddress().getVal()); } @Test public void test061() { Runner runner = new Runner("interop061"); Assert.assertEquals(0, runner.run()); } @Test public void test062() { Runner runner = new Runner("interop062"); Object a = new Object(); TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "object"); Assert.assertEquals(0, runner.run()); } @Test public void test063() { Runner runner = new Runner("interop063"); Object a = new Object(); TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "object"); Assert.assertEquals(0, runner.run()); } @Test public void test064() { Runner runner = new Runner("interop064"); Object a = new Object(); TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "object"); Assert.assertEquals(0, runner.run()); } @Test(expected = SulongRuntimeException.class) public void test065() { Runner runner = new Runner("interop065"); Object a = new Object(); TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "object"); Assert.assertEquals(0, runner.run()); } @Test(expected = SulongRuntimeException.class) public void test066() { Runner runner = new Runner("interop066"); Object a = new Object(); TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "object"); Assert.assertEquals(0, runner.run()); } @Test public void test067() { Runner runner = new Runner("interop067"); Object a = new Object(); TruffleObject to = JavaInterop.asTruffleObject(a); runner.export(to, "object"); Assert.assertEquals(0, runner.run()); } @Test public void test068() { Runner runner = new Runner("interop068"); runner.export(true, "boxed_true"); runner.export(false, "boxed_false"); Assert.assertEquals(0, runner.run()); } @Test public void test069() { Runner runner = new Runner("interop069"); runner.export(42, "a"); runner.run(); try { Value globalSymbol = runner.findGlobalSymbol("registered_tagged_address"); Object result = globalSymbol.execute().get(); Assert.assertTrue(result instanceof Integer && (int) result == 42); } catch (Exception e) { throw new AssertionError(e); } } @Test public void test070() { Runner runner = new Runner("interop070"); runner.run(); try { Value pointer = runner.findGlobalSymbol("returnPointerToGlobal"); TruffleObject pointerTruffleObject = (TruffleObject) pointer.execute().get(); ForeignAccess.sendWrite(Message.WRITE.createNode(), pointerTruffleObject, 0, 42); Value value = runner.findGlobalSymbol("returnGlobal"); Object result = value.execute().get(); Assert.assertTrue(result instanceof Integer && (int) result == 42); } catch (Exception e) { throw new AssertionError(e); } } @Test public void test071() { Runner runner = new Runner("interop071"); runner.run(); try { Object obj = new Object(); TruffleObject o = JavaInterop.asTruffleObject(obj); Value pointer = runner.findGlobalSymbol("returnPointerToGlobal"); TruffleObject pointerTruffleObject = (TruffleObject) pointer.execute().get(); ForeignAccess.sendWrite(Message.WRITE.createNode(), pointerTruffleObject, 0, o); Value value = runner.findGlobalSymbol("returnGlobal"); Object result = value.execute().get(); Assert.assertTrue(result == obj); } catch (Exception e) { throw new AssertionError(e); } } @Test public void test072() { Runner runner = new Runner("interop072"); runner.run(); try { Object obj = new Object(); TruffleObject o = JavaInterop.asTruffleObject(obj); Value pointer = runner.findGlobalSymbol("returnPointerToGlobal"); TruffleObject pointerTruffleObject = (TruffleObject) pointer.execute().get(); Value setter = runner.findGlobalSymbol("setter"); setter.execute(pointerTruffleObject, o); Value value = runner.findGlobalSymbol("returnGlobal"); Object result = value.execute().get(); Assert.assertTrue(result == obj); } catch (Exception e) { throw new AssertionError(e); } } @Test public void test072a() { Runner runner = new Runner("interop072"); runner.run(); try { Value pointer = runner.findGlobalSymbol("returnPointerToGlobal"); TruffleObject pointerTruffleObject = (TruffleObject) pointer.execute().get(); Value setter = runner.findGlobalSymbol("setter"); setter.execute(pointerTruffleObject, 42); Value value = runner.findGlobalSymbol("returnGlobal"); Object result = value.execute().get(); Assert.assertTrue(result instanceof Integer && (int) result == 42); } catch (Exception e) { throw new AssertionError(e); } } @Test public void test072b() { Runner runner = new Runner("interop072"); runner.run(); try { Value pointer = runner.findGlobalSymbol("returnPointerToGlobal"); TruffleObject pointerTruffleObject = (TruffleObject) pointer.execute().get(); Value setter = runner.findGlobalSymbol("setter"); setter.execute(pointerTruffleObject, 42); Value value = runner.findGlobalSymbol("returnGlobal"); Object result = value.execute().get(); Assert.assertTrue(result instanceof Integer && (int) result == 42); Object obj = new Object(); TruffleObject o = JavaInterop.asTruffleObject(obj); setter.execute(pointerTruffleObject, o); result = value.execute().get(); Assert.assertTrue(result == obj); } catch (Exception e) { throw new AssertionError(e); } } @Test public void test073() { Runner runner = new Runner("interop073"); Assert.assertEquals(42, runner.run()); } @Test public void testStrlen() throws Exception { Runner runner = new Runner("strlen"); try { Value strlenFunction = runner.findGlobalSymbol("func"); Value nullString = strlenFunction.execute(JavaInterop.asTruffleObject(new char[]{})); Value a = strlenFunction.execute(JavaInterop.asTruffleObject(new char[]{'a'})); Value abcd = strlenFunction.execute(JavaInterop.asTruffleObject(new char[]{'a', 'b', 'c', 'd'})); Value abcdWithTerminator = strlenFunction.execute(JavaInterop.asTruffleObject(new char[]{'a', 'b', 'c', 'd', '\0'})); Assert.assertEquals(0, nullString.get()); Assert.assertEquals(1, a.get()); Assert.assertEquals(4, abcd.get()); Assert.assertEquals(5, abcdWithTerminator.get()); } finally { runner.dispose(); } } @Test public void testStrcmp() throws Exception { Runner runner = new Runner("strcmp"); try { Value strcmpFunction = runner.findGlobalSymbol("func"); Value test1 = strcmpFunction.execute(JavaInterop.asTruffleObject(new char[]{}), JavaInterop.asTruffleObject(new char[]{})); Value test2 = strcmpFunction.execute(JavaInterop.asTruffleObject(new char[]{'a'}), JavaInterop.asTruffleObject(new char[]{})); Value test3 = strcmpFunction.execute(JavaInterop.asTruffleObject(new char[]{}), JavaInterop.asTruffleObject(new char[]{'a'})); Value test4 = strcmpFunction.execute(JavaInterop.asTruffleObject(new char[]{'a'}), JavaInterop.asTruffleObject(new char[]{'d'})); Value test5 = strcmpFunction.execute(JavaInterop.asTruffleObject(new char[]{'d'}), JavaInterop.asTruffleObject(new char[]{'a'})); Value test6 = strcmpFunction.execute(JavaInterop.asTruffleObject(new char[]{'d'}), JavaInterop.asTruffleObject(new char[]{'d'})); Value test7 = strcmpFunction.execute(JavaInterop.asTruffleObject(new char[]{'a', 'b', 'c'}), JavaInterop.asTruffleObject(new char[]{'a', 'b', 'c', 'd'})); Value test8 = strcmpFunction.execute(JavaInterop.asTruffleObject(new char[]{'a', 'b', 'c', 'd'}), JavaInterop.asTruffleObject(new char[]{'a', 'b', 'c'})); Value test9 = strcmpFunction.execute(JavaInterop.asTruffleObject(new char[]{'A', 'B', 'C', 'D'}), JavaInterop.asTruffleObject(new char[]{'a', 'b', 'c', 'd'})); Assert.assertEquals(0, test1.get()); Assert.assertEquals(97, test2.get()); Assert.assertEquals(-97, test3.get()); Assert.assertEquals(-3, test4.get()); Assert.assertEquals(3, test5.get()); Assert.assertEquals(0, test6.get()); Assert.assertEquals(-100, test7.get()); Assert.assertEquals(100, test8.get()); Assert.assertEquals(-32, test9.get()); Value strcmpWithNativeFunction = runner.findGlobalSymbol("compare_with_native"); Value test10 = strcmpWithNativeFunction.execute(JavaInterop.asTruffleObject(new char[]{})); Value test11 = strcmpWithNativeFunction.execute(JavaInterop.asTruffleObject(new char[]{'f', 'o', 'o'})); Value test12 = strcmpWithNativeFunction.execute(JavaInterop.asTruffleObject(new char[]{'e'})); Value test13 = strcmpWithNativeFunction.execute(JavaInterop.asTruffleObject(new char[]{'g'})); Assert.assertEquals((int) 'f', test10.get()); Assert.assertEquals(0, test11.get()); Assert.assertEquals(1, test12.get()); Assert.assertEquals(-1, test13.get()); } finally { runner.dispose(); } } @Test public void testHandleFromNativeCallback() throws Exception { Runner runner = new Runner("handleFromNativeCallback"); try { TruffleObject managed = JavaInterop.asTruffleObject(new ClassA()); Value testHandleFromNativeCallback = runner.findGlobalSymbol("testHandleFromNativeCallback"); Value ret = testHandleFromNativeCallback.execute(managed); Assert.assertEquals(42, ret.get()); } finally { runner.dispose(); } } @Test public void testPointerThroughNativeCallback() throws Exception { Runner runner = new Runner("pointerThroughNativeCallback"); try { int result = runner.run(); Assert.assertEquals(42, result); } finally { runner.dispose(); } } public static final class ClassA { public boolean valueBool = true; public byte valueB = 40; public char valueC = 41; public int valueI = 42; public long valueL = 43; public float valueF = 44.5F; public double valueD = 45.5; } public static final class ClassB { public byte[] valueB = {1, 2}; public int[] valueI = {5, 6}; public long[] valueL = {7, 8}; public float[] valueF = {9.5F, 10.5F}; public double[] valueD = {11.5, 12.5}; } public static final class ClassC { public boolean valueBool = true; public byte valueB = 1; public char valueC = 2; public int valueI = 3; public long valueL = 4; public float valueF = 5.5F; public double valueD = 6.5F; public boolean addBool(boolean b) { valueBool ^= b; return valueBool; } public byte addB(byte b) { valueB += b; return valueB; } public char addC(char c) { valueC += c; return valueC; } public int addI(int i) { valueI += i; return valueI; } public long addL(long l) { valueL += l; return valueL; } public float addF(float f) { valueF += f; return valueF; } public double addD(double d) { valueD += d; return valueD; } } class ComplexNumber { public double real; public double imaginary; ComplexNumber(double real, double imaginary) { this.real = real; this.imaginary = imaginary; } } @FunctionalInterface public interface FuncIInterface { int eval(int a, int b); } @FunctionalInterface public interface FuncBInterface { byte eval(byte a, byte b); } @FunctionalInterface public interface FuncLInterface { long eval(long a, long b); } @FunctionalInterface public interface FuncFInterface { float eval(float a, float b); } @FunctionalInterface public interface FuncDInterface { double eval(double a, double b); } @FunctionalInterface public interface FuncEInterface { Object eval(Object string); } private static final Path TEST_DIR = new File(LLVMOptions.ENGINE.projectRoot() + "/../cache/tests/interoptests").toPath(); private static final String FILE_SUFFIX = "_clang_v38_O0_MEM2REG.bc"; private static final class Runner { private final Builder builder = PolyglotEngine.newBuilder(); private final String fileName; Runner(String fileName) { this.fileName = fileName; } void export(Object foreignObject, String name) { builder.globalSymbol(name, foreignObject); } int run() { final PolyglotEngine engine = builder.build(); try { File file = new File(TEST_DIR.toFile(), "/" + fileName + "/" + fileName + FILE_SUFFIX); return engine.eval(Source.newBuilder(file).build()).as(Integer.class); } catch (IOException e) { throw new AssertionError(e); } finally { engine.dispose(); } } protected PolyglotEngine prepareVM() throws Exception { PolyglotEngine engine = builder.build(); try { File file = new File(TEST_DIR.toFile(), "/" + fileName + "/" + fileName + FILE_SUFFIX); engine.eval(Source.newBuilder(file).build()).as(Integer.class); } catch (IOException e) { throw new AssertionError(e); } return engine; } private PolyglotEngine vm = null; private static Reference<PolyglotEngine> previousVMReference = new WeakReference<>(null); PolyglotEngine vm() throws Exception { if (vm == null) { vm = prepareVM(); replacePreviousVM(vm); } return vm; } private static void replacePreviousVM(PolyglotEngine newVM) { PolyglotEngine vm = previousVMReference.get(); if (vm == newVM) { return; } if (vm != null) { vm.dispose(); } previousVMReference = new WeakReference<>(newVM); } PolyglotEngine.Value findGlobalSymbol(String name) throws Exception { PolyglotEngine.Value s = vm().findGlobalSymbol(name); assert s != null : "Symbol " + name + " is not found!"; return s; } void dispose() { replacePreviousVM(null); } } }