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