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_CONTEXT_H
18 #define AAPT_TEST_CONTEXT_H
19 
20 #include <list>
21 
22 #include "android-base/logging.h"
23 #include "android-base/macros.h"
24 
25 #include "NameMangler.h"
26 #include "process/IResourceTableConsumer.h"
27 #include "process/SymbolTable.h"
28 #include "test/Common.h"
29 #include "util/Util.h"
30 
31 namespace aapt {
32 namespace test {
33 
34 class Context : public IAaptContext {
35  public:
Context()36   Context() : name_mangler_({}), symbols_(&name_mangler_), min_sdk_version_(0) {}
37 
GetPackageType()38   PackageType GetPackageType() override {
39     return package_type_;
40   }
41 
GetExternalSymbols()42   SymbolTable* GetExternalSymbols() override {
43     return &symbols_;
44   }
45 
GetDiagnostics()46   IDiagnostics* GetDiagnostics() override {
47     return &diagnostics_;
48   }
49 
GetCompilationPackage()50   const std::string& GetCompilationPackage() override {
51     CHECK(bool(compilation_package_)) << "package name not set";
52     return compilation_package_.value();
53   }
54 
SetCompilationPackage(const android::StringPiece & package)55   void SetCompilationPackage(const android::StringPiece& package) {
56     compilation_package_ = package.to_string();
57   }
58 
GetPackageId()59   uint8_t GetPackageId() override {
60     CHECK(bool(package_id_)) << "package ID not set";
61     return package_id_.value();
62   }
63 
SetPackageId(uint8_t package_id)64   void SetPackageId(uint8_t package_id) {
65     package_id_ = package_id;
66   }
67 
GetNameMangler()68   NameMangler* GetNameMangler() override {
69     return &name_mangler_;
70   }
71 
SetNameManglerPolicy(const NameManglerPolicy & policy)72   void SetNameManglerPolicy(const NameManglerPolicy& policy) {
73     name_mangler_ = NameMangler(policy);
74   }
75 
IsVerbose()76   bool IsVerbose() override {
77     return false;
78   }
79 
GetMinSdkVersion()80   int GetMinSdkVersion() override {
81     return min_sdk_version_;
82   }
83 
84  private:
85   DISALLOW_COPY_AND_ASSIGN(Context);
86 
87   friend class ContextBuilder;
88 
89   PackageType package_type_ = PackageType::kApp;
90   Maybe<std::string> compilation_package_;
91   Maybe<uint8_t> package_id_;
92   StdErrDiagnostics diagnostics_;
93   NameMangler name_mangler_;
94   SymbolTable symbols_;
95   int min_sdk_version_;
96 };
97 
98 class ContextBuilder {
99  public:
SetPackageType(PackageType type)100   ContextBuilder& SetPackageType(PackageType type) {
101     context_->package_type_ = type;
102     return *this;
103   }
104 
SetCompilationPackage(const android::StringPiece & package)105   ContextBuilder& SetCompilationPackage(const android::StringPiece& package) {
106     context_->compilation_package_ = package.to_string();
107     return *this;
108   }
109 
SetPackageId(uint8_t id)110   ContextBuilder& SetPackageId(uint8_t id) {
111     context_->package_id_ = id;
112     return *this;
113   }
114 
SetNameManglerPolicy(const NameManglerPolicy & policy)115   ContextBuilder& SetNameManglerPolicy(const NameManglerPolicy& policy) {
116     context_->name_mangler_ = NameMangler(policy);
117     return *this;
118   }
119 
AddSymbolSource(std::unique_ptr<ISymbolSource> src)120   ContextBuilder& AddSymbolSource(std::unique_ptr<ISymbolSource> src) {
121     context_->GetExternalSymbols()->AppendSource(std::move(src));
122     return *this;
123   }
124 
SetMinSdkVersion(int min_sdk)125   ContextBuilder& SetMinSdkVersion(int min_sdk) {
126     context_->min_sdk_version_ = min_sdk;
127     return *this;
128   }
129 
Build()130   std::unique_ptr<Context> Build() { return std::move(context_); }
131 
132  private:
133   std::unique_ptr<Context> context_ = std::unique_ptr<Context>(new Context());
134 };
135 
136 class StaticSymbolSourceBuilder {
137  public:
138   StaticSymbolSourceBuilder& AddPublicSymbol(const android::StringPiece& name, ResourceId id,
139                                              std::unique_ptr<Attribute> attr = {}) {
140     std::unique_ptr<SymbolTable::Symbol> symbol =
141         util::make_unique<SymbolTable::Symbol>(id, std::move(attr), true);
142     symbol_source_->name_map_[ParseNameOrDie(name)] = symbol.get();
143     symbol_source_->id_map_[id] = symbol.get();
144     symbol_source_->symbols_.push_back(std::move(symbol));
145     return *this;
146   }
147 
148   StaticSymbolSourceBuilder& AddSymbol(const android::StringPiece& name, ResourceId id,
149                                        std::unique_ptr<Attribute> attr = {}) {
150     std::unique_ptr<SymbolTable::Symbol> symbol =
151         util::make_unique<SymbolTable::Symbol>(id, std::move(attr), false);
152     symbol_source_->name_map_[ParseNameOrDie(name)] = symbol.get();
153     symbol_source_->id_map_[id] = symbol.get();
154     symbol_source_->symbols_.push_back(std::move(symbol));
155     return *this;
156   }
157 
Build()158   std::unique_ptr<ISymbolSource> Build() {
159     return std::move(symbol_source_);
160   }
161 
162  private:
163   class StaticSymbolSource : public ISymbolSource {
164    public:
165     StaticSymbolSource() = default;
166 
FindByName(const ResourceName & name)167     std::unique_ptr<SymbolTable::Symbol> FindByName(const ResourceName& name) override {
168       auto iter = name_map_.find(name);
169       if (iter != name_map_.end()) {
170         return CloneSymbol(iter->second);
171       }
172       return nullptr;
173     }
174 
FindById(ResourceId id)175     std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) override {
176       auto iter = id_map_.find(id);
177       if (iter != id_map_.end()) {
178         return CloneSymbol(iter->second);
179       }
180       return nullptr;
181     }
182 
183     std::list<std::unique_ptr<SymbolTable::Symbol>> symbols_;
184     std::map<ResourceName, SymbolTable::Symbol*> name_map_;
185     std::map<ResourceId, SymbolTable::Symbol*> id_map_;
186 
187    private:
CloneSymbol(SymbolTable::Symbol * sym)188     std::unique_ptr<SymbolTable::Symbol> CloneSymbol(SymbolTable::Symbol* sym) {
189       std::unique_ptr<SymbolTable::Symbol> clone = util::make_unique<SymbolTable::Symbol>();
190       clone->id = sym->id;
191       if (sym->attribute) {
192         clone->attribute = std::unique_ptr<Attribute>(sym->attribute->Clone(nullptr));
193       }
194       clone->is_public = sym->is_public;
195       return clone;
196     }
197 
198     DISALLOW_COPY_AND_ASSIGN(StaticSymbolSource);
199   };
200 
201   std::unique_ptr<StaticSymbolSource> symbol_source_ = util::make_unique<StaticSymbolSource>();
202 };
203 
204 }  // namespace test
205 }  // namespace aapt
206 
207 #endif /* AAPT_TEST_CONTEXT_H */
208