Java tutorial
/* * Copyright (c) 2012-2017 Red Hat, 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: * Red Hat, Inc. - initial API and implementation */ package org.eclipse.che.plugin.testing.testng.server; import static com.google.common.base.Strings.isNullOrEmpty; import static java.util.Collections.emptyMap; import static java.util.Collections.singletonList; import com.beust.jcommander.JCommander; import com.google.inject.name.Named; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.inject.Inject; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.eclipse.che.api.testing.shared.TestExecutionContext; import org.eclipse.che.commons.annotation.Nullable; import org.eclipse.che.commons.lang.execution.CommandLine; import org.eclipse.che.commons.lang.execution.ExecutionException; import org.eclipse.che.commons.lang.execution.JavaParameters; import org.eclipse.che.commons.lang.execution.ProcessHandler; import org.eclipse.che.plugin.java.testing.AbstractJavaTestRunner; import org.eclipse.che.plugin.java.testing.ClasspathUtil; import org.eclipse.che.plugin.java.testing.JavaTestAnnotations; import org.eclipse.che.plugin.java.testing.JavaTestFinder; import org.eclipse.che.plugin.java.testing.ProjectClasspathProvider; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMethod; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; /** TestNG implementation for the test runner service. */ public class TestNGRunner extends AbstractJavaTestRunner { private static final String TESTNG_NAME = "testng"; private static final Logger LOG = LoggerFactory.getLogger(TestNGRunner.class); private static final String JAVA_IO_TMPDIR = "java.io.tmpdir"; private String workspacePath; private JavaTestFinder javaTestFinder; private final ProjectClasspathProvider classpathProvider; private final TestNGSuiteUtil suiteUtil; @Inject public TestNGRunner(@Named("che.user.workspaces.storage") String workspacePath, JavaTestFinder javaTestFinder, ProjectClasspathProvider classpathProvider, TestNGSuiteUtil suiteUtil) { super(workspacePath, javaTestFinder); this.workspacePath = workspacePath; this.javaTestFinder = javaTestFinder; this.classpathProvider = classpathProvider; this.suiteUtil = suiteUtil; } @Override @Nullable public ProcessHandler execute(TestExecutionContext context) { IJavaProject javaProject = getJavaProject(context.getProjectPath()); if (javaProject.exists()) { return startTestProcess(javaProject, context); } return null; } private ProcessHandler startTestProcess(IJavaProject javaProject, TestExecutionContext context) { File suiteFile = createSuite(context, javaProject); if (suiteFile == null) { throw new RuntimeException("Can't create TestNG suite xml file."); } JavaParameters parameters = new JavaParameters(); parameters.setJavaExecutable(System.getProperty("java.home") + "/bin/java"); parameters.setMainClassName("org.testng.CheTestNGLauncher"); String outputDirectory = getOutputDirectory(javaProject); parameters.getParametersList().add("-d", outputDirectory); parameters.setWorkingDirectory(workspacePath + javaProject.getPath()); List<String> classPath = new ArrayList<>(); Set<String> projectClassPath = classpathProvider.getProjectClassPath(javaProject); classPath.addAll(projectClassPath); classPath.add(ClasspathUtil.getJarPathForClass(org.testng.CheTestNG.class)); classPath.add(ClasspathUtil.getJarPathForClass(JCommander.class)); parameters.getClassPath().addAll(classPath); parameters.getParametersList().add("-suiteFile", suiteFile.getAbsolutePath()); if (context.isDebugModeEnable()) { generateDebuggerPort(); parameters.getVmParameters().add("-Xdebug"); parameters.getVmParameters() .add("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=" + getDebugPort()); } CommandLine command = parameters.createCommand(); try { return new ProcessHandler(command.createProcess()); } catch (ExecutionException e) { LOG.error("Can't run TestNG JVM", e); } return null; } private File createSuite(TestExecutionContext context, IJavaProject javaProject) { String filePath = context.getFilePath(); if (!isNullOrEmpty(filePath) && filePath.endsWith(".xml")) { String path = filePath.substring(javaProject.getPath().toString().length(), filePath.length()); IFile file = javaProject.getProject().getFile(path); return suiteUtil.writeSuite(System.getProperty(JAVA_IO_TMPDIR), file); } List<String> testSuite = findTests(context, javaProject, JavaTestAnnotations.TESTNG_TEST.getName(), ""); Map<String, List<String>> classes = buildTestNgSuite(testSuite, context); return suiteUtil.writeSuite(System.getProperty(JAVA_IO_TMPDIR), javaProject.getElementName(), classes); } private Map<String, List<String>> buildTestNgSuite(List<String> tests, TestExecutionContext context) { switch (context.getContextType()) { case FILE: case FOLDER: case SET: case PROJECT: return createContainerSuite(tests); case CURSOR_POSITION: return createMethodSuite(tests); default: return emptyMap(); } } private Map<String, List<String>> createMethodSuite(List<String> tests) { if (tests.isEmpty()) { return Collections.emptyMap(); } String testMethodDeclaration = tests.get(0); int separatorIndex = testMethodDeclaration.indexOf('#'); if (separatorIndex == -1) { return createContainerSuite(tests); } return Collections.singletonMap(testMethodDeclaration.substring(0, separatorIndex), singletonList(testMethodDeclaration.substring(separatorIndex + 1))); } private Map<String, List<String>> createContainerSuite(List<String> tests) { if (tests.isEmpty()) { return emptyMap(); } Map<String, List<String>> classes = new HashMap<>(tests.size()); for (String testClass : tests) { classes.put(testClass, null); } return classes; } /** {@inheritDoc} */ @Override public String getName() { return TESTNG_NAME; } @Override protected boolean isTestMethod(IMethod method, ICompilationUnit compilationUnit) { return javaTestFinder.isTest(method, compilationUnit, JavaTestAnnotations.TESTNG_TEST.getName()); } @Override protected boolean isTestSuite(String filePath, IJavaProject project) { int projectPathLength = project.getPath().toString().length(); String path = filePath.substring(projectPathLength, filePath.length()); IFile file = project.getProject().getFile(path); if (!file.exists()) { return false; } SAXParserFactory factory = SAXParserFactory.newInstance(); TestNGSuiteParser suiteParser = new TestNGSuiteParser(); try { SAXParser parser = factory.newSAXParser(); parser.parse(file.getContents(), suiteParser); } catch (ParserConfigurationException | SAXException | IOException e) { LOG.error("It is not possible to parse file " + path, e); } catch (CoreException e) { LOG.error("It is not possible to read file " + path, e); } return suiteParser.isSuite(); } }