Merge "Sort modules in the XML by name and abi"
diff --git a/.classpath b/.classpath
index 6eee727..5ed457d 100644
--- a/.classpath
+++ b/.classpath
@@ -28,5 +28,6 @@
<classpathentry kind="var" path="TRADEFED_ROOT/out/soong/.intermediates/external/jacoco/jacoco-cli/linux_glibc_common/combined/jacoco-cli.jar"/>
<classpathentry exported="true" kind="var" path="TRADEFED_ROOT/prebuilts/tools/common/google-api-services-storage/1.23.0/google-api-services-storage-v1-rev114-1.23.0.jar"/>
<classpathentry kind="var" path="TRADEFED_ROOT/out/soong/.intermediates/tools/tradefederation/core/tradefed-protos/linux_glibc_common/combined/tradefed-protos.jar"/>
+ <classpathentry kind="var" path="TRADEFED_ROOT/prebuilts/tools/common/m2/repository/com/google/code/gson/gson/2.8.0/gson-2.8.0.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/atest/test_finders/module_finder.py b/atest/test_finders/module_finder.py
index e3767e4..6c3ecd6 100644
--- a/atest/test_finders/module_finder.py
+++ b/atest/test_finders/module_finder.py
@@ -212,13 +212,12 @@
return test_config
return rel_config
- def _get_test_info_filter(self, path, methods, module_name, **kwargs):
+ def _get_test_info_filter(self, path, methods, **kwargs):
"""Get test info filter.
Args:
path: A string of the test's path.
methods: A set of method name strings.
- module_name: A string of the module name.
rel_module_dir: Optional. A string of the module dir relative to
root.
class_name: Optional. A string of the class name.
@@ -251,7 +250,6 @@
kwargs.get('class_name', '*'), methods), frozenset())])
# Path to non-module dir, treat as package.
elif (not file_name
- and not self.module_info.is_auto_gen_test_config(module_name)
and kwargs.get('rel_module_dir', None) !=
os.path.relpath(path, self.root_dir)):
dir_items = [os.path.join(path, f) for f in os.listdir(path)]
@@ -371,7 +369,7 @@
if not test_path:
return None
test_filter = self._get_test_info_filter(
- test_path, methods, module_name, class_name=class_name,
+ test_path, methods, class_name=class_name,
is_native_test=is_native_test)
tinfo = self._get_test_info(test_path, rel_config, module_name,
test_filter)
@@ -488,7 +486,7 @@
if not rel_module_dir:
return None
rel_config = os.path.join(rel_module_dir, constants.MODULE_CONFIG)
- test_filter = self._get_test_info_filter(path, methods, None,
+ test_filter = self._get_test_info_filter(path, methods,
rel_module_dir=rel_module_dir)
return self._get_test_info(path, rel_config, None, test_filter)
diff --git a/proto/summary_record.proto b/proto/summary_record.proto
deleted file mode 100644
index a3a72b7..0000000
--- a/proto/summary_record.proto
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-syntax = "proto3";
-
-import "google/protobuf/any.proto";
-import "google/protobuf/timestamp.proto";
-import "tools/tradefederation/core/proto/metric_measurement.proto";
-
-option java_package = "com.android.tradefed.result.proto";
-option java_outer_classname = "SummaryRecordProto";
-
-package android_summary_record;
-
-// A Summary of the top level information related to an invocation.
-message SummaryRecord {
-
- // The total number of expected test cases.
- int64 num_expected_tests = 1;
-
- // The total number of executed test cases.
- int64 num_total_tests = 2;
-
- // The total number of failed test cases.
- int64 num_failed_tests = 3;
-
- // The total number of failed test runs.
- int64 num_failed_runs = 4;
-
- // Extra debugging information for the invocation level, if set an invocation
- // failure occurred and this field contains the error.
- string error_message = 5;
-
- // A short summary message or link associated with the invocation.
- string summary_message = 6;
-
- // The time at which this invocation started.
- google.protobuf.Timestamp start_time = 7;
-
- // The time at which this invocation finished.
- google.protobuf.Timestamp end_time = 8;
-
- // Metadata describing the invocation that was run.
- google.protobuf.Any description = 9;
-}
\ No newline at end of file
diff --git a/remote/.classpath b/remote/.classpath
index b59b5c8..74e2efb 100644
--- a/remote/.classpath
+++ b/remote/.classpath
@@ -10,7 +10,6 @@
<classpathentry exported="true" kind="var" path="TRADEFED_ROOT/prebuilts/misc/common/sdklib/sdklib-prebuilt.jar"/>
<classpathentry exported="true" kind="var" path="TRADEFED_ROOT/prebuilts/misc/common/tools-common/tools-common-prebuilt.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/ddmlib"/>
- <classpathentry kind="var" path="TRADEFED_ROOT/out/soong/.intermediates/external/guava/guava/linux_glibc_common/combined/guava.jar"/>
<classpathentry kind="var" path="TRADEFED_ROOT/external/error_prone/error_prone/error_prone_annotations-2.3.2.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/src/com/android/tradefed/device/NativeDevice.java b/src/com/android/tradefed/device/NativeDevice.java
index 92c2c83..a1d307a 100644
--- a/src/com/android/tradefed/device/NativeDevice.java
+++ b/src/com/android/tradefed/device/NativeDevice.java
@@ -37,6 +37,7 @@
import com.android.tradefed.device.contentprovider.ContentProviderHandler;
import com.android.tradefed.host.IHostOptions;
import com.android.tradefed.log.ITestLogger;
+import com.android.tradefed.log.LogUtil;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ByteArrayInputStreamSource;
import com.android.tradefed.result.FileInputStreamSource;
@@ -222,6 +223,8 @@
/** Keep track of the last time Tradefed itself triggered a reboot. */
private long mLastTradefedRebootTime = 0L;
+ private File mExecuteShellCommandLogs = null;
+
/**
* Interface for a generic device communication attempt.
*/
@@ -713,7 +716,29 @@
CollectingOutputReceiver receiver = new CollectingOutputReceiver();
executeShellCommand(command, receiver);
String output = receiver.getOutput();
- CLog.v("%s on %s returned %s", command, getSerialNumber(), output);
+ if (mExecuteShellCommandLogs != null) {
+ // Log all output to a dedicated file as it can be very verbose.
+ String formatted =
+ LogUtil.getLogFormatString(
+ LogLevel.VERBOSE,
+ "NativeDevice",
+ String.format(
+ "%s on %s returned %s\n==== END OF OUTPUT ====\n",
+ command, getSerialNumber(), output));
+ try {
+ FileUtil.writeToFile(formatted, mExecuteShellCommandLogs, true);
+ } catch (IOException e) {
+ // Ignore the full error
+ CLog.e("Failed to log to executeShellCommand log: %s", e.getMessage());
+ }
+ }
+ if (output.length() > 80) {
+ CLog.v(
+ "%s on %s returned %s <truncated - See executeShellCommand log for full trace>",
+ command, getSerialNumber(), output.substring(0, 80));
+ } else {
+ CLog.v("%s on %s returned %s", command, getSerialNumber(), output);
+ }
return output;
}
@@ -4083,6 +4108,13 @@
// Default implementation
mContentProvider = null;
mShouldSkipContentProviderSetup = false;
+ try {
+ mExecuteShellCommandLogs =
+ FileUtil.createTempFile("TestDevice_ExecuteShellCommands", ".txt");
+ } catch (IOException e) {
+ throw new TargetSetupError(
+ "Failed to create the executeShellCommand log file.", e, getDeviceDescriptor());
+ }
}
/**
@@ -4090,6 +4122,8 @@
*/
@Override
public void postInvocationTearDown() {
+ FileUtil.deleteFile(mExecuteShellCommandLogs);
+ mExecuteShellCommandLogs = null;
// Default implementation
if (getIDevice() instanceof StubDevice) {
return;
@@ -4434,4 +4468,9 @@
void resetContentProviderSetup() {
mShouldSkipContentProviderSetup = false;
}
+
+ /** The log that contains all the {@link #executeShellCommand(String)} logs. */
+ public final File getExecuteShellCommandLog() {
+ return mExecuteShellCommandLogs;
+ }
}
diff --git a/src/com/android/tradefed/device/metric/HostStatsdMetricCollector.java b/src/com/android/tradefed/device/metric/HostStatsdMetricCollector.java
index 70ea199..4f2e029 100644
--- a/src/com/android/tradefed/device/metric/HostStatsdMetricCollector.java
+++ b/src/com/android/tradefed/device/metric/HostStatsdMetricCollector.java
@@ -16,6 +16,7 @@
package com.android.tradefed.device.metric;
import com.android.tradefed.config.Option;
+import com.android.tradefed.config.OptionClass;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
@@ -36,6 +37,7 @@
* commands. It has basic push metrics and dump report functions. It can be extended by subclasses
* to process statsd metric report based on the needs.
*/
+@OptionClass(alias = "host-statsd-collector")
public class HostStatsdMetricCollector extends BaseDeviceMetricCollector {
@Option(name = "binary-stats-config", description = "Path to the binary Statsd config file")
diff --git a/src/com/android/tradefed/invoker/RemoteInvocationExecution.java b/src/com/android/tradefed/invoker/RemoteInvocationExecution.java
index 3051db9..f615387 100644
--- a/src/com/android/tradefed/invoker/RemoteInvocationExecution.java
+++ b/src/com/android/tradefed/invoker/RemoteInvocationExecution.java
@@ -42,7 +42,6 @@
import com.android.tradefed.result.LogDataType;
import com.android.tradefed.result.proto.FileProtoResultReporter;
import com.android.tradefed.result.proto.ProtoResultParser;
-import com.android.tradefed.result.proto.SummaryProtoResultReporter;
import com.android.tradefed.targetprep.BuildError;
import com.android.tradefed.targetprep.TargetSetupError;
import com.android.tradefed.util.CommandResult;
@@ -78,7 +77,6 @@
public static final String REMOTE_USER_DIR = "/home/{$USER}/";
public static final String PROTO_RESULT_NAME = "output.pb";
- public static final String PROTO_SUMMARY_NAME = "summary-output.pb";
public static final String STDOUT_FILE = "screen-VM_tradefed-stdout.txt";
public static final String STDERR_FILE = "screen-VM_tradefed-stderr.txt";
public static final String REMOTE_CONFIG = "configuration";
@@ -524,10 +522,6 @@
FileProtoResultReporter protoReporter = new FileProtoResultReporter();
protoReporter.setFileOutput(new File(resultDirPath + PROTO_RESULT_NAME));
reporters.add(protoReporter);
- // Setup a summary reporter
- SummaryProtoResultReporter summaryReporter = new SummaryProtoResultReporter();
- summaryReporter.setFileOutput(new File(resultDirPath + PROTO_SUMMARY_NAME));
- reporters.add(summaryReporter);
config.setTestInvocationListeners(reporters);
diff --git a/src/com/android/tradefed/invoker/TestInvocation.java b/src/com/android/tradefed/invoker/TestInvocation.java
index 6a31ff5..b7b2599 100644
--- a/src/com/android/tradefed/invoker/TestInvocation.java
+++ b/src/com/android/tradefed/invoker/TestInvocation.java
@@ -25,9 +25,12 @@
import com.android.tradefed.device.DeviceUnresponsiveException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.device.ITestDevice.RecoveryMode;
+import com.android.tradefed.device.NativeDevice;
import com.android.tradefed.device.StubDevice;
import com.android.tradefed.device.TestDeviceState;
import com.android.tradefed.device.cloud.ManagedRemoteDevice;
+import com.android.tradefed.device.cloud.NestedRemoteDevice;
+import com.android.tradefed.device.cloud.RemoteAndroidVirtualDevice;
import com.android.tradefed.guice.InvocationScope;
import com.android.tradefed.invoker.sandbox.ParentSandboxInvocationExecution;
import com.android.tradefed.invoker.sandbox.SandboxedInvocationExecution;
@@ -35,9 +38,11 @@
import com.android.tradefed.log.BaseLeveledLogOutput;
import com.android.tradefed.log.ILeveledLogOutput;
import com.android.tradefed.log.ILogRegistry;
+import com.android.tradefed.log.ITestLogger;
import com.android.tradefed.log.LogRegistry;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.postprocessor.IPostProcessor;
+import com.android.tradefed.result.FileInputStreamSource;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.result.LogDataType;
@@ -50,13 +55,16 @@
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.testtype.IResumableTest;
import com.android.tradefed.testtype.IRetriableTest;
+import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.IRunUtil;
+import com.android.tradefed.util.PrettyPrintDelimiter;
import com.android.tradefed.util.RunInterruptedException;
import com.android.tradefed.util.RunUtil;
import com.android.tradefed.util.TimeUtil;
import com.google.common.annotations.VisibleForTesting;
+import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -302,6 +310,9 @@
takeBugreport(badDevice, listener, bugreportName);
}
}
+ // Save the device executeShellCommand logs
+ logExecuteShellCommand(context.getDevices(), listener);
+
mStatus = "tearing down";
try {
invocationPath.doTeardown(context, config, listener, exception);
@@ -526,6 +537,11 @@
if (testDevice.getIDevice() instanceof StubDevice) {
continue;
}
+ if (testDevice instanceof RemoteAndroidVirtualDevice
+ || testDevice instanceof NestedRemoteDevice) {
+ // Vritual devices have a fake battery there is no point in logging it.
+ continue;
+ }
Integer batteryLevel = testDevice.getBattery();
if (batteryLevel == null) {
CLog.v("Failed to get battery level for %s", testDevice.getSerialNumber());
@@ -809,11 +825,32 @@
public static void printStageDelimiter(Stage phase, boolean end) {
String startEnd = end ? "ENDING" : "STARTING";
String message = String.format("===== %s PHASE %s =====", phase, startEnd);
- String limit = "";
- for (int i = 0; i < message.length(); i++) {
- limit += "=";
+ PrettyPrintDelimiter.printStageDelimiter(message);
+ }
+
+ private void logExecuteShellCommand(List<ITestDevice> devices, ITestLogger logger) {
+ for (ITestDevice device : devices) {
+ if (!(device instanceof NativeDevice)) {
+ return;
+ }
+ File log = ((NativeDevice) device).getExecuteShellCommandLog();
+ if (log == null || !log.exists()) {
+ return;
+ }
+ try {
+ if (log != null && !FileUtil.readStringFromFile(log).isEmpty()) {
+ try (InputStreamSource source = new FileInputStreamSource(log)) {
+ logger.testLog(
+ String.format(
+ "executeShellCommandLog_%s", device.getSerialNumber()),
+ LogDataType.TEXT,
+ source);
+ }
+ }
+ } catch (IOException e) {
+ // Ignored
+ CLog.e(e);
+ }
}
- String finalFormat = String.format("\n%s\n%s\n%s", limit, message, limit);
- CLog.d(finalFormat);
}
}
diff --git a/src/com/android/tradefed/result/IResultSummaryReceiver.java b/src/com/android/tradefed/result/IResultSummaryReceiver.java
deleted file mode 100644
index 23644e8..0000000
--- a/src/com/android/tradefed/result/IResultSummaryReceiver.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2019 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.SummaryRecordProto.SummaryRecord;
-
-/**
- * Interface describing an {@link ITestInvocationListener} that can receive a summary of the
- * invocation only instead of the full results.
- */
-public interface IResultSummaryReceiver {
-
- /**
- * Callback where the {@link SummaryRecord} of the results is passed. Will always be called
- * before {@link ITestInvocationListener#invocationEnded(long)}.
- *
- * @param summary a {@link SummaryRecord} containing the summary of the invocation.
- */
- public void setResultSummary(SummaryRecord summary);
-}
diff --git a/src/com/android/tradefed/result/LogSaverResultForwarder.java b/src/com/android/tradefed/result/LogSaverResultForwarder.java
index 14d9f84..6e379a2 100644
--- a/src/com/android/tradefed/result/LogSaverResultForwarder.java
+++ b/src/com/android/tradefed/result/LogSaverResultForwarder.java
@@ -18,14 +18,12 @@
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.proto.SummaryRecordProto.SummaryRecord;
import java.io.IOException;
import java.util.List;
/** A {@link ResultForwarder} for saving logs with the global file saver. */
-public class LogSaverResultForwarder extends ResultForwarder
- implements ILogSaverListener, IResultSummaryReceiver {
+public class LogSaverResultForwarder extends ResultForwarder implements ILogSaverListener {
ILogSaver mLogSaver;
@@ -134,20 +132,4 @@
}
}
}
-
- /** {@inheritDoc} */
- @Override
- public void setResultSummary(SummaryRecord summary) {
- for (ITestInvocationListener listener : getListeners()) {
- try {
- // Forward the logAssociation call
- if (listener instanceof IResultSummaryReceiver) {
- ((IResultSummaryReceiver) listener).setResultSummary(summary);
- }
- } catch (RuntimeException e) {
- CLog.e("Failed to setResultSummary on %s", listener);
- CLog.e(e);
- }
- }
- }
}
\ No newline at end of file
diff --git a/src/com/android/tradefed/result/proto/SummaryProtoParser.java b/src/com/android/tradefed/result/proto/SummaryProtoParser.java
deleted file mode 100644
index 7b635e8..0000000
--- a/src/com/android/tradefed/result/proto/SummaryProtoParser.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2019 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.proto;
-
-import com.android.tradefed.result.proto.SummaryRecordProto.SummaryRecord;
-import com.android.tradefed.util.ByteArrayList;
-
-import com.google.protobuf.CodedInputStream;
-import com.google.protobuf.InvalidProtocolBufferException;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-public class SummaryProtoParser {
-
- /**
- * Pick a 4MB default size to allow the buffer to grow for big protobuf. The default value could
- * fail in some cases.
- */
- private static final int DEFAULT_SIZE_BYTES = 4 * 1024 * 1024;
-
- /**
- * Read {@link SummaryRecord} from a file and return it.
- *
- * @param protoFile The {@link File} containing the record
- * @return a {@link SummaryRecord} created from the file.
- * @throws IOException, InvalidProtocolBufferException
- */
- public static SummaryRecord readFromFile(File protoFile)
- throws IOException, InvalidProtocolBufferException {
- SummaryRecord record = null;
- try (InputStream stream = new FileInputStream(protoFile)) {
- CodedInputStream is = CodedInputStream.newInstance(stream);
- is.setSizeLimit(Integer.MAX_VALUE);
- ByteArrayList data = new ByteArrayList(DEFAULT_SIZE_BYTES);
- while (!is.isAtEnd()) {
- int size = is.readRawVarint32();
- byte[] dataByte = is.readRawBytes(size);
- data.addAll(dataByte);
- }
- record = SummaryRecord.parseFrom(data.getContents());
- data.clear();
- }
- return record;
- }
-}
diff --git a/src/com/android/tradefed/result/proto/SummaryProtoResultReporter.java b/src/com/android/tradefed/result/proto/SummaryProtoResultReporter.java
deleted file mode 100644
index dc63a04..0000000
--- a/src/com/android/tradefed/result/proto/SummaryProtoResultReporter.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2019 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.proto;
-
-import com.android.tradefed.config.Option;
-import com.android.tradefed.invoker.IInvocationContext;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.CollectingTestListener;
-import com.android.tradefed.result.proto.SummaryRecordProto.SummaryRecord;
-import com.android.tradefed.util.StreamUtil;
-
-import com.google.protobuf.Any;
-import com.google.protobuf.Timestamp;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * Reporters that creates a summary proto from an invocation. The summary contains some minimal
- * informations about the invocation.
- */
-public class SummaryProtoResultReporter extends CollectingTestListener {
-
- @Option(
- name = "summary-proto-output-file",
- description = "File where the proto output will be saved",
- mandatory = true
- )
- private File mOutputFile;
-
- private Throwable mInvocationFailure = null;
- private long mStartTimeMs;
- private long mEndTimeMs;
-
- @Override
- public void invocationStarted(IInvocationContext context) {
- mStartTimeMs = System.currentTimeMillis();
- super.invocationStarted(context);
- }
-
- @Override
- public void invocationFailed(Throwable cause) {
- super.invocationFailed(cause);
- mInvocationFailure = cause;
- }
-
- @Override
- public void invocationEnded(long elapsedTime) {
- mEndTimeMs = System.currentTimeMillis();
- super.invocationEnded(elapsedTime);
- writeSummaryProto();
- }
-
- /** Sets the file where to output the result. */
- public void setFileOutput(File output) {
- mOutputFile = output;
- }
-
- private void writeSummaryProto() {
- if (mOutputFile == null) {
- return;
- }
- SummaryRecord.Builder builder = SummaryRecord.newBuilder();
- // Populate the proto
- builder.setNumExpectedTests(getExpectedTests());
- builder.setNumTotalTests(getNumTotalTests());
- builder.setNumFailedTests(getNumAllFailedTests());
- builder.setNumFailedRuns(getNumAllFailedTestRuns());
- if (mInvocationFailure != null) {
- builder.setErrorMessage(StreamUtil.getStackTrace(mInvocationFailure));
- }
- builder.setStartTime(createTimeStamp(mStartTimeMs));
- builder.setEndTime(createTimeStamp(mEndTimeMs));
- builder.setDescription(Any.pack(getInvocationContext().toProto()));
- // Build and write the proto
- SummaryRecord record = builder.build();
- try {
- record.writeDelimitedTo(new FileOutputStream(mOutputFile));
- } catch (IOException e) {
- CLog.e(e);
- throw new RuntimeException(e);
- }
- }
-
- /** Create and populate Timestamp as recommended in the javadoc of the Timestamp proto. */
- private Timestamp createTimeStamp(long currentTimeMs) {
- return Timestamp.newBuilder()
- .setSeconds(currentTimeMs / 1000)
- .setNanos((int) ((currentTimeMs % 1000) * 1000000))
- .build();
- }
-}
diff --git a/src/com/android/tradefed/result/suite/XmlSuiteResultFormatter.java b/src/com/android/tradefed/result/suite/XmlSuiteResultFormatter.java
index 28ae397..1aa9997 100644
--- a/src/com/android/tradefed/result/suite/XmlSuiteResultFormatter.java
+++ b/src/com/android/tradefed/result/suite/XmlSuiteResultFormatter.java
@@ -124,7 +124,7 @@
private static final String LOG_FILE_NAME_ATTR = "file_name";
/** Helper object for JSON conversion. */
- private static final class RunHistory {
+ public static final class RunHistory {
public long startTime;
public long endTime;
}
diff --git a/src/com/android/tradefed/sandbox/SandboxInvocationRunner.java b/src/com/android/tradefed/sandbox/SandboxInvocationRunner.java
index 71f44a9..2d9ca16 100644
--- a/src/com/android/tradefed/sandbox/SandboxInvocationRunner.java
+++ b/src/com/android/tradefed/sandbox/SandboxInvocationRunner.java
@@ -22,6 +22,7 @@
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.util.CommandResult;
import com.android.tradefed.util.CommandStatus;
+import com.android.tradefed.util.PrettyPrintDelimiter;
import com.android.tradefed.util.SerializationUtil;
import org.json.JSONException;
@@ -45,12 +46,14 @@
if (sandbox == null) {
throw new RuntimeException("Couldn't find the sandbox object.");
}
+ PrettyPrintDelimiter.printStageDelimiter("Starting Sandbox Environment Setup");
Exception res = sandbox.prepareEnvironment(context, config, listener);
if (res != null) {
CLog.w("Sandbox prepareEnvironment threw an Exception.");
sandbox.tearDown();
throw res;
}
+ PrettyPrintDelimiter.printStageDelimiter("Done with Sandbox Environment Setup");
try {
CommandResult result = sandbox.run(config, listener);
if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
diff --git a/src/com/android/tradefed/sandbox/TradefedSandbox.java b/src/com/android/tradefed/sandbox/TradefedSandbox.java
index 92fe045..e1f6724 100644
--- a/src/com/android/tradefed/sandbox/TradefedSandbox.java
+++ b/src/com/android/tradefed/sandbox/TradefedSandbox.java
@@ -40,6 +40,7 @@
import com.android.tradefed.util.CommandStatus;
import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.IRunUtil;
+import com.android.tradefed.util.PrettyPrintDelimiter;
import com.android.tradefed.util.QuotationAwareTokenizer;
import com.android.tradefed.util.RunUtil;
import com.android.tradefed.util.StreamUtil;
@@ -64,6 +65,8 @@
*/
public class TradefedSandbox implements ISandbox {
+ private static final String SANDBOX_PREFIX = "sandbox-";
+
private File mStdoutFile = null;
private File mStderrFile = null;
private OutputStream mStdout = null;
@@ -149,6 +152,11 @@
result.setStderr(
String.format("Event receiver thread did not complete.:\n%s", stderrText));
}
+ PrettyPrintDelimiter.printStageDelimiter(
+ String.format(
+ "Execution of the tests occurred in the sandbox, you can find its logs "
+ + "under the name pattern '%s*'",
+ SANDBOX_PREFIX));
return result;
}
@@ -290,7 +298,7 @@
String commandLine = config.getCommandLine();
if (getSandboxOptions(config).shouldUseProtoReporter()) {
mProtoReceiver =
- new StreamProtoReceiver(listener, context, false, false, "sandbox-");
+ new StreamProtoReceiver(listener, context, false, false, SANDBOX_PREFIX);
// Force the child to the same mode as the parent.
commandLine = commandLine + " --" + SandboxOptions.USE_PROTO_REPORTER;
} else {
diff --git a/src/com/android/tradefed/testtype/AndroidJUnitTest.java b/src/com/android/tradefed/testtype/AndroidJUnitTest.java
index bc70bb6..838d9e7 100644
--- a/src/com/android/tradefed/testtype/AndroidJUnitTest.java
+++ b/src/com/android/tradefed/testtype/AndroidJUnitTest.java
@@ -329,6 +329,8 @@
mDeviceIncludeFile = mTestFilterDir.replaceAll("/$", "") + "/" + INCLUDE_FILE;
pushTestFile(mIncludeTestFile, mDeviceIncludeFile, listener);
pushedFile = true;
+ // If an explicit include file filter is provided, do not use the package
+ setTestPackageName(null);
}
// if mExcludeTestFile is set, perform filtering with this file
diff --git a/src/com/android/tradefed/testtype/host/PrettyTestEventLogger.java b/src/com/android/tradefed/testtype/host/PrettyTestEventLogger.java
index 7c414f9..44ffab3 100644
--- a/src/com/android/tradefed/testtype/host/PrettyTestEventLogger.java
+++ b/src/com/android/tradefed/testtype/host/PrettyTestEventLogger.java
@@ -50,7 +50,7 @@
String.format(
"==================== %s STARTED: %s ====================",
test.toString(), date.toString());
- CLog.d(message);
+ CLog.d("\n" + message);
logOnAllDevices(message);
}
@@ -66,7 +66,7 @@
String.format(
"==================== %s ENDED: %s ====================",
test.toString(), date.toString());
- CLog.d(message);
+ CLog.d("\n" + message);
if (mTrace != null
&& mTrace.contains(DeviceNotAvailableException.class.getCanonicalName())) {
CLog.d("Skip logging device side, device was unavailable.");
diff --git a/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java b/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java
index dbc3d9f..78d7b2f 100644
--- a/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java
+++ b/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java
@@ -203,7 +203,8 @@
IModuleParameter mForcedParameter = null;
if (mForcedModuleParameter != null) {
mForcedParameter =
- ModuleParametersHelper.getParameterHandler(mForcedModuleParameter);
+ ModuleParametersHelper.getParameterHandler(
+ mForcedModuleParameter, /* optionalParams */ false);
}
// Invokes parser to process the test module config file
@@ -547,7 +548,9 @@
CLog.d("'%s' was excluded via exclude-module-parameters.");
continue;
}
- IModuleParameter handler = ModuleParametersHelper.getParameterHandler(suiteParam);
+ IModuleParameter handler =
+ ModuleParametersHelper.getParameterHandler(
+ suiteParam, /* optionalParams */ false);
params.add(handler);
}
return params;
diff --git a/src/com/android/tradefed/testtype/suite/params/InstantAppHandler.java b/src/com/android/tradefed/testtype/suite/params/InstantAppHandler.java
index 532d51f..5744f64 100644
--- a/src/com/android/tradefed/testtype/suite/params/InstantAppHandler.java
+++ b/src/com/android/tradefed/testtype/suite/params/InstantAppHandler.java
@@ -19,6 +19,7 @@
import android.platform.test.annotations.AppModeInstant;
import com.android.tradefed.config.IConfiguration;
+import com.android.tradefed.config.IDeviceConfiguration;
import com.android.tradefed.targetprep.ITargetPreparer;
import com.android.tradefed.targetprep.TestAppInstallSetup;
import com.android.tradefed.testtype.IRemoteTest;
@@ -40,9 +41,11 @@
@Override
public void applySetup(IConfiguration moduleConfiguration) {
// First, force target_preparers if they support it to install app in instant mode.
- for (ITargetPreparer preparer : moduleConfiguration.getTargetPreparers()) {
- if (preparer instanceof TestAppInstallSetup) {
- ((TestAppInstallSetup) preparer).setInstantMode(true);
+ for (IDeviceConfiguration deviceConfig : moduleConfiguration.getDeviceConfig()) {
+ for (ITargetPreparer preparer : deviceConfig.getTargetPreparers()) {
+ if (preparer instanceof TestAppInstallSetup) {
+ ((TestAppInstallSetup) preparer).setInstantMode(true);
+ }
}
}
// TODO: Second, notify HostTest that instant mode might be needed for apks.
diff --git a/src/com/android/tradefed/testtype/suite/params/ModuleParameters.java b/src/com/android/tradefed/testtype/suite/params/ModuleParameters.java
index 71c7b9b..8fca54d 100644
--- a/src/com/android/tradefed/testtype/suite/params/ModuleParameters.java
+++ b/src/com/android/tradefed/testtype/suite/params/ModuleParameters.java
@@ -22,7 +22,9 @@
NOT_INSTANT_APP("not_instant_app", "instant_app_family"),
MULTI_ABI("multi_abi", "multi_abi_family"),
- NOT_MULTI_ABI("not_multi_abi", "multi_abi_family");
+ NOT_MULTI_ABI("not_multi_abi", "multi_abi_family"),
+
+ SECONDARY_USER("secondary_user", "secondary_user_family");
public static final String INSTANT_APP_FAMILY = "instant_app_family";
public static final String MULTI_ABI_FAMILY = "multi_abi_family";
diff --git a/src/com/android/tradefed/testtype/suite/params/ModuleParametersHelper.java b/src/com/android/tradefed/testtype/suite/params/ModuleParametersHelper.java
index 517c6f0..e009976 100644
--- a/src/com/android/tradefed/testtype/suite/params/ModuleParametersHelper.java
+++ b/src/com/android/tradefed/testtype/suite/params/ModuleParametersHelper.java
@@ -31,8 +31,29 @@
sHandlerMap.put(ModuleParameters.NOT_MULTI_ABI, new NotMultiAbiHandler());
}
- /** Returns the {@link IModuleParameter} associated with the requested parameter. */
- public static IModuleParameter getParameterHandler(ModuleParameters param) {
- return sHandlerMap.get(param);
+ /**
+ * Optional parameters are params that will not automatically be created when the module
+ * parameterization is enabled. They will need to be explicitly enabled. They represent a second
+ * set of parameterization that is less commonly requested to run. They could be upgraded to
+ * main parameters in the future by moving them above.
+ */
+ private static Map<ModuleParameters, IModuleParameter> sOptionalHandlerMap = new HashMap<>();
+
+ static {
+ sOptionalHandlerMap.put(ModuleParameters.SECONDARY_USER, new SecondaryUserHandler());
+ }
+
+ /**
+ * Returns the {@link IModuleParameter} associated with the requested parameter.
+ *
+ * @param withOptional Whether or not to also check optional params.
+ */
+ public static IModuleParameter getParameterHandler(
+ ModuleParameters param, boolean withOptional) {
+ IModuleParameter value = sHandlerMap.get(param);
+ if (value == null && withOptional) {
+ return sOptionalHandlerMap.get(param);
+ }
+ return value;
}
}
diff --git a/src/com/android/tradefed/testtype/suite/params/SecondaryUserHandler.java b/src/com/android/tradefed/testtype/suite/params/SecondaryUserHandler.java
new file mode 100644
index 0000000..f4a133d
--- /dev/null
+++ b/src/com/android/tradefed/testtype/suite/params/SecondaryUserHandler.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 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.testtype.suite.params;
+
+import com.android.tradefed.config.IConfiguration;
+import com.android.tradefed.config.IDeviceConfiguration;
+import com.android.tradefed.targetprep.CreateUserPreparer;
+import com.android.tradefed.targetprep.ITargetPreparer;
+
+import java.util.List;
+
+/** Handler for {@link ModuleParameters#SECONDARY_USER}. */
+public class SecondaryUserHandler implements IModuleParameter {
+
+ @Override
+ public String getParameterIdentifier() {
+ return "secondary_user";
+ }
+
+ @Override
+ public void applySetup(IConfiguration moduleConfiguration) {
+ for (IDeviceConfiguration deviceConfig : moduleConfiguration.getDeviceConfig()) {
+ List<ITargetPreparer> preparers = deviceConfig.getTargetPreparers();
+ preparers.add(0, new CreateUserPreparer());
+ }
+ }
+}
diff --git a/src/com/android/tradefed/util/PrettyPrintDelimiter.java b/src/com/android/tradefed/util/PrettyPrintDelimiter.java
new file mode 100644
index 0000000..d69dabf
--- /dev/null
+++ b/src/com/android/tradefed/util/PrettyPrintDelimiter.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 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.util;
+
+import com.android.tradefed.log.LogUtil.CLog;
+
+/** Helper utility that helps to print delimited message that stands out. */
+public final class PrettyPrintDelimiter {
+
+ /** Prints a delimited message given a base String. */
+ public static void printStageDelimiter(String message) {
+ String limit = "";
+ for (int i = 0; i < message.length(); i++) {
+ limit += "=";
+ }
+ String finalFormat = String.format("\n%s\n%s\n%s", limit, message, limit);
+ CLog.d(finalFormat);
+ }
+}
diff --git a/tests/src/com/android/tradefed/UnitTests.java b/tests/src/com/android/tradefed/UnitTests.java
index 1f130b3..c84ef69 100644
--- a/tests/src/com/android/tradefed/UnitTests.java
+++ b/tests/src/com/android/tradefed/UnitTests.java
@@ -163,7 +163,6 @@
import com.android.tradefed.result.proto.ProtoResultParserTest;
import com.android.tradefed.result.proto.ProtoResultReporterTest;
import com.android.tradefed.result.proto.StreamProtoResultReporterTest;
-import com.android.tradefed.result.proto.SummaryProtoResultReporterTest;
import com.android.tradefed.result.suite.FormattedGeneratorReporterTest;
import com.android.tradefed.result.suite.XmlSuiteResultFormatterTest;
import com.android.tradefed.sandbox.SandboxConfigDumpTest;
@@ -562,7 +561,6 @@
ProtoResultParserTest.class,
ProtoResultReporterTest.class,
StreamProtoResultReporterTest.class,
- SummaryProtoResultReporterTest.class,
// result.suite
FormattedGeneratorReporterTest.class,
diff --git a/tests/src/com/android/tradefed/device/cloud/NestedRemoteDeviceTest.java b/tests/src/com/android/tradefed/device/cloud/NestedRemoteDeviceTest.java
index efe6c23..4ac2b17 100644
--- a/tests/src/com/android/tradefed/device/cloud/NestedRemoteDeviceTest.java
+++ b/tests/src/com/android/tradefed/device/cloud/NestedRemoteDeviceTest.java
@@ -30,6 +30,7 @@
import com.android.tradefed.util.CommandStatus;
import com.android.tradefed.util.IRunUtil;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -71,6 +72,11 @@
};
}
+ @After
+ public void tearDown() throws Exception {
+ mDevice.postInvocationTearDown();
+ }
+
/** Test that reset device returns true in case of success */
@Test
public void testResetVirtualDevice() throws DeviceNotAvailableException {
diff --git a/tests/src/com/android/tradefed/invoker/RemoteInvocationExecutionTest.java b/tests/src/com/android/tradefed/invoker/RemoteInvocationExecutionTest.java
index 7427f71..bb688b0 100644
--- a/tests/src/com/android/tradefed/invoker/RemoteInvocationExecutionTest.java
+++ b/tests/src/com/android/tradefed/invoker/RemoteInvocationExecutionTest.java
@@ -34,7 +34,6 @@
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.LogDataType;
import com.android.tradefed.result.proto.ProtoResultReporter;
-import com.android.tradefed.result.proto.SummaryProtoResultReporter;
import com.android.tradefed.util.FileUtil;
import org.junit.Before;
@@ -98,9 +97,8 @@
ConfigurationFactory.getInstance()
.createConfigurationFromArgs(new String[] {res.getAbsolutePath()});
List<ITestInvocationListener> listeners = reparse.getTestInvocationListeners();
- assertEquals(2, listeners.size());
+ assertEquals(1, listeners.size());
assertTrue(listeners.get(0) instanceof ProtoResultReporter);
- assertTrue(listeners.get(1) instanceof SummaryProtoResultReporter);
// Ensure the requested type is reset
assertNull(
((DeviceSelectionOptions)
diff --git a/tests/src/com/android/tradefed/result/proto/SummaryProtoResultReporterTest.java b/tests/src/com/android/tradefed/result/proto/SummaryProtoResultReporterTest.java
deleted file mode 100644
index 59aaa93..0000000
--- a/tests/src/com/android/tradefed/result/proto/SummaryProtoResultReporterTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2019 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.proto;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import com.android.tradefed.build.BuildInfo;
-import com.android.tradefed.config.ConfigurationDef;
-import com.android.tradefed.config.ConfigurationDescriptor;
-import com.android.tradefed.invoker.IInvocationContext;
-import com.android.tradefed.invoker.InvocationContext;
-import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
-import com.android.tradefed.result.proto.SummaryRecordProto.SummaryRecord;
-import com.android.tradefed.util.FileUtil;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.io.File;
-import java.util.HashMap;
-
-/** Unit tests for {@link SummaryProtoResultReporter}. */
-@RunWith(JUnit4.class)
-public class SummaryProtoResultReporterTest {
-
- private SummaryProtoResultReporter mReporter;
- private File mOutputFile;
- private IInvocationContext mContext;
-
- @Before
- public void setUp() throws Exception {
- mOutputFile = FileUtil.createTempFile("test-summary-proto", ".pb");
- mReporter = new SummaryProtoResultReporter();
- mReporter.setFileOutput(mOutputFile);
-
- mContext = new InvocationContext();
- mContext.addDeviceBuildInfo(ConfigurationDef.DEFAULT_DEVICE_NAME, new BuildInfo());
- mContext.setConfigurationDescriptor(new ConfigurationDescriptor());
- }
-
- @After
- public void tearDown() {
- FileUtil.deleteFile(mOutputFile);
- }
-
- @Test
- public void testReportSummary() throws Exception {
- mReporter.invocationStarted(mContext);
- mReporter.testRunStarted("run1", 5);
- mReporter.testRunEnded(5L, new HashMap<String, Metric>());
- mReporter.invocationEnded(500L);
-
- assertTrue(FileUtil.readStringFromFile(mOutputFile).length() > 50);
-
- SummaryRecord summary = SummaryProtoParser.readFromFile(mOutputFile);
- assertEquals(5, summary.getNumExpectedTests());
- assertEquals(0, summary.getNumTotalTests());
- }
-}
diff --git a/tests/src/com/android/tradefed/testtype/suite/params/ModuleParametersHelperTest.java b/tests/src/com/android/tradefed/testtype/suite/params/ModuleParametersHelperTest.java
index 34ef701..bd1f3fb 100644
--- a/tests/src/com/android/tradefed/testtype/suite/params/ModuleParametersHelperTest.java
+++ b/tests/src/com/android/tradefed/testtype/suite/params/ModuleParametersHelperTest.java
@@ -29,7 +29,8 @@
@Test
public void testHandlersExists() {
for (ModuleParameters param : ModuleParameters.values()) {
- IModuleParameter handler = ModuleParametersHelper.getParameterHandler(param);
+ IModuleParameter handler =
+ ModuleParametersHelper.getParameterHandler(param, /* Include optional */ true);
assertNotNull(handler);
}
}