/* * Copyright 2012-2015 eBay Software Foundation and selendroid committers. * * Licensed 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 io.selendroid.standalone; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import io.selendroid.standalone.log.LogLevelConverter; import io.selendroid.standalone.log.LogLevelEnum; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import java.util.ArrayList; import java.util.List; public class SelendroidConfiguration { @Parameter(description = "port the server will listen on.", names = "-port") private int port = 4444; @Parameter(description = "timeout that will be used to start Android emulators", names = "-timeoutEmulatorStart") private long timeoutEmulatorStart = 300000; @Parameter(description = "location of the application under test. Absolute path to the apk", names = { "-app", "-aut"}) private List<String> supportedApps = new ArrayList<String>(); @Deprecated @Parameter(names = "-verbose", description = "Debug mode") private boolean verbose = false; @Parameter(names = "-emulatorPort", description = "port number to start running emulators on") private int emulatorPort = 5560; @Parameter(names = "-deviceScreenshot", description = "if true, screenshots will be taken on the device instead of using the ddmlib libary.") private boolean deviceScreenshot = false; @Parameter( description = "the port the selendroid-standalone is using to communicate with instrumentation server", names = {"-selendroidServerPort"}) private int selendroidServerPort = 8080; @Parameter( description = "re-use the configured -selendroidServerPort for each test session", names = {"-reuseSelendroidServerPort"}) private boolean reuseSelendroidServerPort = false; @Parameter(description = "The file of the keystore to be used", names = {"-keystore"}) private String keystore = null; @Parameter(description = "The password for the keystore to be used", names = {"-keystorePassword"}) private String keystorePassword = null; @Parameter(description = "The alias of the keystore to be used", names = {"-keystoreAlias"}) private String keystoreAlias = null; @Parameter(description = "The emulator options used for starting emulators: e.g. -no-audio. When passing multiple options, put them in double quotes: e.g. \"-no-audio -no-window\"", names = {"-emulatorOptions"}) private String emulatorOptions = null; @Parameter(names = "-keepEmulator", description = "if true, emulator will be kept running after test ends.") private boolean keepEmulator = false; @Parameter( description = "if specified, will send a registration request to the given url. Example : http://localhost:4444/grid/register", names = "-hub") private String registrationUrl = null; @Parameter( description = "if specified, will specify the remote proxy to use on the grid. Example : io.selendroid.grid.SelendroidSessionProxy", names = "-proxy") private String proxy = null; @Parameter( description = "host of the node. Ip address needs to be specified for registering to a grid hub (guessing can be wrong complex).", names = "-host") private String serverHost; @Parameter(names = "-keepAdbAlive", description = "If true, adb will not be terminated on server shutdown.") private boolean keepAdbAlive = false; @Parameter(names = "-maxSession", description = "Maximum number of sessions that a grid hub can assign at a time. " + "Default 0, use number of supported devices") private int maxSession = 0; @Parameter(names = "-maxInstances", description = "Maximum number of instances that a grid hub can use at a time.") private int maxInstances = 1; @Parameter(names = "-registerCycle", description = "How often in ms the node will try to register itself again" + ".Allow to restart the hub without having to restart the nodes. 0 to disable auto register. Default 0.") private long registerCycle = 0; @Parameter(names = "-cleanupCycle", description = "How often in ms a proxy will check for timed out thread. Default 5000") private long cleanupCycle = 5000; @Parameter(names = "-timeout", description = "The timeout in seconds before the hub automatically ends a test " + "that hasn't had any activity in the last X seconds. The browser will be released for another test to use." + "This typically takes care of the client crashes. Default 300000.") private long timeout = 300000; @Parameter(names = "-nodePolling", description = "Interval in ms between alive checks of node how often the hub checks " + "if the node is still alive. Default 5000") private long nodePolling = 5000; @Parameter(names = "-unregisterIfStillDownAfter", description = "If the node remains down for more than " + "unregisterIfStillDownAfter ms, it will disappear from the hub. Default is 1min.") private long unregisterIfStillDownAfter = 60000; @Parameter(names = "-downPollingLimit", description = "node is marked as down after downPollingLimit alive checks. Default 2.") private long downPollingLimit = 2; @Parameter(names = "-nodeStatusCheckTimeout", description = "Connection and socket timeout which is used for " + "node alive check. Default 0 and for connection timeout - 120sec, for socket timeout - 3hours") private long nodeStatusCheckTimeout = 0; @Parameter(names = "-noWebviewApp", description = "If you don't want selendroid to auto-extract and have 'AndroidDriver' (webview only app) available.") private boolean noWebViewApp = false; @Parameter(names = "-noClearData", description = "When you quit the app, shell pm clear will not be called with this option specified.") private boolean noClearData = false; @Parameter( description = "maximum session duration in seconds. Session will be forcefully terminated if it takes longer.", names = "-sessionTimeout") private int sessionTimeoutSeconds = 30 * 60; // 30 minutes @Parameter(names = "-forceReinstall", description = "Forces Selendroid Server and the app under test to be reinstalled (for Selendroid developers)") private boolean forceReinstall = false; @Parameter(names = "-logLevel", converter = LogLevelConverter.class, description = "Specifies the log level of selendroid. Available values are: ERROR, WARNING, INFO, DEBUG and VERBOSE.") private LogLevelEnum logLevel = LogLevelEnum.ERROR; @Parameter(names = "-deviceLog", description = "Specifies whether or not adb logging should be enabled for the device running the test", arity = 1) private boolean deviceLog = true; @Parameter(description = "Maximum time in milliseconds to wait for the selendroid-server to come up on the device", names = "-serverStartTimeout") private long serverStartTimeout = 20000; @Parameter(names = {"-h", "--help"}, description = "Prints usage instructions to the terminal") private boolean printHelp = false; @Parameter(names="-serverStartRetries", description="Maximum amount of times the starting of the selendroid-server on the device will be retried") private int serverStartRetries = 5; @Parameter(names = "-folder", description = "The folder which contains Android applications under test. This folder will monitor and add new apps to the apps store during the lifetime of the selendroid node.") private String folder = null; @Parameter(names = "-deleteTmpFiles", description = "Deletes temporary files created by the Selendroid Server.") private boolean deleteTmpFiles = true; @Parameter(names = "-useJUnitBootstrap", description = "Use instrumentation that extends AdroidJUnitRunner") private boolean useJUnitBootstrap = false; public void setKeystore(String keystore) { this.keystore = keystore; } public String getKeystore() { return keystore; } public void setKeystorePassword(String keystorePassword) { this.keystorePassword = keystorePassword; } public String getKeystorePassword() { return keystorePassword; } public void setKeystoreAlias(String keystoreAlias) { this.keystoreAlias = keystoreAlias; } public String getKeystoreAlias() { return keystoreAlias; } public void setSelendroidServerPort(int selendroidServerPort) { this.selendroidServerPort = selendroidServerPort; } public int getSelendroidServerPort() { return selendroidServerPort; } public void addSupportedApp(String appAbsolutPath) { supportedApps.add(appAbsolutPath); } public List<String> getSupportedApps() { return supportedApps; } public static SelendroidConfiguration create(String[] args) { SelendroidConfiguration res = new SelendroidConfiguration(); new JCommander(res).parse(args); return res; } public void setPort(int port) { this.port = port; } public int getPort() { return this.port; } public void setEmulatorPort(int port) { emulatorPort = port; } public int getEmulatorPort() { return emulatorPort; } public long getTimeoutEmulatorStart() { return timeoutEmulatorStart; } public void setTimeoutEmulatorStart(long timeoutEmulatorStart) { this.timeoutEmulatorStart = timeoutEmulatorStart; } public boolean isDeviceScreenshot() { return deviceScreenshot; } public void setDeviceScreenshot(boolean deviceScreenshot) { this.deviceScreenshot = deviceScreenshot; } public String getRegistrationUrl() { return registrationUrl; } public void setRegistrationUrl(String registrationUrl) { this.registrationUrl = registrationUrl; } public String getProxy() { return proxy; } public void setProxy(String proxy) { this.proxy = proxy; } public String getServerHost() { return serverHost; } public void setServerHost(String serverHost) { this.serverHost = serverHost; } public String getEmulatorOptions() { return emulatorOptions; } public void setEmulatorOptions(String qemu) { this.emulatorOptions = qemu; } public boolean shouldKeepAdbAlive() { return keepAdbAlive; } public void setShouldKeepAdbAlive(boolean keepAdbAlive) { this.keepAdbAlive = keepAdbAlive; } public boolean isNoWebViewApp() { return noWebViewApp; } public void setNoWebViewApp(boolean noWebViewApp) { this.noWebViewApp = noWebViewApp; } public boolean isNoClearData() { return noClearData; } public void setNoClearData(boolean noClearData) { this.noClearData = noClearData; } public int getSessionTimeoutMillis() { return sessionTimeoutSeconds * 1000; } public void setSessionTimeoutSeconds(int sessionTimeoutSeconds) { this.sessionTimeoutSeconds = sessionTimeoutSeconds; } public boolean isForceReinstall() { return forceReinstall; } public void setForceReinstall(boolean forceReinstall) { this.forceReinstall = forceReinstall; } public LogLevelEnum getLogLevel() { return logLevel; } public void setLogLevel(LogLevelEnum logLevel) { this.logLevel = logLevel; } public boolean isDeviceLog() { return deviceLog; } public void setDeviceLog(boolean deviceLog) { this.deviceLog = deviceLog; } public long getServerStartTimeout() { return serverStartTimeout; } public void setServerStartTimeout(long serverStartTimeout) { this.serverStartTimeout = serverStartTimeout; } public int getServerStartRetries() { return serverStartRetries; } public void setServerStartRetries(int serverStartRetries) { this.serverStartRetries = serverStartRetries; } public boolean isPrintHelp() { return printHelp; } public void setPrintHelp(boolean printHelp) { this.printHelp = printHelp; } public boolean isKeepEmulator() { return keepEmulator; } public void setKeepEmulator(boolean keepEmulator) { this.keepEmulator = keepEmulator; } @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); } public int getMaxSession() { return maxSession; } public void setMaxSession(int maxSession) { this.maxSession = maxSession; } public int getMaxInstances() { return maxInstances; } public void setMaxInstances(int maxInstances) { this.maxInstances = maxInstances; } public String getAppFolderToMonitor() { return folder; } public void setAppFolderToMonitor(String path) { folder = path; } public boolean isDeleteTmpFiles() { return deleteTmpFiles; } public void setDeleteTmpFiles(boolean deleteTmpFiles){ this.deleteTmpFiles = deleteTmpFiles; } /** * @return {@code true} if Selendroid standalone should run in grid mode. */ public boolean isGrid() { return !StringUtils.isBlank(getRegistrationUrl()) && !StringUtils.isBlank(getServerHost()); } public long getRegisterCycle() { return registerCycle; } public void setRegisterCycle(long registerCycle) { this.registerCycle = registerCycle; } public long getCleanupCycle() { return cleanupCycle; } public void setCleanupCycle(long cleanupCycle) { this.cleanupCycle = cleanupCycle; } public long getTimeout() { return timeout; } public void setTimeout(long timeout) { this.timeout = timeout; } public long getNodePolling() { return nodePolling; } public void setNodePolling(long nodePolling) { this.nodePolling = nodePolling; } public long getUnregisterIfStillDownAfter() { return unregisterIfStillDownAfter; } public void setUnregisterIfStillDownAfter(long unregisterIfStillDownAfter) { this.unregisterIfStillDownAfter = unregisterIfStillDownAfter; } public long getDownPollingLimit() { return downPollingLimit; } public void setDownPollingLimit(long downPollingLimit) { this.downPollingLimit = downPollingLimit; } public long getNodeStatusCheckTimeout() { return nodeStatusCheckTimeout; } public void setNodeStatusCheckTimeout(long nodeStatusCheckTimeout) { this.nodeStatusCheckTimeout = nodeStatusCheckTimeout; } public boolean isReuseSelendroidServerPort() { return reuseSelendroidServerPort; } public void setReuseSelendroidServerPort(boolean reuseSelendroidServerPort) { this.reuseSelendroidServerPort = reuseSelendroidServerPort; } public boolean isUseJUnitBootstrap() { return useJUnitBootstrap; } public void setUseJUnitBootstrap(boolean useJUnitBootstrap) { this.useJUnitBootstrap = useJUnitBootstrap; } }