diff options
author | easoncylee <easoncylee@google.com> | 2019-09-19 18:48:28 +0800 |
---|---|---|
committer | easoncylee <easoncylee@google.com> | 2019-10-08 09:19:39 +0800 |
commit | 3e1954cc4ec294bd6eeabbf687f95a9c367ea086 (patch) | |
tree | 694a2057e804afe93f08879a4fe8ac9d4cd385f9 | |
parent | 2e3c27b74a903f647ed4e4bdd51d945c135fea01 (diff) | |
download | tradefederation-3e1954cc4ec294bd6eeabbf687f95a9c367ea086.tar.gz |
Run Test Mapping tests with different options inside a single suite.
Reason: This CL is to support TMSR running tests with different test
options defined in TEST_MAPPING.
Bug: 117880789
Test: unittests.
Change-Id: I405eeeb353460e424d4df88d66ca40676e600da7
7 files changed, 479 insertions, 93 deletions
diff --git a/src/com/android/tradefed/testtype/suite/BaseTestSuite.java b/src/com/android/tradefed/testtype/suite/BaseTestSuite.java index b2835469a..f43c7af3f 100644 --- a/src/com/android/tradefed/testtype/suite/BaseTestSuite.java +++ b/src/com/android/tradefed/testtype/suite/BaseTestSuite.java @@ -184,6 +184,7 @@ public class BaseTestSuite extends ITestSuite { private SuiteModuleLoader mModuleRepo; private Map<String, List<SuiteTestFilter>> mIncludeFiltersParsed = new HashMap<>(); private Map<String, List<SuiteTestFilter>> mExcludeFiltersParsed = new HashMap<>(); + private List<File> mConfigPaths = new ArrayList<>(); /** {@inheritDoc} */ @Override @@ -304,6 +305,12 @@ public class BaseTestSuite extends ITestSuite { public LinkedHashMap<String, IConfiguration> loadingStrategy( Set<IAbi> abis, List<File> testsDirs, String suitePrefix, String suiteTag) { LinkedHashMap<String, IConfiguration> loadedConfigs = new LinkedHashMap<>(); + // Load and return directly the specific config files. + if (!mConfigPaths.isEmpty()) { + CLog.d("Loading the specified configs and skip loading from the resources."); + return getModuleLoader().loadConfigsFromSpecifiedPaths(mConfigPaths, abis, suiteTag); + } + // Load configs that are part of the resources if (!mSkipJarLoading) { loadedConfigs.putAll( @@ -360,6 +367,11 @@ public class BaseTestSuite extends ITestSuite { mModuleArgs.addAll(moduleArgs); } + /** Clear the stored module args out */ + void clearModuleArgs() { + mModuleArgs.clear(); + } + /** Add config patterns */ public void addConfigPatterns(List<String> patterns) { mConfigPatterns.addAll(patterns); @@ -463,6 +475,21 @@ public class BaseTestSuite extends ITestSuite { mExcludeFiltersParsed.clear(); } + /** + * Add the config path for {@link SuiteModuleLoader} to limit the search loading + * configurations. + * + * @param configPath A {@code File} with the absolute path of the configuration. + */ + void addConfigPaths(File configPath) { + mConfigPaths.add(configPath); + } + + /** Clear the stored config paths out. */ + void clearConfigPaths() { + mConfigPaths.clear(); + } + /* Helper method designed to remove filters in a list not applicable to the given module */ private static void checkFilters(Set<String> filters, String moduleName) { Set<String> cleanedFilters = new HashSet<String>(); diff --git a/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java b/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java index 08dd62613..1884504fb 100644 --- a/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java +++ b/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java @@ -117,6 +117,20 @@ public class SuiteModuleLoader { mExcludedModuleParameters = excludedParams; } + /** Main loading of configurations, looking into the specified files */ + public LinkedHashMap<String, IConfiguration> loadConfigsFromSpecifiedPaths( + List<File> listConfigFiles, + Set<IAbi> abis, + String suiteTag) { + LinkedHashMap<String, IConfiguration> toRun = new LinkedHashMap<>(); + for (File configFile : listConfigFiles) { + toRun.putAll( + loadOneConfig( + configFile.getName(), configFile.getAbsolutePath(), abis, suiteTag)); + } + return toRun; + } + /** Main loading of configurations, looking into a folder */ public LinkedHashMap<String, IConfiguration> loadConfigsFromDirectory( List<File> testsDirs, @@ -130,11 +144,7 @@ public class SuiteModuleLoader { ConfigurationUtil.getConfigNamesFileFromDirs(suitePrefix, testsDirs, patterns)); // Ensure stable initial order of configurations. Collections.sort(listConfigFiles); - for (File configFile : listConfigFiles) { - toRun.putAll( - loadOneConfig( - configFile.getName(), configFile.getAbsolutePath(), abis, suiteTag)); - } + toRun.putAll(loadConfigsFromSpecifiedPaths(listConfigFiles, abis, suiteTag)); return toRun; } diff --git a/src/com/android/tradefed/testtype/suite/TestMappingSuiteRunner.java b/src/com/android/tradefed/testtype/suite/TestMappingSuiteRunner.java index b13ffa7a5..89d4545bc 100644 --- a/src/com/android/tradefed/testtype/suite/TestMappingSuiteRunner.java +++ b/src/com/android/tradefed/testtype/suite/TestMappingSuiteRunner.java @@ -19,12 +19,14 @@ import com.android.tradefed.config.ConfigurationDescriptor; import com.android.tradefed.config.IConfiguration; import com.android.tradefed.config.Option; import com.android.tradefed.log.LogUtil.CLog; +import com.android.tradefed.testtype.IRemoteTest; import com.android.tradefed.util.testmapping.TestInfo; import com.android.tradefed.util.testmapping.TestMapping; import com.android.tradefed.util.testmapping.TestOption; +import com.google.common.annotations.VisibleForTesting; +import java.io.File; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; @@ -89,10 +91,10 @@ public class TestMappingSuiteRunner extends BaseTestSuite { */ @Override public LinkedHashMap<String, IConfiguration> loadTests() { - // Map between test names and a list of test sources for each test. - Map<String, List<String>> testsInTestMapping = new HashMap<>(); - Set<String> includeFilter = getIncludeFilter(); + // Name of the tests + Set<String> testNames = new HashSet<>(); + Set<TestInfo> testInfosToRun = new HashSet<>(); if (mTestGroup == null && includeFilter.isEmpty()) { throw new RuntimeException( "At least one of the options, --test-mapping-test-group or --include-filter, " @@ -114,96 +116,184 @@ public class TestMappingSuiteRunner extends BaseTestSuite { } if (mTestGroup != null) { - Set<TestInfo> testsToRun = + testInfosToRun = TestMapping.getTests( getBuildInfo(), mTestGroup, getPrioritizeHostConfig(), mKeywords); if (!mTestModulesForced.isEmpty()) { CLog.i("Filtering tests for the given names: %s", mTestModulesForced); - testsToRun = - testsToRun + testInfosToRun = + testInfosToRun .stream() .filter(testInfo -> mTestModulesForced.contains(testInfo.getName())) .collect(Collectors.toSet()); } - if (testsToRun.isEmpty()) { + if (testInfosToRun.isEmpty()) { throw new RuntimeException( String.format("No test found for the given group: %s.", mTestGroup)); } - - // Name of the tests - Set<String> testNames = new HashSet<>(); - - Set<String> mappingIncludeFilters = new HashSet<>(); - Set<String> mappingExcludeFilters = new HashSet<>(); - - // module-arg options compiled from test options for each test. - Set<String> moduleArgs = new HashSet<>(); - for (TestInfo test : testsToRun) { - boolean hasIncludeFilters = false; - for (TestOption option : test.getOptions()) { - switch (option.getName()) { - // Handle include and exclude filter at the suite level to hide each - // test runner specific implementation and option names related to filtering - case TEST_MAPPING_INCLUDE_FILTER: - hasIncludeFilters = true; - mappingIncludeFilters.add( - String.format("%s %s", test.getName(), option.getValue())); - break; - case TEST_MAPPING_EXCLUDE_FILTER: - mappingExcludeFilters.add( - String.format("%s %s", test.getName(), option.getValue())); - break; - default: - String moduleArg = - String.format("%s:%s", test.getName(), option.getName()); - if (option.getValue() != null && !option.getValue().isEmpty()) { - moduleArg = String.format("%s:%s", moduleArg, option.getValue()); - } - moduleArgs.add(moduleArg); - break; - } - } - if (!hasIncludeFilters) { - testNames.add(test.getName()); - } + for (TestInfo testInfo : testInfosToRun) { + testNames.add(testInfo.getName()); } + setIncludeFilter(testNames); + } + + // load all the configurations with include-filter injected. + LinkedHashMap<String, IConfiguration> testConfigs = super.loadTests(); - if (mappingIncludeFilters.isEmpty()) { - setIncludeFilter(testNames); - } else { - mappingIncludeFilters.addAll(testNames); - setIncludeFilter(mappingIncludeFilters); + // Create and inject individual tests by calling super.loadTests() with each test info. + for (Map.Entry<String, IConfiguration> entry : testConfigs.entrySet()) { + List<IRemoteTest> allTests = new ArrayList<>(); + IConfiguration moduleConfig = entry.getValue(); + ConfigurationDescriptor configDescriptor = + moduleConfig.getConfigurationDescription(); + String moduleName = configDescriptor.getModuleName(); + String configPath = moduleConfig.getName(); + Set<TestInfo> testInfos = getTestInfos(testInfosToRun, moduleName); + allTests.addAll( + createIndividualTests( + testInfos, configPath)); + if (!allTests.isEmpty()) { + // Set back to IConfiguration only if IRemoteTests are created. + moduleConfig.setTests(allTests); + // Set test sources to ConfigurationDescriptor. + List<String> testSources = getTestSources(testInfos); + configDescriptor.addMetaData(TestMapping.TEST_SOURCES, testSources); } - if (!mappingExcludeFilters.isEmpty()) { - setExcludeFilter(mappingExcludeFilters); + } + return testConfigs; + } + + /** + * Create individual tests with test infos for a module. + * + * @param testInfos A {@code Set<TestInfo>} containing multiple test options. + * @param configPath A {@code String} of configuration path. + * @return The {@link List<IRemoteTest>} that are injected with the test options. + */ + @VisibleForTesting + List<IRemoteTest> createIndividualTests(Set<TestInfo> testInfos, String configPath) { + List<IRemoteTest> tests = new ArrayList<>(); + if (configPath == null) { + throw new RuntimeException(String.format("Configuration path is null.")); + } + File configFie = new File(configPath); + if (!configFie.exists()) { + throw new RuntimeException( + String.format("Configuration path: %s doesn't exits.", configPath)); + } + // De-duplicate test infos so that there won't be duplicate test options. + testInfos = dedupTestInfos(testInfos); + for (TestInfo testInfo : testInfos) { + // Clean up all the test options injected in SuiteModuleLoader. + super.cleanUpSuiteSetup(); + super.clearModuleArgs(); + clearConfigPaths(); + // Set config path to BaseTestSuite to limit the search. + addConfigPaths(configFie); + // Inject the test options from each test info to SuiteModuleLoader. + parseOptions(testInfo); + LinkedHashMap<String, IConfiguration> config = super.loadTests(); + for (Map.Entry<String, IConfiguration> entry : config.entrySet()) { + tests.addAll(entry.getValue().getTests()); } - addModuleArgs(moduleArgs); - - for (TestInfo test : testsToRun) { - List<String> testSources = null; - // TODO(b/117880789): tests may not be grouped by name once that bug is fixed. - // Update the dictionary with better keys. - if (testsInTestMapping.containsKey(test.getName())) { - testSources = testsInTestMapping.get(test.toString()); - } else { - testSources = new ArrayList<String>(); - testsInTestMapping.put(test.getName(), testSources); - } - testSources.addAll(test.getSources()); + } + return tests; + } + + /** + * Get a list of path of TEST_MAPPING for a module. + * + * @param testInfos A {@code Set<TestInfo>} containing multiple test options. + * @return A {@code List<String>} of TEST_MAPPING path. + */ + @VisibleForTesting + List<String> getTestSources(Set<TestInfo> testInfos) { + List<String> testSources = new ArrayList<>(); + for (TestInfo testInfo : testInfos) { + testSources.addAll(testInfo.getSources()); + } + return testSources; + } + + /** + * Parse the test options for the test info. + * + * @param testInfo A {@code Set<TestInfo>} containing multiple test options. + */ + @VisibleForTesting + void parseOptions(TestInfo testInfo) { + Set<String> mappingIncludeFilters = new HashSet<>(); + Set<String> mappingExcludeFilters = new HashSet<>(); + // module-arg options compiled from test options for each test. + Set<String> moduleArgs = new HashSet<>(); + Set<String> testNames = new HashSet<>(); + for (TestOption option : testInfo.getOptions()) { + switch (option.getName()) { + // Handle include and exclude filter at the suite level to hide each + // test runner specific implementation and option names related to filtering + case TEST_MAPPING_INCLUDE_FILTER: + mappingIncludeFilters.add( + String.format("%s %s", testInfo.getName(), option.getValue())); + break; + case TEST_MAPPING_EXCLUDE_FILTER: + mappingExcludeFilters.add( + String.format("%s %s", testInfo.getName(), option.getValue())); + break; + default: + String moduleArg = + String.format("%s:%s", testInfo.getName(), option.getName()); + if (option.getValue() != null && !option.getValue().isEmpty()) { + moduleArg = String.format("%s:%s", moduleArg, option.getValue()); + } + moduleArgs.add(moduleArg); + break; } } - LinkedHashMap<String, IConfiguration> testConfigs = super.loadTests(); - for (Map.Entry<String, IConfiguration> entry : testConfigs.entrySet()) { - ConfigurationDescriptor configDescriptor = - entry.getValue().getConfigurationDescription(); - if (testsInTestMapping.containsKey(configDescriptor.getModuleName())) { - configDescriptor.addMetaData( - TestMapping.TEST_SOURCES, - testsInTestMapping.get(configDescriptor.getModuleName())); + if (mappingIncludeFilters.isEmpty()) { + testNames.add(testInfo.getName()); + setIncludeFilter(testNames); + } else { + setIncludeFilter(mappingIncludeFilters); + } + if (!mappingExcludeFilters.isEmpty()) { + setExcludeFilter(mappingExcludeFilters); + } + addModuleArgs(moduleArgs); + } + + /** + * De-duplicate test infos with the same test options. + * + * @param testInfos A {@code Set<TestInfo>} containing multiple test options. + * @return A {@code Set<TestInfo>} of tests without duplicated test options. + */ + @VisibleForTesting + Set<TestInfo> dedupTestInfos(Set<TestInfo> testInfos) { + Set<String> nameOptions = new HashSet<>(); + Set<TestInfo> dedupTestInfos = new HashSet<>(); + for (TestInfo testInfo : testInfos) { + String nameOption = testInfo.getName() + testInfo.getOptions().toString(); + if (!nameOptions.contains(nameOption)) { + dedupTestInfos.add(testInfo); + nameOptions.add(nameOption); } } + return dedupTestInfos; + } - return testConfigs; + /** + * Get the test infos for the given module name. + * + * @param testInfos A {@code Set<TestInfo>} containing multiple test options. + * @param moduleName A {@code String} name of a test module. + * @return A {@code Set<TestInfo>} of tests for a module. + */ + @VisibleForTesting + Set<TestInfo> getTestInfos(Set<TestInfo> testInfos, String moduleName) { + return testInfos + .stream() + .filter(testInfo -> moduleName.equals(testInfo.getName())) + .collect(Collectors.toSet()); } } diff --git a/src/com/android/tradefed/util/testmapping/TestMapping.java b/src/com/android/tradefed/util/testmapping/TestMapping.java index 8221d1eab..1b02e29a5 100644 --- a/src/com/android/tradefed/util/testmapping/TestMapping.java +++ b/src/com/android/tradefed/util/testmapping/TestMapping.java @@ -281,7 +281,7 @@ public class TestMapping { FileUtil.recursiveDelete(testMappingsDir); } - return TestMapping.mergeTests(tests); + return tests; } /** diff --git a/tests/src/com/android/tradefed/testtype/suite/SuiteModuleLoaderTest.java b/tests/src/com/android/tradefed/testtype/suite/SuiteModuleLoaderTest.java index b5bbd8129..e2a23aebd 100644 --- a/tests/src/com/android/tradefed/testtype/suite/SuiteModuleLoaderTest.java +++ b/tests/src/com/android/tradefed/testtype/suite/SuiteModuleLoaderTest.java @@ -17,6 +17,7 @@ package com.android.tradefed.testtype.suite; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import com.android.tradefed.config.IConfiguration; @@ -287,4 +288,83 @@ public class SuiteModuleLoaderTest { assertEquals( "NativeDnsAsyncTest#Async_Cancel", stubTest.getExcludeFilters().iterator().next()); } + + /** + * Test that the configuration can be found if specifying specific path. + */ + @Test + public void testLoadConfigsFromSpecifiedPaths_OneModule() throws Exception { + createModuleConfig("module1"); + File module1 = new File(mTestsDir, "module1" + SuiteModuleLoader.CONFIG_EXT); + + mRepo = + new SuiteModuleLoader( + new LinkedHashMap<String, List<SuiteTestFilter>>(), + new LinkedHashMap<String, List<SuiteTestFilter>>(), + new ArrayList<>(), + new ArrayList<>()); + + LinkedHashMap<String, IConfiguration> res = + mRepo.loadConfigsFromSpecifiedPaths( + Arrays.asList(module1), mAbis, null); + assertEquals(1, res.size()); + assertNotNull(res.get("armeabi-v7a module1")); + } + + /** + * Test that multiple configurations can be found if specifying specific paths. + */ + @Test + public void testLoadConfigsFromSpecifiedPaths_MultipleModules() throws Exception { + createModuleConfig("module1"); + File module1 = new File(mTestsDir, "module1" + SuiteModuleLoader.CONFIG_EXT); + createModuleConfig("module2"); + File module2 = new File(mTestsDir, "module2" + SuiteModuleLoader.CONFIG_EXT); + + mRepo = + new SuiteModuleLoader( + new LinkedHashMap<String, List<SuiteTestFilter>>(), + new LinkedHashMap<String, List<SuiteTestFilter>>(), + new ArrayList<>(), + new ArrayList<>()); + + LinkedHashMap<String, IConfiguration> res = + mRepo.loadConfigsFromSpecifiedPaths( + Arrays.asList(module1, module2), mAbis, null); + assertEquals(2, res.size()); + assertNotNull(res.get("armeabi-v7a module1")); + assertNotNull(res.get("armeabi-v7a module2")); + } + + /** + * Test that configuration can be found correctly if specifying specific paths but someone is + * excluded. + */ + @Test + public void testLoadConfigsFromSpecifiedPaths_WithExcludeFilter() throws Exception { + createModuleConfig("module1"); + File module1 = new File(mTestsDir, "module1" + SuiteModuleLoader.CONFIG_EXT); + createModuleConfig("module2"); + File module2 = new File(mTestsDir, "module2" + SuiteModuleLoader.CONFIG_EXT); + + Map<String, List<SuiteTestFilter>> excludeFilters = new LinkedHashMap<>(); + SuiteTestFilter filter = + SuiteTestFilter.createFrom( + "armeabi-v7a module2"); + excludeFilters.put("armeabi-v7a module2", Arrays.asList(filter)); + + mRepo = + new SuiteModuleLoader( + new LinkedHashMap<String, List<SuiteTestFilter>>(), + excludeFilters, + new ArrayList<>(), + new ArrayList<>()); + + LinkedHashMap<String, IConfiguration> res = + mRepo.loadConfigsFromSpecifiedPaths( + Arrays.asList(module1, module2), mAbis, null); + assertEquals(1, res.size()); + assertNotNull(res.get("armeabi-v7a module1")); + assertNull(res.get("armeabi-v7a module2")); + } } diff --git a/tests/src/com/android/tradefed/testtype/suite/TestMappingSuiteRunnerTest.java b/tests/src/com/android/tradefed/testtype/suite/TestMappingSuiteRunnerTest.java index b2028d87f..48b660061 100644 --- a/tests/src/com/android/tradefed/testtype/suite/TestMappingSuiteRunnerTest.java +++ b/tests/src/com/android/tradefed/testtype/suite/TestMappingSuiteRunnerTest.java @@ -20,6 +20,8 @@ import static org.junit.Assert.assertTrue; import com.android.tradefed.build.BuildInfoKey.BuildInfoFileKey; import com.android.tradefed.build.IDeviceBuildInfo; +import com.android.tradefed.config.ConfigurationException; +import com.android.tradefed.config.ConfigurationFactory; import com.android.tradefed.config.IConfiguration; import com.android.tradefed.config.OptionSetter; import com.android.tradefed.device.DeviceNotAvailableException; @@ -31,8 +33,11 @@ import com.android.tradefed.testtype.StubTest; import com.android.tradefed.util.AbiUtils; import com.android.tradefed.util.FileUtil; import com.android.tradefed.util.ZipUtil; +import com.android.tradefed.util.testmapping.TestInfo; import com.android.tradefed.util.testmapping.TestMapping; +import com.android.tradefed.util.testmapping.TestOption; +import java.util.ArrayList; import org.easymock.EasyMock; import org.junit.Before; import org.junit.Test; @@ -57,14 +62,17 @@ public class TestMappingSuiteRunnerTest { private static final String ABI_1 = "arm64-v8a"; private static final String ABI_2 = "armeabi-v7a"; + private static final String DISABLED_PRESUBMIT_TESTS = "disabled-presubmit-tests"; + private static final String EMPTY_CONFIG = "empty"; private static final String NON_EXISTING_DIR = "non-existing-dir"; + private static final String TEST_CONFIG_NAME = "test"; private static final String TEST_DATA_DIR = "testdata"; private static final String TEST_MAPPING = "TEST_MAPPING"; private static final String TEST_MAPPINGS_ZIP = "test_mappings.zip"; - private static final String DISABLED_PRESUBMIT_TESTS = "disabled-presubmit-tests"; private TestMappingSuiteRunner mRunner; private OptionSetter mOptionSetter; + private TestMappingSuiteRunner mRunner2; private IDeviceBuildInfo mBuildInfo; private ITestDevice mMockDevice; @@ -79,8 +87,13 @@ public class TestMappingSuiteRunnerTest { mOptionSetter = new OptionSetter(mRunner); mOptionSetter.setOptionValue("suite-config-prefix", "suite"); - EasyMock.expect(mBuildInfo.getFile(BuildInfoFileKey.TARGET_LINKED_DIR)).andReturn(null); - EasyMock.expect(mBuildInfo.getTestsDir()).andReturn(new File(NON_EXISTING_DIR)); + mRunner2 = new FakeTestMappingSuiteRunner(); + mRunner2.setBuild(mBuildInfo); + mRunner2.setDevice(mMockDevice); + + EasyMock.expect(mBuildInfo.getFile(BuildInfoFileKey.TARGET_LINKED_DIR)).andReturn(null) + .anyTimes(); + EasyMock.expect(mBuildInfo.getTestsDir()).andReturn(new File(NON_EXISTING_DIR)).anyTimes(); EasyMock.expect(mMockDevice.getProperty(EasyMock.anyObject())).andReturn(ABI_1); EasyMock.expect(mMockDevice.getProperty(EasyMock.anyObject())).andReturn(ABI_2); EasyMock.replay(mBuildInfo, mMockDevice); @@ -98,6 +111,43 @@ public class TestMappingSuiteRunnerTest { abis.add(new Abi(ABI_2, AbiUtils.getBitness(ABI_2))); return abis; } + + @Override + List<IRemoteTest> createIndividualTests(Set<TestInfo> testInfos, String configPath) { + IRemoteTest fakeTest = EasyMock.createMock(IRemoteTest.class); + return new ArrayList<>(Arrays.asList(fakeTest)); + } + } + + /** + * Test TestMappingSuiteRunner that create a fake IConfiguration with fake a test object. + */ + public static class FakeTestMappingSuiteRunner extends TestMappingSuiteRunner { + @Override + public Set<IAbi> getAbis(ITestDevice device) throws DeviceNotAvailableException { + Set<IAbi> abis = new HashSet<>(); + abis.add(new Abi(ABI_1, AbiUtils.getBitness(ABI_1))); + abis.add(new Abi(ABI_2, AbiUtils.getBitness(ABI_2))); + return abis; + } + + @Override + public LinkedHashMap<String, IConfiguration> loadingStrategy(Set<IAbi> abis, + List<File> testsDirs, String suitePrefix, String suiteTag) { + LinkedHashMap<String, IConfiguration> testConfig = new LinkedHashMap<>(); + try { + IConfiguration config = + ConfigurationFactory.getInstance() + .createConfigurationFromArgs(new String[] {EMPTY_CONFIG}); + config.setTest(new StubTest()); + config.getConfigurationDescription().setModuleName(TEST_CONFIG_NAME); + testConfig.put(TEST_CONFIG_NAME, config); + + } catch (ConfigurationException e) { + throw new RuntimeException(e); + } + return testConfig; + } } /** @@ -174,13 +224,7 @@ public class TestMappingSuiteRunnerTest { assertTrue(mRunner.getIncludeFilter().contains("test2")); assertTrue(mRunner.getIncludeFilter().contains("instrument")); assertTrue(mRunner.getIncludeFilter().contains("suite/stub1")); - // Filters are applied directly - assertTrue(mRunner.getExcludeFilter().contains("suite/stub1 filter.com")); - assertTrue(mRunner.getIncludeFilter().contains("suite/stub2 filter.com")); - - // Check module-arg work as expected. - StubTest test = (StubTest) configMap.get("arm64-v8a suite/stub2").getTests().get(0); - assertTrue(test.getRunTest()); + assertTrue(mRunner.getIncludeFilter().contains("suite/stub2")); assertEquals(4, configMap.size()); assertTrue(configMap.containsKey(ABI_1 + " suite/stub1")); @@ -575,4 +619,141 @@ public class TestMappingSuiteRunnerTest { FileUtil.recursiveDelete(tempDir); } } + + /** + * Test for {@link TestMappingSuiteRunner#getTestInfos(Set, String)} that when a module is + * specified, tests would be still found correctly. + */ + @Test + public void testGetTestInfos() throws Exception { + Set<TestInfo> testInfos = new HashSet<>(); + testInfos.add(createTestInfo("test", "path")); + testInfos.add(createTestInfo("test", "path2")); + testInfos.add(createTestInfo("test2", "path2")); + + assertEquals(2, mRunner.getTestInfos(testInfos, "test").size()); + assertEquals(1, mRunner.getTestInfos(testInfos, "test2").size()); + } + + /** + * Test for {@link TestMappingSuiteRunner#dedupTestInfos(Set)} that tests with the same test + * options would be filtered out. + */ + @Test + public void testDedupTestInfos() throws Exception { + Set<TestInfo> testInfos = new HashSet<>(); + testInfos.add(createTestInfo("test", "path")); + testInfos.add(createTestInfo("test", "path2")); + assertEquals(1, mRunner.dedupTestInfos(testInfos).size()); + + TestInfo anotherInfo = new TestInfo("test", "folder3", false); + anotherInfo.addOption(new TestOption("include-filter", "value1")); + testInfos.add(anotherInfo); + assertEquals(2, mRunner.dedupTestInfos(testInfos).size()); + } + + /** + * Test for {@link TestMappingSuiteRunner#getTestSources(Set)} that test sources would be found + * correctly. + */ + @Test + public void testGetTestSources() throws Exception { + Set<TestInfo> testInfos = new HashSet<>(); + testInfos.add(createTestInfo("test", "path")); + testInfos.add(createTestInfo("test", "path2")); + List<String> results = mRunner.getTestSources(testInfos); + assertEquals(2, results.size()); + } + + /** + * Test for {@link TestMappingSuiteRunner#parseOptions(TestInfo)} that the test options are + * injected correctly. + */ + @Test + public void testParseOptions() throws Exception { + TestInfo info = createTestInfo("test", "path"); + mRunner.parseOptions(info); + assertEquals(1, mRunner.getIncludeFilter().size()); + assertEquals(1, mRunner.getExcludeFilter().size()); + } + + /** + * Test for {@link TestMappingSuiteRunner#createIndividualTests(Set, String)} that IRemoteTest + * object are created according to the test infos with different test options. + */ + @Test + public void testCreateIndividualTestsWithDifferentTestInfos() throws Exception { + File tempDir = null; + try { + tempDir = FileUtil.createTempDir("tmp"); + File moduleConfig = new File(tempDir, "module_name.config"); + moduleConfig.createNewFile(); + Set<TestInfo> testInfos = new HashSet<>(); + testInfos.add(createTestInfo("test", "path")); + testInfos.add(createTestInfo("test2", "path")); + String configPath = moduleConfig.getAbsolutePath(); + assertEquals(2, mRunner2.createIndividualTests(testInfos, configPath).size()); + assertEquals(1, mRunner2.getIncludeFilter().size()); + assertEquals(1, mRunner2.getExcludeFilter().size()); + } finally { + FileUtil.recursiveDelete(tempDir); + } + } + + /** + * Test for {@link TestMappingSuiteRunner#createIndividualTests(Set, String)} that IRemoteTest + * object are created according to the test infos with multiple test options. + */ + @Test + public void testCreateIndividualTestsWithDifferentTestOptions() throws Exception { + File tempDir = null; + try { + tempDir = FileUtil.createTempDir("tmp"); + File moduleConfig = new File(tempDir, "module_name.config"); + moduleConfig.createNewFile(); + Set<TestInfo> testInfos = new HashSet<>(); + testInfos.add(createTestInfo("test", "path")); + TestInfo info = new TestInfo("test", "path", false); + info.addOption(new TestOption("include-filter", "include-filter")); + testInfos.add(info); + String configPath = moduleConfig.getAbsolutePath(); + assertEquals(2, mRunner2.createIndividualTests(testInfos, configPath).size()); + assertEquals(1, mRunner2.getIncludeFilter().size()); + assertEquals(0, mRunner2.getExcludeFilter().size()); + } finally { + FileUtil.recursiveDelete(tempDir); + } + } + + /** + * Test for {@link TestMappingSuiteRunner#createIndividualTests(Set, String)} that IRemoteTest + * object are created according to the test infos with the same test options and name. + */ + @Test + public void testCreateIndividualTestsWithSameTestInfos() throws Exception { + File tempDir = null; + try { + tempDir = FileUtil.createTempDir("tmp"); + File moduleConfig = new File(tempDir, "module_name.config"); + moduleConfig.createNewFile(); + String configPath = moduleConfig.getAbsolutePath(); + Set<TestInfo> testInfos = new HashSet<>(); + testInfos.add(createTestInfo("test", "path")); + testInfos.add(createTestInfo("test", "path")); + assertEquals(1, mRunner2.createIndividualTests(testInfos, configPath).size()); + assertEquals(1, mRunner2.getIncludeFilter().size()); + assertEquals(1, mRunner2.getExcludeFilter().size()); + } finally { + FileUtil.recursiveDelete(tempDir); + } + } + + /** Helper to create specific test infos. */ + private TestInfo createTestInfo(String name, String source) { + TestInfo info = new TestInfo(name, source, false); + info.addOption(new TestOption("include-filter", name)); + info.addOption(new TestOption("exclude-filter", name)); + info.addOption(new TestOption("other", name)); + return info; + } } diff --git a/tests/src/com/android/tradefed/util/testmapping/TestMappingTest.java b/tests/src/com/android/tradefed/util/testmapping/TestMappingTest.java index 8c53c17a6..0d69264eb 100644 --- a/tests/src/com/android/tradefed/util/testmapping/TestMappingTest.java +++ b/tests/src/com/android/tradefed/util/testmapping/TestMappingTest.java @@ -169,12 +169,10 @@ public class TestMappingTest { assertEquals(0, tests.size()); tests = TestMapping.getTests(mockBuildInfo, "presubmit", true, null); - assertEquals(1, tests.size()); + assertEquals(2, tests.size()); Set<String> names = new HashSet<String>(); for (TestInfo test : tests) { names.add(test.getName()); - // Make sure the tests for `test1` are merged and no option is kept. - assertTrue(test.getOptions().isEmpty()); if (test.getName().equals("test1")) { assertTrue(test.getHostOnly()); } else { |