blob: 8819f0b7bf6e394f92875222ed605fc82babe4bd [file] [log] [blame]
/*
* 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<String, File> 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();
});
});
}
}