1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.compatibility.common.tradefed.testtype; 18 19 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; 20 import com.android.compatibility.common.tradefed.testtype.ModuleRepo.ConfigFilter; 21 import com.android.tradefed.build.IBuildInfo; 22 import com.android.tradefed.config.Configuration; 23 import com.android.tradefed.config.ConfigurationDescriptor; 24 import com.android.tradefed.config.IConfiguration; 25 import com.android.tradefed.config.Option; 26 import com.android.tradefed.device.DeviceNotAvailableException; 27 import com.android.tradefed.result.ITestInvocationListener; 28 import com.android.tradefed.targetprep.ITargetPreparer; 29 import com.android.tradefed.testtype.Abi; 30 import com.android.tradefed.testtype.IAbi; 31 import com.android.tradefed.testtype.IAbiReceiver; 32 import com.android.tradefed.testtype.IRemoteTest; 33 import com.android.tradefed.testtype.IRuntimeHintProvider; 34 import com.android.tradefed.testtype.ITestCollector; 35 import com.android.tradefed.testtype.ITestFilterReceiver; 36 import com.android.tradefed.util.AbiUtils; 37 import com.android.tradefed.util.FileUtil; 38 import com.android.tradefed.util.MultiMap; 39 40 import junit.framework.TestCase; 41 42 import org.easymock.EasyMock; 43 44 import java.io.File; 45 import java.io.IOException; 46 import java.util.ArrayList; 47 import java.util.Arrays; 48 import java.util.Collections; 49 import java.util.HashMap; 50 import java.util.HashSet; 51 import java.util.LinkedHashSet; 52 import java.util.List; 53 import java.util.Map; 54 import java.util.Set; 55 56 /** 57 * Unit Tests for {@link ModuleRepo} 58 */ 59 public class ModuleRepoTest extends TestCase { 60 61 private static final String TOKEN = 62 "<target_preparer class=\"com.android.compatibility.common.tradefed.targetprep.TokenRequirement\">\n" 63 + "<option name=\"token\" value=\"%s\" />\n" 64 + "</target_preparer>\n"; 65 private static final String CONFIG = 66 "<configuration description=\"Auto Generated File\">\n" + 67 "%s" + 68 "<test class=\"com.android.compatibility.common.tradefed.testtype.%s\">\n" + 69 "<option name=\"module\" value=\"%s\" />" + 70 "</test>\n" + 71 "</configuration>"; 72 private static final String FOOBAR_TOKEN = "foobar"; 73 private static final String SERIAL1 = "abc"; 74 private static final String SERIAL2 = "def"; 75 private static final String SERIAL3 = "ghi"; 76 private static final Set<String> SERIALS = new HashSet<>(); 77 private static final Set<IAbi> ABIS = new LinkedHashSet<>(); 78 private static final List<String> DEVICE_TOKENS = new ArrayList<>(); 79 private static final List<String> TEST_ARGS= new ArrayList<>(); 80 private static final List<String> MODULE_ARGS = new ArrayList<>(); 81 private static final Set<String> INCLUDES = new HashSet<>(); 82 private static final Set<String> EXCLUDES = new HashSet<>(); 83 private static final MultiMap<String, String> METADATA_INCLUDES = new MultiMap<>(); 84 private static final MultiMap<String, String> METADATA_EXCLUDES = new MultiMap<>(); 85 private static final Set<String> FILES = new HashSet<>(); 86 private static final String FILENAME = "%s.config"; 87 private static final String ROOT_DIR_ATTR = "ROOT_DIR"; 88 private static final String SUITE_NAME_ATTR = "SUITE_NAME"; 89 private static final String START_TIME_MS_ATTR = "START_TIME_MS"; 90 private static final String ABI_32 = "armeabi-v7a"; 91 private static final String ABI_64 = "arm64-v8a"; 92 private static final String MODULE_NAME_A = "FooModuleA"; 93 private static final String MODULE_NAME_B = "FooModuleB"; 94 private static final String MODULE_NAME_C = "FooModuleC"; 95 private static final String NON_EXISTS_MODULE_NAME = "NonExistModule"; 96 private static final String ID_A_32 = AbiUtils.createId(ABI_32, MODULE_NAME_A); 97 private static final String ID_A_64 = AbiUtils.createId(ABI_64, MODULE_NAME_A); 98 private static final String ID_B_32 = AbiUtils.createId(ABI_32, MODULE_NAME_B); 99 private static final String ID_B_64 = AbiUtils.createId(ABI_64, MODULE_NAME_B); 100 private static final String ID_C_32 = AbiUtils.createId(ABI_32, MODULE_NAME_C); 101 private static final String ID_C_64 = AbiUtils.createId(ABI_64, MODULE_NAME_C); 102 private static final String TEST_ARG = TestStub.class.getName() + ":foo:bar"; 103 private static final String MODULE_ARG = "%s:blah:foobar"; 104 private static final String TEST_STUB = "TestStub"; // Trivial test stub 105 private static final String SHARDABLE_TEST_STUB = "ShardableTestStub"; // Shardable and IBuildReceiver 106 private static final String [] EXPECTED_MODULE_IDS = new String[] { 107 "arm64-v8a FooModuleB", 108 "arm64-v8a FooModuleC", 109 "armeabi-v7a FooModuleA", 110 "arm64-v8a FooModuleA", 111 "armeabi-v7a FooModuleC", 112 "armeabi-v7a FooModuleB" 113 }; 114 115 static { 116 SERIALS.add(SERIAL1); 117 SERIALS.add(SERIAL2); 118 SERIALS.add(SERIAL3); ABIS.add(new Abi(ABI_32, "32"))119 ABIS.add(new Abi(ABI_32, "32")); ABIS.add(new Abi(ABI_64, "64"))120 ABIS.add(new Abi(ABI_64, "64")); 121 DEVICE_TOKENS.add(String.format("%s:%s", SERIAL3, FOOBAR_TOKEN)); 122 TEST_ARGS.add(TEST_ARG); String.format(MODULE_ARG, MODULE_NAME_A)123 MODULE_ARGS.add(String.format(MODULE_ARG, MODULE_NAME_A)); String.format(MODULE_ARG, MODULE_NAME_B)124 MODULE_ARGS.add(String.format(MODULE_ARG, MODULE_NAME_B)); String.format(MODULE_ARG, MODULE_NAME_C)125 MODULE_ARGS.add(String.format(MODULE_ARG, MODULE_NAME_C)); String.format(FILENAME, MODULE_NAME_A)126 FILES.add(String.format(FILENAME, MODULE_NAME_A)); String.format(FILENAME, MODULE_NAME_B)127 FILES.add(String.format(FILENAME, MODULE_NAME_B)); String.format(FILENAME, MODULE_NAME_C)128 FILES.add(String.format(FILENAME, MODULE_NAME_C)); 129 } 130 private ModuleRepo mRepo; 131 private File mTestsDir; 132 private File mRootDir; 133 private IBuildInfo mMockBuildInfo; 134 135 @Override setUp()136 public void setUp() throws Exception { 137 mTestsDir = setUpConfigs(); 138 mRepo = new ModuleRepo(); 139 mMockBuildInfo = EasyMock.createMock(IBuildInfo.class); 140 // Flesh out the result directory structure so ModuleRepo can write to the test runs file 141 mRootDir = FileUtil.createTempDir("root"); 142 File subRootDir = new File(mRootDir, String.format("android-suite")); 143 File resultsDir = new File(subRootDir, "results"); 144 File resultDir = new File(resultsDir, CompatibilityBuildHelper.getDirSuffix(0)); 145 resultDir.mkdirs(); 146 147 Map<String, String> mockBuildInfoMap = new HashMap<String, String>(); 148 mockBuildInfoMap.put(ROOT_DIR_ATTR, mRootDir.getAbsolutePath()); 149 mockBuildInfoMap.put(SUITE_NAME_ATTR, "suite"); 150 mockBuildInfoMap.put(START_TIME_MS_ATTR, Long.toString(0)); 151 EasyMock.expect(mMockBuildInfo.getBuildAttributes()).andReturn(mockBuildInfoMap).anyTimes(); 152 EasyMock.replay(mMockBuildInfo); 153 } 154 setUpConfigs()155 private File setUpConfigs() throws IOException { 156 File testsDir = FileUtil.createTempDir("testcases"); 157 createConfig(testsDir, MODULE_NAME_A, null); 158 createConfig(testsDir, MODULE_NAME_B, null); 159 createConfig(testsDir, MODULE_NAME_C, FOOBAR_TOKEN); 160 return testsDir; 161 } 162 createConfig(File testsDir, String name, String token)163 private void createConfig(File testsDir, String name, String token) throws IOException { 164 createConfig(testsDir, name, token, TEST_STUB); 165 } 166 createConfig(File testsDir, String name, String token, String moduleClass)167 private void createConfig(File testsDir, String name, String token, String moduleClass) 168 throws IOException { 169 File config = new File(testsDir, String.format(FILENAME, name)); 170 if (!config.createNewFile()) { 171 throw new IOException(String.format("Failed to create '%s'", config.getAbsolutePath())); 172 } 173 String preparer = ""; 174 if (token != null) { 175 preparer = String.format(TOKEN, token); 176 } 177 FileUtil.writeToFile(String.format(CONFIG, preparer, moduleClass, name), config); 178 } 179 180 @Override tearDown()181 public void tearDown() throws Exception { 182 FileUtil.recursiveDelete(mTestsDir); 183 tearDownConfigs(mTestsDir); 184 tearDownConfigs(mRootDir); 185 } 186 tearDownConfigs(File testsDir)187 private void tearDownConfigs(File testsDir) { 188 FileUtil.recursiveDelete(testsDir); 189 } 190 testInitialization()191 public void testInitialization() throws Exception { 192 mRepo.initialize(3, null, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, MODULE_ARGS, INCLUDES, 193 EXCLUDES, METADATA_INCLUDES, METADATA_EXCLUDES, mMockBuildInfo); 194 assertTrue("Should be initialized", mRepo.isInitialized()); 195 assertEquals("Wrong number of shards", 3, mRepo.getNumberOfShards()); 196 Map<String, Set<String>> deviceTokens = mRepo.getDeviceTokens(); 197 assertEquals("Wrong number of devices with tokens", 1, deviceTokens.size()); 198 Set<String> tokens = deviceTokens.get(SERIAL3); 199 assertEquals("Wrong number of tokens", 1, tokens.size()); 200 assertTrue("Unexpected device token", tokens.contains(FOOBAR_TOKEN)); 201 assertEquals("Wrong number of modules", 4, mRepo.getNonTokenModules().size()); 202 List<IModuleDef> tokenModules = mRepo.getTokenModules(); 203 assertEquals("Wrong number of modules with tokens", 2, tokenModules.size()); 204 } 205 testGetModules()206 public void testGetModules() throws Exception { 207 mRepo.initialize(1, null, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, MODULE_ARGS, INCLUDES, 208 EXCLUDES, METADATA_INCLUDES, METADATA_EXCLUDES, mMockBuildInfo); 209 assertTrue("Should be initialized", mRepo.isInitialized()); 210 assertEquals("Wrong number of tokens", 2, mRepo.getTokenModules().size()); 211 assertEquals("Wrong number of tokens", 4, mRepo.getNonTokenModules().size()); 212 } 213 214 /** 215 * Test sharding with 2 shards of the 4 non token modules. 216 */ testGetModulesSharded()217 public void testGetModulesSharded() throws Exception { 218 mRepo.initialize(2, null, mTestsDir, ABIS, new ArrayList<String>(), TEST_ARGS, MODULE_ARGS, 219 INCLUDES, EXCLUDES, METADATA_INCLUDES, METADATA_EXCLUDES, mMockBuildInfo); 220 assertTrue("Should be initialized", mRepo.isInitialized()); 221 assertEquals("Wrong number of tokens", 2, mRepo.getTokenModules().size()); 222 assertEquals("Wrong number of tokens", 4, mRepo.getNonTokenModules().size()); 223 List<IModuleDef> shard1 = mRepo.getModules(SERIAL1, 0); 224 assertEquals(2, shard1.size()); 225 assertEquals("armeabi-v7a FooModuleA", shard1.get(0).getId()); 226 assertEquals("arm64-v8a FooModuleA", shard1.get(1).getId()); 227 List<IModuleDef> shard2 = mRepo.getModules(SERIAL2, 1); 228 // last shard gets the token modules too 229 assertEquals(4, shard2.size()); 230 assertEquals("armeabi-v7a FooModuleB", shard2.get(0).getId()); 231 assertEquals("arm64-v8a FooModuleB", shard2.get(1).getId()); 232 } 233 234 /** 235 * Test running with only token modules. 236 */ testGetModules_onlyTokenModules()237 public void testGetModules_onlyTokenModules() throws Exception { 238 Set<String> includes = new HashSet<>(); 239 includes.add(MODULE_NAME_C); 240 mRepo.initialize(1, null, mTestsDir, ABIS, new ArrayList<String>(), TEST_ARGS, MODULE_ARGS, 241 includes, EXCLUDES, METADATA_INCLUDES, METADATA_EXCLUDES, mMockBuildInfo); 242 assertTrue("Should be initialized", mRepo.isInitialized()); 243 assertEquals("Wrong number of tokens", 2, mRepo.getTokenModules().size()); 244 assertEquals("Wrong number of tokens", 0, mRepo.getNonTokenModules().size()); 245 List<IModuleDef> modules = mRepo.getModules(SERIAL1, 0); 246 assertNotNull(modules); 247 assertEquals(2, modules.size()); 248 } 249 250 /** 251 * Test running with only token modules, with sharded local run, we specify a token module 252 * for each device, tests should go in the right place. 253 */ testGetModules_TokenModules_multiDevices()254 public void testGetModules_TokenModules_multiDevices() throws Exception { 255 createConfig(mTestsDir, "FooModuleD", "foobar2"); 256 Set<String> includes = new HashSet<>(); 257 includes.add(MODULE_NAME_C); 258 includes.add("FooModuleD"); 259 List<String> tokens = new ArrayList<>(); 260 tokens.add(String.format("%s:%s", SERIAL1, FOOBAR_TOKEN)); 261 tokens.add(String.format("%s:%s", SERIAL2, "foobar2")); 262 mRepo.initialize(2, null, mTestsDir, ABIS, tokens, TEST_ARGS, MODULE_ARGS, 263 includes, EXCLUDES, METADATA_INCLUDES, METADATA_EXCLUDES, mMockBuildInfo); 264 assertTrue("Should be initialized", mRepo.isInitialized()); 265 assertEquals("Wrong number of tokens", 4, mRepo.getTokenModules().size()); 266 assertEquals("Wrong number of tokens", 0, mRepo.getNonTokenModules().size()); 267 List<IModuleDef> modules1 = mRepo.getModules(SERIAL1, 0); 268 assertNotNull(modules1); 269 assertEquals(2, modules1.size()); 270 // Only module C tokens with serial 1. 271 assertTrue(modules1.get(0).getId().contains(MODULE_NAME_C)); 272 assertTrue(modules1.get(1).getId().contains(MODULE_NAME_C)); 273 List<IModuleDef> modules2 = mRepo.getModules(SERIAL2, 1); 274 assertNotNull(modules2); 275 assertEquals(2, modules2.size()); 276 assertTrue(modules2.get(0).getId().contains("FooModuleD")); 277 assertTrue(modules2.get(1).getId().contains("FooModuleD")); 278 } 279 280 /** 281 * Test sharding with 4 shards of the 6 non token modules + 2 token modules. 282 */ testGetModulesSharded_uneven()283 public void testGetModulesSharded_uneven() throws Exception { 284 createConfig(mTestsDir, "FooModuleD", null); 285 mRepo.initialize(4, null, mTestsDir, ABIS, new ArrayList<String>(), TEST_ARGS, MODULE_ARGS, 286 INCLUDES, EXCLUDES, METADATA_INCLUDES, METADATA_EXCLUDES, mMockBuildInfo); 287 assertTrue("Should be initialized", mRepo.isInitialized()); 288 assertEquals("Wrong number of tokens", 2, mRepo.getTokenModules().size()); 289 assertEquals("Wrong number of tokens", 6, mRepo.getNonTokenModules().size()); 290 291 List<IModuleDef> shard1 = mRepo.getModules(SERIAL1, 0); 292 assertEquals(1, shard1.size()); 293 assertEquals("armeabi-v7a FooModuleA", shard1.get(0).getId()); 294 295 List<IModuleDef> shard2 = mRepo.getModules(SERIAL2, 1); 296 assertEquals(1, shard2.size()); 297 assertEquals("arm64-v8a FooModuleA", shard2.get(0).getId()); 298 299 List<IModuleDef> shard3 = mRepo.getModules(SERIAL3, 2); 300 assertEquals(2, shard3.size()); 301 assertEquals("armeabi-v7a FooModuleB", shard3.get(0).getId()); 302 assertEquals("arm64-v8a FooModuleB", shard3.get(1).getId()); 303 304 List<IModuleDef> shard4 = mRepo.getModules(SERIAL2, 3); 305 assertEquals(4, shard4.size()); 306 assertEquals("armeabi-v7a FooModuleC", shard4.get(0).getId()); 307 assertEquals("arm64-v8a FooModuleC", shard4.get(1).getId()); 308 assertEquals("armeabi-v7a FooModuleD", shard4.get(2).getId()); 309 assertEquals("arm64-v8a FooModuleD", shard4.get(3).getId()); 310 } 311 testConfigFilter()312 public void testConfigFilter() throws Exception { 313 File[] configFiles = mTestsDir.listFiles(new ConfigFilter()); 314 assertEquals("Wrong number of config files found.", 3, configFiles.length); 315 for (File file : configFiles) { 316 assertTrue(String.format("Unrecognised file: %s", file.getAbsolutePath()), 317 FILES.contains(file.getName())); 318 } 319 } 320 testFiltering()321 public void testFiltering() throws Exception { 322 Set<String> includeFilters = new HashSet<>(); 323 includeFilters.add(MODULE_NAME_A); 324 Set<String> excludeFilters = new HashSet<>(); 325 excludeFilters.add(ID_A_32); 326 excludeFilters.add(MODULE_NAME_B); 327 mRepo.initialize(1, null, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, MODULE_ARGS, 328 includeFilters, excludeFilters, METADATA_INCLUDES, METADATA_EXCLUDES, 329 mMockBuildInfo); 330 List<IModuleDef> modules = mRepo.getModules(SERIAL1, 0); 331 assertEquals("Incorrect number of modules", 1, modules.size()); 332 IModuleDef module = modules.get(0); 333 assertEquals("Incorrect ID", ID_A_64, module.getId()); 334 checkArgs(module); 335 } 336 337 /** 338 * Test that excluded module shouldn't be loaded. 339 */ testInitialization_ExcludeModule_SkipLoadingConfig()340 public void testInitialization_ExcludeModule_SkipLoadingConfig() { 341 try { 342 Set<String> excludeFilters = new HashSet<String>(); 343 excludeFilters.add(NON_EXISTS_MODULE_NAME); 344 mRepo.initialize(1, null, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, 345 MODULE_ARGS, Collections.emptySet(), excludeFilters, 346 METADATA_INCLUDES, METADATA_EXCLUDES, 347 mMockBuildInfo); 348 } catch (Exception e) { 349 fail("Initialization should not fail if non-existing module is excluded"); 350 } 351 } 352 353 /** 354 * Test that {@link ModuleRepo#getModules(String, int)} handles well all module being filtered. 355 */ testFiltering_empty()356 public void testFiltering_empty() throws Exception { 357 Set<String> includeFilters = new HashSet<>(); 358 Set<String> excludeFilters = new HashSet<>(); 359 excludeFilters.add(MODULE_NAME_A); 360 excludeFilters.add(MODULE_NAME_B); 361 excludeFilters.add(MODULE_NAME_C); 362 mRepo.initialize(1, null, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, MODULE_ARGS, 363 includeFilters, excludeFilters, 364 METADATA_INCLUDES, METADATA_EXCLUDES, mMockBuildInfo); 365 List<IModuleDef> modules = mRepo.getModules(SERIAL1, 0); 366 assertEquals("Incorrect number of modules", 0, modules.size()); 367 } 368 testParsing()369 public void testParsing() throws Exception { 370 mRepo.initialize(1, null, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, MODULE_ARGS, INCLUDES, 371 EXCLUDES, METADATA_INCLUDES, METADATA_EXCLUDES, mMockBuildInfo); 372 List<IModuleDef> modules = mRepo.getModules(SERIAL3, 0); 373 Set<String> idSet = new HashSet<>(); 374 for (IModuleDef module : modules) { 375 idSet.add(module.getId()); 376 } 377 assertEquals("Incorrect number of IDs", 6, idSet.size()); 378 assertTrue("Missing ID_A_32", idSet.contains(ID_A_32)); 379 assertTrue("Missing ID_A_64", idSet.contains(ID_A_64)); 380 assertTrue("Missing ID_B_32", idSet.contains(ID_B_32)); 381 assertTrue("Missing ID_B_64", idSet.contains(ID_B_64)); 382 assertTrue("Missing ID_C_32", idSet.contains(ID_C_32)); 383 assertTrue("Missing ID_C_64", idSet.contains(ID_C_64)); 384 for (IModuleDef module : modules) { 385 checkArgs(module); 386 } 387 } 388 checkArgs(IModuleDef module)389 private void checkArgs(IModuleDef module) { 390 IRemoteTest test = module.getTest(); 391 assertTrue("Incorrect test type", test instanceof TestStub); 392 TestStub stub = (TestStub) test; 393 assertEquals("Incorrect test arg", "bar", stub.mFoo); 394 assertEquals("Incorrect module arg", "foobar", stub.mBlah); 395 } 396 testGetModuleIds()397 public void testGetModuleIds() { 398 mRepo.initialize(3, null, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, MODULE_ARGS, INCLUDES, 399 EXCLUDES, METADATA_INCLUDES, METADATA_EXCLUDES, mMockBuildInfo); 400 assertTrue("Should be initialized", mRepo.isInitialized()); 401 402 assertArrayEquals(EXPECTED_MODULE_IDS, mRepo.getModuleIds()); 403 } 404 assertArrayEquals(Object[] expected, Object[] actual)405 private void assertArrayEquals(Object[] expected, Object[] actual) { 406 assertEquals(Arrays.asList(expected), Arrays.asList(actual)); 407 } 408 409 /** 410 * Test class to provide runtimeHint. 411 */ 412 private class TestRuntime implements IRemoteTest, IRuntimeHintProvider, IAbiReceiver, 413 ITestCollector, ITestFilterReceiver { 414 public long runtimeHint = 0l; 415 @Override getRuntimeHint()416 public long getRuntimeHint() { 417 return runtimeHint; 418 } 419 // ignore all the other calls 420 @Override run(ITestInvocationListener arg0)421 public void run(ITestInvocationListener arg0) throws DeviceNotAvailableException {} 422 @Override addAllExcludeFilters(Set<String> arg0)423 public void addAllExcludeFilters(Set<String> arg0) {} 424 @Override addAllIncludeFilters(Set<String> arg0)425 public void addAllIncludeFilters(Set<String> arg0) {} 426 @Override addExcludeFilter(String arg0)427 public void addExcludeFilter(String arg0) {} 428 @Override addIncludeFilter(String arg0)429 public void addIncludeFilter(String arg0) {} 430 @Override setCollectTestsOnly(boolean arg0)431 public void setCollectTestsOnly(boolean arg0) {} 432 @Override setAbi(IAbi arg0)433 public void setAbi(IAbi arg0) {} 434 @Override getAbi()435 public IAbi getAbi() {return null;} 436 @Override getIncludeFilters()437 public Set<String> getIncludeFilters() { 438 return null; 439 } 440 @Override getExcludeFilters()441 public Set<String> getExcludeFilters() { 442 return null; 443 } 444 @Override clearIncludeFilters()445 public void clearIncludeFilters() {} 446 @Override clearExcludeFilters()447 public void clearExcludeFilters() {} 448 } 449 450 /** 451 * Balance the load of runtime of the modules for the same runtimehint everywhere. 452 */ testGetshard_allSameRuntime()453 public void testGetshard_allSameRuntime() throws Exception { 454 List<IModuleDef> testList = new ArrayList<>(); 455 TestRuntime test1 = new TestRuntime(); 456 test1.runtimeHint = 100l; 457 IModuleDef mod1 = new ModuleDef("test1", new Abi("arm", "32"), test1, 458 new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()); 459 testList.add(mod1); 460 TestRuntime test2 = new TestRuntime(); 461 test2.runtimeHint = 100l; 462 IModuleDef mod2 = new ModuleDef("test2", new Abi("arm", "32"), test2, 463 new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()); 464 testList.add(mod2); 465 TestRuntime test3 = new TestRuntime(); 466 test3.runtimeHint = 100l; 467 IModuleDef mod3 = new ModuleDef("test3", new Abi("arm", "32"), test3, 468 new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()); 469 testList.add(mod3); 470 TestRuntime test4 = new TestRuntime(); 471 test4.runtimeHint = 100l; 472 IModuleDef mod4 = new ModuleDef("test4", new Abi("arm", "32"), test4, 473 new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()); 474 testList.add(mod4); 475 // if we don't shard everything is in one shard. 476 List<IModuleDef> res = mRepo.getShard(testList, 0, 1); 477 assertEquals(4, res.size()); 478 res = mRepo.getShard(testList, 0, 2); 479 assertEquals(2, res.size()); 480 assertEquals(mod1, res.get(0)); 481 assertEquals(mod2, res.get(1)); 482 res = mRepo.getShard(testList, 1, 2); 483 assertEquals(2, res.size()); 484 assertEquals(mod3, res.get(0)); 485 assertEquals(mod4, res.get(1)); 486 } 487 488 /** 489 * When reaching splitting time, we need to ensure that even after best effort, if we cannot 490 * split into the requested number of shardIndex, we simply return null to report an empty 491 * shard. 492 */ testGetShard_cannotSplitMore()493 public void testGetShard_cannotSplitMore() { 494 List<IModuleDef> testList = new ArrayList<>(); 495 TestRuntime test1 = new TestRuntime(); 496 test1.runtimeHint = 100l; 497 IModuleDef mod1 = new ModuleDef("test1", new Abi("arm", "32"), test1, 498 new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()); 499 testList.add(mod1); 500 List<IModuleDef> res = mRepo.getShard(testList, 1, 2); 501 assertNull(res); 502 } 503 504 /** 505 * When there are no metadata based filters specified, config should be included 506 * @throws Exception 507 */ testMetadataFilter_emptyFilters()508 public void testMetadataFilter_emptyFilters() throws Exception { 509 IConfiguration config = new Configuration("foo", "bar"); 510 assertTrue("config not included when metadata filters are empty", 511 mRepo.filterByConfigMetadata(config, METADATA_INCLUDES, METADATA_EXCLUDES)); 512 } 513 514 /** 515 * When inclusion filter is specified, config matching the filter is included 516 * @throws Exception 517 */ testMetadataFilter_matchInclude()518 public void testMetadataFilter_matchInclude() throws Exception { 519 IConfiguration config = new Configuration("foo", "bar"); 520 ConfigurationDescriptor desc = config.getConfigurationDescription(); 521 MultiMap<String, String> metadata = new MultiMap<>(); 522 metadata.put("component", "foo"); 523 desc.setMetaData(metadata); 524 MultiMap<String, String> includeFilter = new MultiMap<>(); 525 includeFilter.put("component", "foo"); 526 assertTrue("config not included with matching inclusion filter", 527 mRepo.filterByConfigMetadata(config, includeFilter, METADATA_EXCLUDES)); 528 } 529 530 /** 531 * When inclusion filter is specified, config not matching the filter is excluded 532 * @throws Exception 533 */ testMetadataFilter_noMatchInclude_mismatchValue()534 public void testMetadataFilter_noMatchInclude_mismatchValue() throws Exception { 535 IConfiguration config = new Configuration("foo", "bar"); 536 ConfigurationDescriptor desc = config.getConfigurationDescription(); 537 MultiMap<String, String> metadata = new MultiMap<>(); 538 metadata.put("component", "foo"); 539 desc.setMetaData(metadata); 540 MultiMap<String, String> includeFilter = new MultiMap<>(); 541 includeFilter.put("component", "bar"); 542 assertFalse("config not excluded with mismatching inclusion filter", 543 mRepo.filterByConfigMetadata(config, includeFilter, METADATA_EXCLUDES)); 544 } 545 546 /** 547 * When inclusion filter is specified, config not matching the filter is excluded 548 * @throws Exception 549 */ testMetadataFilter_noMatchInclude_mismatchKey()550 public void testMetadataFilter_noMatchInclude_mismatchKey() throws Exception { 551 IConfiguration config = new Configuration("foo", "bar"); 552 ConfigurationDescriptor desc = config.getConfigurationDescription(); 553 MultiMap<String, String> metadata = new MultiMap<>(); 554 metadata.put("component", "foo"); 555 desc.setMetaData(metadata); 556 MultiMap<String, String> includeFilter = new MultiMap<>(); 557 includeFilter.put("group", "bar"); 558 assertFalse("config not excluded with mismatching inclusion filter", 559 mRepo.filterByConfigMetadata(config, includeFilter, METADATA_EXCLUDES)); 560 } 561 562 /** 563 * When exclusion filter is specified, config matching the filter is excluded 564 * @throws Exception 565 */ testMetadataFilter_matchExclude()566 public void testMetadataFilter_matchExclude() throws Exception { 567 IConfiguration config = new Configuration("foo", "bar"); 568 ConfigurationDescriptor desc = config.getConfigurationDescription(); 569 MultiMap<String, String> metadata = new MultiMap<>(); 570 metadata.put("component", "foo"); 571 desc.setMetaData(metadata); 572 MultiMap<String, String> excludeFilter = new MultiMap<>(); 573 excludeFilter.put("component", "foo"); 574 assertFalse("config not excluded with matching exclusion filter", 575 mRepo.filterByConfigMetadata(config, METADATA_INCLUDES, excludeFilter)); 576 } 577 578 /** 579 * When exclusion filter is specified, config not matching the filter is included 580 * @throws Exception 581 */ testMetadataFilter_noMatchExclude_mismatchKey()582 public void testMetadataFilter_noMatchExclude_mismatchKey() throws Exception { 583 IConfiguration config = new Configuration("foo", "bar"); 584 ConfigurationDescriptor desc = config.getConfigurationDescription(); 585 MultiMap<String, String> metadata = new MultiMap<>(); 586 metadata.put("component", "foo"); 587 desc.setMetaData(metadata); 588 MultiMap<String, String> excludeFilter = new MultiMap<>(); 589 excludeFilter.put("component", "bar"); 590 assertTrue("config not included with mismatching exclusion filter", 591 mRepo.filterByConfigMetadata(config, METADATA_INCLUDES, excludeFilter)); 592 } 593 594 /** 595 * When exclusion filter is specified, config not matching the filter is included 596 * @throws Exception 597 */ testMetadataFilter_noMatchExclude_mismatchValue()598 public void testMetadataFilter_noMatchExclude_mismatchValue() throws Exception { 599 IConfiguration config = new Configuration("foo", "bar"); 600 ConfigurationDescriptor desc = config.getConfigurationDescription(); 601 MultiMap<String, String> metadata = new MultiMap<>(); 602 metadata.put("component", "foo"); 603 desc.setMetaData(metadata); 604 MultiMap<String, String> excludeFilter = new MultiMap<>(); 605 excludeFilter.put("group", "bar"); 606 assertTrue("config not included with mismatching exclusion filter", 607 mRepo.filterByConfigMetadata(config, METADATA_INCLUDES, excludeFilter)); 608 } 609 610 /** 611 * When inclusion filter is specified, config with one of the metadata field matching the filter 612 * is included 613 * @throws Exception 614 */ testMetadataFilter_matchInclude_multipleMetadataField()615 public void testMetadataFilter_matchInclude_multipleMetadataField() throws Exception { 616 IConfiguration config = new Configuration("foo", "bar"); 617 ConfigurationDescriptor desc = config.getConfigurationDescription(); 618 MultiMap<String, String> metadata = new MultiMap<>(); 619 metadata.put("component", "foo"); 620 metadata.put("component", "bar"); 621 desc.setMetaData(metadata); 622 MultiMap<String, String> includeFilter = new MultiMap<>(); 623 includeFilter.put("component", "foo"); 624 assertTrue("config not included with matching inclusion filter", 625 mRepo.filterByConfigMetadata(config, includeFilter, METADATA_EXCLUDES)); 626 } 627 628 /** 629 * When exclusion filter is specified, config with one of the metadata field matching the filter 630 * is excluded 631 * @throws Exception 632 */ testMetadataFilter_matchExclude_multipleMetadataField()633 public void testMetadataFilter_matchExclude_multipleMetadataField() throws Exception { 634 IConfiguration config = new Configuration("foo", "bar"); 635 ConfigurationDescriptor desc = config.getConfigurationDescription(); 636 MultiMap<String, String> metadata = new MultiMap<>(); 637 metadata.put("component", "foo"); 638 metadata.put("component", "bar"); 639 desc.setMetaData(metadata); 640 MultiMap<String, String> excludeFilter = new MultiMap<>(); 641 excludeFilter.put("component", "foo"); 642 assertFalse("config not excluded with matching exclusion filter", 643 mRepo.filterByConfigMetadata(config, METADATA_INCLUDES, excludeFilter)); 644 } 645 646 /** 647 * When inclusion filters are specified, config with metadata field matching one of the filter 648 * is included 649 * @throws Exception 650 */ testMetadataFilter_matchInclude_multipleFilters()651 public void testMetadataFilter_matchInclude_multipleFilters() throws Exception { 652 IConfiguration config = new Configuration("foo", "bar"); 653 ConfigurationDescriptor desc = config.getConfigurationDescription(); 654 MultiMap<String, String> metadata = new MultiMap<>(); 655 metadata.put("component", "foo"); 656 desc.setMetaData(metadata); 657 MultiMap<String, String> includeFilter = new MultiMap<>(); 658 includeFilter.put("component", "foo"); 659 includeFilter.put("component", "bar"); 660 assertTrue("config not included with matching inclusion filter", 661 mRepo.filterByConfigMetadata(config, includeFilter, METADATA_EXCLUDES)); 662 } 663 664 /** 665 * When exclusion filters are specified, config with metadata field matching one of the filter 666 * is excluded 667 * @throws Exception 668 */ testMetadataFilter_matchExclude_multipleFilters()669 public void testMetadataFilter_matchExclude_multipleFilters() throws Exception { 670 IConfiguration config = new Configuration("foo", "bar"); 671 ConfigurationDescriptor desc = config.getConfigurationDescription(); 672 MultiMap<String, String> metadata = new MultiMap<>(); 673 metadata.put("component", "foo"); 674 desc.setMetaData(metadata); 675 MultiMap<String, String> excludeFilter = new MultiMap<>(); 676 excludeFilter.put("component", "foo"); 677 excludeFilter.put("component", "bar"); 678 assertFalse("config not excluded with matching exclusion filter", 679 mRepo.filterByConfigMetadata(config, METADATA_INCLUDES, excludeFilter)); 680 } 681 682 /** 683 * When inclusion filters are specified, config with metadata field matching one of the filter 684 * is included 685 * @throws Exception 686 */ testMetadataFilter_matchInclude_multipleMetadataAndFilters()687 public void testMetadataFilter_matchInclude_multipleMetadataAndFilters() throws Exception { 688 IConfiguration config = new Configuration("foo", "bar"); 689 ConfigurationDescriptor desc = config.getConfigurationDescription(); 690 MultiMap<String, String> metadata = new MultiMap<>(); 691 metadata.put("component", "foo1"); 692 metadata.put("group", "bar1"); 693 desc.setMetaData(metadata); 694 MultiMap<String, String> includeFilter = new MultiMap<>(); 695 includeFilter.put("component", "foo1"); 696 includeFilter.put("group", "bar2"); 697 assertTrue("config not included with matching inclusion filter", 698 mRepo.filterByConfigMetadata(config, includeFilter, METADATA_EXCLUDES)); 699 } 700 701 /** 702 * When exclusion filters are specified, config with metadata field matching one of the filter 703 * is excluded 704 * @throws Exception 705 */ testMetadataFilter_matchExclude_multipleMetadataAndFilters()706 public void testMetadataFilter_matchExclude_multipleMetadataAndFilters() throws Exception { 707 IConfiguration config = new Configuration("foo", "bar"); 708 ConfigurationDescriptor desc = config.getConfigurationDescription(); 709 MultiMap<String, String> metadata = new MultiMap<>(); 710 metadata.put("component", "foo1"); 711 metadata.put("group", "bar1"); 712 desc.setMetaData(metadata); 713 MultiMap<String, String> excludeFilter = new MultiMap<>(); 714 excludeFilter.put("component", "foo1"); 715 excludeFilter.put("group", "bar2"); 716 assertFalse("config not excluded with matching exclusion filter", 717 mRepo.filterByConfigMetadata(config, METADATA_INCLUDES, excludeFilter)); 718 } 719 720 /** 721 * When inclusion and exclusion filters are both specified, config can pass through the filters 722 * as expected. 723 * @throws Exception 724 */ testMetadataFilter_includeAndExclude()725 public void testMetadataFilter_includeAndExclude() throws Exception { 726 IConfiguration config = new Configuration("foo", "bar"); 727 ConfigurationDescriptor desc = config.getConfigurationDescription(); 728 MultiMap<String, String> metadata = new MultiMap<>(); 729 metadata.put("component", "foo"); 730 metadata.put("group", "bar1"); 731 desc.setMetaData(metadata); 732 MultiMap<String, String> includeFilter = new MultiMap<>(); 733 includeFilter.put("component", "foo"); 734 MultiMap<String, String> excludeFilter = new MultiMap<>(); 735 excludeFilter.put("group", "bar2"); 736 assertTrue("config not included with matching inclusion and mismatching exclusion filters", 737 mRepo.filterByConfigMetadata(config, includeFilter, excludeFilter)); 738 } 739 740 /** 741 * When inclusion and exclusion filters are both specified, config be excluded as specified 742 * @throws Exception 743 */ testMetadataFilter_includeThenExclude()744 public void testMetadataFilter_includeThenExclude() throws Exception { 745 IConfiguration config = new Configuration("foo", "bar"); 746 ConfigurationDescriptor desc = config.getConfigurationDescription(); 747 MultiMap<String, String> metadata = new MultiMap<>(); 748 metadata.put("component", "foo"); 749 metadata.put("group", "bar"); 750 desc.setMetaData(metadata); 751 MultiMap<String, String> includeFilter = new MultiMap<>(); 752 includeFilter.put("component", "foo"); 753 MultiMap<String, String> excludeFilter = new MultiMap<>(); 754 excludeFilter.put("group", "bar"); 755 assertFalse("config not excluded with matching inclusion and exclusion filters", 756 mRepo.filterByConfigMetadata(config, includeFilter, excludeFilter)); 757 } 758 759 public static class TestInject implements IRemoteTest { 760 @Option(name = "simple-string") 761 public String test = null; 762 @Option(name = "list-string") 763 public List<String> testList = new ArrayList<>(); 764 @Option(name = "map-string") 765 public Map<String, String> testMap = new HashMap<>(); 766 767 @Override run(ITestInvocationListener listener)768 public void run(ITestInvocationListener listener) throws DeviceNotAvailableException { 769 } 770 } 771 772 /** 773 * Test that the different format for module-arg and test-arg can properly be passed to the 774 * configuration. 775 */ testInjectConfig()776 public void testInjectConfig() throws Exception { 777 IConfiguration config = new Configuration("foo", "bar"); 778 TestInject checker = new TestInject(); 779 config.setTest(checker); 780 Map<String, List<String>> optionMap = new HashMap<String, List<String>>(); 781 List<String> option1 = new ArrayList<>(); 782 option1.add("value1"); 783 optionMap.put("simple-string", option1); 784 785 List<String> option2 = new ArrayList<>(); 786 option2.add("value2"); 787 option2.add("value3"); 788 option2.add("set-option:moreoption"); 789 optionMap.put("list-string", option2); 790 791 List<String> option3 = new ArrayList<>(); 792 option3.add("set-option:=moreoption"); 793 optionMap.put("map-string", option3); 794 795 mRepo.injectOptionsToConfig(optionMap, config); 796 797 assertEquals("value1", checker.test); 798 assertEquals(option2, checker.testList); 799 Map<String, String> resMap = new HashMap<>(); 800 resMap.put("set-option", "moreoption"); 801 assertEquals(resMap, checker.testMap); 802 } 803 } 804