You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
967 lines
32 KiB
967 lines
32 KiB
/*
|
|
* Copyright (C) 2017 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 "configuration/ConfigurationParser.h"
|
|
|
|
#include <string>
|
|
|
|
#include "android-base/stringprintf.h"
|
|
#include "androidfw/ResourceTypes.h"
|
|
|
|
#include "SdkConstants.h"
|
|
#include "configuration/ConfigurationParser.internal.h"
|
|
#include "test/Test.h"
|
|
#include "xml/XmlDom.h"
|
|
|
|
using ::android::ConfigDescription;
|
|
|
|
namespace aapt {
|
|
|
|
namespace configuration {
|
|
void PrintTo(const AndroidSdk& sdk, std::ostream* os) {
|
|
*os << "SDK: min=" << sdk.min_sdk_version
|
|
<< ", target=" << sdk.target_sdk_version.value_or_default(-1)
|
|
<< ", max=" << sdk.max_sdk_version.value_or_default(-1);
|
|
}
|
|
|
|
bool operator==(const ConfiguredArtifact& lhs, const ConfiguredArtifact& rhs) {
|
|
return lhs.name == rhs.name && lhs.abi_group == rhs.abi_group &&
|
|
lhs.screen_density_group == rhs.screen_density_group &&
|
|
lhs.locale_group == rhs.locale_group && lhs.android_sdk == rhs.android_sdk &&
|
|
lhs.device_feature_group == rhs.device_feature_group &&
|
|
lhs.gl_texture_group == rhs.gl_texture_group;
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& out, const Maybe<std::string>& value) {
|
|
PrintTo(value, &out);
|
|
return out;
|
|
}
|
|
|
|
void PrintTo(const ConfiguredArtifact& artifact, std::ostream* os) {
|
|
*os << "\n{"
|
|
<< "\n name: " << artifact.name << "\n sdk: " << artifact.android_sdk
|
|
<< "\n abi: " << artifact.abi_group << "\n density: " << artifact.screen_density_group
|
|
<< "\n locale: " << artifact.locale_group
|
|
<< "\n features: " << artifact.device_feature_group
|
|
<< "\n textures: " << artifact.gl_texture_group << "\n}\n";
|
|
}
|
|
|
|
namespace handler {
|
|
|
|
namespace {
|
|
|
|
using ::aapt::configuration::Abi;
|
|
using ::aapt::configuration::AndroidManifest;
|
|
using ::aapt::configuration::AndroidSdk;
|
|
using ::aapt::configuration::ConfiguredArtifact;
|
|
using ::aapt::configuration::DeviceFeature;
|
|
using ::aapt::configuration::ExtractConfiguration;
|
|
using ::aapt::configuration::GlTexture;
|
|
using ::aapt::configuration::Locale;
|
|
using ::aapt::configuration::PostProcessingConfiguration;
|
|
using ::aapt::xml::Element;
|
|
using ::aapt::xml::NodeCast;
|
|
using ::android::ResTable_config;
|
|
using ::android::base::StringPrintf;
|
|
using ::testing::ElementsAre;
|
|
using ::testing::Eq;
|
|
using ::testing::SizeIs;
|
|
using ::testing::StrEq;
|
|
|
|
constexpr const char* kValidConfig = R"(<?xml version="1.0" encoding="utf-8" ?>
|
|
<post-process xmlns="http://schemas.android.com/tools/aapt">
|
|
<abi-groups>
|
|
<abi-group label="other" version-code-order="2">
|
|
<abi>x86</abi>
|
|
<abi>mips</abi>
|
|
</abi-group>
|
|
<abi-group label="arm" version-code-order="1">
|
|
<abi>armeabi-v7a</abi>
|
|
<abi>arm64-v8a</abi>
|
|
</abi-group>
|
|
</abi-groups>
|
|
<screen-density-groups>
|
|
<screen-density-group label="large" version-code-order="2">
|
|
<screen-density>xhdpi</screen-density>
|
|
<screen-density>xxhdpi</screen-density>
|
|
<screen-density>xxxhdpi</screen-density>
|
|
</screen-density-group>
|
|
<screen-density-group label="alldpi" version-code-order="1">
|
|
<screen-density>ldpi</screen-density>
|
|
<screen-density>mdpi</screen-density>
|
|
<screen-density>hdpi</screen-density>
|
|
<screen-density>xhdpi</screen-density>
|
|
<screen-density>xxhdpi</screen-density>
|
|
<screen-density>xxxhdpi</screen-density>
|
|
</screen-density-group>
|
|
</screen-density-groups>
|
|
<locale-groups>
|
|
<locale-group label="europe" version-code-order="1">
|
|
<locale>en</locale>
|
|
<locale>es</locale>
|
|
<locale>fr</locale>
|
|
<locale>de</locale>
|
|
</locale-group>
|
|
<locale-group label="north-america" version-code-order="2">
|
|
<locale>en</locale>
|
|
<locale>es-rMX</locale>
|
|
<locale>fr-rCA</locale>
|
|
</locale-group>
|
|
<locale-group label="all" version-code-order="-1">
|
|
<locale />
|
|
</locale-group>
|
|
</locale-groups>
|
|
<android-sdks>
|
|
<android-sdk
|
|
label="v19"
|
|
minSdkVersion="19"
|
|
targetSdkVersion="24"
|
|
maxSdkVersion="25">
|
|
<manifest>
|
|
<!--- manifest additions here XSLT? TODO -->
|
|
</manifest>
|
|
</android-sdk>
|
|
</android-sdks>
|
|
<gl-texture-groups>
|
|
<gl-texture-group label="dxt1" version-code-order="2">
|
|
<gl-texture name="GL_EXT_texture_compression_dxt1">
|
|
<texture-path>assets/dxt1/*</texture-path>
|
|
</gl-texture>
|
|
</gl-texture-group>
|
|
</gl-texture-groups>
|
|
<device-feature-groups>
|
|
<device-feature-group label="low-latency" version-code-order="2">
|
|
<supports-feature>android.hardware.audio.low_latency</supports-feature>
|
|
</device-feature-group>
|
|
</device-feature-groups>
|
|
<artifacts>
|
|
<artifact-format>
|
|
${base}.${abi}.${screen-density}.${locale}.${sdk}.${gl}.${feature}.release
|
|
</artifact-format>
|
|
<artifact
|
|
name="art1"
|
|
abi-group="arm"
|
|
screen-density-group="large"
|
|
locale-group="europe"
|
|
android-sdk="v19"
|
|
gl-texture-group="dxt1"
|
|
device-feature-group="low-latency"/>
|
|
<artifact
|
|
name="art2"
|
|
abi-group="other"
|
|
screen-density-group="alldpi"
|
|
locale-group="north-america"
|
|
android-sdk="v19"
|
|
gl-texture-group="dxt1"
|
|
device-feature-group="low-latency"/>
|
|
</artifacts>
|
|
</post-process>
|
|
)";
|
|
|
|
class ConfigurationParserTest : public ConfigurationParser, public ::testing::Test {
|
|
public:
|
|
ConfigurationParserTest() : ConfigurationParser("", "config.xml") {
|
|
}
|
|
|
|
protected:
|
|
StdErrDiagnostics diag_;
|
|
};
|
|
|
|
TEST_F(ConfigurationParserTest, ForPath_NoFile) {
|
|
auto result = ConfigurationParser::ForPath("./does_not_exist.xml");
|
|
EXPECT_FALSE(result);
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, ExtractConfiguration) {
|
|
Maybe<PostProcessingConfiguration> maybe_config =
|
|
ExtractConfiguration(kValidConfig, "fake.xml", &diag_);
|
|
|
|
PostProcessingConfiguration config = maybe_config.value();
|
|
|
|
auto& arm = config.abi_groups["arm"];
|
|
auto& other = config.abi_groups["other"];
|
|
EXPECT_EQ(arm.order, 1);
|
|
EXPECT_EQ(other.order, 2);
|
|
|
|
auto& large = config.screen_density_groups["large"];
|
|
auto& alldpi = config.screen_density_groups["alldpi"];
|
|
EXPECT_EQ(large.order, 2);
|
|
EXPECT_EQ(alldpi.order, 1);
|
|
|
|
auto& north_america = config.locale_groups["north-america"];
|
|
auto& europe = config.locale_groups["europe"];
|
|
auto& all = config.locale_groups["all"];
|
|
// Checked in reverse to make sure access order does not matter.
|
|
EXPECT_EQ(north_america.order, 2);
|
|
EXPECT_EQ(europe.order, 1);
|
|
EXPECT_EQ(all.order, -1);
|
|
EXPECT_EQ(3ul, config.locale_groups.size());
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, ValidateFile) {
|
|
auto parser = ConfigurationParser::ForContents(kValidConfig, "conf.xml").WithDiagnostics(&diag_);
|
|
auto result = parser.Parse("test.apk");
|
|
ASSERT_TRUE(result);
|
|
const std::vector<OutputArtifact>& value = result.value();
|
|
EXPECT_THAT(value, SizeIs(2ul));
|
|
|
|
const OutputArtifact& a1 = value[0];
|
|
EXPECT_EQ(a1.name, "art1.apk");
|
|
EXPECT_EQ(a1.version, 1);
|
|
EXPECT_THAT(a1.abis, ElementsAre(Abi::kArmV7a, Abi::kArm64V8a));
|
|
EXPECT_THAT(a1.screen_densities,
|
|
ElementsAre(test::ParseConfigOrDie("xhdpi").CopyWithoutSdkVersion(),
|
|
test::ParseConfigOrDie("xxhdpi").CopyWithoutSdkVersion(),
|
|
test::ParseConfigOrDie("xxxhdpi").CopyWithoutSdkVersion()));
|
|
EXPECT_THAT(a1.locales, ElementsAre(test::ParseConfigOrDie("en"), test::ParseConfigOrDie("es"),
|
|
test::ParseConfigOrDie("fr"), test::ParseConfigOrDie("de")));
|
|
ASSERT_TRUE(a1.android_sdk);
|
|
ASSERT_TRUE(a1.android_sdk.value().min_sdk_version);
|
|
EXPECT_EQ(a1.android_sdk.value().min_sdk_version, 19L);
|
|
EXPECT_THAT(a1.textures, SizeIs(1ul));
|
|
EXPECT_THAT(a1.features, SizeIs(1ul));
|
|
|
|
const OutputArtifact& a2 = value[1];
|
|
EXPECT_EQ(a2.name, "art2.apk");
|
|
EXPECT_EQ(a2.version, 2);
|
|
EXPECT_THAT(a2.abis, ElementsAre(Abi::kX86, Abi::kMips));
|
|
EXPECT_THAT(a2.screen_densities,
|
|
ElementsAre(test::ParseConfigOrDie("ldpi").CopyWithoutSdkVersion(),
|
|
test::ParseConfigOrDie("mdpi").CopyWithoutSdkVersion(),
|
|
test::ParseConfigOrDie("hdpi").CopyWithoutSdkVersion(),
|
|
test::ParseConfigOrDie("xhdpi").CopyWithoutSdkVersion(),
|
|
test::ParseConfigOrDie("xxhdpi").CopyWithoutSdkVersion(),
|
|
test::ParseConfigOrDie("xxxhdpi").CopyWithoutSdkVersion()));
|
|
EXPECT_THAT(a2.locales,
|
|
ElementsAre(test::ParseConfigOrDie("en"), test::ParseConfigOrDie("es-rMX"),
|
|
test::ParseConfigOrDie("fr-rCA")));
|
|
ASSERT_TRUE(a2.android_sdk);
|
|
ASSERT_TRUE(a2.android_sdk.value().min_sdk_version);
|
|
EXPECT_EQ(a2.android_sdk.value().min_sdk_version, 19L);
|
|
EXPECT_THAT(a2.textures, SizeIs(1ul));
|
|
EXPECT_THAT(a2.features, SizeIs(1ul));
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, ConfiguredArtifactOrdering) {
|
|
// Create a base builder with the configuration groups but no artifacts to allow it to be copied.
|
|
test::PostProcessingConfigurationBuilder base_builder = test::PostProcessingConfigurationBuilder()
|
|
.AddAbiGroup("arm")
|
|
.AddAbiGroup("arm64")
|
|
.AddAndroidSdk("v23", 23)
|
|
.AddAndroidSdk("v19", 19);
|
|
|
|
{
|
|
// Test version ordering.
|
|
ConfiguredArtifact v23;
|
|
v23.android_sdk = {"v23"};
|
|
ConfiguredArtifact v19;
|
|
v19.android_sdk = {"v19"};
|
|
|
|
test::PostProcessingConfigurationBuilder builder = base_builder;
|
|
PostProcessingConfiguration config = builder.AddArtifact(v23).AddArtifact(v19).Build();
|
|
|
|
config.SortArtifacts();
|
|
ASSERT_THAT(config.artifacts, SizeIs(2));
|
|
EXPECT_THAT(config.artifacts[0], Eq(v19));
|
|
EXPECT_THAT(config.artifacts[1], Eq(v23));
|
|
}
|
|
|
|
{
|
|
// Test ABI ordering.
|
|
ConfiguredArtifact arm;
|
|
arm.android_sdk = {"v19"};
|
|
arm.abi_group = {"arm"};
|
|
ConfiguredArtifact arm64;
|
|
arm64.android_sdk = {"v19"};
|
|
arm64.abi_group = {"arm64"};
|
|
|
|
test::PostProcessingConfigurationBuilder builder = base_builder;
|
|
PostProcessingConfiguration config = builder.AddArtifact(arm64).AddArtifact(arm).Build();
|
|
|
|
config.SortArtifacts();
|
|
ASSERT_THAT(config.artifacts, SizeIs(2));
|
|
EXPECT_THAT(config.artifacts[0], Eq(arm));
|
|
EXPECT_THAT(config.artifacts[1], Eq(arm64));
|
|
}
|
|
|
|
{
|
|
// Test Android SDK has precedence over ABI.
|
|
ConfiguredArtifact arm;
|
|
arm.android_sdk = {"v23"};
|
|
arm.abi_group = {"arm"};
|
|
ConfiguredArtifact arm64;
|
|
arm64.android_sdk = {"v19"};
|
|
arm64.abi_group = {"arm64"};
|
|
|
|
test::PostProcessingConfigurationBuilder builder = base_builder;
|
|
PostProcessingConfiguration config = builder.AddArtifact(arm64).AddArtifact(arm).Build();
|
|
|
|
config.SortArtifacts();
|
|
ASSERT_THAT(config.artifacts, SizeIs(2));
|
|
EXPECT_THAT(config.artifacts[0], Eq(arm64));
|
|
EXPECT_THAT(config.artifacts[1], Eq(arm));
|
|
}
|
|
|
|
{
|
|
// Test version is better than ABI.
|
|
ConfiguredArtifact arm;
|
|
arm.abi_group = {"arm"};
|
|
ConfiguredArtifact v19;
|
|
v19.android_sdk = {"v19"};
|
|
|
|
test::PostProcessingConfigurationBuilder builder = base_builder;
|
|
PostProcessingConfiguration config = builder.AddArtifact(v19).AddArtifact(arm).Build();
|
|
|
|
config.SortArtifacts();
|
|
ASSERT_THAT(config.artifacts, SizeIs(2));
|
|
EXPECT_THAT(config.artifacts[0], Eq(arm));
|
|
EXPECT_THAT(config.artifacts[1], Eq(v19));
|
|
}
|
|
|
|
{
|
|
// Test version is sorted higher than no version.
|
|
ConfiguredArtifact arm;
|
|
arm.abi_group = {"arm"};
|
|
ConfiguredArtifact v19;
|
|
v19.abi_group = {"arm"};
|
|
v19.android_sdk = {"v19"};
|
|
|
|
test::PostProcessingConfigurationBuilder builder = base_builder;
|
|
PostProcessingConfiguration config = builder.AddArtifact(v19).AddArtifact(arm).Build();
|
|
|
|
config.SortArtifacts();
|
|
ASSERT_THAT(config.artifacts, SizeIs(2));
|
|
EXPECT_THAT(config.artifacts[0], Eq(arm));
|
|
EXPECT_THAT(config.artifacts[1], Eq(v19));
|
|
}
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, InvalidNamespace) {
|
|
constexpr const char* invalid_ns = R"(<?xml version="1.0" encoding="utf-8" ?>
|
|
<post-process xmlns="http://schemas.android.com/tools/another-unknown-tool" />)";
|
|
|
|
auto result = ConfigurationParser::ForContents(invalid_ns, "config.xml").Parse("test.apk");
|
|
ASSERT_FALSE(result);
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, ArtifactAction) {
|
|
PostProcessingConfiguration config;
|
|
const auto doc = test::BuildXmlDom(R"xml(
|
|
<artifact
|
|
abi-group="arm"
|
|
screen-density-group="large"
|
|
locale-group="europe"
|
|
android-sdk="v19"
|
|
gl-texture-group="dxt1"
|
|
device-feature-group="low-latency"/>)xml");
|
|
|
|
ASSERT_TRUE(ArtifactTagHandler(&config, NodeCast<Element>(doc->root.get()), &diag_));
|
|
|
|
EXPECT_THAT(config.artifacts, SizeIs(1ul));
|
|
|
|
auto& artifact = config.artifacts.back();
|
|
EXPECT_FALSE(artifact.name); // TODO: make this fail.
|
|
EXPECT_EQ("arm", artifact.abi_group.value());
|
|
EXPECT_EQ("large", artifact.screen_density_group.value());
|
|
EXPECT_EQ("europe", artifact.locale_group.value());
|
|
EXPECT_EQ("v19", artifact.android_sdk.value());
|
|
EXPECT_EQ("dxt1", artifact.gl_texture_group.value());
|
|
EXPECT_EQ("low-latency", artifact.device_feature_group.value());
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, ArtifactFormatAction) {
|
|
const auto doc = test::BuildXmlDom(R"xml(
|
|
<artifact-format>
|
|
${base}.${abi}.${screen-density}.${locale}.${sdk}.${gl}.${feature}.release
|
|
</artifact-format>)xml");
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = ArtifactFormatTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_TRUE(ok);
|
|
ASSERT_TRUE(config.artifact_format);
|
|
EXPECT_EQ(
|
|
"${base}.${abi}.${screen-density}.${locale}.${sdk}.${gl}.${feature}.release",
|
|
static_cast<std::string>(config.artifact_format.value())
|
|
);
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, AbiGroupAction) {
|
|
static constexpr const char* xml = R"xml(
|
|
<abi-group label="arm" version-code-order="2">
|
|
<!-- First comment. -->
|
|
<abi>
|
|
armeabi-v7a
|
|
</abi>
|
|
<!-- Another comment. -->
|
|
<abi>arm64-v8a</abi>
|
|
</abi-group>)xml";
|
|
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = AbiGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_TRUE(ok);
|
|
|
|
EXPECT_THAT(config.abi_groups, SizeIs(1ul));
|
|
ASSERT_EQ(1u, config.abi_groups.count("arm"));
|
|
|
|
auto& out = config.abi_groups["arm"].entry;
|
|
ASSERT_THAT(out, ElementsAre(Abi::kArmV7a, Abi::kArm64V8a));
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, AbiGroupAction_EmptyGroup) {
|
|
static constexpr const char* xml =
|
|
R"xml(<abi-group label="arm64-v8a" version-code-order="3"/>)xml";
|
|
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = AbiGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_TRUE(ok);
|
|
|
|
EXPECT_THAT(config.abi_groups, SizeIs(1ul));
|
|
ASSERT_EQ(1u, config.abi_groups.count("arm64-v8a"));
|
|
|
|
auto& out = config.abi_groups["arm64-v8a"];
|
|
ASSERT_THAT(out.entry, ElementsAre(Abi::kArm64V8a));
|
|
EXPECT_EQ(3, out.order);
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, AbiGroupAction_EmptyGroup_NoOrder) {
|
|
static constexpr const char* xml = R"xml(<abi-group label="arm64-v8a"/>)xml";
|
|
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = AbiGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_FALSE(ok);
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, AbiGroupAction_InvalidEmptyGroup) {
|
|
static constexpr const char* xml = R"xml(<abi-group label="arm" order="2"/>)xml";
|
|
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = AbiGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_FALSE(ok);
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, ScreenDensityGroupAction) {
|
|
static constexpr const char* xml = R"xml(
|
|
<screen-density-group label="large" version-code-order="2">
|
|
<screen-density>xhdpi</screen-density>
|
|
<screen-density>
|
|
xxhdpi
|
|
</screen-density>
|
|
<screen-density>xxxhdpi</screen-density>
|
|
</screen-density-group>)xml";
|
|
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = ScreenDensityGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_TRUE(ok);
|
|
|
|
EXPECT_THAT(config.screen_density_groups, SizeIs(1ul));
|
|
ASSERT_EQ(1u, config.screen_density_groups.count("large"));
|
|
|
|
ConfigDescription xhdpi;
|
|
xhdpi.density = ResTable_config::DENSITY_XHIGH;
|
|
ConfigDescription xxhdpi;
|
|
xxhdpi.density = ResTable_config::DENSITY_XXHIGH;
|
|
ConfigDescription xxxhdpi;
|
|
xxxhdpi.density = ResTable_config::DENSITY_XXXHIGH;
|
|
|
|
auto& out = config.screen_density_groups["large"].entry;
|
|
ASSERT_THAT(out, ElementsAre(xhdpi, xxhdpi, xxxhdpi));
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, ScreenDensityGroupAction_EmtpyGroup) {
|
|
static constexpr const char* xml =
|
|
R"xml(<screen-density-group label="xhdpi" version-code-order="4"/>)xml";
|
|
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = ScreenDensityGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_TRUE(ok);
|
|
|
|
EXPECT_THAT(config.screen_density_groups, SizeIs(1ul));
|
|
ASSERT_EQ(1u, config.screen_density_groups.count("xhdpi"));
|
|
|
|
ConfigDescription xhdpi;
|
|
xhdpi.density = ResTable_config::DENSITY_XHIGH;
|
|
|
|
auto& out = config.screen_density_groups["xhdpi"];
|
|
EXPECT_THAT(out.entry, ElementsAre(xhdpi));
|
|
EXPECT_EQ(4, out.order);
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, ScreenDensityGroupAction_EmtpyGroup_NoVersion) {
|
|
static constexpr const char* xml = R"xml(<screen-density-group label="xhdpi"/>)xml";
|
|
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = ScreenDensityGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_FALSE(ok);
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, ScreenDensityGroupAction_InvalidEmtpyGroup) {
|
|
static constexpr const char* xml = R"xml(<screen-density-group label="really-big-screen"/>)xml";
|
|
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = ScreenDensityGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_FALSE(ok);
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, LocaleGroupAction) {
|
|
static constexpr const char* xml = R"xml(
|
|
<locale-group label="europe" version-code-order="2">
|
|
<locale>en</locale>
|
|
<locale>es</locale>
|
|
<locale>fr</locale>
|
|
<locale>de</locale>
|
|
</locale-group>)xml";
|
|
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = LocaleGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_TRUE(ok);
|
|
|
|
ASSERT_EQ(1ul, config.locale_groups.size());
|
|
ASSERT_EQ(1u, config.locale_groups.count("europe"));
|
|
|
|
const auto& out = config.locale_groups["europe"].entry;
|
|
|
|
ConfigDescription en = test::ParseConfigOrDie("en");
|
|
ConfigDescription es = test::ParseConfigOrDie("es");
|
|
ConfigDescription fr = test::ParseConfigOrDie("fr");
|
|
ConfigDescription de = test::ParseConfigOrDie("de");
|
|
|
|
ASSERT_THAT(out, ElementsAre(en, es, fr, de));
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, LocaleGroupAction_EmtpyGroup) {
|
|
static constexpr const char* xml = R"xml(<locale-group label="en" version-code-order="6"/>)xml";
|
|
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = LocaleGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_TRUE(ok);
|
|
|
|
ASSERT_EQ(1ul, config.locale_groups.size());
|
|
ASSERT_EQ(1u, config.locale_groups.count("en"));
|
|
|
|
const auto& out = config.locale_groups["en"];
|
|
|
|
ConfigDescription en = test::ParseConfigOrDie("en");
|
|
|
|
EXPECT_THAT(out.entry, ElementsAre(en));
|
|
EXPECT_EQ(6, out.order);
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, LocaleGroupAction_EmtpyGroup_NoOrder) {
|
|
static constexpr const char* xml = R"xml(<locale-group label="en"/>)xml";
|
|
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = LocaleGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_FALSE(ok);
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, LocaleGroupAction_InvalidEmtpyGroup) {
|
|
static constexpr const char* xml = R"xml(<locale-group label="arm64"/>)xml";
|
|
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = LocaleGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_FALSE(ok);
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, AndroidSdkGroupAction) {
|
|
static constexpr const char* xml = R"xml(
|
|
<android-sdk label="v19"
|
|
minSdkVersion="19"
|
|
targetSdkVersion="24"
|
|
maxSdkVersion="25">
|
|
<manifest>
|
|
<!--- manifest additions here XSLT? TODO -->
|
|
</manifest>
|
|
</android-sdk>)xml";
|
|
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = AndroidSdkTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_TRUE(ok);
|
|
|
|
ASSERT_EQ(1ul, config.android_sdks.size());
|
|
ASSERT_EQ(1u, config.android_sdks.count("v19"));
|
|
|
|
auto& out = config.android_sdks["v19"];
|
|
|
|
AndroidSdk sdk;
|
|
sdk.min_sdk_version = 19;
|
|
sdk.target_sdk_version = 24;
|
|
sdk.max_sdk_version = 25;
|
|
sdk.manifest = AndroidManifest();
|
|
|
|
ASSERT_EQ(sdk, out);
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_SingleVersion) {
|
|
{
|
|
const char* xml = "<android-sdk label='v19' minSdkVersion='19'></android-sdk>";
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = AndroidSdkTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_TRUE(ok);
|
|
|
|
ASSERT_EQ(1ul, config.android_sdks.size());
|
|
ASSERT_EQ(1u, config.android_sdks.count("v19"));
|
|
|
|
auto& out = config.android_sdks["v19"];
|
|
EXPECT_EQ(19, out.min_sdk_version);
|
|
EXPECT_FALSE(out.max_sdk_version);
|
|
EXPECT_FALSE(out.target_sdk_version);
|
|
}
|
|
|
|
{
|
|
const char* xml =
|
|
"<android-sdk label='v19' minSdkVersion='19' maxSdkVersion='19'></android-sdk>";
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = AndroidSdkTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_TRUE(ok);
|
|
|
|
ASSERT_EQ(1ul, config.android_sdks.size());
|
|
ASSERT_EQ(1u, config.android_sdks.count("v19"));
|
|
|
|
auto& out = config.android_sdks["v19"];
|
|
EXPECT_EQ(19, out.max_sdk_version.value());
|
|
EXPECT_EQ(19, out.min_sdk_version);
|
|
EXPECT_FALSE(out.target_sdk_version);
|
|
}
|
|
|
|
{
|
|
const char* xml =
|
|
"<android-sdk label='v19' minSdkVersion='19' targetSdkVersion='19'></android-sdk>";
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = AndroidSdkTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_TRUE(ok);
|
|
|
|
ASSERT_EQ(1ul, config.android_sdks.size());
|
|
ASSERT_EQ(1u, config.android_sdks.count("v19"));
|
|
|
|
auto& out = config.android_sdks["v19"];
|
|
EXPECT_EQ(19, out.target_sdk_version.value());
|
|
EXPECT_EQ(19, out.min_sdk_version);
|
|
EXPECT_FALSE(out.max_sdk_version);
|
|
}
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_InvalidVersion) {
|
|
static constexpr const char* xml = R"xml(
|
|
<android-sdk
|
|
label="v19"
|
|
minSdkVersion="v19"
|
|
targetSdkVersion="v24"
|
|
maxSdkVersion="v25">
|
|
<manifest>
|
|
<!--- manifest additions here XSLT? TODO -->
|
|
</manifest>
|
|
</android-sdk>)xml";
|
|
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = AndroidSdkTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_FALSE(ok);
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_NonNumeric) {
|
|
auto doc = test::BuildXmlDom(R"xml(
|
|
<android-sdk
|
|
label="Q"
|
|
minSdkVersion="25"
|
|
targetSdkVersion="Q"
|
|
maxSdkVersion="Q">
|
|
</android-sdk>)xml");
|
|
|
|
PostProcessingConfiguration config;
|
|
ASSERT_TRUE(AndroidSdkTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_));
|
|
ASSERT_EQ(1ul, config.android_sdks.size());
|
|
ASSERT_EQ(1u, config.android_sdks.count("Q"));
|
|
|
|
AndroidSdk sdk;
|
|
sdk.min_sdk_version = 25;
|
|
sdk.target_sdk_version = 10000;
|
|
sdk.max_sdk_version = 10000;
|
|
ASSERT_EQ(sdk, config.android_sdks["Q"]);
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, GlTextureGroupAction) {
|
|
static constexpr const char* xml = R"xml(
|
|
<gl-texture-group label="dxt1" version-code-order="2">
|
|
<gl-texture name="GL_EXT_texture_compression_dxt1">
|
|
<texture-path>assets/dxt1/main/*</texture-path>
|
|
<texture-path>
|
|
assets/dxt1/test/*
|
|
</texture-path>
|
|
</gl-texture>
|
|
</gl-texture-group>)xml";
|
|
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = GlTextureGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_TRUE(ok);
|
|
|
|
EXPECT_THAT(config.gl_texture_groups, SizeIs(1ul));
|
|
ASSERT_EQ(1u, config.gl_texture_groups.count("dxt1"));
|
|
|
|
auto& out = config.gl_texture_groups["dxt1"].entry;
|
|
|
|
GlTexture texture{
|
|
std::string("GL_EXT_texture_compression_dxt1"),
|
|
{"assets/dxt1/main/*", "assets/dxt1/test/*"}
|
|
};
|
|
|
|
ASSERT_EQ(1ul, out.size());
|
|
ASSERT_EQ(texture, out[0]);
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, DeviceFeatureGroupAction) {
|
|
static constexpr const char* xml = R"xml(
|
|
<device-feature-group label="low-latency" version-code-order="2">
|
|
<supports-feature>android.hardware.audio.low_latency</supports-feature>
|
|
<supports-feature>
|
|
android.hardware.audio.pro
|
|
</supports-feature>
|
|
</device-feature-group>)xml";
|
|
|
|
auto doc = test::BuildXmlDom(xml);
|
|
|
|
PostProcessingConfiguration config;
|
|
bool ok = DeviceFeatureGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
|
|
ASSERT_TRUE(ok);
|
|
|
|
EXPECT_THAT(config.device_feature_groups, SizeIs(1ul));
|
|
ASSERT_EQ(1u, config.device_feature_groups.count("low-latency"));
|
|
|
|
auto& out = config.device_feature_groups["low-latency"].entry;
|
|
|
|
DeviceFeature low_latency = "android.hardware.audio.low_latency";
|
|
DeviceFeature pro = "android.hardware.audio.pro";
|
|
ASSERT_THAT(out, ElementsAre(low_latency, pro));
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, Group_Valid) {
|
|
Group<int32_t> group;
|
|
group["item1"].order = 1;
|
|
group["item2"].order = 2;
|
|
group["item3"].order = 3;
|
|
group["item4"].order = 4;
|
|
group["item5"].order = 5;
|
|
group["item6"].order = 6;
|
|
|
|
EXPECT_TRUE(IsGroupValid(group, "test", &diag_));
|
|
}
|
|
|
|
TEST_F(ConfigurationParserTest, Group_OverlappingOrder) {
|
|
Group<int32_t> group;
|
|
group["item1"].order = 1;
|
|
group["item2"].order = 2;
|
|
group["item3"].order = 3;
|
|
group["item4"].order = 2;
|
|
group["item5"].order = 5;
|
|
group["item6"].order = 1;
|
|
|
|
EXPECT_FALSE(IsGroupValid(group, "test", &diag_));
|
|
}
|
|
|
|
// Artifact name parser test cases.
|
|
|
|
TEST(ArtifactTest, Simple) {
|
|
StdErrDiagnostics diag;
|
|
ConfiguredArtifact x86;
|
|
x86.abi_group = {"x86"};
|
|
|
|
auto x86_result = x86.ToArtifactName("something.${abi}.apk", "", &diag);
|
|
ASSERT_TRUE(x86_result);
|
|
EXPECT_EQ(x86_result.value(), "something.x86.apk");
|
|
|
|
ConfiguredArtifact arm;
|
|
arm.abi_group = {"armeabi-v7a"};
|
|
|
|
{
|
|
auto arm_result = arm.ToArtifactName("app.${abi}.apk", "", &diag);
|
|
ASSERT_TRUE(arm_result);
|
|
EXPECT_EQ(arm_result.value(), "app.armeabi-v7a.apk");
|
|
}
|
|
|
|
{
|
|
auto arm_result = arm.ToArtifactName("app.${abi}.apk", "different_name.apk", &diag);
|
|
ASSERT_TRUE(arm_result);
|
|
EXPECT_EQ(arm_result.value(), "app.armeabi-v7a.apk");
|
|
}
|
|
|
|
{
|
|
auto arm_result = arm.ToArtifactName("${basename}.${abi}.apk", "app.apk", &diag);
|
|
ASSERT_TRUE(arm_result);
|
|
EXPECT_EQ(arm_result.value(), "app.armeabi-v7a.apk");
|
|
}
|
|
|
|
{
|
|
auto arm_result = arm.ToArtifactName("app.${abi}.${ext}", "app.apk", &diag);
|
|
ASSERT_TRUE(arm_result);
|
|
EXPECT_EQ(arm_result.value(), "app.armeabi-v7a.apk");
|
|
}
|
|
}
|
|
|
|
TEST(ArtifactTest, Complex) {
|
|
StdErrDiagnostics diag;
|
|
ConfiguredArtifact artifact;
|
|
artifact.abi_group = {"mips64"};
|
|
artifact.screen_density_group = {"ldpi"};
|
|
artifact.device_feature_group = {"df1"};
|
|
artifact.gl_texture_group = {"glx1"};
|
|
artifact.locale_group = {"en-AU"};
|
|
artifact.android_sdk = {"v26"};
|
|
|
|
{
|
|
auto result = artifact.ToArtifactName(
|
|
"app.${density}_${locale}_${feature}_${gl}.${sdk}.${abi}.apk", "", &diag);
|
|
ASSERT_TRUE(result);
|
|
EXPECT_EQ(result.value(), "app.ldpi_en-AU_df1_glx1.v26.mips64.apk");
|
|
}
|
|
|
|
{
|
|
auto result = artifact.ToArtifactName(
|
|
"app.${density}_${locale}_${feature}_${gl}.${sdk}.${abi}.apk", "app.apk", &diag);
|
|
ASSERT_TRUE(result);
|
|
EXPECT_EQ(result.value(), "app.ldpi_en-AU_df1_glx1.v26.mips64.apk");
|
|
}
|
|
|
|
{
|
|
auto result = artifact.ToArtifactName(
|
|
"${basename}.${density}_${locale}_${feature}_${gl}.${sdk}.${abi}.apk", "app.apk", &diag);
|
|
ASSERT_TRUE(result);
|
|
EXPECT_EQ(result.value(), "app.ldpi_en-AU_df1_glx1.v26.mips64.apk");
|
|
}
|
|
|
|
{
|
|
auto result = artifact.ToArtifactName(
|
|
"app.${density}_${locale}_${feature}_${gl}.${sdk}.${abi}.${ext}", "app.apk", &diag);
|
|
ASSERT_TRUE(result);
|
|
EXPECT_EQ(result.value(), "app.ldpi_en-AU_df1_glx1.v26.mips64.apk");
|
|
}
|
|
|
|
{
|
|
auto result = artifact.ToArtifactName(
|
|
"${basename}.${density}_${locale}_${feature}_${gl}.${sdk}.${abi}", "app.apk", &diag);
|
|
ASSERT_TRUE(result);
|
|
EXPECT_EQ(result.value(), "app.ldpi_en-AU_df1_glx1.v26.mips64.apk");
|
|
}
|
|
}
|
|
|
|
TEST(ArtifactTest, Missing) {
|
|
StdErrDiagnostics diag;
|
|
ConfiguredArtifact x86;
|
|
x86.abi_group = {"x86"};
|
|
|
|
EXPECT_FALSE(x86.ToArtifactName("something.${density}.apk", "", &diag));
|
|
EXPECT_FALSE(x86.ToArtifactName("something.apk", "", &diag));
|
|
EXPECT_FALSE(x86.ToArtifactName("something.${density}.apk", "something.apk", &diag));
|
|
EXPECT_FALSE(x86.ToArtifactName("something.apk", "something.apk", &diag));
|
|
}
|
|
|
|
TEST(ArtifactTest, Empty) {
|
|
StdErrDiagnostics diag;
|
|
ConfiguredArtifact artifact;
|
|
|
|
EXPECT_FALSE(artifact.ToArtifactName("something.${density}.apk", "", &diag));
|
|
EXPECT_TRUE(artifact.ToArtifactName("something.apk", "", &diag));
|
|
EXPECT_FALSE(artifact.ToArtifactName("something.${density}.apk", "something.apk", &diag));
|
|
EXPECT_TRUE(artifact.ToArtifactName("something.apk", "something.apk", &diag));
|
|
}
|
|
|
|
TEST(ArtifactTest, Repeated) {
|
|
StdErrDiagnostics diag;
|
|
ConfiguredArtifact artifact;
|
|
artifact.screen_density_group = {"mdpi"};
|
|
|
|
ASSERT_TRUE(artifact.ToArtifactName("something.${density}.apk", "", &diag));
|
|
EXPECT_FALSE(artifact.ToArtifactName("something.${density}.${density}.apk", "", &diag));
|
|
ASSERT_TRUE(artifact.ToArtifactName("something.${density}.apk", "something.apk", &diag));
|
|
}
|
|
|
|
TEST(ArtifactTest, Nesting) {
|
|
StdErrDiagnostics diag;
|
|
ConfiguredArtifact x86;
|
|
x86.abi_group = {"x86"};
|
|
|
|
EXPECT_FALSE(x86.ToArtifactName("something.${abi${density}}.apk", "", &diag));
|
|
|
|
const Maybe<std::string>& name = x86.ToArtifactName("something.${abi${abi}}.apk", "", &diag);
|
|
ASSERT_TRUE(name);
|
|
EXPECT_EQ(name.value(), "something.${abix86}.apk");
|
|
}
|
|
|
|
TEST(ArtifactTest, Recursive) {
|
|
StdErrDiagnostics diag;
|
|
ConfiguredArtifact artifact;
|
|
artifact.device_feature_group = {"${gl}"};
|
|
artifact.gl_texture_group = {"glx1"};
|
|
|
|
EXPECT_FALSE(artifact.ToArtifactName("app.${feature}.${gl}.apk", "", &diag));
|
|
|
|
artifact.device_feature_group = {"df1"};
|
|
artifact.gl_texture_group = {"${feature}"};
|
|
{
|
|
const auto& result = artifact.ToArtifactName("app.${feature}.${gl}.apk", "", &diag);
|
|
ASSERT_TRUE(result);
|
|
EXPECT_EQ(result.value(), "app.df1.${feature}.apk");
|
|
}
|
|
|
|
// This is an invalid case, but should be the only possible case due to the ordering of
|
|
// replacement.
|
|
artifact.device_feature_group = {"${gl}"};
|
|
artifact.gl_texture_group = {"glx1"};
|
|
{
|
|
const auto& result = artifact.ToArtifactName("app.${feature}.apk", "", &diag);
|
|
ASSERT_TRUE(result);
|
|
EXPECT_EQ(result.value(), "app.glx1.apk");
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace handler
|
|
} // namespace configuration
|
|
} // namespace aapt
|