blob: 4f43c4069edc58b6989d6d97478850434d5188c6 [file] [log] [blame]
Adam Lesinski1ab598f2015-08-14 14:26:04 -07001/*
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 "compile/IdAssigner.h"
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -070018#include "test/Test.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070019
20namespace aapt {
21
22::testing::AssertionResult verifyIds(ResourceTable* table);
23
24TEST(IdAssignerTest, AssignIds) {
25 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
Adam Lesinskid0f116b2016-07-08 15:00:32 -070026 .addSimple("@android:attr/foo")
27 .addSimple("@android:attr/bar")
28 .addSimple("@android:id/foo")
29 .setPackageId("android", 0x01)
Adam Lesinski1ab598f2015-08-14 14:26:04 -070030 .build();
31
32 std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
33 IdAssigner assigner;
34
35 ASSERT_TRUE(assigner.consume(context.get(), table.get()));
36 ASSERT_TRUE(verifyIds(table.get()));
37}
38
39TEST(IdAssignerTest, AssignIdsWithReservedIds) {
40 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -070041 .addSimple("@android:id/foo", ResourceId(0x01010000))
42 .addSimple("@android:dimen/two")
43 .addSimple("@android:integer/three")
44 .addSimple("@android:string/five")
45 .addSimple("@android:attr/fun", ResourceId(0x01040000))
Adam Lesinskid0f116b2016-07-08 15:00:32 -070046 .addSimple("@android:attr/foo", ResourceId(0x01040006))
47 .addSimple("@android:attr/bar")
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -070048 .addSimple("@android:attr/baz")
Adam Lesinskid0f116b2016-07-08 15:00:32 -070049 .addSimple("@app:id/biz")
50 .setPackageId("android", 0x01)
51 .setPackageId("app", 0x7f)
Adam Lesinski1ab598f2015-08-14 14:26:04 -070052 .build();
53
54 std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
55 IdAssigner assigner;
56
57 ASSERT_TRUE(assigner.consume(context.get(), table.get()));
58 ASSERT_TRUE(verifyIds(table.get()));
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -070059
60 Maybe<ResourceTable::SearchResult> maybeResult;
61
62 // Expect to fill in the gaps between 0x0101XXXX and 0x0104XXXX.
63
64 maybeResult = table->findResource(test::parseNameOrDie("@android:dimen/two"));
65 AAPT_ASSERT_TRUE(maybeResult);
66 EXPECT_EQ(make_value<uint8_t>(2), maybeResult.value().type->id);
67
68 maybeResult = table->findResource(test::parseNameOrDie("@android:integer/three"));
69 AAPT_ASSERT_TRUE(maybeResult);
70 EXPECT_EQ(make_value<uint8_t>(3), maybeResult.value().type->id);
71
72 // Expect to bypass the reserved 0x0104XXXX IDs and use the next 0x0105XXXX IDs.
73
74 maybeResult = table->findResource(test::parseNameOrDie("@android:string/five"));
75 AAPT_ASSERT_TRUE(maybeResult);
76 EXPECT_EQ(make_value<uint8_t>(5), maybeResult.value().type->id);
77
78 // Expect to fill in the gaps between 0x01040000 and 0x01040006.
79
80 maybeResult = table->findResource(test::parseNameOrDie("@android:attr/bar"));
81 AAPT_ASSERT_TRUE(maybeResult);
82 EXPECT_EQ(make_value<uint16_t>(1), maybeResult.value().entry->id);
83
84 maybeResult = table->findResource(test::parseNameOrDie("@android:attr/baz"));
85 AAPT_ASSERT_TRUE(maybeResult);
86 EXPECT_EQ(make_value<uint16_t>(2), maybeResult.value().entry->id);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070087}
88
89TEST(IdAssignerTest, FailWhenNonUniqueIdsAssigned) {
90 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
Adam Lesinskid0f116b2016-07-08 15:00:32 -070091 .addSimple("@android:attr/foo", ResourceId(0x01040006))
92 .addSimple("@android:attr/bar", ResourceId(0x01040006))
93 .setPackageId("android", 0x01)
94 .setPackageId("app", 0x7f)
Adam Lesinski1ab598f2015-08-14 14:26:04 -070095 .build();
96
97 std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
98 IdAssigner assigner;
99
100 ASSERT_FALSE(assigner.consume(context.get(), table.get()));
101}
102
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -0700103TEST(IdAssignerTest, AssignIdsWithIdMap) {
104 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
105 .addSimple("@android:attr/foo")
106 .addSimple("@android:attr/bar")
107 .setPackageId("android", 0x01)
108 .build();
109
110 std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
111 std::unordered_map<ResourceName, ResourceId> idMap = {
112 { test::parseNameOrDie("@android:attr/foo"), ResourceId(0x01010002) } };
113 IdAssigner assigner(&idMap);
114 ASSERT_TRUE(assigner.consume(context.get(), table.get()));
115 ASSERT_TRUE(verifyIds(table.get()));
116 Maybe<ResourceTable::SearchResult> result = table->findResource(
117 test::parseNameOrDie("@android:attr/foo"));
118 AAPT_ASSERT_TRUE(result);
119
120 const ResourceTable::SearchResult& searchResult = result.value();
121 EXPECT_EQ(make_value<uint8_t>(0x01), searchResult.package->id);
122 EXPECT_EQ(make_value<uint8_t>(0x01), searchResult.type->id);
123 EXPECT_EQ(make_value<uint16_t>(0x0002), searchResult.entry->id);
124}
125
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700126::testing::AssertionResult verifyIds(ResourceTable* table) {
127 std::set<uint8_t> packageIds;
128 for (auto& package : table->packages) {
129 if (!package->id) {
130 return ::testing::AssertionFailure() << "package " << package->name << " has no ID";
131 }
132
133 if (!packageIds.insert(package->id.value()).second) {
134 return ::testing::AssertionFailure() << "package " << package->name
135 << " has non-unique ID " << std::hex << (int) package->id.value() << std::dec;
136 }
137 }
138
139 for (auto& package : table->packages) {
140 std::set<uint8_t> typeIds;
141 for (auto& type : package->types) {
142 if (!type->id) {
143 return ::testing::AssertionFailure() << "type " << type->type << " of package "
144 << package->name << " has no ID";
145 }
146
147 if (!typeIds.insert(type->id.value()).second) {
148 return ::testing::AssertionFailure() << "type " << type->type
149 << " of package " << package->name << " has non-unique ID "
150 << std::hex << (int) type->id.value() << std::dec;
151 }
152 }
153
154
155 for (auto& type : package->types) {
156 std::set<uint16_t> entryIds;
157 for (auto& entry : type->entries) {
158 if (!entry->id) {
159 return ::testing::AssertionFailure() << "entry " << entry->name << " of type "
160 << type->type << " of package " << package->name << " has no ID";
161 }
162
163 if (!entryIds.insert(entry->id.value()).second) {
164 return ::testing::AssertionFailure() << "entry " << entry->name
165 << " of type " << type->type << " of package " << package->name
166 << " has non-unique ID "
167 << std::hex << (int) entry->id.value() << std::dec;
168 }
169 }
170 }
171 }
172 return ::testing::AssertionSuccess() << "all IDs are unique and assigned";
173}
174
175} // namespace aapt