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
31namespace aapt {
32namespace test {
33
34class Context : public IAaptContext {
35 public:
36  Context() : name_mangler_({}), symbols_(&name_mangler_), min_sdk_version_(0) {}
37
38  PackageType GetPackageType() override {
39    return package_type_;
40  }
41
42  SymbolTable* GetExternalSymbols() override {
43    return &symbols_;
44  }
45
46  IDiagnostics* GetDiagnostics() override {
47    return &diagnostics_;
48  }
49
50  const std::string& GetCompilationPackage() override {
51    CHECK(bool(compilation_package_)) << "package name not set";
52    return compilation_package_.value();
53  }
54
55  void SetCompilationPackage(const android::StringPiece& package) {
56    compilation_package_ = package.to_string();
57  }
58
59  uint8_t GetPackageId() override {
60    CHECK(bool(package_id_)) << "package ID not set";
61    return package_id_.value();
62  }
63
64  void SetPackageId(uint8_t package_id) {
65    package_id_ = package_id;
66  }
67
68  NameMangler* GetNameMangler() override {
69    return &name_mangler_;
70  }
71
72  void SetNameManglerPolicy(const NameManglerPolicy& policy) {
73    name_mangler_ = NameMangler(policy);
74  }
75
76  bool IsVerbose() override {
77    return false;
78  }
79
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
98class ContextBuilder {
99 public:
100  ContextBuilder& SetPackageType(PackageType type) {
101    context_->package_type_ = type;
102    return *this;
103  }
104
105  ContextBuilder& SetCompilationPackage(const android::StringPiece& package) {
106    context_->compilation_package_ = package.to_string();
107    return *this;
108  }
109
110  ContextBuilder& SetPackageId(uint8_t id) {
111    context_->package_id_ = id;
112    return *this;
113  }
114
115  ContextBuilder& SetNameManglerPolicy(const NameManglerPolicy& policy) {
116    context_->name_mangler_ = NameMangler(policy);
117    return *this;
118  }
119
120  ContextBuilder& AddSymbolSource(std::unique_ptr<ISymbolSource> src) {
121    context_->GetExternalSymbols()->AppendSource(std::move(src));
122    return *this;
123  }
124
125  ContextBuilder& SetMinSdkVersion(int min_sdk) {
126    context_->min_sdk_version_ = min_sdk;
127    return *this;
128  }
129
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
136class 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
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
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
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:
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