/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.truffle.api.test.vm;
import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.interop.MessageResolution;
import com.oracle.truffle.api.interop.Resolve;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.interop.java.JavaInterop;
import com.oracle.truffle.api.interop.java.MethodMessage;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.vm.PolyglotEngine;
import org.junit.After;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
public class ExchangingObjectsForbiddenTest {
private MyObj myObj;
private PolyglotEngine myEngine;
private PolyglotEngine.Value myObjWrapped;
private CallWithValue myObjCall;
private MyObj otherObj;
private PolyglotEngine otherEngine;
private PolyglotEngine.Value otherObjWrapped;
@Test
public void sendOtherObjectAsParameterToMyEngine() {
myObjWrapped.execute(otherObj);
assertEquals("Plain TruffleObject can be sent anywhere", otherObj, myObj.value);
}
@Test
public void sendWrappedOtherObjectAsParameterToMyEngine() {
myObj.value = null;
try {
myObjWrapped.execute(otherObjWrapped.get());
} catch (IllegalArgumentException ex) {
// OK
}
assertNull("Value hasn't been changed", myObj.value);
}
@Test
public void sendOtherObjectViaCallToMyEngine() {
myObjCall.call(otherObj);
assertEquals("Plain TruffleObject can be sent anywhere", otherObj, myObj.value);
}
@Test
public void sendWrappedOtherObjectViaCallToMyEngine() {
myObj.value = null;
try {
myObjWrapped.execute(otherObjWrapped.get());
} catch (IllegalArgumentException ex) {
// OK
}
assertNull("Value hasn't been changed", myObj.value);
}
@Before
public void prepareSystem() {
myObj = new MyObj();
myEngine = PolyglotEngine.newBuilder().globalSymbol("myObj", myObj).build();
myObjWrapped = myEngine.findGlobalSymbol("myObj");
assertNotNull(myObjWrapped.get());
assertTrue(myObjWrapped.get() instanceof TruffleObject);
assertFalse(myObjWrapped.get() instanceof MyObj);
myObjCall = myObjWrapped.as(CallWithValue.class);
otherObj = new MyObj();
otherEngine = PolyglotEngine.newBuilder().globalSymbol("myObj", otherObj).build();
otherObjWrapped = otherEngine.findGlobalSymbol("myObj");
}
@After
public void disposeSystem() {
myEngine.dispose();
}
@MessageResolution(receiverType = MyObj.class)
static final class MyObj implements TruffleObject {
private Object value;
@Override
public ForeignAccess getForeignAccess() {
return MyObjForeign.ACCESS;
}
static boolean isInstance(TruffleObject obj) {
return obj instanceof MyObj;
}
@Resolve(message = "EXECUTE")
abstract static class ExecNode extends Node {
protected Object access(MyObj obj, Object... value) {
obj.value = value[0];
return JavaInterop.asTruffleValue(null);
}
}
}
abstract static class MyLang extends TruffleLanguage<Object> {
}
@FunctionalInterface
interface CallWithValue {
@MethodMessage(message = "EXECUTE")
void call(Object value);
}
}