1 /* 2 * Copyright (C) 2015 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 17 #ifndef AAPT_TEST_BUILDERS_H 18 #define AAPT_TEST_BUILDERS_H 19 20 #include <memory> 21 22 #include "android-base/logging.h" 23 #include "android-base/macros.h" 24 25 #include "ResourceTable.h" 26 #include "ResourceValues.h" 27 #include "test/Common.h" 28 #include "util/Util.h" 29 #include "xml/XmlDom.h" 30 31 namespace aapt { 32 namespace test { 33 34 class ResourceTableBuilder { 35 public: 36 ResourceTableBuilder() = default; 37 38 StringPool* string_pool() { return &table_->string_pool; } 39 40 ResourceTableBuilder& SetPackageId(const android::StringPiece& package_name, uint8_t id) { 41 ResourceTablePackage* package = table_->CreatePackage(package_name, id); 42 CHECK(package != nullptr); 43 return *this; 44 } 45 46 ResourceTableBuilder& AddSimple(const android::StringPiece& name, const ResourceId& id = {}) { 47 return AddValue(name, id, util::make_unique<Id>()); 48 } 49 50 ResourceTableBuilder& AddSimple(const android::StringPiece& name, const ConfigDescription& config, 51 const ResourceId& id = {}) { 52 return AddValue(name, config, id, util::make_unique<Id>()); 53 } 54 55 ResourceTableBuilder& AddReference(const android::StringPiece& name, 56 const android::StringPiece& ref) { 57 return AddReference(name, {}, ref); 58 } 59 60 ResourceTableBuilder& AddReference(const android::StringPiece& name, const ResourceId& id, 61 const android::StringPiece& ref) { 62 return AddValue(name, id, util::make_unique<Reference>(ParseNameOrDie(ref))); 63 } 64 65 ResourceTableBuilder& AddString(const android::StringPiece& name, 66 const android::StringPiece& str) { 67 return AddString(name, {}, str); 68 } 69 70 ResourceTableBuilder& AddString(const android::StringPiece& name, const ResourceId& id, 71 const android::StringPiece& str) { 72 return AddValue( 73 name, id, util::make_unique<String>(table_->string_pool.MakeRef(str))); 74 } 75 76 ResourceTableBuilder& AddString(const android::StringPiece& name, const ResourceId& id, 77 const ConfigDescription& config, 78 const android::StringPiece& str) { 79 return AddValue(name, config, id, util::make_unique<String>( 80 table_->string_pool.MakeRef(str))); 81 } 82 83 ResourceTableBuilder& AddFileReference(const android::StringPiece& name, 84 const android::StringPiece& path) { 85 return AddFileReference(name, {}, path); 86 } 87 88 ResourceTableBuilder& AddFileReference(const android::StringPiece& name, const ResourceId& id, 89 const android::StringPiece& path) { 90 return AddValue(name, id, util::make_unique<FileReference>( 91 table_->string_pool.MakeRef(path))); 92 } 93 94 ResourceTableBuilder& AddFileReference(const android::StringPiece& name, 95 const android::StringPiece& path, 96 const ConfigDescription& config) { 97 return AddValue(name, config, {}, util::make_unique<FileReference>( 98 table_->string_pool.MakeRef(path))); 99 } 100 101 ResourceTableBuilder& AddValue(const android::StringPiece& name, std::unique_ptr<Value> value) { 102 return AddValue(name, {}, std::move(value)); 103 } 104 105 ResourceTableBuilder& AddValue(const android::StringPiece& name, const ResourceId& id, 106 std::unique_ptr<Value> value) { 107 return AddValue(name, {}, id, std::move(value)); 108 } 109 110 ResourceTableBuilder& AddValue(const android::StringPiece& name, const ConfigDescription& config, 111 const ResourceId& id, std::unique_ptr<Value> value) { 112 ResourceName res_name = ParseNameOrDie(name); 113 CHECK(table_->AddResourceAllowMangled(res_name, id, config, {}, std::move(value), 114 GetDiagnostics())); 115 return *this; 116 } 117 118 ResourceTableBuilder& SetSymbolState(const android::StringPiece& name, const ResourceId& id, 119 SymbolState state, bool allow_new = false) { 120 ResourceName res_name = ParseNameOrDie(name); 121 Symbol symbol; 122 symbol.state = state; 123 symbol.allow_new = allow_new; 124 CHECK(table_->SetSymbolStateAllowMangled(res_name, id, symbol, GetDiagnostics())); 125 return *this; 126 } 127 128 std::unique_ptr<ResourceTable> Build() { return std::move(table_); } 129 130 private: 131 DISALLOW_COPY_AND_ASSIGN(ResourceTableBuilder); 132 133 std::unique_ptr<ResourceTable> table_ = util::make_unique<ResourceTable>(); 134 }; 135 136 inline std::unique_ptr<Reference> BuildReference(const android::StringPiece& ref, 137 const Maybe<ResourceId>& id = {}) { 138 std::unique_ptr<Reference> reference = 139 util::make_unique<Reference>(ParseNameOrDie(ref)); 140 reference->id = id; 141 return reference; 142 } 143 144 inline std::unique_ptr<BinaryPrimitive> BuildPrimitive(uint8_t type, 145 uint32_t data) { 146 android::Res_value value = {}; 147 value.size = sizeof(value); 148 value.dataType = type; 149 value.data = data; 150 return util::make_unique<BinaryPrimitive>(value); 151 } 152 153 template <typename T> 154 class ValueBuilder { 155 public: 156 template <typename... Args> 157 explicit ValueBuilder(Args&&... args) 158 : value_(new T{std::forward<Args>(args)...}) {} 159 160 template <typename... Args> 161 ValueBuilder& SetSource(Args&&... args) { 162 value_->SetSource(Source{std::forward<Args>(args)...}); 163 return *this; 164 } 165 166 ValueBuilder& SetComment(const android::StringPiece& str) { 167 value_->SetComment(str); 168 return *this; 169 } 170 171 std::unique_ptr<Value> Build() { return std::move(value_); } 172 173 private: 174 DISALLOW_COPY_AND_ASSIGN(ValueBuilder); 175 176 std::unique_ptr<Value> value_; 177 }; 178 179 class AttributeBuilder { 180 public: 181 explicit AttributeBuilder(bool weak = false) 182 : attr_(util::make_unique<Attribute>(weak)) { 183 attr_->type_mask = android::ResTable_map::TYPE_ANY; 184 } 185 186 AttributeBuilder& SetTypeMask(uint32_t typeMask) { 187 attr_->type_mask = typeMask; 188 return *this; 189 } 190 191 AttributeBuilder& AddItem(const android::StringPiece& name, uint32_t value) { 192 attr_->symbols.push_back(Attribute::Symbol{ 193 Reference(ResourceName({}, ResourceType::kId, name)), value}); 194 return *this; 195 } 196 197 std::unique_ptr<Attribute> Build() { return std::move(attr_); } 198 199 private: 200 DISALLOW_COPY_AND_ASSIGN(AttributeBuilder); 201 202 std::unique_ptr<Attribute> attr_; 203 }; 204 205 class StyleBuilder { 206 public: 207 StyleBuilder() = default; 208 209 StyleBuilder& SetParent(const android::StringPiece& str) { 210 style_->parent = Reference(ParseNameOrDie(str)); 211 return *this; 212 } 213 214 StyleBuilder& AddItem(const android::StringPiece& str, std::unique_ptr<Item> value) { 215 style_->entries.push_back( 216 Style::Entry{Reference(ParseNameOrDie(str)), std::move(value)}); 217 return *this; 218 } 219 220 StyleBuilder& AddItem(const android::StringPiece& str, const ResourceId& id, 221 std::unique_ptr<Item> value) { 222 AddItem(str, std::move(value)); 223 style_->entries.back().key.id = id; 224 return *this; 225 } 226 227 std::unique_ptr<Style> Build() { return std::move(style_); } 228 229 private: 230 DISALLOW_COPY_AND_ASSIGN(StyleBuilder); 231 232 std::unique_ptr<Style> style_ = util::make_unique<Style>(); 233 }; 234 235 class StyleableBuilder { 236 public: 237 StyleableBuilder() = default; 238 239 StyleableBuilder& AddItem(const android::StringPiece& str, const Maybe<ResourceId>& id = {}) { 240 styleable_->entries.push_back(Reference(ParseNameOrDie(str))); 241 styleable_->entries.back().id = id; 242 return *this; 243 } 244 245 std::unique_ptr<Styleable> Build() { return std::move(styleable_); } 246 247 private: 248 DISALLOW_COPY_AND_ASSIGN(StyleableBuilder); 249 250 std::unique_ptr<Styleable> styleable_ = util::make_unique<Styleable>(); 251 }; 252 253 inline std::unique_ptr<xml::XmlResource> BuildXmlDom(const android::StringPiece& str) { 254 std::stringstream in; 255 in << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" << str; 256 StdErrDiagnostics diag; 257 std::unique_ptr<xml::XmlResource> doc = 258 xml::Inflate(&in, &diag, Source("test.xml")); 259 CHECK(doc != nullptr) << "failed to parse inline XML string"; 260 return doc; 261 } 262 263 inline std::unique_ptr<xml::XmlResource> BuildXmlDomForPackageName( 264 IAaptContext* context, const android::StringPiece& str) { 265 std::unique_ptr<xml::XmlResource> doc = BuildXmlDom(str); 266 doc->file.name.package = context->GetCompilationPackage(); 267 return doc; 268 } 269 270 } // namespace test 271 } // namespace aapt 272 273 #endif /* AAPT_TEST_BUILDERS_H */ 274