release-request-447544c9-42cd-4c45-a7c6-4f09361c94db-for-git_oc-dr1-release-4277755 snap-temp-L90500000093605838
Change-Id: Ib5bdaedf375ff9b9992d99d486ebeb34146d1887
diff --git a/src/com/android/tradefed/testtype/suite/ITestSuite.java b/src/com/android/tradefed/testtype/suite/ITestSuite.java
index 37a0e60..abd20e3 100644
--- a/src/com/android/tradefed/testtype/suite/ITestSuite.java
+++ b/src/com/android/tradefed/testtype/suite/ITestSuite.java
@@ -169,6 +169,7 @@
config.getKey(),
config.getValue().getTests(),
config.getValue().getTargetPreparers(),
+ config.getValue().getMultiTargetPreparers(),
config.getValue().getConfigurationDescription());
module.setDevice(mDevice);
module.setBuild(mBuildInfo);
diff --git a/src/com/android/tradefed/testtype/suite/ModuleDefinition.java b/src/com/android/tradefed/testtype/suite/ModuleDefinition.java
index 8a0c5b1..8b5e089 100644
--- a/src/com/android/tradefed/testtype/suite/ModuleDefinition.java
+++ b/src/com/android/tradefed/testtype/suite/ModuleDefinition.java
@@ -38,8 +38,10 @@
import com.android.tradefed.targetprep.ITargetCleaner;
import com.android.tradefed.targetprep.ITargetPreparer;
import com.android.tradefed.targetprep.TargetSetupError;
+import com.android.tradefed.targetprep.multi.IMultiTargetPreparer;
import com.android.tradefed.testtype.IBuildReceiver;
import com.android.tradefed.testtype.IDeviceTest;
+import com.android.tradefed.testtype.IMultiDeviceTest;
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.testtype.IRuntimeHintProvider;
import com.android.tradefed.testtype.ITestCollector;
@@ -71,8 +73,10 @@
private Collection<IRemoteTest> mTests = null;
private List<ITargetPreparer> mPreparers = new ArrayList<>();
private List<ITargetCleaner> mCleaners = new ArrayList<>();
+ private List<IMultiTargetPreparer> mMultiPreparers = new ArrayList<>();
private IBuildInfo mBuild;
private ITestDevice mDevice;
+ private Map<ITestDevice, IBuildInfo> mDeviceInfos;
private boolean mCollectTestsOnly = false;
private List<TestRunResult> mTestsResults = new ArrayList<>();
@@ -101,6 +105,7 @@
String name,
Collection<IRemoteTest> tests,
List<ITargetPreparer> preparers,
+ List<IMultiTargetPreparer> multiPreparers,
ConfigurationDescriptor configDescriptor) {
mId = name;
mTests = tests;
@@ -114,6 +119,8 @@
MODULE_ABI, configDescriptor.getAbi().getName());
}
+ mMultiPreparers.addAll(multiPreparers);
+
for (ITargetPreparer preparer : preparers) {
mPreparers.add(preparer);
if (preparer instanceof ITargetCleaner) {
@@ -193,6 +200,13 @@
}
/**
+ * Inject the {@link Map} of {@link ITestDevice} and {@link IBuildInfo} for the configuration.
+ */
+ public void setDeviceInfos(Map<ITestDevice, IBuildInfo> deviceInfos) {
+ mDeviceInfos = deviceInfos;
+ }
+
+ /**
* Run all the {@link IRemoteTest} contained in the module and use all the preparers before and
* after to setup and clean the device.
*
@@ -225,6 +239,17 @@
break;
}
}
+ // Skip multi-preparation if preparation already failed.
+ if (preparationException == null) {
+ for (IMultiTargetPreparer multiPreparer : mMultiPreparers) {
+ preparationException = runMultiPreparerSetup(multiPreparer, listener);
+ if (preparationException != null) {
+ mIsFailedModule = true;
+ CLog.e("Some preparation step failed. failing the module %s", getId());
+ break;
+ }
+ }
+ }
mElapsedPreparation = getCurrentTime() - prepStartTime;
// Run the tests
try {
@@ -257,6 +282,9 @@
if (test instanceof IDeviceTest) {
((IDeviceTest) test).setDevice(mDevice);
}
+ if (test instanceof IMultiDeviceTest) {
+ ((IMultiDeviceTest) test).setDeviceInfos(mDeviceInfos);
+ }
if (test instanceof ISystemStatusCheckerReceiver) {
// We do not pass down Status checker because they are already running at the
// top level suite.
@@ -314,6 +342,12 @@
long cleanStartTime = getCurrentTime();
try {
// Tear down
+ List<IMultiTargetPreparer> cleanerList = new ArrayList<>(mMultiPreparers);
+ Collections.reverse(cleanerList);
+ for (IMultiTargetPreparer multiCleaner : cleanerList) {
+ CLog.d("Multi cleaner: %s", multiCleaner.getClass().getSimpleName());
+ multiCleaner.tearDown(mModuleInvocationContext, null);
+ }
for (ITargetCleaner cleaner : mCleaners) {
CLog.d("Cleaner: %s", cleaner.getClass().getSimpleName());
cleaner.tearDown(mDevice, mBuild, null);
@@ -430,6 +464,23 @@
}
}
+ /** Run all multi target preparer step. */
+ private Exception runMultiPreparerSetup(IMultiTargetPreparer preparer, ITestLogger logger) {
+ CLog.d("Multi preparer: %s", preparer.getClass().getSimpleName());
+ try {
+ // set the logger in case they need it.
+ if (preparer instanceof ITestLoggerReceiver) {
+ ((ITestLoggerReceiver) preparer).setTestLogger(logger);
+ }
+ preparer.setUp(mModuleInvocationContext);
+ return null;
+ } catch (BuildError | TargetSetupError | DeviceNotAvailableException e) {
+ CLog.e("Unexpected Exception from preparer: %s", preparer.getClass().getName());
+ CLog.e(e);
+ return e;
+ }
+ }
+
/** Returns the current time. */
private long getCurrentTime() {
return System.currentTimeMillis();
diff --git a/src/com/android/tradefed/testtype/suite/ModuleSplitter.java b/src/com/android/tradefed/testtype/suite/ModuleSplitter.java
index 83d6c19..8f3a17a 100644
--- a/src/com/android/tradefed/testtype/suite/ModuleSplitter.java
+++ b/src/com/android/tradefed/testtype/suite/ModuleSplitter.java
@@ -19,6 +19,7 @@
import com.android.tradefed.config.IConfiguration;
import com.android.tradefed.config.OptionCopier;
import com.android.tradefed.targetprep.ITargetPreparer;
+import com.android.tradefed.targetprep.multi.IMultiTargetPreparer;
import com.android.tradefed.testtype.IAbiReceiver;
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.testtype.IShardableTest;
@@ -97,7 +98,8 @@
new ModuleDefinition(
moduleName,
config.getTests(),
- clonePreparers(config),
+ clonePreparers(config.getTargetPreparers()),
+ clonePreparers(config.getMultiTargetPreparers()),
config.getConfigurationDescription());
currentList.add(module);
} else {
@@ -121,7 +123,8 @@
new ModuleDefinition(
moduleName,
shardedTests,
- clonePreparers(config),
+ clonePreparers(config.getTargetPreparers()),
+ clonePreparers(config.getMultiTargetPreparers()),
config.getConfigurationDescription());
currentList.add(module);
}
@@ -155,7 +158,8 @@
new ModuleDefinition(
moduleName,
testList,
- clonePreparers(config),
+ clonePreparers(config.getTargetPreparers()),
+ clonePreparers(config.getMultiTargetPreparers()),
config.getConfigurationDescription());
currentList.add(module);
}
@@ -171,16 +175,17 @@
}
/**
- * Deep clone a list of {@link ITargetPreparer}. We are ensured to find a default constructor
- * with no arguments since that's the expectation from Tradefed when loading configuration.
- * Cloning preparers is required since they may be stateful and we cannot share instance across
- * devices.
+ * Deep clone a list of {@link ITargetPreparer} or {@link IMultiTargetPreparer}. We are ensured
+ * to find a default constructor with no arguments since that's the expectation from Tradefed
+ * when loading configuration. Cloning preparers is required since they may be stateful and we
+ * cannot share instance across devices.
*/
- private static List<ITargetPreparer> clonePreparers(IConfiguration config) {
- List<ITargetPreparer> clones = new ArrayList<>();
- for (ITargetPreparer prep : config.getTargetPreparers()) {
+ private static <T> List<T> clonePreparers(List<T> preparerList) {
+ List<T> clones = new ArrayList<>();
+ for (T prep : preparerList) {
try {
- ITargetPreparer clone = prep.getClass().newInstance();
+ @SuppressWarnings("unchecked")
+ T clone = (T) prep.getClass().newInstance();
OptionCopier.copyOptions(prep, clone);
// Ensure we copy the Abi too.
if (clone instanceof IAbiReceiver) {
diff --git a/src/com/android/tradefed/testtype/suite/ValidateSuiteConfigHelper.java b/src/com/android/tradefed/testtype/suite/ValidateSuiteConfigHelper.java
index 85a8b50..914037f 100644
--- a/src/com/android/tradefed/testtype/suite/ValidateSuiteConfigHelper.java
+++ b/src/com/android/tradefed/testtype/suite/ValidateSuiteConfigHelper.java
@@ -17,6 +17,7 @@
import com.android.tradefed.build.StubBuildProvider;
import com.android.tradefed.config.IConfiguration;
+import com.android.tradefed.config.IDeviceConfiguration;
import com.android.tradefed.result.TextResultReporter;
/**
@@ -35,6 +36,15 @@
if (!config.getBuildProvider().getClass().isAssignableFrom(StubBuildProvider.class)) {
return false;
}
+ // if a multi device config is presented, ensure none of the devices define a build_provider
+ for (IDeviceConfiguration deviceConfig : config.getDeviceConfig()) {
+ if (!deviceConfig
+ .getBuildProvider()
+ .getClass()
+ .isAssignableFrom(StubBuildProvider.class)) {
+ return false;
+ }
+ }
if (config.getTestInvocationListeners().size() != 1) {
return false;
}
diff --git a/tests/src/com/android/tradefed/testtype/suite/ModuleDefinitionTest.java b/tests/src/com/android/tradefed/testtype/suite/ModuleDefinitionTest.java
index 4a8cf31..5b98c4a 100644
--- a/tests/src/com/android/tradefed/testtype/suite/ModuleDefinitionTest.java
+++ b/tests/src/com/android/tradefed/testtype/suite/ModuleDefinitionTest.java
@@ -30,6 +30,7 @@
import com.android.tradefed.targetprep.ITargetCleaner;
import com.android.tradefed.targetprep.ITargetPreparer;
import com.android.tradefed.targetprep.TargetSetupError;
+import com.android.tradefed.targetprep.multi.IMultiTargetPreparer;
import com.android.tradefed.testtype.Abi;
import com.android.tradefed.testtype.IBuildReceiver;
import com.android.tradefed.testtype.IDeviceTest;
@@ -56,6 +57,7 @@
private ITargetPreparer mMockPrep;
private ITargetCleaner mMockCleaner;
private List<ITargetPreparer> mTargetPrepList;
+ private List<IMultiTargetPreparer> mMultiTargetPrepList;
private ITestInvocationListener mMockListener;
private IBuildInfo mMockBuildInfo;
private ITestDevice mMockDevice;
@@ -117,11 +119,16 @@
mMockCleaner = EasyMock.createMock(ITargetCleaner.class);
mTargetPrepList.add(mMockPrep);
mTargetPrepList.add(mMockCleaner);
+ mMultiTargetPrepList = new ArrayList<>();
mMockBuildInfo = EasyMock.createMock(IBuildInfo.class);
mMockDevice = EasyMock.createMock(ITestDevice.class);
mModule =
new ModuleDefinition(
- MODULE_NAME, mTestList, mTargetPrepList, new ConfigurationDescriptor());
+ MODULE_NAME,
+ mTestList,
+ mTargetPrepList,
+ mMultiTargetPrepList,
+ new ConfigurationDescriptor());
}
/**
@@ -197,7 +204,11 @@
});
mModule =
new ModuleDefinition(
- MODULE_NAME, mTestList, mTargetPrepList, new ConfigurationDescriptor());
+ MODULE_NAME,
+ mTestList,
+ mTargetPrepList,
+ mMultiTargetPrepList,
+ new ConfigurationDescriptor());
mMockCleaner.tearDown(EasyMock.eq(mMockDevice), EasyMock.eq(mMockBuildInfo),
EasyMock.isNull());
mMockListener.testRunStarted(EasyMock.eq(MODULE_NAME), EasyMock.eq(1));
@@ -222,7 +233,11 @@
testList.add(new TestObject("run1", testCount, false));
mModule =
new ModuleDefinition(
- MODULE_NAME, testList, mTargetPrepList, new ConfigurationDescriptor());
+ MODULE_NAME,
+ testList,
+ mTargetPrepList,
+ mMultiTargetPrepList,
+ new ConfigurationDescriptor());
mModule.setBuild(mMockBuildInfo);
mModule.setDevice(mMockDevice);
mMockPrep.setUp(EasyMock.eq(mMockDevice), EasyMock.eq(mMockBuildInfo));
@@ -254,7 +269,11 @@
testList.add(new TestObject("run1", testCount, true));
mModule =
new ModuleDefinition(
- MODULE_NAME, testList, mTargetPrepList, new ConfigurationDescriptor());
+ MODULE_NAME,
+ testList,
+ mTargetPrepList,
+ mMultiTargetPrepList,
+ new ConfigurationDescriptor());
mModule.setBuild(mMockBuildInfo);
mModule.setDevice(mMockDevice);
mMockPrep.setUp(EasyMock.eq(mMockDevice), EasyMock.eq(mMockBuildInfo));
@@ -297,7 +316,9 @@
descriptor.setAbi(new Abi("arm", "32"));
List<IRemoteTest> testList = new ArrayList<>();
testList.add(new TestObject("run1", testCount, false));
- mModule = new ModuleDefinition(MODULE_NAME, testList, mTargetPrepList, descriptor);
+ mModule =
+ new ModuleDefinition(
+ MODULE_NAME, testList, mTargetPrepList, mMultiTargetPrepList, descriptor);
// Check that the invocation module created has expected informations
IInvocationContext moduleContext = mModule.getModuleInvocationContext();
assertEquals(
diff --git a/tests/src/com/android/tradefed/testtype/suite/ValidateSuiteConfigHelperTest.java b/tests/src/com/android/tradefed/testtype/suite/ValidateSuiteConfigHelperTest.java
index f5e5a6b..3caa45a 100644
--- a/tests/src/com/android/tradefed/testtype/suite/ValidateSuiteConfigHelperTest.java
+++ b/tests/src/com/android/tradefed/testtype/suite/ValidateSuiteConfigHelperTest.java
@@ -20,7 +20,9 @@
import com.android.tradefed.build.LocalFolderBuildProvider;
import com.android.tradefed.config.Configuration;
+import com.android.tradefed.config.DeviceConfigurationHolder;
import com.android.tradefed.config.IConfiguration;
+import com.android.tradefed.config.IDeviceConfiguration;
import com.android.tradefed.result.CollectingTestListener;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.TextResultReporter;
@@ -50,6 +52,21 @@
assertFalse(ValidateSuiteConfigHelper.validateConfig(config));
}
+ /**
+ * Test that a config using the device holder config (multi device) is correctly rejected since
+ * it is not using the default build_provider.
+ */
+ @Test
+ public void testNotRunningAsSuite_MultiDevice_buildProvider() throws Exception {
+ IConfiguration config = new Configuration("test", "test description");
+ // LocalFolderBuildProvider extends the default StubBuildProvider but is still correctly
+ // rejected.
+ IDeviceConfiguration deviceConfig = new DeviceConfigurationHolder("default");
+ deviceConfig.addSpecificConfig(new LocalFolderBuildProvider());
+ config.setDeviceConfig(deviceConfig);
+ assertFalse(ValidateSuiteConfigHelper.validateConfig(config));
+ }
+
/** Test that a config with a result reporter cannot run as suite. */
@Test
public void testNotRunningAsSuite_resultReporter() {