blob: b1e201b3ec1b1c64a8af15d6d609d18adf812304 [file] [log] [blame]
Adam Lesinski6f6ceb72014-11-14 14:48:12 -08001/*
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#include "Linker.h"
18#include "Resolver.h"
19#include "ResourceTable.h"
20#include "ResourceValues.h"
21#include "Util.h"
22
23#include <androidfw/AssetManager.h>
24#include <gtest/gtest.h>
25#include <string>
26
27namespace aapt {
28
29struct LinkerTest : public ::testing::Test {
30 virtual void SetUp() override {
31 mTable = std::make_shared<ResourceTable>();
32 mTable->setPackage(u"android");
33 mLinker = std::make_shared<Linker>(mTable, std::make_shared<Resolver>(
34 mTable, std::make_shared<android::AssetManager>()));
35
36 // Create a few attributes for use in the tests.
37
38 addResource(ResourceName{ {}, ResourceType::kAttr, u"integer" },
39 util::make_unique<Attribute>(false, android::ResTable_map::TYPE_INTEGER));
40
41 addResource(ResourceName{ {}, ResourceType::kAttr, u"string" },
42 util::make_unique<Attribute>(false, android::ResTable_map::TYPE_STRING));
43
44 addResource(ResourceName{ {}, ResourceType::kId, u"apple" }, util::make_unique<Id>());
45
46 addResource(ResourceName{ {}, ResourceType::kId, u"banana" }, util::make_unique<Id>());
47
48 std::unique_ptr<Attribute> flagAttr = util::make_unique<Attribute>(
49 false, android::ResTable_map::TYPE_FLAGS);
50 flagAttr->symbols.push_back(Attribute::Symbol{
51 ResourceNameRef{ u"android", ResourceType::kId, u"apple" }, 1 });
52 flagAttr->symbols.push_back(Attribute::Symbol{
53 ResourceNameRef{ u"android", ResourceType::kId, u"banana" }, 2 });
54 addResource(ResourceName{ {}, ResourceType::kAttr, u"flags" }, std::move(flagAttr));
55 }
56
57 /*
58 * Convenience method for adding resources with the default configuration and some
59 * bogus source line.
60 */
61 bool addResource(const ResourceNameRef& name, std::unique_ptr<Value> value) {
62 return mTable->addResource(name, {}, SourceLine{ "test.xml", 21 }, std::move(value));
63 }
64
65 std::shared_ptr<ResourceTable> mTable;
66 std::shared_ptr<Linker> mLinker;
67};
68
69TEST_F(LinkerTest, DoNotInterpretEscapedStringAsReference) {
70 ASSERT_TRUE(addResource(ResourceName{ u"android", ResourceType::kString, u"foo" },
71 util::make_unique<String>(mTable->getValueStringPool().makeRef(u"?123"))));
72
73 ASSERT_TRUE(mLinker->linkAndValidate());
74 EXPECT_TRUE(mLinker->getUnresolvedReferences().empty());
75}
76
77TEST_F(LinkerTest, EscapeAndConvertRawString) {
78 std::unique_ptr<Style> style = util::make_unique<Style>();
79 style->entries.push_back(Style::Entry{
80 ResourceNameRef{ u"android", ResourceType::kAttr, u"integer" },
81 util::make_unique<RawString>(mTable->getValueStringPool().makeRef(u" 123"))
82 });
83 const Style* result = style.get();
84 ASSERT_TRUE(addResource(ResourceName{ u"android", ResourceType::kStyle, u"foo" },
85 std::move(style)));
86
87 ASSERT_TRUE(mLinker->linkAndValidate());
88 EXPECT_TRUE(mLinker->getUnresolvedReferences().empty());
89
90 EXPECT_NE(nullptr, dynamic_cast<BinaryPrimitive*>(result->entries.front().value.get()));
91}
92
93TEST_F(LinkerTest, FailToConvertRawString) {
94 std::unique_ptr<Style> style = util::make_unique<Style>();
95 style->entries.push_back(Style::Entry{
96 ResourceNameRef{ u"android", ResourceType::kAttr, u"integer" },
97 util::make_unique<RawString>(mTable->getValueStringPool().makeRef(u"yo what is up?"))
98 });
99 ASSERT_TRUE(addResource(ResourceName{ u"android", ResourceType::kStyle, u"foo" },
100 std::move(style)));
101
102 ASSERT_FALSE(mLinker->linkAndValidate());
103}
104
105TEST_F(LinkerTest, ConvertRawStringToString) {
106 std::unique_ptr<Style> style = util::make_unique<Style>();
107 style->entries.push_back(Style::Entry{
108 ResourceNameRef{ u"android", ResourceType::kAttr, u"string" },
109 util::make_unique<RawString>(
110 mTable->getValueStringPool().makeRef(u" \"this is \\u00fa\"."))
111 });
112 const Style* result = style.get();
113 ASSERT_TRUE(addResource(ResourceName{ u"android", ResourceType::kStyle, u"foo" },
114 std::move(style)));
115
116 ASSERT_TRUE(mLinker->linkAndValidate());
117 EXPECT_TRUE(mLinker->getUnresolvedReferences().empty());
118
119 const String* str = dynamic_cast<const String*>(result->entries.front().value.get());
120 ASSERT_NE(nullptr, str);
121 EXPECT_EQ(*str->value, u"this is \u00fa.");
122}
123
124TEST_F(LinkerTest, ConvertRawStringToFlags) {
125 std::unique_ptr<Style> style = util::make_unique<Style>();
126 style->entries.push_back(Style::Entry{
127 ResourceNameRef{ u"android", ResourceType::kAttr, u"flags" },
128 util::make_unique<RawString>(mTable->getValueStringPool().makeRef(u"banana | apple"))
129 });
130 const Style* result = style.get();
131 ASSERT_TRUE(addResource(ResourceName{ u"android", ResourceType::kStyle, u"foo" },
132 std::move(style)));
133
134 ASSERT_TRUE(mLinker->linkAndValidate());
135 EXPECT_TRUE(mLinker->getUnresolvedReferences().empty());
136
137 const BinaryPrimitive* bin = dynamic_cast<const BinaryPrimitive*>(
138 result->entries.front().value.get());
139 ASSERT_NE(nullptr, bin);
140 EXPECT_EQ(bin->value.data, 1u | 2u);
141}
142
143} // namespace aapt