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