package org.testng.eclipse.ui.util; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.variables.VariablesPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; import org.eclipse.jface.preference.IPreferenceStore; import org.testng.eclipse.TestNGPlugin; import org.testng.eclipse.TestNGPluginConstants; import org.testng.eclipse.launch.ITestNGLaunchConfigurationProvider; import org.testng.eclipse.launch.TestNGLaunchConfigurationConstants; import org.testng.eclipse.launch.TestNGLaunchConfigurationConstants.LaunchType; import org.testng.eclipse.launch.TestNGLaunchConfigurationConstants.Protocols; import org.testng.eclipse.ui.RunInfo; import org.testng.eclipse.util.JDTUtil; import org.testng.eclipse.util.StringUtils; import org.testng.eclipse.util.SuiteGenerator; import org.testng.eclipse.util.param.ParameterSolver; import org.testng.remote.RemoteTestNG; import org.testng.xml.LaunchSuite; /** * Helper methods to store and retrieve values from a launch configuration. * * @author cbeust */ public class ConfigurationHelper { public static class LaunchInfo { private String m_projectName; private LaunchType m_launchType; private Collection<String> m_classNames; private Collection<String> m_packageNames; private Map<String, List<String>> m_classMethods; private String m_suiteName; private Map<String, List<String>> m_groupMap = new HashMap<>(); private String m_logLevel; private boolean m_verbose; private boolean m_debug; private Protocols m_protocol; public LaunchInfo(String projectName, LaunchType launchType, Collection<String> classNames, Collection<String> packageNames, Map<String, List<String>> classMethodsMap, Map<String, List<String>> groupMap, String suiteName, String logLevel, boolean verbose, boolean debug, Protocols protocol) { m_projectName= projectName; m_launchType= launchType; m_classNames= classNames; m_classMethods= classMethodsMap; m_groupMap= groupMap; m_suiteName= suiteName.trim(); m_logLevel= logLevel; m_packageNames = packageNames; m_verbose = verbose; m_debug = debug; m_protocol = protocol; } } public static int getLogLevel(ILaunchConfiguration config) { String stringResult = getStringAttribute(config, TestNGLaunchConfigurationConstants.LOG_LEVEL); if(null == stringResult) { return TestNGLaunchConfigurationConstants.DEFAULT_LOG_LEVEL; } else { return Integer.parseInt(stringResult); } } public static boolean getVerbose(ILaunchConfiguration config) { return getBooleanAttribute(config, TestNGLaunchConfigurationConstants.VERBOSE); } public static boolean getDebug(ILaunchConfiguration config) { return getBooleanAttribute(config, TestNGLaunchConfigurationConstants.DEBUG); } public static Protocols getProtocol(ILaunchConfiguration config) { String stringResult = getStringAttribute(config, TestNGLaunchConfigurationConstants.PROTOCOL); return null == stringResult ? TestNGLaunchConfigurationConstants.DEFAULT_SERIALIZATION_PROTOCOL : Protocols.get(stringResult); } public static String getSourcePath(ILaunchConfiguration config) { return getStringAttribute(config, TestNGLaunchConfigurationConstants.DIRECTORY_TEST_LIST); } public static List<String> getGroups(ILaunchConfiguration config) { return getListAttribute(config, TestNGLaunchConfigurationConstants.GROUP_LIST); } public static List<String> getGroupClasses(ILaunchConfiguration config) { return getListAttribute(config, TestNGLaunchConfigurationConstants.GROUP_CLASS_LIST); } public static List<String> getClasses(ILaunchConfiguration config) { return getListAttribute(config, TestNGLaunchConfigurationConstants.CLASS_TEST_LIST); } public static List<String> getPackages(ILaunchConfiguration config) { return getListAttribute(config, TestNGLaunchConfigurationConstants.PACKAGE_TEST_LIST); } public static List<String> getSuites(ILaunchConfiguration config) { return getListAttribute(config, TestNGLaunchConfigurationConstants.SUITE_TEST_LIST); } public static List<String> getSources(ILaunchConfiguration config) { return getListAttribute(config, TestNGLaunchConfigurationConstants.SOURCE_TEST_LIST); } public static String getProjectName(ILaunchConfiguration config) { return getStringAttribute(config, IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME); } public static String getMain(ILaunchConfiguration configuration) { return getStringAttribute(configuration, IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME); } public static List<String> getMethods(ILaunchConfiguration configuration) { return getListAttribute(configuration, TestNGLaunchConfigurationConstants.METHOD_TEST_LIST); } private static String getProjectJvmArgs() { IPreferenceStore store = TestNGPlugin.getDefault().getPreferenceStore(); String result = store.getString(TestNGPluginConstants.S_JVM_ARGS); return result; } /** * @return the JVM args from the configuration or, if not found, from the preferences. */ public static String getJvmArgs(ILaunchConfiguration configuration) throws CoreException { StringBuilder jvmArgs = new StringBuilder(); jvmArgs.append(TestNGLaunchConfigurationConstants.VM_ENABLEASSERTION_OPTION); // JVM args from the previous configuration take precedence over the preference jvmArgs.append(" ").append(configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, getProjectJvmArgs())); for (ITestNGLaunchConfigurationProvider lcp : TestNGPlugin.getLaunchConfigurationProviders()) { String args = lcp.getVmArguments(configuration); if (args != null && !args.isEmpty()) { jvmArgs.append(" ").append(args); } } addDebugProperties(jvmArgs, configuration); return VariablesPlugin.getDefault().getStringVariableManager() .performStringSubstitution(jvmArgs.toString()); } /** * Add the debug and/or verbose properties of RemoteTestNG if user specified */ private static void addDebugProperties(StringBuilder vmArgs, ILaunchConfiguration config) { if (getVerbose(config)) { vmArgs.append(" -D" + RemoteTestNG.PROPERTY_VERBOSE); } if (getDebug(config)) { vmArgs.append(" -D" + RemoteTestNG.PROPERTY_DEBUG); } } public static IJavaProject getJavaProject(ILaunchConfiguration configuration) throws CoreException { String projectName = getProjectName(configuration); if (projectName != null) { projectName = projectName.trim(); if (projectName.length() > 0) { IProject project = ResourcesPlugin.getWorkspace().getRoot() .getProject(projectName); IJavaProject javaProject = JavaCore.create(project); if (javaProject != null && javaProject.exists()) { return javaProject; } } } return null; } public static ILaunchConfigurationWorkingCopy setJvmArgs( ILaunchConfigurationWorkingCopy configuration, String args) { configuration.setAttribute( IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, args); return configuration; } public static LaunchType getType(ILaunchConfiguration configuration) { int result = getIntAttribute(configuration, TestNGLaunchConfigurationConstants.TYPE); return LaunchType.fromInt(result); } public static String getProjectName(ILaunch launch) { return launch.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME); } public static int getPort(ILaunch launch) { try { return Integer.parseInt(launch.getAttribute(TestNGLaunchConfigurationConstants.PORT)); } catch(Throwable thr) { return 0; } } public static String getSubName(ILaunch launch) { return launch.getAttribute(TestNGLaunchConfigurationConstants.TESTNG_RUN_NAME_ATTR); } ///////////////////// private static Map<String, String> getMapAttribute(ILaunchConfiguration config, String attr) { Map<String, String> result = null; try { result = config.getAttribute(attr, result); } catch(CoreException cex) { TestNGPlugin.log(cex); } return result; } private static List<String> getListAttribute(ILaunchConfiguration config, String attr) { List<String> result = null; try { result = config.getAttribute(attr, result); } catch (CoreException e) { TestNGPlugin.log(e); } return result; } private static String getStringAttribute(ILaunchConfiguration config, String attr) { String result = null; try { result = config.getAttribute(attr, result); } catch (CoreException e) { TestNGPlugin.log(e); } return result; } private static int getIntAttribute(ILaunchConfiguration config, String attr) { int result = 0; try { result = config.getAttribute(attr, result); } catch (CoreException e) { TestNGPlugin.log(e); } return result; } private static boolean getBooleanAttribute(ILaunchConfiguration config, String attr) { return getBooleanAttribute(config, attr, false); } private static boolean getBooleanAttribute(ILaunchConfiguration config, String attr, boolean defaultValue) { boolean result = defaultValue; try { result = config.getAttribute(attr, result); } catch (CoreException e) { TestNGPlugin.log(e); } return result; } public static ILaunchConfigurationWorkingCopy createBasicConfiguration(final ILaunchManager launchManager, final IProject project, final String confName) { ILaunchConfigurationWorkingCopy wConf = null; try { ILaunchConfigurationType configurationType = launchManager.getLaunchConfigurationType(TestNGLaunchConfigurationConstants.ID_TESTNG_APPLICATION); wConf = configurationType.newInstance(null /*project*/, confName); // launchManager.generateUniqueLaunchConfigurationNameFrom(confName)); wConf.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, RemoteTestNG.class.getName()); wConf.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, project.getName()); } catch(CoreException ce) { TestNGPlugin.log(ce); } return wConf; } /** * @param selectedProject */ public static void createBasicConfiguration(IJavaProject javaProject, ILaunchConfigurationWorkingCopy config) { final String projectName = (javaProject == null) ? "" : javaProject.getElementName(); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, projectName); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, RemoteTestNG.class.getName()); config.setAttribute(TestNGLaunchConfigurationConstants.TYPE, LaunchType.CLASS.ordinal()); config.setAttribute(TestNGLaunchConfigurationConstants.LOG_LEVEL, String.valueOf(TestNGLaunchConfigurationConstants.DEFAULT_LOG_LEVEL)); } /** * @return List<LaunchSuite> * @throws CoreException */ public static List<LaunchSuite> getLaunchSuites(IJavaProject ijp, ILaunchConfiguration configuration) throws CoreException { LaunchType type = ConfigurationHelper.getType(configuration); List<String> packages= null; List<String> testClasses = null; List<String> groups = null; Map<String, List<String>> classMethods= null; if (type == LaunchType.SUITE) { return createLaunchSuites(ijp.getProject(), getSuites(configuration)); } if (type == LaunchType.GROUP) { groups = getGroups(configuration); testClasses = getGroupClasses(configuration); packages= getListAttribute(configuration, TestNGLaunchConfigurationConstants.PACKAGE_TEST_LIST); } else if (type == LaunchType.CLASS) { testClasses = getClasses(configuration); } else if (type == LaunchType.METHOD) { classMethods= getClassMethods(configuration); } else if (type == LaunchType.PACKAGE) { packages= getListAttribute(configuration, TestNGLaunchConfigurationConstants.PACKAGE_TEST_LIST); } // ~~ // collect test parameters // List<IJavaElement> je = new ArrayList<>(); if (packages != null) { for (String pkg : packages) { for (IPackageFragment pf : ijp.getPackageFragments()) { if (pf.getElementName().equals(pkg)) { je.add(pf); break; } } } } if (testClasses != null) { for (String clz : testClasses) { IType t = ijp.findType(clz); if (t != null) { je.add(t); } } } if (classMethods != null) { for (Entry<String, List<String>> entry : classMethods.entrySet()) { IType t = ijp.findType(entry.getKey()); if (t != null) { for (String mthd : entry.getValue()) { IMethod m = JDTUtil.solveMethod(t, mthd); if (m == null) { throw new JavaModelException(new CoreException(TestNGPlugin.createError( "no test method [" + mthd + "] was found"))); } je.add(m); } } } } Map<String, String> parameters= ParameterSolver.solveParameters(je.toArray(new IJavaElement[je.size()])); // ~~ IPath workingDirectory = getWorkingDirectoryPath(configuration); String workingDir; if (workingDirectory == null) { workingDir = getDefaultWorkingDirectory(configuration).getAbsolutePath(); } else { workingDir = workingDirectory.toOSString(); } return createLaunchSuites(ijp.getProject().getName(), packages, testClasses, classMethods, groups, parameters, getLogLevel(configuration), workingDir ); } public static IPath getWorkingDirectoryPath(ILaunchConfiguration configuration) throws CoreException { String path = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, (String) null); if (path != null) { path = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(path); return new Path(path); } return null; } protected static File getDefaultWorkingDirectory(ILaunchConfiguration configuration) throws CoreException { // default working directory is the project if this config has a project IJavaProject jp = getJavaProject(configuration); if (jp != null) { IProject p = jp.getProject(); // p.getLocation() will be null in the case where the location is relative to an undefined workspace path variable. if (p.getLocation() != null) { return p.getLocation().toFile(); } } return null; } public static Map<String, List<String>> getClassMethods(ILaunchConfiguration configuration) { Map<String, String> confResult = getMapAttribute(configuration, TestNGLaunchConfigurationConstants.ALL_METHODS_LIST); if(null == confResult) return null; Map<String, List<String>> results= new HashMap<String, List<String>>(); for (Map.Entry<String, String> entry : confResult.entrySet()) { String className= entry.getKey(); String methodNames= entry.getValue(); results.put(className, Arrays.asList(methodNames.split(";"))); } return results; } /** * @return List<LaunchSuite> */ private static List<LaunchSuite> createLaunchSuites(final IProject project, List<String> suites) { List<LaunchSuite> result = new ArrayList<>(); for (String suitePath : suites) { File suiteFile= new File(suitePath); if(suiteFile.exists() && suiteFile.isFile()) { } else { suiteFile= project.getFile(suitePath).getLocation().toFile(); } result.add(SuiteGenerator.createProxiedXmlSuite(suiteFile)); } return result; } /** * Custom Eclipse plugin suite generator. Instead of using TestNG core * suite generator, we are using a set of custom generators that allow * more customization. */ private static List<LaunchSuite> createLaunchSuites(String projectName, List<String> packages, List<String> classNames, Map<String, List<String>> classMethods, List<String> groupNames, Map<String, String> parameters, final int logLevel, final String workingDir) { return Arrays.asList( new LaunchSuite[] { SuiteGenerator.createCustomizedSuite(projectName, packages, classNames, classMethods, groupNames, parameters, logLevel, workingDir) }); } /** * Looks for an available configuration that matches the project and confName parameters. * If the defaultConfiguration is not null, it is used. The * defaultConfiguration may be null, which may cause null to be returned if there is not * an exact match for the project and confName parameters. This method was added to allow * the FailureTab to pass along the previous configuration for re-use, so that any jvm args * defined there will be used. * @param launchManager * @param project * @param confName * @param defaultConfiguration * @return */ public static ILaunchConfiguration findConfiguration(ILaunchManager launchManager, IProject project, String confName, RunInfo runInfo) { ILaunchConfiguration resultConf = null; try { ILaunchConfigurationType confType = launchManager .getLaunchConfigurationType(TestNGLaunchConfigurationConstants.ID_TESTNG_APPLICATION); ; ILaunchConfiguration[] availConfs = launchManager .getLaunchConfigurations(confType); final String projectName = project.getName(); final String mainRunner = TestNGPluginConstants.MAIN_RUNNER; for (ILaunchConfiguration availConf : availConfs) { String confProjectName = ConfigurationHelper .getProjectName(availConf); String confMainName = ConfigurationHelper .getMain(availConf); if (projectName.equals(confProjectName) && mainRunner.equals(confMainName) ) { if (confName != null && confName.equals(availConf.getName())) { resultConf = availConf; break; } else if (runInfo != null) { Map<String, List<String>> availableClassMethods = getClassMethods(availConf); String method = runInfo.getMethodName(); if (method != null && availableClassMethods != null) { String className = runInfo.getClassName(); List<String> methods = availableClassMethods.get(className); if (methods != null) { if (methods.size() == 1) { String available = (String) methods.get(0); if (method.equalsIgnoreCase(available)) { resultConf = availConf; break; } } } } }// else if // TODO: else complain about no reference parameters }// if } // for } catch (CoreException ce) { ; // IGNORE } return resultConf; } public static Map<String, String> toClassMethodsMap(Map<String, Collection<String>> classMethods) { Map<String, String> result= new HashMap<String, String>(); for (Map.Entry<String, Collection<String>> entry : classMethods.entrySet()) { String clsName = entry.getKey(); Collection<String> methods= entry.getValue(); StringBuffer strMethods = new StringBuffer(); int i = 0; for (String method : methods) { if (i++ > 0) strMethods.append(";"); strMethods.append(method); } result.put(clsName, strMethods.toString()); } return result; } /** * @param configuration */ public static void updateLaunchConfiguration(ILaunchConfigurationWorkingCopy configuration, LaunchInfo launchInfo) { Map<String, Collection<String>> classMethods = new HashMap<>(); if (launchInfo.m_groupMap != null) { Collection<List<String>> classes= launchInfo.m_groupMap.values(); if(null != classes) { for (List<String> classList : classes) { for (String c : classList) { classMethods.put(c, Collections.<String>emptyList()); } } } } Collection<String> classNames= launchInfo.m_classNames; List<String> classNamesList= new ArrayList<String>(); if(null != classNames && !classNames.isEmpty()) { for (String cls : classNames) { classMethods.put(cls, Collections.<String>emptyList()); classNamesList.add(cls); } } List<String> packageList = new ArrayList<String>(); if (launchInfo.m_packageNames != null) { packageList.addAll(launchInfo.m_packageNames); } if(null != launchInfo.m_classMethods) { classMethods.putAll(launchInfo.m_classMethods); } configuration.setAttribute(TestNGLaunchConfigurationConstants.TYPE, launchInfo.m_launchType.ordinal()); configuration.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, launchInfo.m_projectName); configuration.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, RemoteTestNG.class.getName()); configuration.setAttribute(TestNGLaunchConfigurationConstants.CLASS_TEST_LIST, classNamesList); configuration.setAttribute(TestNGLaunchConfigurationConstants.PACKAGE_TEST_LIST, packageList); configuration.setAttribute(TestNGLaunchConfigurationConstants.GROUP_LIST, new ArrayList<String>(launchInfo.m_groupMap.keySet())); configuration.setAttribute(TestNGLaunchConfigurationConstants.GROUP_CLASS_LIST, Utils.uniqueMergeList(launchInfo.m_groupMap.values())); configuration.setAttribute(TestNGLaunchConfigurationConstants.SUITE_TEST_LIST, StringUtils.stringToNullList(launchInfo.m_suiteName)); configuration.setAttribute(TestNGLaunchConfigurationConstants.ALL_METHODS_LIST, toClassMethodsMap(classMethods)); configuration.setAttribute(TestNGLaunchConfigurationConstants.LOG_LEVEL, launchInfo.m_logLevel); configuration.setAttribute(TestNGLaunchConfigurationConstants.VERBOSE, launchInfo.m_verbose); configuration.setAttribute(TestNGLaunchConfigurationConstants.DEBUG, launchInfo.m_debug); configuration.setAttribute(TestNGLaunchConfigurationConstants.PROTOCOL, launchInfo.m_protocol.toString()); } }