blob: 4393e154d909c73a1e19a4490a12ba44eb98b28c [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.testng.ant;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.tools.ant.module.api.support.ActionUtils;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.project.classpath.ProjectClassPathModifier;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.libraries.Library;
import org.netbeans.api.project.libraries.LibraryManager;
import org.netbeans.modules.java.testrunner.JavaUtils;
import org.netbeans.modules.testng.api.TestNGSupport.Action;
import org.netbeans.modules.testng.spi.TestConfig;
import org.netbeans.modules.testng.spi.TestNGSupportImplementation;
import org.netbeans.spi.project.ProjectServiceProvider;
import org.netbeans.spi.project.ant.AntArtifactProvider;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.lookup.ServiceProvider;
/**
*
* @author lukas
*/
@ServiceProvider(service = TestNGSupportImplementation.class)
public class AntTestNGSupport extends TestNGSupportImplementation {
private static final Logger LOGGER = Logger.getLogger(AntTestNGSupport.class.getName());
private static final Set<Action> SUPPORTED_ACTIONS;
static {
Set<Action> s = new HashSet<Action>();
// s.add(Action.CREATE_TEST);
// s.add(Action.RUN_FAILED);
// s.add(Action.RUN_TESTMETHOD);
s.add(Action.RUN_TESTSUITE);
// s.add(Action.DEBUG_TEST);
// s.add(Action.DEBUG_TESTMETHOD);
s.add(Action.DEBUG_TESTSUITE);
SUPPORTED_ACTIONS = Collections.unmodifiableSet(s);
}
@Override
public boolean isSupportEnabled(FileObject[] activatedFOs) {
return JavaUtils.isSupportEnabled(AntArtifactProvider.class, activatedFOs);
}
@Override
public boolean isActionSupported(Action action, Project p) {
return p != null && p.getLookup().lookup(AntArtifactProvider.class) != null && SUPPORTED_ACTIONS.contains(action);
}
@Override
public void configureProject(FileObject createdFile) {
assert createdFile != null;
Project p = FileOwnerQuery.getOwner(createdFile);
ClassPath cp = ClassPath.getClassPath(createdFile, ClassPath.COMPILE);
FileObject ng = cp.findResource("org.testng.annotations.Test"); //NOI18N
if (ng == null) {
// add library to the project
Library nglib = LibraryManager.getDefault().getLibrary("testng"); //NOI18N
try {
if (!ProjectClassPathModifier.addLibraries(new Library[]{nglib}, createdFile, ClassPath.COMPILE)) {
LOGGER.log(Level.FINE, "TestNG library not added to project {0}", p); //NOI18N
}
} catch (IOException ex) {
Logger.getLogger(AntTestNGSupport.class.getName()).log(Level.SEVERE, null, ex);
} catch (UnsupportedOperationException ex) {
Logger.getLogger(AntTestNGSupport.class.getName()).log(Level.SEVERE, null, ex);
}
}
// AntBuildExtender extender = p.getLookup().lookup(AntBuildExtender.class);
// if (extender != null) {
// String ID = "test-ng-1.0"; //NOI18N
// Extension extension = extender.getExtension(ID);
// if (extension == null) {
// LOGGER.log(Level.FINER, "Extensible targets: {0}", extender.getExtensibleTargets());
// try {
// // create testng-build.xml
// FileObject testng = p.getProjectDirectory().getFileObject("nbproject").createData("testng-impl", "xml"); //NOI18N
// InputStream is = AntTestNGSupport.class.getResourceAsStream("testng-build.xml"); //NOI18N
// FileLock lock = testng.lock();
// OutputStream os = testng.getOutputStream(lock);
// try {
// FileUtil.copy(is, os);
// } finally {
// if (is != null) {
// is.close();
// }
// if (os != null) {
// os.close();
// }
// lock.releaseLock();
// }
// extension = extender.addExtension(ID, testng);
// extension.addDependency("-pre-pre-compile", "-reinit-tasks"); //NOI18N
// ProjectManager.getDefault().saveProject(p);
// } catch (IOException ex) {
// LOGGER.log(Level.SEVERE, null, ex);
// }
// }
// }
}
@Override
public TestExecutor createExecutor(Project p) {
return new AntExecutor(p);
}
private static class AntExecutor implements TestNGSupportImplementation.TestExecutor {
private static final String failedConfPath = "build/test/results/testng-failed.xml"; //NOI18N
private Project p;
public AntExecutor(Project p) {
this.p = p;
}
@Override
public boolean hasFailedTests() {
FileObject projectHome = p.getProjectDirectory();
//XXX - should rather listen on a fileobject??
FileUtil.refreshFor(FileUtil.toFile(projectHome));
FileObject failedTestsConfig = projectHome.getFileObject(failedConfPath);
return failedTestsConfig != null && failedTestsConfig.isValid();
}
@Override
public void execute(Action action, TestConfig config) throws IOException {
FileObject projectHome = p.getProjectDirectory();
Properties props = new Properties();
String cmd = null;
FileObject test = config.getTest();
ClassPath classPath = ClassPath.getClassPath(test, ClassPath.SOURCE);
if(classPath == null) {
LOGGER.log(Level.WARNING, "Could not find any classpath for file {0}", FileUtil.toFile(test)); //NOI18N
return;
}
FileObject[] testRoots = classPath.getRoots();
FileObject testRoot = null;
for (FileObject root : testRoots) {
if (FileUtil.isParentOf(root, test)) {
testRoot = root;
break;
}
}
if (Action.RUN_TESTSUITE.equals(action)) {
cmd = "test-single"; //NOI18N
String xml = FileUtil.getRelativePath(testRoot, test);
assert xml != null;
props.put("test.includes", xml); //NOI18N
if (isNbModuleProject()) {
props.setProperty("continue.after.failing.tests", "true"); //NOI18N
}
} else if (Action.DEBUG_TESTSUITE.equals(action)) {
if (isNbModuleProject()) {
cmd = "debug-test-single-nb"; //NOI18N
String xml = FileUtil.getRelativePath(testRoot, test);
assert xml != null;
props.put("test.class", xml); //NOI18N
props.setProperty("continue.after.failing.tests", "true"); //NOI18N
} else {
cmd = "debug-test"; //NOI18N
props.put("test.class", "'".concat(FileUtil.toFile(test).getAbsolutePath()).concat("'")); //NOI18N
}
} else if (Action.RUN_TESTMETHOD.equals(action)) {
if (isNbModuleProject()) {
cmd = "test-method"; //NOI18N
props.put("test.class", config.getPackageName() + "." + config.getClassName()); //NOI18N
props.put("test.methods", config.getMethodName()); //NOI18N
props.setProperty("continue.after.failing.tests", "true"); //NOI18N
} else {
cmd = "test-single-method"; //NOI18N
props.put("test.class", config.getPackageName() + "." + config.getClassName()); //NOI18N
props.put("test.method", config.getMethodName()); //NOI18N
}
} else if (Action.DEBUG_TESTMETHOD.equals(action)) {
if (isNbModuleProject()) {
cmd = "debug-test-single-nb"; //NOI18N
props.put("test.class", config.getPackageName() + "." + config.getClassName()); //NOI18N
props.put("test.methods", config.getMethodName()); //NOI18N
props.setProperty("continue.after.failing.tests", "true"); //NOI18N
} else {
cmd = "debug-test-method"; //NOI18N
props.put("test.class", config.getPackageName() + "." + config.getClassName()); //NOI18N
props.put("test.method", config.getMethodName()); //NOI18N
}
}
assert cmd != null : "Unsupported action: " + action; //NOI18N
props.put("javac.includes", ActionUtils.antIncludesList(new FileObject[]{testRoot}, testRoot, true)); //NOI18N
props.setProperty("ignore.failing.tests", "true"); //NOI18N
FileObject buildFO = projectHome.getFileObject("build.xml"); //NOI18N
if(buildFO == null) {
LOGGER.log(Level.WARNING, "Could not locate build.xml for project in {0}", projectHome); //NOI18N
return;
}
ActionUtils.runTarget(buildFO, new String[]{cmd}, props);
}
private boolean isNbModuleProject() {
return p.getLookup().lookup(AntTestNGSupportProjectServiceProvider.class) != null;
}
@ProjectServiceProvider(service = AntTestNGSupportProjectServiceProvider.class, projectType = "org-netbeans-modules-apisupport-project")
public static class AntTestNGSupportProjectServiceProvider {
public AntTestNGSupportProjectServiceProvider(Project p) { }
}
}
}