blob: 921f6752c6607fc8de09ddac419c1e1425b96eaa [file] [log] [blame]
/*
* Copyright (C) 2018 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;
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.ConfigurationDescriptor;
import com.android.tradefed.config.IConfiguration;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionClass;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.invoker.TestInformation;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.targetprep.BaseTargetPreparer;
import com.android.tradefed.testtype.Abi;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IRemoteTest;
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.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/** Unit tests for {@link SuiteModuleLoader}. */
@RunWith(JUnit4.class)
public class SuiteModuleLoaderTest {
private static final String TEST_CONFIG =
"<configuration description=\"Runs a stub tests part of some suite\">\n"
+ " <target_preparer class=\"com.android.tradefed.testtype.suite.SuiteModuleLoaderTest$PreparerInject\" />\n"
+ " <test class=\"com.android.tradefed.testtype.suite.SuiteModuleLoaderTest"
+ "$TestInject\" />\n"
+ "</configuration>";
private static final String TEST_INSTANT_CONFIG =
"<configuration description=\"Runs a stub tests part of some suite\">\n"
+ " <option name=\"config-descriptor:metadata\" key=\"parameter\" value=\"instant_app\" />"
// Duplicate parameter should not have impact
+ " <option name=\"config-descriptor:metadata\" key=\"parameter\" value=\"instant_app\" />"
+ " <test class=\"com.android.tradefed.testtype.suite.TestSuiteStub\" />\n"
+ "</configuration>";
private SuiteModuleLoader mRepo;
private File mTestsDir;
private Set<IAbi> mAbis;
@Before
public void setUp() throws Exception {
mRepo =
new SuiteModuleLoader(
new LinkedHashMap<String, List<SuiteTestFilter>>(),
new LinkedHashMap<String, List<SuiteTestFilter>>(),
new ArrayList<>(),
new ArrayList<>());
mTestsDir = FileUtil.createTempDir("suite-module-loader-tests");
mAbis = new HashSet<>();
mAbis.add(new Abi("armeabi-v7a", "32"));
}
@After
public void tearDown() {
FileUtil.recursiveDelete(mTestsDir);
}
private void createModuleConfig(String moduleName) throws IOException {
File module = new File(mTestsDir, moduleName + SuiteModuleLoader.CONFIG_EXT);
FileUtil.writeToFile(TEST_CONFIG, module);
}
private void createInstantModuleConfig(String moduleName) throws IOException {
File module = new File(mTestsDir, moduleName + SuiteModuleLoader.CONFIG_EXT);
FileUtil.writeToFile(TEST_INSTANT_CONFIG, module);
}
@OptionClass(alias = "preparer-inject")
public static class PreparerInject extends BaseTargetPreparer {
@Option(name = "preparer-string")
public String preparer = null;
}
@OptionClass(alias = "test-inject")
public static class TestInject implements IRemoteTest {
@Option(name = "simple-string")
public String test = null;
@Option(name = "empty-string")
public String testEmpty = null;
@Option(name = "alias-option")
public String testAlias = null;
@Option(name = "list-string")
public List<String> testList = new ArrayList<>();
@Option(name = "map-string")
public Map<String, String> testMap = new HashMap<>();
@Override
public void run(TestInformation testInfo, ITestInvocationListener listener)
throws DeviceNotAvailableException {}
}
/** Test an end-to-end injection of --module-arg. */
@Test
public void testInjectConfigOptions_moduleArgs() throws Exception {
List<String> moduleArgs = new ArrayList<>();
moduleArgs.add("module1:simple-string:value1");
moduleArgs.add("module1:empty-string:"); // value is the empty string
moduleArgs.add("module1:list-string:value2");
moduleArgs.add("module1:list-string:value3");
moduleArgs.add("module1:list-string:set-option:moreoption");
moduleArgs.add("module1:list-string:"); // value is the empty string
moduleArgs.add("module1:map-string:set-option:=moreoption");
moduleArgs.add("module1:map-string:empty-option:="); // value is the empty string
createModuleConfig("module1");
mRepo =
new SuiteModuleLoader(
new LinkedHashMap<String, List<SuiteTestFilter>>(),
new LinkedHashMap<String, List<SuiteTestFilter>>(),
new ArrayList<>(),
moduleArgs);
List<String> patterns = new ArrayList<>();
patterns.add(".*.config");
patterns.add(".*.xml");
LinkedHashMap<String, IConfiguration> res =
mRepo.loadConfigsFromDirectory(
Arrays.asList(mTestsDir), mAbis, null, null, patterns);
assertNotNull(res.get("armeabi-v7a module1"));
IConfiguration config = res.get("armeabi-v7a module1");
TestInject checker = (TestInject) config.getTests().get(0);
assertEquals("value1", checker.test);
assertEquals("", checker.testEmpty);
// Check list
assertTrue(checker.testList.size() == 4);
assertTrue(checker.testList.contains("value2"));
assertTrue(checker.testList.contains("value3"));
assertTrue(checker.testList.contains("set-option:moreoption"));
assertTrue(checker.testList.contains(""));
// Chech map
assertTrue(checker.testMap.size() == 2);
assertEquals("moreoption", checker.testMap.get("set-option"));
assertEquals("", checker.testMap.get("empty-option"));
}
/** Test an end-to-end injection of --test-arg. */
@Test
public void testInjectConfigOptions_testArgs() throws Exception {
List<String> testArgs = new ArrayList<>();
// Value for ITargetPreparer
testArgs.add(
"com.android.tradefed.testtype.suite.SuiteModuleLoaderTest$PreparerInject:"
+ "preparer-string:preparer");
// Values for IRemoteTest
testArgs.add(
"com.android.tradefed.testtype.suite.SuiteModuleLoaderTest$TestInject:"
+ "simple-string:value1");
testArgs.add(
"com.android.tradefed.testtype.suite.SuiteModuleLoaderTest$TestInject:"
+ "empty-string:"); // value is the empty string
testArgs.add(
"com.android.tradefed.testtype.suite.SuiteModuleLoaderTest$TestInject:"
+ "list-string:value2");
testArgs.add(
"com.android.tradefed.testtype.suite.SuiteModuleLoaderTest$TestInject:"
+ "list-string:value3");
testArgs.add(
"com.android.tradefed.testtype.suite.SuiteModuleLoaderTest$TestInject:"
+ "list-string:set-option:moreoption");
testArgs.add(
"com.android.tradefed.testtype.suite.SuiteModuleLoaderTest$TestInject:"
+ "list-string:"); // value is the empty string
testArgs.add(
"com.android.tradefed.testtype.suite.SuiteModuleLoaderTest$TestInject:"
+ "map-string:set-option:=moreoption");
testArgs.add(
"com.android.tradefed.testtype.suite.SuiteModuleLoaderTest$TestInject:"
+ "map-string:empty-option:="); // value is the empty string
createModuleConfig("module1");
mRepo =
new SuiteModuleLoader(
new LinkedHashMap<String, List<SuiteTestFilter>>(),
new LinkedHashMap<String, List<SuiteTestFilter>>(),
testArgs,
new ArrayList<>());
List<String> patterns = new ArrayList<>();
patterns.add(".*.config");
patterns.add(".*.xml");
LinkedHashMap<String, IConfiguration> res =
mRepo.loadConfigsFromDirectory(
Arrays.asList(mTestsDir), mAbis, null, null, patterns);
assertNotNull(res.get("armeabi-v7a module1"));
IConfiguration config = res.get("armeabi-v7a module1");
PreparerInject preparer = (PreparerInject) config.getTargetPreparers().get(0);
assertEquals("preparer", preparer.preparer);
TestInject checker = (TestInject) config.getTests().get(0);
assertEquals("value1", checker.test);
assertEquals("", checker.testEmpty);
// Check list
assertTrue(checker.testList.size() == 4);
assertTrue(checker.testList.contains("value2"));
assertTrue(checker.testList.contains("value3"));
assertTrue(checker.testList.contains("set-option:moreoption"));
assertTrue(checker.testList.contains(""));
// Chech map
assertTrue(checker.testMap.size() == 2);
assertEquals("moreoption", checker.testMap.get("set-option"));
assertEquals("", checker.testMap.get("empty-option"));
}
@Test
public void testInjectConfigOptions_moduleArgs_alias() throws Exception {
List<String> moduleArgs = new ArrayList<>();
moduleArgs.add("module1:{test-inject}alias-option:value1");
createModuleConfig("module1");
mRepo =
new SuiteModuleLoader(
new LinkedHashMap<String, List<SuiteTestFilter>>(),
new LinkedHashMap<String, List<SuiteTestFilter>>(),
new ArrayList<>(),
moduleArgs);
List<String> patterns = new ArrayList<>();
patterns.add(".*.config");
patterns.add(".*.xml");
LinkedHashMap<String, IConfiguration> res =
mRepo.loadConfigsFromDirectory(
Arrays.asList(mTestsDir), mAbis, null, null, patterns);
assertNotNull(res.get("armeabi-v7a module1"));
IConfiguration config = res.get("armeabi-v7a module1");
TestInject checker = (TestInject) config.getTests().get(0);
assertEquals("value1", checker.testAlias);
}
/**
* Test that if the base module is excluded in full, the filters of parameterized modules are
* still populated with the proper filters.
*/
@Test
public void testFilterParameterized() throws Exception {
Map<String, List<SuiteTestFilter>> excludeFilters = new LinkedHashMap<>();
createInstantModuleConfig("basemodule");
SuiteTestFilter fullFilter = SuiteTestFilter.createFrom("armeabi-v7a basemodule");
excludeFilters.put("armeabi-v7a basemodule", Arrays.asList(fullFilter));
SuiteTestFilter instantMethodFilter =
SuiteTestFilter.createFrom(
"armeabi-v7a basemodule[instant] NativeDnsAsyncTest#Async_Cancel");
excludeFilters.put("armeabi-v7a basemodule[instant]", Arrays.asList(instantMethodFilter));
mRepo =
new SuiteModuleLoader(
new LinkedHashMap<String, List<SuiteTestFilter>>(),
excludeFilters,
new ArrayList<>(),
new ArrayList<>());
mRepo.setParameterizedModules(true);
List<String> patterns = new ArrayList<>();
patterns.add(".*.config");
patterns.add(".*.xml");
LinkedHashMap<String, IConfiguration> res =
mRepo.loadConfigsFromDirectory(
Arrays.asList(mTestsDir), mAbis, null, null, patterns);
assertEquals(1, res.size());
// Full module was excluded completely
IConfiguration instantModule = res.get("armeabi-v7a basemodule[instant]");
assertNotNull(instantModule);
TestSuiteStub stubTest = (TestSuiteStub) instantModule.getTests().get(0);
assertEquals(1, stubTest.getExcludeFilters().size());
assertEquals(
"NativeDnsAsyncTest#Async_Cancel", stubTest.getExcludeFilters().iterator().next());
// Ensure that appropriate metadata are set on the module config descriptor
ConfigurationDescriptor descriptor = instantModule.getConfigurationDescription();
assertEquals(
1,
descriptor
.getAllMetaData()
.get(ConfigurationDescriptor.ACTIVE_PARAMETER_KEY)
.size());
assertEquals(
"instant",
descriptor
.getAllMetaData()
.getUniqueMap()
.get(ConfigurationDescriptor.ACTIVE_PARAMETER_KEY));
assertEquals("armeabi-v7a", descriptor.getAbi().getName());
}
/**
* 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"));
}
}