/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "link/ManifestFixer.h" #include "test/Test.h" using ::android::StringPiece; using ::testing::NotNull; namespace aapt { struct ManifestFixerTest : public ::testing::Test { std::unique_ptr mContext; void SetUp() override { mContext = test::ContextBuilder() .SetCompilationPackage("android") .SetPackageId(0x01) .SetNameManglerPolicy(NameManglerPolicy{"android"}) .AddSymbolSource( test::StaticSymbolSourceBuilder() .AddSymbol( "android:attr/package", ResourceId(0x01010000), test::AttributeBuilder() .SetTypeMask(android::ResTable_map::TYPE_STRING) .Build()) .AddSymbol( "android:attr/minSdkVersion", ResourceId(0x01010001), test::AttributeBuilder() .SetTypeMask(android::ResTable_map::TYPE_STRING | android::ResTable_map::TYPE_INTEGER) .Build()) .AddSymbol( "android:attr/targetSdkVersion", ResourceId(0x01010002), test::AttributeBuilder() .SetTypeMask(android::ResTable_map::TYPE_STRING | android::ResTable_map::TYPE_INTEGER) .Build()) .AddSymbol("android:string/str", ResourceId(0x01060000)) .Build()) .Build(); } std::unique_ptr Verify(const StringPiece& str) { return VerifyWithOptions(str, {}); } std::unique_ptr VerifyWithOptions( const StringPiece& str, const ManifestFixerOptions& options) { std::unique_ptr doc = test::BuildXmlDom(str); ManifestFixer fixer(options); if (fixer.Consume(mContext.get(), doc.get())) { return doc; } return {}; } }; TEST_F(ManifestFixerTest, EnsureManifestIsRootTag) { EXPECT_EQ(nullptr, Verify("")); EXPECT_EQ(nullptr, Verify("")); EXPECT_NE(nullptr, Verify("")); } TEST_F(ManifestFixerTest, EnsureManifestHasPackage) { EXPECT_NE(nullptr, Verify("")); EXPECT_NE(nullptr, Verify("")); EXPECT_NE(nullptr, Verify("")); EXPECT_EQ(nullptr, Verify("")); EXPECT_EQ(nullptr, Verify("")); EXPECT_EQ(nullptr, Verify("")); } TEST_F(ManifestFixerTest, AllowMetaData) { auto doc = Verify(R"EOF( )EOF"); ASSERT_NE(nullptr, doc); } TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) { ManifestFixerOptions options = {std::string("8"), std::string("22")}; std::unique_ptr doc = VerifyWithOptions(R"EOF( )EOF", options); ASSERT_NE(nullptr, doc); xml::Element* el; xml::Attribute* attr; el = doc->root.get(); ASSERT_NE(nullptr, el); el = el->FindChild({}, "uses-sdk"); ASSERT_NE(nullptr, el); attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion"); ASSERT_NE(nullptr, attr); EXPECT_EQ("7", attr->value); attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion"); ASSERT_NE(nullptr, attr); EXPECT_EQ("21", attr->value); doc = VerifyWithOptions(R"EOF( )EOF", options); ASSERT_NE(nullptr, doc); el = doc->root.get(); ASSERT_NE(nullptr, el); el = el->FindChild({}, "uses-sdk"); ASSERT_NE(nullptr, el); attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion"); ASSERT_NE(nullptr, attr); EXPECT_EQ("8", attr->value); attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion"); ASSERT_NE(nullptr, attr); EXPECT_EQ("21", attr->value); doc = VerifyWithOptions(R"EOF( )EOF", options); ASSERT_NE(nullptr, doc); el = doc->root.get(); ASSERT_NE(nullptr, el); el = el->FindChild({}, "uses-sdk"); ASSERT_NE(nullptr, el); attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion"); ASSERT_NE(nullptr, attr); EXPECT_EQ("8", attr->value); attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion"); ASSERT_NE(nullptr, attr); EXPECT_EQ("22", attr->value); doc = VerifyWithOptions(R"EOF( )EOF", options); ASSERT_NE(nullptr, doc); el = doc->root.get(); ASSERT_NE(nullptr, el); el = el->FindChild({}, "uses-sdk"); ASSERT_NE(nullptr, el); attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion"); ASSERT_NE(nullptr, attr); EXPECT_EQ("8", attr->value); attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion"); ASSERT_NE(nullptr, attr); EXPECT_EQ("22", attr->value); } TEST_F(ManifestFixerTest, UsesSdkMustComeBeforeApplication) { ManifestFixerOptions options = {std::string("8"), std::string("22")}; std::unique_ptr doc = VerifyWithOptions(R"EOF( )EOF", options); ASSERT_NE(nullptr, doc); xml::Element* manifest_el = doc->root.get(); ASSERT_NE(nullptr, manifest_el); ASSERT_EQ("manifest", manifest_el->name); xml::Element* application_el = manifest_el->FindChild("", "application"); ASSERT_NE(nullptr, application_el); xml::Element* uses_sdk_el = manifest_el->FindChild("", "uses-sdk"); ASSERT_NE(nullptr, uses_sdk_el); // Check that the uses_sdk_el comes before application_el in the children // vector. // Since there are no namespaces here, these children are direct descendants // of manifest. auto uses_sdk_iter = std::find_if(manifest_el->children.begin(), manifest_el->children.end(), [&](const std::unique_ptr& child) { return child.get() == uses_sdk_el; }); auto application_iter = std::find_if(manifest_el->children.begin(), manifest_el->children.end(), [&](const std::unique_ptr& child) { return child.get() == application_el; }); ASSERT_NE(manifest_el->children.end(), uses_sdk_iter); ASSERT_NE(manifest_el->children.end(), application_iter); // The distance should be positive, meaning uses_sdk_iter comes before // application_iter. EXPECT_GT(std::distance(uses_sdk_iter, application_iter), 0); } TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) { ManifestFixerOptions options; options.rename_manifest_package = std::string("com.android"); std::unique_ptr doc = VerifyWithOptions(R"EOF( )EOF", options); ASSERT_NE(nullptr, doc); xml::Element* manifestEl = doc->root.get(); ASSERT_NE(nullptr, manifestEl); xml::Attribute* attr = nullptr; attr = manifestEl->FindAttribute({}, "package"); ASSERT_NE(nullptr, attr); EXPECT_EQ(std::string("com.android"), attr->value); xml::Element* applicationEl = manifestEl->FindChild({}, "application"); ASSERT_NE(nullptr, applicationEl); attr = applicationEl->FindAttribute(xml::kSchemaAndroid, "name"); ASSERT_NE(nullptr, attr); EXPECT_EQ(std::string("android.MainApplication"), attr->value); attr = applicationEl->FindAttribute({}, "text"); ASSERT_NE(nullptr, attr); EXPECT_EQ(std::string("hello"), attr->value); xml::Element* el; el = applicationEl->FindChild({}, "activity"); ASSERT_NE(nullptr, el); attr = el->FindAttribute(xml::kSchemaAndroid, "name"); ASSERT_NE(nullptr, el); EXPECT_EQ(std::string("android.activity.Start"), attr->value); el = applicationEl->FindChild({}, "receiver"); ASSERT_NE(nullptr, el); attr = el->FindAttribute(xml::kSchemaAndroid, "name"); ASSERT_NE(nullptr, el); EXPECT_EQ(std::string("com.google.android.Receiver"), attr->value); } TEST_F(ManifestFixerTest, RenameManifestInstrumentationPackageAndFullyQualifyTarget) { ManifestFixerOptions options; options.rename_instrumentation_target_package = std::string("com.android"); std::unique_ptr doc = VerifyWithOptions(R"EOF( )EOF", options); ASSERT_NE(nullptr, doc); xml::Element* manifest_el = doc->root.get(); ASSERT_NE(nullptr, manifest_el); xml::Element* instrumentation_el = manifest_el->FindChild({}, "instrumentation"); ASSERT_NE(nullptr, instrumentation_el); xml::Attribute* attr = instrumentation_el->FindAttribute(xml::kSchemaAndroid, "targetPackage"); ASSERT_NE(nullptr, attr); EXPECT_EQ(std::string("com.android"), attr->value); } TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) { ManifestFixerOptions options; options.version_name_default = std::string("Beta"); options.version_code_default = std::string("0x10000000"); std::unique_ptr doc = VerifyWithOptions(R"EOF( )EOF", options); ASSERT_NE(nullptr, doc); xml::Element* manifest_el = doc->root.get(); ASSERT_NE(nullptr, manifest_el); xml::Attribute* attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName"); ASSERT_NE(nullptr, attr); EXPECT_EQ(std::string("Beta"), attr->value); attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode"); ASSERT_NE(nullptr, attr); EXPECT_EQ(std::string("0x10000000"), attr->value); } TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) { EXPECT_EQ(nullptr, Verify("")); EXPECT_EQ(nullptr, Verify("")); std::unique_ptr doc = Verify(""); ASSERT_NE(nullptr, doc); xml::Element* el = doc->root.get(); ASSERT_NE(nullptr, el); EXPECT_EQ("manifest", el->name); xml::Attribute* attr = el->FindAttribute("", "coreApp"); ASSERT_NE(nullptr, attr); EXPECT_NE(nullptr, attr->compiled_value); EXPECT_NE(nullptr, ValueCast(attr->compiled_value.get())); } TEST_F(ManifestFixerTest, UsesFeatureMustHaveNameOrGlEsVersion) { std::string input = R"EOF( )EOF"; EXPECT_NE(nullptr, Verify(input)); input = R"EOF( )EOF"; EXPECT_EQ(nullptr, Verify(input)); input = R"EOF( )EOF"; EXPECT_EQ(nullptr, Verify(input)); input = R"EOF( )EOF"; EXPECT_EQ(nullptr, Verify(input)); input = R"EOF( )EOF"; EXPECT_EQ(nullptr, Verify(input)); } TEST_F(ManifestFixerTest, IgnoreNamespacedElements) { std::string input = R"EOF( )EOF"; EXPECT_NE(nullptr, Verify(input)); } TEST_F(ManifestFixerTest, DoNotIgnoreNonNamespacedElements) { std::string input = R"EOF( )EOF"; EXPECT_EQ(nullptr, Verify(input)); } TEST_F(ManifestFixerTest, SupportKeySets) { std::string input = R"( )"; EXPECT_THAT(Verify(input), NotNull()); } } // namespace aapt