1c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski/*
2c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski * Copyright (C) 2017 The Android Open Source Project
3c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski *
4c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski * you may not use this file except in compliance with the License.
6c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski * You may obtain a copy of the License at
7c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski *
8c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski *
10c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski * Unless required by applicable law or agreed to in writing, software
11c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski * See the License for the specific language governing permissions and
14c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski * limitations under the License.
15c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski */
16c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
17c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski#include "link/XmlCompatVersioner.h"
18c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
19c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski#include "Linkers.h"
20c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski#include "test/Test.h"
21c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
225c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinskiusing ::aapt::test::ValueEq;
235c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinskiusing ::testing::Eq;
245c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinskiusing ::testing::IsNull;
255c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinskiusing ::testing::NotNull;
265c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinskiusing ::testing::SizeIs;
275c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski
28c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskinamespace aapt {
29c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
30c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskiconstexpr auto TYPE_DIMENSION = android::ResTable_map::TYPE_DIMENSION;
31c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskiconstexpr auto TYPE_STRING = android::ResTable_map::TYPE_STRING;
32c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
33c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskistruct R {
34c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  struct attr {
35c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    enum : uint32_t {
36c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      paddingLeft = 0x010100d6u,         // (API 1)
37c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      paddingRight = 0x010100d8u,        // (API 1)
38c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      progressBarPadding = 0x01010319u,  // (API 11)
39c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      paddingStart = 0x010103b3u,        // (API 17)
40c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      paddingHorizontal = 0x0101053du,   // (API 26)
41c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    };
42c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  };
43c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski};
44c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
45c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskiclass XmlCompatVersionerTest : public ::testing::Test {
46c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski public:
47c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  void SetUp() override {
48c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    context_ =
49c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski        test::ContextBuilder()
50c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski            .SetCompilationPackage("com.app")
51c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski            .SetPackageId(0x7f)
52c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski            .SetPackageType(PackageType::kApp)
53c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski            .SetMinSdkVersion(SDK_GINGERBREAD)
54c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski            .AddSymbolSource(
55c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                test::StaticSymbolSourceBuilder()
56c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                    .AddPublicSymbol("android:attr/paddingLeft", R::attr::paddingLeft,
57c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                                     util::make_unique<Attribute>(false, TYPE_DIMENSION))
58c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                    .AddPublicSymbol("android:attr/paddingRight", R::attr::paddingRight,
59c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                                     util::make_unique<Attribute>(false, TYPE_DIMENSION))
60c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                    .AddPublicSymbol("android:attr/progressBarPadding", R::attr::progressBarPadding,
61c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                                     util::make_unique<Attribute>(false, TYPE_DIMENSION))
62c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                    .AddPublicSymbol("android:attr/paddingStart", R::attr::paddingStart,
63c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                                     util::make_unique<Attribute>(false, TYPE_DIMENSION))
64c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                    .AddPublicSymbol("android:attr/paddingHorizontal", R::attr::paddingHorizontal,
65c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                                     util::make_unique<Attribute>(false, TYPE_DIMENSION))
66c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                    .AddSymbol("com.app:attr/foo", ResourceId(0x7f010000),
67c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                               util::make_unique<Attribute>(false, TYPE_STRING))
68c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                    .Build())
69c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski            .Build();
70c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  }
71c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
72c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski protected:
73c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  std::unique_ptr<IAaptContext> context_;
74c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski};
75c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
76c744ae8aca97edfb2422598ea620e8219449fa9bAdam LesinskiTEST_F(XmlCompatVersionerTest, NoRulesOnlyStripsAndCopies) {
775c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  auto doc = test::BuildXmlDomForPackageName(context_.get(), R"(
78c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      <View xmlns:android="http://schemas.android.com/apk/res/android"
79c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          xmlns:app="http://schemas.android.com/apk/res-auto"
80c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          android:paddingHorizontal="24dp"
81c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          app:foo="16dp"
825c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski          foo="bar"/>)");
83c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
84c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  XmlReferenceLinker linker;
85c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
86c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
87c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  XmlCompatVersioner::Rules rules;
88c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  const util::Range<ApiVersion> api_range{SDK_GINGERBREAD, SDK_O + 1};
89c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
90c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  XmlCompatVersioner versioner(&rules);
91c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs =
92c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      versioner.Process(context_.get(), doc.get(), api_range);
935c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(versioned_docs, SizeIs(2u));
94c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
95c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  xml::Element* el;
96c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
97c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  // Source XML file's sdkVersion == 0, so the first one must also have the same sdkVersion.
985c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(versioned_docs[0]->file.config.sdkVersion, Eq(0u));
995c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  el = versioned_docs[0]->root.get();
1005c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(el, NotNull());
1015c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->attributes, SizeIs(2u));
1025c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull());
1035c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute(xml::kSchemaAuto, "foo"), NotNull());
1045c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute({}, "foo"), NotNull());
1055c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski
1065c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1));
1075c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  el = versioned_docs[1]->root.get();
1085c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(el, NotNull());
1095c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->attributes, SizeIs(3u));
1105c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), NotNull());
1115c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute(xml::kSchemaAuto, "foo"), NotNull());
1125c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute({}, "foo"), NotNull());
113c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski}
114c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
115c744ae8aca97edfb2422598ea620e8219449fa9bAdam LesinskiTEST_F(XmlCompatVersionerTest, SingleRule) {
1165c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  auto doc = test::BuildXmlDomForPackageName(context_.get(), R"(
117c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      <View xmlns:android="http://schemas.android.com/apk/res/android"
118c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          xmlns:app="http://schemas.android.com/apk/res-auto"
119c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          android:paddingHorizontal="24dp"
120c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          app:foo="16dp"
1215c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski          foo="bar"/>)");
122c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
123c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  XmlReferenceLinker linker;
124c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
125c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
126c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  XmlCompatVersioner::Rules rules;
127c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  rules[R::attr::paddingHorizontal] =
128c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      util::make_unique<DegradeToManyRule>(std::vector<ReplacementAttr>(
129c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          {ReplacementAttr{"paddingLeft", R::attr::paddingLeft, Attribute(false, TYPE_DIMENSION)},
130c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski           ReplacementAttr{"paddingRight", R::attr::paddingRight,
131c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                           Attribute(false, TYPE_DIMENSION)}}));
132c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
133c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  const util::Range<ApiVersion> api_range{SDK_GINGERBREAD, SDK_O + 1};
134c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
135c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  XmlCompatVersioner versioner(&rules);
136c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs =
137c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      versioner.Process(context_.get(), doc.get(), api_range);
1385c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(versioned_docs, SizeIs(2u));
139c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
140c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  xml::Element* el;
141c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
1425c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(versioned_docs[0]->file.config.sdkVersion, Eq(0u));
1435c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  el = versioned_docs[0]->root.get();
1445c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(el, NotNull());
1455c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->attributes, SizeIs(4u));
1465c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull());
1475c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute(xml::kSchemaAuto, "foo"), NotNull());
1485c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute({}, "foo"), NotNull());
149c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
150c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
1515c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr, NotNull());
1525c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr->compiled_value, NotNull());
153c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(attr->compiled_attribute);
154c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
155c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
1565c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr, NotNull());
1575c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr->compiled_value, NotNull());
158c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(attr->compiled_attribute);
159c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
1605c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1));
1615c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  el = versioned_docs[1]->root.get();
1625c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(el, NotNull());
1635c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->attributes, SizeIs(5u));
1645c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), NotNull());
1655c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute(xml::kSchemaAuto, "foo"), NotNull());
1665c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute({}, "foo"), NotNull());
167c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
168c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
1695c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr, NotNull());
1705c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr->compiled_value, NotNull());
171c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(attr->compiled_attribute);
172c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
173c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
1745c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr, NotNull());
1755c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr->compiled_value, NotNull());
176c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(attr->compiled_attribute);
177c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski}
178c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
179c744ae8aca97edfb2422598ea620e8219449fa9bAdam LesinskiTEST_F(XmlCompatVersionerTest, ChainedRule) {
1805c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  auto doc = test::BuildXmlDomForPackageName(context_.get(), R"(
181c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      <View xmlns:android="http://schemas.android.com/apk/res/android"
1825c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski          android:paddingHorizontal="24dp" />)");
183c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
184c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  XmlReferenceLinker linker;
185c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
186c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
187c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  XmlCompatVersioner::Rules rules;
188c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  rules[R::attr::progressBarPadding] =
189c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      util::make_unique<DegradeToManyRule>(std::vector<ReplacementAttr>(
190c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          {ReplacementAttr{"paddingLeft", R::attr::paddingLeft, Attribute(false, TYPE_DIMENSION)},
191c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski           ReplacementAttr{"paddingRight", R::attr::paddingRight,
192c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                           Attribute(false, TYPE_DIMENSION)}}));
193c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  rules[R::attr::paddingHorizontal] =
194c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      util::make_unique<DegradeToManyRule>(std::vector<ReplacementAttr>({ReplacementAttr{
195c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          "progressBarPadding", R::attr::progressBarPadding, Attribute(false, TYPE_DIMENSION)}}));
196c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
197c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  const util::Range<ApiVersion> api_range{SDK_GINGERBREAD, SDK_O + 1};
198c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
199c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  XmlCompatVersioner versioner(&rules);
200c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs =
201c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      versioner.Process(context_.get(), doc.get(), api_range);
2025c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(versioned_docs, SizeIs(3u));
203c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
204c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  xml::Element* el;
205c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
2065c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(versioned_docs[0]->file.config.sdkVersion, Eq(0u));
2075c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  el = versioned_docs[0]->root.get();
2085c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(el, NotNull());
2095c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->attributes, SizeIs(2u));
2105c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull());
211c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
212c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
2135c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr, NotNull());
2145c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr->compiled_value, NotNull());
215c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(attr->compiled_attribute);
216c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
217c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
2185c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr, NotNull());
2195c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr->compiled_value, NotNull());
220c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(attr->compiled_attribute);
221c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
2225c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_HONEYCOMB));
2235c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  el = versioned_docs[1]->root.get();
2245c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(el, NotNull());
2255c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->attributes, SizeIs(1u));
2265c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull());
2275c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"), IsNull());
2285c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingRight"), IsNull());
229c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
230c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  attr = el->FindAttribute(xml::kSchemaAndroid, "progressBarPadding");
2315c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr, NotNull());
2325c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr->compiled_value, NotNull());
233c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(attr->compiled_attribute);
234c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
2355c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(versioned_docs[2]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1));
2365c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  el = versioned_docs[2]->root.get();
2375c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(el, NotNull());
2385c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->attributes, SizeIs(2u));
2395c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"), IsNull());
2405c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingRight"), IsNull());
241c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
242c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  attr = el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal");
2435c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr, NotNull());
2445c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr->compiled_value, NotNull());
245c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(attr->compiled_attribute);
246c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
247c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  attr = el->FindAttribute(xml::kSchemaAndroid, "progressBarPadding");
2485c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr, NotNull());
2495c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr->compiled_value, NotNull());
250c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(attr->compiled_attribute);
251c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski}
252c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
253c744ae8aca97edfb2422598ea620e8219449fa9bAdam LesinskiTEST_F(XmlCompatVersionerTest, DegradeRuleOverridesExistingAttribute) {
2545c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  auto doc = test::BuildXmlDomForPackageName(context_.get(), R"(
255c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      <View xmlns:android="http://schemas.android.com/apk/res/android"
256c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          android:paddingHorizontal="24dp"
257c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          android:paddingLeft="16dp"
2585c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski          android:paddingRight="16dp"/>)");
259c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
260c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  XmlReferenceLinker linker;
261c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
262c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
2635c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  Item* padding_horizontal_value =
2645c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski      doc->root->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")->compiled_value.get();
2655c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(padding_horizontal_value, NotNull());
266c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
267c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  XmlCompatVersioner::Rules rules;
268c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  rules[R::attr::paddingHorizontal] =
269c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      util::make_unique<DegradeToManyRule>(std::vector<ReplacementAttr>(
270c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          {ReplacementAttr{"paddingLeft", R::attr::paddingLeft, Attribute(false, TYPE_DIMENSION)},
271c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski           ReplacementAttr{"paddingRight", R::attr::paddingRight,
272c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                           Attribute(false, TYPE_DIMENSION)}}));
273c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
274c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  const util::Range<ApiVersion> api_range{SDK_GINGERBREAD, SDK_O + 1};
275c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
276c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  XmlCompatVersioner versioner(&rules);
277c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs =
278c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      versioner.Process(context_.get(), doc.get(), api_range);
2795c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(versioned_docs, SizeIs(2u));
280c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
281c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  xml::Element* el;
282c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
2835c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(versioned_docs[0]->file.config.sdkVersion, Eq(0u));
2845c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  el = versioned_docs[0]->root.get();
2855c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(el, NotNull());
2865c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->attributes, SizeIs(2u));
2875c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull());
288c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
289c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
2905c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr, NotNull());
2915c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr->compiled_value, NotNull());
292c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(attr->compiled_attribute);
2935c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
294c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
295c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
2965c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr, NotNull());
2975c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr->compiled_value, NotNull());
298c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(attr->compiled_attribute);
2995c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
300c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
3015c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1));
3025c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  el = versioned_docs[1]->root.get();
3035c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(el, NotNull());
3045c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  EXPECT_THAT(el->attributes, SizeIs(3u));
305c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
306c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  attr = el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal");
3075c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr, NotNull());
3085c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr->compiled_value, NotNull());
309c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(attr->compiled_attribute);
3105c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
311c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
312c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
3135c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr, NotNull());
3145c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr->compiled_value, NotNull());
315c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(attr->compiled_attribute);
3165c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
317c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
318c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
3195c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr, NotNull());
3205c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(attr->compiled_value, NotNull());
321c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ASSERT_TRUE(attr->compiled_attribute);
3225c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
323c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski}
324c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
325c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski}  // namespace aapt
326