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 /** Metadata key for a config to specify if it is prioritizing host config. */ 54 public static final String PRIORITIZE_HOST_CONFIG_KEY = "prioritize-host-config"; 55 56 /** Metadata key for a config to specify the module dir path when it's a module config. */ 57 public static final String MODULE_DIR_PATH_KEY = "module-dir-path"; 58 59 @Option(name = "test-suite-tag", description = "A membership tag to suite. Can be repeated.") 60 private List<String> mSuiteTags = new ArrayList<>(); 61 62 @Option(name = "metadata", description = "Metadata associated with this configuration, can be " 63 + "free formed key value pairs, and a key may be associated with multiple values.") 64 private MultiMap<String, String> mMetaData = new MultiMap<>(); 65 66 @Option( 67 name = "not-shardable", 68 description = 69 "A metadata that allows a suite configuration to specify that it cannot be " 70 + "sharded. Not because it doesn't support it but because it doesn't make " 71 + "sense." 72 ) 73 private boolean mNotShardable = false; 74 75 @Option( 76 name = "not-strict-shardable", 77 description = 78 "A metadata to allows a suite configuration to specify that it cannot be" 79 + " sharded in a strict context (independent shards). If a config is" 80 + " already not-shardable, it will be not-strict-shardable.") 81 private boolean mNotStrictShardable = false; 82 83 @Option( 84 name = "not-iremotetest-shardable", 85 description = 86 "A metadata to allows a suite configuration to specify that it cannot be" 87 + " sharded in a strict context (independent shards). If a config is" 88 + " already not-shardable, it will be not-strict-shardable.") 89 private boolean mNotIRemoteTestShardable = false; 90 91 @Option( 92 name = "use-sandboxing", 93 description = "Option used to notify an invocation that it is running in a sandbox." 94 ) 95 private boolean mUseSandboxing = false; 96 97 /** Optional Abi information the configuration will be run against. */ 98 private IAbi mAbi = null; 99 /** Optional for a module configuration, the original name of the module. */ 100 private String mModuleName = null; 101 /** Optional: track the shard index of the invocation */ 102 private Integer mShardIndex = null; 103 104 private MultiMap<String, String> mInternalMetaData = new MultiMap<>(); 105 106 /** a list of options applicable to rerun the test */ 107 private final List<OptionDef> mRerunOptions = new ArrayList<>(); 108 109 /** Returns the list of suite tags the test is part of. */ getSuiteTags()110 public List<String> getSuiteTags() { 111 return mSuiteTags; 112 } 113 114 /** Sets the list of suite tags the test is part of. */ setSuiteTags(List<String> suiteTags)115 public void setSuiteTags(List<String> suiteTags) { 116 mSuiteTags = suiteTags; 117 } 118 119 /** Retrieves all configured metadata and return a copy of the map. */ getAllMetaData()120 public MultiMap<String, String> getAllMetaData() { 121 MultiMap<String, String> copy = new MultiMap<>(); 122 copy.putAll(mMetaData); 123 copy.putAll(mInternalMetaData); 124 return copy; 125 } 126 127 /** Get the named metadata entries */ getMetaData(String name)128 public List<String> getMetaData(String name) { 129 MultiMap<String, String> copy = new MultiMap<>(); 130 copy.putAll(mMetaData); 131 copy.putAll(mInternalMetaData); 132 List<String> entry = copy.get(name); 133 if (entry == null) { 134 return null; 135 } 136 return new ArrayList<>(entry); 137 } 138 139 @VisibleForTesting setMetaData(MultiMap<String, String> metadata)140 public void setMetaData(MultiMap<String, String> metadata) { 141 mMetaData = metadata; 142 } 143 144 /** 145 * Add a value for a given key to the metadata entries. 146 * 147 * @param key {@link String} of the key to add values to. 148 * @param value A{@link String} of the additional value. 149 */ addMetadata(String key, String value)150 public void addMetadata(String key, String value) { 151 mInternalMetaData.put(key, value); 152 } 153 154 /** 155 * Add more values of a given key to the metadata entries. 156 * 157 * @param key {@link String} of the key to add values to. 158 * @param values a list of {@link String} of the additional values. 159 */ addMetadata(String key, List<String> values)160 public void addMetadata(String key, List<String> values) { 161 for (String source : values) { 162 mInternalMetaData.put(key, source); 163 } 164 } 165 166 /** 167 * Remove the tracking of the specified metadata key. 168 */ removeMetadata(String key)169 public List<String> removeMetadata(String key) { 170 return mInternalMetaData.remove(key); 171 } 172 173 /** Returns if the configuration is shardable or not as part of a suite */ isNotShardable()174 public boolean isNotShardable() { 175 return mNotShardable; 176 } 177 178 /** Returns if the configuration is strict shardable or not as part of a suite */ isNotStrictShardable()179 public boolean isNotStrictShardable() { 180 return mNotStrictShardable; 181 } 182 183 /** Returns if the configuration should split the IRemoteTest into different modules. */ isNotIRemoteTestShardable()184 public boolean isNotIRemoteTestShardable() { 185 return mNotIRemoteTestShardable; 186 } 187 setNotIRemoteTestShardable(boolean notIRemoteTestShardable)188 public void setNotIRemoteTestShardable(boolean notIRemoteTestShardable) { 189 mNotIRemoteTestShardable = notIRemoteTestShardable; 190 } 191 192 /** Sets the abi the configuration is going to run against. */ setAbi(IAbi abi)193 public void setAbi(IAbi abi) { 194 mAbi = abi; 195 } 196 197 /** Returns the abi the configuration is running against if known, null otherwise. */ getAbi()198 public IAbi getAbi() { 199 return mAbi; 200 } 201 202 /** If this configuration represents a module, we can set the module name associated with it. */ setModuleName(String name)203 public void setModuleName(String name) { 204 mModuleName = name; 205 } 206 207 /** Returns the module name of the module configuration. */ getModuleName()208 public String getModuleName() { 209 return mModuleName; 210 } 211 212 /** Returns true if the invocation should run in sandboxed mode. False otherwise. */ shouldUseSandbox()213 public boolean shouldUseSandbox() { 214 return mUseSandboxing; 215 } 216 217 /** Sets whether or not a config will run in sandboxed mode or not. */ setSandboxed(boolean useSandboxed)218 public void setSandboxed(boolean useSandboxed) { 219 mUseSandboxing = useSandboxed; 220 } 221 222 /** Set the shard index for the invocation in local sharding. */ setShardIndex(int index)223 public void setShardIndex(int index) { 224 mShardIndex = index; 225 } 226 227 /** Get the shard index of the invocation during local sharding. Returns null if no sharding. */ getShardIndex()228 public Integer getShardIndex() { 229 return mShardIndex; 230 } 231 232 /** 233 * Add the option to a list of options that can be used to rerun the test. 234 * 235 * @param optionDef a {@link OptionDef} object of the test option. 236 */ addRerunOption(OptionDef optionDef)237 public void addRerunOption(OptionDef optionDef) { 238 mRerunOptions.add(optionDef); 239 } 240 241 /** Get the list of {@link OptionDef} that can be used for rerun. */ getRerunOptions()242 public List<OptionDef> getRerunOptions() { 243 return mRerunOptions; 244 } 245 246 /** Convert the current instance of the descriptor into its proto format. */ toProto()247 public ConfigurationDescription.Descriptor toProto() { 248 Descriptor.Builder descriptorBuilder = Descriptor.newBuilder(); 249 // Test Suite Tags 250 descriptorBuilder.addAllTestSuiteTag(mSuiteTags); 251 // Metadata 252 List<Metadata> metadatas = new ArrayList<>(); 253 MultiMap<String, String> local = getAllMetaData(); 254 for (String key : local.keySet()) { 255 Metadata value = Metadata.newBuilder().setKey(key).addAllValue(local.get(key)).build(); 256 metadatas.add(value); 257 } 258 descriptorBuilder.addAllMetadata(metadatas); 259 // Shardable 260 descriptorBuilder.setShardable(!mNotShardable); 261 // Strict Shardable 262 descriptorBuilder.setStrictShardable(!mNotStrictShardable); 263 // Use sandboxing 264 descriptorBuilder.setUseSandboxing(mUseSandboxing); 265 // Module name 266 if (mModuleName != null) { 267 descriptorBuilder.setModuleName(mModuleName); 268 } 269 // Abi 270 if (mAbi != null) { 271 descriptorBuilder.setAbi(mAbi.toProto()); 272 } 273 return descriptorBuilder.build(); 274 } 275 276 /** Inverse operation from {@link #toProto()} to get the object back. */ fromProto( ConfigurationDescription.Descriptor protoDescriptor)277 public static ConfigurationDescriptor fromProto( 278 ConfigurationDescription.Descriptor protoDescriptor) { 279 ConfigurationDescriptor configDescriptor = new ConfigurationDescriptor(); 280 // Test Suite Tags 281 configDescriptor.mSuiteTags.addAll(protoDescriptor.getTestSuiteTagList()); 282 // Metadata 283 for (Metadata meta : protoDescriptor.getMetadataList()) { 284 for (String value : meta.getValueList()) { 285 configDescriptor.mMetaData.put(meta.getKey(), value); 286 } 287 } 288 // Shardable 289 configDescriptor.mNotShardable = !protoDescriptor.getShardable(); 290 // Strict Shardable 291 configDescriptor.mNotStrictShardable = !protoDescriptor.getStrictShardable(); 292 // Use sandboxing 293 configDescriptor.mUseSandboxing = protoDescriptor.getUseSandboxing(); 294 // Module Name 295 if (!protoDescriptor.getModuleName().isEmpty()) { 296 configDescriptor.mModuleName = protoDescriptor.getModuleName(); 297 } 298 // Abi 299 if (protoDescriptor.hasAbi()) { 300 configDescriptor.mAbi = Abi.fromProto(protoDescriptor.getAbi()); 301 } 302 return configDescriptor; 303 } 304 305 /** Return a deep-copy of the {@link ConfigurationDescriptor} object. */ 306 @Override clone()307 public ConfigurationDescriptor clone() { 308 return fromProto(this.toProto()); 309 } 310 } 311