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.config.OptionUpdateRule; 23 import com.android.tradefed.log.LogUtil.CLog; 24 import com.android.tradefed.util.UniqueMultiMap; 25 26 /** 27 * Implementation of {@link ICommandOptions}. 28 */ 29 public class CommandOptions implements ICommandOptions { 30 31 @Option(name = "help", description = 32 "display the help text for the most important/critical options.", 33 importance = Importance.ALWAYS) 34 private boolean mHelpMode = false; 35 36 @Option(name = "help-all", description = "display the full help text for all options.", 37 importance = Importance.ALWAYS) 38 private boolean mFullHelpMode = false; 39 40 @Option(name = "json-help", description = "display the full help in json format.") 41 private boolean mJsonHelpMode = false; 42 43 public static final String DRY_RUN_OPTION = "dry-run"; 44 public static final String NOISY_DRY_RUN_OPTION = "noisy-dry-run"; 45 46 @Option( 47 name = DRY_RUN_OPTION, 48 description = 49 "build but don't actually run the command. Intended as a quick check " 50 + "to ensure that a command is runnable.", 51 importance = Importance.ALWAYS 52 ) 53 private boolean mDryRunMode = false; 54 55 @Option( 56 name = NOISY_DRY_RUN_OPTION, 57 description = 58 "build but don't actually run the command. This version prints the " 59 + "command to the console. Intended for cmdfile debugging.", 60 importance = Importance.ALWAYS 61 ) 62 private boolean mNoisyDryRunMode = false; 63 64 @Option(name = "min-loop-time", description = 65 "the minimum invocation time in ms when in loop mode.") 66 private Long mMinLoopTime = 10L * 60L * 1000L; 67 68 @Option(name = "max-random-loop-time", description = 69 "the maximum time to wait between invocation attempts when in loop mode. " + 70 "when set, the actual value will be a random number between min-loop-time and this " + 71 "number.", 72 updateRule = OptionUpdateRule.LEAST) 73 private Long mMaxRandomLoopTime = null; 74 75 @Option(name = "test-tag", description = "Identifier for the invocation during reporting.") 76 private String mTestTag = "stub"; 77 78 @Option(name = "test-tag-suffix", description = "suffix for test-tag. appended to test-tag to " 79 + "represents some variants of one test.") 80 private String mTestTagSuffix = null; 81 82 @Option(name = "loop", description = "keep running continuously.", 83 importance = Importance.ALWAYS) 84 private boolean mLoopMode = false; 85 86 @Option(name = "all-devices", description = 87 "fork this command to run on all connected devices.") 88 private boolean mAllDevices = false; 89 90 @Option(name = "bugreport-on-invocation-ended", description = 91 "take a bugreport when the test invocation has ended") 92 private boolean mTakeBugreportOnInvocationEnded = false; 93 94 @Option(name = "bugreportz-on-invocation-ended", description = "Attempt to take a bugreportz " 95 + "instead of bugreport during the test invocation final bugreport.") 96 private boolean mTakeBugreportzOnInvocationEnded = false; 97 98 @Option(name = "invocation-timeout", description = 99 "the maximum time to wait for an invocation to terminate before attempting to force" 100 + "stop it.", isTimeVal = true) 101 private long mInvocationTimeout = 0; 102 103 @Option(name = "shard-count", description = 104 "the number of total shards to run. Without --shard-index option, this will cause " + 105 "the command to spawn multiple shards in the current TF instance. With --shard-index " + 106 "option, it will cause the command to run a single shard of tests only.") 107 private Integer mShardCount; 108 109 @Option(name = "shard-index", description = 110 "the index of shard to run. Only set if shard-count > 1 and the value is in range " + 111 "[0, shard-count)") 112 private Integer mShardIndex; 113 114 @Option( 115 name = "skip-pre-device-setup", 116 description = 117 "allow TestInvocation to skip calling device.preInvocationSetup. This is for " 118 + "delaying device setup when the test runs with VersionedTfLauncher." 119 ) 120 private boolean mSkipPreDeviceSetup = false; 121 122 @Option( 123 name = "dynamic-sharding", 124 description = 125 "Allow to dynamically move IRemoteTest from one shard to another. Only for local " 126 + "sharding." 127 ) 128 private boolean mDynamicSharding = true; 129 130 @Option( 131 name = "invocation-data", 132 description = 133 "A map of values that describe the invocation, these values will be added to the " 134 + "invocation context." 135 ) 136 private UniqueMultiMap<String, String> mInvocationData = new UniqueMultiMap<>(); 137 138 @Option( 139 name = "disable-strict-sharding", 140 description = "Temporary option to disable the new sharding logic while being tested." 141 ) 142 private boolean mUseTfSharding = false; 143 144 public static final String USE_SANDBOX = "use-sandbox"; 145 146 @Option( 147 name = USE_SANDBOX, 148 description = "Set if the invocation should use a sandbox to run or not." 149 ) 150 private boolean mUseSandbox = false; 151 152 153 /** 154 * Set the help mode for the config. 155 * <p/> 156 * Exposed for testing. 157 */ setHelpMode(boolean helpMode)158 void setHelpMode(boolean helpMode) { 159 mHelpMode = helpMode; 160 } 161 162 /** 163 * {@inheritDoc} 164 */ 165 @Override isHelpMode()166 public boolean isHelpMode() { 167 return mHelpMode; 168 } 169 170 /** 171 * {@inheritDoc} 172 */ 173 @Override isFullHelpMode()174 public boolean isFullHelpMode() { 175 return mFullHelpMode; 176 } 177 178 /** 179 * Set the json help mode for the config. 180 * <p/> 181 * Exposed for testing. 182 */ setJsonHelpMode(boolean jsonHelpMode)183 void setJsonHelpMode(boolean jsonHelpMode) { 184 mJsonHelpMode = jsonHelpMode; 185 } 186 187 /** 188 * {@inheritDoc} 189 */ 190 @Override isJsonHelpMode()191 public boolean isJsonHelpMode() { 192 return mJsonHelpMode; 193 } 194 195 /** 196 * Set the dry run mode for the config. 197 * <p/> 198 * Exposed for testing. 199 */ setDryRunMode(boolean dryRunMode)200 void setDryRunMode(boolean dryRunMode) { 201 mDryRunMode = dryRunMode; 202 } 203 204 /** 205 * {@inheritDoc} 206 */ 207 @Override isDryRunMode()208 public boolean isDryRunMode() { 209 return mDryRunMode || mNoisyDryRunMode; 210 } 211 212 /** 213 * {@inheritDoc} 214 */ 215 @Override isNoisyDryRunMode()216 public boolean isNoisyDryRunMode() { 217 return mNoisyDryRunMode; 218 } 219 220 /** 221 * Set the loop mode for the config. 222 */ 223 @Override setLoopMode(boolean loopMode)224 public void setLoopMode(boolean loopMode) { 225 mLoopMode = loopMode; 226 } 227 228 /** 229 * {@inheritDoc} 230 */ 231 @Override isLoopMode()232 public boolean isLoopMode() { 233 return mLoopMode; 234 } 235 236 /** 237 * Set the min loop time for the config. 238 * <p/> 239 * Exposed for testing. 240 */ setMinLoopTime(long loopTime)241 void setMinLoopTime(long loopTime) { 242 mMinLoopTime = loopTime; 243 } 244 245 /** 246 * {@inheritDoc} 247 * @deprecated use {@link #getLoopTime()} instead 248 */ 249 @Deprecated 250 @Override getMinLoopTime()251 public long getMinLoopTime() { 252 return mMinLoopTime; 253 } 254 255 /** 256 * {@inheritDoc} 257 */ 258 @Override getLoopTime()259 public long getLoopTime() { 260 if (mMaxRandomLoopTime != null) { 261 long randomizedValue = mMaxRandomLoopTime - mMinLoopTime; 262 if (randomizedValue > 0) { 263 return mMinLoopTime + Math.round(randomizedValue * Math.random()); 264 } else { 265 CLog.e("max loop time %d is less than min loop time %d", mMaxRandomLoopTime, 266 mMinLoopTime); 267 } 268 } 269 return mMinLoopTime; 270 } 271 272 273 @Override clone()274 public ICommandOptions clone() { 275 CommandOptions clone = new CommandOptions(); 276 try { 277 OptionCopier.copyOptions(this, clone); 278 } catch (ConfigurationException e) { 279 CLog.e("failed to clone command options: %s", e.getMessage()); 280 } 281 return clone; 282 } 283 284 /** 285 * {@inheritDoc} 286 */ 287 @Override runOnAllDevices()288 public boolean runOnAllDevices() { 289 return mAllDevices; 290 } 291 292 /** 293 * {@inheritDoc} 294 */ 295 @Override takeBugreportOnInvocationEnded()296 public boolean takeBugreportOnInvocationEnded() { 297 return mTakeBugreportOnInvocationEnded; 298 } 299 300 /** {@inheritDoc} */ 301 @Override setBugreportOnInvocationEnded(boolean takeBugreport)302 public void setBugreportOnInvocationEnded(boolean takeBugreport) { 303 mTakeBugreportOnInvocationEnded = takeBugreport; 304 } 305 306 /** 307 * {@inheritDoc} 308 */ 309 @Override takeBugreportzOnInvocationEnded()310 public boolean takeBugreportzOnInvocationEnded() { 311 return mTakeBugreportzOnInvocationEnded; 312 } 313 314 /** {@inheritDoc} */ 315 @Override setBugreportzOnInvocationEnded(boolean takeBugreportz)316 public void setBugreportzOnInvocationEnded(boolean takeBugreportz) { 317 mTakeBugreportzOnInvocationEnded = takeBugreportz; 318 } 319 320 /** 321 * {@inheritDoc} 322 */ 323 @Override getInvocationTimeout()324 public long getInvocationTimeout() { 325 return mInvocationTimeout; 326 } 327 328 /** 329 * {@inheritDoc} 330 */ 331 @Override setInvocationTimeout(Long invocationTimeout)332 public void setInvocationTimeout(Long invocationTimeout) { 333 mInvocationTimeout = invocationTimeout; 334 } 335 336 /** 337 * {@inheritDoc} 338 */ 339 @Override getShardCount()340 public Integer getShardCount() { 341 return mShardCount; 342 } 343 344 /** 345 * {@inheritDoc} 346 */ 347 @Override setShardCount(Integer shardCount)348 public void setShardCount(Integer shardCount) { 349 mShardCount = shardCount; 350 } 351 352 /** 353 * {@inheritDoc} 354 */ 355 @Override getShardIndex()356 public Integer getShardIndex() { 357 return mShardIndex; 358 } 359 360 /** 361 * {@inheritDoc} 362 */ 363 @Override setShardIndex(Integer shardIndex)364 public void setShardIndex(Integer shardIndex) { 365 mShardIndex = shardIndex; 366 } 367 368 /** 369 * {@inheritDoc} 370 */ 371 @Override setTestTag(String testTag)372 public void setTestTag(String testTag) { 373 mTestTag = testTag; 374 } 375 376 /** 377 * {@inheritDoc} 378 */ 379 @Override getTestTag()380 public String getTestTag() { 381 return mTestTag; 382 } 383 384 /** 385 * {@inheritDoc} 386 */ 387 @Override getTestTagSuffix()388 public String getTestTagSuffix() { 389 return mTestTagSuffix; 390 } 391 392 /** {@inheritDoc} */ 393 @Override 394 shouldSkipPreDeviceSetup()395 public boolean shouldSkipPreDeviceSetup() { 396 return mSkipPreDeviceSetup; 397 } 398 399 /** {@inheritDoc} */ 400 @Override shouldUseDynamicSharding()401 public boolean shouldUseDynamicSharding() { 402 return mDynamicSharding; 403 } 404 405 /** {@inheritDoc} */ 406 @Override getInvocationData()407 public UniqueMultiMap<String, String> getInvocationData() { 408 return mInvocationData; 409 } 410 411 /** {@inheritDoc} */ 412 @Override shouldUseTfSharding()413 public boolean shouldUseTfSharding() { 414 return mUseTfSharding; 415 } 416 417 /** {@inheritDoc} */ 418 @Override shouldUseSandboxing()419 public boolean shouldUseSandboxing() { 420 return mUseSandbox; 421 } 422 423 /** {@inheritDoc} */ 424 @Override setShouldUseSandboxing(boolean use)425 public void setShouldUseSandboxing(boolean use) { 426 mUseSandbox = use; 427 } 428 } 429