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