Mercurial > hg > truffle
diff truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java @ 22135:e70b20f4bb00
Implementing API for Java/Truffle interop. Based around JavaInterop.asJavaObject and JavaInterop.asTruffleObject methods. Connected to TruffleVM via Symbol.as(Class) wrapper. Verified by extended TCK.
author | Jaroslav Tulach <jaroslav.tulach@oracle.com> |
---|---|
date | Mon, 07 Sep 2015 17:07:20 +0200 |
parents | d045a505c2b3 |
children | a583d7ffd285 |
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java Fri Sep 04 16:41:38 2015 +0200 +++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java Mon Sep 07 17:07:20 2015 +0200 @@ -24,10 +24,14 @@ */ package com.oracle.truffle.tck; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.vm.TruffleVM; import java.io.IOException; import java.util.Random; +import java.util.logging.Level; +import java.util.logging.Logger; import static org.junit.Assert.*; import org.junit.Test; @@ -37,6 +41,8 @@ * include in your test suite. */ public abstract class TruffleTCK { + private static final Logger LOG = Logger.getLogger(TruffleTCK.class.getName()); + private static final Random RANDOM = new Random(); private TruffleVM tckVM; protected TruffleTCK() { @@ -56,7 +62,7 @@ protected abstract TruffleVM prepareVM() throws Exception; /** - * Mimetype associated with your language. The mimetype will be passed to + * MIME type associated with your language. The MIME type will be passed to * {@link TruffleVM#eval(com.oracle.truffle.api.source.Source)} method of the * {@link #prepareVM() created TruffleVM}. * @@ -124,6 +130,31 @@ */ protected abstract String invalidCode(); + /** + * Name of a function that returns a compound object with members representing certain + * operations. In the JavaScript the object should look like: + * + * <pre> + * <b>var</b> obj = { + * 'fourtyTwo': function {@link #fourtyTwo()}, + * 'plus': function {@link #plusInt()}, + * 'returnsNull': function {@link #returnsNull()}, + * 'returnsThis': function() { return obj; } + * }; + * <b>return</b> obj; + * </pre> + * + * The returned object shall have three functions that will be obtained and used exactly as + * described in their Javadoc - e.g. {@link #fourtyTwo()}, {@link #plusInt()} and + * {@link #returnsNull()}. In addition to that there should be one more function + * <b>returnsThis</b> that will return the object itself again. + * + * @return name of a function that returns such compound object + */ + protected String compoundObject() { + return null; + } + private TruffleVM vm() throws Exception { if (tckVM == null) { tckVM = prepareVM(); @@ -149,10 +180,17 @@ } @Test - public void testNull() throws Exception { - if (getClass() == TruffleTCK.class) { + public void testFortyTwoWithCompoundObject() throws Exception { + CompoundObject obj = findCompoundSymbol("testFortyTwoWithCompoundObject"); + if (obj == null) { return; } + Number res = obj.fourtyTwo(); + assertEquals("Should be 42", 42, res.intValue()); + } + + @Test + public void testNull() throws Exception { TruffleVM.Symbol retNull = findGlobalSymbol(returnsNull()); Object res = retNull.invoke(null).get(); @@ -161,19 +199,37 @@ } @Test + public void testNullInCompoundObject() throws Exception { + CompoundObject obj = findCompoundSymbol("testNullInCompoundObject"); + if (obj == null) { + return; + } + Object res = obj.returnsNull(); + assertNull("Should yield real Java null", res); + } + + @Test public void testPlusWithInts() throws Exception { - Random r = new Random(); - int a = r.nextInt(100); - int b = r.nextInt(100); + int a = RANDOM.nextInt(100); + int b = RANDOM.nextInt(100); TruffleVM.Symbol plus = findGlobalSymbol(plusInt()); - Object res = plus.invoke(null, a, b).get(); + Number n = plus.invoke(null, a, b).as(Number.class); + assert a + b == n.intValue() : "The value is correct: (" + a + " + " + b + ") = " + n.intValue(); + } - assert res instanceof Number : "+ on two ints should yield a number, but was: " + res; + @Test + public void testPlusWithIntsOnCompoundObject() throws Exception { + int a = RANDOM.nextInt(100); + int b = RANDOM.nextInt(100); - Number n = (Number) res; + CompoundObject obj = findCompoundSymbol("testPlusWithIntsOnCompoundObject"); + if (obj == null) { + return; + } + Number n = obj.plus(a, b); assert a + b == n.intValue() : "The value is correct: (" + a + " + " + b + ") = " + n.intValue(); } @@ -189,7 +245,8 @@ public void testMaxOrMinValue() throws Exception { TruffleVM.Symbol apply = findGlobalSymbol(applyNumbers()); - Object res = apply.invoke(null, new MaxMinObject(true)).get(); + TruffleObject fn = JavaInterop.asTruffleFunction(LongBinaryOperation.class, new MaxMinObject(true)); + Object res = apply.invoke(null, fn).get(); assert res instanceof Number : "result should be a number: " + res; @@ -202,12 +259,17 @@ public void testMaxOrMinValue2() throws Exception { TruffleVM.Symbol apply = findGlobalSymbol(applyNumbers()); - Object res = apply.invoke(null, new MaxMinObject(false)).get(); + TruffleObject fn = JavaInterop.asTruffleFunction(LongBinaryOperation.class, new MaxMinObject(false)); + final TruffleVM.Symbol result = apply.invoke(null, fn); - assert res instanceof Number : "result should be a number: " + res; + try { + String res = result.as(String.class); + fail("Cannot be converted to String: " + res); + } catch (ClassCastException ex) { + // correct + } - Number n = (Number) res; - + Number n = result.as(Number.class); assert 28 == n.intValue() : "18 < 32 and plus 10"; } @@ -224,18 +286,19 @@ int prev1 = 0; int prev2 = 0; - Random r = new Random(); for (int i = 0; i < 10; i++) { - int quantum = r.nextInt(10); + int quantum = RANDOM.nextInt(10); for (int j = 0; j < quantum; j++) { Object res = count1.invoke(null).get(); assert res instanceof Number : "expecting number: " + res; - assert ((Number) res).intValue() == ++prev1 : "expecting " + prev1 + " but was " + res; + ++prev1; + assert ((Number) res).intValue() == prev1 : "expecting " + prev1 + " but was " + res; } for (int j = 0; j < quantum; j++) { Object res = count2.invoke(null).get(); assert res instanceof Number : "expecting number: " + res; - assert ((Number) res).intValue() == ++prev2 : "expecting " + prev2 + " but was " + res; + ++prev2; + assert ((Number) res).intValue() == prev2 : "expecting " + prev2 + " but was " + res; } assert prev1 == prev2 : "At round " + i + " the same number of invocations " + prev1 + " vs. " + prev2; } @@ -247,4 +310,36 @@ assert s != null : "Symbol " + name + " is not found!"; return s; } + + private CompoundObject findCompoundSymbol(String name) throws Exception { + final String compoundObjectName = compoundObject(); + if (compoundObjectName == null) { + final long introduced = 1441616302340L; + long wait = (System.currentTimeMillis() - introduced) / 3600; + if (wait < 100) { + wait = 100; + } + LOG.log(Level.SEVERE, "compoundObject() method not overriden! Skipping {1} test for now. But sleeping for {0} ms.", new Object[]{wait, name}); + Thread.sleep(wait); + return null; + } + TruffleVM.Symbol s = vm().findGlobalSymbol(compoundObjectName); + assert s != null : "Symbol " + compoundObjectName + " is not found!"; + CompoundObject obj = s.invoke(null).as(CompoundObject.class); + int traverse = RANDOM.nextInt(10); + while (traverse-- >= 0) { + obj = obj.returnsThis(); + } + return obj; + } + + interface CompoundObject { + Number fourtyTwo(); + + Number plus(int x, int y); + + Object returnsNull(); + + CompoundObject returnsThis(); + } }