blob: 10ff3748d096764d3d2225d1fd9288d87f57b485 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 Red Hat Inc. and others
*
* 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:
* Red Hat, Inc. - initial API and Implementation
*******************************************************************************/
package org.eclipse.dltk.ruby.testing.internal.miniunit;
import java.io.File;
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.MethodDeclaration;
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.InterpreterConfig;
import org.eclipse.dltk.ruby.ast.RubyClassDeclaration;
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 MiniTestingEngine extends AbstractRubyTestingEngine {
static class TestUnitValidateVisitor extends AbstractTestingEngineValidateVisitor {
private static final String MINITEST_AUTORUN = "minitest/autorun"; //$NON-NLS-1$
private static final String MINITEST_TEST = "Minitest::Test"; //$NON-NLS-1$
private static final String TEST = "test"; //$NON-NLS-1$
private ISourceModule module;
private int testUnitWeight = 0;
static final int REQUIRE_WEIGHT = 10;
static final int TESTCASE_WEIGHT = 10;
static final int METHOD_WEIGHT = 1;
public TestUnitValidateVisitor(ISourceModule module) {
this.module = module;
}
@Override
public boolean visitGeneral(ASTNode node) throws Exception {
if (node instanceof CallExpression) {
final CallExpression call = (CallExpression) node;
if (isRequire(call, MINITEST_AUTORUN)) {
testUnitWeight += REQUIRE_WEIGHT;
}
} else if (node instanceof RubyClassDeclaration) {
if (isSuperClassOf(module, (RubyClassDeclaration) node, MINITEST_TEST)) {
testUnitWeight += TESTCASE_WEIGHT;
}
} else if (node instanceof MethodDeclaration) {
if (isNodeOnStack(RubyClassDeclaration.class) && isMethodPrefix((MethodDeclaration) node, TEST)) {
testUnitWeight += METHOD_WEIGHT;
}
}
return super.visitGeneral(node);
}
public IStatus getStatus() {
if (testUnitWeight >= Math.min(REQUIRE_WEIGHT, TESTCASE_WEIGHT)) {
return Status.OK_STATUS;
}
if (testUnitWeight >= METHOD_WEIGHT) {
return createStatus(IStatus.INFO, Messages.validate_probablyMinitest);
}
return createStatus(IStatus.WARNING, Messages.validate_notMinitest);
}
}
@Override
public IStatus validateSourceModule(ISourceModule module) {
final ModuleDeclaration declaration = ResolverUtils.parse(module);
if (declaration == null) {
return createStatus(IStatus.WARNING, Messages.validate_sourceErrors);
}
final TestUnitValidateVisitor visitor = new TestUnitValidateVisitor(module);
try {
declaration.traverse(visitor);
} catch (Exception e) {
return createStatus(IStatus.WARNING, NLS.bind(Messages.validate_runtimeError, e.getMessage()));
}
return visitor.getStatus();
}
static final String MINITEST_RUNNER = "dltk-minitest-runner.rb"; //$NON-NLS-1$
@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);
// add runner
if (!RubyTestingLaunchConfigurationDelegate.isContainerMode(configuration)) {
if (config.getEnvironment().isLocal()) {
final String runnerName = MINITEST_RUNNER;
if (!isDevelopmentMode(config, runnerName)) {
final File runnerFile = getRunnerFile(getBundle(), RUNNER_PATH, runnerName);
config.addInterpreterArg("-r"); //$NON-NLS-1$
config.addInterpreterArg(runnerFile.getPath());
}
}
} 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);
final IPath path = resource.getProjectRelativePath();
if (path.isEmpty()) {
config.addEnvVar(RUBY_TESTING_PATH, "."); //$NON-NLS-1$
} else {
config.addEnvVar(RUBY_TESTING_PATH, path.toOSString());
}
}
}
@Override
public String getMainScriptPath(ILaunchConfiguration configuration, IEnvironment scriptEnvironment)
throws CoreException {
if (RubyTestingLaunchConfigurationDelegate.isContainerMode(configuration)) {
return getRunnerFile(getBundle(), RUNNER_PATH, MINITEST_RUNNER).getPath();
} else {
return null;
}
}
@Override
public ITestRunnerUI getTestRunnerUI(IScriptProject project, ILaunchConfiguration configuration) {
return new MiniTestRunnerUI(this, project);
}
}