blob: 36e90b81252c08eaa23f2ed29a962c69fc4302c4 [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 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();
});
}
}