Bring back ScriptLaunchingTests as it's needed.
Change-Id: I39e5bdf0d793e340b6b0fd12bff6d67784fb77e1
diff --git a/core/tests/org.eclipse.dltk.core.tests/src/org/eclipse/dltk/core/tests/launching/ScriptLaunchingTests.java b/core/tests/org.eclipse.dltk.core.tests/src/org/eclipse/dltk/core/tests/launching/ScriptLaunchingTests.java
new file mode 100644
index 0000000..7a97787
--- /dev/null
+++ b/core/tests/org.eclipse.dltk.core.tests/src/org/eclipse/dltk/core/tests/launching/ScriptLaunchingTests.java
@@ -0,0 +1,673 @@
+package org.eclipse.dltk.core.tests.launching;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IDebugEventSetListener;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationType;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchDelegate;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.Launch;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.core.model.IStreamMonitor;
+import org.eclipse.debug.core.model.IStreamsProxy;
+import org.eclipse.dltk.core.IScriptProject;
+import org.eclipse.dltk.core.environment.EnvironmentManager;
+import org.eclipse.dltk.core.environment.IFileHandle;
+import org.eclipse.dltk.core.tests.model.AbstractModelTests;
+import org.eclipse.dltk.debug.core.ExtendedDebugEventDetails;
+import org.eclipse.dltk.debug.core.model.IScriptLineBreakpoint;
+import org.eclipse.dltk.debug.core.model.IScriptStackFrame;
+import org.eclipse.dltk.debug.core.model.IScriptThread;
+import org.eclipse.dltk.internal.debug.core.model.ScriptDebugTarget;
+import org.eclipse.dltk.internal.debug.core.model.ScriptLineBreakpoint;
+import org.eclipse.dltk.internal.debug.core.model.ScriptThread;
+import org.eclipse.dltk.launching.IInterpreterInstall;
+import org.eclipse.dltk.launching.IInterpreterInstallType;
+import org.eclipse.dltk.launching.InterpreterConfig;
+import org.eclipse.dltk.launching.InterpreterSearcher;
+import org.eclipse.dltk.launching.ScriptLaunchConfigurationConstants;
+
+public abstract class ScriptLaunchingTests extends AbstractModelTests {
+
+ protected IScriptProject scriptProject;
+
+ protected IInterpreterInstall[] interpreterInstalls;
+
+ public ScriptLaunchingTests(String name) {
+ super(name);
+ }
+
+ // Configuration
+ @Override
+ public void setUpSuite() throws Exception {
+ super.setUpSuite();
+ scriptProject = setUpScriptProject(getProjectName(), getBundleName());
+
+ final IProject project = scriptProject.getProject();
+ IProjectDescription description = project.getDescription();
+ description.setNatureIds(new String[] { getNatureId() });
+ project.setDescription(description, null);
+
+ if (!hasPredefinedInterpreters()) {
+ interpreterInstalls = searchInstalls(getNatureId());
+ } else {
+ interpreterInstalls = getPredefinedInterpreterInstalls();
+ }
+ }
+
+ /**
+ * Should return predefined interpreters. Used with hasPredefinedInterpreters
+ * method as true.
+ *
+ * @return Not null array of interpreter installs.
+ */
+ protected IInterpreterInstall[] getPredefinedInterpreterInstalls() {
+ return new IInterpreterInstall[0];
+ }
+
+ @Override
+ public void tearDownSuite() throws Exception {
+ deleteProject(getProjectName());
+ super.tearDownSuite();
+ }
+
+ // Helper methods
+ protected ILaunchConfiguration createTestLaunchConfiguration(final String natureId, final String projectName,
+ final String script, final String arguments) {
+ return new ILaunchConfiguration() {
+ @Override
+ public boolean contentsEqual(ILaunchConfiguration configuration) {
+ return false;
+ }
+
+ @Override
+ public ILaunchConfigurationWorkingCopy copy(String name) throws CoreException {
+ return null;
+ }
+
+ @Override
+ public void delete() throws CoreException {
+
+ }
+
+ @Override
+ public boolean exists() {
+ return false;
+ }
+
+ @Override
+ public boolean getAttribute(String attributeName, boolean defaultValue) throws CoreException {
+ if (attributeName.equals(ScriptLaunchConfigurationConstants.ATTR_DEFAULT_BUILDPATH)) {
+ return true;
+ } else if (attributeName.equals(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES)) {
+ return true;
+ }
+
+ return defaultValue;
+ }
+
+ @Override
+ public int getAttribute(String attributeName, int defaultValue) throws CoreException {
+ if (attributeName.equals(ScriptLaunchConfigurationConstants.ATTR_DLTK_DBGP_WAITING_TIMEOUT)) {
+ return 10000;
+ }
+ return defaultValue;
+ }
+
+ @Override
+ public List<String> getAttribute(String attributeName, List<String> defaultValue) throws CoreException {
+ return defaultValue;
+ }
+
+ @Override
+ public Set<String> getAttribute(String attributeName, Set<String> defaultValue) throws CoreException {
+ return defaultValue;
+ }
+
+ @Override
+ public Map<String, String> getAttribute(String attributeName, Map<String, String> defaultValue)
+ throws CoreException {
+ if (attributeName.equals(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES)) {
+ Map<String, String> env = new HashMap<>();
+ configureEnvironment(env);
+ return env;
+ }
+ return defaultValue;
+ }
+
+ @Override
+ public String getAttribute(String attributeName, String defaultValue) throws CoreException {
+
+ if (attributeName.equals(ScriptLaunchConfigurationConstants.ATTR_MAIN_SCRIPT_NAME)) {
+ return script;
+ } else if (attributeName.equals(ScriptLaunchConfigurationConstants.ATTR_PROJECT_NAME)) {
+ return projectName;
+ } else if (attributeName.equals(ScriptLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY)) {
+ return null;
+ } else if (attributeName.equals(ScriptLaunchConfigurationConstants.ATTR_SCRIPT_ARGUMENTS)) {
+ return arguments;
+ } else if (attributeName.equals(ScriptLaunchConfigurationConstants.ATTR_INTERPRETER_ARGUMENTS)) {
+ return "";
+ } else if (attributeName.equals(ScriptLaunchConfigurationConstants.ATTR_SCRIPT_NATURE)) {
+ return natureId;
+ }
+ return defaultValue;
+ }
+
+ @Override
+ public Map<String, Object> getAttributes() throws CoreException {
+ return null;
+ }
+
+ @Override
+ public String getCategory() throws CoreException {
+ return null;
+ }
+
+ @Override
+ public IFile getFile() {
+ return ScriptLaunchingTests.this.getFile(projectName + '/' + script);
+ }
+
+ @Override
+ public IPath getLocation() {
+ return null;
+ }
+
+ @Override
+ public IResource[] getMappedResources() throws CoreException {
+ return null;
+ }
+
+ @Override
+ public String getMemento() throws CoreException {
+ return null;
+ }
+
+ @Override
+ public Set<String> getModes() throws CoreException {
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ return null;
+ }
+
+ @Override
+ public ILaunchDelegate getPreferredDelegate(Set<String> modes) throws CoreException {
+ return null;
+ }
+
+ @Override
+ public ILaunchConfigurationType getType() throws CoreException {
+ return null;
+ }
+
+ @Override
+ public ILaunchConfigurationWorkingCopy getWorkingCopy() throws CoreException {
+ return null;
+ }
+
+ @Override
+ public boolean isLocal() {
+ return false;
+ }
+
+ @Override
+ public boolean isMigrationCandidate() throws CoreException {
+ return false;
+ }
+
+ @Override
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ @Override
+ public boolean isWorkingCopy() {
+ return false;
+ }
+
+ @Override
+ public ILaunch launch(String mode, IProgressMonitor monitor) throws CoreException {
+ return null;
+ }
+
+ @Override
+ public ILaunch launch(String mode, IProgressMonitor monitor, boolean build) throws CoreException {
+ return null;
+ }
+
+ @Override
+ public ILaunch launch(String mode, IProgressMonitor monitor, boolean build, boolean register)
+ throws CoreException {
+ return null;
+ }
+
+ @Override
+ public void migrate() throws CoreException {
+
+ }
+
+ @Override
+ public boolean supportsMode(String mode) throws CoreException {
+ return false;
+ }
+
+ @Override
+ public <T> T getAdapter(Class<T> adapter) {
+ return null;
+ }
+
+ @Override
+ public boolean hasAttribute(String attributeName) throws CoreException {
+ return false;
+ }
+
+ @Override
+ public void delete(int flag) throws CoreException {
+
+ }
+
+ @Override
+ public ILaunchConfiguration getPrototype() throws CoreException {
+ return null;
+ }
+
+ @Override
+ public boolean isAttributeModified(String attribute) throws CoreException {
+ return false;
+ }
+
+ @Override
+ public boolean isPrototype() {
+ return false;
+ }
+
+ @Override
+ public Collection<ILaunchConfiguration> getPrototypeChildren() throws CoreException {
+ return null;
+ }
+
+ @Override
+ public int getKind() throws CoreException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public Set<String> getPrototypeVisibleAttributes() throws CoreException {
+ return null;
+ }
+
+ @Override
+ public void setPrototypeAttributeVisibility(String attribute, boolean visible) throws CoreException {
+ }
+ };
+ }
+
+ protected void configureEnvironment(Map<?, ?> env) {
+ }
+
+ public IInterpreterInstall[] searchInstalls(String natureId) {
+ final List<IInterpreterInstall> installs = new ArrayList<>();
+ final InterpreterSearcher searcher = new InterpreterSearcher();
+
+ searcher.search(EnvironmentManager.getLocalEnvironment(), natureId, null, 1, null);
+
+ if (searcher.hasResults()) {
+ IFileHandle[] files = searcher.getFoundFiles();
+ IInterpreterInstallType[] types = searcher.getFoundInstallTypes();
+
+ for (int i = 0; i < files.length; ++i) {
+ final IFileHandle file = files[i];
+ final IInterpreterInstallType type = types[i];
+
+ // // Skip useless interpreters
+ // if (!isInterpreterRequired(file))
+ // continue;
+
+ String installId = getNatureId() + "_" + Integer.toString(i);
+ IInterpreterInstall install = type.findInterpreterInstall(installId);
+
+ if (install == null)
+ install = type.createInterpreterInstall(installId);
+
+ install.setName(file.toString());
+ install.setInstallLocation(file);
+ install.setLibraryLocations(null);
+ install.setEnvironmentVariables(null);
+ installs.add(install);
+ }
+ }
+
+ return installs.toArray(new IInterpreterInstall[installs.size()]);
+ }
+
+ public void internalTestRequiredInterpreterAvailable(String name) {
+ assertTrue("Interpreter " + name + " not available", isInterpreterAvailable(name));
+ }
+
+ private boolean isInterpreterAvailable(String interpreterName) {
+ for (int i = 0; i < interpreterInstalls.length; i++) {
+ IFileHandle installLocation = interpreterInstalls[i].getInstallLocation();
+ if (isRequiredInstall(interpreterName, installLocation)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isRequiredInstall(String interpreterName, IFileHandle installLocation) {
+ String executableName = installLocation.getName();
+ if (executableName.startsWith(interpreterName)) {
+ return true;
+ }
+ return false;
+ }
+
+ public final static int SKIP_STDOUT_TEST = 1;
+
+ protected void internalTestRun(String name) throws Exception {
+ internalTestRun(name, 0);
+ }
+
+ protected void internalTestRun(String name, int flags) throws Exception {
+ if (interpreterInstalls.length == 0) {
+ fail("No interperters found for nature " + getNatureId());
+ }
+
+ for (int i = 0; i < interpreterInstalls.length; ++i) {
+ final IInterpreterInstall install = interpreterInstalls[i];
+ if (!isRequiredInstall(name, install.getInstallLocation())) {
+ continue;
+ }
+ // System.out.println("Interpreter install location (run): "
+ // + install.getInstallLocation().toString());
+
+ // InterpretersUpdater updater = new InterpretersUpdater();
+ // updater.updateInterpreterSettings(getNatureId(),
+ // interpreterInstalls, install);
+
+ final long time = System.currentTimeMillis();
+ final String stdoutTest = Long.toString(time) + "_stdout";
+ final String stderrTest = Long.toString(time) + "_stderr";
+
+ final ILaunchConfiguration configuration = createLaunchConfiguration(stdoutTest + " " + stderrTest);
+
+ final ILaunch launch = new Launch(configuration, ILaunchManager.RUN_MODE, null);
+
+ startLaunch(launch, install);
+
+ IProcess[] processes = launch.getProcesses();
+ assertEquals(1, processes.length);
+
+ final IProcess process = processes[0];
+ final IStreamsProxy proxy = process.getStreamsProxy();
+ assertNotNull(proxy);
+
+ final IStreamMonitor outputMonitor = proxy.getOutputStreamMonitor();
+ assertNotNull(outputMonitor);
+
+ final IStreamMonitor errorMonitor = proxy.getErrorStreamMonitor();
+ assertNotNull(errorMonitor);
+
+ while (!process.isTerminated()) {
+ Thread.sleep(20);
+ }
+
+ assertTrue(process.isTerminated());
+
+ final int exitValue = process.getExitValue();
+ assertEquals(0, exitValue);
+
+ if ((flags & SKIP_STDOUT_TEST) == 0) {
+ final String output = outputMonitor.getContents();
+ assertEquals(stdoutTest, output);
+ }
+
+ final String error = errorMonitor.getContents();
+ assertEquals(stderrTest, error);
+ return;
+ }
+ assertTrue("Requied interpreter are't found" + name, false);
+ }
+
+ public static class DebugEventStats implements IDebugEventSetListener {
+ private int suspendCount;
+ private int resumeCount;
+ private int beforeSuspendCount;
+ private int beforeResumeCount;
+ private int beforeCodeLoaded;
+ private int beforeVmStarted;
+
+ public DebugEventStats() {
+ this.suspendCount = 0;
+ this.resumeCount = 0;
+ }
+
+ @Override
+ public void handleDebugEvents(DebugEvent[] events) {
+ for (int i = 0; i < events.length; ++i) {
+ DebugEvent event = events[i];
+
+ final int kind = event.getKind();
+ switch (kind) {
+ case DebugEvent.RESUME:
+ resumeCount += 1;
+ break;
+ case DebugEvent.SUSPEND:
+ suspendCount += 1;
+ try {
+ final Object source = event.getSource();
+ if (source instanceof IScriptStackFrame) {
+ ((IScriptStackFrame) source).resume();
+ } else if (source instanceof IScriptThread) {
+ ((IScriptThread) source).resume();
+ }
+ } catch (DebugException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ break;
+ case DebugEvent.CREATE:
+ break;
+ case DebugEvent.TERMINATE:
+ break;
+ case DebugEvent.CHANGE:
+ break;
+ case DebugEvent.MODEL_SPECIFIC:
+ handleExtendedEvent(event);
+ break;
+ }
+ }
+ }
+
+ private void handleExtendedEvent(DebugEvent event) {
+ int extendedType = event.getDetail();
+ switch (extendedType) {
+ case ExtendedDebugEventDetails.BEFORE_VM_STARTED:
+ handleBeforeVmStarted((InterpreterConfig) event.getSource());
+ break;
+ case ExtendedDebugEventDetails.BEFORE_CODE_LOADED:
+ handleBeforeCodeLoaded((ScriptDebugTarget) event.getSource());
+ break;
+ case ExtendedDebugEventDetails.BEFORE_RESUME:
+ handleBeforeResume((ScriptThread) event.getSource());
+ break;
+ case ExtendedDebugEventDetails.BEFORE_SUSPEND:
+ handleBeforeSuspend((ScriptThread) event.getSource());
+ break;
+ }
+
+ }
+
+ private void handleBeforeSuspend(ScriptThread source) {
+ beforeSuspendCount++;
+ }
+
+ private void handleBeforeResume(ScriptThread source) {
+ beforeResumeCount++;
+ }
+
+ private void handleBeforeCodeLoaded(ScriptDebugTarget source) {
+ beforeCodeLoaded++;
+ }
+
+ private void handleBeforeVmStarted(InterpreterConfig source) {
+ beforeVmStarted++;
+ }
+
+ public void reset() {
+ suspendCount = 0;
+ resumeCount = 0;
+ beforeSuspendCount = 0;
+ beforeResumeCount = 0;
+ beforeCodeLoaded = 0;
+ beforeVmStarted = 0;
+ }
+
+ public int getSuspendCount() {
+ return suspendCount;
+ }
+
+ public int getResumeCount() {
+ return resumeCount;
+ }
+
+ public int getBeforeSuspendCount() {
+ return beforeSuspendCount;
+ }
+
+ public int getBeforeResumeCount() {
+ return beforeResumeCount;
+ }
+
+ public int getBeforeCodeLoaded() {
+ return beforeCodeLoaded;
+ }
+
+ public int getBeforeVmStarted() {
+ return beforeVmStarted;
+ }
+ }
+
+ public DebugEventStats internalTestDebug(String name) throws Exception {
+ if (interpreterInstalls.length == 0) {
+ fail("No interperters found for nature " + getNatureId());
+ }
+
+ // Debug
+ for (int i = 0; i < interpreterInstalls.length; ++i) {
+ final IInterpreterInstall install = interpreterInstalls[i];
+ if (!isRequiredInstall(name, install.getInstallLocation())) {
+ continue;
+ }
+
+ DebugEventStats stats = new DebugEventStats();
+
+ DebugPlugin.getDefault().addDebugEventListener(stats);
+ // System.out.println("Interperter install location (debug): "
+ // + install.getInstallLocation());
+
+ // final InterpretersUpdater updater = new InterpretersUpdater();
+ // updater.updateInterpreterSettings(getNatureId(),
+ // interpreterInstalls, install);
+
+ stats.reset();
+
+ final ILaunch launch = new Launch(createLaunchConfiguration(""), ILaunchManager.DEBUG_MODE, null);
+
+ // Setting breakpoint
+ IFile file = launch.getLaunchConfiguration().getFile();
+ IScriptLineBreakpoint b = new ScriptLineBreakpoint(getDebugModelId(), file, file.getLocation(), 1, -1, -1,
+ true);
+
+ try {
+ startLaunch(launch, install);
+
+ IProcess[] processes = launch.getProcesses();
+ assertEquals(1, processes.length);
+
+ final IProcess process = processes[0];
+ while (!process.isTerminated()) {
+ Thread.sleep(200);
+ }
+
+ assertTrue(process.isTerminated());
+ final int exitValue = process.getExitValue();
+ assertEquals(0, exitValue);
+ } finally {
+ b.delete();
+
+ }
+ DebugPlugin.getDefault().removeDebugEventListener(stats);
+ return stats;
+ }
+
+ fail("Requied interpreter \"" + name + "\" is not found");
+ return null;
+ }
+
+ protected abstract String getProjectName();
+
+ protected abstract String getBundleName();
+
+ protected abstract String getNatureId();
+
+ protected abstract String getDebugModelId();
+
+ protected abstract void startLaunch(ILaunch launch, final IInterpreterInstall install) throws CoreException;
+
+ protected abstract ILaunchConfiguration createLaunchConfiguration(String arguments);
+
+ protected boolean hasPredefinedInterpreters() {
+ return false;
+ }
+
+ protected IInterpreterInstall createInstall(String path, String id, IInterpreterInstallType type) {
+ IFileHandle file = EnvironmentManager.getLocalEnvironment().getFile(new Path(path));
+ if (!file.exists()) {
+ return null;
+ }
+ IInterpreterInstall install = type.findInterpreterInstall(id);
+
+ if (install == null)
+ install = type.createInterpreterInstall(id);
+
+ install.setName("");
+ install.setInstallLocation(file);
+ install.setLibraryLocations(null);
+ install.setEnvironmentVariables(null);
+ return install;
+ }
+
+ protected void createAddInstall(List<IInterpreterInstall> installs, String path, String id,
+ IInterpreterInstallType type) {
+ IInterpreterInstall install = createInstall(path, id, type);
+ if (install != null) {
+ installs.add(install);
+ }
+ }
+}