Merge "Update PushFilePreparer to new interface"
diff --git a/atest/TEST_MAPPING b/atest/TEST_MAPPING
index cebe409..32e6a6d 100644
--- a/atest/TEST_MAPPING
+++ b/atest/TEST_MAPPING
@@ -1,6 +1,32 @@
// Below lists the TEST_MAPPING tests to do ASuite unittests to make sure
// the expectation of ASuite are still good.
{
+ "mainline-presubmit": [
+ {
+ "name": "HelloWorldTests"
+ },
+ {
+ "name": "hello_world_test",
+ "host": true
+ },
+ {
+ "name": "CtsApacheHttpLegacy27ApiSignatureTestCases"
+ },
+ {
+ "name": "ziparchive-tests"
+ },
+ {
+ "name": "CtsDpiTestCases",
+ "options": [
+ {
+ "include-filter": "android.dpi.cts.ConfigurationScreenLayoutTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsSampleHostTestCases"
+ }
+ ],
"presubmit": [
{
// Host side ATest unittests.
diff --git a/device_build_interfaces/com/android/tradefed/device/StubLocalAndroidVirtualDevice.java b/device_build_interfaces/com/android/tradefed/device/StubLocalAndroidVirtualDevice.java
index 5066999..5ce00ec 100644
--- a/device_build_interfaces/com/android/tradefed/device/StubLocalAndroidVirtualDevice.java
+++ b/device_build_interfaces/com/android/tradefed/device/StubLocalAndroidVirtualDevice.java
@@ -21,9 +21,9 @@
* A placeholder {@link IDevice} used by {@link DeviceManager} to allocate when {@link
* DeviceSelectionOptions#localVirtualDeviceRequested()} is <code>true</code>
*/
-public class StubLocalAndroidVirtualDevice extends StubDevice {
+public class StubLocalAndroidVirtualDevice extends TcpDevice {
public StubLocalAndroidVirtualDevice(String serial) {
- super(serial, false);
+ super(serial);
}
}
diff --git a/proto/test_record.proto b/proto/test_record.proto
index cbbfafc..58e7147 100644
--- a/proto/test_record.proto
+++ b/proto/test_record.proto
@@ -94,4 +94,22 @@
// A stacktrace.
string trace = 2;
+
+ // A more detailed failure status description.
+ FailureStatus failure_status = 3;
+}
+
+// A Fail TestStatus can be associated with a more granular failure status that helps understanding
+// the context.
+enum FailureStatus {
+ // The test in progress was the reason for the failure.
+ TEST_FAILURE = 0;
+ // A timeout condition on the operation in progress occurred.
+ TIMED_OUT = 1;
+ // The test in progress was cancelled.
+ CANCELLED = 2;
+ // A failure attributed to something not functioning properly.
+ INFRA_FAILURE = 10;
+ // System under test crashed and caused the test to fail.
+ SYSTEM_UNDER_TEST_CRASHED = 20;
}
\ No newline at end of file
diff --git a/src/com/android/tradefed/config/RetryConfigurationFactory.java b/src/com/android/tradefed/config/RetryConfigurationFactory.java
index bbc8c0d..fc9ae95 100644
--- a/src/com/android/tradefed/config/RetryConfigurationFactory.java
+++ b/src/com/android/tradefed/config/RetryConfigurationFactory.java
@@ -49,9 +49,9 @@
RetryRescheduler retryRunner = (RetryRescheduler) rerunner;
retryRunner.setConfiguration(retryConfig);
try {
- retryRunner.run(null);
+ retryRunner.run(null, null);
return retryRunner.getRetryConfiguration();
- } catch (Exception e) {
+ } catch (Throwable e) {
throw new ConfigurationException(e.getMessage(), e);
}
}
diff --git a/src/com/android/tradefed/device/LocalAndroidVirtualDevice.java b/src/com/android/tradefed/device/LocalAndroidVirtualDevice.java
index cce0bbf..66a92fb 100644
--- a/src/com/android/tradefed/device/LocalAndroidVirtualDevice.java
+++ b/src/com/android/tradefed/device/LocalAndroidVirtualDevice.java
@@ -20,6 +20,7 @@
import com.android.ddmlib.Log.LogLevel;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.build.IDeviceBuildInfo;
+import com.android.tradefed.device.cloud.GceAvdInfo;
import com.android.tradefed.log.ITestLogger;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.FileInputStreamSource;
@@ -36,6 +37,7 @@
import com.android.tradefed.util.ZipUtil;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
+import com.google.common.net.HostAndPort;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -43,7 +45,9 @@
import java.util.List;
/** The class for local virtual devices running on TradeFed host. */
-public class LocalAndroidVirtualDevice extends TestDevice implements ITestLoggerReceiver {
+public class LocalAndroidVirtualDevice extends RemoteAndroidDevice implements ITestLoggerReceiver {
+
+ private static final int INVALID_PORT = 0;
// Environment variables.
private static final String ANDROID_HOST_OUT = "ANDROID_HOST_OUT";
@@ -53,13 +57,8 @@
// The name of the GZIP file containing launch_cvd and stop_cvd.
private static final String CVD_HOST_PACKAGE_NAME = "cvd-host_package.tar.gz";
- // The port of cuttlefish instance 1.
- private static final int CUTTLEFISH_FIRST_HOST_PORT = 6520;
-
private static final String ACLOUD_CVD_TEMP_DIR_NAME = "acloud_cvd_temp";
- private static final String INSTANCE_DIR_NAME_PREFIX = "instance_home_";
private static final String CUTTLEFISH_RUNTIME_DIR_NAME = "cuttlefish_runtime";
- private static final String INSTANCE_NAME_PREFIX = "local-instance-";
private ITestLogger mTestLogger = null;
@@ -68,11 +67,7 @@
private boolean mShouldDeleteHostPackageDir = false;
private File mImageDir = null;
- // The data for restoring the stub device at tear-down.
- private String mOriginalSerialNumber = null;
-
- // A positive integer for acloud to identify this device.
- private int mInstanceId = -1;
+ private GceAvdInfo mGceAvdInfo = null;
public LocalAndroidVirtualDevice(
IDevice device, IDeviceStateMonitor stateMonitor, IDeviceMonitor allocationMonitor) {
@@ -86,27 +81,58 @@
// The setup method in super class does not require the device to be online.
super.preInvocationSetup(info, testResourceBuildInfos);
- // TODO(b/133211308): multiple instances
- mInstanceId = 1;
- replaceStubDevice("127.0.0.1:" + (CUTTLEFISH_FIRST_HOST_PORT + mInstanceId - 1));
-
createTempDirs((IDeviceBuildInfo) info);
- CommandResult result = acloudCreate(info.getBuildFlavor(), getOptions());
+ CommandResult result = null;
+ File report = null;
+ try {
+ report = FileUtil.createTempFile("report", ".json");
+ result = acloudCreate(info.getBuildFlavor(), report, getOptions());
+ loadAvdInfo(report);
+ } catch (IOException ex) {
+ throw new TargetSetupError(
+ "Cannot create acloud report file.", ex, getDeviceDescriptor());
+ } finally {
+ FileUtil.deleteFile(report);
+ }
if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
throw new TargetSetupError(
- String.format("Cannot launch virtual device. stderr:\n%s", result.getStderr()),
+ String.format("Cannot execute acloud command. stderr:\n%s", result.getStderr()),
getDeviceDescriptor());
}
+
+ HostAndPort hostAndPort = mGceAvdInfo.hostAndPort();
+ replaceStubDevice(hostAndPort.toString());
+
+ RecoveryMode previousMode = getRecoveryMode();
+ try {
+ setRecoveryMode(RecoveryMode.NONE);
+ if (!adbTcpConnect(hostAndPort.getHost(), Integer.toString(hostAndPort.getPort()))) {
+ throw new TargetSetupError(
+ String.format("Cannot connect to %s.", hostAndPort), getDeviceDescriptor());
+ }
+ waitForDeviceAvailable();
+ } finally {
+ setRecoveryMode(previousMode);
+ }
}
/** Execute common tear-down procedure and stop the virtual device. */
@Override
public void postInvocationTearDown(Throwable exception) {
TestDeviceOptions options = getOptions();
+ HostAndPort hostAndPort = getHostAndPortFromAvdInfo();
+ String instanceName = (mGceAvdInfo != null ? mGceAvdInfo.instanceName() : null);
try {
- if (!options.shouldSkipTearDown() && mHostPackageDir != null) {
- CommandResult result = acloudDelete(options);
+ if (!options.shouldSkipTearDown() && hostAndPort != null) {
+ if (!adbTcpDisconnect(
+ hostAndPort.getHost(), Integer.toString(hostAndPort.getPort()))) {
+ CLog.e("Cannot disconnect from %s", hostAndPort.toString());
+ }
+ }
+
+ if (!options.shouldSkipTearDown() && instanceName != null) {
+ CommandResult result = acloudDelete(instanceName, options);
if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
CLog.e("Cannot stop the virtual device.");
}
@@ -114,7 +140,9 @@
CLog.i("Skip stopping the virtual device.");
}
- reportInstanceLogs();
+ if (instanceName != null) {
+ reportInstanceLogs(instanceName);
+ }
} finally {
restoreStubDevice();
@@ -122,10 +150,15 @@
deleteTempDirs();
} else {
CLog.i(
- "Skip deleting the temporary directories.\nHost package: %s\nImage: %s\n",
- mHostPackageDir, mImageDir);
+ "Skip deleting the temporary directories.\n"
+ + "Address: %s\nName: %s\nHost package: %s\nImage: %s",
+ hostAndPort, instanceName, mHostPackageDir, mImageDir);
+ mHostPackageDir = null;
+ mImageDir = null;
}
+ mGceAvdInfo = null;
+
super.postInvocationTearDown(exception);
}
}
@@ -202,38 +235,14 @@
throw new TargetSetupError(
"Unexpected device type: " + device.getClass(), getDeviceDescriptor());
}
- mOriginalSerialNumber = device.getSerialNumber();
setIDevice(new StubLocalAndroidVirtualDevice(newSerialNumber));
setFastbootEnabled(false);
}
- /**
- * Set this device to be offline and associate it with a {@link StubLocalAndroidVirtualDevice}.
- */
+ /** Restore the {@link StubLocalAndroidVirtualDevice} with the initial serial number. */
private void restoreStubDevice() {
- if (mOriginalSerialNumber == null) {
- CLog.w("Skip restoring the stub device.");
- return;
- }
- setIDevice(new StubLocalAndroidVirtualDevice(mOriginalSerialNumber));
+ setIDevice(new StubLocalAndroidVirtualDevice(getInitialSerial()));
setFastbootEnabled(false);
- mOriginalSerialNumber = null;
- }
-
- private String getInstanceDirName() {
- return INSTANCE_DIR_NAME_PREFIX + mInstanceId;
- }
-
- private File getInstanceDir() {
- return FileUtil.getFileForPath(
- getTmpDir(),
- ACLOUD_CVD_TEMP_DIR_NAME,
- getInstanceDirName(),
- CUTTLEFISH_RUNTIME_DIR_NAME);
- }
-
- private String getInstanceName() {
- return INSTANCE_NAME_PREFIX + mInstanceId;
}
private static void addLogLevelToAcloudCommand(List<String> command, LogLevel logLevel) {
@@ -244,7 +253,7 @@
}
}
- private CommandResult acloudCreate(String buildFlavor, TestDeviceOptions options) {
+ private CommandResult acloudCreate(String buildFlavor, File report, TestDeviceOptions options) {
CommandResult result = null;
File acloud = options.getAvdDriverBinary();
@@ -262,6 +271,7 @@
options.getGceCmdTimeout(),
acloud,
buildFlavor,
+ report,
options.getGceDriverLogLevel(),
options.getGceDriverParams());
if (CommandStatus.SUCCESS.equals(result.getStatus())) {
@@ -275,18 +285,16 @@
}
private CommandResult acloudCreate(
- long timeout, File acloud, String buildFlavor, LogLevel logLevel, List<String> args) {
+ long timeout,
+ File acloud,
+ String buildFlavor,
+ File report,
+ LogLevel logLevel,
+ List<String> args) {
IRunUtil runUtil = createRunUtil();
// The command creates the instance directory under TMPDIR.
runUtil.setEnvVariable(TMPDIR, getTmpDir().getAbsolutePath());
- // The command finds bin/launch_cvd in ANDROID_HOST_OUT.
- runUtil.setEnvVariable(ANDROID_HOST_OUT, mHostPackageDir.getAbsolutePath());
runUtil.setEnvVariable(TARGET_PRODUCT, buildFlavor);
- // TODO(b/141349771): Size of sockaddr_un->sun_path is 108, which may be too small for this
- // path.
- if (new File(getInstanceDir(), "launcher_monitor.sock").getAbsolutePath().length() > 108) {
- CLog.w("Length of instance path is too long for launch_cvd.");
- }
List<String> command =
new ArrayList<String>(
@@ -294,9 +302,13 @@
acloud.getAbsolutePath(),
"create",
"--local-instance",
- Integer.toString(mInstanceId),
"--local-image",
mImageDir.getAbsolutePath(),
+ "--local-tool",
+ mHostPackageDir.getAbsolutePath(),
+ "--report_file",
+ report.getAbsolutePath(),
+ "--no-autoconnect",
"--yes",
"--skip-pre-run-check"));
addLogLevelToAcloudCommand(command, logLevel);
@@ -308,7 +320,47 @@
return result;
}
- private CommandResult acloudDelete(TestDeviceOptions options) {
+ /**
+ * Get valid host and port from mGceAvdInfo.
+ *
+ * @return {@link HostAndPort} if the port is valid; null otherwise.
+ */
+ private HostAndPort getHostAndPortFromAvdInfo() {
+ if (mGceAvdInfo == null) {
+ return null;
+ }
+ HostAndPort hostAndPort = mGceAvdInfo.hostAndPort();
+ if (hostAndPort == null
+ || !hostAndPort.hasPort()
+ || hostAndPort.getPort() == INVALID_PORT) {
+ return null;
+ }
+ return hostAndPort;
+ }
+
+ /** Initialize instance name, host address, and port from an acloud report file. */
+ private void loadAvdInfo(File report) throws TargetSetupError {
+ mGceAvdInfo = GceAvdInfo.parseGceInfoFromFile(report, getDeviceDescriptor(), INVALID_PORT);
+ if (mGceAvdInfo == null) {
+ throw new TargetSetupError("Cannot read acloud report file.", getDeviceDescriptor());
+ }
+
+ if (Strings.isNullOrEmpty(mGceAvdInfo.instanceName())) {
+ throw new TargetSetupError("No instance name in acloud report.", getDeviceDescriptor());
+ }
+
+ if (getHostAndPortFromAvdInfo() == null) {
+ throw new TargetSetupError("No port in acloud report.", getDeviceDescriptor());
+ }
+
+ if (!GceAvdInfo.GceStatus.SUCCESS.equals(mGceAvdInfo.getStatus())) {
+ throw new TargetSetupError(
+ "Cannot launch virtual device: " + mGceAvdInfo.getErrors(),
+ getDeviceDescriptor());
+ }
+ }
+
+ private CommandResult acloudDelete(String instanceName, TestDeviceOptions options) {
File acloud = options.getAvdDriverBinary();
if (acloud == null || !acloud.isFile()) {
CLog.e("Specified AVD driver binary is not a file.");
@@ -324,8 +376,9 @@
Arrays.asList(
acloud.getAbsolutePath(),
"delete",
+ "--local-only",
"--instance-names",
- getInstanceName()));
+ instanceName));
addLogLevelToAcloudCommand(command, options.getGceDriverLogLevel());
CommandResult result =
@@ -335,24 +388,29 @@
return result;
}
- private void reportInstanceLogs() {
+ private void reportInstanceLogs(String instanceName) {
if (mTestLogger == null) {
return;
}
- reportInstanceLog("kernel.log", LogDataType.KERNEL_LOG);
- reportInstanceLog("logcat", LogDataType.LOGCAT);
- reportInstanceLog("launcher.log", LogDataType.TEXT);
- reportInstanceLog("cuttlefish_config.json", LogDataType.TEXT);
+ File instanceDir =
+ FileUtil.getFileForPath(
+ getTmpDir(),
+ ACLOUD_CVD_TEMP_DIR_NAME,
+ instanceName,
+ CUTTLEFISH_RUNTIME_DIR_NAME);
+ reportInstanceLog(new File(instanceDir, "kernel.log"), LogDataType.KERNEL_LOG);
+ reportInstanceLog(new File(instanceDir, "logcat"), LogDataType.LOGCAT);
+ reportInstanceLog(new File(instanceDir, "launcher.log"), LogDataType.TEXT);
+ reportInstanceLog(new File(instanceDir, "cuttlefish_config.json"), LogDataType.TEXT);
}
- private void reportInstanceLog(String fileName, LogDataType type) {
- File file = new File(getInstanceDir(), fileName);
+ private void reportInstanceLog(File file, LogDataType type) {
if (file.exists()) {
try (InputStreamSource source = new FileInputStreamSource(file)) {
- mTestLogger.testLog(fileName, type, source);
+ mTestLogger.testLog(file.getName(), type, source);
}
} else {
- CLog.w("%s doesn't exist.", fileName);
+ CLog.w("%s doesn't exist.", file.getAbsolutePath());
}
}
diff --git a/src/com/android/tradefed/device/TestDevice.java b/src/com/android/tradefed/device/TestDevice.java
index 8d5c71e..5387567 100644
--- a/src/com/android/tradefed/device/TestDevice.java
+++ b/src/com/android/tradefed/device/TestDevice.java
@@ -27,6 +27,7 @@
import com.android.tradefed.result.ByteArrayInputStreamSource;
import com.android.tradefed.result.FileInputStreamSource;
import com.android.tradefed.result.InputStreamSource;
+import com.android.tradefed.util.AaptParser;
import com.android.tradefed.util.CommandResult;
import com.android.tradefed.util.CommandStatus;
import com.android.tradefed.util.KeyguardControllerState;
@@ -194,6 +195,9 @@
packageFile.getAbsolutePath(), extraArgs.toString(), getSerialNumber());
performDeviceAction(String.format("install %s", packageFile.getAbsolutePath()),
installAction, MAX_RETRY_ATTEMPTS);
+ List<File> packageFiles = new ArrayList();
+ packageFiles.add(packageFile);
+ allowLegacyStorageForApps(packageFiles);
return response[0];
}
@@ -332,6 +336,9 @@
};
performDeviceAction(String.format("install %s", packageFile.getAbsolutePath()),
installAction, MAX_RETRY_ATTEMPTS);
+ List<File> packageFiles = new ArrayList();
+ packageFiles.add(packageFile);
+ allowLegacyStorageForApps(packageFiles);
return response[0];
}
@@ -404,9 +411,47 @@
String.format("install %s", packageFiles.toString()),
installAction,
MAX_RETRY_ATTEMPTS);
+ allowLegacyStorageForApps(packageFiles);
return response[0];
}
+ /**
+ * Allows Legacy External Storage access for apps that request for it.
+ *
+ * <p>Apps that request for legacy external storage access are granted the access by setting
+ * MANAGE_EXTERNAL_STORAGE App Op. This gives the app File manager privileges, File managers
+ * have legacy external storage access.
+ *
+ * @param appFiles List of Files. Apk Files of the apps that are installed.
+ */
+ private void allowLegacyStorageForApps(List<File> appFiles) throws DeviceNotAvailableException {
+ for (File appFile : appFiles) {
+ AaptParser aaptParser = AaptParser.parse(appFile);
+ if (aaptParser != null
+ && aaptParser.getTargetSdkVersion() > 29
+ && aaptParser.isRequestingLegacyStorage()) {
+ // Set the MANAGE_EXTERNAL_STORAGE App Op to MODE_ALLOWED (Code = 0)
+ // for all users.
+ ArrayList<Integer> userIds = listUsers();
+ for (int userId : userIds) {
+ CommandResult setFileManagerAppOpResult =
+ executeShellV2Command(
+ "appops set --user "
+ + userId
+ + " --uid "
+ + aaptParser.getPackageName()
+ + " MANAGE_EXTERNAL_STORAGE 0");
+ if (!CommandStatus.SUCCESS.equals(setFileManagerAppOpResult.getStatus())) {
+ CLog.e(
+ "Failed to set MANAGE_EXTERNAL_STORAGE App Op to"
+ + " allow legacy external storage for: %s ; stderr: %s",
+ aaptParser.getPackageName(), setFileManagerAppOpResult.getStderr());
+ }
+ }
+ }
+ }
+ }
+
/** {@inheritDoc} */
@Override
public String installPackages(
diff --git a/src/com/android/tradefed/result/ResultForwarder.java b/src/com/android/tradefed/result/ResultForwarder.java
index fa64e72..750b125 100644
--- a/src/com/android/tradefed/result/ResultForwarder.java
+++ b/src/com/android/tradefed/result/ResultForwarder.java
@@ -206,6 +206,19 @@
}
}
+ /** {@inheritDoc} */
+ @Override
+ public void testRunFailed(FailureDescription failure) {
+ for (ITestInvocationListener listener : mListeners) {
+ try {
+ listener.testRunFailed(failure);
+ } catch (RuntimeException e) {
+ CLog.e("Exception while invoking %s#testRunFailed", listener.getClass().getName());
+ CLog.e(e);
+ }
+ }
+ }
+
/**
* {@inheritDoc}
*/
@@ -268,6 +281,19 @@
/** {@inheritDoc} */
@Override
+ public void testFailed(TestDescription test, FailureDescription failure) {
+ for (ITestInvocationListener listener : mListeners) {
+ try {
+ listener.testFailed(test, failure);
+ } catch (RuntimeException e) {
+ CLog.e("Exception while invoking %s#testFailed", listener.getClass().getName());
+ CLog.e(e);
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void testEnded(TestDescription test, HashMap<String, Metric> testMetrics) {
testEnded(test, System.currentTimeMillis(), testMetrics);
}
diff --git a/src/com/android/tradefed/testtype/TfTestLauncher.java b/src/com/android/tradefed/testtype/TfTestLauncher.java
index 2c49459..d940b4b 100644
--- a/src/com/android/tradefed/testtype/TfTestLauncher.java
+++ b/src/com/android/tradefed/testtype/TfTestLauncher.java
@@ -42,8 +42,10 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.regex.Pattern;
/**
@@ -60,6 +62,12 @@
+ "sub process. Run will be slightly slower because of the overhead.")
private boolean mEnableCoverage = false;
+ @Option(name = "include-coverage", description = "Patterns to include in the code coverage.")
+ private Set<String> mIncludeCoverage = new LinkedHashSet<>();
+
+ @Option(name = "exclude-coverage", description = "Patterns to exclude in the code coverage.")
+ private Set<String> mExcludeCoverage = new LinkedHashSet<>();
+
@Option(
name = "hprof-heap-memory",
description =
@@ -240,10 +248,19 @@
* @param destfile destination file where the report will be put.
*/
private void addCoverageArgs(File jacocoAgent, List<String> args, File destfile) {
- String javaagent = String.format("-javaagent:%s=destfile=%s,"
- + "includes=com.android.tradefed*:com.google.android.tradefed*",
- jacocoAgent.getAbsolutePath(),
- destfile.getAbsolutePath());
+ if (mIncludeCoverage.isEmpty() && mExcludeCoverage.isEmpty()) {
+ mIncludeCoverage.add("com.android.tradefed*");
+ mIncludeCoverage.add("com.google.android.tradefed*");
+ }
+ String includeFilter = String.join(":", mIncludeCoverage);
+ String javaagent =
+ String.format(
+ "-javaagent:%s=destfile=%s," + "includes=%s",
+ jacocoAgent.getAbsolutePath(), destfile.getAbsolutePath(), includeFilter);
+ if (!mExcludeCoverage.isEmpty()) {
+ String excludeFilter = String.join(":", mExcludeCoverage);
+ javaagent += ",excludes=" + excludeFilter;
+ }
args.add(javaagent);
}
diff --git a/src/com/android/tradefed/testtype/suite/BaseTestSuite.java b/src/com/android/tradefed/testtype/suite/BaseTestSuite.java
index d2dab70..cd3296e 100644
--- a/src/com/android/tradefed/testtype/suite/BaseTestSuite.java
+++ b/src/com/android/tradefed/testtype/suite/BaseTestSuite.java
@@ -102,12 +102,11 @@
private List<String> mModuleArgs = new ArrayList<>();
@Option(
- name = TEST_ARG_OPTION,
- description =
- "the arguments to pass to a test. The expected format is"
- + "\"<test-class>:<arg-name>:[<arg-key>:=]<arg-value>\"",
- importance = Importance.ALWAYS
- )
+ name = TEST_ARG_OPTION,
+ description =
+ "The arguments to pass to a test or its preparers. The expected format is"
+ + "\"<test-class>:<arg-name>:[<arg-key>:=]<arg-value>\"",
+ importance = Importance.ALWAYS)
private List<String> mTestArgs = new ArrayList<>();
@Option(
diff --git a/src/com/android/tradefed/testtype/suite/ModuleListener.java b/src/com/android/tradefed/testtype/suite/ModuleListener.java
index 3dad444..f78d76f 100644
--- a/src/com/android/tradefed/testtype/suite/ModuleListener.java
+++ b/src/com/android/tradefed/testtype/suite/ModuleListener.java
@@ -111,15 +111,20 @@
}
/** Helper to log the test passed if it didn't fail. */
- private void logTestPassed(String testName) {
+ private void logTestPassed(TestDescription testName) {
if (!mTestFailed && !mCollectTestsOnly) {
+ String runName = "";
+ // Only print the run name in addition to test case fully qualified if different.
+ if (!testName.getClassName().startsWith(getCurrentRunResults().getName())) {
+ runName = getCurrentRunResults().getName() + " ";
+ }
+ String runAndTestCase = String.format("%s%s", runName, testName.toString());
CLog.logAndDisplay(
LogLevel.INFO,
- "[%d/%d] %s %s pass",
+ "[%d/%d] %s pass",
mTestsRan,
getExpectedTests(),
- getCurrentRunResults().getName(),
- testName);
+ runAndTestCase);
}
mTestsRan++;
}
@@ -133,7 +138,7 @@
/** {@inheritDoc} */
@Override
public void testEnded(TestDescription test, long endTime, HashMap<String, Metric> testMetrics) {
- logTestPassed(test.toString());
+ logTestPassed(test);
super.testEnded(test, endTime, testMetrics);
}
diff --git a/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java b/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java
index 0f40af6..c4cd8cc 100644
--- a/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java
+++ b/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java
@@ -64,7 +64,7 @@
public class SuiteModuleLoader {
public static final String CONFIG_EXT = ".config";
- private Map<String, List<OptionDef>> mTestOptions = new HashMap<>();
+ private Map<String, List<OptionDef>> mTestOrPreparerOptions = new HashMap<>();
private Map<String, List<OptionDef>> mModuleOptions = new HashMap<>();
private boolean mIncludeAll;
private Map<String, List<SuiteTestFilter>> mIncludeFilters = new HashMap<>();
@@ -93,7 +93,7 @@
mIncludeFilters = includeFilters;
mExcludeFilters = excludeFilters;
- parseArgs(testArgs, mTestOptions);
+ parseArgs(testArgs, mTestOrPreparerOptions);
parseArgs(moduleArgs, mModuleOptions);
}
@@ -620,6 +620,10 @@
// Set target preparers
List<ITargetPreparer> preparers = config.getTargetPreparers();
for (ITargetPreparer preparer : preparers) {
+ String className = preparer.getClass().getName();
+ if (mTestOrPreparerOptions.containsKey(className)) {
+ config.injectOptionValues(mTestOrPreparerOptions.get(className));
+ }
if (preparer instanceof IAbiReceiver) {
((IAbiReceiver) preparer).setAbi(abi);
}
@@ -629,8 +633,8 @@
List<IRemoteTest> tests = config.getTests();
for (IRemoteTest test : tests) {
String className = test.getClass().getName();
- if (mTestOptions.containsKey(className)) {
- config.injectOptionValues(mTestOptions.get(className));
+ if (mTestOrPreparerOptions.containsKey(className)) {
+ config.injectOptionValues(mTestOrPreparerOptions.get(className));
}
addFiltersToTest(test, abi, fullId, mIncludeFilters, mExcludeFilters);
if (test instanceof IAbiReceiver) {
diff --git a/src/com/android/tradefed/testtype/suite/params/ModuleParameters.java b/src/com/android/tradefed/testtype/suite/params/ModuleParameters.java
index ad77eee..0709915 100644
--- a/src/com/android/tradefed/testtype/suite/params/ModuleParameters.java
+++ b/src/com/android/tradefed/testtype/suite/params/ModuleParameters.java
@@ -29,10 +29,9 @@
public static final String INSTANT_APP_FAMILY = "instant_app_family";
public static final String MULTI_ABI_FAMILY = "multi_abi_family";
+ public static final String SECONDARY_USER_FAMILY = "secondary_user_family";
public static final String[] FAMILY_LIST =
- new String[] {
- INSTANT_APP_FAMILY, MULTI_ABI_FAMILY,
- };
+ new String[] {INSTANT_APP_FAMILY, MULTI_ABI_FAMILY, SECONDARY_USER_FAMILY};
private final String mName;
/** Defines whether several module parameters are associated and mutually exclusive. */
diff --git a/src/com/android/tradefed/testtype/suite/retry/ResultsPlayer.java b/src/com/android/tradefed/testtype/suite/retry/ResultsPlayer.java
index 96538ec..c1a10d7 100644
--- a/src/com/android/tradefed/testtype/suite/retry/ResultsPlayer.java
+++ b/src/com/android/tradefed/testtype/suite/retry/ResultsPlayer.java
@@ -22,6 +22,7 @@
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.device.StubDevice;
import com.android.tradefed.invoker.IInvocationContext;
+import com.android.tradefed.invoker.TestInformation;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ILogSaverListener;
import com.android.tradefed.result.ITestInvocationListener;
@@ -29,7 +30,6 @@
import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.TestResult;
import com.android.tradefed.result.TestRunResult;
-import com.android.tradefed.testtype.IInvocationContextReceiver;
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.util.TimeUtil;
@@ -41,15 +41,13 @@
import java.util.Map.Entry;
/** Special runner that replays the results given to it. */
-public final class ResultsPlayer
- implements IRemoteTest, IInvocationContextReceiver, IConfigurationReceiver {
+public final class ResultsPlayer implements IRemoteTest, IConfigurationReceiver {
private class ReplayModuleHolder {
public IInvocationContext mModuleContext;
public List<Entry<TestDescription, TestResult>> mResults = new ArrayList<>();
}
- private IInvocationContext mContext;
private Map<TestRunResult, ReplayModuleHolder> mModuleResult;
private IConfiguration mConfiguration;
@@ -59,11 +57,12 @@
}
@Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
+ public void run(TestInformation testInfo, ITestInvocationListener listener)
+ throws DeviceNotAvailableException {
// Very first thing of the retry is to check whether all devices are available, this avoids
// use wasting time replaying result for an invocation that will fail right after during
// the re-run.
- for (ITestDevice device : mContext.getDevices()) {
+ for (ITestDevice device : testInfo.getContext().getDevices()) {
if (device.getIDevice() instanceof StubDevice) {
continue;
}
@@ -83,9 +82,11 @@
IInvocationContext moduleContext = holder.mModuleContext;
if (moduleContext != null) {
- for (String deviceName : mContext.getDeviceConfigNames()) {
- moduleContext.addAllocatedDevice(deviceName, mContext.getDevice(deviceName));
- moduleContext.addDeviceBuildInfo(deviceName, mContext.getBuildInfo(deviceName));
+ for (String deviceName : testInfo.getContext().getDeviceConfigNames()) {
+ moduleContext.addAllocatedDevice(
+ deviceName, testInfo.getContext().getDevice(deviceName));
+ moduleContext.addDeviceBuildInfo(
+ deviceName, testInfo.getContext().getBuildInfo(deviceName));
}
listener.testModuleStarted(moduleContext);
}
@@ -141,12 +142,6 @@
/** {@inheritDoc} */
@Override
- public void setInvocationContext(IInvocationContext invocationContext) {
- mContext = invocationContext;
- }
-
- /** {@inheritDoc} */
- @Override
public void setConfiguration(IConfiguration configuration) {
mConfiguration = configuration;
}
diff --git a/src/com/android/tradefed/testtype/suite/retry/RetryRescheduler.java b/src/com/android/tradefed/testtype/suite/retry/RetryRescheduler.java
index e75267b..24d6c07 100644
--- a/src/com/android/tradefed/testtype/suite/retry/RetryRescheduler.java
+++ b/src/com/android/tradefed/testtype/suite/retry/RetryRescheduler.java
@@ -15,6 +15,8 @@
*/
package com.android.tradefed.testtype.suite.retry;
+import static org.junit.Assert.assertNull;
+
import com.android.annotations.VisibleForTesting;
import com.android.tradefed.config.ConfigurationException;
import com.android.tradefed.config.ConfigurationFactory;
@@ -25,6 +27,7 @@
import com.android.tradefed.config.Option.Importance;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.invoker.IRescheduler;
+import com.android.tradefed.invoker.TestInformation;
import com.android.tradefed.log.FileLogger;
import com.android.tradefed.log.ILeveledLogOutput;
import com.android.tradefed.log.LogUtil.CLog;
@@ -109,7 +112,13 @@
private IConfiguration mRescheduledConfiguration;
@Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
+ public void run(
+ TestInformation testInfo /* do not use - should be null */,
+ ITestInvocationListener listener /* do not use - should be null */)
+ throws DeviceNotAvailableException {
+ assertNull(testInfo);
+ assertNull(listener);
+
// Get the re-loader for previous results
Object loader = mConfiguration.getConfigurationObject(PREVIOUS_LOADER_NAME);
if (loader == null) {
diff --git a/src/com/android/tradefed/util/AaptParser.java b/src/com/android/tradefed/util/AaptParser.java
index 58a8b39..b20652e 100644
--- a/src/com/android/tradefed/util/AaptParser.java
+++ b/src/com/android/tradefed/util/AaptParser.java
@@ -37,10 +37,15 @@
Pattern.MULTILINE);
private static final Pattern SDK_PATTERN = Pattern.compile(
"^sdkVersion:'(\\d+)'", Pattern.MULTILINE);
+ private static final Pattern TARGET_SDK_PATTERN =
+ Pattern.compile("^targetSdkVersion:'(\\d+)'", Pattern.MULTILINE);
/** Patterns for native code are not always present, so the list may stay empty. */
private static final Pattern NATIVE_CODE_PATTERN =
Pattern.compile("native-code: '(.*?)'( '.*?')*");
+ private static final Pattern REQUEST_LEGACY_STORAGE_PATTERN =
+ Pattern.compile("requestLegacyExternalStorage.*=\\(.*\\)(.*)", Pattern.MULTILINE);
+
private static final Pattern ALT_NATIVE_CODE_PATTERN =
Pattern.compile("alt-native-code: '(.*)'");
private static final int AAPT_TIMEOUT_MS = 60000;
@@ -52,6 +57,8 @@
private List<String> mNativeCode = new ArrayList<>();
private String mLabel;
private int mSdkVersion = INVALID_SDK;
+ private int mTargetSdkVersion = 10000;
+ private boolean mRequestLegacyStorage = false;
// @VisibleForTesting
AaptParser() {
@@ -73,6 +80,10 @@
if (m.find()) {
mSdkVersion = Integer.parseInt(m.group(1));
}
+ m = TARGET_SDK_PATTERN.matcher(aaptOut);
+ if (m.find()) {
+ mTargetSdkVersion = Integer.parseInt(m.group(1));
+ }
m = NATIVE_CODE_PATTERN.matcher(aaptOut);
if (m.find()) {
for (int i = 1; i <= m.groupCount(); i++) {
@@ -96,6 +107,16 @@
return false;
}
+ boolean parseXmlTree(String aaptOut) {
+ Matcher m = REQUEST_LEGACY_STORAGE_PATTERN.matcher(aaptOut);
+ if (m.find()) {
+ // 0xffffffff is true and 0x0 is false
+ mRequestLegacyStorage = m.group(1).equals("0xffffffff");
+ }
+ // REQUEST_LEGACY_STORAGE_PATTERN may or may not be present
+ return true;
+ }
+
/**
* Parse info from the apk.
*
@@ -118,17 +139,38 @@
if (stderr != null && !stderr.isEmpty()) {
CLog.e("aapt dump badging stderr: %s", stderr);
}
-
- if (CommandStatus.SUCCESS.equals(result.getStatus())) {
- AaptParser p = new AaptParser();
- if (p.parse(result.getStdout()))
- return p;
+ AaptParser p = new AaptParser();
+ if (!CommandStatus.SUCCESS.equals(result.getStatus()) || !p.parse(result.getStdout())) {
+ CLog.e(
+ "Failed to run aapt on %s. stdout: %s",
+ apkFile.getAbsoluteFile(), result.getStdout());
return null;
}
- CLog.e(
- "Failed to run aapt on %s. stdout: %s",
- apkFile.getAbsoluteFile(), result.getStdout());
- return null;
+ result =
+ RunUtil.getDefault()
+ .runTimedCmdRetry(
+ AAPT_TIMEOUT_MS,
+ 0L,
+ 2,
+ "aapt",
+ "dump",
+ "xmltree",
+ apkFile.getAbsolutePath(),
+ "AndroidManifest.xml");
+
+ stderr = result.getStderr();
+ if (stderr != null && !stderr.isEmpty()) {
+ CLog.e("aapt dump xmltree AndroidManifest.xml stderr: %s", stderr);
+ }
+
+ if (!CommandStatus.SUCCESS.equals(result.getStatus())
+ || !p.parseXmlTree(result.getStdout())) {
+ CLog.e(
+ "Failed to run aapt on %s. stdout: %s",
+ apkFile.getAbsoluteFile(), result.getStdout());
+ return null;
+ }
+ return p;
}
public String getPackageName() {
@@ -154,4 +196,17 @@
public int getSdkVersion() {
return mSdkVersion;
}
+
+ public int getTargetSdkVersion() {
+ return mTargetSdkVersion;
+ }
+
+ /**
+ * Check if the app is requesting legacy storage.
+ *
+ * @return boolean return true if requestLegacyExternalStorage is true in AndroidManifest.xml
+ */
+ public boolean isRequestingLegacyStorage() {
+ return mRequestLegacyStorage;
+ }
}
diff --git a/test_result_interfaces/Android.bp b/test_result_interfaces/Android.bp
index 9a8cc0b..6d6d6b1 100644
--- a/test_result_interfaces/Android.bp
+++ b/test_result_interfaces/Android.bp
@@ -20,6 +20,7 @@
],
libs: [
"ddmlib-prebuilt",
+ "jsr305",
"tradefed-common-util",
"tradefed-protos",
],
diff --git a/test_result_interfaces/com/android/tradefed/result/FailureDescription.java b/test_result_interfaces/com/android/tradefed/result/FailureDescription.java
new file mode 100644
index 0000000..4018ace
--- /dev/null
+++ b/test_result_interfaces/com/android/tradefed/result/FailureDescription.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 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.result;
+
+import com.android.tradefed.result.proto.TestRecordProto;
+
+import javax.annotation.Nullable;
+
+/**
+ * The class describing a failure information in Trade Federation. This class contains the debugging
+ * information and context of the failure that helps understanding the issue.
+ */
+public class FailureDescription {
+ // The error message generated from the failure
+ private String mErrorMessage;
+ // Optional: The category of the failure
+ private @Nullable TestRecordProto.FailureStatus mFailureStatus;
+
+ FailureDescription() {}
+
+ /**
+ * Set the {@link com.android.tradefed.result.proto.TestRecordProto.FailureStatus} associated
+ * with the failure.
+ */
+ public FailureDescription setFailureStatus(TestRecordProto.FailureStatus status) {
+ mFailureStatus = status;
+ return this;
+ }
+
+ /** Returns the FailureStatus associated with the failure. Can be null. */
+ public @Nullable TestRecordProto.FailureStatus getFailureStatus() {
+ return mFailureStatus;
+ }
+
+ /** Returns the error message associated with the failure. */
+ public String getErrorMessage() {
+ return mErrorMessage;
+ }
+
+ @Override
+ public String toString() {
+ // For backward compatibility of result interface, toString falls back to the simple message
+ return mErrorMessage;
+ }
+
+ /**
+ * Create a {@link FailureDescription} based on the error message generated from the failure.
+ *
+ * @param errorMessage The error message from the failure.
+ * @return the created {@link FailureDescription}
+ */
+ public static FailureDescription create(String errorMessage) {
+ return create(errorMessage, null);
+ }
+
+ /**
+ * Create a {@link FailureDescription} based on the error message generated from the failure.
+ *
+ * @param errorMessage The error message from the failure.
+ * @param status The status associated with the failure.
+ * @return the created {@link FailureDescription}
+ */
+ public static FailureDescription create(
+ String errorMessage, @Nullable TestRecordProto.FailureStatus status) {
+ FailureDescription info = new FailureDescription();
+ info.mErrorMessage = errorMessage;
+ info.mFailureStatus = status;
+ return info;
+ }
+}
diff --git a/test_result_interfaces/com/android/tradefed/result/ITestLifeCycleReceiver.java b/test_result_interfaces/com/android/tradefed/result/ITestLifeCycleReceiver.java
index a4f86cc..99f563f 100644
--- a/test_result_interfaces/com/android/tradefed/result/ITestLifeCycleReceiver.java
+++ b/test_result_interfaces/com/android/tradefed/result/ITestLifeCycleReceiver.java
@@ -88,6 +88,15 @@
public default void testRunFailed(String errorMessage) {}
/**
+ * Reports test run failed to complete due to a failure described by {@link FailureDescription}.
+ *
+ * @param failure {@link FailureDescription} describing the failure and its context.
+ */
+ public default void testRunFailed(FailureDescription failure) {
+ testRunFailed(failure.toString());
+ }
+
+ /**
* Reports end of test run.
*
* @param elapsedTimeMillis device reported elapsed time, in milliseconds
@@ -145,6 +154,18 @@
public default void testFailed(TestDescription test, String trace) {}
/**
+ * Reports the failure of a individual test case.
+ *
+ * <p>Will be called between testStarted and testEnded.
+ *
+ * @param test identifies the test
+ * @param failure {@link FailureDescription} describing the failure and its context.
+ */
+ public default void testFailed(TestDescription test, FailureDescription failure) {
+ testFailed(test, failure.toString());
+ }
+
+ /**
* Called when an atomic test flags that it assumes a condition that is false
*
* @param test identifies the test
diff --git a/test_result_interfaces/com/android/tradefed/result/MultiFailureDescription.java b/test_result_interfaces/com/android/tradefed/result/MultiFailureDescription.java
new file mode 100644
index 0000000..55ad8dc
--- /dev/null
+++ b/test_result_interfaces/com/android/tradefed/result/MultiFailureDescription.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2020 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.result;
+
+import com.android.tradefed.result.proto.TestRecordProto.FailureStatus;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+/**
+ * Collect multiple {@link FailureDescription} in one holder. This can be used to carry all the
+ * failures description when several attempts on the same test case or run are made, each resulting
+ * in a failure.
+ */
+public final class MultiFailureDescription extends FailureDescription {
+
+ private List<FailureDescription> mFailures = new ArrayList<>();
+
+ public MultiFailureDescription(List<FailureDescription> failures) {
+ super();
+ mFailures.addAll(failures);
+ }
+
+ public MultiFailureDescription(FailureDescription... failures) {
+ super();
+ mFailures.addAll(Arrays.asList(failures));
+ }
+
+ /**
+ * Add another failure to an existing {@link MultiFailureDescription}.
+ *
+ * @param failure The additional failure
+ * @return The current {@link MultiFailureDescription}.
+ */
+ public MultiFailureDescription addFailure(FailureDescription failure) {
+ mFailures.add(failure);
+ return this;
+ }
+
+ /**
+ * Returns the list of {@link FailureDescription} tracked by the {@link
+ * MultiFailureDescription}.
+ */
+ public List<FailureDescription> getFailures() {
+ return mFailures;
+ }
+
+ @Override
+ public @Nullable FailureStatus getFailureStatus() {
+ throw new UnsupportedOperationException(
+ "Cannot call #getFailureStatus on MultiFailureDescription");
+ }
+
+ @Override
+ public String getErrorMessage() {
+ throw new UnsupportedOperationException(
+ "Cannot call #getErrorMessage on MultiFailureDescription");
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb =
+ new StringBuilder(String.format("There were %d failures:", mFailures.size()));
+ for (FailureDescription f : mFailures) {
+ sb.append(String.format("\n %s", f.toString()));
+ }
+ return sb.toString();
+ }
+}
diff --git a/tests/src/com/android/tradefed/UnitTests.java b/tests/src/com/android/tradefed/UnitTests.java
index ecd6680..c299b28 100644
--- a/tests/src/com/android/tradefed/UnitTests.java
+++ b/tests/src/com/android/tradefed/UnitTests.java
@@ -160,6 +160,7 @@
import com.android.tradefed.result.DeviceFileReporterTest;
import com.android.tradefed.result.DeviceUnavailEmailResultReporterTest;
import com.android.tradefed.result.EmailResultReporterTest;
+import com.android.tradefed.result.FailureDescriptionTest;
import com.android.tradefed.result.FailureEmailResultReporterTest;
import com.android.tradefed.result.FileSystemLogSaverTest;
import com.android.tradefed.result.InvocationFailureEmailResultReporterTest;
@@ -170,6 +171,7 @@
import com.android.tradefed.result.LogFileSaverTest;
import com.android.tradefed.result.LogcatCrashResultForwarderTest;
import com.android.tradefed.result.MetricsXMLResultReporterTest;
+import com.android.tradefed.result.MultiFailureDescriptionTest;
import com.android.tradefed.result.SnapshotInputStreamSourceTest;
import com.android.tradefed.result.SubprocessResultsReporterTest;
import com.android.tradefed.result.TestDescriptionTest;
@@ -589,6 +591,7 @@
DeviceFileReporterTest.class,
DeviceUnavailEmailResultReporterTest.class,
EmailResultReporterTest.class,
+ FailureDescriptionTest.class,
FailureEmailResultReporterTest.class,
FileSystemLogSaverTest.class,
InvocationFailureEmailResultReporterTest.class,
@@ -599,6 +602,7 @@
LogcatCrashResultForwarderTest.class,
LogFileSaverTest.class,
MetricsXMLResultReporterTest.class,
+ MultiFailureDescriptionTest.class,
SnapshotInputStreamSourceTest.class,
SubprocessResultsReporterTest.class,
TestDescriptionTest.class,
diff --git a/tests/src/com/android/tradefed/config/ConfigurationXmlParserTest.java b/tests/src/com/android/tradefed/config/ConfigurationXmlParserTest.java
index f1eee0b..b40597d 100644
--- a/tests/src/com/android/tradefed/config/ConfigurationXmlParserTest.java
+++ b/tests/src/com/android/tradefed/config/ConfigurationXmlParserTest.java
@@ -303,7 +303,7 @@
* Map)}. when presented a device tag with a used name, should merge them.
*/
@Test
- public void testParse_deviceTagSameName() {
+ public void testParse_deviceTagSameName() throws Exception {
final String normalConfig =
"<configuration description=\"desc\" >\n" +
" <device name=\"device1\">\n" +
@@ -318,15 +318,11 @@
"</configuration>";
final String configName = "config";
ConfigurationDef configDef = new ConfigurationDef(configName);
- try {
- xmlParser.parse(configDef, configName, getStringAsStream(normalConfig), null);
- assertTrue(configDef.getObjectClassMap().get(Configuration.DEVICE_NAME).size() == 2);
- assertTrue("{device1}opName".equals(configDef.getOptionList().get(0).name));
- assertEquals("{device2}opName3", configDef.getOptionList().get(1).name);
- assertTrue("{device1}opName2".equals(configDef.getOptionList().get(2).name));
- } catch(ConfigurationException unExpected) {
- fail("No exception should have been thrown.");
- }
+ xmlParser.parse(configDef, configName, getStringAsStream(normalConfig), null);
+ assertTrue(configDef.getObjectClassMap().get(Configuration.DEVICE_NAME).size() == 2);
+ assertTrue("{device1}opName".equals(configDef.getOptionList().get(0).name));
+ assertEquals("{device2}opName3", configDef.getOptionList().get(1).name);
+ assertTrue("{device1}opName2".equals(configDef.getOptionList().get(2).name));
}
/**
diff --git a/tests/src/com/android/tradefed/device/LocalAndroidVirtualDeviceTest.java b/tests/src/com/android/tradefed/device/LocalAndroidVirtualDeviceTest.java
index 28335ef..c123833 100644
--- a/tests/src/com/android/tradefed/device/LocalAndroidVirtualDeviceTest.java
+++ b/tests/src/com/android/tradefed/device/LocalAndroidVirtualDeviceTest.java
@@ -41,6 +41,7 @@
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.easymock.Capture;
import org.easymock.EasyMock;
+import org.easymock.IAnswer;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -61,22 +62,27 @@
super(device, stateMonitor, allocationMonitor);
}
- IDevice currentDevice = null;
- IRunUtil currentRunUtil = null;
+ IRunUtil currentRunUtil;
+ boolean expectToConnect;
@Override
- public IDevice getIDevice() {
- return currentDevice;
+ public boolean adbTcpConnect(String host, String port) {
+ Assert.assertTrue("Unexpected method call to adbTcpConnect.", expectToConnect);
+ Assert.assertEquals(IP_ADDRESS, host);
+ Assert.assertEquals(PORT, port);
+ return true;
}
@Override
- public void setIDevice(IDevice device) {
- currentDevice = device;
+ public boolean adbTcpDisconnect(String host, String port) {
+ Assert.assertEquals(IP_ADDRESS, host);
+ Assert.assertEquals(PORT, port);
+ return true;
}
@Override
- public void setDeviceState(TestDeviceState state) {
- Assert.assertEquals(TestDeviceState.NOT_AVAILABLE, state);
+ public void waitForDeviceAvailable() {
+ Assert.assertTrue("Unexpected method call to waitForDeviceAvailable.", expectToConnect);
}
@Override
@@ -94,9 +100,44 @@
}
private static final String STUB_SERIAL_NUMBER = "local-virtual-device-0";
- private static final String ONLINE_SERIAL_NUMBER = "127.0.0.1:6520";
+ private static final String IP_ADDRESS = "127.0.0.1";
+ private static final String PORT = "6520";
+ private static final String ONLINE_SERIAL_NUMBER = IP_ADDRESS + ":" + PORT;
+ private static final String INSTANCE_NAME = "local-instance-1";
private static final String BUILD_FLAVOR = "cf_x86_phone-userdebug";
private static final long ACLOUD_TIMEOUT = 12345;
+ private static final String SUCCESS_REPORT_STRING =
+ String.format(
+ "{"
+ + " \"command\": \"create\","
+ + " \"data\": {"
+ + " \"devices\": ["
+ + " {"
+ + " \"ip\": \"%s\","
+ + " \"instance_name\": \"%s\""
+ + " }"
+ + " ]"
+ + " },"
+ + " \"errors\": [],"
+ + " \"status\": \"SUCCESS\""
+ + "}",
+ ONLINE_SERIAL_NUMBER, INSTANCE_NAME);
+ private static final String FAILURE_REPORT_STRING =
+ String.format(
+ "{"
+ + " \"command\": \"create\","
+ + " \"data\": {"
+ + " \"devices_failing_boot\": ["
+ + " {"
+ + " \"ip\": \"%s\","
+ + " \"instance_name\": \"%s\""
+ + " }"
+ + " ]"
+ + " },"
+ + " \"errors\": [],"
+ + " \"status\": \"BOOT_FAIL\""
+ + "}",
+ ONLINE_SERIAL_NUMBER, INSTANCE_NAME);
// Temporary files.
private File mAcloud;
@@ -104,12 +145,7 @@
private File mHostPackageTarGzip;
private File mTmpDir;
- // The initial stub device.
- private StubLocalAndroidVirtualDevice mStubLocalAvd;
-
- // Mock objects
- private IDeviceStateMonitor mMockDeviceStateMonitor;
- private IDeviceMonitor mMockDeviceMonitor;
+ // Mock object.
private IDeviceBuildInfo mMockDeviceBuildInfo;
// The object under test.
@@ -123,20 +159,22 @@
createHostPackage(mHostPackageTarGzip);
mTmpDir = FileUtil.createTempDir("LocalAvdTmp");
- mStubLocalAvd = new StubLocalAndroidVirtualDevice(STUB_SERIAL_NUMBER);
-
- mMockDeviceStateMonitor = EasyMock.createMock(IDeviceStateMonitor.class);
- mMockDeviceMonitor = EasyMock.createMock(IDeviceMonitor.class);
mMockDeviceBuildInfo = EasyMock.createMock(IDeviceBuildInfo.class);
EasyMock.expect(mMockDeviceBuildInfo.getDeviceImageFile()).andReturn(mImageZip);
EasyMock.expect(mMockDeviceBuildInfo.getFile(EasyMock.eq("cvd-host_package.tar.gz")))
.andReturn(mHostPackageTarGzip);
EasyMock.expect(mMockDeviceBuildInfo.getBuildFlavor()).andReturn(BUILD_FLAVOR);
+ IDeviceStateMonitor mockDeviceStateMonitor = EasyMock.createMock(IDeviceStateMonitor.class);
+ mockDeviceStateMonitor.setIDevice(EasyMock.anyObject());
+ EasyMock.expectLastCall().anyTimes();
+ IDeviceMonitor mockDeviceMonitor = EasyMock.createMock(IDeviceMonitor.class);
+ EasyMock.replay(mMockDeviceBuildInfo, mockDeviceStateMonitor, mockDeviceMonitor);
mLocalAvd =
new TestableLocalAndroidVirtualDevice(
- mStubLocalAvd, mMockDeviceStateMonitor, mMockDeviceMonitor);
- mLocalAvd.setIDevice(mStubLocalAvd);
+ new StubLocalAndroidVirtualDevice(STUB_SERIAL_NUMBER),
+ mockDeviceStateMonitor,
+ mockDeviceMonitor);
TestDeviceOptions options = mLocalAvd.getOptions();
options.setGceCmdTimeout(ACLOUD_TIMEOUT);
options.setAvdDriverBinary(mAcloud);
@@ -178,35 +216,54 @@
}
}
- private void replayAllMocks(Object... mocks) {
- EasyMock.replay(mocks);
- EasyMock.replay(mMockDeviceStateMonitor, mMockDeviceMonitor, mMockDeviceBuildInfo);
- }
-
private IRunUtil mockAcloudCreate(
- CommandStatus status, Capture<String> hostPackageDir, Capture<String> imageDir) {
+ CommandStatus status,
+ String reportString,
+ Capture<String> reportFile,
+ Capture<String> hostPackageDir,
+ Capture<String> imageDir) {
IRunUtil runUtil = EasyMock.createMock(IRunUtil.class);
runUtil.setEnvVariable(EasyMock.eq("TMPDIR"), EasyMock.eq(mTmpDir.getAbsolutePath()));
- runUtil.setEnvVariable(EasyMock.eq("ANDROID_HOST_OUT"), EasyMock.capture(hostPackageDir));
runUtil.setEnvVariable(EasyMock.eq("TARGET_PRODUCT"), EasyMock.eq(BUILD_FLAVOR));
- CommandResult result = new CommandResult(status);
- result.setStderr("acloud create");
- result.setStdout("acloud create");
+ IAnswer<CommandResult> writeToReportFile =
+ new IAnswer() {
+ @Override
+ public CommandResult answer() throws Throwable {
+ Object[] args = EasyMock.getCurrentArguments();
+ for (int index = 0; index < args.length; index++) {
+ if ("--report_file".equals(args[index])) {
+ index++;
+ File file = new File((String) args[index]);
+ FileUtil.writeToFile(reportString, file);
+ }
+ }
+
+ CommandResult result = new CommandResult(status);
+ result.setStderr("acloud create");
+ result.setStdout("acloud create");
+ return result;
+ }
+ };
+
EasyMock.expect(
runUtil.runTimedCmd(
EasyMock.eq(ACLOUD_TIMEOUT),
- EasyMock.startsWith(mAcloud.getAbsolutePath()),
+ EasyMock.eq(mAcloud.getAbsolutePath()),
EasyMock.eq("create"),
EasyMock.eq("--local-instance"),
- EasyMock.eq("1"),
EasyMock.eq("--local-image"),
EasyMock.capture(imageDir),
+ EasyMock.eq("--local-tool"),
+ EasyMock.capture(hostPackageDir),
+ EasyMock.eq("--report_file"),
+ EasyMock.capture(reportFile),
+ EasyMock.eq("--no-autoconnect"),
EasyMock.eq("--yes"),
EasyMock.eq("--skip-pre-run-check"),
EasyMock.eq("-vv"),
EasyMock.eq("-test")))
- .andReturn(result);
+ .andAnswer(writeToReportFile);
return runUtil;
}
@@ -221,10 +278,11 @@
EasyMock.expect(
runUtil.runTimedCmd(
EasyMock.eq(ACLOUD_TIMEOUT),
- EasyMock.startsWith(mAcloud.getAbsolutePath()),
+ EasyMock.eq(mAcloud.getAbsolutePath()),
EasyMock.eq("delete"),
+ EasyMock.eq("--local-only"),
EasyMock.eq("--instance-names"),
- EasyMock.eq("local-instance-1"),
+ EasyMock.eq(INSTANCE_NAME),
EasyMock.eq("-vv")))
.andReturn(result);
@@ -269,10 +327,16 @@
@Test
public void testPreinvocationSetupSuccess()
throws DeviceNotAvailableException, IOException, TargetSetupError {
+ Capture<String> reportFile = new Capture<String>();
Capture<String> hostPackageDir = new Capture<String>();
Capture<String> imageDir = new Capture<String>();
IRunUtil acloudCreateRunUtil =
- mockAcloudCreate(CommandStatus.SUCCESS, hostPackageDir, imageDir);
+ mockAcloudCreate(
+ CommandStatus.SUCCESS,
+ SUCCESS_REPORT_STRING,
+ reportFile,
+ hostPackageDir,
+ imageDir);
IRunUtil acloudDeleteRunUtil = mockAcloudDelete(CommandStatus.SUCCESS);
@@ -281,11 +345,12 @@
IDevice mockOnlineDevice = EasyMock.createMock(IDevice.class);
EasyMock.expect(mockOnlineDevice.getSerialNumber()).andReturn(ONLINE_SERIAL_NUMBER);
- replayAllMocks(acloudCreateRunUtil, acloudDeleteRunUtil, testLogger, mockOnlineDevice);
+ EasyMock.replay(acloudCreateRunUtil, acloudDeleteRunUtil, testLogger, mockOnlineDevice);
// Test setUp.
mLocalAvd.setTestLogger(testLogger);
mLocalAvd.currentRunUtil = acloudCreateRunUtil;
+ mLocalAvd.expectToConnect = true;
mLocalAvd.preInvocationSetup(mMockDeviceBuildInfo, null);
Assert.assertEquals(ONLINE_SERIAL_NUMBER, mLocalAvd.getIDevice().getSerialNumber());
@@ -300,34 +365,42 @@
// Create the logs and configuration that the local AVD object expects.
File runtimeDir =
FileUtil.getFileForPath(
- mTmpDir, "acloud_cvd_temp", "instance_home_1", "cuttlefish_runtime");
+ mTmpDir, "acloud_cvd_temp", INSTANCE_NAME, "cuttlefish_runtime");
Assert.assertTrue(runtimeDir.mkdirs());
createEmptyFiles(
runtimeDir, "kernel.log", "logcat", "launcher.log", "cuttlefish_config.json");
// Test tearDown.
mLocalAvd.currentRunUtil = acloudDeleteRunUtil;
+ mLocalAvd.expectToConnect = false;
mLocalAvd.postInvocationTearDown(null);
assertFinalDeviceState(mLocalAvd.getIDevice());
+ Assert.assertFalse(new File(reportFile.getValue()).exists());
Assert.assertFalse(capturedHostPackageDir.exists());
Assert.assertFalse(capturedImageDir.exists());
}
- /** Test that the device cannot boot within timeout. */
+ /** Test that the acloud command reports failure. */
@Test
- public void testPreInvocationSetupTimeout() throws DeviceNotAvailableException {
+ public void testPreInvocationSetupBootFailure() throws DeviceNotAvailableException {
+ Capture<String> reportFile = new Capture<String>();
Capture<String> hostPackageDir = new Capture<String>();
Capture<String> imageDir = new Capture<String>();
IRunUtil acloudCreateRunUtil =
- mockAcloudCreate(CommandStatus.TIMED_OUT, hostPackageDir, imageDir);
+ mockAcloudCreate(
+ CommandStatus.SUCCESS,
+ FAILURE_REPORT_STRING,
+ reportFile,
+ hostPackageDir,
+ imageDir);
IRunUtil acloudDeleteRunUtil = mockAcloudDelete(CommandStatus.FAILED);
ITestLogger testLogger = EasyMock.createMock(ITestLogger.class);
- replayAllMocks(acloudCreateRunUtil, acloudDeleteRunUtil, testLogger);
+ EasyMock.replay(acloudCreateRunUtil, acloudDeleteRunUtil, testLogger);
// Test setUp.
TargetSetupError expectedException = null;
@@ -340,7 +413,7 @@
expectedException = e;
}
- Assert.assertEquals(ONLINE_SERIAL_NUMBER, mLocalAvd.getIDevice().getSerialNumber());
+ Assert.assertEquals(STUB_SERIAL_NUMBER, mLocalAvd.getIDevice().getSerialNumber());
File capturedHostPackageDir = new File(hostPackageDir.getValue());
File capturedImageDir = new File(imageDir.getValue());
@@ -353,23 +426,23 @@
assertFinalDeviceState(mLocalAvd.getIDevice());
+ Assert.assertFalse(new File(reportFile.getValue()).exists());
Assert.assertFalse(capturedHostPackageDir.exists());
Assert.assertFalse(capturedImageDir.exists());
}
- /** Test that the device fails to boot. */
+ /** Test that the acloud command fails, and the report is empty. */
@Test
public void testPreInvocationSetupFailure() throws DeviceNotAvailableException {
+ Capture<String> reportFile = new Capture<String>();
Capture<String> hostPackageDir = new Capture<String>();
Capture<String> imageDir = new Capture<String>();
IRunUtil acloudCreateRunUtil =
- mockAcloudCreate(CommandStatus.FAILED, hostPackageDir, imageDir);
-
- IRunUtil acloudDeleteRunUtil = mockAcloudDelete(CommandStatus.FAILED);
+ mockAcloudCreate(CommandStatus.FAILED, "", reportFile, hostPackageDir, imageDir);
ITestLogger testLogger = EasyMock.createMock(ITestLogger.class);
- replayAllMocks(acloudCreateRunUtil, acloudDeleteRunUtil, testLogger);
+ EasyMock.replay(acloudCreateRunUtil, testLogger);
// Test setUp.
TargetSetupError expectedException = null;
@@ -382,7 +455,7 @@
expectedException = e;
}
- Assert.assertEquals(ONLINE_SERIAL_NUMBER, mLocalAvd.getIDevice().getSerialNumber());
+ Assert.assertEquals(STUB_SERIAL_NUMBER, mLocalAvd.getIDevice().getSerialNumber());
File capturedHostPackageDir = new File(hostPackageDir.getValue());
File capturedImageDir = new File(imageDir.getValue());
@@ -390,11 +463,12 @@
Assert.assertTrue(capturedImageDir.isDirectory());
// Test tearDown.
- mLocalAvd.currentRunUtil = acloudDeleteRunUtil;
+ mLocalAvd.currentRunUtil = null;
mLocalAvd.postInvocationTearDown(expectedException);
assertFinalDeviceState(mLocalAvd.getIDevice());
+ Assert.assertFalse(new File(reportFile.getValue()).exists());
Assert.assertFalse(capturedHostPackageDir.exists());
Assert.assertFalse(capturedImageDir.exists());
}
diff --git a/tests/src/com/android/tradefed/device/metric/BugreportzOnFailureCollectorTest.java b/tests/src/com/android/tradefed/device/metric/BugreportzOnFailureCollectorTest.java
index fb4b2d5..330b2c5 100644
--- a/tests/src/com/android/tradefed/device/metric/BugreportzOnFailureCollectorTest.java
+++ b/tests/src/com/android/tradefed/device/metric/BugreportzOnFailureCollectorTest.java
@@ -56,7 +56,7 @@
public void testCollect() throws Exception {
TestDescription test = new TestDescription("class", "test");
mMockListener.testStarted(EasyMock.eq(test), EasyMock.anyLong());
- mMockListener.testFailed(EasyMock.eq(test), EasyMock.anyObject());
+ mMockListener.testFailed(EasyMock.eq(test), (String) EasyMock.anyObject());
mMockListener.testEnded(
EasyMock.eq(test),
EasyMock.anyLong(),
diff --git a/tests/src/com/android/tradefed/device/metric/DebugHostLogOnFailureCollectorTest.java b/tests/src/com/android/tradefed/device/metric/DebugHostLogOnFailureCollectorTest.java
index 9d610e3..5eb295e 100644
--- a/tests/src/com/android/tradefed/device/metric/DebugHostLogOnFailureCollectorTest.java
+++ b/tests/src/com/android/tradefed/device/metric/DebugHostLogOnFailureCollectorTest.java
@@ -117,7 +117,7 @@
.testRunStarted(
Mockito.eq("runName"), Mockito.eq(1), Mockito.eq(0), Mockito.anyLong());
Mockito.verify(mMockListener).testStarted(Mockito.eq(test), Mockito.anyLong());
- Mockito.verify(mMockListener).testFailed(Mockito.eq(test), Mockito.any());
+ Mockito.verify(mMockListener).testFailed(Mockito.eq(test), (String) Mockito.any());
Mockito.verify(mMockListener)
.testLog(
Mockito.eq("class#test-debug-hostlog-on-failure"),
@@ -152,7 +152,7 @@
.testRunStarted(
Mockito.eq("runName"), Mockito.eq(1), Mockito.eq(0), Mockito.anyLong());
Mockito.verify(mMockListener).testStarted(Mockito.eq(test), Mockito.anyLong());
- Mockito.verify(mMockListener).testFailed(Mockito.eq(test), Mockito.any());
+ Mockito.verify(mMockListener).testFailed(Mockito.eq(test), (String) Mockito.any());
// No file is logged
Mockito.verify(mMockListener, never())
.testLog(
diff --git a/tests/src/com/android/tradefed/device/metric/LogcatOnFailureCollectorTest.java b/tests/src/com/android/tradefed/device/metric/LogcatOnFailureCollectorTest.java
index ca86faa..b338ed2 100644
--- a/tests/src/com/android/tradefed/device/metric/LogcatOnFailureCollectorTest.java
+++ b/tests/src/com/android/tradefed/device/metric/LogcatOnFailureCollectorTest.java
@@ -111,7 +111,7 @@
EasyMock.eq("runName"), EasyMock.eq(1), EasyMock.eq(0), EasyMock.anyLong());
TestDescription test = new TestDescription("class", "test");
mMockListener.testStarted(EasyMock.eq(test), EasyMock.anyLong());
- mMockListener.testFailed(EasyMock.eq(test), EasyMock.anyObject());
+ mMockListener.testFailed(EasyMock.eq(test), (String) EasyMock.anyObject());
mMockListener.testEnded(
EasyMock.eq(test),
EasyMock.anyLong(),
@@ -152,7 +152,7 @@
EasyMock.eq("runName"), EasyMock.eq(1), EasyMock.eq(0), EasyMock.anyLong());
TestDescription test = new TestDescription("class", "test");
mMockListener.testStarted(EasyMock.eq(test), EasyMock.anyLong());
- mMockListener.testFailed(EasyMock.eq(test), EasyMock.anyObject());
+ mMockListener.testFailed(EasyMock.eq(test), (String) EasyMock.anyObject());
mMockListener.testEnded(
EasyMock.eq(test),
EasyMock.anyLong(),
@@ -201,7 +201,7 @@
TestDescription test = new TestDescription("class", "test");
TestDescription test2 = new TestDescription("class2", "test2");
mMockListener.testStarted(EasyMock.eq(test), EasyMock.anyLong());
- mMockListener.testFailed(EasyMock.eq(test), EasyMock.anyObject());
+ mMockListener.testFailed(EasyMock.eq(test), (String) EasyMock.anyObject());
mMockListener.testEnded(
EasyMock.eq(test),
EasyMock.anyLong(),
@@ -221,7 +221,7 @@
mMockListener.testRunStarted(
EasyMock.eq("runName2"), EasyMock.eq(1), EasyMock.eq(0), EasyMock.anyLong());
mMockListener.testStarted(EasyMock.eq(test2), EasyMock.anyLong());
- mMockListener.testFailed(EasyMock.eq(test2), EasyMock.anyObject());
+ mMockListener.testFailed(EasyMock.eq(test2), (String) EasyMock.anyObject());
mMockListener.testEnded(
EasyMock.eq(test2),
EasyMock.anyLong(),
diff --git a/tests/src/com/android/tradefed/device/metric/ScreenshotOnFailureCollectorTest.java b/tests/src/com/android/tradefed/device/metric/ScreenshotOnFailureCollectorTest.java
index 683a466..20776d0 100644
--- a/tests/src/com/android/tradefed/device/metric/ScreenshotOnFailureCollectorTest.java
+++ b/tests/src/com/android/tradefed/device/metric/ScreenshotOnFailureCollectorTest.java
@@ -59,7 +59,7 @@
public void testCollect() throws Exception {
TestDescription test = new TestDescription("class", "test");
mMockListener.testStarted(EasyMock.eq(test), EasyMock.anyLong());
- mMockListener.testFailed(EasyMock.eq(test), EasyMock.anyObject());
+ mMockListener.testFailed(EasyMock.eq(test), (String) EasyMock.anyObject());
mMockListener.testEnded(
EasyMock.eq(test),
EasyMock.anyLong(),
diff --git a/tests/src/com/android/tradefed/log/LogRegistryTest.java b/tests/src/com/android/tradefed/log/LogRegistryTest.java
index b43ff87..deda135 100644
--- a/tests/src/com/android/tradefed/log/LogRegistryTest.java
+++ b/tests/src/com/android/tradefed/log/LogRegistryTest.java
@@ -105,10 +105,10 @@
}
/**
- * Tests for ensuring new threads spawned without an explicit ThreadGroup will inherit the
- * same logger as the parent's logger.
+ * Tests for ensuring new threads spawned without an explicit ThreadGroup will inherit the same
+ * logger as the parent's logger.
*/
- public void testThreadedLogging() {
+ public void testThreadedLogging() throws Exception {
final String testMessage = "Another test message!";
final ILeveledLogOutput mockLogger = EasyMock.createMock(ILeveledLogOutput.class);
@@ -129,11 +129,9 @@
secondThread.start();
try {
secondThread.join(); // threaded, but force serialization for testing
- }
- catch (InterruptedException ie) {
- fail("Thread was unexpectedly interrupted.");
- }
- finally {
+ } catch (InterruptedException ie) {
+ throw new RuntimeException(ie);
+ } finally {
mLogRegistry.unregisterLogger();
}
}
@@ -151,12 +149,6 @@
ThreadGroup tg = new ThreadGroup("TestThreadGroup");
Thread firstThread = new Thread(tg, new FirstThread());
firstThread.start();
-
- try {
- firstThread.join(); // threaded, but force serialization for testing
- }
- catch (InterruptedException ie) {
- fail("Thread was unexpectedly interrupted.");
- }
+ firstThread.join(); // threaded, but force serialization for testing
}
}
diff --git a/tests/src/com/android/tradefed/log/TerribleFailureEmailHandlerTest.java b/tests/src/com/android/tradefed/log/TerribleFailureEmailHandlerTest.java
index 777e498..5d74abc 100644
--- a/tests/src/com/android/tradefed/log/TerribleFailureEmailHandlerTest.java
+++ b/tests/src/com/android/tradefed/log/TerribleFailureEmailHandlerTest.java
@@ -67,15 +67,10 @@
}
/**
- * Test that onTerribleFailure catches IllegalArgumentException when Mailer
- * state is incorrect
+ * Test that onTerribleFailure catches IllegalArgumentException when Mailer state is incorrect
*/
- public void testOnTerribleFailure_catchesIllegalArgumentException() {
- try {
- mMockEmail.send(EasyMock.<Message> anyObject());
- } catch (IOException e) {
- fail("IOException escaped the method under test - should never happen");
- }
+ public void testOnTerribleFailure_catchesIllegalArgumentException() throws IOException {
+ mMockEmail.send(EasyMock.<Message>anyObject());
EasyMock.expectLastCall().andThrow(new IllegalArgumentException("Mailer state illegal"));
EasyMock.replay(mMockEmail);
@@ -84,15 +79,9 @@
assertFalse(retValue);
}
- /**
- * Test that onTerribleFailure catches IOException
- */
- public void testOnTerribleFailure_catchesIOException() {
- try {
- mMockEmail.send(EasyMock.<Message> anyObject());
- } catch (IOException e) {
- fail("IOException escaped the method under test - should never happen");
- }
+ /** Test that onTerribleFailure catches IOException */
+ public void testOnTerribleFailure_catchesIOException() throws IOException {
+ mMockEmail.send(EasyMock.<Message>anyObject());
EasyMock.expectLastCall().andThrow(new IOException("Mailer had an IO Exception"));
EasyMock.replay(mMockEmail);
diff --git a/tests/src/com/android/tradefed/result/FailureDescriptionTest.java b/tests/src/com/android/tradefed/result/FailureDescriptionTest.java
new file mode 100644
index 0000000..da94866
--- /dev/null
+++ b/tests/src/com/android/tradefed/result/FailureDescriptionTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 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.result;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import com.android.tradefed.result.proto.TestRecordProto.FailureStatus;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link FailureDescription}. */
+@RunWith(JUnit4.class)
+public class FailureDescriptionTest {
+
+ private FailureDescription mFailureDescription;
+
+ @Test
+ public void testCreation() {
+ mFailureDescription = FailureDescription.create("error message");
+ assertNull(mFailureDescription.getFailureStatus());
+ assertEquals("error message", mFailureDescription.toString());
+ mFailureDescription.setFailureStatus(FailureStatus.TEST_FAILURE);
+ assertEquals(FailureStatus.TEST_FAILURE, mFailureDescription.getFailureStatus());
+ }
+}
diff --git a/tests/src/com/android/tradefed/result/MultiFailureDescriptionTest.java b/tests/src/com/android/tradefed/result/MultiFailureDescriptionTest.java
new file mode 100644
index 0000000..3b86019
--- /dev/null
+++ b/tests/src/com/android/tradefed/result/MultiFailureDescriptionTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 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.result;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link MultiFailureDescription}. */
+@RunWith(JUnit4.class)
+public class MultiFailureDescriptionTest {
+
+ private MultiFailureDescription mMultiFailureDesc;
+
+ @Test
+ public void testCreation() {
+ FailureDescription failure1 = FailureDescription.create("error message 1");
+ FailureDescription failure2 = FailureDescription.create("error message 2");
+ mMultiFailureDesc = new MultiFailureDescription(failure1, failure2);
+ assertEquals(2, mMultiFailureDesc.getFailures().size());
+ assertEquals(
+ "There were 2 failures:\n" + " error message 1\n" + " error message 2",
+ mMultiFailureDesc.toString());
+ }
+}
diff --git a/tests/src/com/android/tradefed/targetprep/InstrumentationPreparerTest.java b/tests/src/com/android/tradefed/targetprep/InstrumentationPreparerTest.java
index ac6b032..7c05067 100644
--- a/tests/src/com/android/tradefed/targetprep/InstrumentationPreparerTest.java
+++ b/tests/src/com/android/tradefed/targetprep/InstrumentationPreparerTest.java
@@ -99,7 +99,7 @@
public void run(TestInformation testInfo, ITestInvocationListener listener) {
listener.testRunStarted(packageName, 1);
listener.testStarted(test);
- listener.testFailed(test, null);
+ listener.testFailed(test, "error");
listener.testEnded(test, new HashMap<String, Metric>());
listener.testRunEnded(0, new HashMap<String, Metric>());
}
diff --git a/tests/src/com/android/tradefed/testtype/GoogleBenchmarkTestTest.java b/tests/src/com/android/tradefed/testtype/GoogleBenchmarkTestTest.java
index 58788c9..9fbfa13 100644
--- a/tests/src/com/android/tradefed/testtype/GoogleBenchmarkTestTest.java
+++ b/tests/src/com/android/tradefed/testtype/GoogleBenchmarkTestTest.java
@@ -267,7 +267,7 @@
"%s/test1 --benchmark_list_tests=true", nativeTestPath)))
.andReturn("method1\nmethod2\nmethod3");
mMockInvocationListener.testRunStarted(test1, 3);
- mMockInvocationListener.testRunFailed(EasyMock.anyObject());
+ mMockInvocationListener.testRunFailed((String) EasyMock.anyObject());
// Even with exception testrunEnded is expected.
mMockInvocationListener.testRunEnded(
EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
diff --git a/tests/src/com/android/tradefed/testtype/HostTestTest.java b/tests/src/com/android/tradefed/testtype/HostTestTest.java
index 544991b..c119c26 100644
--- a/tests/src/com/android/tradefed/testtype/HostTestTest.java
+++ b/tests/src/com/android/tradefed/testtype/HostTestTest.java
@@ -1323,7 +1323,7 @@
EasyMock.eq(test1),
EasyMock.contains("MultipleFailureException: There were 2 errors:"));
mListener.testEnded(EasyMock.eq(test1), (HashMap<String, Metric>) EasyMock.anyObject());
- mListener.testRunFailed(EasyMock.anyObject());
+ mListener.testRunFailed((String) EasyMock.anyObject());
mListener.testRunEnded(EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
EasyMock.replay(mListener);
try {
@@ -2186,7 +2186,7 @@
mListener.testRunStarted(EasyMock.anyObject(), EasyMock.eq(1));
TestDescription tid = new TestDescription(JUnit4FailedBefore.class.getName(), "test1");
mListener.testStarted(EasyMock.eq(tid));
- mListener.testFailed(EasyMock.eq(tid), EasyMock.anyObject());
+ mListener.testFailed(EasyMock.eq(tid), (String) EasyMock.anyObject());
mListener.testEnded(EasyMock.eq(tid), (HashMap<String, Metric>) EasyMock.anyObject());
mListener.testRunEnded(EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
diff --git a/tests/src/com/android/tradefed/testtype/InstrumentationFileTestTest.java b/tests/src/com/android/tradefed/testtype/InstrumentationFileTestTest.java
index a44cf0a..09c5ef4 100644
--- a/tests/src/com/android/tradefed/testtype/InstrumentationFileTestTest.java
+++ b/tests/src/com/android/tradefed/testtype/InstrumentationFileTestTest.java
@@ -19,7 +19,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
@@ -673,7 +672,7 @@
}
} catch (IOException e) {
// fail if the file is corrupt in any way
- fail("failed reading test file");
+ throw new RuntimeException(e);
}
}
diff --git a/tests/src/com/android/tradefed/testtype/NoisyDryRunTestTest.java b/tests/src/com/android/tradefed/testtype/NoisyDryRunTestTest.java
index a277317..2c3d663 100644
--- a/tests/src/com/android/tradefed/testtype/NoisyDryRunTestTest.java
+++ b/tests/src/com/android/tradefed/testtype/NoisyDryRunTestTest.java
@@ -141,7 +141,7 @@
mMockListener.testRunStarted("com.android.tradefed.testtype.NoisyDryRunTest_parseFile", 1);
mMockListener.testStarted(anyObject());
mMockListener.testEnded(anyObject(), EasyMock.<HashMap<String, Metric>>anyObject());
- mMockListener.testFailed(anyObject(), anyObject());
+ mMockListener.testFailed(anyObject(), (String) anyObject());
mMockListener.testRunEnded(EasyMock.eq(0l), EasyMock.<HashMap<String, Metric>>anyObject());
replayMocks();
@@ -166,7 +166,7 @@
mMockListener.testStarted(anyObject());
mMockListener.testEnded(anyObject(), EasyMock.<HashMap<String, Metric>>anyObject());
mMockListener.testStarted(anyObject());
- mMockListener.testFailed(anyObject(), anyObject());
+ mMockListener.testFailed(anyObject(), (String) anyObject());
mMockListener.testEnded(anyObject(), EasyMock.<HashMap<String, Metric>>anyObject());
mMockListener.testRunEnded(EasyMock.eq(0l), EasyMock.<HashMap<String, Metric>>anyObject());
replayMocks();
diff --git a/tests/src/com/android/tradefed/testtype/PythonUnitTestResultParserTest.java b/tests/src/com/android/tradefed/testtype/PythonUnitTestResultParserTest.java
index 366f75c..a8f4299 100644
--- a/tests/src/com/android/tradefed/testtype/PythonUnitTestResultParserTest.java
+++ b/tests/src/com/android/tradefed/testtype/PythonUnitTestResultParserTest.java
@@ -497,16 +497,16 @@
mMockListener.testFailed(
EasyMock.eq(new TestDescription("__main__.DisconnectionTest", "test_disconnect")),
- EasyMock.anyObject());
+ (String) EasyMock.anyObject());
mMockListener.testFailed(
EasyMock.eq(new TestDescription("__main__.EmulatorTest", "test_emulator_connect")),
- EasyMock.anyObject());
+ (String) EasyMock.anyObject());
mMockListener.testIgnored(
EasyMock.eq(new TestDescription("__main__.PowerTest", "test_resume_usb_kick")));
// Multi-line error
mMockListener.testFailed(
EasyMock.eq(new TestDescription("__main__.ServerTest", "test_handle_inheritance")),
- EasyMock.anyObject());
+ (String) EasyMock.anyObject());
mMockListener.testRunEnded(10314, new HashMap<String, Metric>());
replay(mMockListener);
@@ -550,7 +550,7 @@
mMockListener.testFailed(
EasyMock.eq(new TestDescription("__main__.ConnectionTest", "test_reconnect")),
- EasyMock.anyObject());
+ (String) EasyMock.anyObject());
mMockListener.testIgnored(
EasyMock.eq(new TestDescription("__main__.PowerTest", "test_resume_usb_kick")));
diff --git a/tests/src/com/android/tradefed/testtype/TfTestLauncherTest.java b/tests/src/com/android/tradefed/testtype/TfTestLauncherTest.java
index 8c1bad4..3c2ccb6 100644
--- a/tests/src/com/android/tradefed/testtype/TfTestLauncherTest.java
+++ b/tests/src/com/android/tradefed/testtype/TfTestLauncherTest.java
@@ -236,6 +236,9 @@
public void testRunCoverage() throws Exception {
OptionSetter setter = new OptionSetter(mTfTestLauncher);
setter.setOptionValue("jacoco-code-coverage", "true");
+ setter.setOptionValue("include-coverage", "com.android.tradefed*");
+ setter.setOptionValue("include-coverage", "com.google.android.tradefed*");
+ setter.setOptionValue("exclude-coverage", "com.test*");
EasyMock.expect(mMockBuildInfo.getRootDir()).andReturn(new File(""));
EasyMock.expect(mMockBuildInfo.getTestTag()).andReturn(TEST_TAG);
EasyMock.expect(mMockBuildInfo.getBuildBranch()).andReturn(BUILD_BRANCH).times(2);
@@ -253,6 +256,13 @@
mTfTestLauncher.preRun();
EasyMock.verify(mMockBuildInfo, mMockRunUtil, mMockListener);
assertTrue(mTfTestLauncher.mCmdArgs.get(2).startsWith("-javaagent:"));
+ assertTrue(
+ mTfTestLauncher
+ .mCmdArgs
+ .get(2)
+ .contains(
+ "includes=com.android.tradefed*:com.google.android.tradefed*,"
+ + "excludes=com.test*"));
} finally {
FileUtil.recursiveDelete(mTfTestLauncher.mTmpDir);
mTfTestLauncher.cleanTmpFile();
diff --git a/tests/src/com/android/tradefed/testtype/binary/ExecutableHostTestTest.java b/tests/src/com/android/tradefed/testtype/binary/ExecutableHostTestTest.java
index e973b80..96e99cc 100644
--- a/tests/src/com/android/tradefed/testtype/binary/ExecutableHostTestTest.java
+++ b/tests/src/com/android/tradefed/testtype/binary/ExecutableHostTestTest.java
@@ -120,8 +120,8 @@
mExecutableTest.run(mTestInfo, mMockListener);
verify(mMockListener, Mockito.times(1)).testRunStarted(eq(tmpBinary.getName()), eq(1));
- verify(mMockListener, Mockito.times(0)).testRunFailed(any());
- verify(mMockListener, Mockito.times(0)).testFailed(any(), any());
+ verify(mMockListener, Mockito.times(0)).testRunFailed((String) any());
+ verify(mMockListener, Mockito.times(0)).testFailed(any(), (String) any());
verify(mMockListener, Mockito.times(1))
.testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
} finally {
@@ -154,8 +154,8 @@
mExecutableTest.run(mTestInfo, mMockListener);
verify(mMockListener, Mockito.times(1)).testRunStarted(eq(tmpBinary.getName()), eq(1));
- verify(mMockListener, Mockito.times(0)).testRunFailed(any());
- verify(mMockListener, Mockito.times(0)).testFailed(any(), any());
+ verify(mMockListener, Mockito.times(0)).testRunFailed((String) any());
+ verify(mMockListener, Mockito.times(0)).testFailed(any(), (String) any());
verify(mMockListener, Mockito.times(1))
.testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
} finally {
@@ -194,7 +194,7 @@
String.format(
"Device became unavailable after %s.",
tmpBinary.getAbsolutePath())));
- verify(mMockListener, Mockito.times(0)).testFailed(any(), any());
+ verify(mMockListener, Mockito.times(0)).testFailed(any(), (String) any());
verify(mMockListener, Mockito.times(1))
.testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
} finally {
@@ -226,8 +226,8 @@
mExecutableTest.run(mTestInfo, mMockListener);
verify(mMockListener, Mockito.times(1)).testRunStarted(eq(tmpBinary.getName()), eq(1));
- verify(mMockListener, Mockito.times(0)).testRunFailed(any());
- verify(mMockListener, Mockito.times(0)).testFailed(any(), any());
+ verify(mMockListener, Mockito.times(0)).testRunFailed((String) any());
+ verify(mMockListener, Mockito.times(0)).testFailed(any(), (String) any());
verify(mMockListener, Mockito.times(1))
.testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
} finally {
@@ -300,7 +300,7 @@
mExecutableTest.run(mTestInfo, mMockListener);
verify(mMockListener, Mockito.times(1)).testRunStarted(eq(tmpBinary.getName()), eq(1));
- verify(mMockListener, Mockito.times(0)).testRunFailed(any());
+ verify(mMockListener, Mockito.times(0)).testRunFailed((String) any());
verify(mMockListener, Mockito.times(1)).testFailed(any(), eq("stdout\nExit Code: 5"));
verify(mMockListener, Mockito.times(1))
.testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
diff --git a/tests/src/com/android/tradefed/testtype/junit4/LongevityHostRunnerTest.java b/tests/src/com/android/tradefed/testtype/junit4/LongevityHostRunnerTest.java
index 07c13b0..37b4b74 100644
--- a/tests/src/com/android/tradefed/testtype/junit4/LongevityHostRunnerTest.java
+++ b/tests/src/com/android/tradefed/testtype/junit4/LongevityHostRunnerTest.java
@@ -226,7 +226,7 @@
mHostTest.publicSetClassName(PassingLongevitySuite.class.getName());
mHostTest.run(mTestInfo, mMockListener);
// Verify nothing failed, but something passed.
- verify(mMockListener, never()).testFailed(any(), any());
+ verify(mMockListener, never()).testFailed(any(), (String) any());
verify(mMockListener).testEnded(any(), Mockito.<HashMap<String, Metric>>any());
}
diff --git a/tests/src/com/android/tradefed/testtype/python/PythonBinaryHostTestTest.java b/tests/src/com/android/tradefed/testtype/python/PythonBinaryHostTestTest.java
index b285530..5fd5c5f 100644
--- a/tests/src/com/android/tradefed/testtype/python/PythonBinaryHostTestTest.java
+++ b/tests/src/com/android/tradefed/testtype/python/PythonBinaryHostTestTest.java
@@ -188,7 +188,7 @@
EasyMock.anyObject());
// Report a failure if we cannot parse the logs
mMockListener.testRunStarted(binary.getName(), 0);
- mMockListener.testRunFailed(EasyMock.anyObject());
+ mMockListener.testRunFailed((String) EasyMock.anyObject());
mMockListener.testRunEnded(
EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
diff --git a/tests/src/com/android/tradefed/testtype/rust/RustBinaryHostTestTest.java b/tests/src/com/android/tradefed/testtype/rust/RustBinaryHostTestTest.java
index 2fbef8e..09831e7 100644
--- a/tests/src/com/android/tradefed/testtype/rust/RustBinaryHostTestTest.java
+++ b/tests/src/com/android/tradefed/testtype/rust/RustBinaryHostTestTest.java
@@ -166,7 +166,7 @@
EasyMock.anyObject());
// Report a failure if we cannot parse the logs and the logs is not empty.
mMockListener.testRunStarted(binary.getName(), 0);
- mMockListener.testRunFailed(EasyMock.anyObject());
+ mMockListener.testRunFailed((String) EasyMock.anyObject());
mMockListener.testRunEnded(
EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
diff --git a/tests/src/com/android/tradefed/testtype/rust/RustTestResultParserTest.java b/tests/src/com/android/tradefed/testtype/rust/RustTestResultParserTest.java
index 9e06ae9..9a261c0 100644
--- a/tests/src/com/android/tradefed/testtype/rust/RustTestResultParserTest.java
+++ b/tests/src/com/android/tradefed/testtype/rust/RustTestResultParserTest.java
@@ -134,9 +134,10 @@
EasyMock.anyObject(), EasyMock.<HashMap<String, Metric>>anyObject());
}
mMockListener.testFailed(
- EasyMock.eq(new TestDescription("test", "idents")), EasyMock.anyObject());
+ EasyMock.eq(new TestDescription("test", "idents")), (String) EasyMock.anyObject());
mMockListener.testFailed(
- EasyMock.eq(new TestDescription("test", "literal_string")), EasyMock.anyObject());
+ EasyMock.eq(new TestDescription("test", "literal_string")),
+ (String) EasyMock.anyObject());
mMockListener.testRunEnded(0, new HashMap<String, Metric>());
replay(mMockListener);
mParser.processNewLines(contents);
diff --git a/tests/src/com/android/tradefed/testtype/suite/ModuleDefinitionTest.java b/tests/src/com/android/tradefed/testtype/suite/ModuleDefinitionTest.java
index bc6e8fc..4273924 100644
--- a/tests/src/com/android/tradefed/testtype/suite/ModuleDefinitionTest.java
+++ b/tests/src/com/android/tradefed/testtype/suite/ModuleDefinitionTest.java
@@ -456,7 +456,7 @@
EasyMock.anyLong(),
EasyMock.<HashMap<String, Metric>>anyObject());
}
- mMockListener.testFailed(EasyMock.anyObject(), EasyMock.anyObject());
+ mMockListener.testFailed(EasyMock.anyObject(), (String) EasyMock.anyObject());
String aggError =
"unresponsive\n====Next Error====\n"
+ "Module fakeName only ran 1 out of 4 expected tests.\n====Next "
@@ -877,8 +877,8 @@
EasyMock.anyLong(),
EasyMock.<HashMap<String, Metric>>anyObject());
}
- mMockListener.testFailed(EasyMock.anyObject(), EasyMock.anyObject());
- mMockListener.testRunFailed(EasyMock.anyObject());
+ mMockListener.testFailed(EasyMock.anyObject(), (String) EasyMock.anyObject());
+ mMockListener.testRunFailed((String) EasyMock.anyObject());
mMockListener.testRunEnded(
EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
// Recovery is disabled during tearDown
@@ -939,8 +939,8 @@
EasyMock.anyLong(),
EasyMock.<HashMap<String, Metric>>anyObject());
}
- mMockListener.testFailed(EasyMock.anyObject(), EasyMock.anyObject());
- mMockListener.testRunFailed(EasyMock.anyObject());
+ mMockListener.testFailed(EasyMock.anyObject(), (String) EasyMock.anyObject());
+ mMockListener.testRunFailed((String) EasyMock.anyObject());
mMockListener.testRunEnded(
EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
@@ -1283,7 +1283,7 @@
EasyMock.anyLong(),
EasyMock.<HashMap<String, Metric>>anyObject());
}
- mMockListener.testFailed(EasyMock.anyObject(), EasyMock.anyObject());
+ mMockListener.testFailed(EasyMock.anyObject(), (String) EasyMock.anyObject());
mMockListener.testRunFailed(
"unresponsive"
+ TestRunResult.ERROR_DIVIDER
@@ -1531,7 +1531,7 @@
EasyMock.<HashMap<String, Metric>>anyObject());
TestDescription testFail0 = new TestDescription(runName + "0class", "fail0");
mMockListener.testStarted(EasyMock.eq(testFail0), EasyMock.anyLong());
- mMockListener.testFailed(EasyMock.eq(testFail0), EasyMock.anyObject());
+ mMockListener.testFailed(EasyMock.eq(testFail0), (String) EasyMock.anyObject());
mMockListener.testEnded(
EasyMock.eq(testFail0),
EasyMock.anyLong(),
@@ -1552,7 +1552,7 @@
EasyMock.<HashMap<String, Metric>>anyObject());
TestDescription testFail0_1 = new TestDescription(runName + "1class", "fail0");
mMockListener.testStarted(EasyMock.eq(testFail0_1), EasyMock.anyLong());
- mMockListener.testFailed(EasyMock.eq(testFail0_1), EasyMock.anyObject());
+ mMockListener.testFailed(EasyMock.eq(testFail0_1), (String) EasyMock.anyObject());
mMockListener.testEnded(
EasyMock.eq(testFail0_1),
EasyMock.anyLong(),
@@ -1637,7 +1637,7 @@
}
TestDescription testFail0 = new TestDescription(runName + "0class", "fail0");
mMockListener.testStarted(EasyMock.eq(testFail0), EasyMock.anyLong());
- mMockListener.testFailed(EasyMock.eq(testFail0), EasyMock.anyObject());
+ mMockListener.testFailed(EasyMock.eq(testFail0), (String) EasyMock.anyObject());
mMockListener.testEnded(
EasyMock.eq(testFail0),
EasyMock.anyLong(),
@@ -1662,7 +1662,7 @@
}
TestDescription testFail0_1 = new TestDescription(runName + "1class", "fail0");
mMockListener.testStarted(EasyMock.eq(testFail0_1), EasyMock.anyLong());
- mMockListener.testFailed(EasyMock.eq(testFail0_1), EasyMock.anyObject());
+ mMockListener.testFailed(EasyMock.eq(testFail0_1), (String) EasyMock.anyObject());
mMockListener.testEnded(
EasyMock.eq(testFail0_1),
EasyMock.anyLong(),
diff --git a/tests/src/com/android/tradefed/testtype/suite/SuiteModuleLoaderTest.java b/tests/src/com/android/tradefed/testtype/suite/SuiteModuleLoaderTest.java
index 6a75933..6f4fe50 100644
--- a/tests/src/com/android/tradefed/testtype/suite/SuiteModuleLoaderTest.java
+++ b/tests/src/com/android/tradefed/testtype/suite/SuiteModuleLoaderTest.java
@@ -26,6 +26,7 @@
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.invoker.TestInformation;
import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.targetprep.BaseTargetPreparer;
import com.android.tradefed.testtype.Abi;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IRemoteTest;
@@ -54,6 +55,7 @@
private static final String TEST_CONFIG =
"<configuration description=\"Runs a stub tests part of some suite\">\n"
+ + " <target_preparer class=\"com.android.tradefed.testtype.suite.SuiteModuleLoaderTest$PreparerInject\" />\n"
+ " <test class=\"com.android.tradefed.testtype.suite.SuiteModuleLoaderTest"
+ "$TestInject\" />\n"
+ "</configuration>";
@@ -96,6 +98,12 @@
FileUtil.writeToFile(TEST_INSTANT_CONFIG, module);
}
+ @OptionClass(alias = "preparer-inject")
+ public static class PreparerInject extends BaseTargetPreparer {
+ @Option(name = "preparer-string")
+ public String preparer = null;
+ }
+
@OptionClass(alias = "test-inject")
public static class TestInject implements IRemoteTest {
@Option(name = "simple-string")
@@ -168,6 +176,11 @@
@Test
public void testInjectConfigOptions_testArgs() throws Exception {
List<String> testArgs = new ArrayList<>();
+ // Value for ITargetPreparer
+ testArgs.add(
+ "com.android.tradefed.testtype.suite.SuiteModuleLoaderTest$PreparerInject:"
+ + "preparer-string:preparer");
+ // Values for IRemoteTest
testArgs.add(
"com.android.tradefed.testtype.suite.SuiteModuleLoaderTest$TestInject:"
+ "simple-string:value1");
@@ -210,6 +223,9 @@
assertNotNull(res.get("armeabi-v7a module1"));
IConfiguration config = res.get("armeabi-v7a module1");
+ PreparerInject preparer = (PreparerInject) config.getTargetPreparers().get(0);
+ assertEquals("preparer", preparer.preparer);
+
TestInject checker = (TestInject) config.getTests().get(0);
assertEquals("value1", checker.test);
assertEquals("", checker.testEmpty);
diff --git a/tests/src/com/android/tradefed/testtype/suite/retry/ResultsPlayerTest.java b/tests/src/com/android/tradefed/testtype/suite/retry/ResultsPlayerTest.java
index 06c8b32..eda01e0 100644
--- a/tests/src/com/android/tradefed/testtype/suite/retry/ResultsPlayerTest.java
+++ b/tests/src/com/android/tradefed/testtype/suite/retry/ResultsPlayerTest.java
@@ -24,6 +24,7 @@
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.invoker.InvocationContext;
+import com.android.tradefed.invoker.TestInformation;
import com.android.tradefed.log.ILeveledLogOutput;
import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
import com.android.tradefed.result.ITestInvocationListener;
@@ -47,6 +48,7 @@
private ResultsPlayer mPlayer;
private ITestInvocationListener mMockListener;
private IInvocationContext mContext;
+ private TestInformation mTestInfo;
private ITestDevice mMockDevice;
private IDevice mMockIDevice;
private IConfiguration mMockConfig;
@@ -64,9 +66,9 @@
EasyMock.expect(mMockLogOutput.getLogLevel()).andReturn(LogLevel.VERBOSE);
mMockLogOutput.setLogLevel(LogLevel.WARN);
mMockLogOutput.setLogLevel(LogLevel.VERBOSE);
+ mTestInfo = TestInformation.newBuilder().setInvocationContext(mContext).build();
mPlayer = new ResultsPlayer();
- mPlayer.setInvocationContext(mContext);
mPlayer.setConfiguration(mMockConfig);
mContext.addAllocatedDevice(ConfigurationDef.DEFAULT_DEVICE_NAME, mMockDevice);
@@ -96,7 +98,7 @@
mMockListener.testRunEnded(500L, new HashMap<String, Metric>());
EasyMock.replay(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
- mPlayer.run(mMockListener);
+ mPlayer.run(mTestInfo, mMockListener);
EasyMock.verify(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
}
@@ -142,7 +144,7 @@
mMockListener.testModuleEnded();
EasyMock.replay(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
- mPlayer.run(mMockListener);
+ mPlayer.run(mTestInfo, mMockListener);
EasyMock.verify(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
}
@@ -169,7 +171,7 @@
mMockListener.testRunEnded(500L, new HashMap<String, Metric>());
EasyMock.replay(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
- mPlayer.run(mMockListener);
+ mPlayer.run(mTestInfo, mMockListener);
EasyMock.verify(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
}
@@ -212,7 +214,7 @@
mMockListener.testRunEnded(500L, new HashMap<String, Metric>());
EasyMock.replay(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
- mPlayer.run(mMockListener);
+ mPlayer.run(mTestInfo, mMockListener);
EasyMock.verify(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
}
diff --git a/tests/src/com/android/tradefed/testtype/suite/retry/RetryReschedulerTest.java b/tests/src/com/android/tradefed/testtype/suite/retry/RetryReschedulerTest.java
index a7709aa..245b2ed 100644
--- a/tests/src/com/android/tradefed/testtype/suite/retry/RetryReschedulerTest.java
+++ b/tests/src/com/android/tradefed/testtype/suite/retry/RetryReschedulerTest.java
@@ -124,7 +124,7 @@
mRescheduledConfiguration,
mMockCommandOptions,
mMockRequirements);
- mTest.run(null);
+ mTest.run(null, null);
EasyMock.verify(
mMockRescheduler,
mMockLoader,
@@ -169,7 +169,7 @@
mRescheduledConfiguration,
mMockCommandOptions,
mMockRequirements);
- mTest.run(null);
+ mTest.run(null, null);
EasyMock.verify(
mMockRescheduler,
mMockLoader,
@@ -206,7 +206,7 @@
mMockFactory,
mRescheduledConfiguration,
mMockCommandOptions);
- mTest.run(null);
+ mTest.run(null, null);
EasyMock.verify(
mMockRescheduler,
mMockLoader,
@@ -245,7 +245,7 @@
mMockFactory,
mRescheduledConfiguration,
mMockCommandOptions);
- mTest.run(null);
+ mTest.run(null, null);
EasyMock.verify(
mMockRescheduler,
mMockLoader,
@@ -284,7 +284,7 @@
mMockFactory,
mRescheduledConfiguration,
mMockCommandOptions);
- mTest.run(null);
+ mTest.run(null, null);
EasyMock.verify(
mMockRescheduler,
mMockLoader,
@@ -329,7 +329,7 @@
mMockFactory,
mRescheduledConfiguration,
mMockCommandOptions);
- mTest.run(null);
+ mTest.run(null, null);
EasyMock.verify(
mMockRescheduler,
mMockLoader,
@@ -368,7 +368,7 @@
mMockFactory,
mRescheduledConfiguration,
mMockCommandOptions);
- mTest.run(null);
+ mTest.run(null, null);
EasyMock.verify(
mMockRescheduler,
mMockLoader,
@@ -411,7 +411,7 @@
mMockFactory,
mRescheduledConfiguration,
mMockCommandOptions);
- mTest.run(null);
+ mTest.run(null, null);
EasyMock.verify(
mMockRescheduler,
mMockLoader,
@@ -452,7 +452,7 @@
mMockFactory,
mRescheduledConfiguration,
mMockCommandOptions);
- mTest.run(null);
+ mTest.run(null, null);
EasyMock.verify(
mMockRescheduler,
mMockLoader,
@@ -490,7 +490,7 @@
mMockFactory,
mRescheduledConfiguration,
mMockCommandOptions);
- mTest.run(null);
+ mTest.run(null, null);
EasyMock.verify(
mMockRescheduler,
mMockLoader,
@@ -539,7 +539,7 @@
mMockFactory,
mRescheduledConfiguration,
mMockCommandOptions);
- mTest.run(null);
+ mTest.run(null, null);
EasyMock.verify(
mMockRescheduler,
mMockLoader,
diff --git a/tests/src/com/android/tradefed/util/AaptParserTest.java b/tests/src/com/android/tradefed/util/AaptParserTest.java
index b754df1..f25871c 100644
--- a/tests/src/com/android/tradefed/util/AaptParserTest.java
+++ b/tests/src/com/android/tradefed/util/AaptParserTest.java
@@ -139,4 +139,117 @@
assertEquals("arm64-v8a", p.getNativeCode().get(0));
assertEquals("armeabi-v7a", p.getNativeCode().get(1));
}
+
+ public void testParseXmlTree_withRequestLegacyFlagTrue() {
+ AaptParser p = new AaptParser();
+ p.parseXmlTree(
+ "N: android=http://schemas.android.com/apk/res/android\n"
+ + " E: manifest (line=2)\n"
+ + " A: android:versionCode(0x0101021b)=(type 0x10)0x1d\n"
+ + " A: android:versionName(0x0101021c)=\"R\" (Raw: \"R\")\n"
+ + " A: android:compileSdkVersion(0x01010572)=(type 0x10)0x1d\n"
+ + " A: android:compileSdkVersionCodename(0x01010573)=\"R\" (Raw: "
+ + "\"R\")\n"
+ + " A: package=\"com.android.foo\" (Raw: \"com.android.foo\")\n"
+ + " A: platformBuildVersionCode=(type 0x10)0x1d\n"
+ + " A: platformBuildVersionName=\"R\" (Raw: \"R\")\n"
+ + " E: uses-sdk (line=5)\n"
+ + " A: android:minSdkVersion(0x0101020c)=(type 0x10)0x1c\n"
+ + " A: android:targetSdkVersion(0x01010270)=\"R\" (Raw: \"R\")\n"
+ + " E: application (line=12)\n"
+ + " A: android:targetSdkVersion(0x01010270)=(type 0x10)0x1e\n"
+ + " A: android:supportsRtl(0x010103af)=(type 0x12)0xffffffff\n"
+ + " A: android:extractNativeLibs(0x010104ea)=(type 0x12)0xffffffff\n"
+ + " A: android:appComponentFactory(0x0101057a)=\"androidx.core.app"
+ + ".CoreComponentFactory\" (Raw: \"androidx.core.app"
+ + ".CoreComponentFactory\")\n"
+ + " A: android:requestLegacyExternalStorage(0x01010603)=(type 0x12)"
+ + "0xffffffff\n");
+ assertTrue(p.isRequestingLegacyStorage());
+ }
+
+ public void testParseXmlTree_withRequestLegacyFlagFalse() {
+ AaptParser p = new AaptParser();
+ p.parseXmlTree(
+ "N: android=http://schemas.android.com/apk/res/android\n"
+ + " E: manifest (line=2)\n"
+ + " A: android:versionCode(0x0101021b)=(type 0x10)0x1d\n"
+ + " A: android:versionName(0x0101021c)=\"R\" (Raw: \"R\")\n"
+ + " A: android:compileSdkVersion(0x01010572)=(type 0x10)0x1d\n"
+ + " A: android:compileSdkVersionCodename(0x01010573)=\"R\" (Raw: "
+ + "\"R\")\n"
+ + " A: package=\"com.android.foo\" (Raw: \"com.android.foo\")\n"
+ + " A: platformBuildVersionCode=(type 0x10)0x1d\n"
+ + " A: platformBuildVersionName=\"R\" (Raw: \"R\")\n"
+ + " E: uses-sdk (line=5)\n"
+ + " A: android:minSdkVersion(0x0101020c)=(type 0x10)0x1c\n"
+ + " A: android:targetSdkVersion(0x01010270)=\"R\" (Raw: \"R\")\n"
+ + " E: application (line=12)\n"
+ + " A: android:targetSdkVersion(0x01010270)=(type 0x10)0x1e\n"
+ + " A: android:supportsRtl(0x010103af)=(type 0x12)0xffffffff\n"
+ + " A: android:extractNativeLibs(0x010104ea)=(type 0x12)0xffffffff\n"
+ + " A: android:appComponentFactory(0x0101057a)=\"androidx.core.app"
+ + ".CoreComponentFactory\" (Raw: \"androidx.core.app"
+ + ".CoreComponentFactory\")\n"
+ + " A: android:requestLegacyExternalStorage(0x01010603)=(type 0x12)"
+ + "0x0\n");
+ assertFalse(p.isRequestingLegacyStorage());
+ }
+
+ public void testParseXmlTree_withoutRequestLegacyFlag() {
+ AaptParser p = new AaptParser();
+ p.parseXmlTree(
+ "N: android=http://schemas.android.com/apk/res/android\n"
+ + " E: manifest (line=2)\n"
+ + " A: android:versionCode(0x0101021b)=(type 0x10)0x1d\n"
+ + " A: android:versionName(0x0101021c)=\"R\" (Raw: \"R\")\n"
+ + " A: android:compileSdkVersion(0x01010572)=(type 0x10)0x1d\n"
+ + " A: android:compileSdkVersionCodename(0x01010573)=\"R\" (Raw: "
+ + "\"R\")\n"
+ + " A: package=\"com.android.foo\" (Raw: \"com.android.foo\")\n"
+ + " A: platformBuildVersionCode=(type 0x10)0x1d\n"
+ + " A: platformBuildVersionName=\"R\" (Raw: \"R\")\n"
+ + " E: uses-sdk (line=5)\n"
+ + " A: android:minSdkVersion(0x0101020c)=(type 0x10)0x1c\n"
+ + " A: android:targetSdkVersion(0x01010270)=\"R\" (Raw: \"R\")\n"
+ + " E: application (line=12)\n"
+ + " A: android:targetSdkVersion(0x01010270)=(type 0x10)0x1e\n"
+ + " A: android:supportsRtl(0x010103af)=(type 0x12)0xffffffff\n"
+ + " A: android:extractNativeLibs(0x010104ea)=(type 0x12)0xffffffff\n"
+ + " A: android:appComponentFactory(0x0101057a)=\"androidx.core.app"
+ + ".CoreComponentFactory\" (Raw: \"androidx.core.app");
+ assertFalse(p.isRequestingLegacyStorage());
+ }
+
+ public void testParseTargetSdkVersion() {
+ AaptParser p = new AaptParser();
+ p.parse(
+ "package: name='com.android.foo' versionCode='13' versionName='2.3'\n"
+ + "sdkVersion:'5'\n"
+ + "targetSdkVersion:'29'\n"
+ + "application-label-fr:'Faa'\n"
+ + "uses-permission:'android.permission.INTERNET'");
+ assertEquals(29, p.getTargetSdkVersion());
+ }
+
+ public void testParseInvalidTargetSdkVersion() {
+ AaptParser p = new AaptParser();
+ p.parse(
+ "package: name='com.android.foo' versionCode='13' versionName='2.3'\n"
+ + "sdkVersion:'5'\n"
+ + "targetSdkVersion:'R'\n"
+ + "application-label-fr:'Faa'\n"
+ + "uses-permission:'android.permission.INTERNET'");
+ assertEquals(10000, p.getTargetSdkVersion());
+ }
+
+ public void testParseNoTargetSdkVersion() {
+ AaptParser p = new AaptParser();
+ p.parse(
+ "package: name='com.android.foo' versionCode='13' versionName='2.3'\n"
+ + "sdkVersion:'5'\n"
+ + "application-label-fr:'Faa'\n"
+ + "uses-permission:'android.permission.INTERNET'");
+ assertEquals(10000, p.getTargetSdkVersion());
+ }
}
diff --git a/tests/src/com/android/tradefed/util/ZipUtilTest.java b/tests/src/com/android/tradefed/util/ZipUtilTest.java
index 51dc090..e06b846 100644
--- a/tests/src/com/android/tradefed/util/ZipUtilTest.java
+++ b/tests/src/com/android/tradefed/util/ZipUtilTest.java
@@ -266,9 +266,6 @@
try (BufferedReader br = new BufferedReader(new FileReader(targetFile))) {
String line = br.readLine();
assertTrue(line.endsWith("this is a text file."));
- } catch (IOException e) {
- // fail if the file is corrupt in any way
- fail("failed reading text file");
}
// Verify file permissions - read/write - 666 rw-rw-rw-
permissions = Files.getPosixFilePermissions(targetFile.toPath());