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