/* * Copyright (c) 2016, 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 static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import org.junit.Assert; import org.junit.Test; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.vm.PolyglotEngine; public class InteractiveEvalTest { @Test public void testDefaultInteractiveLanguage() throws UnsupportedEncodingException { ByteArrayOutputStream out = new ByteArrayOutputStream(); PolyglotEngine engine = PolyglotEngine.newBuilder().setOut(out).build(); Source s = Source.newBuilder("").mimeType("application/x-test-definteract").name("definteract").interactive().build(); PolyglotEngine.Value value = engine.eval(s); Assert.assertEquals("42", value.get()); String strOutput = out.toString(StandardCharsets.UTF_8.name()); Assert.assertEquals("42" + System.getProperty("line.separator"), strOutput); } @Test public void testDefaultInteractiveLanguageDirectly() throws UnsupportedEncodingException { ByteArrayOutputStream out = new ByteArrayOutputStream(); PolyglotEngine engine = PolyglotEngine.newBuilder().setOut(out).build(); Source s = Source.newBuilder("").mimeType("application/x-test-definteract").name("definteract").interactive().build(); PolyglotEngine.Value value = engine.getLanguages().get("application/x-test-definteract").eval(s); Assert.assertEquals("42", value.get()); String strOutput = out.toString(StandardCharsets.UTF_8.name()); Assert.assertEquals("42" + System.getProperty("line.separator"), strOutput); } @Test public void testSpecialInteractiveLanguage() throws UnsupportedEncodingException { ByteArrayOutputStream out = new ByteArrayOutputStream(); PolyglotEngine engine = PolyglotEngine.newBuilder().setOut(out).build(); Source s = Source.newBuilder("").mimeType("application/x-test-specinteract").name("specinteract").interactive().build(); PolyglotEngine.Value value = engine.eval(s); Assert.assertEquals("42", value.get()); String strOutput = out.toString(StandardCharsets.UTF_8.name()); Assert.assertEquals("\"42\"", strOutput); } @Test public void testSpecialInteractiveLanguageDirectly() throws UnsupportedEncodingException { ByteArrayOutputStream out = new ByteArrayOutputStream(); PolyglotEngine engine = PolyglotEngine.newBuilder().setOut(out).build(); Source s = Source.newBuilder("").mimeType("application/x-test-specinteract").name("specinteract").interactive().build(); PolyglotEngine.Value value = engine.getLanguages().get("application/x-test-specinteract").eval(s); Assert.assertEquals("42", value.get()); String strOutput = out.toString(StandardCharsets.UTF_8.name()); Assert.assertEquals("\"42\"", strOutput); } @Test public void testDefaultNoninteractiveLanguage() throws UnsupportedEncodingException { ByteArrayOutputStream out = new ByteArrayOutputStream(); PolyglotEngine engine = PolyglotEngine.newBuilder().setOut(out).build(); Source s = Source.newBuilder("").mimeType("application/x-test-definteract").name("defnoninteract").build(); PolyglotEngine.Value value = engine.eval(s); Assert.assertEquals("42", value.get()); String strOutput = out.toString(StandardCharsets.UTF_8.name()); Assert.assertTrue(strOutput.isEmpty()); } @Test public void testSpecialNoninteractiveLanguage() throws UnsupportedEncodingException { ByteArrayOutputStream out = new ByteArrayOutputStream(); PolyglotEngine engine = PolyglotEngine.newBuilder().setOut(out).build(); Source s = Source.newBuilder("").mimeType("application/x-test-specinteract").name("specnoninteract").build(); PolyglotEngine.Value value = engine.eval(s); Assert.assertEquals("42", value.get()); String strOutput = out.toString(StandardCharsets.UTF_8.name()); Assert.assertTrue(strOutput.isEmpty()); } @Test public void isInteractive1() { PolyglotEngine engine = PolyglotEngine.newBuilder().build(); PolyglotEngine.Language language = engine.getLanguages().get("application/x-test-specinteract"); assertFalse("SpecialInteractive language isn't interactive", language.isInteractive()); } @Test public void isInteractive2() { PolyglotEngine engine = PolyglotEngine.newBuilder().build(); PolyglotEngine.Language language = engine.getLanguages().get("application/x-test-definteract"); assertTrue("DefaultInteractive language is interactive", language.isInteractive()); } @Test public void isInteractive3() { PolyglotEngine engine = PolyglotEngine.newBuilder().build(); PolyglotEngine.Language language = engine.getLanguages().get("application/x-test-async"); assertTrue("By default a language is interactive", language.isInteractive()); } private static class InteractiveContext { final Env env; InteractiveContext(Env env) { this.env = env; } String getValue() { return "42"; } } @TruffleLanguage.Registration(name = "DefaultInteractive", mimeType = "application/x-test-definteract", version = "1.0") public static class DefaultInteractiveLanguage extends TruffleLanguage<InteractiveContext> { @Override protected InteractiveContext createContext(Env env) { return new InteractiveContext(env); } @Override protected CallTarget parse(ParsingRequest request) throws Exception { return Truffle.getRuntime().createCallTarget(new RootNode(this) { @Override public Object execute(VirtualFrame frame) { return getContextReference().get().getValue(); } }); } @Override protected Object findExportedSymbol(InteractiveContext context, String globalName, boolean onlyExplicit) { return null; } @Override protected Object getLanguageGlobal(InteractiveContext context) { return null; } @Override protected boolean isObjectOfLanguage(Object object) { return false; } } @TruffleLanguage.Registration(name = "SpecialInteractive", mimeType = "application/x-test-specinteract", version = "1.0", interactive = false) public static class SpecialInteractiveLanguage extends TruffleLanguage<InteractiveContext> { @Override protected InteractiveContext createContext(Env env) { return new InteractiveContext(env); } @Override protected CallTarget parse(ParsingRequest request) throws Exception { Source code = request.getSource(); return Truffle.getRuntime().createCallTarget(new RootNode(this) { @Override public Object execute(VirtualFrame frame) { InteractiveContext ic = getContextReference().get(); Object value = ic.getValue(); if (code.isInteractive()) { try { ic.env.out().write(("\"" + value + "\"").getBytes(StandardCharsets.UTF_8)); } catch (IOException ioex) { return ioex; } } return value; } }); } @Override protected boolean isVisible(InteractiveContext context, Object value) { return false; } @Override protected Object findExportedSymbol(InteractiveContext context, String globalName, boolean onlyExplicit) { return null; } @Override protected Object getLanguageGlobal(InteractiveContext context) { return null; } @Override protected boolean isObjectOfLanguage(Object object) { return false; } } }