blob: 9db6d243261e5209614a1f3f53c2df89ed847dc9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2016 xored software, Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* xored software, Inc. - initial API and Implementation (Alex Panchenko)
*******************************************************************************/
package org.eclipse.dltk.ruby.testing.internal.rspec;
import java.util.Stack;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
import org.eclipse.dltk.ast.expressions.CallExpression;
import org.eclipse.dltk.compiler.util.Util;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.environment.IEnvironment;
import org.eclipse.dltk.launching.AbstractScriptLaunchConfigurationDelegate;
import org.eclipse.dltk.launching.InterpreterConfig;
import org.eclipse.dltk.ruby.testing.internal.AbstractRubyTestingEngine;
import org.eclipse.dltk.ruby.testing.internal.AbstractTestingEngineValidateVisitor;
import org.eclipse.dltk.ruby.testing.internal.Messages;
import org.eclipse.dltk.ruby.testing.internal.ResolverUtils;
import org.eclipse.dltk.ruby.testing.internal.RubyTestingLaunchConfigurationDelegate;
import org.eclipse.dltk.testing.DLTKTestingConstants;
import org.eclipse.dltk.testing.ITestRunnerUI;
import org.eclipse.osgi.util.NLS;
public class RspecTestingEngine extends AbstractRubyTestingEngine {
static class RSpecValidateVisitor extends
AbstractTestingEngineValidateVisitor {
private static final String RSPEC = "spec"; //$NON-NLS-1$
private int weight = 0;
static final int REQUIRE_WEIGHT = 9;
static final int TEST_WEIGHT = 3;
@Override
public boolean visitGeneral(ASTNode node) throws Exception {
if (node instanceof CallExpression) {
final CallExpression call = (CallExpression) node;
if (isRequire(call, RSPEC)) {
weight += REQUIRE_WEIGHT;
} else if (isMethodCall(call, RSpecUtils.CONTEXT_METHODS)
|| isMethodCall(call, RSpecUtils.SHARED_GROUP)) {
contextCalls.push(node);
} else if (!contextCalls.isEmpty()
&& (isMethodCall(call, RSpecUtils.TEST_METHODS) || isMethodCall(
call, RSpecUtils.TEST_SHARED))) {
weight += TEST_WEIGHT;
}
}
return super.visitGeneral(node);
}
@Override
public void endvisitGeneral(ASTNode node) throws Exception {
if (!contextCalls.isEmpty()) {
if (contextCalls.peek() == node) {
contextCalls.pop();
}
}
super.endvisitGeneral(node);
}
private final Stack contextCalls = new Stack();
public IStatus getStatus() {
if (weight >= REQUIRE_WEIGHT + TEST_WEIGHT) {
return Status.OK_STATUS;
}
if (weight >= TEST_WEIGHT) {
return createStatus(IStatus.INFO,
Messages.validate_probablyRSpec);
}
return createStatus(IStatus.WARNING, Messages.validate_notRSpec);
}
}
@Override
public IStatus validateSourceModule(ISourceModule module) {
final ModuleDeclaration declaration = ResolverUtils.parse(module);
if (declaration == null) {
return createStatus(IStatus.WARNING, Messages.validate_sourceErrors);
}
final RSpecValidateVisitor visitor = new RSpecValidateVisitor();
try {
declaration.traverse(visitor);
} catch (Exception e) {
return createStatus(IStatus.WARNING, NLS.bind(
Messages.validate_runtimeError, e.getMessage()));
}
return visitor.getStatus();
}
static final String RSPEC_RUNNER = "dltk-rspec-runner.rb"; //$NON-NLS-1$
@Override
public String getMainScriptPath(ILaunchConfiguration configuration,
IEnvironment scriptEnvironment) throws CoreException {
return getRunnerFile(getBundle(), RUNNER_PATH, RSPEC_RUNNER).getPath();
}
@Override
public void configureLaunch(InterpreterConfig config,
ILaunchConfiguration configuration, ILaunch launch)
throws CoreException {
// select port number
final String strPort = String.valueOf(allocatePort());
launch.setAttribute(DLTKTestingConstants.ATTR_PORT, strPort);
config.addEnvVar(RUBY_TESTING_PORT, strPort);
final String failureNames = configuration.getAttribute(
DLTKTestingConstants.ATTR_FAILURES_NAMES, Util.EMPTY_STRING);
if (failureNames.length() != 0) {
config.addScriptArg("-e"); //$NON-NLS-1$
config.addScriptArg(failureNames);
}
if (!RubyTestingLaunchConfigurationDelegate
.isContainerMode(configuration)) {
final String mainScript = AbstractScriptLaunchConfigurationDelegate
.getMainScriptName(configuration);
// ssanders - Fully qualify the script path, otherwise it won't be
// found for nested folders
final IScriptProject scriptProject = AbstractScriptLaunchConfigurationDelegate
.getScriptProject(configuration);
final IPath scriptPath = scriptProject.getProject().getLocation()
.append(mainScript);
config.addScriptArg(config.getEnvironment().getFile(scriptPath)
.toOSString());
} else {
final String containerHandle = configuration
.getAttribute(DLTKTestingConstants.ATTR_TEST_CONTAINER,
Util.EMPTY_STRING);
Assert.isLegal(containerHandle.length() != 0);
IModelElement element = DLTKCore.create(containerHandle);
Assert.isNotNull(element);
IResource resource = element.getUnderlyingResource();
Assert.isNotNull(resource);
config.addScriptArg(resource.getLocation().toOSString());
}
}
/*
* @see org.eclipse.dltk.testing.ITestingEngine#getTestRunnerUI()
*/
@Override
public ITestRunnerUI getTestRunnerUI(IScriptProject project,
ILaunchConfiguration configuration) {
return new RSpecTestRunnerUI(this, project);
}
}