package org.rubypeople.rdt.testunit.launcher;
import java.io.IOException;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.rubypeople.rdt.core.IRubyElement;
import org.rubypeople.rdt.core.IRubyProject;
import org.rubypeople.rdt.core.IRubyScript;
import org.rubypeople.rdt.core.IType;
import org.rubypeople.rdt.core.RubyCore;
import org.rubypeople.rdt.core.SocketUtil;
import org.rubypeople.rdt.internal.testunit.ui.TestUnitMessages;
import org.rubypeople.rdt.internal.testunit.ui.TestunitPlugin;
import org.rubypeople.rdt.launching.IRubyLaunchConfigurationConstants;
import org.rubypeople.rdt.launching.RubyLaunchDelegate;
public class TestUnitLaunchConfigurationDelegate extends RubyLaunchDelegate {
/**
* The single test type, or "" iff running a launch container.
*/
public static final String TESTTYPE_ATTR = TestunitPlugin.PLUGIN_ID + ".TESTTYPE"; //$NON-NLS-1$
/**
* The test method, or "" iff running the whole test type.
*/
public static final String TESTNAME_ATTR = TestunitPlugin.PLUGIN_ID + ".TESTNAME"; //$NON-NLS-1$
/**
* The launch container, or "" iff running a single test type.
*/
public static final String LAUNCH_CONTAINER_ATTR = TestunitPlugin.PLUGIN_ID + ".CONTAINER"; //$NON-NLS-1$
public static final String ID_TESTUNIT_APPLICATION = "org.rubypeople.rdt.testunit.launchconfig"; //$NON-NLS-1$
private static final String TEST_RUNNER_FILE = "RemoteTestRunner.rb";
private static final int TEST_RUNNER_VERSION = 3; // Bump up whenever we have a new remote test runner and we need to copy it over top of old ones!
private int port = -1;
@Override
public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException {
IType[] testTypes = findTestTypes(configuration, monitor);
getTestRunnerPath();
// setDefaultSourceLocator(launch, configuration);
launch.setAttribute(TestunitPlugin.TESTUNIT_PORT_ATTR, Integer.toString(getPort()));
if (testTypes != null && testTypes.length > 0 && testTypes[0] != null) launch.setAttribute(TESTTYPE_ATTR, testTypes[0].getHandleIdentifier());
super.launch(configuration, mode, launch, monitor);
}
protected IType[] findTestTypes(ILaunchConfiguration configuration, IProgressMonitor pm) throws CoreException {
IRubyProject javaProject= getRubyProject(configuration);
if ((javaProject == null) || !javaProject.exists()) {
informAndAbort(TestUnitMessages.TestUnitBaseLaunchConfiguration_error_invalidproject, null, IRubyLaunchConfigurationConstants.ERR_NOT_A_RUBY_PROJECT);
}
// if (!TestSearchEngine.hasTestCaseType(javaProject)) {
// informAndAbort(TestUnitMessages.JUnitBaseLaunchConfiguration_error_junitnotonpath, null, ITestUnitStatusConstants.ERR_JUNIT_NOT_ON_PATH);
// }
String containerHandle = configuration.getAttribute(LAUNCH_CONTAINER_ATTR, ""); //$NON-NLS-1$
if (containerHandle.length() > 0) {
IRubyElement element = RubyCore.create(containerHandle);
if (element != null) {
if (element.isType(IRubyElement.TYPE)) {
return new IType[] { (IType) element };
}
IRubyScript script = (IRubyScript) element;
if (script != null) {
IType type = script.findPrimaryType();
if (type != null)
return new IType[] { type };
}
}
}
String testTypeName= configuration.getAttribute(TESTTYPE_ATTR, (String) null);
if (testTypeName != null && testTypeName.length() > 0) {
return new IType[] {javaProject.findType(testTypeName, pm)};
}
return new IType[0];
}
protected void informAndAbort(String message, Throwable exception, int code) throws CoreException {
IStatus status= new Status(IStatus.INFO, TestunitPlugin.PLUGIN_ID, code, message, exception);
if (showStatusMessage(status))
throw new CoreException(status);
abort(message, exception, code);
}
private boolean showStatusMessage(final IStatus status) {
final boolean[] success= new boolean[] { false };
getDisplay().syncExec(
new Runnable() {
public void run() {
Shell shell= TestunitPlugin.getActiveWorkbenchShell();
if (shell == null)
shell= getDisplay().getActiveShell();
if (shell != null) {
MessageDialog.openInformation(shell, TestUnitMessages.JUnitBaseLaunchConfiguration_dialog_title, status.getMessage());
success[0]= true;
}
}
}
);
return success[0];
}
private Display getDisplay() {
Display display;
display= Display.getCurrent();
if (display == null)
display= Display.getDefault();
return display;
}
public static String getTestRunnerPath() {
// Copy test runner files over to workspace
IPath stateLocation = TestunitPlugin.getDefault().getStateLocation();
IPath versionFile = stateLocation.append("ruby").append("testRunnerV" + TEST_RUNNER_VERSION);
boolean force = !versionFile.toFile().exists();
RubyCore.copyToStateLocation(TestunitPlugin.getDefault(), new Path("ruby").append(TEST_RUNNER_FILE), force);
RubyCore.copyToStateLocation(TestunitPlugin.getDefault(), new Path("ruby").append("RemoteTestRunnerRSpec.rb"), force);
try
{
versionFile.toFile().createNewFile();
}
catch (IOException e)
{
// ignore
}
IPath path = TestunitPlugin.getDefault().getStateLocation().append(new Path("ruby").append(TEST_RUNNER_FILE));
if (!path.toFile().exists())
throw new RuntimeException("Expected directory of ruby/" + TEST_RUNNER_FILE + " does not exist: " + path);
return path.toPortableString();
}
private int getPort() {
if (port == -1) {
port = SocketUtil.findFreePort();
}
return port;
}
@Override
public String getProgramArguments(ILaunchConfiguration configuration) throws CoreException {
StringBuffer buffer = new StringBuffer();
buffer.append(getLaunchContainerPath(configuration));
buffer.append(' ');
buffer.append(Integer.toString(getPort()));
buffer.append(' ');
buffer.append(Boolean.toString(false));
buffer.append(' ');
buffer.append(configuration.getAttribute(TestUnitLaunchConfigurationDelegate.TESTTYPE_ATTR, ""));
buffer.append(' ');
buffer.append(configuration.getAttribute(TestUnitLaunchConfigurationDelegate.TESTNAME_ATTR, ""));
return buffer.toString();
}
private String getLaunchContainerPath(ILaunchConfiguration configuration) throws CoreException {
String container = configuration.getAttribute(TestUnitLaunchConfigurationDelegate.LAUNCH_CONTAINER_ATTR, "");
IRubyElement element = (IRubyElement) RubyCore.create(container);
if (element != null)
container = element.getResource().getProjectRelativePath().toOSString();
if (!container.startsWith("\"") && container.indexOf(' ') != -1) {
container = '"' + container + '"';
}
return container;
}
}