blob: 7eb2f9cd0a817f445a7df8285178347c6116c59b [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* 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 com.android.tradefed.command;
import com.android.ddmlib.DdmPreferences;
import com.android.ddmlib.Log;
import com.android.tradefed.config.ConfigurationException;
import com.android.tradefed.config.ConfigurationFactory;
import com.android.tradefed.config.IConfiguration;
import com.android.tradefed.config.IConfigurationFactory;
import com.android.tradefed.config.Option;
import com.android.tradefed.device.DeviceManager;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.IDeviceManager;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.invoker.ITestInvocation;
import com.android.tradefed.invoker.TestInvocation;
import com.android.tradefed.log.ILeveledLogOutput;
import com.android.tradefed.util.RunUtil;
/**
* Command-line launcher for Trade Federation.
* <p/>
* Loads the test configuration based on command line arguments, connects to available device,
* and delegates off to {@link ITestInvocation} to perform the work of running of tests.
*/
public class Command {
private static final String LOG_TAG = "Command";
/** the minimum invocation time in ms when in loop mode */
private static final long MIN_LOOP_TIME = 2 * 60 * 1000;
/** the time in ms to wait for a device */
private static final long WAIT_DEVICE_TIME = 10 * 1000;
public Command() {
}
/**
* The main worker method that will parse the command line arguments, and invoke the test run.
* <p/>
* TODO: support "--help"
* @param args the command line arguments. Expected format is:
* [configuration options] [--loop] configuration_name
* where:
* <li> configuration_name: unique name of {@link IConfiguration} to use
* <li> configuration options: the {@link Option} names and associated values to provide to
* the {@link IConfiguration}
* <li> --loop: keep running an invocation continuously. Each invocation will be spaced at
* least 2 minutes apart. ie if a prior invocation has nothing to do, the program will sleep
* until 2 minutes has elapsed before starting next invocation.
*/
protected void run(String[] args) {
// TODO: look at better way of parsing arguments specific to this class
boolean loopMode = false;
boolean helpMode = false;
for (String arg : args) {
if (arg.equals("--loop")) {
loopMode = true;
} else if (arg.equals("--help")) {
helpMode = true;
}
}
if (helpMode) {
getConfigFactory().printHelp(args, System.out);
return;
}
IDeviceManager manager = null;
try {
manager = getDeviceManager();
if (loopMode) {
while (true) {
long startTime = System.currentTimeMillis();
Log.i(LOG_TAG, "Starting new invocation");
runInvocation(manager, args);
long stopTime = System.currentTimeMillis();
long sleepTime = MIN_LOOP_TIME - (stopTime - startTime);
if (sleepTime > 0) {
Log.i(LOG_TAG, String.format("Sleeping for %d ms", sleepTime));
RunUtil.sleep(sleepTime);
}
}
} else {
runInvocation(manager, args);
}
} catch (DeviceNotAvailableException e) {
System.out.println("Could not find device to test");
} catch (ConfigurationException e) {
System.out.println(String.format("Failed to load configuration: %s", e.getMessage()));
} catch (Throwable e) {
System.out.println("Uncaught exception!");
e.printStackTrace();
}
exit(manager);
}
protected void runInvocation(IDeviceManager manager, String[] args)
throws ConfigurationException, DeviceNotAvailableException {
ILeveledLogOutput logger = null;
ITestDevice device = null;
try {
IConfiguration config = createConfiguration(args);
logger = config.getLogOutput();
Log.setLogOutput(logger);
DdmPreferences.setLogLevel(logger.getLogLevel());
ITestInvocation instance = createRunInstance();
device = manager.allocateDevice(config.getDeviceRecovery(), WAIT_DEVICE_TIME);
instance.invoke(device, config);
} finally {
if (manager != null && device != null) {
manager.freeDevice(device);
}
if (logger != null) {
logger.closeLog();
}
}
}
private void exit(IDeviceManager manager) {
if (manager != null) {
manager.terminate();
}
}
/**
* Factory method for creating a {@link TestInvocation}.
*
* @return the {@link ITestInvocation} to use
*/
ITestInvocation createRunInstance() {
return new TestInvocation();
}
/**
* Factory method for getting a reference to the {@link IDeviceManager}
*
* @return the {@link IDeviceManager} to use
*/
IDeviceManager getDeviceManager() {
return DeviceManager.getInstance();
}
/**
* Factory method for creating a {@link IConfiguration}.
*
* @param args the command line arguments
* @return the {@link IConfiguration} populated with option values supplied in args
* @throws {@link ConfigurationException} if {@link IConfiguration} could not be loaded.
*/
protected IConfiguration createConfiguration(String[] args) throws ConfigurationException {
return getConfigFactory().createConfigurationFromArgs(args);
}
protected IConfigurationFactory getConfigFactory() {
return ConfigurationFactory.getInstance();
}
/**
* Main entry point for TradeFederation command line launcher.
*
* @param args command line arguments. Expected format: [option] [config_name]
*/
public static void main(String[] args) {
Command cmd = new Command();
cmd.run(args);
}
}