blob: 1ed4536c4566d3011998c48a74acdee579dd6881 [file] [log] [blame]
Adam Lesinskic744ae82017-05-17 19:28:38 -07001/*
2 * Copyright (C) 2017 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 "link/XmlCompatVersioner.h"
18
19#include "Linkers.h"
20#include "test/Test.h"
21
Adam Lesinski6b372992017-08-09 10:54:23 -070022using ::aapt::test::ValueEq;
23using ::testing::Eq;
24using ::testing::IsNull;
25using ::testing::NotNull;
26using ::testing::SizeIs;
27
Adam Lesinskic744ae82017-05-17 19:28:38 -070028namespace aapt {
29
30constexpr auto TYPE_DIMENSION = android::ResTable_map::TYPE_DIMENSION;
31constexpr auto TYPE_STRING = android::ResTable_map::TYPE_STRING;
32
33struct R {
34 struct attr {
35 enum : uint32_t {
36 paddingLeft = 0x010100d6u, // (API 1)
37 paddingRight = 0x010100d8u, // (API 1)
38 progressBarPadding = 0x01010319u, // (API 11)
39 paddingStart = 0x010103b3u, // (API 17)
40 paddingHorizontal = 0x0101053du, // (API 26)
41 };
42 };
43};
44
45class XmlCompatVersionerTest : public ::testing::Test {
46 public:
47 void SetUp() override {
48 context_ =
49 test::ContextBuilder()
50 .SetCompilationPackage("com.app")
51 .SetPackageId(0x7f)
52 .SetPackageType(PackageType::kApp)
53 .SetMinSdkVersion(SDK_GINGERBREAD)
54 .AddSymbolSource(
55 test::StaticSymbolSourceBuilder()
56 .AddPublicSymbol("android:attr/paddingLeft", R::attr::paddingLeft,
Adam Lesinski73bff1e2017-12-08 16:06:10 -080057 util::make_unique<Attribute>(TYPE_DIMENSION))
Adam Lesinskic744ae82017-05-17 19:28:38 -070058 .AddPublicSymbol("android:attr/paddingRight", R::attr::paddingRight,
Adam Lesinski73bff1e2017-12-08 16:06:10 -080059 util::make_unique<Attribute>(TYPE_DIMENSION))
Adam Lesinskic744ae82017-05-17 19:28:38 -070060 .AddPublicSymbol("android:attr/progressBarPadding", R::attr::progressBarPadding,
Adam Lesinski73bff1e2017-12-08 16:06:10 -080061 util::make_unique<Attribute>(TYPE_DIMENSION))
Adam Lesinskic744ae82017-05-17 19:28:38 -070062 .AddPublicSymbol("android:attr/paddingStart", R::attr::paddingStart,
Adam Lesinski73bff1e2017-12-08 16:06:10 -080063 util::make_unique<Attribute>(TYPE_DIMENSION))
Adam Lesinskic744ae82017-05-17 19:28:38 -070064 .AddPublicSymbol("android:attr/paddingHorizontal", R::attr::paddingHorizontal,
Adam Lesinski73bff1e2017-12-08 16:06:10 -080065 util::make_unique<Attribute>(TYPE_DIMENSION))
Adam Lesinskic744ae82017-05-17 19:28:38 -070066 .AddSymbol("com.app:attr/foo", ResourceId(0x7f010000),
Adam Lesinski73bff1e2017-12-08 16:06:10 -080067 util::make_unique<Attribute>(TYPE_STRING))
Adam Lesinskic744ae82017-05-17 19:28:38 -070068 .Build())
69 .Build();
70 }
71
72 protected:
73 std::unique_ptr<IAaptContext> context_;
74};
75
76TEST_F(XmlCompatVersionerTest, NoRulesOnlyStripsAndCopies) {
Adam Lesinski6b372992017-08-09 10:54:23 -070077 auto doc = test::BuildXmlDomForPackageName(context_.get(), R"(
Adam Lesinskic744ae82017-05-17 19:28:38 -070078 <View xmlns:android="http://schemas.android.com/apk/res/android"
79 xmlns:app="http://schemas.android.com/apk/res-auto"
80 android:paddingHorizontal="24dp"
81 app:foo="16dp"
Adam Lesinski6b372992017-08-09 10:54:23 -070082 foo="bar"/>)");
Adam Lesinskic744ae82017-05-17 19:28:38 -070083
84 XmlReferenceLinker linker;
85 ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
86
87 XmlCompatVersioner::Rules rules;
88 const util::Range<ApiVersion> api_range{SDK_GINGERBREAD, SDK_O + 1};
89
90 XmlCompatVersioner versioner(&rules);
91 std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs =
92 versioner.Process(context_.get(), doc.get(), api_range);
Adam Lesinski6b372992017-08-09 10:54:23 -070093 ASSERT_THAT(versioned_docs, SizeIs(2u));
Adam Lesinskic744ae82017-05-17 19:28:38 -070094
95 xml::Element* el;
96
97 // Source XML file's sdkVersion == 0, so the first one must also have the same sdkVersion.
Adam Lesinski6b372992017-08-09 10:54:23 -070098 EXPECT_THAT(versioned_docs[0]->file.config.sdkVersion, Eq(0u));
99 el = versioned_docs[0]->root.get();
100 ASSERT_THAT(el, NotNull());
101 EXPECT_THAT(el->attributes, SizeIs(2u));
102 EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull());
103 EXPECT_THAT(el->FindAttribute(xml::kSchemaAuto, "foo"), NotNull());
104 EXPECT_THAT(el->FindAttribute({}, "foo"), NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700105
Adam Lesinski6b372992017-08-09 10:54:23 -0700106 EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1));
107 el = versioned_docs[1]->root.get();
108 ASSERT_THAT(el, NotNull());
109 EXPECT_THAT(el->attributes, SizeIs(3u));
110 EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), NotNull());
111 EXPECT_THAT(el->FindAttribute(xml::kSchemaAuto, "foo"), NotNull());
112 EXPECT_THAT(el->FindAttribute({}, "foo"), NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700113}
114
115TEST_F(XmlCompatVersionerTest, SingleRule) {
Adam Lesinski6b372992017-08-09 10:54:23 -0700116 auto doc = test::BuildXmlDomForPackageName(context_.get(), R"(
Adam Lesinskic744ae82017-05-17 19:28:38 -0700117 <View xmlns:android="http://schemas.android.com/apk/res/android"
118 xmlns:app="http://schemas.android.com/apk/res-auto"
119 android:paddingHorizontal="24dp"
120 app:foo="16dp"
Adam Lesinski6b372992017-08-09 10:54:23 -0700121 foo="bar"/>)");
Adam Lesinskic744ae82017-05-17 19:28:38 -0700122
123 XmlReferenceLinker linker;
124 ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
125
126 XmlCompatVersioner::Rules rules;
127 rules[R::attr::paddingHorizontal] =
128 util::make_unique<DegradeToManyRule>(std::vector<ReplacementAttr>(
Adam Lesinski73bff1e2017-12-08 16:06:10 -0800129 {ReplacementAttr{"paddingLeft", R::attr::paddingLeft, Attribute(TYPE_DIMENSION)},
130 ReplacementAttr{"paddingRight", R::attr::paddingRight, Attribute(TYPE_DIMENSION)}}));
Adam Lesinskic744ae82017-05-17 19:28:38 -0700131
132 const util::Range<ApiVersion> api_range{SDK_GINGERBREAD, SDK_O + 1};
133
134 XmlCompatVersioner versioner(&rules);
135 std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs =
136 versioner.Process(context_.get(), doc.get(), api_range);
Adam Lesinski6b372992017-08-09 10:54:23 -0700137 ASSERT_THAT(versioned_docs, SizeIs(2u));
Adam Lesinskic744ae82017-05-17 19:28:38 -0700138
139 xml::Element* el;
140
Adam Lesinski6b372992017-08-09 10:54:23 -0700141 EXPECT_THAT(versioned_docs[0]->file.config.sdkVersion, Eq(0u));
142 el = versioned_docs[0]->root.get();
143 ASSERT_THAT(el, NotNull());
144 EXPECT_THAT(el->attributes, SizeIs(4u));
145 EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull());
146 EXPECT_THAT(el->FindAttribute(xml::kSchemaAuto, "foo"), NotNull());
147 EXPECT_THAT(el->FindAttribute({}, "foo"), NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700148
149 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
Adam Lesinski6b372992017-08-09 10:54:23 -0700150 ASSERT_THAT(attr, NotNull());
151 ASSERT_THAT(attr->compiled_value, NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700152 ASSERT_TRUE(attr->compiled_attribute);
153
154 attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
Adam Lesinski6b372992017-08-09 10:54:23 -0700155 ASSERT_THAT(attr, NotNull());
156 ASSERT_THAT(attr->compiled_value, NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700157 ASSERT_TRUE(attr->compiled_attribute);
158
Adam Lesinski6b372992017-08-09 10:54:23 -0700159 EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1));
160 el = versioned_docs[1]->root.get();
161 ASSERT_THAT(el, NotNull());
162 EXPECT_THAT(el->attributes, SizeIs(5u));
163 EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), NotNull());
164 EXPECT_THAT(el->FindAttribute(xml::kSchemaAuto, "foo"), NotNull());
165 EXPECT_THAT(el->FindAttribute({}, "foo"), NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700166
167 attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
Adam Lesinski6b372992017-08-09 10:54:23 -0700168 ASSERT_THAT(attr, NotNull());
169 ASSERT_THAT(attr->compiled_value, NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700170 ASSERT_TRUE(attr->compiled_attribute);
171
172 attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
Adam Lesinski6b372992017-08-09 10:54:23 -0700173 ASSERT_THAT(attr, NotNull());
174 ASSERT_THAT(attr->compiled_value, NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700175 ASSERT_TRUE(attr->compiled_attribute);
176}
177
178TEST_F(XmlCompatVersionerTest, ChainedRule) {
Adam Lesinski6b372992017-08-09 10:54:23 -0700179 auto doc = test::BuildXmlDomForPackageName(context_.get(), R"(
Adam Lesinskic744ae82017-05-17 19:28:38 -0700180 <View xmlns:android="http://schemas.android.com/apk/res/android"
Adam Lesinski6b372992017-08-09 10:54:23 -0700181 android:paddingHorizontal="24dp" />)");
Adam Lesinskic744ae82017-05-17 19:28:38 -0700182
183 XmlReferenceLinker linker;
184 ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
185
186 XmlCompatVersioner::Rules rules;
187 rules[R::attr::progressBarPadding] =
188 util::make_unique<DegradeToManyRule>(std::vector<ReplacementAttr>(
Adam Lesinski73bff1e2017-12-08 16:06:10 -0800189 {ReplacementAttr{"paddingLeft", R::attr::paddingLeft, Attribute(TYPE_DIMENSION)},
190 ReplacementAttr{"paddingRight", R::attr::paddingRight, Attribute(TYPE_DIMENSION)}}));
Adam Lesinskic744ae82017-05-17 19:28:38 -0700191 rules[R::attr::paddingHorizontal] =
192 util::make_unique<DegradeToManyRule>(std::vector<ReplacementAttr>({ReplacementAttr{
Adam Lesinski73bff1e2017-12-08 16:06:10 -0800193 "progressBarPadding", R::attr::progressBarPadding, Attribute(TYPE_DIMENSION)}}));
Adam Lesinskic744ae82017-05-17 19:28:38 -0700194
195 const util::Range<ApiVersion> api_range{SDK_GINGERBREAD, SDK_O + 1};
196
197 XmlCompatVersioner versioner(&rules);
198 std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs =
199 versioner.Process(context_.get(), doc.get(), api_range);
Adam Lesinski6b372992017-08-09 10:54:23 -0700200 ASSERT_THAT(versioned_docs, SizeIs(3u));
Adam Lesinskic744ae82017-05-17 19:28:38 -0700201
202 xml::Element* el;
203
Adam Lesinski6b372992017-08-09 10:54:23 -0700204 EXPECT_THAT(versioned_docs[0]->file.config.sdkVersion, Eq(0u));
205 el = versioned_docs[0]->root.get();
206 ASSERT_THAT(el, NotNull());
207 EXPECT_THAT(el->attributes, SizeIs(2u));
208 EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700209
210 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
Adam Lesinski6b372992017-08-09 10:54:23 -0700211 ASSERT_THAT(attr, NotNull());
212 ASSERT_THAT(attr->compiled_value, NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700213 ASSERT_TRUE(attr->compiled_attribute);
214
215 attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
Adam Lesinski6b372992017-08-09 10:54:23 -0700216 ASSERT_THAT(attr, NotNull());
217 ASSERT_THAT(attr->compiled_value, NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700218 ASSERT_TRUE(attr->compiled_attribute);
219
Adam Lesinski6b372992017-08-09 10:54:23 -0700220 EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_HONEYCOMB));
221 el = versioned_docs[1]->root.get();
222 ASSERT_THAT(el, NotNull());
223 EXPECT_THAT(el->attributes, SizeIs(1u));
224 EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull());
225 EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"), IsNull());
226 EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingRight"), IsNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700227
228 attr = el->FindAttribute(xml::kSchemaAndroid, "progressBarPadding");
Adam Lesinski6b372992017-08-09 10:54:23 -0700229 ASSERT_THAT(attr, NotNull());
230 ASSERT_THAT(attr->compiled_value, NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700231 ASSERT_TRUE(attr->compiled_attribute);
232
Adam Lesinski6b372992017-08-09 10:54:23 -0700233 EXPECT_THAT(versioned_docs[2]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1));
234 el = versioned_docs[2]->root.get();
235 ASSERT_THAT(el, NotNull());
236 EXPECT_THAT(el->attributes, SizeIs(2u));
237 EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"), IsNull());
238 EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingRight"), IsNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700239
240 attr = el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal");
Adam Lesinski6b372992017-08-09 10:54:23 -0700241 ASSERT_THAT(attr, NotNull());
242 ASSERT_THAT(attr->compiled_value, NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700243 ASSERT_TRUE(attr->compiled_attribute);
244
245 attr = el->FindAttribute(xml::kSchemaAndroid, "progressBarPadding");
Adam Lesinski6b372992017-08-09 10:54:23 -0700246 ASSERT_THAT(attr, NotNull());
247 ASSERT_THAT(attr->compiled_value, NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700248 ASSERT_TRUE(attr->compiled_attribute);
249}
250
251TEST_F(XmlCompatVersionerTest, DegradeRuleOverridesExistingAttribute) {
Adam Lesinski6b372992017-08-09 10:54:23 -0700252 auto doc = test::BuildXmlDomForPackageName(context_.get(), R"(
Adam Lesinskic744ae82017-05-17 19:28:38 -0700253 <View xmlns:android="http://schemas.android.com/apk/res/android"
254 android:paddingHorizontal="24dp"
255 android:paddingLeft="16dp"
Adam Lesinski6b372992017-08-09 10:54:23 -0700256 android:paddingRight="16dp"/>)");
Adam Lesinskic744ae82017-05-17 19:28:38 -0700257
258 XmlReferenceLinker linker;
259 ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
260
Adam Lesinski6b372992017-08-09 10:54:23 -0700261 Item* padding_horizontal_value =
262 doc->root->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")->compiled_value.get();
263 ASSERT_THAT(padding_horizontal_value, NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700264
265 XmlCompatVersioner::Rules rules;
266 rules[R::attr::paddingHorizontal] =
267 util::make_unique<DegradeToManyRule>(std::vector<ReplacementAttr>(
Adam Lesinski73bff1e2017-12-08 16:06:10 -0800268 {ReplacementAttr{"paddingLeft", R::attr::paddingLeft, Attribute(TYPE_DIMENSION)},
269 ReplacementAttr{"paddingRight", R::attr::paddingRight, Attribute(TYPE_DIMENSION)}}));
Adam Lesinskic744ae82017-05-17 19:28:38 -0700270
271 const util::Range<ApiVersion> api_range{SDK_GINGERBREAD, SDK_O + 1};
272
273 XmlCompatVersioner versioner(&rules);
274 std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs =
275 versioner.Process(context_.get(), doc.get(), api_range);
Adam Lesinski6b372992017-08-09 10:54:23 -0700276 ASSERT_THAT(versioned_docs, SizeIs(2u));
Adam Lesinskic744ae82017-05-17 19:28:38 -0700277
278 xml::Element* el;
279
Adam Lesinski6b372992017-08-09 10:54:23 -0700280 EXPECT_THAT(versioned_docs[0]->file.config.sdkVersion, Eq(0u));
281 el = versioned_docs[0]->root.get();
282 ASSERT_THAT(el, NotNull());
283 EXPECT_THAT(el->attributes, SizeIs(2u));
284 EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700285
286 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
Adam Lesinski6b372992017-08-09 10:54:23 -0700287 ASSERT_THAT(attr, NotNull());
288 ASSERT_THAT(attr->compiled_value, NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700289 ASSERT_TRUE(attr->compiled_attribute);
Adam Lesinski6b372992017-08-09 10:54:23 -0700290 ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
Adam Lesinskic744ae82017-05-17 19:28:38 -0700291
292 attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
Adam Lesinski6b372992017-08-09 10:54:23 -0700293 ASSERT_THAT(attr, NotNull());
294 ASSERT_THAT(attr->compiled_value, NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700295 ASSERT_TRUE(attr->compiled_attribute);
Adam Lesinski6b372992017-08-09 10:54:23 -0700296 ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
Adam Lesinskic744ae82017-05-17 19:28:38 -0700297
Adam Lesinski6b372992017-08-09 10:54:23 -0700298 EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1));
299 el = versioned_docs[1]->root.get();
300 ASSERT_THAT(el, NotNull());
301 EXPECT_THAT(el->attributes, SizeIs(3u));
Adam Lesinskic744ae82017-05-17 19:28:38 -0700302
303 attr = el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal");
Adam Lesinski6b372992017-08-09 10:54:23 -0700304 ASSERT_THAT(attr, NotNull());
305 ASSERT_THAT(attr->compiled_value, NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700306 ASSERT_TRUE(attr->compiled_attribute);
Adam Lesinski6b372992017-08-09 10:54:23 -0700307 ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
Adam Lesinskic744ae82017-05-17 19:28:38 -0700308
309 attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
Adam Lesinski6b372992017-08-09 10:54:23 -0700310 ASSERT_THAT(attr, NotNull());
311 ASSERT_THAT(attr->compiled_value, NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700312 ASSERT_TRUE(attr->compiled_attribute);
Adam Lesinski6b372992017-08-09 10:54:23 -0700313 ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
Adam Lesinskic744ae82017-05-17 19:28:38 -0700314
315 attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
Adam Lesinski6b372992017-08-09 10:54:23 -0700316 ASSERT_THAT(attr, NotNull());
317 ASSERT_THAT(attr->compiled_value, NotNull());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700318 ASSERT_TRUE(attr->compiled_attribute);
Adam Lesinski6b372992017-08-09 10:54:23 -0700319 ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
Adam Lesinskic744ae82017-05-17 19:28:38 -0700320}
321
322} // namespace aapt