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