blob: ff7bf5ce719523b6a3a27e6d493f5330eaee144e [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) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070025 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
26 .addSimple("android:attr/foo")
27 .addSimple("android:attr/bar")
28 .addSimple("android:id/foo")
29 .setPackageId("android", 0x01)
30 .build();
Adam Lesinski1ab598f2015-08-14 14:26:04 -070031
Adam Lesinskicacb28f2016-10-19 12:18:14 -070032 std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
33 IdAssigner assigner;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070034
Adam Lesinskicacb28f2016-10-19 12:18:14 -070035 ASSERT_TRUE(assigner.consume(context.get(), table.get()));
36 ASSERT_TRUE(verifyIds(table.get()));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070037}
38
39TEST(IdAssignerTest, AssignIdsWithReservedIds) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070040 std::unique_ptr<ResourceTable> table =
41 test::ResourceTableBuilder()
42 .addSimple("android:id/foo", ResourceId(0x01010000))
43 .addSimple("android:dimen/two")
44 .addSimple("android:integer/three")
45 .addSimple("android:string/five")
46 .addSimple("android:attr/fun", ResourceId(0x01040000))
47 .addSimple("android:attr/foo", ResourceId(0x01040006))
48 .addSimple("android:attr/bar")
49 .addSimple("android:attr/baz")
50 .addSimple("app:id/biz")
51 .setPackageId("android", 0x01)
52 .setPackageId("app", 0x7f)
53 .build();
Adam Lesinski1ab598f2015-08-14 14:26:04 -070054
Adam Lesinskicacb28f2016-10-19 12:18:14 -070055 std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
56 IdAssigner assigner;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070057
Adam Lesinskicacb28f2016-10-19 12:18:14 -070058 ASSERT_TRUE(assigner.consume(context.get(), table.get()));
59 ASSERT_TRUE(verifyIds(table.get()));
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -070060
Adam Lesinskicacb28f2016-10-19 12:18:14 -070061 Maybe<ResourceTable::SearchResult> maybeResult;
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -070062
Adam Lesinskicacb28f2016-10-19 12:18:14 -070063 // Expect to fill in the gaps between 0x0101XXXX and 0x0104XXXX.
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -070064
Adam Lesinskicacb28f2016-10-19 12:18:14 -070065 maybeResult = table->findResource(test::parseNameOrDie("android:dimen/two"));
66 AAPT_ASSERT_TRUE(maybeResult);
67 EXPECT_EQ(make_value<uint8_t>(2), maybeResult.value().type->id);
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -070068
Adam Lesinskicacb28f2016-10-19 12:18:14 -070069 maybeResult =
70 table->findResource(test::parseNameOrDie("android:integer/three"));
71 AAPT_ASSERT_TRUE(maybeResult);
72 EXPECT_EQ(make_value<uint8_t>(3), maybeResult.value().type->id);
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -070073
Adam Lesinskicacb28f2016-10-19 12:18:14 -070074 // Expect to bypass the reserved 0x0104XXXX IDs and use the next 0x0105XXXX
75 // IDs.
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -070076
Adam Lesinskicacb28f2016-10-19 12:18:14 -070077 maybeResult =
78 table->findResource(test::parseNameOrDie("android:string/five"));
79 AAPT_ASSERT_TRUE(maybeResult);
80 EXPECT_EQ(make_value<uint8_t>(5), maybeResult.value().type->id);
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -070081
Adam Lesinskicacb28f2016-10-19 12:18:14 -070082 // Expect to fill in the gaps between 0x01040000 and 0x01040006.
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -070083
Adam Lesinskicacb28f2016-10-19 12:18:14 -070084 maybeResult = table->findResource(test::parseNameOrDie("android:attr/bar"));
85 AAPT_ASSERT_TRUE(maybeResult);
86 EXPECT_EQ(make_value<uint16_t>(1), maybeResult.value().entry->id);
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -070087
Adam Lesinskicacb28f2016-10-19 12:18:14 -070088 maybeResult = table->findResource(test::parseNameOrDie("android:attr/baz"));
89 AAPT_ASSERT_TRUE(maybeResult);
90 EXPECT_EQ(make_value<uint16_t>(2), maybeResult.value().entry->id);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070091}
92
93TEST(IdAssignerTest, FailWhenNonUniqueIdsAssigned) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070094 std::unique_ptr<ResourceTable> table =
95 test::ResourceTableBuilder()
96 .addSimple("android:attr/foo", ResourceId(0x01040006))
97 .addSimple("android:attr/bar", ResourceId(0x01040006))
98 .setPackageId("android", 0x01)
99 .setPackageId("app", 0x7f)
100 .build();
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700101
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700102 std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
103 IdAssigner assigner;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700104
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700105 ASSERT_FALSE(assigner.consume(context.get(), table.get()));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700106}
107
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -0700108TEST(IdAssignerTest, AssignIdsWithIdMap) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700109 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
110 .addSimple("android:attr/foo")
111 .addSimple("android:attr/bar")
112 .setPackageId("android", 0x01)
113 .build();
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -0700114
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700115 std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
116 std::unordered_map<ResourceName, ResourceId> idMap = {
117 {test::parseNameOrDie("android:attr/foo"), ResourceId(0x01010002)}};
118 IdAssigner assigner(&idMap);
119 ASSERT_TRUE(assigner.consume(context.get(), table.get()));
120 ASSERT_TRUE(verifyIds(table.get()));
121 Maybe<ResourceTable::SearchResult> result =
122 table->findResource(test::parseNameOrDie("android:attr/foo"));
123 AAPT_ASSERT_TRUE(result);
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -0700124
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700125 const ResourceTable::SearchResult& searchResult = result.value();
126 EXPECT_EQ(make_value<uint8_t>(0x01), searchResult.package->id);
127 EXPECT_EQ(make_value<uint8_t>(0x01), searchResult.type->id);
128 EXPECT_EQ(make_value<uint16_t>(0x0002), searchResult.entry->id);
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -0700129}
130
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700131::testing::AssertionResult verifyIds(ResourceTable* table) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700132 std::set<uint8_t> packageIds;
133 for (auto& package : table->packages) {
134 if (!package->id) {
135 return ::testing::AssertionFailure() << "package " << package->name
136 << " has no ID";
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700137 }
138
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700139 if (!packageIds.insert(package->id.value()).second) {
140 return ::testing::AssertionFailure()
141 << "package " << package->name << " has non-unique ID " << std::hex
142 << (int)package->id.value() << std::dec;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700143 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700144 }
145
146 for (auto& package : table->packages) {
147 std::set<uint8_t> typeIds;
148 for (auto& type : package->types) {
149 if (!type->id) {
150 return ::testing::AssertionFailure() << "type " << type->type
151 << " of package " << package->name
152 << " has no ID";
153 }
154
155 if (!typeIds.insert(type->id.value()).second) {
156 return ::testing::AssertionFailure()
157 << "type " << type->type << " of package " << package->name
158 << " has non-unique ID " << std::hex << (int)type->id.value()
159 << std::dec;
160 }
161 }
162
163 for (auto& type : package->types) {
164 std::set<uint16_t> entryIds;
165 for (auto& entry : type->entries) {
166 if (!entry->id) {
167 return ::testing::AssertionFailure()
168 << "entry " << entry->name << " of type " << type->type
169 << " of package " << package->name << " has no ID";
170 }
171
172 if (!entryIds.insert(entry->id.value()).second) {
173 return ::testing::AssertionFailure()
174 << "entry " << entry->name << " of type " << type->type
175 << " of package " << package->name << " has non-unique ID "
176 << std::hex << (int)entry->id.value() << std::dec;
177 }
178 }
179 }
180 }
181 return ::testing::AssertionSuccess() << "all IDs are unique and assigned";
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700182}
183
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700184} // namespace aapt