/* MonkeyTalk - a cross-platform functional testing tool
Copyright (C) 2012 Gorilla Logic, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package com.gorillalogic.monkeytalk.runner;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.PrintStream;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.beust.jcommander.DynamicParameter;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.converters.FileConverter;
import com.gorillalogic.monkeytalk.BuildStamp;
import com.gorillalogic.monkeytalk.agents.AndroidEmulatorAgent;
import com.gorillalogic.monkeytalk.utils.AndroidUtils;
/**
* Pure Java commandline runner that handles argument parse and then uses
* {@link com.gorillalogic.monkeytalk.processor.Runner} to do the actually running.
*/
public class Runner {
/**
* Parse the given commandline args, and run.
*
* @param args
* the commandline args
*/
public static void main(String[] args) {
CommandlineParser parser = null;
try {
parser = new CommandlineParser(args);
} catch (Exception ex) {
System.out.println(BuildStamp.STAMP);
System.out.println("\nERROR: Bad commandline args\n");
return;
}
if (parser.version) {
System.out.println(BuildStamp.STAMP);
return;
} else if (parser.help) {
System.out.println(BuildStamp.STAMP);
parser.printUsage();
return;
}
com.gorillalogic.monkeytalk.processor.Runner runner = null;
try {
runner = new com.gorillalogic.monkeytalk.processor.Runner(parser.agent, parser.host,
parser.port);
} catch (RuntimeException ex) {
System.out.println(BuildStamp.STAMP);
System.out.println("\nERROR: " + ex.getMessage() + "\n");
parser.printUsage();
}
if (runner != null) {
try {
runner.setGlobalTimeout(parser.timeout);
runner.setGlobalThinktime(parser.thinktime);
runner.setGlobalScreenshotOnError(parser.screenshotOnError);
if (parser.adb != null) {
runner.setAdb(parser.adb);
} else if (parser.agent != null && parser.agent.equalsIgnoreCase("AndroidEmulator")) {
runner.setAdb(AndroidUtils.getAdb());
}
runner.setAgentProperty(AndroidEmulatorAgent.ADB_SERIAL_PROP, parser.adbSerial);
runner.setAgentProperty(AndroidEmulatorAgent.ADB_LOCAL_PORT_PROP,
(parser.adbLocalPort > 0 ? Integer.toString(parser.adbLocalPort) : null));
runner.setAgentProperty(AndroidEmulatorAgent.ADB_REMOTE_PORT_PROP,
(parser.adbRemotePort > 0 ? Integer.toString(parser.adbRemotePort) : null));
runner.setVerbose(parser.verbose);
runner.setReportdir(parser.reportdir);
runner.setTakeAfterMetrics(parser.screenshots);
runner.setTakeAfterScreenshot(parser.screenshots);
if (parser.quiet && !parser.verbose) {
System.setOut(new PrintStream(new ByteArrayOutputStream()));
}
if (parser.scripts == null) {
throw new RuntimeException("You must specify a script or suite to run");
} else {
// wait until the agent is ready
if (!runner.waitUntilReady(parser.startup)) {
throw new RuntimeException(
"Unable to startup MonkeyTalk connection - timeout after "
+ parser.startup + "s");
}
// for each script, run it!
for (File script : parser.scripts) {
runner.run(script, parser.getGlobals());
}
}
} catch (RuntimeException ex) {
System.out.println(BuildStamp.STAMP);
System.out.println("\nERROR: " + ex.getMessage() + "\n");
parser.printUsage();
} finally {
if (runner.getAgent() != null) {
runner.getAgent().close();
}
}
}
}
/**
* Commandline arg parser based on JCommander.
*/
private static class CommandlineParser {
private JCommander jcommander;
@Parameter(names = "-agent", description = "Target agent [iOS, Android, AndroidEmulator]", required = true)
private String agent;
@Parameter(names = "-host", description = "Target host, defaults to localhost")
private String host = "localhost";
@Parameter(names = "-port", description = "Target port, defaults based on agent")
private int port = -1;
@Parameter(names = "-timeout", description = "Global timeout (in ms)")
private int timeout = -1;
@Parameter(names = "-thinktime", description = "Global thinktime (in ms)")
private int thinktime = -1;
@Parameter(names = "-startup", description = "Startup timeout (in s)")
private int startup = -1;
@Parameter(names = "-reportdir", converter = FileConverter.class, description = "Output folder for suite results")
private File reportdir;
@Parameter(names = "-adb", description = "Path to ADB", converter = FileConverter.class)
private File adb;
@Parameter(names = "-adbSerial", description = "ADB serial number")
private String adbSerial = null;
@Parameter(names = "-adbLocalPort", description = "ADB local port")
private int adbLocalPort = -1;
@Parameter(names = "-adbRemotePort", description = "ADB remote port")
private int adbRemotePort = -1;
@Parameter(names = "-screenshotOnError", description = "Take screenshot on error, defaults to on")
private boolean screenshotOnError = true;
@Parameter(names = "-screenshots", description = "Take before and after screenshots on every command")
private boolean screenshots = false;
@Parameter(names = "-help", description = "print help and exit", help = true)
private boolean help = false;
@Parameter(names = "-version", description = "print version and exit", help = true)
private boolean version = false;
@Parameter(converter = FileConverter.class, description = "scripts...")
private List<File> scripts;
@Parameter(names = "-quiet", description = "Turn off all output")
private boolean quiet = false;
@Parameter(names = "-verbose", description = "Turn on extra output")
private boolean verbose = false;
@DynamicParameter(names = "-D", description = "Global variables")
private Map<String, String> globals = new LinkedHashMap<String, String>();
public CommandlineParser(String[] args) {
jcommander = new JCommander(this, args);
}
public void printUsage() {
jcommander.usage();
}
/**
* Helper to guarantee that global variable values are not quoted.
*
* @return the commandline global variables as a map
*/
private Map<String, String> getGlobals() {
Map<String, String> m = new LinkedHashMap<String, String>();
for (Map.Entry<String, String> entry : globals.entrySet()) {
String val = entry.getValue();
if (val.startsWith("\"") && val.endsWith("\"")) {
val = val.substring(1, val.length() - 1);
}
m.put(entry.getKey(), val);
}
return m;
}
}
}