From aa1f69f3fb50defdda5aab682275d35be49557fa Mon Sep 17 00:00:00 2001 From: Martin Entlicher Date: Sun, 6 Feb 2022 11:22:23 +0100 Subject: [PATCH] Integration tests of Truffle/Graal scripts debugger. --- .../nbproject/project.properties | 1 + .../nbproject/project.xml | 23 ++ .../jpda/truffle/TruffleDebugManager.java | 5 +- .../impl/TruffleBreakpointsHandler.java | 2 + .../jpda/truffle/DebugAllBaseTest.java | 247 ++++++++++++++++++ .../debugger/jpda/truffle/DebugJSTest.java | 99 +++++++ .../jpda/truffle/DebugPythonTest.java | 87 ++++++ .../debugger/jpda/truffle/DebugRTest.java | 86 ++++++ .../debugger/jpda/truffle/DebugRubyTest.java | 101 +++++++ .../debugger/jpda/truffle/DebugSLTest.java | 193 -------------- .../debugger/jpda/truffle/JPDATestCase.java | 144 ++++++++++ .../debugger/jpda/truffle/PolyglotTest.java | 194 ++++++++++++++ .../TestApp.sl => scripts/DebuggerBase.js} | 35 ++- .../jpda/truffle/scripts/DebuggerBase.py | 49 ++++ .../jpda/truffle/scripts/DebuggerBase.r | 49 ++++ .../jpda/truffle/scripts/DebuggerBase.ruby | 49 ++++ .../debugger/jpda/truffle/scripts/Types.js | 61 +++++ .../debugger/jpda/truffle/scripts/Types.py | 41 +++ .../debugger/jpda/truffle/scripts/Types.r | 41 +++ .../debugger/jpda/truffle/scripts/Types.ruby | 51 ++++ .../debugger/jpda/truffle/scripts/Weather.js | 124 +++++++++ .../debugger/jpda/truffle/scripts/Weather.py | 36 +++ .../debugger/jpda/truffle/scripts/Weather.r | 56 ++++ .../debugger/jpda/truffle/scripts/Weather.rb | 29 ++ ...pFromFile.java => PolyglotWeatherApp.java} | 25 +- .../debugger/jpda/truffle/testapps/SLApp.java | 65 ----- .../jpda/truffle/testapps/WeatherCity.java | 52 ++++ .../truffle/testapps/WeatherCityService.java | 67 +++++ .../backend/truffle/JPDATruffleAccessor.java | 1 + .../api/debugger/jpda/JPDASupport.java | 148 +++++++---- nbbuild/travis/scripting.sh | 2 + 31 files changed, 1839 insertions(+), 324 deletions(-) create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugAllBaseTest.java create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugJSTest.java create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugPythonTest.java create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugRTest.java create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugRubyTest.java delete mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugSLTest.java create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/JPDATestCase.java create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/PolyglotTest.java rename java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/{testapps/TestApp.sl => scripts/DebuggerBase.js} (70%) create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/DebuggerBase.py create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/DebuggerBase.r create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/DebuggerBase.ruby create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Types.js create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Types.py create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Types.r create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Types.ruby create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.js create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.py create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.r create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.rb rename java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/{SLAppFromFile.java => PolyglotWeatherApp.java} (62%) delete mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/SLApp.java create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/WeatherCity.java create mode 100644 java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/WeatherCityService.java diff --git a/java/debugger.jpda.truffle/nbproject/project.properties b/java/debugger.jpda.truffle/nbproject/project.properties index adfab1c044cf..3d3ba965b03d 100644 --- a/java/debugger.jpda.truffle/nbproject/project.properties +++ b/java/debugger.jpda.truffle/nbproject/project.properties @@ -23,4 +23,5 @@ requires.nb.javac=true truffle.sl=external/antlr4-runtime-4.7.2.jar:external/truffle-sl-1.0.0-rc6.jar cp.extra=${tools.jar}:${truffle.sl} test-unit-sys-prop.test.dir.src=${basedir}/test/unit/src/ +test-unit-sys-prop.test.dir.classes=${basedir}/build/test/unit/classes test-unit-sys-prop.netbeans.user=${basedir}/work/nb_user_dir diff --git a/java/debugger.jpda.truffle/nbproject/project.xml b/java/debugger.jpda.truffle/nbproject/project.xml index f15d91317001..3d345abe7907 100644 --- a/java/debugger.jpda.truffle/nbproject/project.xml +++ b/java/debugger.jpda.truffle/nbproject/project.xml @@ -258,13 +258,36 @@ unit + + org.netbeans.core.startup + + + + org.netbeans.libs.freemarker + + + + org.netbeans.libs.javacapi + + org.netbeans.modules.debugger.jpda + + + + + org.netbeans.api.debugger.jpda + + + org.netbeans.libs.junit4 + + org.netbeans.modules.nbjunit + diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/TruffleDebugManager.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/TruffleDebugManager.java index 01f209f961c1..14aa3f012efb 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/TruffleDebugManager.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/TruffleDebugManager.java @@ -146,7 +146,9 @@ private JPDABreakpointListener addPolyglotEngineCreationBP(final JPDADebugger de @Override public void breakpointReached(JPDABreakpointEvent event) { try { - handleEngineBuilder(debugger, event); + if (event.getDebugger() == debugger) { + handleEngineBuilder(debugger, event); + } } finally { event.resume(); } @@ -193,6 +195,7 @@ private void handleEngineBuilder(final JPDADebugger debugger, JPDABreakpointEven builderExitBreakpoint.setBreakpointType(MethodBreakpoint.TYPE_METHOD_EXIT); builderExitBreakpoint.setThreadFilters(debugger, new JPDAThread[]{entryEvent.getThread()}); builderExitBreakpoint.setSuspend(JPDABreakpoint.SUSPEND_EVENT_THREAD); + builderExitBreakpoint.setSession(debugger); builderExitBreakpoint.setHidden(true); builderExitBreakpoint.addJPDABreakpointListener(exitEvent -> { try { diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/TruffleBreakpointsHandler.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/TruffleBreakpointsHandler.java index ce0c05a5e15c..606b9b0cc514 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/TruffleBreakpointsHandler.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/TruffleBreakpointsHandler.java @@ -262,6 +262,7 @@ private ObjectReference setLineBreakpoint(ObjectReference debugManager, setLineBreakpointMethod, args, ObjectReference.INVOKE_SINGLE_THREADED); + ret.disableCollection(); return ret; } catch (VMDisconnectedExceptionWrapper | InternalExceptionWrapper | ClassNotLoadedException | ClassNotPreparedExceptionWrapper | @@ -396,6 +397,7 @@ public void callMethods(JPDAThread thread) throws InvocationException { Exceptions.printStackTrace(ex); } TruffleBreakpointsRegistry.getDefault().remove(debugger, bpImpl); + bpImpl.enableCollection(); } } catch (VMDisconnectedExceptionWrapper ex) {} } diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugAllBaseTest.java b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugAllBaseTest.java new file mode 100644 index 000000000000..8819f0b7bf6e --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugAllBaseTest.java @@ -0,0 +1,247 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.debugger.jpda.truffle; + +import java.io.File; +import java.net.URL; +import junit.framework.Test; + +import org.netbeans.api.debugger.DebuggerManager; +import org.netbeans.api.debugger.jpda.JPDADebugger; +import org.netbeans.api.debugger.jpda.Variable; +import org.netbeans.modules.debugger.jpda.truffle.breakpoints.TruffleLineBreakpoint; +import org.netbeans.modules.debugger.jpda.truffle.frames.TruffleStackFrame; +import org.netbeans.modules.debugger.jpda.truffle.vars.TruffleVariable; +import org.netbeans.modules.debugger.jpda.truffle.vars.impl.TruffleScope; +import org.netbeans.modules.javascript2.debug.breakpoints.JSLineBreakpoint; + +public class DebugAllBaseTest extends JPDATestCase { + + private static final String SCRIPT_NAME = "DebuggerBase"; + private static final String[] SCRIPT_EXTENSIONS = { "js", "py", "r", "ruby" }; + private static final String[] LAUNCHERS = { "js", "graalpython", "Rscript", "ruby" }; + + public DebugAllBaseTest(String name) { + super(name); + } + + public static Test suite() { + return createSuite(DebugAllBaseTest.class); + } + + private void forAllScripts(ThrowableBiConsumer scriptConsumer) { + for (int i = 0; i < LAUNCHERS.length; i++) { + String launcher = LAUNCHERS[i]; + File source = getScriptSourceFile(SCRIPT_NAME + "." + SCRIPT_EXTENSIONS[i]); + try { + scriptConsumer.accept(launcher, source); + } catch (Throwable t) { + throw new AssertionError(launcher + " " + source, t); + } + } + } + + public void testBreakpoints() { + DebuggerManager dm = DebuggerManager.getDebuggerManager(); + forAllScripts((launcher, source) -> { + URL url = source.toURI().toURL(); + JSLineBreakpoint lb1 = new TruffleLineBreakpoint(url, 25); + dm.addBreakpoint(lb1); + JSLineBreakpoint lb2 = new TruffleLineBreakpoint(url, 29); + dm.addBreakpoint(lb2); + String sourcePath = source.getAbsolutePath(); + runScriptUnderJPDA(launcher, source.getAbsolutePath(), support -> { + JPDADebugger debugger = support.getDebugger(); + checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, 25); + support.doContinue(); + support.waitState(JPDADebugger.STATE_STOPPED); + checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, 29); + dm.removeBreakpoint(lb2); + support.doContinue(); + }); + }); + } + + public void testBreakpointsConditional() { + DebuggerManager dm = DebuggerManager.getDebuggerManager(); + forAllScripts((launcher, source) -> { + String and; + switch (launcher) { + case "js": and = "&&"; break; + case "Rscript": and = "&"; break; + default: and = "and"; + } + String condition = "n == 2 " + and + " n1 == 3"; + URL url = source.toURI().toURL(); + JSLineBreakpoint lb = new TruffleLineBreakpoint(url, 35); + lb.setCondition(condition); + dm.addBreakpoint(lb); + String sourcePath = source.getAbsolutePath(); + runScriptUnderJPDA(launcher, source.getAbsolutePath(), support -> { + JPDADebugger debugger = support.getDebugger(); + // The conditional breakpoint is hit two times: + checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, 35); + support.doContinue(); + support.waitState(JPDADebugger.STATE_STOPPED); + checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, 35); + support.doContinue(); + }); + }); + } + + public void testSteps() { + DebuggerManager dm = DebuggerManager.getDebuggerManager(); + forAllScripts((launcher, source) -> { + URL url = source.toURI().toURL(); + String sourcePath = source.getAbsolutePath(); + JSLineBreakpoint lb1 = new TruffleLineBreakpoint(url, 42); + dm.addBreakpoint(lb1); + runScriptUnderJPDA(launcher, source.getAbsolutePath(), support -> { + JPDADebugger debugger = support.getDebugger(); + checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, 42); + support.stepOver(); + checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, 43); + support.stepInto(); + checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, 23); + support.stepOut(); + checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, 43); + support.doContinue(); + }); + }); + } + + public void testEval() { + DebuggerManager dm = DebuggerManager.getDebuggerManager(); + forAllScripts((launcher, source) -> { + URL url = source.toURI().toURL(); + String sourcePath = source.getAbsolutePath(); + JSLineBreakpoint lb1 = new TruffleLineBreakpoint(url, 29); + dm.addBreakpoint(lb1); + runScriptUnderJPDA(launcher, source.getAbsolutePath(), support -> { + JPDADebugger debugger = support.getDebugger(); + checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, 29); + // a = 20 + Variable v = debugger.evaluate("a"); + TruffleVariable tv = TruffleVariable.get(v); + assertTrue(tv.getDisplayValue(), tv.getDisplayValue().contains("20")); + // o.ao = "AO" + String expr; + switch (launcher) { + case "ruby": expr = "o.instance_variable_get :@ao"; break; + case "Rscript": expr = "o[\"ao\"]"; break; + default: expr = "o.ao"; + } + v = debugger.evaluate(expr); + tv = TruffleVariable.get(v); + assertTrue(tv.getDisplayValue(), tv.getDisplayValue().contains("AO")); + // arr[1] + arr[2] + v = debugger.evaluate("arr[1] + arr[2]"); + tv = TruffleVariable.get(v); + String result = launcher.equals("Rscript") ? "9" : "7"; // Arrays start at index 1 in R + assertTrue(tv.getDisplayValue(), tv.getDisplayValue().contains(result)); + support.doContinue(); + }); + }); + } + + public void testLocalVariables() { + DebuggerManager dm = DebuggerManager.getDebuggerManager(); + forAllScripts((launcher, source) -> { + URL url = source.toURI().toURL(); + String sourcePath = source.getAbsolutePath(); + JSLineBreakpoint lb1 = new TruffleLineBreakpoint(url, 23); + dm.addBreakpoint(lb1); + runScriptUnderJPDA(launcher, source.getAbsolutePath(), support -> { + JPDADebugger debugger = support.getDebugger(); + TruffleStackFrame frame = checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, 23); + if (launcher.equals("Rscript") && frame.getScopes().length == 0) { + support.doContinue(); + return; + } + TruffleScope scope = frame.getScopes()[0]; + if (launcher.equals("js")) { + assertNull("a is not visible yet", findVariable(scope, "a")); + assertNull("o is not visible yet", findVariable(scope, "o")); + assertNull("arr is not visible yet", findVariable(scope, "arr")); + } + support.stepOver(); + scope = checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, 24).getScopes()[0]; + assertNotNull("a is visible", findVariable(scope, "a")); + if (launcher.equals("js")) { + assertNull("o is not visible yet", findVariable(scope, "o")); + assertNull("arr is not visible yet", findVariable(scope, "arr")); + } + support.stepOver(); + scope = checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, 25).getScopes()[0]; + assertNotNull("a is visible", findVariable(scope, "a")); + assertNotNull("o is visible", findVariable(scope, "o")); + if (launcher.equals("js")) { + assertNull("arr is not visible yet", findVariable(scope, "arr")); + } + support.stepOver(); + support.stepOver(); + scope = checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, 27).getScopes()[0]; + assertNotNull("a is visible", findVariable(scope, "a")); + assertNotNull("o is visible", findVariable(scope, "o")); + assertNotNull("arr is visible", findVariable(scope, "arr")); + support.doContinue(); + }); + }); + } + + public void testObjectProperties() { + DebuggerManager dm = DebuggerManager.getDebuggerManager(); + forAllScripts((launcher, source) -> { + URL url = source.toURI().toURL(); + String sourcePath = source.getAbsolutePath(); + JSLineBreakpoint lb1 = new TruffleLineBreakpoint(url, 29); + dm.addBreakpoint(lb1); + runScriptUnderJPDA(launcher, source.getAbsolutePath(), support -> { + JPDADebugger debugger = support.getDebugger(); + TruffleStackFrame frame = checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, 29); + TruffleVariable o = findVariable(frame.getScopes()[0], "o"); + assertNotNull("Variable o not found!", o); + Object[] children = o.getChildren(); + String aoName = launcher.equals("ruby") ? "@ao" : "ao"; + boolean hasAO = false; + for (Object ch : children) { + if (ch instanceof TruffleVariable && ((TruffleVariable) ch).getName().equals(aoName)) { + hasAO = true; + break; + } + } + StringBuilder chstr = new StringBuilder("(" + children.length + ")"); + if (!hasAO) { + for (Object ch : children) { + chstr.append(ch.getClass().getName()); + chstr.append('{'); + if (ch instanceof TruffleVariable) { + chstr.append(((TruffleVariable) ch).getName()); + chstr.append(": "); + chstr.append(((TruffleVariable) ch).getValue()); + } + chstr.append('}'); + } + } + assertTrue("AO child was not found, children = " + chstr, hasAO); + support.doContinue(); + }); + }); + } +} diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugJSTest.java b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugJSTest.java new file mode 100644 index 000000000000..f2707811e60b --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugJSTest.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.debugger.jpda.truffle; + +import java.io.File; +import junit.framework.Test; +import static junit.framework.TestCase.assertEquals; + +import org.netbeans.api.debugger.DebuggerManager; +import org.netbeans.api.debugger.jpda.JPDADebugger; +import org.netbeans.modules.debugger.jpda.truffle.frames.TruffleStackFrame; +import org.netbeans.modules.debugger.jpda.truffle.vars.TruffleVariable; +import org.netbeans.modules.debugger.jpda.truffle.vars.impl.TruffleScope; + +public class DebugJSTest extends JPDATestCase { + + public DebugJSTest(String name) { + super(name); + } + + public static Test suite() { + return createSuite(DebugJSTest.class); + } + + public void testJSTypes() throws Exception { + DebuggerManager dm = DebuggerManager.getDebuggerManager(); + File source = new File(sourceRoot, "org/netbeans/modules/debugger/jpda/truffle/scripts/Types.js"); + String sourcePath = source.getAbsolutePath(); + int debugLine = 51; + String methodName = "typesTest"; + runScriptUnderJPDA("js", source.getAbsolutePath(), support -> { + JPDADebugger debugger = support.getDebugger(); + TruffleStackFrame frame = checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, debugLine); + assertEquals("Bad method name", methodName, frame.getMethodName()); + checkVariableTypes(frame.getScopes()); + support.doContinue(); + }); + } + + private static void checkVariableTypes(TruffleScope[] scopes) { + assertEquals(1, scopes.length); + TruffleVariable[] variables = scopes[0].getVariables(); + assertEquals("this", variables[0].getName()); + checkVar(variables[1], "a1", "Array", "[]"); + checkVar(variables[2], "a2", "Array", "(3)[1, 2, [3, 4]]"); + + checkVar(variables[3], "b1", "boolean", "true"); + checkVar(variables[4], "b2", "boolean", "false"); + + checkVar(variables[5], "c1", "TestClass", "{}"); + + checkVar(variables[6], "i1", "number", "0"); + checkVar(variables[7], "i2", "number", "42"); + checkVar(variables[8], "i3", "number", "42.42"); + checkVar(variables[9], "i4", "number", "-0"); + checkVar(variables[10], "i5", "number", "-Infinity"); + checkVar(variables[11], "i6", "number", "Infinity"); + checkVar(variables[12], "i7", "number", "-Infinity"); + checkVar(variables[13], "i8", "number", "NaN"); + + checkVar(variables[14], "aSparse", "Array", null/*"(11)[1, 2, empty × 8, 10]"*/); + assertTrue(variables[14].getValue().toString(), variables[14].getValue().toString().startsWith("(11)[")); // Do not rely on the exact format + checkVar(variables[15], "s1", "string", "String"); + checkVar(variables[16], "f1", "pow2", null); + assertTrue(variables[16].getValue().toString(), variables[16].getValue().toString().startsWith("function pow2(x)")); + checkVar(variables[17], "d1", "Date", null); + checkVar(variables[18], "undef", "undefined", "undefined"); + checkVar(variables[19], "nul", "null", "null"); + checkVar(variables[20], "sy", "symbol", "Symbol(symbolic)"); + checkVar(variables[21], "o1", "Object", "{}"); + checkVar(variables[22], "o2", "TestFncProp", "{fncProp: \"Property\", a: \"A\"}"); + checkVar(variables[23], "map", "Map", null); + } + + private static void checkVar(TruffleVariable variable, String name, String type, String value) { + assertEquals("Name", name, variable.getName()); + assertEquals("Type of " + name, type, variable.getType()); + if (value != null) { + assertEquals("Value of " + name, value, variable.getValue()); + } + } + +} diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugPythonTest.java b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugPythonTest.java new file mode 100644 index 000000000000..7f1b1a0b7731 --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugPythonTest.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.debugger.jpda.truffle; + +import java.io.File; +import java.net.URL; +import junit.framework.Test; +import static junit.framework.TestCase.assertEquals; + +import org.netbeans.api.debugger.DebuggerManager; +import org.netbeans.api.debugger.jpda.JPDADebugger; +import org.netbeans.modules.debugger.jpda.truffle.breakpoints.TruffleLineBreakpoint; +import org.netbeans.modules.debugger.jpda.truffle.frames.TruffleStackFrame; +import org.netbeans.modules.debugger.jpda.truffle.vars.TruffleVariable; +import org.netbeans.modules.debugger.jpda.truffle.vars.impl.TruffleScope; +import org.netbeans.modules.javascript2.debug.breakpoints.JSLineBreakpoint; + +public class DebugPythonTest extends JPDATestCase { + + public DebugPythonTest(String name) { + super(name); + } + + public static Test suite() { + return createSuite(DebugPythonTest.class); + } + + public void testPythonTypes() throws Exception { + DebuggerManager dm = DebuggerManager.getDebuggerManager(); + File source = new File(sourceRoot, "org/netbeans/modules/debugger/jpda/truffle/scripts/Types.py"); + URL url = source.toURI().toURL(); + String sourcePath = source.getAbsolutePath(); + int debugLine = 39; + String methodName = "typesTest"; + JSLineBreakpoint lb1 = new TruffleLineBreakpoint(url, debugLine); + dm.addBreakpoint(lb1); + runScriptUnderJPDA("graalpython", source.getAbsolutePath(), support -> { + JPDADebugger debugger = support.getDebugger(); + TruffleStackFrame frame = checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, debugLine); + assertEquals("Bad method name", methodName, frame.getMethodName()); + checkVariableTypes(frame.getScopes()); + support.doContinue(); + }); + } + + private static void checkVariableTypes(TruffleScope[] scopes) { + assertTrue(scopes.length >= 1); + TruffleVariable[] variables = scopes[0].getVariables(); + checkVar(variables[0], "a", "list", "[1, 2, 3, 42]"); + + checkVar(variables[1], "b1", "bool", "True"); + checkVar(variables[2], "b2", "bool", "False"); + + checkVar(variables[3], "i", "int", "42"); + checkVar(variables[4], "s", "str", "'string'"); + checkVar(variables[5], "n", "NoneType", "None"); + checkVar(variables[6], "f", "function", null); + assertTrue(variables[6].getValue().toString(), variables[6].getValue().toString().contains("Callable")); + checkVar(variables[7], "d", "datetime", null); + checkVar(variables[8], "map", "dict", null); + } + + private static void checkVar(TruffleVariable variable, String name, String type, String value) { + assertEquals("Name", name, variable.getName()); + assertEquals("Type of " + name, type, variable.getType()); + if (value != null) { + assertEquals("Value of " + name, value, variable.getValue()); + } + } + +} diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugRTest.java b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugRTest.java new file mode 100644 index 000000000000..c209c55cb373 --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugRTest.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.debugger.jpda.truffle; + +import java.io.File; +import java.net.URL; +import junit.framework.Test; +import static junit.framework.TestCase.assertEquals; + +import org.netbeans.api.debugger.DebuggerManager; +import org.netbeans.api.debugger.jpda.JPDADebugger; +import org.netbeans.modules.debugger.jpda.truffle.breakpoints.TruffleLineBreakpoint; +import org.netbeans.modules.debugger.jpda.truffle.frames.TruffleStackFrame; +import org.netbeans.modules.debugger.jpda.truffle.vars.TruffleVariable; +import org.netbeans.modules.debugger.jpda.truffle.vars.impl.TruffleScope; +import org.netbeans.modules.javascript2.debug.breakpoints.JSLineBreakpoint; + +public class DebugRTest extends JPDATestCase { + + public DebugRTest(String name) { + super(name); + } + + public static Test suite() { + return createSuite(DebugRTest.class); + } + + public void testRTypes() throws Exception { + DebuggerManager dm = DebuggerManager.getDebuggerManager(); + File source = new File(sourceRoot, "org/netbeans/modules/debugger/jpda/truffle/scripts/Types.r"); + URL url = source.toURI().toURL(); + String sourcePath = source.getAbsolutePath(); + int debugLine = 38; + String methodName = "typesTest"; + JSLineBreakpoint lb1 = new TruffleLineBreakpoint(url, debugLine); + dm.addBreakpoint(lb1); + runScriptUnderJPDA("Rscript", source.getAbsolutePath(), support -> { + JPDADebugger debugger = support.getDebugger(); + TruffleStackFrame frame = checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, debugLine); + assertTrue("Bad method name: " + frame.getMethodName(), frame.getMethodName().contains(methodName)); + checkVariableTypes(frame.getScopes()); + support.doContinue(); + }); + } + + private static void checkVariableTypes(TruffleScope[] scopes) { + assertEquals(1, scopes.length); + TruffleVariable[] variables = scopes[0].getVariables(); + + checkVar(variables[0], "a", "double", "[1] 1 2 3 42"); + checkVar(variables[1], "b1", "logical", "[1] TRUE"); + checkVar(variables[2], "b2", "logical", "[1] FALSE"); + + checkVar(variables[3], "i", "double", "[1] 42"); + checkVar(variables[4], "s", "character", "[1] \"string\""); + checkVar(variables[5], "n", "NULL", "NULL"); + checkVar(variables[6], "f", "closure", "function() {\n\n}"); + checkVar(variables[7], "d", "double", null); + checkVar(variables[8], "map", "environment", null); + } + + private static void checkVar(TruffleVariable variable, String name, String type, String value) { + assertEquals("Name", name, variable.getName()); + assertEquals("Type of " + name, type, variable.getType()); + if (value != null) { + assertEquals("Value of " + name, value, variable.getValue()); + } + } + +} diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugRubyTest.java b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugRubyTest.java new file mode 100644 index 000000000000..1f253c6a66ec --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugRubyTest.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.debugger.jpda.truffle; + +import java.io.File; +import java.net.URL; +import junit.framework.Test; +import static junit.framework.TestCase.assertEquals; + +import org.netbeans.api.debugger.DebuggerManager; +import org.netbeans.api.debugger.jpda.JPDADebugger; +import org.netbeans.modules.debugger.jpda.truffle.breakpoints.TruffleLineBreakpoint; +import org.netbeans.modules.debugger.jpda.truffle.frames.TruffleStackFrame; +import org.netbeans.modules.debugger.jpda.truffle.vars.TruffleVariable; +import org.netbeans.modules.debugger.jpda.truffle.vars.impl.TruffleScope; +import org.netbeans.modules.javascript2.debug.breakpoints.JSLineBreakpoint; + +public class DebugRubyTest extends JPDATestCase { + + public DebugRubyTest(String name) { + super(name); + } + + public static Test suite() { + return createSuite(DebugRubyTest.class); + } + + public void testRubyTypes() throws Exception { + DebuggerManager dm = DebuggerManager.getDebuggerManager(); + File source = new File(sourceRoot, "org/netbeans/modules/debugger/jpda/truffle/scripts/Types.ruby"); + URL url = source.toURI().toURL(); + String sourcePath = source.getAbsolutePath(); + int debugLine = 46; + String methodName = "typesTest"; + JSLineBreakpoint lb1 = new TruffleLineBreakpoint(url, debugLine); + dm.addBreakpoint(lb1); + runScriptUnderJPDA("ruby", source.getAbsolutePath(), support -> { + JPDADebugger debugger = support.getDebugger(); + TruffleStackFrame frame = checkStoppedAtScript(debugger.getCurrentThread(), sourcePath, debugLine); + assertTrue("Bad method name: " + frame.getMethodName(), frame.getMethodName().contains(methodName)); + checkVariableTypes(frame.getScopes()); + support.doContinue(); + }); + } + + private static void checkVariableTypes(TruffleScope[] scopes) { + assertEquals(1, scopes.length); + TruffleVariable[] variables = scopes[0].getVariables(); + assertEquals("self", variables[0].getName()); + checkVar(variables[1], "a1", "Array", "[]"); + checkVar(variables[2], "a2", "Array", "[1, 2, [3, 4]]"); + + checkVar(variables[3], "b1", "", "true"); + checkVar(variables[4], "b2", "", "false"); + + checkVar(variables[5], "null", "NilClass", "nil"); + + checkVar(variables[6], "i1", "", "0"); + checkVar(variables[7], "i2", "", "42"); + checkVar(variables[8], "i3", "", "42.42"); + checkVar(variables[9], "i4", "", "-0.0"); + checkVar(variables[10], "i5", "", "-Infinity"); + checkVar(variables[11], "i6", "", "Infinity"); + checkVar(variables[12], "i7", "", "-Infinity"); + checkVar(variables[13], "i8", "", "NaN"); + + checkVar(variables[14], "nc", "Complex", "(2+3i)"); + checkVar(variables[15], "nr", "Rational", "(11/2)"); + checkVar(variables[16], "f", "Method", null); + assertTrue(variables[16].getValue().toString(), variables[16].getValue().toString().contains("Callable")); + checkVar(variables[17], "d", "Time", null); + checkVar(variables[18], "str", "String", "\"A String\""); + checkVar(variables[19], "symbol", "Symbol", ":symbolic"); + checkVar(variables[20], "hash", "Hash", "{:a=>1, \"b\"=>2}"); + } + + private static void checkVar(TruffleVariable variable, String name, String type, String value) { + assertEquals("Name", name, variable.getName()); + assertEquals("Type of " + name, type, variable.getType()); + if (value != null) { + assertEquals("Value of " + name, value, variable.getValue()); + } + } + +} diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugSLTest.java b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugSLTest.java deleted file mode 100644 index 94e0f43f8d7c..000000000000 --- a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugSLTest.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.netbeans.modules.debugger.jpda.truffle; - -import com.oracle.truffle.api.TruffleLanguage; -import com.oracle.truffle.sl.SLLanguage; -import java.io.File; -import java.lang.reflect.Field; -import java.net.URISyntaxException; -import java.net.URL; -import junit.framework.Test; -import junit.framework.TestCase; -import org.graalvm.polyglot.Engine; -import org.netbeans.api.debugger.DebuggerManager; -import org.netbeans.api.debugger.jpda.CallStackFrame; -import org.netbeans.api.debugger.jpda.JPDADebugger; -import org.netbeans.api.debugger.jpda.JPDASupport; -import org.netbeans.api.debugger.jpda.LineBreakpoint; -import org.netbeans.junit.NbTestCase; -import org.netbeans.modules.debugger.jpda.truffle.access.CurrentPCInfo; -import org.netbeans.modules.debugger.jpda.truffle.access.TruffleAccess; -import org.netbeans.modules.debugger.jpda.truffle.access.TruffleStrataProvider; -import org.netbeans.modules.debugger.jpda.truffle.breakpoints.TruffleLineBreakpoint; -import org.netbeans.modules.debugger.jpda.truffle.frames.TruffleStackFrame; -import org.netbeans.modules.debugger.jpda.truffle.source.SourcePosition; -import org.netbeans.modules.javascript2.debug.EditorLineHandlerFactory; -import org.openide.filesystems.FileObject; -import org.openide.filesystems.URLMapper; - -public class DebugSLTest extends NbTestCase { - private DebuggerManager dm = DebuggerManager.getDebuggerManager(); - private final String sourceRoot = System.getProperty("test.dir.src"); - private JPDASupport support; - - public DebugSLTest(String name) { - super(name); - } - - public static Test suite() throws URISyntaxException { - final File sdkAPI = new File(Engine.class.getProtectionDomain().getCodeSource().getLocation().toURI()); - final File truffleAPI = new File(TruffleLanguage.class.getProtectionDomain().getCodeSource().getLocation().toURI()); - final File sl = new File(SLLanguage.class.getProtectionDomain().getCodeSource().getLocation().toURI()); - final File antlr4 = new File(org.antlr.v4.runtime.Parser.class.getProtectionDomain().getCodeSource().getLocation().toURI()); - final File junit = new File(TestCase.class.getProtectionDomain().getCodeSource().getLocation().toURI()); - assertTrue("SDK API exists: " + sdkAPI, sdkAPI.exists()); - assertTrue("truffle-api JAR exists: " + truffleAPI, truffleAPI.exists()); - assertTrue("sl JAR exists: " + sl, sl.exists()); - assertTrue("antlr4 JAR exists: " + antlr4, antlr4.exists()); - assertTrue("junit JAR exists: " + junit, junit.exists()); - - System.setProperty("graal-sdk.jar", sdkAPI.getAbsolutePath()); - System.setProperty("truffle.jar", truffleAPI.getAbsolutePath()); - System.setProperty("sl.jar", sl.getAbsolutePath()); - System.setProperty("antlr4.jar", antlr4.getAbsolutePath()); - System.setProperty("junit.jar", junit.getAbsolutePath()); - - return JPDASupport.createTestSuite(DebugSLTest.class); - } - - public void testStepIntoMainSL() throws Exception { - doStepIntoSL(0, "main", 2); - } - - public void testStepIntoInvokeAs() throws Exception { - doStepIntoSL(1, "init", 7); - } - - public void testStepIntoDynamicInterface() throws Exception { - doStepIntoSL(2, "main", 2); - } - - private void doStepIntoSL(int bpNum, String methodName, int lineNo) throws Exception { - try { - JPDASupport.removeAllBreakpoints(); - org.netbeans.api.debugger.jpda.Utils.BreakPositions bp = org.netbeans.api.debugger.jpda.Utils.getBreakPositions( - sourceRoot - + "org/netbeans/modules/debugger/jpda/truffle/testapps/SLApp.java"); - LineBreakpoint lb = bp.getLineBreakpoints().get(bpNum); - dm.addBreakpoint(lb); - support = JPDASupport.attach("org.netbeans.modules.debugger.jpda.truffle.testapps.SLApp", - new String[0], - new File[] { - new File(System.getProperty("graal-sdk.jar")), - new File(System.getProperty("truffle.jar")), - new File(System.getProperty("antlr4.jar")), - new File(System.getProperty("sl.jar")), - new File(System.getProperty("junit.jar")), - } - ); - support.waitState(JPDADebugger.STATE_STOPPED); - support.stepInto(); - final JPDADebugger debugger = support.getDebugger(); - CallStackFrame frame = debugger.getCurrentCallStackFrame(); - assertNotNull(frame); - // Check that frame is in the Truffle access method - String haltedClass = TruffleAccess.BASIC_CLASS_NAME; - Field haltedMethodField = TruffleAccess.class.getDeclaredField("METHOD_EXEC_HALTED"); - haltedMethodField.setAccessible(true); - String haltedMethod = (String) haltedMethodField.get(null); - /* Debug where it's stopped at: - System.err.println("Stopped in "+frame.getClassName()+"."+frame.getMethodName()+"()"); - CallStackFrame[] callStack = frame.getThread().getCallStack(); - for (CallStackFrame sf : callStack) { - System.err.println(" at "+sf.getClassName()+"."+sf.getMethodName()+"():"+sf.getLineNumber(null)+" stratum: "+sf.getDefaultStratum()); - }*/ - assertEquals("Stopped in Truffle halted class", haltedClass, frame.getClassName()); - assertEquals("Stopped in Truffle halted method", haltedMethod, frame.getMethodName()); - assertEquals("Unexpected stratum", TruffleStrataProvider.TRUFFLE_STRATUM, frame.getDefaultStratum()); - - CurrentPCInfo currentPCInfo = TruffleAccess.getCurrentPCInfo(frame.getThread()); - assertNotNull("Missing CurrentPCInfo", currentPCInfo); - TruffleStackFrame topFrame = currentPCInfo.getTopFrame(); - assertNotNull("No top frame", topFrame); - SourcePosition sourcePosition = topFrame.getSourcePosition(); - assertEquals("Bad source", "Meaning of world.sl", sourcePosition.getSource().getName()); - assertEquals("Bad line", lineNo, sourcePosition.getStartLine()); - assertEquals("Bad method name", methodName, topFrame.getMethodName()); - - support.doContinue(); - support.waitState(JPDADebugger.STATE_DISCONNECTED); - } finally { - if (support != null) { - support.doFinish(); - } - } - } - - public void testBreakpointsInSL() throws Exception { - try { - JPDASupport.removeAllBreakpoints(); - org.netbeans.api.debugger.jpda.Utils.BreakPositions bp = org.netbeans.api.debugger.jpda.Utils.getBreakPositions( - sourceRoot - + "org/netbeans/modules/debugger/jpda/truffle/testapps/TestApp.sl"); - LineBreakpoint lb = bp.getLineBreakpoints().get(0); - // An ugly way to transform the Java breakpoint into Truffle breakpoint, used in SL. - FileObject fo = URLMapper.findFileObject(new URL(lb.getURL())); - dm.addBreakpoint(new TruffleLineBreakpoint(EditorLineHandlerFactory.getHandler(fo, lb.getLineNumber()))); - support = JPDASupport.attach("org.netbeans.modules.debugger.jpda.truffle.testapps.SLAppFromFile", - new String[] { - sourceRoot + "org/netbeans/modules/debugger/jpda/truffle/testapps/TestApp.sl" - }, - new File[] { - new File(System.getProperty("graal-sdk.jar")), - new File(System.getProperty("truffle.jar")), - new File(System.getProperty("antlr4.jar")), - new File(System.getProperty("sl.jar")), - new File(System.getProperty("junit.jar")), - } - ); - support.waitState(JPDADebugger.STATE_STOPPED); - - final JPDADebugger debugger = support.getDebugger(); - CallStackFrame frame = debugger.getCurrentCallStackFrame(); - assertNotNull(frame); - // Check that frame is in the Truffle guest language - assertEquals("Unexpected stratum", TruffleStrataProvider.TRUFFLE_STRATUM, frame.getDefaultStratum()); - - CurrentPCInfo currentPCInfo = TruffleAccess.getCurrentPCInfo(frame.getThread()); - assertNotNull("Missing CurrentPCInfo", currentPCInfo); - TruffleStackFrame topFrame = currentPCInfo.getTopFrame(); - assertNotNull("No top frame", topFrame); - SourcePosition sourcePosition = topFrame.getSourcePosition(); - assertEquals("Bad source", "TestApp.sl", sourcePosition.getSource().getName()); - assertEquals("Bad line", lb.getLineNumber(), sourcePosition.getStartLine()); - assertEquals("Bad method name", "main", topFrame.getMethodName()); - - support.doContinue(); - support.waitState(JPDADebugger.STATE_DISCONNECTED); - } finally { - if (support != null) { - support.doFinish(); - } - } - } - -} diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/JPDATestCase.java b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/JPDATestCase.java new file mode 100644 index 000000000000..b22939ab99be --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/JPDATestCase.java @@ -0,0 +1,144 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.debugger.jpda.truffle; + +import java.io.File; +import java.util.logging.Level; +import junit.framework.Test; +import junit.framework.TestCase; +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertNotNull; +import org.netbeans.api.debugger.jpda.JPDADebugger; +import org.netbeans.api.debugger.jpda.JPDASupport; +import org.netbeans.api.debugger.jpda.JPDAThread; +import org.netbeans.junit.NbModuleSuite; +import org.netbeans.junit.NbTestCase; +import org.netbeans.modules.debugger.jpda.truffle.access.CurrentPCInfo; +import org.netbeans.modules.debugger.jpda.truffle.access.TruffleAccess; +import org.netbeans.modules.debugger.jpda.truffle.frames.TruffleStackFrame; +import org.netbeans.modules.debugger.jpda.truffle.source.SourceBinaryTranslator; +import org.netbeans.modules.debugger.jpda.truffle.source.SourcePosition; +import org.netbeans.modules.debugger.jpda.truffle.vars.TruffleVariable; +import org.netbeans.modules.debugger.jpda.truffle.vars.impl.TruffleScope; +import org.openide.filesystems.FileUtil; +import org.openide.util.Utilities; + +public abstract class JPDATestCase extends NbTestCase { + + protected final File sourceRoot = new File(System.getProperty("test.dir.src")); + + protected static Test createSuite(Class clazz) { + return NbModuleSuite.createConfiguration(clazz). + gui(false). + failOnException(Level.INFO). + enableClasspathModules(false). + clusters(".*"). + suite(); + } + + public JPDATestCase(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + JPDASupport.removeAllBreakpoints(); + super.setUp(); + } + + protected String getBinariesPath(String sourcesPath) { + return Utilities.toFile(SourceBinaryTranslator.source2Binary(FileUtil.toFileObject(new File(sourcesPath)))).getAbsolutePath(); + } + + protected final File getScriptSourceFile(String scriptName) { + String scriptPath = "org/netbeans/modules/debugger/jpda/truffle/scripts/" + scriptName; + scriptPath = scriptPath.replace('/', File.separatorChar); + return new File(sourceRoot, scriptPath); + } + + protected final File getJavaSourceFile(String javaFileName) { + String sourcePath = "org/netbeans/modules/debugger/jpda/truffle/testapps/" + javaFileName; + sourcePath = sourcePath.replace('/', File.separatorChar); + return new File(sourceRoot, sourcePath); + } + + protected final void runScriptUnderJPDA(String launcher, String scriptPath, ThrowableConsumer supportConsumer) throws Exception { + // Translate script path from source dir to target dir: + scriptPath = getBinariesPath(scriptPath); + JPDASupport support = JPDASupport.attachScript(launcher, scriptPath); + run(support, supportConsumer, false); + } + + protected final void runJavaUnderJPDA(String mainClass, ThrowableConsumer supportConsumer) throws Exception { + JPDASupport support = JPDASupport.attach(mainClass); + run(support, supportConsumer, false); + } + + private void run(JPDASupport support, ThrowableConsumer supportConsumer, boolean resume) throws Exception { + try { + support.waitState(JPDADebugger.STATE_STOPPED); + if (resume) { + support.doContinue(); + support.waitState(JPDADebugger.STATE_STOPPED); + } + supportConsumer.accept(support); + support.waitState(JPDADebugger.STATE_DISCONNECTED); + } catch (Throwable t) { + // Report any exception just in case the finally block does not finish cleanly + t.printStackTrace(); + throw t; + } finally { + support.doFinish(); + } + } + + protected TruffleStackFrame checkStoppedAtScript(JPDAThread thread, String sourcePath, int line) { + CurrentPCInfo currentPCInfo = TruffleAccess.getCurrentPCInfo(thread); + assertNotNull("Missing CurrentPCInfo, suspended at " + thread.getClassName() + "." + thread.getMethodName(), currentPCInfo); + TruffleStackFrame topFrame = currentPCInfo.getTopFrame(); + assertNotNull("No top frame", topFrame); + SourcePosition sourcePosition = topFrame.getSourcePosition(); + if (sourcePath != null && new File(sourcePath).isAbsolute()) { + assertEquals("Bad source", getBinariesPath(sourcePath), sourcePosition.getSource().getPath()); + } + assertEquals("Bad line", line, sourcePosition.getStartLine()); + return topFrame; + } + + protected static TruffleVariable findVariable(TruffleScope scope, String name) { + for (TruffleVariable var : scope.getVariables()) { + if (var.getName().equals(name)) { + return var; + } + } + return null; + } + + @FunctionalInterface + protected interface ThrowableConsumer { + + void accept(T t) throws Exception; + } + + @FunctionalInterface + protected interface ThrowableBiConsumer { + + void accept(T t, U u) throws Exception; + } +} diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/PolyglotTest.java b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/PolyglotTest.java new file mode 100644 index 000000000000..36e90b81252c --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/PolyglotTest.java @@ -0,0 +1,194 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.debugger.jpda.truffle; + +import java.io.File; +import junit.framework.Test; +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertNotNull; + +import org.netbeans.api.debugger.ActionsManager; +import org.netbeans.api.debugger.DebuggerManager; +import org.netbeans.api.debugger.jpda.CallStackFrame; +import org.netbeans.api.debugger.jpda.JPDADebugger; +import org.netbeans.api.debugger.jpda.LineBreakpoint; +import org.netbeans.modules.debugger.jpda.truffle.frames.TruffleStackFrame; +import org.netbeans.modules.debugger.jpda.truffle.vars.TruffleVariable; + +public class PolyglotTest extends JPDATestCase { + + private static final String ACTION_PAUSE_IN_GRAAL = "pauseInGraalScript"; + + public PolyglotTest(String name) { + super(name); + } + + public static Test suite() { + return createSuite(PolyglotTest.class); + } + + @Override // The app loads scripts from the compiled classes location always + protected String getBinariesPath(String sourcesPath) { + String classesDir = System.getProperty("test.dir.classes"); + if (classesDir == null) { + return super.getBinariesPath(sourcesPath); + } + String base = sourceRoot.getAbsolutePath(); + if (!sourcesPath.startsWith(base)) { + return sourcesPath; + } + String relPath = sourcesPath.substring(base.length()); + while (relPath.startsWith(File.separator)) { + relPath = relPath.substring(File.separator.length()); + } + return new File(classesDir, relPath).getAbsolutePath(); + } + + public void testWeatherApp() throws Exception { + DebuggerManager dm = DebuggerManager.getDebuggerManager(); + String sourcePathJS = getScriptSourceFile("Weather.js").getAbsolutePath(); + String sourcePathPython = getScriptSourceFile("Weather.py").getAbsolutePath(); + String sourcePathR = "org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.r"; // relative path in R + LineBreakpoint lb = LineBreakpoint.create(getJavaSourceFile("PolyglotWeatherApp.java").toURI().toURL().toString(), 30); + dm.addBreakpoint(lb); + runJavaUnderJPDA("org.netbeans.modules.debugger.jpda.truffle.testapps.PolyglotWeatherApp", support -> { + final JPDADebugger debugger = support.getDebugger(); + CallStackFrame frame = debugger.getCurrentCallStackFrame(); + assertEquals(30, frame.getLineNumber(null)); + dm.removeBreakpoint(lb); + ActionsManager actions = DebuggerManager.getDebuggerManager().getCurrentEngine().getActionsManager(); + assertFalse("Pause in Graal Script not enabled initially", actions.isEnabled(ACTION_PAUSE_IN_GRAAL)); + support.stepOver(); + assertTrue("Pause in Graal Script enabled after Engine creation", actions.isEnabled(ACTION_PAUSE_IN_GRAAL)); + support.stepOver(); + frame = debugger.getCurrentCallStackFrame(); + assertEquals(32, frame.getLineNumber(null)); + support.stepOver(); + frame = debugger.getCurrentCallStackFrame(); + assertEquals(33, frame.getLineNumber(null)); + actions.doAction(ACTION_PAUSE_IN_GRAAL); + support.doContinue(); + support.waitState(JPDADebugger.STATE_STOPPED); + + // We should be suspended in the JavaScript + TruffleStackFrame tframe = checkStoppedAtScript(debugger.getCurrentThread(), sourcePathJS, 124); + assertEquals("JavaScript", tframe.getLanguage().getName()); + support.stepInto(); + checkStoppedAtScript(debugger.getCurrentThread(), sourcePathJS, 23); + support.stepOver(); // loading Ruby + support.stepOver(); + tframe = checkStoppedAtScript(debugger.getCurrentThread(), sourcePathJS, 26); + TruffleVariable rubyWeather = findVariable(tframe.getScopes()[0], "Weather"); + assertNotNull("Weather variable", rubyWeather); + assertEquals("Ruby", rubyWeather.getLanguage().getName()); + assertEquals("Weather", rubyWeather.getValue()); + support.stepOver(); + support.stepOver(); + //support.stepOver(); + checkStoppedAtScript(debugger.getCurrentThread(), sourcePathJS, 32); + support.stepOver(); // loading R + checkStoppedAtScript(debugger.getCurrentThread(), sourcePathJS, 35); + support.stepOver(); + support.stepOver(); + support.stepOver(); + tframe = checkStoppedAtScript(debugger.getCurrentThread(), sourcePathJS, 40); + TruffleVariable createModel = findVariable(tframe.getScopes()[0], "createModel"); + assertEquals("R", createModel.getLanguage().getName()); + assertEquals("closure", createModel.getType()); + support.stepOver(); // loading Python + support.stepOver(); + tframe = checkStoppedAtScript(debugger.getCurrentThread(), sourcePathJS, 58); + TruffleVariable purchase = findVariable(tframe.getScopes()[0], "Purchase"); + assertEquals("Python", purchase.getLanguage().getName()); + assertEquals("function", purchase.getType()); + support.stepOver(); + support.stepOver(); + tframe = checkStoppedAtScript(debugger.getCurrentThread(), sourcePathJS, 61); + TruffleVariable cities = findVariable(tframe.getScopes()[0], "cities"); + assertEquals("Host", cities.getLanguage().getName()); + support.stepOver(); + support.stepOver(); + support.stepInto(); + tframe = checkStoppedAtScript(debugger.getCurrentThread(), sourcePathJS, 79); + assertEquals("updateModel", tframe.getMethodName()); + support.stepOver(); + support.stepOver(); + support.stepOver(); + support.stepOver(); + + // Calling into R: + support.stepInto(); + tframe = checkStoppedAtScript(debugger.getCurrentThread(), sourcePathR, 27); + assertEquals("R", tframe.getLanguage().getName()); + assertEquals("createModel", tframe.getMethodName()); + TruffleVariable getName = findVariable(tframe.getScopes()[0], "getName"); + assertEquals("JavaScript", getName.getLanguage().getName()); + support.stepOver(); + support.stepOver(); + checkStoppedAtScript(debugger.getCurrentThread(), sourcePathR, 33); + support.stepOver(); + + // Back in JavaScript: + tframe = checkStoppedAtScript(debugger.getCurrentThread(), sourcePathJS, 92); + assertEquals("JavaScript", tframe.getLanguage().getName()); + support.stepOver(); + support.stepOver(); + tframe = checkStoppedAtScript(debugger.getCurrentThread(), sourcePathJS, 97); + TruffleVariable model = findVariable(tframe.getScopes()[0], "model"); + assertEquals("R", model.getLanguage().getName()); + support.stepOver(); + tframe = checkStoppedAtScript(debugger.getCurrentThread(), sourcePathJS, 98); + TruffleVariable numCities = findVariable(tframe.getScopes()[0], "numCities"); + assertEquals("number", numCities.getType()); + assertEquals("5", numCities.getValue()); + support.stepOver(); + support.stepOver(); + support.stepOver(); + support.stepOver(); + + // Calling into Ruby: + support.stepInto(); + tframe = checkStoppedAtScript(debugger.getCurrentThread(), null, 22); // In an eval script + assertEquals("Ruby", tframe.getLanguage().getName()); + support.stepOut(); + + // Back in JavaScript + tframe = checkStoppedAtScript(debugger.getCurrentThread(), sourcePathJS, 103); + support.stepOver(); + tframe = checkStoppedAtScript(debugger.getCurrentThread(), sourcePathJS, 106); + + // Calling into Python: + support.stepInto(); + tframe = checkStoppedAtScript(debugger.getCurrentThread(), null, 4); // In an eval script + assertEquals("Python", tframe.getLanguage().getName()); + support.stepOver(); + support.stepInto(); + tframe = checkStoppedAtScript(debugger.getCurrentThread(), null, 9); // In an eval script + assertEquals("fruits", tframe.getMethodName()); + support.stepOut(); + support.stepOut(); + + // Back in JavaScript + tframe = checkStoppedAtScript(debugger.getCurrentThread(), sourcePathJS, 106); + assertEquals("JavaScript", tframe.getLanguage().getName()); + + support.doContinue(); + }); + } +} diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/TestApp.sl b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/DebuggerBase.js similarity index 70% rename from java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/TestApp.sl rename to java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/DebuggerBase.js index 6d1100675fb9..aaae1fad54da 100644 --- a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/TestApp.sl +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/DebuggerBase.js @@ -17,8 +17,33 @@ * under the License. */ -function main() { - x = 42; - println(x); // LBREAKPOINT - return x; -} \ No newline at end of file +statement = "First Statement"; + +function fnc1() { + let a = 20; + let o = {}; + o.ao = "AO"; + let arr = []; + arr = [5, 4, 3, 2, 1] + + return 30; +} + +function fnc2(n) { + + let n1 = n + 1; + let f2 = 0; + if (n1 <= 10) { + f2 = fnc2(n1) + 1; + } + return f2; +} + +ga = 6; +fnc1(); + +for (let i of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) { + + fnc2(i); + +} diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/DebuggerBase.py b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/DebuggerBase.py new file mode 100644 index 000000000000..188e6bd1513d --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/DebuggerBase.py @@ -0,0 +1,49 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +class TestObject: + def addAO(self): self.ao = "AO" +def fnc1(): + a = 20 + o = TestObject() + o.addAO() + arr = [] + arr = [5, 4, 3, 2, 1] + + return 30 + + +def fnc2(n): + + n1 = n + 1 + f2 = 0 + if n1 <= 10: + f2 = fnc2(n1) + 1 + + return f2 + + +ga = 6 +fnc1() + +for i in range(1, 10): + + fnc2(i) + + diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/DebuggerBase.r b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/DebuggerBase.r new file mode 100644 index 000000000000..a09ae2010ab0 --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/DebuggerBase.r @@ -0,0 +1,49 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +x <- "First statement" + +fnc1 <- function() { + a <- 20 + o <- list() + o <- list(ao = "AO") + arr <- c() + arr <- c(5, 4, 3, 2, 1) + + return(30) +} + +fnc2 <- function(n) { + + n1 <- n + 1 + f2 <- 0 + if (n1 <= 10) { + f2 <- fnc2(n1) + 1 + } + return(f2) +} + +ga <- 6 +y <- fnc1() + +for (i in 1:10) { + + fnc2(i) + +} diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/DebuggerBase.ruby b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/DebuggerBase.ruby new file mode 100644 index 000000000000..3f0ad2469c98 --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/DebuggerBase.ruby @@ -0,0 +1,49 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +statement = "First Statement" + +def fnc1() + a = 20 + o = Object.new + o.instance_variable_set :@ao, "AO" + arr = [] + arr = [5, 4, 3, 2, 1] + + 30 +end + +def fnc2(n) + + n1 = n + 1 + f2 = 0 + if (n1 <= 10) + f2 = fnc2(n1) + 1 + end + f2 +end + +$ga = 6 +fnc1() + +for i in 1..10 do + + fnc2(i) + +end diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Types.js b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Types.js new file mode 100644 index 000000000000..3390c662f68c --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Types.js @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +function typesTest() { + let a1 = []; + let a2 = [1, 2, [3, 4]]; + let b1 = true; + let b2 = false; + let c1 = new TestClass(); + let i1 = 0; + let i2 = 42; + let i3 = 42.42; + let i4 = -0.0; + let i5 = 1/i4; + let i6 = 1/0.0; + let i7 = -1/0.0; + let i8 = 0.0/0.0; + let aSparse = [1, 2]; + aSparse[10] = 10; + let s1 = "String"; + let f1 = function pow2(x) { + return x*x; + }; + let d1 = new Date(1000000000); + let undef; + let nul = null; + let sy = Symbol('symbolic'); + let o1 = {}; + let o2 = new TestFncProp(); + o2.fncProp = "Property"; + o2.a = "A"; + let map = new Map(); + map.set("key1", 42); + map.set("key2", "v24"); + debugger; + f1(5); +} + +function TestFncProp() { +} + +class TestClass { +} + +typesTest(); diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Types.py b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Types.py new file mode 100644 index 000000000000..80aa2715a6ad --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Types.py @@ -0,0 +1,41 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +import datetime +def Callable(): + pass + + +def typesTest(): + + a = [1, 2, 3, 42] + b1 = True + b2 = False + i = 42 + s = "string" + n = None + f = Callable + d = datetime.datetime.now() + map = dict() + map["key1"] = 42 + map["key2"] = "v24" + + bp = "breakpoint is here" + +typesTest() diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Types.r b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Types.r new file mode 100644 index 000000000000..f84a7da28620 --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Types.r @@ -0,0 +1,41 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +Callable <- function() { + +} + +typesTest <- function() { + + a <- c(1, 2, 3, 42) + b1 <- TRUE + b2 <- FALSE + i <- 42 + s <- "string" + n <- NULL + f <- Callable + d <- Sys.Date() + map <- new.env() + map[["key1"]] <- 42 + map[["key2"]] <- "v24" + + bp <- "breakpoint is here" +} + +typesTest() diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Types.ruby b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Types.ruby new file mode 100644 index 000000000000..f3c8cca78a1a --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Types.ruby @@ -0,0 +1,51 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +def Callable + +end + +def typesTest + + a1 = [] + a2 = [1, 2, [3, 4]] + b1 = true + b2 = false + null = nil + i1 = 0 + i2 = 42 + i3 = 42.42 + i4 = -0.0; + i5 = 1/i4; + i6 = 1/0.0; + i7 = -1/0.0; + i8 = 0.0/0.0; + nc = 2 + 3i + nr = Rational(5.5) + f = method(:Callable) + d = Time.now + str = "A String" + symbol = :symbolic + hash = {:a => 1, "b" => 2} + i1 + i2 + +end + +typesTest() + diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.js b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.js new file mode 100644 index 000000000000..c2017aa1c43c --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.js @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +function weather() { + + // Load the Ruby module + Polyglot.eval("application/x-ruby", "eval(File.open(\"org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.rb\").read)"); + + let Weather = Polyglot.import('weather') + Polyglot.export('tempInCity', function(name) { + return Weather.temperature_in_city(name); + }); + + // Load the R module + console.log("Preparing weather model... This may take a while."); + Polyglot.eval("application/x-r", "source(\"org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.r\")"); + + // Import the function exported from the R module + let createModel = Polyglot.import('createModel'); + let predictTemp = Polyglot.import('do_predict'); + let plotModel = Polyglot.import('plotModel'); + + // Load the Python module + Polyglot.eval("text/x-python", "import polyglot\n" + + "@polyglot.export_value\n" + + "def purchase(n):\n" + + " bill = 0\n" + + " bill += fruits(n, n // 2)\n" + + " return bill\n" + + "\n" + + "def fruits(a, b):\n" + + " prices = {'apple': 0.40, 'banana': 0.50}\n" + + " my_purchase = {\n" + + " 'apple': a,\n" + + " 'banana': b}\n" + + " grocery_bill = 0\n" + + " for f in my_purchase:\n" + + " grocery_bill += prices[f] * my_purchase[f]\n" + + " return grocery_bill\n"); + let Purchase = Polyglot.import('purchase') + + let cityService = new (Java.type('org.netbeans.modules.debugger.jpda.truffle.testapps.WeatherCityService')); + var cities = cityService.getAll(); + + let javaNullObj = cityService.getNull(); + + // Create the linear regression model -> calls to R + let updateModel = function(size) { + function adjustIndex(i) { + if (i >= 1) { + return i - 1; + } else { + throw 'Wrong index: ' + i; + } + } + function convertTemp(conversion, t) { + switch(conversion) { + case 'C2F': return t * 1.8 + 32; + case 'F2C': return (t - 32) / 1.8; + default: throw "Unsupported conversion: " + conversion; + } + } + let getName = function(i) { + return cities[adjustIndex(i)].getName(); + } + let getLatitude = function(i) { + return cities[adjustIndex(i)].getLatitude(); + } + let getLongitude = function(i) { + return cities[adjustIndex(i)].getLongitude(); + } + let getTemperature = function(i) { + let c = cities[adjustIndex(i)]; + return convertTemp('C2F', c.getTemperature()); + } + return createModel(size, cities.length, getName, getLatitude, getLongitude, getTemperature); + } + + let model = updateModel(5); + + let numCities = model.data.name.length; + print("Have " + numCities + " cities:"); + for (let i = 0; i < numCities; i++) { + let name = cities[i].getName(); + + // Step into Ruby + let temperature = Weather.temperature_in_city(name); + + // Step into Python + let purchase = Purchase(i); + print(" City " + name + ", " + cities[i].getCountry() + " has temperature " + temperature + "°C and bill $" + purchase); + } + + print("Approximated temperatures by latitude are:"); + let tMean = 0; + for (let lat = 90; lat >= -90; lat -= 10) { + + // Step into R + let t = predictTemp(model, lat); + print("Temperature at latitude " + lat + " is " + t + "°C."); + tMean += t; + } + tMean /= 19; + return tMean; +} + +// Step into the weather test +weather(); diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.py b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.py new file mode 100644 index 000000000000..f5909339e6fe --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.py @@ -0,0 +1,36 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +import polyglot +@polyglot.export_value +def purchase(n): + bill = 0 + bill += fruits(n, n // 2) + return bill + +def fruits(a, b): + prices = {'apple': 0.40, 'banana': 0.50} + my_purchase = { + 'apple': a, + 'banana': b} + grocery_bill = 0 + for f in my_purchase: + grocery_bill += prices[f] * my_purchase[f] + return grocery_bill + diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.r b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.r new file mode 100644 index 000000000000..3df2d4862c62 --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.r @@ -0,0 +1,56 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# Import the tempInCity function exported from the Ruby module +tempInCity <- import('tempInCity') + +# The lattice library is needed for the visualization +library(lattice) + +createModel <- function(size, length, getName, getLat, getLong, getTemp) { + idx <- sample(1:length, size) + data <- as.data.frame(list( + name = sapply(idx, function(i) getName(i)), + lat = sapply(idx, function(i) getLat(i)), + long = sapply(idx, function(i) getLong(i)), + temp = sapply(idx, function(i) getTemp(i)))) + list(data=data, model=lm(temp~lat, data=data)) +} + +do_predict <- function(model, lat) { + predict(model$model, as.data.frame(list(lat = lat)))[[1]] +} + +plotModel <- function(model) { + svg() + print(xyplot(temp ~ lat, data = model$data, + panel = function(x, y) { + panel.xyplot(x, y, cex=2, pch=19) + panel.abline(model$model) + labelsIdx <- seq(1, length(x), length.out = 10) # show only 10 labels, to make the graph more readable + panel.text(x[labelsIdx] + 1, y[labelsIdx], model$data$name[labelsIdx], adj = c(0, 0.5)) + })); + grDevices:::svg.off() +} + +# Export the functions +export('createModel', createModel) +export('do_predict', do_predict) +export('plotModel', plotModel) + diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.rb b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.rb new file mode 100644 index 000000000000..aaea35849e19 --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.rb @@ -0,0 +1,29 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +module Weather + def self.temperature_in_city(name) + name = Truffle::Interop.from_java_string(name) + cityArray = name.bytes + citySum = cityArray.reduce(0, :+) + weatherTemperature = citySum.modulo(36) + end +end + +Truffle::Interop.export :weather, Weather diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/SLAppFromFile.java b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/PolyglotWeatherApp.java similarity index 62% rename from java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/SLAppFromFile.java rename to java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/PolyglotWeatherApp.java index e50a3f6f0788..1517d1aaf212 100644 --- a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/SLAppFromFile.java +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/PolyglotWeatherApp.java @@ -16,28 +16,23 @@ * specific language governing permissions and limitations * under the License. */ - package org.netbeans.modules.debugger.jpda.truffle.testapps; -import java.io.ByteArrayOutputStream; import java.io.File; - +import java.io.IOException; import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Source; import org.graalvm.polyglot.Value; -import static org.junit.Assert.assertEquals; -public class SLAppFromFile { - public static void main(String... args) throws Exception { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - Context context = Context.newBuilder().out(os).build(); +public class PolyglotWeatherApp { - String path = args[0]; - Source src = Source.newBuilder("sl", new File(path)).build(); - - Value result = context.eval(src); // LBREAKPOINT - - assertEquals("Expected result", 42L, result.asLong()); - assertEquals("Expected output", "42\n", os.toString("UTF-8")); + public static void main(String[] args) throws IOException { + Context context = Context.newBuilder().allowAllAccess(true).build(); + File script = new File(new File("").getAbsolutePath(), "org/netbeans/modules/debugger/jpda/truffle/scripts/Weather.js"); + Source source = Source.newBuilder("js", script).build(); + Value result = context.eval(source); + double t = result.asDouble(); + System.out.println("Mean temperature = "+t); } + } diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/SLApp.java b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/SLApp.java deleted file mode 100644 index 4d1e9f6a0b91..000000000000 --- a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/SLApp.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.netbeans.modules.debugger.jpda.truffle.testapps; - -import java.io.ByteArrayOutputStream; - -import org.graalvm.polyglot.Context; -import org.graalvm.polyglot.Source; -import org.graalvm.polyglot.Value; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -public class SLApp { - public static void main(String... args) throws Exception { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - - Source src = Source.newBuilder("sl", - "function main() {\n" + - " x = 42;\n" + - " println(x);\n" + - " return x;\n" + - "}\n"+ - "function init() {\n"+ - " obj = new();\n"+ - " obj.fourtyTwo = main;\n"+ - " return obj;\n"+ - "}\n", - "Meaning of world.sl").build(); - - Context context = Context.newBuilder().allowAllAccess(true).out(os).build(); - Value result = context.eval(src); // LBREAKPOINT - - assertEquals("Expected result", 42L, result.asLong()); - assertEquals("Expected output", "42\n", os.toString("UTF-8")); - - // dynamic generated interface - Value init = context.getBindings("sl").getMember("init"); - assertNotNull("init method found", init); - Compute c = init.execute().as(Compute.class); // LBREAKPOINT - Object result42 = c.fourtyTwo(); // LBREAKPOINT - assertEquals("Expected result", 42L, result42); - assertEquals("Expected output", "42\n42\n", os.toString("UTF-8")); - } - - public static interface Compute { - public Number fourtyTwo(); - } -} diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/WeatherCity.java b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/WeatherCity.java new file mode 100644 index 000000000000..3f2018309fe2 --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/WeatherCity.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.debugger.jpda.truffle.testapps; + +public class WeatherCity { + + private final int id; + private final String name; + private final String country; + private final int population; + private final double longitude; + private final double lat; + private double temperature; + + public WeatherCity(int id, String name, String country, int population, double lat, double longitude, double temperature) { + this.id = id; + this.name = name; + this.country = country; + this.longitude = longitude; + this.lat = lat; + this.temperature = temperature; + this.population = population; + } + + public int getId() { return id; } + public String getName() { return name; } + public String getCountry() { return country; } + public int getPopulation() { return population; } + public double getLatitude() { return lat; } + public double getLongitude() { return longitude; } + public double getTemperature() { return temperature; } + + public void updateTemperature(double newValue) { + temperature = newValue; + } +} diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/WeatherCityService.java b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/WeatherCityService.java new file mode 100644 index 000000000000..048279ee46bd --- /dev/null +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/WeatherCityService.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.debugger.jpda.truffle.testapps; + +import java.util.Arrays; + +public class WeatherCityService { + + // A test sample + private static WeatherCity[] cities = new WeatherCity[] { + new WeatherCity(0, "San Roque", "N. Mariana Islands", 1097, 15.25, 145.77, 13.2346746509429), + new WeatherCity(1, "La Sabana", "Honduras", 1572, 15.37, -87.93, 29.5364631644916), + new WeatherCity(2, "Videbaek", "Denmark", 4076, 56.08, 8.63, 24.2545498488471), + new WeatherCity(3, "Nasirabad", "Pakistan", 28506, 27.38, 67.91, 25.4554680001456), + new WeatherCity(4, "Okazaki", "Japan", 355573, 34.96, 137.16, 7.89123377134092), + new WeatherCity(5, "Huddersfield", "UK", 149607, 53.66, -1.8, 26.9585336048622), + new WeatherCity(6, "Cocentaina", "Spain", 11223, 38.75, -0.44, 16.3208602035884), + new WeatherCity(7, "Ankathia", "Greece", 1300, 40.56, 22.47, 9.76689549605362), + new WeatherCity(8, "Mediesu Aurit", "Romania", 7062, 47.78, 23.15, 10.8357614693232), + new WeatherCity(9, "Juan Lopez", "Dominican Republic", 1547, 19.43, -70.52, 14.5722625446506), + new WeatherCity(10, "Birnin Kebbi", "Nigeria", 111883, 12.46, 4.19, 23.3168364593294), + new WeatherCity(11, "Chistopol", "Russia", 62020, 55.36, 50.64, 3.51541253109463), + new WeatherCity(12, "Periyialion", "Greece", 2120, 37.95, 22.84, 16.3009215018246), + new WeatherCity(13, "Togo", "Japan", 42643, 35.1, 137.04, 8.89008317119442), + new WeatherCity(14, "Shiyan", "China", 413581, 32.57, 110.78, 20.1505158017389), + new WeatherCity(15, "Iira", "Estonia", 138, 58.99, 24.72, 12.9968547783792), + new WeatherCity(16, "Ilha Soltera", "Brazil", 25305, -20.38, -51.34, 14.7320180023089), + new WeatherCity(17, "Ikorodu", "Nigeria", 321809, 6.61, 3.51, 22.5338149268646), + new WeatherCity(18, "Kocani", "Macedonia", 34448, 41.93, 22.4, 2.02855428215116), + new WeatherCity(19, "Siatista", "Greece", 5603, 40.26, 21.54, 22.2741849503946), + new WeatherCity(20, "Pella", "Greece", 2482, 40.76, 22.52, 13.1903853449039), + }; + + public int getTotalCount() { return cities.length; } + public WeatherCity[] getAll() { return cities; } + public WeatherCity[] getAllPaged(int skip, int pageSize) { + return Arrays.stream(cities).skip(skip).limit(pageSize).toArray(n -> new WeatherCity[n]); + } + + public WeatherCity findByName(String name) { + return Arrays.stream(cities).filter(x -> x.getName().equals(name)).findFirst().orElse(null); + } + + public void updateTemperature(int id, double temperature) { + cities[id].updateTemperature(temperature); + } + public Object getNull() { + return null; + } + +} diff --git a/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/JPDATruffleAccessor.java b/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/JPDATruffleAccessor.java index 8fbdfa9f3e64..5a7d973e526d 100644 --- a/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/JPDATruffleAccessor.java +++ b/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/JPDATruffleAccessor.java @@ -501,6 +501,7 @@ private static Breakpoint doSetLineBreakpoint(DebuggerSession debuggerSession, bb.resolveListener(new Breakpoint.ResolveListener() { @Override public void breakpointResolved(Breakpoint breakpoint, SourceSection section) { + trace("JPDATruffleAccessor breakpointResolved({0}, {1})", breakpoint, section); // Notify breakpoint resolution after we actually install it. // Resolution that is performed synchronously with the breakpoint installation // would block doSetLineBreakpoint() method invocation on breakpointResolvedAccess breakpoint diff --git a/java/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/JPDASupport.java b/java/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/JPDASupport.java index b13a30a6f79c..31eedcef714e 100644 --- a/java/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/JPDASupport.java +++ b/java/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/JPDASupport.java @@ -19,67 +19,70 @@ package org.netbeans.api.debugger.jpda; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.connect.AttachingConnector; +import com.sun.jdi.connect.Transport; + +import java.beans.PropertyChangeEvent; +import java.io.EOFException; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.lang.reflect.Method; import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import java.util.Map; -import org.netbeans.api.debugger.*; - -import java.io.*; -import java.util.*; -import java.net.URLClassLoader; -import java.net.URL; -import java.beans.PropertyChangeEvent; -import java.text.DateFormat; -import java.text.SimpleDateFormat; - -import com.sun.jdi.connect.*; -import com.sun.jdi.VirtualMachineManager; -import com.sun.jdi.Bootstrap; -//import org.netbeans.api.java.classpath.ClassPath; import junit.framework.Test; import junit.framework.TestCase; +import static org.junit.Assert.assertEquals; + +import org.netbeans.api.debugger.ActionsManager; +import org.netbeans.api.debugger.ActionsManagerListener; +import org.netbeans.api.debugger.Breakpoint; +import org.netbeans.api.debugger.DebuggerEngine; +import org.netbeans.api.debugger.DebuggerManager; +import org.netbeans.api.debugger.DebuggerManagerListener; +import org.netbeans.api.debugger.Session; +import org.netbeans.api.debugger.Watch; import org.netbeans.api.java.classpath.ClassPath; -//import org.netbeans.spi.java.classpath.support.ClassPathSupport; -import org.netbeans.api.java.queries.SourceForBinaryQuery; import org.netbeans.junit.NbModuleSuite; import org.netbeans.junit.NbModuleSuite.Configuration; import org.netbeans.spi.java.classpath.support.ClassPathSupport; -import org.openide.filesystems.FileObject; -import org.openide.filesystems.FileUtil; -import org.openide.util.Exceptions; /** * Contains support functionality for unit tests. * * @author Maros Sandor */ -public class JPDASupport implements DebuggerManagerListener { +public final class JPDASupport implements DebuggerManagerListener { private static final boolean verbose = false; - private static final DateFormat df = new SimpleDateFormat("kk:mm:ss.SSS"); private static DebuggerManager dm = DebuggerManager.getDebuggerManager (); private JPDADebugger jpdaDebugger; private DebuggerEngine debuggerEngine; + private final ProcessIO processIO; - - private Object [] debuggerStartLock = new Object[1]; - private Object [] stepLock = new Object[1]; - - private Object STATE_LOCK = new Object (); - + private Object STATE_LOCK = new Object (); - private JPDASupport (JPDADebugger jpdaDebugger) { + private JPDASupport (JPDADebugger jpdaDebugger, ProcessIO pio) { this.jpdaDebugger = jpdaDebugger; jpdaDebugger.addPropertyChangeListener (this); DebuggerEngine[] de = dm.getDebuggerEngines (); int i, k = de.length; - for (i = 0; i < k; i++) + for (i = 0; i < k; i++) { if (de [i].lookupFirst (null, JPDADebugger.class) == jpdaDebugger) { debuggerEngine = de [i]; break; } + } + this.processIO = pio; } public static Test createTestSuite(Class clazz) { @@ -182,26 +185,62 @@ public static JPDASupport attach (String mainClass, String[] args, File[] classP break; } } - if (connector == null) - throw new RuntimeException - ("No attaching socket connector available"); - + if (connector == null) { + throw new RuntimeException("No attaching socket connector available"); + } JPDADebugger jpdaDebugger = JPDADebugger.attach ( "localhost", port, createServices () ); - return new JPDASupport (jpdaDebugger); + return new JPDASupport (jpdaDebugger, pio); } - + public static JPDASupport attachScript(String launcher, String path) throws IOException, DebuggerStartException { + String [] cmdArray = new String [] { + System.getProperty ("java.home") + File.separatorChar + + "bin" + File.separatorChar + launcher, + "--jvm", + "--vm.agentlib:jdwp=transport=dt_socket,suspend=y,server=y", + path + }; + Process process = Runtime.getRuntime ().exec (cmdArray); + String line = readLine (process.getInputStream ()); + int port = Integer.parseInt (line.substring (line.lastIndexOf (':') + 1).trim ()); + ProcessIO pio = new ProcessIO (process); + pio.go(); + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + List aconnectors = vmm.attachingConnectors(); + AttachingConnector connector = null; + for (Iterator i = aconnectors.iterator(); i.hasNext();) { + AttachingConnector ac = (AttachingConnector) i.next(); + Transport t = ac.transport (); + if (t != null && t.name().equals("dt_socket")) { + connector = ac; + break; + } + } + if (connector == null) { + throw new RuntimeException("No attaching socket connector available"); + } + + JPDADebugger jpdaDebugger = JPDADebugger.attach ( + "localhost", + port, + new Object[]{} + ); + return new JPDASupport(jpdaDebugger, pio); + } + + // public interface ........................................................ public void doContinue () { - if (jpdaDebugger.getState () != JPDADebugger.STATE_STOPPED) + if (jpdaDebugger.getState () != JPDADebugger.STATE_STOPPED) { throw new IllegalStateException (); - debuggerEngine.getActionsManager ().doAction - (ActionsManager.ACTION_CONTINUE); + } + debuggerEngine.getActionsManager().doAction(ActionsManager.ACTION_CONTINUE); } public void stepOver () { @@ -217,9 +256,10 @@ public void stepOut () { } public void step (Object action) { - if (jpdaDebugger.getState () != JPDADebugger.STATE_STOPPED) + if (jpdaDebugger.getState () != JPDADebugger.STATE_STOPPED) { throw new IllegalStateException (); - debuggerEngine.getActionsManager ().doAction (action); + } + DebuggerManager.getDebuggerManager().getCurrentEngine().getActionsManager().doAction(action); waitState (JPDADebugger.STATE_STOPPED); } @@ -245,6 +285,11 @@ public void doFinish () { debuggerEngine.getActionsManager (). doAction (ActionsManager.ACTION_KILL); waitState (JPDADebugger.STATE_DISCONNECTED); + try { + processIO.join(); + } catch (InterruptedException ex) { + // Interrupted + } } public void waitState (int state) { @@ -322,7 +367,7 @@ private static Object[] createServices () { } private static String readLine (InputStream in) throws IOException { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); for (;;) { int c = in.read(); if (c == -1) throw new EOFException(); @@ -363,7 +408,12 @@ private static Process launchVM ( cmdArray = arr; } - return Runtime.getRuntime ().exec (cmdArray); + ProcessBuilder pb = new ProcessBuilder().command(cmdArray); + String classesDir = System.getProperty("test.dir.classes"); + if (classesDir != null) { + pb.directory(new File(classesDir)); + } + return pb.start(); } private static String getClassPath(File[] extraCP) { @@ -477,7 +527,9 @@ public void engineRemoved (DebuggerEngine debuggerEngine) { private static class ProcessIO { - private Process p; + private final Process p; + private Thread threadOut; + private Thread threadErr; public ProcessIO(Process p) { this.p = p; @@ -487,8 +539,14 @@ public void go() { InputStream out = p.getInputStream(); InputStream err = p.getErrorStream(); - new SimplePipe(System.out, out).start(); - new SimplePipe(System.out, err).start(); + (threadOut = new SimplePipe(System.out, out)).start(); + (threadErr = new SimplePipe(System.out, err)).start(); + } + + private void join() throws InterruptedException { + threadOut.join(); + threadErr.join(); + assertEquals(0, p.waitFor()); } } diff --git a/nbbuild/travis/scripting.sh b/nbbuild/travis/scripting.sh index 82e47bac874a..1c7a06e2750b 100755 --- a/nbbuild/travis/scripting.sh +++ b/nbbuild/travis/scripting.sh @@ -35,6 +35,7 @@ fi $GRAALVM/bin/gu install python $GRAALVM/bin/gu install R +$GRAALVM/bin/gu install ruby # Test on GraalVM @@ -45,3 +46,4 @@ JAVA_HOME=$GRAALVM ant -f platform/core.network/build.xml test JAVA_HOME=$GRAALVM ant -f webcommon/libs.graaljs/build.xml test JAVA_HOME=$GRAALVM ant -f profiler/profiler.oql/build.xml test JAVA_HOME=$GRAALVM ant -f java/nashorn.execution/build.xml test +JAVA_HOME=$GRAALVM ant -f java/debugger.jpda.truffle/build.xml test