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 "NameMangler.h"
21#include "util/Util.h"
22
23#include "process/IResourceTableConsumer.h"
24#include "process/SymbolTable.h"
25#include "test/Common.h"
26
27#include <cassert>
28#include <list>
29
30namespace aapt {
31namespace test {
32
33class Context : public IAaptContext {
34public:
35    SymbolTable* getExternalSymbols() override {
36        return &mSymbols;
37    }
38
39    IDiagnostics* getDiagnostics() override {
40        return &mDiagnostics;
41    }
42
43    const std::u16string& getCompilationPackage() override {
44        assert(mCompilationPackage && "package name not set");
45        return mCompilationPackage.value();
46    }
47
48    uint8_t getPackageId() override {
49        assert(mPackageId && "package ID not set");
50        return mPackageId.value();
51    }
52
53    NameMangler* getNameMangler() override {
54        return &mNameMangler;
55    }
56
57    bool verbose() override {
58        return false;
59    }
60
61private:
62    friend class ContextBuilder;
63
64    Context() : mNameMangler({}) {
65    }
66
67    Maybe<std::u16string> mCompilationPackage;
68    Maybe<uint8_t> mPackageId;
69    StdErrDiagnostics mDiagnostics;
70    SymbolTable mSymbols;
71    NameMangler mNameMangler;
72};
73
74class ContextBuilder {
75private:
76    std::unique_ptr<Context> mContext = std::unique_ptr<Context>(new Context());
77
78public:
79    ContextBuilder& setCompilationPackage(const StringPiece16& package) {
80        mContext->mCompilationPackage = package.toString();
81        return *this;
82    }
83
84    ContextBuilder& setPackageId(uint8_t id) {
85        mContext->mPackageId = id;
86        return *this;
87    }
88
89    ContextBuilder& setNameManglerPolicy(NameManglerPolicy policy) {
90        mContext->mNameMangler = NameMangler(policy);
91        return *this;
92    }
93
94    ContextBuilder& addSymbolSource(std::unique_ptr<ISymbolSource> src) {
95        mContext->getExternalSymbols()->appendSource(std::move(src));
96        return *this;
97    }
98
99    std::unique_ptr<Context> build() {
100        return std::move(mContext);
101    }
102};
103
104class StaticSymbolSourceBuilder {
105public:
106    StaticSymbolSourceBuilder& addPublicSymbol(const StringPiece16& name, ResourceId id,
107                                               std::unique_ptr<Attribute> attr = {}) {
108        std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>(
109                id, std::move(attr), true);
110        mSymbolSource->mNameMap[parseNameOrDie(name)] = symbol.get();
111        mSymbolSource->mIdMap[id] = symbol.get();
112        mSymbolSource->mSymbols.push_back(std::move(symbol));
113        return *this;
114    }
115
116    StaticSymbolSourceBuilder& addSymbol(const StringPiece16& name, ResourceId id,
117                                         std::unique_ptr<Attribute> attr = {}) {
118        std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>(
119                id, std::move(attr), false);
120        mSymbolSource->mNameMap[parseNameOrDie(name)] = symbol.get();
121        mSymbolSource->mIdMap[id] = symbol.get();
122        mSymbolSource->mSymbols.push_back(std::move(symbol));
123        return *this;
124    }
125
126    std::unique_ptr<ISymbolSource> build() {
127        return std::move(mSymbolSource);
128    }
129
130private:
131    class StaticSymbolSource : public ISymbolSource {
132    public:
133        StaticSymbolSource() = default;
134
135        std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) override {
136            auto iter = mNameMap.find(name);
137            if (iter != mNameMap.end()) {
138                return cloneSymbol(iter->second);
139            }
140            return nullptr;
141        }
142
143        std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) override {
144            auto iter = mIdMap.find(id);
145            if (iter != mIdMap.end()) {
146                return cloneSymbol(iter->second);
147            }
148            return nullptr;
149        }
150
151        std::list<std::unique_ptr<SymbolTable::Symbol>> mSymbols;
152        std::map<ResourceName, SymbolTable::Symbol*> mNameMap;
153        std::map<ResourceId, SymbolTable::Symbol*> mIdMap;
154
155    private:
156        std::unique_ptr<SymbolTable::Symbol> cloneSymbol(SymbolTable::Symbol* sym) {
157            std::unique_ptr<SymbolTable::Symbol> clone = util::make_unique<SymbolTable::Symbol>();
158            clone->id = sym->id;
159            if (sym->attribute) {
160                clone->attribute = std::unique_ptr<Attribute>(sym->attribute->clone(nullptr));
161            }
162            clone->isPublic = sym->isPublic;
163            return clone;
164        }
165
166        DISALLOW_COPY_AND_ASSIGN(StaticSymbolSource);
167    };
168
169    std::unique_ptr<StaticSymbolSource> mSymbolSource = util::make_unique<StaticSymbolSource>();
170};
171
172} // namespace test
173} // namespace aapt
174
175#endif /* AAPT_TEST_CONTEXT_H */
176