ManifestFixer_test.cpp revision 63699b128e009c65affe50995bd8f86eca1a8694
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "link/ManifestFixer.h" 18 19#include "test/Test.h" 20 21using android::StringPiece; 22 23namespace aapt { 24 25struct ManifestFixerTest : public ::testing::Test { 26 std::unique_ptr<IAaptContext> mContext; 27 28 void SetUp() override { 29 mContext = 30 test::ContextBuilder() 31 .SetCompilationPackage("android") 32 .SetPackageId(0x01) 33 .SetNameManglerPolicy(NameManglerPolicy{"android"}) 34 .AddSymbolSource( 35 test::StaticSymbolSourceBuilder() 36 .AddSymbol( 37 "android:attr/package", ResourceId(0x01010000), 38 test::AttributeBuilder() 39 .SetTypeMask(android::ResTable_map::TYPE_STRING) 40 .Build()) 41 .AddSymbol( 42 "android:attr/minSdkVersion", ResourceId(0x01010001), 43 test::AttributeBuilder() 44 .SetTypeMask(android::ResTable_map::TYPE_STRING | 45 android::ResTable_map::TYPE_INTEGER) 46 .Build()) 47 .AddSymbol( 48 "android:attr/targetSdkVersion", ResourceId(0x01010002), 49 test::AttributeBuilder() 50 .SetTypeMask(android::ResTable_map::TYPE_STRING | 51 android::ResTable_map::TYPE_INTEGER) 52 .Build()) 53 .AddSymbol("android:string/str", ResourceId(0x01060000)) 54 .Build()) 55 .Build(); 56 } 57 58 std::unique_ptr<xml::XmlResource> Verify(const StringPiece& str) { 59 return VerifyWithOptions(str, {}); 60 } 61 62 std::unique_ptr<xml::XmlResource> VerifyWithOptions( 63 const StringPiece& str, const ManifestFixerOptions& options) { 64 std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(str); 65 ManifestFixer fixer(options); 66 if (fixer.Consume(mContext.get(), doc.get())) { 67 return doc; 68 } 69 return {}; 70 } 71}; 72 73TEST_F(ManifestFixerTest, EnsureManifestIsRootTag) { 74 EXPECT_EQ(nullptr, Verify("<other-tag />")); 75 EXPECT_EQ(nullptr, Verify("<ns:manifest xmlns:ns=\"com\" />")); 76 EXPECT_NE(nullptr, Verify("<manifest package=\"android\"></manifest>")); 77} 78 79TEST_F(ManifestFixerTest, EnsureManifestHasPackage) { 80 EXPECT_NE(nullptr, Verify("<manifest package=\"android\" />")); 81 EXPECT_NE(nullptr, Verify("<manifest package=\"com.android\" />")); 82 EXPECT_NE(nullptr, Verify("<manifest package=\"com.android.google\" />")); 83 EXPECT_EQ(nullptr, 84 Verify("<manifest package=\"com.android.google.Class$1\" />")); 85 EXPECT_EQ(nullptr, Verify("<manifest " 86 "xmlns:android=\"http://schemas.android.com/apk/" 87 "res/android\" " 88 "android:package=\"com.android\" />")); 89 EXPECT_EQ(nullptr, Verify("<manifest package=\"@string/str\" />")); 90} 91 92TEST_F(ManifestFixerTest, AllowMetaData) { 93 auto doc = Verify(R"EOF( 94 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 95 package="android"> 96 <meta-data /> 97 <application> 98 <meta-data /> 99 <activity android:name=".Hi"><meta-data /></activity> 100 <activity-alias android:name=".Ho"><meta-data /></activity-alias> 101 <receiver android:name=".OffTo"><meta-data /></receiver> 102 <provider android:name=".Work"><meta-data /></provider> 103 <service android:name=".We"><meta-data /></service> 104 </application> 105 <instrumentation android:name=".Go"><meta-data /></instrumentation> 106 </manifest>)EOF"); 107 ASSERT_NE(nullptr, doc); 108} 109 110TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) { 111 ManifestFixerOptions options = {std::string("8"), std::string("22")}; 112 113 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF( 114 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 115 package="android"> 116 <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="21" /> 117 </manifest>)EOF", 118 options); 119 ASSERT_NE(nullptr, doc); 120 121 xml::Element* el; 122 xml::Attribute* attr; 123 124 el = xml::FindRootElement(doc.get()); 125 ASSERT_NE(nullptr, el); 126 el = el->FindChild({}, "uses-sdk"); 127 ASSERT_NE(nullptr, el); 128 attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion"); 129 ASSERT_NE(nullptr, attr); 130 EXPECT_EQ("7", attr->value); 131 attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion"); 132 ASSERT_NE(nullptr, attr); 133 EXPECT_EQ("21", attr->value); 134 135 doc = VerifyWithOptions(R"EOF( 136 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 137 package="android"> 138 <uses-sdk android:targetSdkVersion="21" /> 139 </manifest>)EOF", 140 options); 141 ASSERT_NE(nullptr, doc); 142 143 el = xml::FindRootElement(doc.get()); 144 ASSERT_NE(nullptr, el); 145 el = el->FindChild({}, "uses-sdk"); 146 ASSERT_NE(nullptr, el); 147 attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion"); 148 ASSERT_NE(nullptr, attr); 149 EXPECT_EQ("8", attr->value); 150 attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion"); 151 ASSERT_NE(nullptr, attr); 152 EXPECT_EQ("21", attr->value); 153 154 doc = VerifyWithOptions(R"EOF( 155 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 156 package="android"> 157 <uses-sdk /> 158 </manifest>)EOF", 159 options); 160 ASSERT_NE(nullptr, doc); 161 162 el = xml::FindRootElement(doc.get()); 163 ASSERT_NE(nullptr, el); 164 el = el->FindChild({}, "uses-sdk"); 165 ASSERT_NE(nullptr, el); 166 attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion"); 167 ASSERT_NE(nullptr, attr); 168 EXPECT_EQ("8", attr->value); 169 attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion"); 170 ASSERT_NE(nullptr, attr); 171 EXPECT_EQ("22", attr->value); 172 173 doc = VerifyWithOptions(R"EOF( 174 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 175 package="android" />)EOF", 176 options); 177 ASSERT_NE(nullptr, doc); 178 179 el = xml::FindRootElement(doc.get()); 180 ASSERT_NE(nullptr, el); 181 el = el->FindChild({}, "uses-sdk"); 182 ASSERT_NE(nullptr, el); 183 attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion"); 184 ASSERT_NE(nullptr, attr); 185 EXPECT_EQ("8", attr->value); 186 attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion"); 187 ASSERT_NE(nullptr, attr); 188 EXPECT_EQ("22", attr->value); 189} 190 191TEST_F(ManifestFixerTest, UsesSdkMustComeBeforeApplication) { 192 ManifestFixerOptions options = {std::string("8"), std::string("22")}; 193 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF( 194 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 195 package="android"> 196 <application android:name=".MainApplication" /> 197 </manifest>)EOF", 198 options); 199 ASSERT_NE(nullptr, doc); 200 201 xml::Element* manifest_el = xml::FindRootElement(doc.get()); 202 ASSERT_NE(nullptr, manifest_el); 203 ASSERT_EQ("manifest", manifest_el->name); 204 205 xml::Element* application_el = manifest_el->FindChild("", "application"); 206 ASSERT_NE(nullptr, application_el); 207 208 xml::Element* uses_sdk_el = manifest_el->FindChild("", "uses-sdk"); 209 ASSERT_NE(nullptr, uses_sdk_el); 210 211 // Check that the uses_sdk_el comes before application_el in the children 212 // vector. 213 // Since there are no namespaces here, these children are direct descendants 214 // of manifest. 215 auto uses_sdk_iter = 216 std::find_if(manifest_el->children.begin(), manifest_el->children.end(), 217 [&](const std::unique_ptr<xml::Node>& child) { 218 return child.get() == uses_sdk_el; 219 }); 220 221 auto application_iter = 222 std::find_if(manifest_el->children.begin(), manifest_el->children.end(), 223 [&](const std::unique_ptr<xml::Node>& child) { 224 return child.get() == application_el; 225 }); 226 227 ASSERT_NE(manifest_el->children.end(), uses_sdk_iter); 228 ASSERT_NE(manifest_el->children.end(), application_iter); 229 230 // The distance should be positive, meaning uses_sdk_iter comes before 231 // application_iter. 232 EXPECT_GT(std::distance(uses_sdk_iter, application_iter), 0); 233} 234 235TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) { 236 ManifestFixerOptions options; 237 options.rename_manifest_package = std::string("com.android"); 238 239 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF( 240 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 241 package="android"> 242 <application android:name=".MainApplication" text="hello"> 243 <activity android:name=".activity.Start" /> 244 <receiver android:name="com.google.android.Receiver" /> 245 </application> 246 </manifest>)EOF", 247 options); 248 ASSERT_NE(nullptr, doc); 249 250 xml::Element* manifestEl = xml::FindRootElement(doc.get()); 251 ASSERT_NE(nullptr, manifestEl); 252 253 xml::Attribute* attr = nullptr; 254 255 attr = manifestEl->FindAttribute({}, "package"); 256 ASSERT_NE(nullptr, attr); 257 EXPECT_EQ(std::string("com.android"), attr->value); 258 259 xml::Element* applicationEl = manifestEl->FindChild({}, "application"); 260 ASSERT_NE(nullptr, applicationEl); 261 262 attr = applicationEl->FindAttribute(xml::kSchemaAndroid, "name"); 263 ASSERT_NE(nullptr, attr); 264 EXPECT_EQ(std::string("android.MainApplication"), attr->value); 265 266 attr = applicationEl->FindAttribute({}, "text"); 267 ASSERT_NE(nullptr, attr); 268 EXPECT_EQ(std::string("hello"), attr->value); 269 270 xml::Element* el; 271 el = applicationEl->FindChild({}, "activity"); 272 ASSERT_NE(nullptr, el); 273 274 attr = el->FindAttribute(xml::kSchemaAndroid, "name"); 275 ASSERT_NE(nullptr, el); 276 EXPECT_EQ(std::string("android.activity.Start"), attr->value); 277 278 el = applicationEl->FindChild({}, "receiver"); 279 ASSERT_NE(nullptr, el); 280 281 attr = el->FindAttribute(xml::kSchemaAndroid, "name"); 282 ASSERT_NE(nullptr, el); 283 EXPECT_EQ(std::string("com.google.android.Receiver"), attr->value); 284} 285 286TEST_F(ManifestFixerTest, 287 RenameManifestInstrumentationPackageAndFullyQualifyTarget) { 288 ManifestFixerOptions options; 289 options.rename_instrumentation_target_package = std::string("com.android"); 290 291 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF( 292 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 293 package="android"> 294 <instrumentation android:name=".TestRunner" android:targetPackage="android" /> 295 </manifest>)EOF", 296 options); 297 ASSERT_NE(nullptr, doc); 298 299 xml::Element* manifest_el = xml::FindRootElement(doc.get()); 300 ASSERT_NE(nullptr, manifest_el); 301 302 xml::Element* instrumentation_el = 303 manifest_el->FindChild({}, "instrumentation"); 304 ASSERT_NE(nullptr, instrumentation_el); 305 306 xml::Attribute* attr = 307 instrumentation_el->FindAttribute(xml::kSchemaAndroid, "targetPackage"); 308 ASSERT_NE(nullptr, attr); 309 EXPECT_EQ(std::string("com.android"), attr->value); 310} 311 312TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) { 313 ManifestFixerOptions options; 314 options.version_name_default = std::string("Beta"); 315 options.version_code_default = std::string("0x10000000"); 316 317 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF( 318 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 319 package="android" />)EOF", 320 options); 321 ASSERT_NE(nullptr, doc); 322 323 xml::Element* manifest_el = xml::FindRootElement(doc.get()); 324 ASSERT_NE(nullptr, manifest_el); 325 326 xml::Attribute* attr = 327 manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName"); 328 ASSERT_NE(nullptr, attr); 329 EXPECT_EQ(std::string("Beta"), attr->value); 330 331 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode"); 332 ASSERT_NE(nullptr, attr); 333 EXPECT_EQ(std::string("0x10000000"), attr->value); 334} 335 336TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) { 337 EXPECT_EQ(nullptr, 338 Verify("<manifest package=\"android\" coreApp=\"hello\" />")); 339 EXPECT_EQ(nullptr, 340 Verify("<manifest package=\"android\" coreApp=\"1dp\" />")); 341 342 std::unique_ptr<xml::XmlResource> doc = 343 Verify("<manifest package=\"android\" coreApp=\"true\" />"); 344 ASSERT_NE(nullptr, doc); 345 346 xml::Element* el = xml::FindRootElement(doc.get()); 347 ASSERT_NE(nullptr, el); 348 349 EXPECT_EQ("manifest", el->name); 350 351 xml::Attribute* attr = el->FindAttribute("", "coreApp"); 352 ASSERT_NE(nullptr, attr); 353 354 EXPECT_NE(nullptr, attr->compiled_value); 355 EXPECT_NE(nullptr, ValueCast<BinaryPrimitive>(attr->compiled_value.get())); 356} 357 358TEST_F(ManifestFixerTest, UsesFeatureMustHaveNameOrGlEsVersion) { 359 std::string input = R"EOF( 360 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 361 package="android"> 362 <uses-feature android:name="feature" /> 363 <uses-feature android:glEsVersion="1" /> 364 <feature-group /> 365 <feature-group> 366 <uses-feature android:name="feature_in_group" /> 367 <uses-feature android:glEsVersion="2" /> 368 </feature-group> 369 </manifest>)EOF"; 370 EXPECT_NE(nullptr, Verify(input)); 371 372 input = R"EOF( 373 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 374 package="android"> 375 <uses-feature android:name="feature" android:glEsVersion="1" /> 376 </manifest>)EOF"; 377 EXPECT_EQ(nullptr, Verify(input)); 378 379 input = R"EOF( 380 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 381 package="android"> 382 <uses-feature /> 383 </manifest>)EOF"; 384 EXPECT_EQ(nullptr, Verify(input)); 385 386 input = R"EOF( 387 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 388 package="android"> 389 <feature-group> 390 <uses-feature android:name="feature" android:glEsVersion="1" /> 391 </feature-group> 392 </manifest>)EOF"; 393 EXPECT_EQ(nullptr, Verify(input)); 394 395 input = R"EOF( 396 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 397 package="android"> 398 <feature-group> 399 <uses-feature /> 400 </feature-group> 401 </manifest>)EOF"; 402 EXPECT_EQ(nullptr, Verify(input)); 403} 404 405TEST_F(ManifestFixerTest, IgnoreNamespacedElements) { 406 std::string input = R"EOF( 407 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 408 package="android"> 409 <special:tag whoo="true" xmlns:special="http://google.com" /> 410 </manifest>)EOF"; 411 EXPECT_NE(nullptr, Verify(input)); 412} 413 414TEST_F(ManifestFixerTest, DoNotIgnoreNonNamespacedElements) { 415 std::string input = R"EOF( 416 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 417 package="android"> 418 <tag whoo="true" /> 419 </manifest>)EOF"; 420 EXPECT_EQ(nullptr, Verify(input)); 421} 422 423} // namespace aapt 424