blob: 8fb70746fb8a5598099d1fb55420cd1e9f817030 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2019 Xored Software Inc and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Xored Software Inc - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.rcptt.runner;
import static java.util.Arrays.asList;
import java.io.File;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.rcptt.internal.launching.TestEngineManager;
import org.eclipse.rcptt.launching.injection.Directory;
import org.eclipse.rcptt.launching.injection.InjectionConfiguration;
import org.eclipse.rcptt.launching.injection.InjectionFactory;
import org.eclipse.rcptt.launching.injection.UpdateSite;
import org.eclipse.rcptt.reporting.core.ReportRendererManager;
import org.eclipse.rcptt.reporting.core.ReportRendererManager.ReportRenderer;
import org.eclipse.rcptt.tesla.core.TeslaFeatures;
import org.eclipse.rcptt.tesla.core.TeslaLimits;
public class RunnerConfiguration {
private static final int DEFAULT_EXECUTION_TIMEOUT = 18000;
private static final int DEFAULT_SHUTDOWN_TIMEOUT = 5 * 60;
private static final int DEFAULT_WAIT_AUT_TIMEOUT = 5 * 60;
enum CommandArg {
Runner("The runner platform (SWT or RAP)", "runnerPlatform"),
Location("AUT Product location", "aut"), //
Count("AUT Instances count", "autCount"), //
RAPPort("RAP AUT Server port", "rapPort"), //
RAPServletPath("RAP AUT servlet path", "rapPath"), //
RAPOpenBrowserCommand("Start browser command", "browserCmd"), //
WsPrefix(
"AUT workspaces prefix to use. Workspaces will contain numeric number.",
"autWsPrefix", "wsPrefix"), //
Suites("Comma separated testsuite names.", "suites"), //
Import("Project to import to AUT workspace", "import"), //
Q7Report("File name of q7 report", "q7report"), //
AUTReport("File name of AUT report about initialization issues",
"autReport"), //
HTMLReport("File name of HTML report", "htmlReport"), //
JUnitReport("File path of JUnit report", "junitReport"), //
Report(
"Comma separated pair of report id, report file name without extension",
"report"), //
// Logging("Enable advanced logging mode", "logging"), //
MemoryUsage("Output memory usage information", "memoryUsage"), //
ExecutionTimeout("Execution timeout (default 18000 seconds (5 hours))",
"timeout"), //
Limit("Execute only first N tests)", "limit"), //
AutArgs("Comma separated list of arguments to pass for AUT", "autArgs"), //
AutVMArgs("Comma separated list of arguments to pass to AUT Java VM",
"autVMArgs"), //
JavaVM("Java virtual machine to test on. Default: current VM", "autVM",
"autJVM", "javaVM"), //
UpdateSite(
"Comma separated update site location and features required to be injected into AUT",
"injection:site", "site"), //
Directory("Location of plugins directory to be injected into AUT.",
"injection:dir", "dir"), //
ConnectTimeout("Q7 Connection timeout", "connectTimeout"), //
ConsoleLogsPrefix("Console log prefix", "autConsolePrefix"), //
TimeoutRestartTestCount(
"Restart AUT then specified amount of tests are failed with timeout (default value is 2, one by one)",
"timeoutRestartTestCount"), //
ConnectionResetRetry("Retry tests after connection reset errors", "connectionResetRetry"), //
OnlySpecified("Inject only specified sites", "injectSpecified"), //
NoSecurityStorage("Do not override secure storage location",
"noSecurityOverride"), //
TestOptions("Execution options", "testOptions"), //
ShutdownListenerPort("Shutdown Listener Port", "shutdownListenerPort"), //
Help("This message", "help", "h", "?"), //
TagsToSkip("Skip tests with listed tags during execution", "skipTags"), //
SplitHTMLReport("Split HTML Report", "splitHtmlReport"), //
ShutdownTimeout(
"AUT shutdown timeout (default 300 seconds (5 minutes))",
"shutdownTimeout"), //
ReuseExisingWorkspace(
"When true, treat autWsPrefix as full workspace path and do not change it",
"reuseExistingWorkspace"), //
Tests("Semicolon-separated list of test name glob patterns (* - any chars, ? - exactly one char)", "tests"), //
TestEngine("Semicolon-separated list of test engines configuration parameters", "testEngine");
CommandArg(String message, String... val) {
this.val = val;
this.message = message;
}
private String message;
private String[] val;
public String[] getCommands() {
return val;
}
public String getMessage() {
return message;
}
};
private static final String SEPARATOR = ";";
public final List<File> toImport = new ArrayList<File>();
public String location;
private String q7ReportLocation = null;
private String autReportLocation = null;
public String htmlReportLocation = null;
public String junitReportLocation = null;
public final List<String> toTest = new ArrayList<String>();
public final List<String> suites = new ArrayList<String>();
public int autCount = 1;
public String autWorkspacePrefix;
public String[] autArgs;
public String[] autVMArgs = new String[0];
public int timeoutRestart = 2;
public int connectionResetRetry = 3;
public boolean splitHTMLReport = false;
public boolean reuseExistingWorkspace = false;
public boolean outputMemoryUsage = false;
public String path = null;
public String browserCmd = null;
public Integer port = null;
public boolean rapPlatform = false;
public static class UserReport {
public String id;
public String path;
public ReportRenderer renderer;
}
public UserReport report = null;
public String autConsolePrefix = null;
public int executionTimeout = DEFAULT_EXECUTION_TIMEOUT;
public int shutdownTimeout = DEFAULT_SHUTDOWN_TIMEOUT;
public int waitAutTimeout = DEFAULT_WAIT_AUT_TIMEOUT;
public boolean onlySpecified = false;
public Map<String, String> testOptions = new HashMap<String, String>();
public int shudownListenerPort = 0;
public String javaVM;
public InjectionConfiguration config = null;
public int limit = -1;
public String[] tagsToSkip = new String[] { "skipExecution" };
public boolean overrideSecurityStorage = true;
public Map<String, Map<String, String>> testEngines = new HashMap<String, Map<String, String>>();
public RunnerConfiguration() {
}
private String getFriendlyName() {
String result = "aut-";
// try to gather some more friendly name than
// just a number that will be appended somewhere later
if (this.location != null) {
File autDir = new File(this.location);
String autName = autDir.getName();
if (autName != null && autName.length() > 0)
result += autName + "-";
}
return result;
}
private boolean fillDefaults() {
if (autWorkspacePrefix == null) {
boolean success = false;
try {
Location location = Platform.getInstanceLocation();
if (location != null) {
URL url = location.getURL();
if (url != null) {
File file = new File(url.toURI());
File parent = file.getParentFile();
if (parent != null) {
String path = new File(parent.getAbsolutePath(),
getFriendlyName()).toString();
// and finally
autWorkspacePrefix = path;
success = true;
}
}
}
} catch (Exception e) {
}
if (!success) {
System.out.println("ERROR: Unable to guess wokspace location.");
return false;
}
}
if (autConsolePrefix == null) {
boolean success = false;
try {
Location location = Platform.getInstanceLocation();
if (location != null) {
URL url = location.getURL();
if (url != null) {
File file = new File(url.toURI());
String path = new File(file.getAbsolutePath(),
getFriendlyName()).toString();
// and finally
autConsolePrefix = path;
success = true;
}
}
} catch (Exception e) {
}
if (!success) {
System.out.println("ERROR: Unable to guess logs location.");
return false;
}
}
return true;
}
public boolean processArgs(final String[] args) {
Iterator<String> i = Arrays.asList(args).iterator();
while (i.hasNext()) {
final String arg = i.next();
CommandArg cmdArg = findArg(arg);
if (cmdArg == null) {
System.out.println("Invalid argument:" + arg);
continue;
}
switch (cmdArg) {
case OnlySpecified:
onlySpecified = true;
break;
case SplitHTMLReport:
splitHTMLReport = true;
break;
case ReuseExisingWorkspace:
reuseExistingWorkspace = true;
break;
// case Logging:
// Q7Features.getInstance().getOption(TeslaFeatures.LOGGING)
// .setValue("true");
// break;
case MemoryUsage:
outputMemoryUsage = true;
break;
case Suites:
final String[] suiteArgs = getSplitArguments(i);
for (final String suite : suiteArgs) {
if (!suites.contains(suite))
suites.add(suite);
}
break;
case Tests:
toTest.addAll(new HashSet<String>(asList(getSplitArguments(i))));
break;
case Report:
String[] arguments = getSplitArguments(i);
if (arguments.length != 2) {
HeadlessRunnerPlugin.getDefault().info(
"ERROR: Invalid report argument format.");
return false;
} else {
report = new UserReport();
report.id = arguments[0];
report.path = arguments[1];
ReportRenderer[] renderers = ReportRendererManager
.getInstance().getExtensions();
for (ReportRenderer reportRenderer : renderers) {
if (report.id.equals(reportRenderer.getId())) {
report.renderer = reportRenderer;
break;
}
}
if (report.renderer == null) {
HeadlessRunnerPlugin.getDefault().info(
"ERROR: Failed to locate report renderer for id: "
+ report.id);
System.err
.println("ERROR: Failed to locate report renderer for id: "
+ report.id);
report = null;
return false;
}
}
break;
case Q7Report:
q7ReportLocation = i.next();
break;
case AUTReport:
autReportLocation = i.next();
break;
case HTMLReport:
htmlReportLocation = i.next();
break;
case JUnitReport:
junitReportLocation = i.next();
break;
case Import:
final String[] files = getSplitArguments(i);
for (final String filePath : files) {
final File file = new File(filePath);
if (!file.exists() || !file.isDirectory()) {
System.out
.println(String
.format("Invalid project location in '-import' arg: %s",
filePath));
continue;
}
if (!toImport.contains(file))
toImport.add(file);
}
break;
case Location:
if (location != null) {
HeadlessRunnerPlugin
.getDefault()
.info("WARNING: AUT location was specified several times. The last location will be used");
}
location = i.next();
// Backward compatibility
File f = new File(location);
if (f.exists() && f.isFile()) {
location = f.getParent();
}
break;
case TimeoutRestartTestCount:
try {
timeoutRestart = Integer.parseInt(i.next());
} catch (final NumberFormatException e) {
HeadlessRunnerPlugin
.getDefault()
.info("WARNING: AUT Timeout Restart test count must be integer value.");
}
break;
case ConnectionResetRetry:
try {
connectionResetRetry = Integer.parseInt(i.next());
} catch (NumberFormatException e) {
HeadlessRunnerPlugin.getDefault()
.info("WARNING: AUT Connection Reset retry count must be an integer value.");
}
break;
case Count:
try {
autCount = Integer.parseInt(i.next());
} catch (final NumberFormatException e) {
HeadlessRunnerPlugin
.getDefault()
.info("WARNING: AUT count parameter must be an integer value.");
}
break;
case Limit:
try {
limit = Integer.parseInt(i.next());
} catch (final NumberFormatException e) {
HeadlessRunnerPlugin
.getDefault()
.info("WARNING: AUT limit parameter must be an integer value.");
}
break;
case WsPrefix:
autWorkspacePrefix = i.next();
break;
case ExecutionTimeout:
try {
executionTimeout = Integer.parseInt(i.next());
} catch (final NumberFormatException e) {
HeadlessRunnerPlugin
.getDefault()
.info("WARNING: Execution timeout parameter must be an integer value.");
}
break;
case AutArgs:
autArgs = getSplitArguments(i);
break;
case AutVMArgs:
autVMArgs = getSplitArguments(i);
break;
case JavaVM:
javaVM = i.next();
if (!new File(javaVM).exists()) {
HeadlessRunnerPlugin.getDefault().info(
"ERROR: Invalid Java VM path: " + javaVM);
}
break;
case UpdateSite:
initInjection();
String[] split = getSplitArguments(i);
if (split.length > 0) {
UpdateSite site = InjectionFactory.eINSTANCE
.createUpdateSite();
site.setUri(split[0]);
if (split.length > 1) {
List<String> list = new ArrayList<String>(
Arrays.asList(split));
list.remove(0);
site.getUnits().addAll(list);
} else {
site.setAllUnits(true);
}
config.getEntries().add(site);
}
break;
case Directory:
initInjection();
String folder = i.next();
Directory directory = InjectionFactory.eINSTANCE
.createDirectory();
directory.setPath(folder);
config.getEntries().add(directory);
break;
case ConnectTimeout:
try {
String strTimeout = i.next();
int timeout = Integer.parseInt(strTimeout);
if (timeout < 1) {
HeadlessRunnerPlugin
.getDefault()
.info("WARNING: ConnectTimeout value is invalid. Default value will be used...");
} else {
TeslaFeatures.getInstance()
.getOption(TeslaLimits.AUT_STARTUP_TIMEOUT)
.setValue(strTimeout);
}
} catch (final NumberFormatException e) {
HeadlessRunnerPlugin
.getDefault()
.info("WARNING: ConnectTimeout value is invalid. Default value will be used...");
}
break;
case TestOptions:
String optionsStr = i.next();
for (String optionStr : optionsStr.split(";")) {
if (optionStr.trim().length() == 0) {
continue;
}
int eqIndex = optionStr.indexOf('=');
if (eqIndex == -1) {
HeadlessRunnerPlugin
.getDefault()
.info("WARNING: Invalid value for testOptions. should be key1=value1;key2=value2");
}
String name = optionStr.substring(0, eqIndex).trim();
String value = optionStr.substring(eqIndex + 1).trim();
if ("overrideSecurityStorage".equals(name)) {
overrideSecurityStorage = "true".equals(value);
} else {
testOptions.put(name, value);
}
}
break;
case ShutdownListenerPort:
try {
shudownListenerPort = Integer.parseInt(i.next());
} catch (final NumberFormatException e) {
HeadlessRunnerPlugin
.getDefault()
.info("WARNING: shudownListenerPort parameter must be an integer value.");
}
break;
case ConsoleLogsPrefix:
autConsolePrefix = i.next();
break;
case TagsToSkip:
tagsToSkip = getSplitArguments(i);
break;
case NoSecurityStorage:
overrideSecurityStorage = false;
break;
case Help:
System.out
.println("RCPTT Headless Runner command line arguments:");
for (CommandArg v : CommandArg.values()) {
System.out.print("\t");
String[] commands = v.getCommands();
for (int k = 0; k < commands.length; ++k) {
System.out.print("-" + commands[k]);
if (k != commands.length - 1) {
System.out.print(", ");
}
}
System.out.print(":\t" + v.getMessage());
System.out.println();
}
return false;
case ShutdownTimeout:
try {
shutdownTimeout = Integer.parseInt(i.next());
} catch (final NumberFormatException e) {
HeadlessRunnerPlugin
.getDefault()
.info("WARNING: Shutdown timeout parameter must be an integer value.");
}
break;
case RAPPort:
try {
port = Integer.parseInt(i.next());
} catch (final NumberFormatException e) {
HeadlessRunnerPlugin.getDefault().info(
"WARNING: RAP server port parameter must be an integer value.");
port = null;
}
break;
case RAPServletPath:
path = i.next();
break;
case RAPOpenBrowserCommand:
browserCmd = i.next();
break;
case Runner:
rapPlatform = i.next().equalsIgnoreCase("rap");
break;
case TestEngine:
String testEngineStr = i.next();
int colIndex = testEngineStr.indexOf(':');
if (colIndex == -1) {
HeadlessRunnerPlugin
.getDefault()
.info("WARNING: Invalid value for testEngine. Should be 'testEngineId:key1=value1;key2=value2'");
break;
}
String id = testEngineStr.substring(0, colIndex).trim();
String paramsStr = testEngineStr.substring(colIndex + 1).trim();
Map<String, String> params = new HashMap<String, String>();
for (String paramStr : paramsStr.split(";")) {
if (paramStr.trim().length() == 0) {
continue;
}
int eqIndex = paramStr.indexOf('=');
if (eqIndex == -1) {
HeadlessRunnerPlugin
.getDefault()
.info("WARNING: Invalid value for testEngine. Should be 'testEngineId:key1=value1;key2=value2'");
break;
}
String name = paramStr.substring(0, eqIndex).trim();
String value = paramStr.substring(eqIndex + 1).trim();
String message = TestEngineManager.getInstance()
.validateParameter(id, name, value);
if (message != null && !message.equals("")) {
HeadlessRunnerPlugin
.getDefault()
.info(MessageFormat.format("WARNING: Invalid value for {0}. {1}", name, message));
continue;
}
params.put(name, value);
}
testEngines.put(id, params);
break;
}
}
return fillDefaults();
}
private String[] getSplitArguments(Iterator<String> i) {
if (!i.hasNext()) {
return new String[0];
}
String val = i.next();
if (val.startsWith("'") && val.endsWith("'")) {
val = val.substring(1, val.length() - 1);
}
if (val.startsWith("\"") && val.endsWith("\"")) {
val = val.substring(1, val.length() - 1);
}
List<String> splitResult = new ArrayList<String>();
String[] split = val.split(SEPARATOR);
splitResult.addAll(Arrays.asList(split));
if (val.endsWith(SEPARATOR)) {
// Eat one more argument
splitResult.addAll(Arrays.asList(getSplitArguments(i)));
}
return splitResult.toArray(new String[splitResult.size()]);
}
private void initInjection() {
if (config == null) {
config = InjectionFactory.eINSTANCE.createInjectionConfiguration();
}
}
private CommandArg findArg(String arg) {
CommandArg[] values = CommandArg.values();
for (CommandArg commandArg : values) {
String[] val = commandArg.getCommands();
for (String s : val) {
if (("-" + s).equals(arg) || ("--" + s).equals(arg)) {
return commandArg;
}
}
}
return null;
}
// default values
public String getQ7ReportLocation() {
return (q7ReportLocation != null) ? q7ReportLocation : new File(
getStateLocationFile(), "q7.report").getAbsolutePath();
}
public String getAutReportLocation() {
return (autReportLocation != null) ? autReportLocation : new File(
getStateLocationFile(), "autReport.html").getAbsolutePath();
}
private static File getStateLocationFile() {
return HeadlessRunnerPlugin.getDefault().getStateLocation().toFile();
}
}