1 /* 2 * Copyright (C) 2018 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 package com.android.tradefed.testtype.suite; 17 18 import com.android.tradefed.config.ConfigurationDef.OptionDef; 19 import com.android.tradefed.config.ConfigurationException; 20 import com.android.tradefed.config.ConfigurationFactory; 21 import com.android.tradefed.config.ConfigurationUtil; 22 import com.android.tradefed.config.IConfiguration; 23 import com.android.tradefed.config.IConfigurationFactory; 24 import com.android.tradefed.log.LogUtil.CLog; 25 import com.android.tradefed.targetprep.ITargetPreparer; 26 import com.android.tradefed.testtype.IAbi; 27 import com.android.tradefed.testtype.IAbiReceiver; 28 import com.android.tradefed.testtype.IRemoteTest; 29 import com.android.tradefed.testtype.ITestFileFilterReceiver; 30 import com.android.tradefed.testtype.ITestFilterReceiver; 31 import com.android.tradefed.testtype.suite.params.IModuleParameter; 32 import com.android.tradefed.testtype.suite.params.ModuleParameters; 33 import com.android.tradefed.testtype.suite.params.ModuleParametersHelper; 34 import com.android.tradefed.testtype.suite.params.NegativeHandler; 35 import com.android.tradefed.testtype.suite.params.NotMultiAbiHandler; 36 import com.android.tradefed.util.AbiUtils; 37 import com.android.tradefed.util.FileUtil; 38 import com.android.tradefed.util.StreamUtil; 39 40 import com.google.common.base.Strings; 41 42 import java.io.File; 43 import java.io.FilenameFilter; 44 import java.io.IOException; 45 import java.io.PrintWriter; 46 import java.util.ArrayList; 47 import java.util.Arrays; 48 import java.util.Collection; 49 import java.util.Collections; 50 import java.util.HashMap; 51 import java.util.HashSet; 52 import java.util.LinkedHashMap; 53 import java.util.List; 54 import java.util.Map; 55 import java.util.Set; 56 import java.util.regex.Matcher; 57 import java.util.regex.Pattern; 58 59 /** 60 * Retrieves Compatibility test module definitions from the repository. TODO: Add the expansion of 61 * suite when loading a module. 62 */ 63 public class SuiteModuleLoader { 64 65 public static final String CONFIG_EXT = ".config"; 66 private Map<String, List<OptionDef>> mTestOptions = new HashMap<>(); 67 private Map<String, List<OptionDef>> mModuleOptions = new HashMap<>(); 68 private boolean mIncludeAll; 69 private Map<String, List<SuiteTestFilter>> mIncludeFilters = new HashMap<>(); 70 private Map<String, List<SuiteTestFilter>> mExcludeFilters = new HashMap<>(); 71 private IConfigurationFactory mConfigFactory = ConfigurationFactory.getInstance(); 72 73 private boolean mAllowParameterizedModules = false; 74 private ModuleParameters mForcedModuleParameter = null; 75 private Set<ModuleParameters> mExcludedModuleParameters = new HashSet<>(); 76 77 /** 78 * Ctor for the SuiteModuleLoader. 79 * 80 * @param includeFilters The formatted and parsed include filters. 81 * @param excludeFilters The formatted and parsed exclude filters. 82 * @param testArgs the list of test ({@link IRemoteTest}) arguments. 83 * @param moduleArgs the list of module arguments. 84 */ SuiteModuleLoader( Map<String, List<SuiteTestFilter>> includeFilters, Map<String, List<SuiteTestFilter>> excludeFilters, List<String> testArgs, List<String> moduleArgs)85 public SuiteModuleLoader( 86 Map<String, List<SuiteTestFilter>> includeFilters, 87 Map<String, List<SuiteTestFilter>> excludeFilters, 88 List<String> testArgs, 89 List<String> moduleArgs) { 90 mIncludeAll = includeFilters.isEmpty(); 91 mIncludeFilters = includeFilters; 92 mExcludeFilters = excludeFilters; 93 94 parseArgs(testArgs, mTestOptions); 95 parseArgs(moduleArgs, mModuleOptions); 96 } 97 98 /** Sets whether or not to allow parameterized modules. */ setParameterizedModules(boolean allowed)99 public final void setParameterizedModules(boolean allowed) { 100 mAllowParameterizedModules = allowed; 101 } 102 103 /** Sets the only {@link ModuleParameters} type that should be run. */ setModuleParameter(ModuleParameters param)104 public final void setModuleParameter(ModuleParameters param) { 105 mForcedModuleParameter = param; 106 } 107 108 /** Sets the set of {@link ModuleParameters} that should not be considered at all. */ setExcludedModuleParameters(Set<ModuleParameters> excludedParams)109 public final void setExcludedModuleParameters(Set<ModuleParameters> excludedParams) { 110 mExcludedModuleParameters = excludedParams; 111 } 112 113 /** Main loading of configurations, looking into a folder */ loadConfigsFromDirectory( List<File> testsDirs, Set<IAbi> abis, String suitePrefix, String suiteTag, List<String> patterns)114 public LinkedHashMap<String, IConfiguration> loadConfigsFromDirectory( 115 List<File> testsDirs, 116 Set<IAbi> abis, 117 String suitePrefix, 118 String suiteTag, 119 List<String> patterns) { 120 LinkedHashMap<String, IConfiguration> toRun = new LinkedHashMap<>(); 121 List<File> listConfigFiles = new ArrayList<>(); 122 listConfigFiles.addAll( 123 ConfigurationUtil.getConfigNamesFileFromDirs(suitePrefix, testsDirs, patterns)); 124 // Ensure stable initial order of configurations. 125 Collections.sort(listConfigFiles); 126 for (File configFile : listConfigFiles) { 127 toRun.putAll( 128 loadOneConfig( 129 configFile.getName(), configFile.getAbsolutePath(), abis, suiteTag)); 130 } 131 return toRun; 132 } 133 134 /** 135 * Main loading of configurations, looking into the resources on the classpath. (TF configs for 136 * example). 137 */ loadConfigsFromJars( Set<IAbi> abis, String suitePrefix, String suiteTag)138 public LinkedHashMap<String, IConfiguration> loadConfigsFromJars( 139 Set<IAbi> abis, String suitePrefix, String suiteTag) { 140 LinkedHashMap<String, IConfiguration> toRun = new LinkedHashMap<>(); 141 142 IConfigurationFactory configFactory = ConfigurationFactory.getInstance(); 143 List<String> configs = configFactory.getConfigList(suitePrefix, false); 144 // Sort configs to ensure they are always evaluated and added in the same order. 145 Collections.sort(configs); 146 for (String configName : configs) { 147 toRun.putAll(loadOneConfig(configName, configName, abis, suiteTag)); 148 } 149 return toRun; 150 } 151 152 /** 153 * Pass the filters to the {@link IRemoteTest}. Default behavior is to ignore if the IRemoteTest 154 * does not implements {@link ITestFileFilterReceiver}. This can be overriden to create a more 155 * restrictive behavior. 156 * 157 * @param test The {@link IRemoteTest} that is being considered. 158 * @param abi The Abi we are currently working on. 159 * @param name The name of the module. 160 * @param includeFilters The formatted and parsed include filters. 161 * @param excludeFilters The formatted and parsed exclude filters. 162 */ addFiltersToTest( IRemoteTest test, IAbi abi, String name, Map<String, List<SuiteTestFilter>> includeFilters, Map<String, List<SuiteTestFilter>> excludeFilters)163 public void addFiltersToTest( 164 IRemoteTest test, 165 IAbi abi, 166 String name, 167 Map<String, List<SuiteTestFilter>> includeFilters, 168 Map<String, List<SuiteTestFilter>> excludeFilters) { 169 String moduleId = AbiUtils.createId(abi.getName(), name); 170 if (!(test instanceof ITestFilterReceiver)) { 171 CLog.e("Test in module %s does not implement ITestFilterReceiver.", moduleId); 172 return; 173 } 174 List<SuiteTestFilter> mdIncludes = getFilterList(includeFilters, moduleId); 175 List<SuiteTestFilter> mdExcludes = getFilterList(excludeFilters, moduleId); 176 if (!mdIncludes.isEmpty()) { 177 addTestIncludes((ITestFilterReceiver) test, mdIncludes, name); 178 } 179 if (!mdExcludes.isEmpty()) { 180 addTestExcludes((ITestFilterReceiver) test, mdExcludes, name); 181 } 182 } 183 184 /** 185 * Load a single config location (file or on TF classpath). It can results in several {@link 186 * IConfiguration}. If a single configuration get expanded in different ways. 187 * 188 * @param configName The actual config name only. (no path) 189 * @param configFullName The fully qualified config name. (with path, if any). 190 * @param abis The set of all abis that needs to run. 191 * @param suiteTag the Tag of the suite aimed to be run. 192 * @return A map of loaded configuration. 193 */ loadOneConfig( String configName, String configFullName, Set<IAbi> abis, String suiteTag)194 private LinkedHashMap<String, IConfiguration> loadOneConfig( 195 String configName, String configFullName, Set<IAbi> abis, String suiteTag) { 196 LinkedHashMap<String, IConfiguration> toRun = new LinkedHashMap<>(); 197 final String name = configName.replace(CONFIG_EXT, ""); 198 final String[] pathArg = new String[] {configFullName}; 199 try { 200 boolean primaryAbi = true; 201 boolean shouldCreateMultiAbi = true; 202 // If a particular parameter was requested to be run, find it. 203 IModuleParameter mForcedParameter = null; 204 if (mForcedModuleParameter != null) { 205 mForcedParameter = 206 ModuleParametersHelper.getParameterHandler( 207 mForcedModuleParameter, /* optionalParams */ false); 208 } 209 210 // Invokes parser to process the test module config file 211 // Need to generate a different config for each ABI as we cannot guarantee the 212 // configs are idempotent. This however means we parse the same file multiple times 213 for (IAbi abi : abis) { 214 // Only enable the primary abi filtering when switching to the parameterized mode 215 if (mAllowParameterizedModules && !primaryAbi && !shouldCreateMultiAbi) { 216 continue; 217 } 218 String baseId = AbiUtils.createId(abi.getName(), name); 219 IConfiguration config = null; 220 try { 221 config = mConfigFactory.createConfigurationFromArgs(pathArg); 222 } catch (ConfigurationException e) { 223 // If the module should not have been running in the first place, give it a 224 // pass on the configuration failure. 225 if (!shouldRunModule(baseId)) { 226 primaryAbi = false; 227 // If the module should not run tests based on the state of filters, 228 // skip this name/abi combination. 229 continue; 230 } 231 throw e; 232 } 233 234 // If a suiteTag is used, we load with it. 235 if (!Strings.isNullOrEmpty(suiteTag) 236 && !config.getConfigurationDescription() 237 .getSuiteTags() 238 .contains(suiteTag)) { 239 // Do not print here, it could leave several hundred lines of logs. 240 continue; 241 } 242 243 boolean skipCreatingBaseConfig = false; 244 List<IModuleParameter> params = null; 245 try { 246 params = getModuleParameters(name, config); 247 } catch (ConfigurationException e) { 248 // If the module should not have been running in the first place, give it a 249 // pass on the configuration failure. 250 if (!shouldRunModule(baseId)) { 251 primaryAbi = false; 252 // If the module should not run tests based on the state of filters, 253 // skip this name/abi combination. 254 continue; 255 } 256 throw e; 257 } 258 259 // Handle parameterized modules if enabled. 260 if (mAllowParameterizedModules) { 261 262 if (params.isEmpty() 263 && mForcedParameter != null 264 && !(mForcedParameter instanceof NegativeHandler)) { 265 // If the AndroidTest.xml doesn't specify any parameter but we forced a 266 // parameter like 'instant' to execute. In this case we don't create the 267 // standard module. 268 continue; 269 } 270 271 shouldCreateMultiAbi = shouldCreateMultiAbiForBase(params); 272 273 // If we find any parameterized combination. 274 for (IModuleParameter param : params) { 275 if (param instanceof NegativeHandler) { 276 if (mForcedParameter != null 277 && !param.getClass().equals(mForcedParameter.getClass())) { 278 skipCreatingBaseConfig = true; 279 } 280 continue; 281 } 282 if (mForcedParameter != null) { 283 // When a particular parameter is forced, only create it not the others 284 if (param.getClass().equals(mForcedParameter.getClass())) { 285 skipCreatingBaseConfig = true; 286 } else { 287 continue; 288 } 289 } 290 // Only create primary abi of parameterized modules 291 if (!primaryAbi) { 292 continue; 293 } 294 String fullId = 295 String.format("%s[%s]", baseId, param.getParameterIdentifier()); 296 if (shouldRunParameterized(baseId, fullId)) { 297 IConfiguration paramConfig = 298 mConfigFactory.createConfigurationFromArgs(pathArg); 299 setUpConfig(name, baseId, fullId, paramConfig, abi); 300 param.applySetup(paramConfig); 301 toRun.put(fullId, paramConfig); 302 } 303 } 304 } 305 primaryAbi = false; 306 // If a parameterized form of the module was forced, we don't create the standard 307 // version of it. 308 if (skipCreatingBaseConfig) { 309 continue; 310 } 311 if (shouldRunModule(baseId)) { 312 // Always add the base regular configuration to the execution. 313 setUpConfig(name, baseId, baseId, config, abi); 314 toRun.put(baseId, config); 315 } 316 } 317 } catch (ConfigurationException e) { 318 throw new RuntimeException( 319 String.format( 320 "Error parsing configuration: %s: '%s'", 321 configFullName, e.getMessage()), 322 e); 323 } 324 325 return toRun; 326 } 327 328 /** @return the {@link Set} of modules whose name contains the given pattern. */ getModuleNamesMatching( File directory, String suitePrefix, String pattern)329 public static Set<File> getModuleNamesMatching( 330 File directory, String suitePrefix, String pattern) { 331 List<File> extraTestCasesDirs = Arrays.asList(directory); 332 List<String> patterns = new ArrayList<>(); 333 patterns.add(pattern); 334 Set<File> modules = 335 ConfigurationUtil.getConfigNamesFileFromDirs( 336 suitePrefix, extraTestCasesDirs, patterns); 337 return modules; 338 } 339 340 /** 341 * Utility method that allows to parse and create a structure with the option filters. 342 * 343 * @param stringFilters The original option filters format. 344 * @param filters The filters parsed from the string format. 345 * @param abis The Abis to consider in the filtering. 346 */ addFilters( Set<String> stringFilters, Map<String, List<SuiteTestFilter>> filters, Set<IAbi> abis)347 public static void addFilters( 348 Set<String> stringFilters, Map<String, List<SuiteTestFilter>> filters, Set<IAbi> abis) { 349 for (String filterString : stringFilters) { 350 SuiteTestFilter filter = SuiteTestFilter.createFrom(filterString); 351 String abi = filter.getAbi(); 352 if (abi == null) { 353 for (IAbi a : abis) { 354 addFilter(a.getName(), filter, filters); 355 } 356 } else { 357 addFilter(abi, filter, filters); 358 } 359 } 360 } 361 addFilter( String abi, SuiteTestFilter filter, Map<String, List<SuiteTestFilter>> filters)362 private static void addFilter( 363 String abi, SuiteTestFilter filter, Map<String, List<SuiteTestFilter>> filters) { 364 getFilterList(filters, AbiUtils.createId(abi, filter.getName())).add(filter); 365 } 366 getFilterList( Map<String, List<SuiteTestFilter>> filters, String id)367 private static List<SuiteTestFilter> getFilterList( 368 Map<String, List<SuiteTestFilter>> filters, String id) { 369 List<SuiteTestFilter> fs = filters.get(id); 370 if (fs == null) { 371 fs = new ArrayList<>(); 372 filters.put(id, fs); 373 } 374 return fs; 375 } 376 shouldRunModule(String moduleId)377 private boolean shouldRunModule(String moduleId) { 378 List<SuiteTestFilter> mdIncludes = getFilterList(mIncludeFilters, moduleId); 379 List<SuiteTestFilter> mdExcludes = getFilterList(mExcludeFilters, moduleId); 380 // if including all modules or includes exist for this module, and there are not excludes 381 // for the entire module, this module should be run. 382 return (mIncludeAll || !mdIncludes.isEmpty()) && !containsModuleExclude(mdExcludes); 383 } 384 385 /** 386 * Except if the parameterized module is explicitly excluded, including the base module result 387 * in including its parameterization variant. 388 */ shouldRunParameterized(String baseId, String parameterModuleId)389 private boolean shouldRunParameterized(String baseId, String parameterModuleId) { 390 // Explicitly excluded 391 List<SuiteTestFilter> mdExcludes = getFilterList(mExcludeFilters, parameterModuleId); 392 if (containsModuleExclude(mdExcludes)) { 393 return false; 394 } 395 // itself or its base is included 396 List<SuiteTestFilter> mdIncludes = getFilterList(mIncludeFilters, baseId); 397 List<SuiteTestFilter> mParamIncludes = getFilterList(mIncludeFilters, parameterModuleId); 398 if (mIncludeAll || !mdIncludes.isEmpty() || !mParamIncludes.isEmpty()) { 399 return true; 400 } 401 return false; 402 } 403 addTestIncludes( ITestFilterReceiver test, List<SuiteTestFilter> includes, String name)404 private void addTestIncludes( 405 ITestFilterReceiver test, List<SuiteTestFilter> includes, String name) { 406 if (test instanceof ITestFileFilterReceiver) { 407 File includeFile = createFilterFile(name, ".include", includes); 408 ((ITestFileFilterReceiver) test).setIncludeTestFile(includeFile); 409 } else { 410 // add test includes one at a time 411 for (SuiteTestFilter include : includes) { 412 String filterTestName = include.getTest(); 413 if (filterTestName != null) { 414 test.addIncludeFilter(filterTestName); 415 } 416 } 417 } 418 } 419 addTestExcludes( ITestFilterReceiver test, List<SuiteTestFilter> excludes, String name)420 private void addTestExcludes( 421 ITestFilterReceiver test, List<SuiteTestFilter> excludes, String name) { 422 if (test instanceof ITestFileFilterReceiver) { 423 File excludeFile = createFilterFile(name, ".exclude", excludes); 424 ((ITestFileFilterReceiver) test).setExcludeTestFile(excludeFile); 425 } else { 426 // add test excludes one at a time 427 for (SuiteTestFilter exclude : excludes) { 428 test.addExcludeFilter(exclude.getTest()); 429 } 430 } 431 } 432 createFilterFile(String prefix, String suffix, List<SuiteTestFilter> filters)433 private File createFilterFile(String prefix, String suffix, List<SuiteTestFilter> filters) { 434 File filterFile = null; 435 PrintWriter out = null; 436 try { 437 filterFile = FileUtil.createTempFile(prefix, suffix); 438 out = new PrintWriter(filterFile); 439 for (SuiteTestFilter filter : filters) { 440 String filterTest = filter.getTest(); 441 if (filterTest != null) { 442 out.println(filterTest); 443 } 444 } 445 out.flush(); 446 } catch (IOException e) { 447 throw new RuntimeException("Failed to create filter file"); 448 } finally { 449 StreamUtil.close(out); 450 } 451 filterFile.deleteOnExit(); 452 return filterFile; 453 } 454 455 /** Returns true iff one or more test filters in excludes apply to the entire module. */ containsModuleExclude(Collection<SuiteTestFilter> excludes)456 private boolean containsModuleExclude(Collection<SuiteTestFilter> excludes) { 457 for (SuiteTestFilter exclude : excludes) { 458 if (exclude.getTest() == null) { 459 return true; 460 } 461 } 462 return false; 463 } 464 465 /** A {@link FilenameFilter} to find all the config files in a directory. */ 466 public static class ConfigFilter implements FilenameFilter { 467 468 /** {@inheritDoc} */ 469 @Override accept(File dir, String name)470 public boolean accept(File dir, String name) { 471 return name.endsWith(CONFIG_EXT); 472 } 473 } 474 475 /** 476 * Parse a list of args formatted as expected into {@link OptionDef} to be injected to module 477 * configurations. 478 * 479 * <p>Format: <module name / module id / class runner>:<option name>:[<arg-key>:=]<arg-value> 480 */ parseArgs(List<String> args, Map<String, List<OptionDef>> moduleOptions)481 private void parseArgs(List<String> args, Map<String, List<OptionDef>> moduleOptions) { 482 for (String arg : args) { 483 int moduleSep = arg.indexOf(":"); 484 if (moduleSep == -1) { 485 throw new RuntimeException("Expected delimiter ':' for module or class."); 486 } 487 String moduleName = arg.substring(0, moduleSep); 488 String remainder = arg.substring(moduleSep + 1); 489 List<OptionDef> listOption = moduleOptions.get(moduleName); 490 if (listOption == null) { 491 listOption = new ArrayList<>(); 492 moduleOptions.put(moduleName, listOption); 493 } 494 int optionNameSep = remainder.indexOf(":"); 495 if (optionNameSep == -1) { 496 throw new RuntimeException( 497 "Expected delimiter ':' between option name and values."); 498 } 499 String optionName = remainder.substring(0, optionNameSep); 500 Pattern pattern = Pattern.compile("\\{(.*)\\}(.*)"); 501 Matcher match = pattern.matcher(optionName); 502 if (match.find()) { 503 String alias = match.group(1); 504 String name = match.group(2); 505 optionName = alias + ":" + name; 506 } 507 String optionValueString = remainder.substring(optionNameSep + 1); 508 // TODO: See if QuotationTokenizer can be improved for multi-character delimiter. 509 // or change the delimiter to a single char. 510 String[] tokens = optionValueString.split(":="); 511 OptionDef option = null; 512 if (tokens.length == 1) { 513 option = new OptionDef(optionName, tokens[0], moduleName); 514 } else if (tokens.length == 2) { 515 option = new OptionDef(optionName, tokens[0], tokens[1], moduleName); 516 } 517 listOption.add(option); 518 } 519 } 520 521 /** Gets the list of {@link IModuleParameter}s associated with a module. */ getModuleParameters(String moduleName, IConfiguration config)522 private List<IModuleParameter> getModuleParameters(String moduleName, IConfiguration config) 523 throws ConfigurationException { 524 List<IModuleParameter> params = new ArrayList<>(); 525 // Track family of the parameters to make sure we have no duplicate. 526 Map<String, ModuleParameters> duplicateModule = new LinkedHashMap<>(); 527 528 List<String> parameters = 529 config.getConfigurationDescription().getMetaData(ITestSuite.PARAMETER_KEY); 530 if (parameters == null || parameters.isEmpty()) { 531 return params; 532 } 533 for (String p : parameters) { 534 ModuleParameters suiteParam = ModuleParameters.valueOf(p.toUpperCase()); 535 String family = suiteParam.getFamily(); 536 if (duplicateModule.containsKey(family)) { 537 // Duplicate family members are not accepted. 538 throw new ConfigurationException( 539 String.format( 540 "Module %s is declaring parameter: " 541 + "%s and %s when only one expected.", 542 moduleName, suiteParam, duplicateModule.get(family))); 543 } else { 544 duplicateModule.put(suiteParam.getFamily(), suiteParam); 545 } 546 // Do not consider the excluded parameterization dimension 547 if (mExcludedModuleParameters.contains(suiteParam)) { 548 CLog.d("'%s' was excluded via exclude-module-parameters."); 549 continue; 550 } 551 IModuleParameter handler = 552 ModuleParametersHelper.getParameterHandler( 553 suiteParam, /* optionalParams */ false); 554 params.add(handler); 555 } 556 return params; 557 } 558 559 /** 560 * Setup the options for the module configuration. 561 * 562 * @param name The base name of the module 563 * @param id The base id name of the module. 564 * @param fullId The full id of the module. 565 * @param config The module configuration. 566 * @param abi The abi of the module. 567 * @throws ConfigurationException 568 */ setUpConfig(String name, String id, String fullId, IConfiguration config, IAbi abi)569 private void setUpConfig(String name, String id, String fullId, IConfiguration config, IAbi abi) 570 throws ConfigurationException { 571 List<OptionDef> optionsToInject = new ArrayList<>(); 572 if (mModuleOptions.containsKey(name)) { 573 optionsToInject.addAll(mModuleOptions.get(name)); 574 } 575 if (mModuleOptions.containsKey(id)) { 576 optionsToInject.addAll(mModuleOptions.get(id)); 577 } 578 if (mModuleOptions.containsKey(fullId)) { 579 optionsToInject.addAll(mModuleOptions.get(fullId)); 580 } 581 config.injectOptionValues(optionsToInject); 582 583 // Set target preparers 584 List<ITargetPreparer> preparers = config.getTargetPreparers(); 585 for (ITargetPreparer preparer : preparers) { 586 if (preparer instanceof IAbiReceiver) { 587 ((IAbiReceiver) preparer).setAbi(abi); 588 } 589 } 590 591 // Set IRemoteTests 592 List<IRemoteTest> tests = config.getTests(); 593 for (IRemoteTest test : tests) { 594 String className = test.getClass().getName(); 595 if (mTestOptions.containsKey(className)) { 596 config.injectOptionValues(mTestOptions.get(className)); 597 } 598 addFiltersToTest(test, abi, name, mIncludeFilters, mExcludeFilters); 599 if (test instanceof IAbiReceiver) { 600 ((IAbiReceiver) test).setAbi(abi); 601 } 602 } 603 604 // add the abi and module name to the description 605 config.getConfigurationDescription().setAbi(abi); 606 config.getConfigurationDescription().setModuleName(name); 607 608 config.validateOptions(false); 609 } 610 611 /** Whether or not the base configuration should be created for all abis or not. */ shouldCreateMultiAbiForBase(List<IModuleParameter> params)612 private boolean shouldCreateMultiAbiForBase(List<IModuleParameter> params) { 613 for (IModuleParameter param : params) { 614 if (param instanceof NotMultiAbiHandler) { 615 return false; 616 } 617 } 618 return true; 619 } 620 } 621