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 22c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskinamespace aapt { 23c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 24c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskiconstexpr auto TYPE_DIMENSION = android::ResTable_map::TYPE_DIMENSION; 25c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskiconstexpr auto TYPE_STRING = android::ResTable_map::TYPE_STRING; 26c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 27c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskistruct R { 28c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski struct attr { 29c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski enum : uint32_t { 30c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski paddingLeft = 0x010100d6u, // (API 1) 31c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski paddingRight = 0x010100d8u, // (API 1) 32c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski progressBarPadding = 0x01010319u, // (API 11) 33c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski paddingStart = 0x010103b3u, // (API 17) 34c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski paddingHorizontal = 0x0101053du, // (API 26) 35c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski }; 36c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski }; 37c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski}; 38c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 39c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskiclass XmlCompatVersionerTest : public ::testing::Test { 40c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski public: 41c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski void SetUp() override { 42c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski context_ = 43c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski test::ContextBuilder() 44c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski .SetCompilationPackage("com.app") 45c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski .SetPackageId(0x7f) 46c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski .SetPackageType(PackageType::kApp) 47c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski .SetMinSdkVersion(SDK_GINGERBREAD) 48c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski .AddSymbolSource( 49c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski test::StaticSymbolSourceBuilder() 50c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski .AddPublicSymbol("android:attr/paddingLeft", R::attr::paddingLeft, 51c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski util::make_unique<Attribute>(false, TYPE_DIMENSION)) 52c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski .AddPublicSymbol("android:attr/paddingRight", R::attr::paddingRight, 53c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski util::make_unique<Attribute>(false, TYPE_DIMENSION)) 54c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski .AddPublicSymbol("android:attr/progressBarPadding", R::attr::progressBarPadding, 55c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski util::make_unique<Attribute>(false, TYPE_DIMENSION)) 56c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski .AddPublicSymbol("android:attr/paddingStart", R::attr::paddingStart, 57c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski util::make_unique<Attribute>(false, TYPE_DIMENSION)) 58c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski .AddPublicSymbol("android:attr/paddingHorizontal", R::attr::paddingHorizontal, 59c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski util::make_unique<Attribute>(false, TYPE_DIMENSION)) 60c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski .AddSymbol("com.app:attr/foo", ResourceId(0x7f010000), 61c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski util::make_unique<Attribute>(false, TYPE_STRING)) 62c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski .Build()) 63c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski .Build(); 64c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski } 65c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 66c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski protected: 67c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski std::unique_ptr<IAaptContext> context_; 68c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski}; 69c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 70c744ae8aca97edfb2422598ea620e8219449fa9bAdam LesinskiTEST_F(XmlCompatVersionerTest, NoRulesOnlyStripsAndCopies) { 71c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski auto doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF( 72c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski <View xmlns:android="http://schemas.android.com/apk/res/android" 73c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski xmlns:app="http://schemas.android.com/apk/res-auto" 74c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski android:paddingHorizontal="24dp" 75c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski app:foo="16dp" 76c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski foo="bar"/>)EOF"); 77c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 78c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski XmlReferenceLinker linker; 79c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(linker.Consume(context_.get(), doc.get())); 80c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 81c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski XmlCompatVersioner::Rules rules; 82c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski const util::Range<ApiVersion> api_range{SDK_GINGERBREAD, SDK_O + 1}; 83c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 84c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski XmlCompatVersioner versioner(&rules); 85c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs = 86c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski versioner.Process(context_.get(), doc.get(), api_range); 87c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_EQ(2u, versioned_docs.size()); 88c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 89c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski xml::Element* el; 90c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 91c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski // Source XML file's sdkVersion == 0, so the first one must also have the same sdkVersion. 92c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(static_cast<uint16_t>(0), versioned_docs[0]->file.config.sdkVersion); 93c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski el = xml::FindRootElement(versioned_docs[0].get()); 94c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, el); 95c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(2u, el->attributes.size()); 96c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")); 97c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAuto, "foo")); 98c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_NE(nullptr, el->FindAttribute({}, "foo")); 99c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 100c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(static_cast<uint16_t>(SDK_LOLLIPOP_MR1), versioned_docs[1]->file.config.sdkVersion); 101c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski el = xml::FindRootElement(versioned_docs[1].get()); 102c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, el); 103c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(3u, el->attributes.size()); 104c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")); 105c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAuto, "foo")); 106c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_NE(nullptr, el->FindAttribute({}, "foo")); 107c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski} 108c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 109c744ae8aca97edfb2422598ea620e8219449fa9bAdam LesinskiTEST_F(XmlCompatVersionerTest, SingleRule) { 110c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski auto doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF( 111c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski <View xmlns:android="http://schemas.android.com/apk/res/android" 112c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski xmlns:app="http://schemas.android.com/apk/res-auto" 113c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski android:paddingHorizontal="24dp" 114c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski app:foo="16dp" 115c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski foo="bar"/>)EOF"); 116c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 117c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski XmlReferenceLinker linker; 118c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(linker.Consume(context_.get(), doc.get())); 119c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 120c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski XmlCompatVersioner::Rules rules; 121c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski rules[R::attr::paddingHorizontal] = 122c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski util::make_unique<DegradeToManyRule>(std::vector<ReplacementAttr>( 123c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski {ReplacementAttr{"paddingLeft", R::attr::paddingLeft, Attribute(false, TYPE_DIMENSION)}, 124c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ReplacementAttr{"paddingRight", R::attr::paddingRight, 125c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski Attribute(false, TYPE_DIMENSION)}})); 126c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 127c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski const util::Range<ApiVersion> api_range{SDK_GINGERBREAD, SDK_O + 1}; 128c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 129c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski XmlCompatVersioner versioner(&rules); 130c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs = 131c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski versioner.Process(context_.get(), doc.get(), api_range); 132c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_EQ(2u, versioned_docs.size()); 133c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 134c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski xml::Element* el; 135c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 136c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(static_cast<uint16_t>(0), versioned_docs[0]->file.config.sdkVersion); 137c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski el = xml::FindRootElement(versioned_docs[0].get()); 138c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, el); 139c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(4u, el->attributes.size()); 140c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")); 141c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAuto, "foo")); 142c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_NE(nullptr, el->FindAttribute({}, "foo")); 143c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 144c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"); 145c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr); 146c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr->compiled_value); 147c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(attr->compiled_attribute); 148c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 149c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight"); 150c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr); 151c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr->compiled_value); 152c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(attr->compiled_attribute); 153c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 154c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(static_cast<uint16_t>(SDK_LOLLIPOP_MR1), versioned_docs[1]->file.config.sdkVersion); 155c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski el = xml::FindRootElement(versioned_docs[1].get()); 156c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, el); 157c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(5u, el->attributes.size()); 158c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")); 159c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAuto, "foo")); 160c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_NE(nullptr, el->FindAttribute({}, "foo")); 161c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 162c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"); 163c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr); 164c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr->compiled_value); 165c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(attr->compiled_attribute); 166c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 167c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight"); 168c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr); 169c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr->compiled_value); 170c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(attr->compiled_attribute); 171c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski} 172c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 173c744ae8aca97edfb2422598ea620e8219449fa9bAdam LesinskiTEST_F(XmlCompatVersionerTest, ChainedRule) { 174c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski auto doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF( 175c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski <View xmlns:android="http://schemas.android.com/apk/res/android" 176c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski android:paddingHorizontal="24dp" />)EOF"); 177c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 178c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski XmlReferenceLinker linker; 179c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(linker.Consume(context_.get(), doc.get())); 180c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 181c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski XmlCompatVersioner::Rules rules; 182c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski rules[R::attr::progressBarPadding] = 183c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski util::make_unique<DegradeToManyRule>(std::vector<ReplacementAttr>( 184c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski {ReplacementAttr{"paddingLeft", R::attr::paddingLeft, Attribute(false, TYPE_DIMENSION)}, 185c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ReplacementAttr{"paddingRight", R::attr::paddingRight, 186c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski Attribute(false, TYPE_DIMENSION)}})); 187c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski rules[R::attr::paddingHorizontal] = 188c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski util::make_unique<DegradeToManyRule>(std::vector<ReplacementAttr>({ReplacementAttr{ 189c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski "progressBarPadding", R::attr::progressBarPadding, Attribute(false, TYPE_DIMENSION)}})); 190c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 191c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski const util::Range<ApiVersion> api_range{SDK_GINGERBREAD, SDK_O + 1}; 192c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 193c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski XmlCompatVersioner versioner(&rules); 194c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs = 195c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski versioner.Process(context_.get(), doc.get(), api_range); 196c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_EQ(3u, versioned_docs.size()); 197c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 198c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski xml::Element* el; 199c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 200c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(static_cast<uint16_t>(0), versioned_docs[0]->file.config.sdkVersion); 201c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski el = xml::FindRootElement(versioned_docs[0].get()); 202c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, el); 203c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(2u, el->attributes.size()); 204c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")); 205c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 206c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"); 207c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr); 208c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr->compiled_value); 209c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(attr->compiled_attribute); 210c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 211c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight"); 212c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr); 213c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr->compiled_value); 214c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(attr->compiled_attribute); 215c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 216c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(static_cast<uint16_t>(SDK_HONEYCOMB), versioned_docs[1]->file.config.sdkVersion); 217c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski el = xml::FindRootElement(versioned_docs[1].get()); 218c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, el); 219c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(1u, el->attributes.size()); 220c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")); 221c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingLeft")); 222c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingRight")); 223c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 224c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski attr = el->FindAttribute(xml::kSchemaAndroid, "progressBarPadding"); 225c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr); 226c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr->compiled_value); 227c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(attr->compiled_attribute); 228c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 229c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(static_cast<uint16_t>(SDK_LOLLIPOP_MR1), versioned_docs[2]->file.config.sdkVersion); 230c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski el = xml::FindRootElement(versioned_docs[2].get()); 231c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, el); 232c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(2u, el->attributes.size()); 233c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingLeft")); 234c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingRight")); 235c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 236c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski attr = el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"); 237c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr); 238c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr->compiled_value); 239c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(attr->compiled_attribute); 240c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 241c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski attr = el->FindAttribute(xml::kSchemaAndroid, "progressBarPadding"); 242c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr); 243c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr->compiled_value); 244c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(attr->compiled_attribute); 245c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski} 246c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 247c744ae8aca97edfb2422598ea620e8219449fa9bAdam LesinskiTEST_F(XmlCompatVersionerTest, DegradeRuleOverridesExistingAttribute) { 248c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski auto doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF( 249c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski <View xmlns:android="http://schemas.android.com/apk/res/android" 250c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski android:paddingHorizontal="24dp" 251c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski android:paddingLeft="16dp" 252c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski android:paddingRight="16dp"/>)EOF"); 253c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 254c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski XmlReferenceLinker linker; 255c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(linker.Consume(context_.get(), doc.get())); 256c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 257c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski Item* padding_horizontal_value = xml::FindRootElement(doc.get()) 258c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal") 259c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ->compiled_value.get(); 260c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, padding_horizontal_value); 261c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 262c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski XmlCompatVersioner::Rules rules; 263c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski rules[R::attr::paddingHorizontal] = 264c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski util::make_unique<DegradeToManyRule>(std::vector<ReplacementAttr>( 265c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski {ReplacementAttr{"paddingLeft", R::attr::paddingLeft, Attribute(false, TYPE_DIMENSION)}, 266c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ReplacementAttr{"paddingRight", R::attr::paddingRight, 267c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski Attribute(false, TYPE_DIMENSION)}})); 268c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 269c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski const util::Range<ApiVersion> api_range{SDK_GINGERBREAD, SDK_O + 1}; 270c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 271c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski XmlCompatVersioner versioner(&rules); 272c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs = 273c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski versioner.Process(context_.get(), doc.get(), api_range); 274c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_EQ(2u, versioned_docs.size()); 275c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 276c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski xml::Element* el; 277c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 278c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(static_cast<uint16_t>(0), versioned_docs[0]->file.config.sdkVersion); 279c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski el = xml::FindRootElement(versioned_docs[0].get()); 280c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, el); 281c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(2u, el->attributes.size()); 282c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")); 283c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 284c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"); 285c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr); 286c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr->compiled_value); 287c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(padding_horizontal_value->Equals(attr->compiled_value.get())); 288c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(attr->compiled_attribute); 289c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 290c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight"); 291c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr); 292c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr->compiled_value); 293c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(padding_horizontal_value->Equals(attr->compiled_value.get())); 294c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(attr->compiled_attribute); 295c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 296c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(static_cast<uint16_t>(SDK_LOLLIPOP_MR1), versioned_docs[1]->file.config.sdkVersion); 297c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski el = xml::FindRootElement(versioned_docs[1].get()); 298c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, el); 299c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski EXPECT_EQ(3u, el->attributes.size()); 300c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 301c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski attr = el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"); 302c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr); 303c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr->compiled_value); 304c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(padding_horizontal_value->Equals(attr->compiled_value.get())); 305c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(attr->compiled_attribute); 306c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 307c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"); 308c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr); 309c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr->compiled_value); 310c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(padding_horizontal_value->Equals(attr->compiled_value.get())); 311c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(attr->compiled_attribute); 312c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 313c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight"); 314c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr); 315c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_NE(nullptr, attr->compiled_value); 316c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(padding_horizontal_value->Equals(attr->compiled_value.get())); 317c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ASSERT_TRUE(attr->compiled_attribute); 318c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski} 319c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 320c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski} // namespace aapt 321