1 /*
2  * Copyright (C) 2016 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.config;
17 
18 import com.android.tradefed.build.BuildSerializedVersion;
19 import com.android.tradefed.config.proto.ConfigurationDescription;
20 import com.android.tradefed.config.proto.ConfigurationDescription.Descriptor;
21 import com.android.tradefed.config.proto.ConfigurationDescription.Metadata;
22 import com.android.tradefed.testtype.Abi;
23 import com.android.tradefed.testtype.IAbi;
24 import com.android.tradefed.util.MultiMap;
25 
26 import com.google.common.annotations.VisibleForTesting;
27 
28 import java.io.Serializable;
29 import java.util.ArrayList;
30 import java.util.List;
31 
32 /**
33  * Configuration Object that describes some aspect of the configuration itself. Like a membership
34  * test-suite-tag. This class cannot receive option values via command line. Only directly in the
35  * xml.
36  */
37 @OptionClass(alias = "config-descriptor")
38 public class ConfigurationDescriptor implements Serializable, Cloneable {
39 
40     /** Enum used to indicate local test runner. */
41     public enum LocalTestRunner {
42         NONE,
43         ATEST;
44     }
45 
46     private static final long serialVersionUID = BuildSerializedVersion.VERSION;
47 
48     /** Metadata key for a config to specify that it was sharded. */
49     public static final String LOCAL_SHARDED_KEY = "sharded";
50     /** Metadata key for a config parameterization, optional. */
51     public static final String ACTIVE_PARAMETER_KEY = "active-parameter";
52 
53     @Option(name = "test-suite-tag", description = "A membership tag to suite. Can be repeated.")
54     private List<String> mSuiteTags = new ArrayList<>();
55 
56     @Option(name = "metadata", description = "Metadata associated with this configuration, can be "
57             + "free formed key value pairs, and a key may be associated with multiple values.")
58     private MultiMap<String, String> mMetaData = new MultiMap<>();
59 
60     @Option(
61         name = "not-shardable",
62         description =
63                 "A metadata that allows a suite configuration to specify that it cannot be "
64                         + "sharded. Not because it doesn't support it but because it doesn't make "
65                         + "sense."
66     )
67     private boolean mNotShardable = false;
68 
69     @Option(
70         name = "not-strict-shardable",
71         description =
72                 "A metadata to allows a suite configuration to specify that it cannot be "
73                         + "sharded in a strict context (independent shards). If a config is already "
74                         + "not-shardable, it will be not-strict-shardable."
75     )
76     private boolean mNotStrictShardable = false;
77 
78     @Option(
79         name = "use-sandboxing",
80         description = "Option used to notify an invocation that it is running in a sandbox."
81     )
82     private boolean mUseSandboxing = false;
83 
84     /** Optional Abi information the configuration will be run against. */
85     private IAbi mAbi = null;
86     /** Optional for a module configuration, the original name of the module. */
87     private String mModuleName = null;
88 
89     /** a list of options applicable to rerun the test */
90     private final List<OptionDef> mRerunOptions = new ArrayList<>();
91 
92     /** Returns the list of suite tags the test is part of. */
getSuiteTags()93     public List<String> getSuiteTags() {
94         return mSuiteTags;
95     }
96 
97     /** Sets the list of suite tags the test is part of. */
setSuiteTags(List<String> suiteTags)98     public void setSuiteTags(List<String> suiteTags) {
99         mSuiteTags = suiteTags;
100     }
101 
102     /** Retrieves all configured metadata and return a copy of the map. */
getAllMetaData()103     public MultiMap<String, String> getAllMetaData() {
104         MultiMap<String, String> copy = new MultiMap<>();
105         copy.putAll(mMetaData);
106         return copy;
107     }
108 
109     /** Get the named metadata entries */
getMetaData(String name)110     public List<String> getMetaData(String name) {
111         List<String> entry = mMetaData.get(name);
112         if (entry == null) {
113             return null;
114         }
115         return new ArrayList<>(entry);
116     }
117 
118     @VisibleForTesting
setMetaData(MultiMap<String, String> metadata)119     public void setMetaData(MultiMap<String, String> metadata) {
120         mMetaData = metadata;
121     }
122 
123     /**
124      * Add a value for a given key to the metadata entries.
125      *
126      * @param key {@link String} of the key to add values to.
127      * @param value A{@link String} of the additional value.
128      */
addMetadata(String key, String value)129     public void addMetadata(String key, String value) {
130         mMetaData.put(key, value);
131     }
132 
133     /**
134      * Add more values of a given key to the metadata entries.
135      *
136      * @param key {@link String} of the key to add values to.
137      * @param values a list of {@link String} of the additional values.
138      */
addMetadata(String key, List<String> values)139     public void addMetadata(String key, List<String> values) {
140         for (String source : values) {
141             mMetaData.put(key, source);
142         }
143     }
144 
145     /** Returns if the configuration is shardable or not as part of a suite */
isNotShardable()146     public boolean isNotShardable() {
147         return mNotShardable;
148     }
149 
150     /** Returns if the configuration is strict shardable or not as part of a suite */
isNotStrictShardable()151     public boolean isNotStrictShardable() {
152         return mNotStrictShardable;
153     }
154 
155     /** Sets the abi the configuration is going to run against. */
setAbi(IAbi abi)156     public void setAbi(IAbi abi) {
157         mAbi = abi;
158     }
159 
160     /** Returns the abi the configuration is running against if known, null otherwise. */
getAbi()161     public IAbi getAbi() {
162         return mAbi;
163     }
164 
165     /** If this configuration represents a module, we can set the module name associated with it. */
setModuleName(String name)166     public void setModuleName(String name) {
167         mModuleName = name;
168     }
169 
170     /** Returns the module name of the module configuration. */
getModuleName()171     public String getModuleName() {
172         return mModuleName;
173     }
174 
175     /** Returns true if the invocation should run in sandboxed mode. False otherwise. */
shouldUseSandbox()176     public boolean shouldUseSandbox() {
177         return mUseSandboxing;
178     }
179 
180     /** Sets whether or not a config will run in sandboxed mode or not. */
setSandboxed(boolean useSandboxed)181     public void setSandboxed(boolean useSandboxed) {
182         mUseSandboxing = useSandboxed;
183     }
184 
185     /**
186      * Add the option to a list of options that can be used to rerun the test.
187      *
188      * @param optionDef a {@link OptionDef} object of the test option.
189      */
addRerunOption(OptionDef optionDef)190     public void addRerunOption(OptionDef optionDef) {
191         mRerunOptions.add(optionDef);
192     }
193 
194     /** Get the list of {@link OptionDef} that can be used for rerun. */
getRerunOptions()195     public List<OptionDef> getRerunOptions() {
196         return mRerunOptions;
197     }
198 
199     /** Convert the current instance of the descriptor into its proto format. */
toProto()200     public ConfigurationDescription.Descriptor toProto() {
201         Descriptor.Builder descriptorBuilder = Descriptor.newBuilder();
202         // Test Suite Tags
203         descriptorBuilder.addAllTestSuiteTag(mSuiteTags);
204         // Metadata
205         List<Metadata> metadatas = new ArrayList<>();
206         for (String key : mMetaData.keySet()) {
207             Metadata value =
208                     Metadata.newBuilder().setKey(key).addAllValue(mMetaData.get(key)).build();
209             metadatas.add(value);
210         }
211         descriptorBuilder.addAllMetadata(metadatas);
212         // Shardable
213         descriptorBuilder.setShardable(!mNotShardable);
214         // Strict Shardable
215         descriptorBuilder.setStrictShardable(!mNotStrictShardable);
216         // Use sandboxing
217         descriptorBuilder.setUseSandboxing(mUseSandboxing);
218         // Module name
219         if (mModuleName != null) {
220             descriptorBuilder.setModuleName(mModuleName);
221         }
222         // Abi
223         if (mAbi != null) {
224             descriptorBuilder.setAbi(mAbi.toProto());
225         }
226         return descriptorBuilder.build();
227     }
228 
229     /** Inverse operation from {@link #toProto()} to get the object back. */
fromProto( ConfigurationDescription.Descriptor protoDescriptor)230     public static ConfigurationDescriptor fromProto(
231             ConfigurationDescription.Descriptor protoDescriptor) {
232         ConfigurationDescriptor configDescriptor = new ConfigurationDescriptor();
233         // Test Suite Tags
234         configDescriptor.mSuiteTags.addAll(protoDescriptor.getTestSuiteTagList());
235         // Metadata
236         for (Metadata meta : protoDescriptor.getMetadataList()) {
237             for (String value : meta.getValueList()) {
238                 configDescriptor.mMetaData.put(meta.getKey(), value);
239             }
240         }
241         // Shardable
242         configDescriptor.mNotShardable = !protoDescriptor.getShardable();
243         // Strict Shardable
244         configDescriptor.mNotStrictShardable = !protoDescriptor.getStrictShardable();
245         // Use sandboxing
246         configDescriptor.mUseSandboxing = protoDescriptor.getUseSandboxing();
247         // Module Name
248         if (!protoDescriptor.getModuleName().isEmpty()) {
249             configDescriptor.mModuleName = protoDescriptor.getModuleName();
250         }
251         // Abi
252         if (protoDescriptor.hasAbi()) {
253             configDescriptor.mAbi = Abi.fromProto(protoDescriptor.getAbi());
254         }
255         return configDescriptor;
256     }
257 
258     /** Return a deep-copy of the {@link ConfigurationDescriptor} object. */
259     @Override
clone()260     public ConfigurationDescriptor clone() {
261         return fromProto(this.toProto());
262     }
263 }
264