1 /* 2 * Copyright (C) 2011 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.command; 17 18 import com.android.tradefed.config.ConfigurationException; 19 import com.android.tradefed.config.Option; 20 import com.android.tradefed.config.Option.Importance; 21 import com.android.tradefed.config.OptionCopier; 22 import com.android.tradefed.device.metric.AutoLogCollector; 23 import com.android.tradefed.log.LogUtil.CLog; 24 import com.android.tradefed.util.UniqueMultiMap; 25 26 import java.util.LinkedHashMap; 27 import java.util.LinkedHashSet; 28 import java.util.Map; 29 import java.util.Set; 30 31 /** 32 * Implementation of {@link ICommandOptions}. 33 */ 34 public class CommandOptions implements ICommandOptions { 35 36 @Option(name = "help", description = 37 "display the help text for the most important/critical options.", 38 importance = Importance.ALWAYS) 39 private boolean mHelpMode = false; 40 41 @Option(name = "help-all", description = "display the full help text for all options.", 42 importance = Importance.ALWAYS) 43 private boolean mFullHelpMode = false; 44 45 public static final String DRY_RUN_OPTION = "dry-run"; 46 public static final String NOISY_DRY_RUN_OPTION = "noisy-dry-run"; 47 48 @Option( 49 name = DRY_RUN_OPTION, 50 description = 51 "build but don't actually run the command. Intended as a quick check " 52 + "to ensure that a command is runnable.", 53 importance = Importance.ALWAYS 54 ) 55 private boolean mDryRunMode = false; 56 57 @Option( 58 name = NOISY_DRY_RUN_OPTION, 59 description = 60 "build but don't actually run the command. This version prints the " 61 + "command to the console. Intended for cmdfile debugging.", 62 importance = Importance.ALWAYS 63 ) 64 private boolean mNoisyDryRunMode = false; 65 66 @Option(name = "min-loop-time", description = 67 "the minimum invocation time in ms when in loop mode.") 68 private Long mMinLoopTime = 10L * 60L * 1000L; 69 70 public static final String TEST_TAG_OPTION = "test-tag"; 71 72 @Option(name = TEST_TAG_OPTION, description = "Identifier for the invocation during reporting.") 73 private String mTestTag = "stub"; 74 75 @Option(name = "test-tag-suffix", description = "suffix for test-tag. appended to test-tag to " 76 + "represents some variants of one test.") 77 private String mTestTagSuffix = null; 78 79 @Option(name = "loop", description = "keep running continuously.", 80 importance = Importance.ALWAYS) 81 private boolean mLoopMode = false; 82 83 @Option(name = "all-devices", description = 84 "fork this command to run on all connected devices.") 85 private boolean mAllDevices = false; 86 87 @Option(name = "bugreport-on-invocation-ended", description = 88 "take a bugreport when the test invocation has ended") 89 private boolean mTakeBugreportOnInvocationEnded = false; 90 91 @Option(name = "bugreportz-on-invocation-ended", description = "Attempt to take a bugreportz " 92 + "instead of bugreport during the test invocation final bugreport.") 93 private boolean mTakeBugreportzOnInvocationEnded = false; 94 95 @Option(name = "invocation-timeout", description = 96 "the maximum time to wait for an invocation to terminate before attempting to force" 97 + "stop it.", isTimeVal = true) 98 private long mInvocationTimeout = 0; 99 100 @Option(name = "shard-count", description = 101 "the number of total shards to run. Without --shard-index option, this will cause " + 102 "the command to spawn multiple shards in the current TF instance. With --shard-index " + 103 "option, it will cause the command to run a single shard of tests only.") 104 private Integer mShardCount; 105 106 @Option(name = "shard-index", description = 107 "the index of shard to run. Only set if shard-count > 1 and the value is in range " + 108 "[0, shard-count)") 109 private Integer mShardIndex; 110 111 @Option( 112 name = "enable-token-sharding", 113 description = "Whether or not to allow sharding with the token support enabled." 114 ) 115 private boolean mTokenSharding = false; 116 117 @Option( 118 name = "dynamic-sharding", 119 description = 120 "Allow to dynamically move IRemoteTest from one shard to another. Only for local " 121 + "sharding." 122 ) 123 private boolean mDynamicSharding = true; 124 125 public static final String INVOCATION_DATA = "invocation-data"; 126 127 @Option( 128 name = INVOCATION_DATA, 129 description = 130 "A map of values that describe the invocation, these values will be added to the " 131 + "invocation context.") 132 private UniqueMultiMap<String, String> mInvocationData = new UniqueMultiMap<>(); 133 134 public static final String USE_SANDBOX = "use-sandbox"; 135 public static final String ENABLE_SANDBOX_TEST_MODE = "sandbox-test-mode"; 136 public static final String USE_REMOTE_SANDBOX = "use-remote-sandbox"; 137 138 @Option( 139 name = USE_SANDBOX, 140 description = "Set if the invocation should use a sandbox to run or not." 141 ) 142 private boolean mUseSandbox = false; 143 144 @Option( 145 name = ENABLE_SANDBOX_TEST_MODE, 146 description = 147 "Sandbox test mode where the sandbox will use itself to generate another layer " 148 + "of sandboxing. This is used for the sandbox to validate itself.") 149 private boolean mSandboxTestMode = false; 150 151 @Option( 152 name = USE_REMOTE_SANDBOX, 153 description = "Whether or not to trigger --use-sandbox in the remote invocation." 154 ) 155 private boolean mUseRemoteSandbox = false; 156 157 @Deprecated 158 @Option( 159 name = "parallel-remote-setup", 160 description = 161 "For remote sharded invocation, whether or not to attempt the setup in parallel.") 162 private boolean mUseParallelRemoteSetup = false; 163 164 @Option( 165 name = "replicate-parent-setup", 166 description = 167 "For remote sharded invocation, whether or not to replicate parent setup on " 168 + "all devices.") 169 private boolean mReplicateParentSetup = false; 170 171 @Option( 172 name = "report-module-progression", 173 description = "For remote invocation, whether or not to report progress at module level." 174 ) 175 private boolean mReportModuleProgression = false; 176 177 @Deprecated 178 @Option( 179 name = "extra-postsubmit-remote-instance", 180 description = 181 "Option that allows to run more instances in the remote VM in postsubmit. " 182 + "Used for experimentation.") 183 private int mExtraRemoteInstancePostsubmit = 0; 184 185 @Option( 186 name = "auto-collect", 187 description = 188 "Specify a set of collectors that will be automatically managed by the harness " 189 + "to collect logs." 190 ) 191 private Set<AutoLogCollector> mAutoCollectors = new LinkedHashSet<>(); 192 193 @Deprecated 194 @Option( 195 name = "logcat-on-failure", 196 description = "take a logcat snapshot on every test failure." 197 ) 198 private boolean mLogcatOnFailure = false; 199 200 @Deprecated 201 @Option(name = "screenshot-on-failure", description = "Take a screenshot on every test failure") 202 private boolean mScreenshotOnFailure = false; 203 204 @Option( 205 name = "host-log-suffix", 206 description = "Suffix to add to Tradefed host_log before logging it." 207 ) 208 private String mHostLogSuffix = null; 209 210 @Option( 211 name = "early-device-release", 212 description = "Feature flag to release the device as soon as done with it.") 213 private boolean mEnableEarlyDeviceRelease = true; 214 215 @Option( 216 name = "dynamic-download-args", 217 description = 218 "Extra args passed to the IRemoteFileResolver interface for dynamic download " 219 + "in the queryArgs.") 220 private Map<String, String> mDynamicDownloadArgs = new LinkedHashMap<>(); 221 222 /** 223 * Set the help mode for the config. 224 * <p/> 225 * Exposed for testing. 226 */ setHelpMode(boolean helpMode)227 void setHelpMode(boolean helpMode) { 228 mHelpMode = helpMode; 229 } 230 231 /** 232 * {@inheritDoc} 233 */ 234 @Override isHelpMode()235 public boolean isHelpMode() { 236 return mHelpMode; 237 } 238 239 /** 240 * {@inheritDoc} 241 */ 242 @Override isFullHelpMode()243 public boolean isFullHelpMode() { 244 return mFullHelpMode; 245 } 246 247 /** 248 * Set the dry run mode for the config. 249 * <p/> 250 * Exposed for testing. 251 */ setDryRunMode(boolean dryRunMode)252 void setDryRunMode(boolean dryRunMode) { 253 mDryRunMode = dryRunMode; 254 } 255 256 /** 257 * {@inheritDoc} 258 */ 259 @Override isDryRunMode()260 public boolean isDryRunMode() { 261 return mDryRunMode || mNoisyDryRunMode; 262 } 263 264 /** 265 * {@inheritDoc} 266 */ 267 @Override isNoisyDryRunMode()268 public boolean isNoisyDryRunMode() { 269 return mNoisyDryRunMode; 270 } 271 272 /** 273 * Set the loop mode for the config. 274 */ 275 @Override setLoopMode(boolean loopMode)276 public void setLoopMode(boolean loopMode) { 277 mLoopMode = loopMode; 278 } 279 280 /** 281 * {@inheritDoc} 282 */ 283 @Override isLoopMode()284 public boolean isLoopMode() { 285 return mLoopMode; 286 } 287 288 /** 289 * Set the min loop time for the config. 290 * <p/> 291 * Exposed for testing. 292 */ setMinLoopTime(long loopTime)293 void setMinLoopTime(long loopTime) { 294 mMinLoopTime = loopTime; 295 } 296 297 /** 298 * {@inheritDoc} 299 */ 300 @Override getLoopTime()301 public long getLoopTime() { 302 return mMinLoopTime; 303 } 304 305 306 @Override clone()307 public ICommandOptions clone() { 308 CommandOptions clone = new CommandOptions(); 309 try { 310 OptionCopier.copyOptions(this, clone); 311 } catch (ConfigurationException e) { 312 CLog.e("failed to clone command options: %s", e.getMessage()); 313 } 314 return clone; 315 } 316 317 /** 318 * {@inheritDoc} 319 */ 320 @Override runOnAllDevices()321 public boolean runOnAllDevices() { 322 return mAllDevices; 323 } 324 325 /** 326 * {@inheritDoc} 327 */ 328 @Override takeBugreportOnInvocationEnded()329 public boolean takeBugreportOnInvocationEnded() { 330 return mTakeBugreportOnInvocationEnded; 331 } 332 333 /** {@inheritDoc} */ 334 @Override setBugreportOnInvocationEnded(boolean takeBugreport)335 public void setBugreportOnInvocationEnded(boolean takeBugreport) { 336 mTakeBugreportOnInvocationEnded = takeBugreport; 337 } 338 339 /** 340 * {@inheritDoc} 341 */ 342 @Override takeBugreportzOnInvocationEnded()343 public boolean takeBugreportzOnInvocationEnded() { 344 return mTakeBugreportzOnInvocationEnded; 345 } 346 347 /** {@inheritDoc} */ 348 @Override setBugreportzOnInvocationEnded(boolean takeBugreportz)349 public void setBugreportzOnInvocationEnded(boolean takeBugreportz) { 350 mTakeBugreportzOnInvocationEnded = takeBugreportz; 351 } 352 353 /** 354 * {@inheritDoc} 355 */ 356 @Override getInvocationTimeout()357 public long getInvocationTimeout() { 358 return mInvocationTimeout; 359 } 360 361 /** 362 * {@inheritDoc} 363 */ 364 @Override setInvocationTimeout(Long invocationTimeout)365 public void setInvocationTimeout(Long invocationTimeout) { 366 mInvocationTimeout = invocationTimeout; 367 } 368 369 /** 370 * {@inheritDoc} 371 */ 372 @Override getShardCount()373 public Integer getShardCount() { 374 return mShardCount; 375 } 376 377 /** 378 * {@inheritDoc} 379 */ 380 @Override setShardCount(Integer shardCount)381 public void setShardCount(Integer shardCount) { 382 mShardCount = shardCount; 383 } 384 385 /** 386 * {@inheritDoc} 387 */ 388 @Override getShardIndex()389 public Integer getShardIndex() { 390 return mShardIndex; 391 } 392 393 /** 394 * {@inheritDoc} 395 */ 396 @Override setShardIndex(Integer shardIndex)397 public void setShardIndex(Integer shardIndex) { 398 mShardIndex = shardIndex; 399 } 400 401 /** {@inheritDoc} */ 402 @Override shouldUseTokenSharding()403 public boolean shouldUseTokenSharding() { 404 return mTokenSharding; 405 } 406 407 /** 408 * {@inheritDoc} 409 */ 410 @Override setTestTag(String testTag)411 public void setTestTag(String testTag) { 412 mTestTag = testTag; 413 } 414 415 /** 416 * {@inheritDoc} 417 */ 418 @Override getTestTag()419 public String getTestTag() { 420 return mTestTag; 421 } 422 423 /** 424 * {@inheritDoc} 425 */ 426 @Override getTestTagSuffix()427 public String getTestTagSuffix() { 428 return mTestTagSuffix; 429 } 430 431 /** {@inheritDoc} */ 432 @Override shouldUseDynamicSharding()433 public boolean shouldUseDynamicSharding() { 434 return mDynamicSharding; 435 } 436 437 /** {@inheritDoc} */ 438 @Override getInvocationData()439 public UniqueMultiMap<String, String> getInvocationData() { 440 return mInvocationData; 441 } 442 443 /** {@inheritDoc} */ 444 @Override shouldUseSandboxing()445 public boolean shouldUseSandboxing() { 446 return mUseSandbox; 447 } 448 449 /** {@inheritDoc} */ 450 @Override setShouldUseSandboxing(boolean use)451 public void setShouldUseSandboxing(boolean use) { 452 mUseSandbox = use; 453 } 454 455 /** {@inheritDoc} */ 456 @Override shouldUseSandboxTestMode()457 public boolean shouldUseSandboxTestMode() { 458 return mSandboxTestMode; 459 } 460 461 /** {@inheritDoc} */ 462 @Override setUseSandboxTestMode(boolean use)463 public void setUseSandboxTestMode(boolean use) { 464 mSandboxTestMode = use; 465 } 466 467 /** {@inheritDoc} */ 468 @Override shouldUseRemoteSandboxMode()469 public boolean shouldUseRemoteSandboxMode() { 470 return mUseRemoteSandbox; 471 } 472 473 /** {@inheritDoc} */ 474 @Override getAutoLogCollectors()475 public Set<AutoLogCollector> getAutoLogCollectors() { 476 return mAutoCollectors; 477 } 478 479 /** {@inheritDoc} */ 480 @Override setAutoLogCollectors(Set<AutoLogCollector> autoLogCollectors)481 public void setAutoLogCollectors(Set<AutoLogCollector> autoLogCollectors) { 482 mAutoCollectors = autoLogCollectors; 483 } 484 485 /** {@inheritDoc} */ 486 @Override captureScreenshotOnFailure()487 public boolean captureScreenshotOnFailure() { 488 return mScreenshotOnFailure; 489 } 490 491 /** {@inheritDoc} */ 492 @Override captureLogcatOnFailure()493 public boolean captureLogcatOnFailure() { 494 return mLogcatOnFailure; 495 } 496 497 /** {@inheritDoc} */ 498 @Override getHostLogSuffix()499 public String getHostLogSuffix() { 500 return mHostLogSuffix; 501 } 502 503 /** {@inheritDoc} */ 504 @Override setHostLogSuffix(String suffix)505 public void setHostLogSuffix(String suffix) { 506 mHostLogSuffix = suffix; 507 } 508 509 /** {@inheritDoc} */ 510 @Override shouldUseParallelRemoteSetup()511 public boolean shouldUseParallelRemoteSetup() { 512 return mUseParallelRemoteSetup; 513 } 514 515 /** {@inheritDoc} */ 516 @Override shouldUseReplicateSetup()517 public boolean shouldUseReplicateSetup() { 518 return mReplicateParentSetup; 519 } 520 521 /** {@inheritDoc} */ 522 @Override setReplicateSetup(boolean replicate)523 public void setReplicateSetup(boolean replicate) { 524 mReplicateParentSetup = replicate; 525 } 526 527 /** {@inheritDoc} */ 528 @Override shouldReportModuleProgression()529 public boolean shouldReportModuleProgression() { 530 return mReportModuleProgression; 531 } 532 533 /** {@inheritDoc} */ 534 @Override getExtraRemotePostsubmitInstance()535 public int getExtraRemotePostsubmitInstance() { 536 return mExtraRemoteInstancePostsubmit; 537 } 538 539 /** {@inheritDoc} */ 540 @Override earlyDeviceRelease()541 public boolean earlyDeviceRelease() { 542 return mEnableEarlyDeviceRelease; 543 } 544 545 /** {@inheritDoc} */ 546 @Override getDynamicDownloadArgs()547 public Map<String, String> getDynamicDownloadArgs() { 548 return mDynamicDownloadArgs; 549 } 550 } 551