blob: 4d9bfec84b826715a743956cd44afa9603c8dc85 [file] [log] [blame]
/*
* Copyright (C) 2017 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.compatibility.common.tradefed.presubmit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import com.android.compatibility.SuiteInfo;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.compatibility.common.tradefed.result.ResultReporter;
import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
import com.android.compatibility.common.tradefed.testtype.IModuleDef;
import com.android.compatibility.common.util.IInvocationResult;
import com.android.compatibility.common.util.TestStatus;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.ConfigurationFactory;
import com.android.tradefed.config.OptionSetter;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.invoker.InvocationContext;
import com.android.tradefed.invoker.ShardListener;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.ResultForwarder;
import com.android.tradefed.testtype.IBuildReceiver;
import com.android.tradefed.testtype.IDeviceTest;
import com.android.tradefed.testtype.IInvocationContextReceiver;
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.util.AbiUtils;
import com.android.tradefed.util.FileUtil;
import org.easymock.EasyMock;
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.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* Integration tests between {@link CompatibilityTest} and {@link ResultReporter} to ensure proper
* flow of run and results.
*/
@RunWith(JUnit4.class)
public class IntegrationTest {
private static final String CONFIG =
"<configuration description=\"Auto Generated File\">\n" +
"<option name=\"config-descriptor:metadata\" key=\"component\" value=\"%s\" />\n" +
"<test class=\"com.android.compatibility.common.tradefed.testtype.%s\">\n" +
" <option name=\"report-test\" value=\"%s\" />\n" +
" <option name=\"run-complete\" value=\"%s\" />\n" +
" <option name=\"test-fail\" value=\"%s\" />\n" +
" <option name=\"internal-retry\" value=\"%s\" />\n" +
"</test>\n" +
"</configuration>";
private static final String FILENAME = "%s.config";
private static final String TEST_STUB = "TestStub"; // Test stub
private static final String SIMPLE_TEST_STUB = "SimpleTestStub"; // Simple test stub
private static final String TEST_STUB_SHARDABLE = "TestStubShardable";
private static final String COMMAND_LINE = "run cts";
private CompatibilityTest mTest;
private ResultReporter mReporter;
private ITestDevice mMockDevice;
private IBuildInfo mMockBuildInfo;
private IInvocationContext mContext;
private File mRootDir;
private File mAndroidFolder;
private File mTestDir;
private Map<String, String> mAttributes;
@Before
public void setUp() throws IOException {
mAttributes = new HashMap<>();
mTest = new CompatibilityTest() {
@Override
protected Set<String> getAbisForBuildTargetArch() {
Set<String> abis = new HashSet<>();
abis.add("arm64-v8a");
abis.add("armeabi-v7a");
return abis;
}
};
mReporter = new ResultReporter();
mMockDevice = EasyMock.createMock(ITestDevice.class);
mMockBuildInfo = EasyMock.createMock(IBuildInfo.class);
mTest.setBuild(mMockBuildInfo);
mTest.setDevice(mMockDevice);
mRootDir = FileUtil.createTempDir("fake-cts-root-dir");
mAndroidFolder = FileUtil.createTempDir("android-", mRootDir);
mTestDir = new File(mAndroidFolder, "testcases");
mTestDir.mkdirs();
String suiteName = mAndroidFolder.getName().split("-")[1];
// Create fake build attributes
mAttributes.put(CompatibilityBuildHelper.ROOT_DIR, mRootDir.getAbsolutePath());
mAttributes.put(CompatibilityBuildHelper.SUITE_NAME, suiteName);
mAttributes.put(CompatibilityBuildHelper.START_TIME_MS, "0");
mAttributes.put(CompatibilityBuildHelper.SUITE_VERSION, "10");
mAttributes.put(CompatibilityBuildHelper.SUITE_PLAN, "cts");
mAttributes.put(CompatibilityBuildHelper.SUITE_BUILD, "good-build");
mAttributes.put(CompatibilityBuildHelper.COMMAND_LINE_ARGS, COMMAND_LINE);
// these attributes seems necessary for re-run, not for run
mAttributes.put("cts:build_fingerprint", "fingerprint");
mAttributes.put("cts:build_product", "product");
mAttributes.put("cts:build_id", "bid");
EasyMock.expect(mMockBuildInfo.getBuildAttributes()).andStubReturn(mAttributes);
EasyMock.expect(mMockDevice.getSerialNumber()).andStubReturn("SERIAL");
EasyMock.expect(mMockBuildInfo.getDeviceSerial()).andStubReturn("SERIAL");
mContext = new InvocationContext();
mContext.addAllocatedDevice("default", mMockDevice);
mContext.addDeviceBuildInfo("default", mMockBuildInfo);
mTest.setInvocationContext(mContext);
}
@After
public void tearDown() {
FileUtil.recursiveDelete(mRootDir);
}
/**
* Create a CTS configuration with a fake tests to exercise all cases.
*
* @param testsDir The testcases/ dir where to put the module
* @param name the name of the module.
* @param moduleClass the fake test class to use.
* @param reportTest True if the test report some tests
* @param runComplete True if the test run is complete
* @param doesOneTestFail True if one of the test is going to fail
* @param internalRetry True if the test will retry the module itself once
*/
private void createConfig(File testsDir, String name, String moduleClass, boolean reportTest,
boolean runComplete, boolean doesOneTestFail, boolean internalRetry)
throws IOException {
createConfig(testsDir, name, moduleClass, reportTest, runComplete, doesOneTestFail,
internalRetry, "foo");
}
/**
* Create a CTS configuration with a fake tests to exercise all cases.
*
* @param testsDir The testcases/ dir where to put the module
* @param name the name of the module.
* @param moduleClass the fake test class to use.
* @param reportTest True if the test report some tests
* @param runComplete True if the test run is complete
* @param doesOneTestFail True if one of the test is going to fail
* @param internalRetry True if the test will retry the module itself once
* @param component the platform component name that the module can be categorized under
*/
private void createConfig(File testsDir, String name, String moduleClass, boolean reportTest,
boolean runComplete, boolean doesOneTestFail, boolean internalRetry, String component)
throws IOException {
File config = new File(testsDir, String.format(FILENAME, name));
FileUtil.deleteFile(config);
if (!config.createNewFile()) {
throw new IOException(String.format("Failed to create '%s'", config.getAbsolutePath()));
}
FileUtil.writeToFile(String.format(CONFIG, component, moduleClass, reportTest, runComplete,
doesOneTestFail, internalRetry), config);
}
/**
* Simple tests running in one module that should be marked complete.
*/
@Test
public void testSingleModuleRun() throws Exception {
final String moduleName = "module_run";
final String mAbi = "arm64-v8a";
createConfig(mTestDir, moduleName, TEST_STUB, true, true, true, false);
EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
EasyMock.expectLastCall();
EasyMock.replay(mMockDevice, mMockBuildInfo);
mReporter.invocationStarted(mContext);
mTest.run(mReporter);
mReporter.invocationEnded(500);
EasyMock.verify(mMockDevice, mMockBuildInfo);
IInvocationResult result = mReporter.getResult();
assertEquals(2, result.countResults(TestStatus.PASS));
assertEquals(1, result.countResults(TestStatus.FAIL));
assertEquals(1, result.getModules().size());
assertEquals(1, result.getModuleCompleteCount());
}
/**
* Verify that result reporters test run ended callback can receive component name as configured
* in module config metadata field.
*/
@Test
public void testSingleModuleRun_checkMetadata() throws Exception {
final String moduleName = "AwsomeModule";
final String mAbi = "arm64-v8a";
final String component = "CriticalComponent";
final List<String> receivedComponentsTestEnded = new ArrayList<>();
final List<String> receivedModuleNameTestEnded = new ArrayList<>();
final List<String> receivedAbiTestEnded = new ArrayList<>();
final List<String> receivedComponentsTestRunEnded = new ArrayList<>();
final List<String> receivedModuleNameTestRunEnded = new ArrayList<>();
final List<String> receivedAbiTestRunEnded = new ArrayList<>();
createConfig(mTestDir, moduleName, SIMPLE_TEST_STUB, true, true, true, false, component);
EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
EasyMock.expectLastCall();
EasyMock.replay(mMockDevice, mMockBuildInfo);
ITestInvocationListener myListener = new ITestInvocationListener() {
private IInvocationContext myContext;
@Override
public void invocationStarted(IInvocationContext context) {
myContext = context;
}
@Override
public void testRunEnded(long elapsedTimeMillis, Map<String, String> runMetrics) {
receivedComponentsTestRunEnded.addAll(myContext.getModuleInvocationContext()
.getConfigurationDescriptor().getMetaData("component"));
receivedModuleNameTestRunEnded.addAll(myContext.getModuleInvocationContext()
.getAttributes().get(IModuleDef.MODULE_NAME));
receivedAbiTestRunEnded.addAll(myContext.getModuleInvocationContext()
.getAttributes().get(IModuleDef.MODULE_ABI));
}
@Override
public void testEnded(TestIdentifier test, long endTime,
Map<String, String> testMetrics) {
receivedComponentsTestEnded.addAll(myContext.getModuleInvocationContext()
.getConfigurationDescriptor().getMetaData("component"));
receivedModuleNameTestEnded.addAll(myContext.getModuleInvocationContext()
.getAttributes().get(IModuleDef.MODULE_NAME));
receivedAbiTestEnded.addAll(myContext.getModuleInvocationContext()
.getAttributes().get(IModuleDef.MODULE_ABI));
}
};
myListener.invocationStarted(mContext);
mTest.run(myListener);
myListener.invocationEnded(500);
EasyMock.verify(mMockDevice, mMockBuildInfo);
// verify metadata was retrieved during testRunEnded callbacks
assertEquals("[testRunEnded] wrong number of metadata collected",
1, receivedComponentsTestRunEnded.size());
assertEquals("[testRunEnded] wrong component metadata field received",
component, receivedComponentsTestRunEnded.get(0));
assertEquals("[testRunEnded] wrong number of module name collected",
1, receivedModuleNameTestRunEnded.size());
assertEquals(moduleName, receivedModuleNameTestRunEnded.get(0));
assertEquals("[testEnded] wrong number of module abi collected",
1, receivedAbiTestRunEnded.size());
assertEquals(mAbi, receivedAbiTestRunEnded.get(0));
// verify metadata was retrieved during testEnded callbacks
assertEquals("[testEnded] wrong number of metadata collected",
1, receivedComponentsTestEnded.size());
assertEquals("[testEnded] wrong component metadata field received",
component, receivedComponentsTestEnded.get(0));
assertEquals("[testEnded] wrong number of module name collected",
1, receivedModuleNameTestEnded.size());
assertEquals(moduleName, receivedModuleNameTestEnded.get(0));
assertEquals("[testEnded] wrong number of module abi collected",
1, receivedAbiTestEnded.size());
assertEquals(mAbi, receivedAbiTestEnded.get(0));
}
/**
* Simple tests running in one module that run some tests but not all of them.
*/
@Test
public void testSingleModuleRun_incomplete() throws Exception {
final String moduleName = "module_run_incomplete";
final String mAbi = "arm64-v8a";
createConfig(mTestDir, moduleName, TEST_STUB, true, false, true, false);
EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
EasyMock.expectLastCall();
EasyMock.replay(mMockDevice, mMockBuildInfo);
mReporter.invocationStarted(mContext);
mTest.run(mReporter);
mReporter.invocationEnded(500);
EasyMock.verify(mMockDevice, mMockBuildInfo);
IInvocationResult result = mReporter.getResult();
assertEquals(1, result.countResults(TestStatus.PASS));
assertEquals(1, result.countResults(TestStatus.FAIL));
// Module should not be seen as complete.
assertEquals(1, result.getModules().size());
assertEquals(0, result.getModuleCompleteCount());
}
/**
* Simple tests running in one module that should be marked complete since it runs all its
* tests after an internal retry (like InstrumentationTest).
* FIXME: Fix the expectation of this test
*/
@Test
public void testSingleModuleRun_completeAfterInternalRetry() throws Exception {
final String moduleName = "module_completeAfterRetry";
final String mAbi = "arm64-v8a";
createConfig(mTestDir, moduleName, TEST_STUB, true, true, true, true);
EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
EasyMock.expectLastCall();
EasyMock.replay(mMockDevice, mMockBuildInfo);
mReporter.invocationStarted(mContext);
mTest.run(mReporter);
mReporter.invocationEnded(500);
EasyMock.verify(mMockDevice, mMockBuildInfo);
IInvocationResult result = mReporter.getResult();
// FIXME: All tests should be marked as executed and not aggregating the count.
assertEquals(2, result.countResults(TestStatus.PASS));
assertEquals(1, result.countResults(TestStatus.FAIL));
// FIXME: Module should be complete since all its test have run.
assertEquals(1, result.getModules().size());
assertEquals(0, result.getModuleCompleteCount());
}
/**
* Simple tests running in one module that run some tests but not all of them, then we
* attempt to run it again and they still didn't run.
* FIXME: This test expectation needs to be fixed
*/
@Test
public void testSingleModuleRun_incomplete_rerun_incomplete() throws Exception {
final String moduleName = "module_incomplete_rerun";
final String mAbi = "arm64-v8a";
createConfig(mTestDir, moduleName, TEST_STUB, true, false, true, false);
EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
EasyMock.expectLastCall();
// extra calls for retry
EasyMock.expect(mMockDevice.getProperty("ro.build.fingerprint")).andReturn("fingerprint");
EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
EasyMock.expectLastCall();
mMockBuildInfo.addBuildAttribute(EasyMock.eq("retry_command_line_args"),
EasyMock.eq(COMMAND_LINE));
EasyMock.expectLastCall();
EasyMock.replay(mMockDevice, mMockBuildInfo);
mReporter.invocationStarted(mContext);
mTest.run(mReporter);
mReporter.invocationEnded(500);
IInvocationResult result = mReporter.getResult();
assertEquals(1, result.countResults(TestStatus.PASS));
assertEquals(1, result.countResults(TestStatus.FAIL));
// Module should not be seen as complete.
assertEquals(0, result.getModuleCompleteCount());
// We re-run it
mReporter = new ResultReporter();
mTest = new CompatibilityTest() {
@Override
protected Set<String> getAbisForBuildTargetArch() {
Set<String> abis = new HashSet<>();
abis.add("arm64-v8a");
return abis;
}
};
mTest.setDevice(mMockDevice);
mTest.setBuild(mMockBuildInfo);
mTest.setInvocationContext(mContext);
OptionSetter setter = new OptionSetter(mTest, mReporter);
setter.setOptionValue("retry", "0");
mReporter.invocationStarted(mContext);
mTest.run(mReporter);
mReporter.invocationEnded(500);
EasyMock.verify(mMockDevice, mMockBuildInfo);
// Check retry results
result = mReporter.getResult();
// FIXME: We should only have 1 not_executed in the retry too. They should not aggregate
// from one run to another.
assertEquals(1, result.countResults(TestStatus.PASS));
assertEquals(1, result.countResults(TestStatus.FAIL));
// Module should not be seen as complete.
assertEquals(1, result.getModules().size());
assertEquals(0, result.getModuleCompleteCount());
}
/**
* Simple tests running in one module that run some tests but not all of them, we then attempt
* to retry run them and this time the not_executed is executed.
*/
@Test
public void testSingleModuleRun_incomplete_rerun_complete() throws Exception {
final String moduleName = "module_incom_rerun_complete";
final String mAbi = "arm64-v8a";
createConfig(mTestDir, moduleName, TEST_STUB, true, false, true, false);
EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
EasyMock.expectLastCall();
// extra calls for retry
EasyMock.expect(mMockDevice.getProperty("ro.build.fingerprint")).andReturn("fingerprint");
EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
EasyMock.expectLastCall();
mMockBuildInfo.addBuildAttribute(EasyMock.eq("retry_command_line_args"),
EasyMock.eq(COMMAND_LINE));
EasyMock.expectLastCall();
EasyMock.replay(mMockDevice, mMockBuildInfo);
mReporter.invocationStarted(mContext);
mTest.run(mReporter);
mReporter.invocationEnded(500);
IInvocationResult result = mReporter.getResult();
assertEquals(1, result.countResults(TestStatus.PASS));
assertEquals(1, result.countResults(TestStatus.FAIL));
// Module should not be seen as complete.
assertEquals(0, result.getModuleCompleteCount());
// We replace the config by one that runs all tests without failures.
createConfig(mTestDir, moduleName, TEST_STUB, true, true, false, false);
// Usually configs do not change during the same session so we clear the map to have
// the new version of the config.
((ConfigurationFactory)ConfigurationFactory.getInstance()).clearMapConfig();
// We re-run it
mReporter = new ResultReporter();
mTest = new CompatibilityTest() {
@Override
protected Set<String> getAbisForBuildTargetArch() {
Set<String> abis = new HashSet<>();
abis.add("arm64-v8a");
return abis;
}
};
mTest.setDevice(mMockDevice);
mTest.setBuild(mMockBuildInfo);
mTest.setInvocationContext(mContext);
OptionSetter setter = new OptionSetter(mTest, mReporter);
setter.setOptionValue("retry", "0");
mReporter.invocationStarted(mContext);
mTest.run(mReporter);
mReporter.invocationEnded(500);
EasyMock.verify(mMockDevice, mMockBuildInfo);
// Check retry results
result = mReporter.getResult();
assertEquals(3, result.countResults(TestStatus.PASS));
assertEquals(0, result.countResults(TestStatus.FAIL));
// Module should be marked as complete after retry.
assertEquals(1, result.getModules().size());
assertEquals(1, result.getModuleCompleteCount());
}
// ***** Case for sharding interaction *****
/**
* Helper to create a shard listener with the original reporter as master.
*/
private ITestInvocationListener getShardListener(ResultReporter masterReporter) {
List<ITestInvocationListener> shardListeners = new ArrayList<ITestInvocationListener>();
ShardListener origConfigListener = new ShardListener(masterReporter);
ResultReporter reporterClone = (ResultReporter) masterReporter.clone();
shardListeners.add(reporterClone);
shardListeners.add(origConfigListener);
ResultForwarder shard = new ResultForwarder(shardListeners);
return shard;
}
/**
* Helper Thread to run the IShardableTest.
*/
private class ShardThread extends Thread {
private IRemoteTest mShardTest;
private ResultReporter mMasterReporter;
private IBuildInfo mBuild;
private ITestDevice mDevice;
private IInvocationContext mShardContext;
public ShardThread(IRemoteTest test, ResultReporter masterReporter, IBuildInfo build,
ITestDevice device, IInvocationContext context) {
mShardTest = test;
mMasterReporter = masterReporter;
mBuild = build;
mDevice = device;
mShardContext = context;
}
@Override
public void run() {
ITestInvocationListener listener = getShardListener(mMasterReporter);
((IBuildReceiver)mShardTest).setBuild(mBuild);
((IDeviceTest)mShardTest).setDevice(mDevice);
((IInvocationContextReceiver)mShardTest).setInvocationContext(mContext);
listener.invocationStarted(mShardContext);
try {
mShardTest.run(listener);
} catch (DeviceNotAvailableException e) {
throw new RuntimeException(e);
} finally {
listener.invocationEnded(500);
}
}
}
/**
* Simple tests running in one module that should be marked complete when each shard run a test
* from the module. Each Module is going to run 1 pass 1 fail. 2 modules and 2 shards.
* Using the {@link CompatibilityTest#split()}.
*/
@Test
public void testSingleModuleRun_sharded() throws Exception {
final String moduleName = "module_sharded";
Set<String> abis = AbiUtils.getAbisForArch(SuiteInfo.TARGET_ARCH);
Iterator<String> ite = abis.iterator();
final String abi1 = ite.next();
final String abi2 = ite.next();
createConfig(mTestDir, moduleName, TEST_STUB_SHARDABLE, true, true, true, false);
EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(
String.format("%s,%s", abi1, abi2));
mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
EasyMock.anyObject());
EasyMock.expectLastCall();
EasyMock.replay(mMockDevice, mMockBuildInfo);
OptionSetter setter = new OptionSetter(mTest);
setter.setOptionValue("shards", "2");
List<IRemoteTest> tests = (List<IRemoteTest>) mTest.split();
// We expect 2 shards
assertEquals(2, tests.size());
List<ShardThread> threads = new ArrayList<>();
// Run all shards
for (IRemoteTest test : tests) {
ShardThread st = new ShardThread(test, mReporter, mMockBuildInfo, mMockDevice,
mContext);
threads.add(st);
st.start();
}
for (ShardThread thread : threads) {
thread.join(5000);
}
// Allow some time for ResultReport to finalize the results coming from the threads.
boolean finalized = mReporter.waitForFinalized(2, TimeUnit.MINUTES);
assertTrue(finalized);
EasyMock.verify(mMockDevice, mMockBuildInfo);
// Check aggregated results to make sure it's consistent.
IInvocationResult result = mReporter.getResult();
assertEquals(4, result.countResults(TestStatus.PASS));
assertEquals(4, result.countResults(TestStatus.FAIL));
assertEquals(2, result.getModules().size());
assertEquals(2, result.getModuleCompleteCount());
}
/**
* Simple tests running in one module that should be marked incomplete when shards do not
* complete. Each shard is going to run 1 pass 1 fail 1 not_executed.
* Using the {@link CompatibilityTest#split()}.
*/
@Test
public void testSingleModuleRun_sharded_incomplete() throws Exception {
final String moduleName = "module_sharded_incomplete";
Set<String> abis = AbiUtils.getAbisForArch(SuiteInfo.TARGET_ARCH);
Iterator<String> ite = abis.iterator();
final String abi1 = ite.next();
final String abi2 = ite.next();
createConfig(mTestDir, moduleName, TEST_STUB_SHARDABLE, true, false, true, false);
EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(
String.format("%s,%s", abi1, abi2));
mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
EasyMock.anyObject());
EasyMock.expectLastCall();
EasyMock.replay(mMockDevice, mMockBuildInfo);
OptionSetter setter = new OptionSetter(mTest);
setter.setOptionValue("shards", "2");
List<IRemoteTest> tests = (List<IRemoteTest>) mTest.split();
// We expect 2 shards
assertEquals(2, tests.size());
List<ShardThread> threads = new ArrayList<>();
// Run all shards
for (IRemoteTest test : tests) {
ShardThread st = new ShardThread(test, mReporter, mMockBuildInfo, mMockDevice,
mContext);
threads.add(st);
st.start();
}
for (ShardThread thread : threads) {
thread.join(5000);
}
// Allow some time for ResultReport to finalize the results coming from the threads.
boolean finalized = mReporter.waitForFinalized(2, TimeUnit.MINUTES);
assertTrue(finalized);
EasyMock.verify(mMockDevice, mMockBuildInfo);
// Check aggregated results to make sure it's consistent.
IInvocationResult result = mReporter.getResult();
assertEquals(4, result.countResults(TestStatus.PASS));
assertEquals(4, result.countResults(TestStatus.FAIL));
assertEquals(2, result.getModules().size());
assertEquals(0, result.getModuleCompleteCount());
}
/**
* Simple tests running in one module that should be marked complete when each shard run a test
* from the module.
* We are going to run only one of the shard since IStrictShardable allows it.
* Using the {@link CompatibilityTest#getTestShard(int, int)}.
* FIXME: Fix expectation of this test.
*/
@Test
public void testSingleModuleRun_sharded_getTestShard() throws Exception {
final String moduleName = "module_sharded_getTestShard";
Set<String> abis = AbiUtils.getAbisForArch(SuiteInfo.TARGET_ARCH);
Iterator<String> ite = abis.iterator();
final String abi1 = ite.next();
final String abi2 = ite.next();
createConfig(mTestDir, moduleName, TEST_STUB_SHARDABLE, true, true, true, false);
EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(
String.format("%s,%s", abi1, abi2));
String expectedAdd = AbiUtils.createId(abi1, moduleName) + ","
+ AbiUtils.createId(abi2, moduleName);
mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
EasyMock.anyObject());
EasyMock.expectLastCall();
mAttributes.put(CompatibilityBuildHelper.MODULE_IDS, expectedAdd);
EasyMock.replay(mMockDevice, mMockBuildInfo);
List<IRemoteTest> tests = new ArrayList<>();
tests.add(mTest.getTestShard(3, 0));
// We are only running one of the shards since they should be independent.
assertEquals(1, tests.size());
((IBuildReceiver)tests.get(0)).setBuild(mMockBuildInfo);
((IDeviceTest)tests.get(0)).setDevice(mMockDevice);
((IInvocationContextReceiver)tests.get(0)).setInvocationContext(mContext);
mReporter.invocationStarted(mContext);
try {
tests.get(0).run(mReporter);
} catch (DeviceNotAvailableException e) {
throw new RuntimeException(e);
} finally {
mReporter.invocationEnded(500);
}
EasyMock.verify(mMockDevice, mMockBuildInfo);
IInvocationResult result = mReporter.getResult();
assertEquals(2, result.countResults(TestStatus.PASS));
assertEquals(2, result.countResults(TestStatus.FAIL));
// FIXME: Only one module should be expected since within the one shard requested to run
// only one module existed.
assertEquals(2, result.getModules().size());
// FIXME: The module for the shard should be completed since all tests run.
// TestRunHandler in this case create an expectation of 3 testRunStarted just because of
// the number of shards.
assertEquals(0, result.getModuleCompleteCount());
}
}