| /* |
| * 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) { } |
| } |
| } |
| } |