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 /** Test that excluded module shouldn't be loaded. */ testInitialization_ExcludeModule_SkipLoadingConfig()338 public void testInitialization_ExcludeModule_SkipLoadingConfig() throws Exception { 339 Set<String> excludeFilters = new HashSet<String>(); 340 excludeFilters.add(NON_EXISTS_MODULE_NAME); 341 mRepo.initialize( 342 1, 343 null, 344 mTestsDir, 345 ABIS, 346 DEVICE_TOKENS, 347 TEST_ARGS, 348 MODULE_ARGS, 349 Collections.emptySet(), 350 excludeFilters, 351 METADATA_INCLUDES, 352 METADATA_EXCLUDES, 353 mMockBuildInfo); 354 } 355 356 /** 357 * Test that {@link ModuleRepo#getModules(String, int)} handles well all module being filtered. 358 */ testFiltering_empty()359 public void testFiltering_empty() throws Exception { 360 Set<String> includeFilters = new HashSet<>(); 361 Set<String> excludeFilters = new HashSet<>(); 362 excludeFilters.add(MODULE_NAME_A); 363 excludeFilters.add(MODULE_NAME_B); 364 excludeFilters.add(MODULE_NAME_C); 365 mRepo.initialize(1, null, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, MODULE_ARGS, 366 includeFilters, excludeFilters, 367 METADATA_INCLUDES, METADATA_EXCLUDES, mMockBuildInfo); 368 List<IModuleDef> modules = mRepo.getModules(SERIAL1, 0); 369 assertEquals("Incorrect number of modules", 0, modules.size()); 370 } 371 testParsing()372 public void testParsing() throws Exception { 373 mRepo.initialize(1, null, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, MODULE_ARGS, INCLUDES, 374 EXCLUDES, METADATA_INCLUDES, METADATA_EXCLUDES, mMockBuildInfo); 375 List<IModuleDef> modules = mRepo.getModules(SERIAL3, 0); 376 Set<String> idSet = new HashSet<>(); 377 for (IModuleDef module : modules) { 378 idSet.add(module.getId()); 379 } 380 assertEquals("Incorrect number of IDs", 6, idSet.size()); 381 assertTrue("Missing ID_A_32", idSet.contains(ID_A_32)); 382 assertTrue("Missing ID_A_64", idSet.contains(ID_A_64)); 383 assertTrue("Missing ID_B_32", idSet.contains(ID_B_32)); 384 assertTrue("Missing ID_B_64", idSet.contains(ID_B_64)); 385 assertTrue("Missing ID_C_32", idSet.contains(ID_C_32)); 386 assertTrue("Missing ID_C_64", idSet.contains(ID_C_64)); 387 for (IModuleDef module : modules) { 388 checkArgs(module); 389 } 390 } 391 checkArgs(IModuleDef module)392 private void checkArgs(IModuleDef module) { 393 IRemoteTest test = module.getTest(); 394 assertTrue("Incorrect test type", test instanceof TestStub); 395 TestStub stub = (TestStub) test; 396 assertEquals("Incorrect test arg", "bar", stub.mFoo); 397 assertEquals("Incorrect module arg", "foobar", stub.mBlah); 398 } 399 testGetModuleIds()400 public void testGetModuleIds() { 401 mRepo.initialize(3, null, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, MODULE_ARGS, INCLUDES, 402 EXCLUDES, METADATA_INCLUDES, METADATA_EXCLUDES, mMockBuildInfo); 403 assertTrue("Should be initialized", mRepo.isInitialized()); 404 405 assertArrayEquals(EXPECTED_MODULE_IDS, mRepo.getModuleIds()); 406 } 407 assertArrayEquals(Object[] expected, Object[] actual)408 private void assertArrayEquals(Object[] expected, Object[] actual) { 409 assertEquals(Arrays.asList(expected), Arrays.asList(actual)); 410 } 411 412 /** 413 * Test class to provide runtimeHint. 414 */ 415 private class TestRuntime implements IRemoteTest, IRuntimeHintProvider, IAbiReceiver, 416 ITestCollector, ITestFilterReceiver { 417 public long runtimeHint = 0l; 418 @Override getRuntimeHint()419 public long getRuntimeHint() { 420 return runtimeHint; 421 } 422 // ignore all the other calls 423 @Override run(ITestInvocationListener arg0)424 public void run(ITestInvocationListener arg0) throws DeviceNotAvailableException {} 425 @Override addAllExcludeFilters(Set<String> arg0)426 public void addAllExcludeFilters(Set<String> arg0) {} 427 @Override addAllIncludeFilters(Set<String> arg0)428 public void addAllIncludeFilters(Set<String> arg0) {} 429 @Override addExcludeFilter(String arg0)430 public void addExcludeFilter(String arg0) {} 431 @Override addIncludeFilter(String arg0)432 public void addIncludeFilter(String arg0) {} 433 @Override setCollectTestsOnly(boolean arg0)434 public void setCollectTestsOnly(boolean arg0) {} 435 @Override setAbi(IAbi arg0)436 public void setAbi(IAbi arg0) {} 437 @Override getAbi()438 public IAbi getAbi() {return null;} 439 @Override getIncludeFilters()440 public Set<String> getIncludeFilters() { 441 return null; 442 } 443 @Override getExcludeFilters()444 public Set<String> getExcludeFilters() { 445 return null; 446 } 447 @Override clearIncludeFilters()448 public void clearIncludeFilters() {} 449 @Override clearExcludeFilters()450 public void clearExcludeFilters() {} 451 } 452 453 /** 454 * Balance the load of runtime of the modules for the same runtimehint everywhere. 455 */ testGetshard_allSameRuntime()456 public void testGetshard_allSameRuntime() throws Exception { 457 List<IModuleDef> testList = new ArrayList<>(); 458 TestRuntime test1 = new TestRuntime(); 459 test1.runtimeHint = 100l; 460 IModuleDef mod1 = new ModuleDef("test1", new Abi("arm", "32"), test1, 461 new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()); 462 testList.add(mod1); 463 TestRuntime test2 = new TestRuntime(); 464 test2.runtimeHint = 100l; 465 IModuleDef mod2 = new ModuleDef("test2", new Abi("arm", "32"), test2, 466 new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()); 467 testList.add(mod2); 468 TestRuntime test3 = new TestRuntime(); 469 test3.runtimeHint = 100l; 470 IModuleDef mod3 = new ModuleDef("test3", new Abi("arm", "32"), test3, 471 new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()); 472 testList.add(mod3); 473 TestRuntime test4 = new TestRuntime(); 474 test4.runtimeHint = 100l; 475 IModuleDef mod4 = new ModuleDef("test4", new Abi("arm", "32"), test4, 476 new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()); 477 testList.add(mod4); 478 // if we don't shard everything is in one shard. 479 List<IModuleDef> res = mRepo.getShard(testList, 0, 1); 480 assertEquals(4, res.size()); 481 res = mRepo.getShard(testList, 0, 2); 482 assertEquals(2, res.size()); 483 assertEquals(mod1, res.get(0)); 484 assertEquals(mod2, res.get(1)); 485 res = mRepo.getShard(testList, 1, 2); 486 assertEquals(2, res.size()); 487 assertEquals(mod3, res.get(0)); 488 assertEquals(mod4, res.get(1)); 489 } 490 491 /** 492 * When reaching splitting time, we need to ensure that even after best effort, if we cannot 493 * split into the requested number of shardIndex, we simply return null to report an empty 494 * shard. 495 */ testGetShard_cannotSplitMore()496 public void testGetShard_cannotSplitMore() { 497 List<IModuleDef> testList = new ArrayList<>(); 498 TestRuntime test1 = new TestRuntime(); 499 test1.runtimeHint = 100l; 500 IModuleDef mod1 = new ModuleDef("test1", new Abi("arm", "32"), test1, 501 new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()); 502 testList.add(mod1); 503 List<IModuleDef> res = mRepo.getShard(testList, 1, 2); 504 assertNull(res); 505 } 506 507 /** 508 * When there are no metadata based filters specified, config should be included 509 * @throws Exception 510 */ testMetadataFilter_emptyFilters()511 public void testMetadataFilter_emptyFilters() throws Exception { 512 IConfiguration config = new Configuration("foo", "bar"); 513 assertTrue("config not included when metadata filters are empty", 514 mRepo.filterByConfigMetadata(config, METADATA_INCLUDES, METADATA_EXCLUDES)); 515 } 516 517 /** 518 * When inclusion filter is specified, config matching the filter is included 519 * @throws Exception 520 */ testMetadataFilter_matchInclude()521 public void testMetadataFilter_matchInclude() throws Exception { 522 IConfiguration config = new Configuration("foo", "bar"); 523 ConfigurationDescriptor desc = config.getConfigurationDescription(); 524 MultiMap<String, String> metadata = new MultiMap<>(); 525 metadata.put("component", "foo"); 526 desc.setMetaData(metadata); 527 MultiMap<String, String> includeFilter = new MultiMap<>(); 528 includeFilter.put("component", "foo"); 529 assertTrue("config not included with matching inclusion filter", 530 mRepo.filterByConfigMetadata(config, includeFilter, METADATA_EXCLUDES)); 531 } 532 533 /** 534 * When inclusion filter is specified, config not matching the filter is excluded 535 * @throws Exception 536 */ testMetadataFilter_noMatchInclude_mismatchValue()537 public void testMetadataFilter_noMatchInclude_mismatchValue() throws Exception { 538 IConfiguration config = new Configuration("foo", "bar"); 539 ConfigurationDescriptor desc = config.getConfigurationDescription(); 540 MultiMap<String, String> metadata = new MultiMap<>(); 541 metadata.put("component", "foo"); 542 desc.setMetaData(metadata); 543 MultiMap<String, String> includeFilter = new MultiMap<>(); 544 includeFilter.put("component", "bar"); 545 assertFalse("config not excluded with mismatching inclusion filter", 546 mRepo.filterByConfigMetadata(config, includeFilter, METADATA_EXCLUDES)); 547 } 548 549 /** 550 * When inclusion filter is specified, config not matching the filter is excluded 551 * @throws Exception 552 */ testMetadataFilter_noMatchInclude_mismatchKey()553 public void testMetadataFilter_noMatchInclude_mismatchKey() throws Exception { 554 IConfiguration config = new Configuration("foo", "bar"); 555 ConfigurationDescriptor desc = config.getConfigurationDescription(); 556 MultiMap<String, String> metadata = new MultiMap<>(); 557 metadata.put("component", "foo"); 558 desc.setMetaData(metadata); 559 MultiMap<String, String> includeFilter = new MultiMap<>(); 560 includeFilter.put("group", "bar"); 561 assertFalse("config not excluded with mismatching inclusion filter", 562 mRepo.filterByConfigMetadata(config, includeFilter, METADATA_EXCLUDES)); 563 } 564 565 /** 566 * When exclusion filter is specified, config matching the filter is excluded 567 * @throws Exception 568 */ testMetadataFilter_matchExclude()569 public void testMetadataFilter_matchExclude() throws Exception { 570 IConfiguration config = new Configuration("foo", "bar"); 571 ConfigurationDescriptor desc = config.getConfigurationDescription(); 572 MultiMap<String, String> metadata = new MultiMap<>(); 573 metadata.put("component", "foo"); 574 desc.setMetaData(metadata); 575 MultiMap<String, String> excludeFilter = new MultiMap<>(); 576 excludeFilter.put("component", "foo"); 577 assertFalse("config not excluded with matching exclusion filter", 578 mRepo.filterByConfigMetadata(config, METADATA_INCLUDES, excludeFilter)); 579 } 580 581 /** 582 * When exclusion filter is specified, config not matching the filter is included 583 * @throws Exception 584 */ testMetadataFilter_noMatchExclude_mismatchKey()585 public void testMetadataFilter_noMatchExclude_mismatchKey() throws Exception { 586 IConfiguration config = new Configuration("foo", "bar"); 587 ConfigurationDescriptor desc = config.getConfigurationDescription(); 588 MultiMap<String, String> metadata = new MultiMap<>(); 589 metadata.put("component", "foo"); 590 desc.setMetaData(metadata); 591 MultiMap<String, String> excludeFilter = new MultiMap<>(); 592 excludeFilter.put("component", "bar"); 593 assertTrue("config not included with mismatching exclusion filter", 594 mRepo.filterByConfigMetadata(config, METADATA_INCLUDES, excludeFilter)); 595 } 596 597 /** 598 * When exclusion filter is specified, config not matching the filter is included 599 * @throws Exception 600 */ testMetadataFilter_noMatchExclude_mismatchValue()601 public void testMetadataFilter_noMatchExclude_mismatchValue() throws Exception { 602 IConfiguration config = new Configuration("foo", "bar"); 603 ConfigurationDescriptor desc = config.getConfigurationDescription(); 604 MultiMap<String, String> metadata = new MultiMap<>(); 605 metadata.put("component", "foo"); 606 desc.setMetaData(metadata); 607 MultiMap<String, String> excludeFilter = new MultiMap<>(); 608 excludeFilter.put("group", "bar"); 609 assertTrue("config not included with mismatching exclusion filter", 610 mRepo.filterByConfigMetadata(config, METADATA_INCLUDES, excludeFilter)); 611 } 612 613 /** 614 * When inclusion filter is specified, config with one of the metadata field matching the filter 615 * is included 616 * @throws Exception 617 */ testMetadataFilter_matchInclude_multipleMetadataField()618 public void testMetadataFilter_matchInclude_multipleMetadataField() throws Exception { 619 IConfiguration config = new Configuration("foo", "bar"); 620 ConfigurationDescriptor desc = config.getConfigurationDescription(); 621 MultiMap<String, String> metadata = new MultiMap<>(); 622 metadata.put("component", "foo"); 623 metadata.put("component", "bar"); 624 desc.setMetaData(metadata); 625 MultiMap<String, String> includeFilter = new MultiMap<>(); 626 includeFilter.put("component", "foo"); 627 assertTrue("config not included with matching inclusion filter", 628 mRepo.filterByConfigMetadata(config, includeFilter, METADATA_EXCLUDES)); 629 } 630 631 /** 632 * When exclusion filter is specified, config with one of the metadata field matching the filter 633 * is excluded 634 * @throws Exception 635 */ testMetadataFilter_matchExclude_multipleMetadataField()636 public void testMetadataFilter_matchExclude_multipleMetadataField() throws Exception { 637 IConfiguration config = new Configuration("foo", "bar"); 638 ConfigurationDescriptor desc = config.getConfigurationDescription(); 639 MultiMap<String, String> metadata = new MultiMap<>(); 640 metadata.put("component", "foo"); 641 metadata.put("component", "bar"); 642 desc.setMetaData(metadata); 643 MultiMap<String, String> excludeFilter = new MultiMap<>(); 644 excludeFilter.put("component", "foo"); 645 assertFalse("config not excluded with matching exclusion filter", 646 mRepo.filterByConfigMetadata(config, METADATA_INCLUDES, excludeFilter)); 647 } 648 649 /** 650 * When inclusion filters are specified, config with metadata field matching one of the filter 651 * is included 652 * @throws Exception 653 */ testMetadataFilter_matchInclude_multipleFilters()654 public void testMetadataFilter_matchInclude_multipleFilters() throws Exception { 655 IConfiguration config = new Configuration("foo", "bar"); 656 ConfigurationDescriptor desc = config.getConfigurationDescription(); 657 MultiMap<String, String> metadata = new MultiMap<>(); 658 metadata.put("component", "foo"); 659 desc.setMetaData(metadata); 660 MultiMap<String, String> includeFilter = new MultiMap<>(); 661 includeFilter.put("component", "foo"); 662 includeFilter.put("component", "bar"); 663 assertTrue("config not included with matching inclusion filter", 664 mRepo.filterByConfigMetadata(config, includeFilter, METADATA_EXCLUDES)); 665 } 666 667 /** 668 * When exclusion filters are specified, config with metadata field matching one of the filter 669 * is excluded 670 * @throws Exception 671 */ testMetadataFilter_matchExclude_multipleFilters()672 public void testMetadataFilter_matchExclude_multipleFilters() throws Exception { 673 IConfiguration config = new Configuration("foo", "bar"); 674 ConfigurationDescriptor desc = config.getConfigurationDescription(); 675 MultiMap<String, String> metadata = new MultiMap<>(); 676 metadata.put("component", "foo"); 677 desc.setMetaData(metadata); 678 MultiMap<String, String> excludeFilter = new MultiMap<>(); 679 excludeFilter.put("component", "foo"); 680 excludeFilter.put("component", "bar"); 681 assertFalse("config not excluded with matching exclusion filter", 682 mRepo.filterByConfigMetadata(config, METADATA_INCLUDES, excludeFilter)); 683 } 684 685 /** 686 * When inclusion filters are specified, config with metadata field matching one of the filter 687 * is included 688 * @throws Exception 689 */ testMetadataFilter_matchInclude_multipleMetadataAndFilters()690 public void testMetadataFilter_matchInclude_multipleMetadataAndFilters() throws Exception { 691 IConfiguration config = new Configuration("foo", "bar"); 692 ConfigurationDescriptor desc = config.getConfigurationDescription(); 693 MultiMap<String, String> metadata = new MultiMap<>(); 694 metadata.put("component", "foo1"); 695 metadata.put("group", "bar1"); 696 desc.setMetaData(metadata); 697 MultiMap<String, String> includeFilter = new MultiMap<>(); 698 includeFilter.put("component", "foo1"); 699 includeFilter.put("group", "bar2"); 700 assertTrue("config not included with matching inclusion filter", 701 mRepo.filterByConfigMetadata(config, includeFilter, METADATA_EXCLUDES)); 702 } 703 704 /** 705 * When exclusion filters are specified, config with metadata field matching one of the filter 706 * is excluded 707 * @throws Exception 708 */ testMetadataFilter_matchExclude_multipleMetadataAndFilters()709 public void testMetadataFilter_matchExclude_multipleMetadataAndFilters() throws Exception { 710 IConfiguration config = new Configuration("foo", "bar"); 711 ConfigurationDescriptor desc = config.getConfigurationDescription(); 712 MultiMap<String, String> metadata = new MultiMap<>(); 713 metadata.put("component", "foo1"); 714 metadata.put("group", "bar1"); 715 desc.setMetaData(metadata); 716 MultiMap<String, String> excludeFilter = new MultiMap<>(); 717 excludeFilter.put("component", "foo1"); 718 excludeFilter.put("group", "bar2"); 719 assertFalse("config not excluded with matching exclusion filter", 720 mRepo.filterByConfigMetadata(config, METADATA_INCLUDES, excludeFilter)); 721 } 722 723 /** 724 * When inclusion and exclusion filters are both specified, config can pass through the filters 725 * as expected. 726 * @throws Exception 727 */ testMetadataFilter_includeAndExclude()728 public void testMetadataFilter_includeAndExclude() throws Exception { 729 IConfiguration config = new Configuration("foo", "bar"); 730 ConfigurationDescriptor desc = config.getConfigurationDescription(); 731 MultiMap<String, String> metadata = new MultiMap<>(); 732 metadata.put("component", "foo"); 733 metadata.put("group", "bar1"); 734 desc.setMetaData(metadata); 735 MultiMap<String, String> includeFilter = new MultiMap<>(); 736 includeFilter.put("component", "foo"); 737 MultiMap<String, String> excludeFilter = new MultiMap<>(); 738 excludeFilter.put("group", "bar2"); 739 assertTrue("config not included with matching inclusion and mismatching exclusion filters", 740 mRepo.filterByConfigMetadata(config, includeFilter, excludeFilter)); 741 } 742 743 /** 744 * When inclusion and exclusion filters are both specified, config be excluded as specified 745 * @throws Exception 746 */ testMetadataFilter_includeThenExclude()747 public void testMetadataFilter_includeThenExclude() throws Exception { 748 IConfiguration config = new Configuration("foo", "bar"); 749 ConfigurationDescriptor desc = config.getConfigurationDescription(); 750 MultiMap<String, String> metadata = new MultiMap<>(); 751 metadata.put("component", "foo"); 752 metadata.put("group", "bar"); 753 desc.setMetaData(metadata); 754 MultiMap<String, String> includeFilter = new MultiMap<>(); 755 includeFilter.put("component", "foo"); 756 MultiMap<String, String> excludeFilter = new MultiMap<>(); 757 excludeFilter.put("group", "bar"); 758 assertFalse("config not excluded with matching inclusion and exclusion filters", 759 mRepo.filterByConfigMetadata(config, includeFilter, excludeFilter)); 760 } 761 762 public static class TestInject implements IRemoteTest { 763 @Option(name = "simple-string") 764 public String test = null; 765 @Option(name = "list-string") 766 public List<String> testList = new ArrayList<>(); 767 @Option(name = "map-string") 768 public Map<String, String> testMap = new HashMap<>(); 769 770 @Override run(ITestInvocationListener listener)771 public void run(ITestInvocationListener listener) throws DeviceNotAvailableException { 772 } 773 } 774 775 /** 776 * Test that the different format for module-arg and test-arg can properly be passed to the 777 * configuration. 778 */ testInjectConfig()779 public void testInjectConfig() throws Exception { 780 IConfiguration config = new Configuration("foo", "bar"); 781 TestInject checker = new TestInject(); 782 config.setTest(checker); 783 Map<String, List<String>> optionMap = new HashMap<String, List<String>>(); 784 List<String> option1 = new ArrayList<>(); 785 option1.add("value1"); 786 optionMap.put("simple-string", option1); 787 788 List<String> option2 = new ArrayList<>(); 789 option2.add("value2"); 790 option2.add("value3"); 791 option2.add("set-option:moreoption"); 792 optionMap.put("list-string", option2); 793 794 List<String> option3 = new ArrayList<>(); 795 option3.add("set-option:=moreoption"); 796 optionMap.put("map-string", option3); 797 798 mRepo.injectOptionsToConfig(optionMap, config); 799 800 assertEquals("value1", checker.test); 801 assertEquals(option2, checker.testList); 802 Map<String, String> resMap = new HashMap<>(); 803 resMap.put("set-option", "moreoption"); 804 assertEquals(resMap, checker.testMap); 805 } 806 } 807