blob: 0e29ba6b6071ee1d04acfa3fc11b118824a27aea [file] [log] [blame]
/*
* 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"
namespace aapt {
struct ManifestFixerTest : public ::testing::Test {
std::unique_ptr<IAaptContext> 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<xml::XmlResource> Verify(const StringPiece& str) {
return VerifyWithOptions(str, {});
}
std::unique_ptr<xml::XmlResource> VerifyWithOptions(
const StringPiece& str, const ManifestFixerOptions& options) {
std::unique_ptr<xml::XmlResource> 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("<other-tag />"));
EXPECT_EQ(nullptr, Verify("<ns:manifest xmlns:ns=\"com\" />"));
EXPECT_NE(nullptr, Verify("<manifest package=\"android\"></manifest>"));
}
TEST_F(ManifestFixerTest, EnsureManifestHasPackage) {
EXPECT_NE(nullptr, Verify("<manifest package=\"android\" />"));
EXPECT_NE(nullptr, Verify("<manifest package=\"com.android\" />"));
EXPECT_NE(nullptr, Verify("<manifest package=\"com.android.google\" />"));
EXPECT_EQ(nullptr,
Verify("<manifest package=\"com.android.google.Class$1\" />"));
EXPECT_EQ(nullptr, Verify("<manifest "
"xmlns:android=\"http://schemas.android.com/apk/"
"res/android\" "
"android:package=\"com.android\" />"));
EXPECT_EQ(nullptr, Verify("<manifest package=\"@string/str\" />"));
}
TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
ManifestFixerOptions options = {std::string("8"), std::string("22")};
std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android">
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="21" />
</manifest>)EOF",
options);
ASSERT_NE(nullptr, doc);
xml::Element* el;
xml::Attribute* attr;
el = xml::FindRootElement(doc.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(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android">
<uses-sdk android:targetSdkVersion="21" />
</manifest>)EOF",
options);
ASSERT_NE(nullptr, doc);
el = xml::FindRootElement(doc.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(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android">
<uses-sdk />
</manifest>)EOF",
options);
ASSERT_NE(nullptr, doc);
el = xml::FindRootElement(doc.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(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android" />)EOF",
options);
ASSERT_NE(nullptr, doc);
el = xml::FindRootElement(doc.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, RenameManifestPackageAndFullyQualifyClasses) {
ManifestFixerOptions options;
options.rename_manifest_package = std::string("com.android");
std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android">
<application android:name=".MainApplication" text="hello">
<activity android:name=".activity.Start" />
<receiver android:name="com.google.android.Receiver" />
</application>
</manifest>)EOF",
options);
ASSERT_NE(nullptr, doc);
xml::Element* manifestEl = xml::FindRootElement(doc.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<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android">
<instrumentation android:targetPackage="android" />
</manifest>)EOF",
options);
ASSERT_NE(nullptr, doc);
xml::Element* manifest_el = xml::FindRootElement(doc.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<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android" />)EOF",
options);
ASSERT_NE(nullptr, doc);
xml::Element* manifest_el = xml::FindRootElement(doc.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("<manifest package=\"android\" coreApp=\"hello\" />"));
EXPECT_EQ(nullptr,
Verify("<manifest package=\"android\" coreApp=\"1dp\" />"));
std::unique_ptr<xml::XmlResource> doc =
Verify("<manifest package=\"android\" coreApp=\"true\" />");
ASSERT_NE(nullptr, doc);
xml::Element* el = xml::FindRootElement(doc.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<BinaryPrimitive>(attr->compiled_value.get()));
}
} // namespace aapt