Home | History | Annotate | Download | only in configuration
      1 /*
      2  * Copyright (C) 2017 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 "configuration/ConfigurationParser.h"
     18 
     19 #include <string>
     20 
     21 #include "androidfw/ResourceTypes.h"
     22 
     23 #include "test/Test.h"
     24 #include "xml/XmlDom.h"
     25 
     26 namespace aapt {
     27 namespace {
     28 
     29 using ::android::ResTable_config;
     30 using configuration::Abi;
     31 using configuration::AndroidSdk;
     32 using configuration::Artifact;
     33 using configuration::PostProcessingConfiguration;
     34 using configuration::DeviceFeature;
     35 using configuration::GlTexture;
     36 using configuration::Locale;
     37 using configuration::AndroidManifest;
     38 using ::testing::ElementsAre;
     39 using xml::Element;
     40 using xml::NodeCast;
     41 
     42 constexpr const char* kValidConfig = R"(<?xml version="1.0" encoding="utf-8" ?>
     43 <post-process xmlns="http://schemas.android.com/tools/aapt">
     44   <groups>
     45     <abi-group label="arm">
     46       <abi>armeabi-v7a</abi>
     47       <abi>arm64-v8a</abi>
     48     </abi-group>
     49     <abi-group label="other">
     50       <abi>x86</abi>
     51       <abi>mips</abi>
     52     </abi-group>
     53     <screen-density-group label="large">
     54       <screen-density>xhdpi</screen-density>
     55       <screen-density>xxhdpi</screen-density>
     56       <screen-density>xxxhdpi</screen-density>
     57     </screen-density-group>
     58     <screen-density-group label="alldpi">
     59       <screen-density>ldpi</screen-density>
     60       <screen-density>mdpi</screen-density>
     61       <screen-density>hdpi</screen-density>
     62       <screen-density>xhdpi</screen-density>
     63       <screen-density>xxhdpi</screen-density>
     64       <screen-density>xxxhdpi</screen-density>
     65     </screen-density-group>
     66     <locale-group label="europe">
     67       <locale lang="en"/>
     68       <locale lang="es"/>
     69       <locale lang="fr"/>
     70       <locale lang="de"/>
     71     </locale-group>
     72     <locale-group label="north-america">
     73       <locale lang="en"/>
     74       <locale lang="es" region="MX"/>
     75       <locale lang="fr" region="CA"/>
     76     </locale-group>
     77     <locale-group label="all">
     78       <locale/>
     79     </locale-group>
     80     <android-sdk-group label="19">
     81       <android-sdk
     82           minSdkVersion="19"
     83           targetSdkVersion="24"
     84           maxSdkVersion="25">
     85         <manifest>
     86           <!--- manifest additions here XSLT? TODO -->
     87         </manifest>
     88       </android-sdk>
     89     </android-sdk-group>
     90     <gl-texture-group label="dxt1">
     91       <gl-texture name="GL_EXT_texture_compression_dxt1">
     92         <texture-path>assets/dxt1/*</texture-path>
     93       </gl-texture>
     94     </gl-texture-group>
     95     <device-feature-group label="low-latency">
     96       <supports-feature>android.hardware.audio.low_latency</supports-feature>
     97     </device-feature-group>
     98   </groups>
     99   <artifacts>
    100     <artifact-format>
    101       ${base}.${abi}.${screen-density}.${locale}.${sdk}.${gl}.${feature}.release
    102     </artifact-format>
    103     <artifact
    104         name="art1"
    105         abi-group="arm"
    106         screen-density-group="large"
    107         locale-group="europe"
    108         android-sdk-group="19"
    109         gl-texture-group="dxt1"
    110         device-feature-group="low-latency"/>
    111     <artifact
    112         name="art2"
    113         abi-group="other"
    114         screen-density-group="alldpi"
    115         locale-group="north-america"
    116         android-sdk-group="19"
    117         gl-texture-group="dxt1"
    118         device-feature-group="low-latency"/>
    119   </artifacts>
    120 </post-process>
    121 )";
    122 
    123 class ConfigurationParserTest : public ConfigurationParser, public ::testing::Test {
    124  public:
    125   ConfigurationParserTest() : ConfigurationParser("") {}
    126 
    127  protected:
    128   StdErrDiagnostics diag_;
    129 };
    130 
    131 TEST_F(ConfigurationParserTest, ForPath_NoFile) {
    132   auto result = ConfigurationParser::ForPath("./does_not_exist.xml");
    133   EXPECT_FALSE(result);
    134 }
    135 
    136 TEST_F(ConfigurationParserTest, ValidateFile) {
    137   auto parser = ConfigurationParser::ForContents(kValidConfig).WithDiagnostics(&diag_);
    138   auto result = parser.Parse();
    139   ASSERT_TRUE(result);
    140   PostProcessingConfiguration& value = result.value();
    141   EXPECT_EQ(2ul, value.artifacts.size());
    142   ASSERT_TRUE(value.artifact_format);
    143   EXPECT_EQ(
    144       "${base}.${abi}.${screen-density}.${locale}.${sdk}.${gl}.${feature}.release",
    145       value.artifact_format.value()
    146   );
    147 
    148   EXPECT_EQ(2ul, value.abi_groups.size());
    149   EXPECT_EQ(2ul, value.abi_groups["arm"].size());
    150   EXPECT_EQ(2ul, value.abi_groups["other"].size());
    151 
    152   EXPECT_EQ(2ul, value.screen_density_groups.size());
    153   EXPECT_EQ(3ul, value.screen_density_groups["large"].size());
    154   EXPECT_EQ(6ul, value.screen_density_groups["alldpi"].size());
    155 
    156   EXPECT_EQ(3ul, value.locale_groups.size());
    157   EXPECT_EQ(4ul, value.locale_groups["europe"].size());
    158   EXPECT_EQ(3ul, value.locale_groups["north-america"].size());
    159   EXPECT_EQ(1ul, value.locale_groups["all"].size());
    160 
    161   EXPECT_EQ(1ul, value.android_sdk_groups.size());
    162   EXPECT_EQ(1ul, value.android_sdk_groups["19"].size());
    163 
    164   EXPECT_EQ(1ul, value.gl_texture_groups.size());
    165   EXPECT_EQ(1ul, value.gl_texture_groups["dxt1"].size());
    166 
    167   EXPECT_EQ(1ul, value.device_feature_groups.size());
    168   EXPECT_EQ(1ul, value.device_feature_groups["low-latency"].size());
    169 }
    170 
    171 TEST_F(ConfigurationParserTest, InvalidNamespace) {
    172   constexpr const char* invalid_ns = R"(<?xml version="1.0" encoding="utf-8" ?>
    173   <post-process xmlns="http://schemas.android.com/tools/another-unknown-tool" />)";
    174 
    175   auto result = ConfigurationParser::ForContents(invalid_ns).Parse();
    176   ASSERT_FALSE(result);
    177 }
    178 
    179 TEST_F(ConfigurationParserTest, ArtifactAction) {
    180   static constexpr const char* xml = R"xml(
    181     <artifact
    182         abi-group="arm"
    183         screen-density-group="large"
    184         locale-group="europe"
    185         android-sdk-group="19"
    186         gl-texture-group="dxt1"
    187         device-feature-group="low-latency"/>)xml";
    188 
    189   auto doc = test::BuildXmlDom(xml);
    190 
    191   PostProcessingConfiguration config;
    192   bool ok = artifact_handler_(&config, NodeCast<Element>(doc->root.get()), &diag_);
    193   ASSERT_TRUE(ok);
    194 
    195   EXPECT_EQ(1ul, config.artifacts.size());
    196 
    197   auto& artifact = config.artifacts.front();
    198   EXPECT_EQ("", artifact.name); // TODO: make this fail.
    199   EXPECT_EQ("arm", artifact.abi_group.value());
    200   EXPECT_EQ("large", artifact.screen_density_group.value());
    201   EXPECT_EQ("europe", artifact.locale_group.value());
    202   EXPECT_EQ("19", artifact.android_sdk_group.value());
    203   EXPECT_EQ("dxt1", artifact.gl_texture_group.value());
    204   EXPECT_EQ("low-latency", artifact.device_feature_group.value());
    205 
    206   // Perform a second action to ensure we get 2 artifacts.
    207   static constexpr const char* second = R"xml(
    208     <artifact
    209         abi-group="other"
    210         screen-density-group="large"
    211         locale-group="europe"
    212         android-sdk-group="19"
    213         gl-texture-group="dxt1"
    214         device-feature-group="low-latency"/>)xml";
    215   doc = test::BuildXmlDom(second);
    216 
    217   ok = artifact_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
    218   ASSERT_TRUE(ok);
    219   EXPECT_EQ(2ul, config.artifacts.size());
    220 }
    221 
    222 TEST_F(ConfigurationParserTest, ArtifactFormatAction) {
    223   static constexpr const char* xml = R"xml(
    224     <artifact-format>
    225       ${base}.${abi}.${screen-density}.${locale}.${sdk}.${gl}.${feature}.release
    226     </artifact-format>)xml";
    227 
    228   auto doc = test::BuildXmlDom(xml);
    229 
    230   PostProcessingConfiguration config;
    231   bool ok = artifact_format_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
    232   ASSERT_TRUE(ok);
    233   ASSERT_TRUE(config.artifact_format);
    234   EXPECT_EQ(
    235       "${base}.${abi}.${screen-density}.${locale}.${sdk}.${gl}.${feature}.release",
    236       static_cast<std::string>(config.artifact_format.value())
    237   );
    238 }
    239 
    240 TEST_F(ConfigurationParserTest, AbiGroupAction) {
    241   static constexpr const char* xml = R"xml(
    242     <abi-group label="arm">
    243       <!-- First comment. -->
    244       <abi>
    245         armeabi-v7a
    246       </abi>
    247       <!-- Another comment. -->
    248       <abi>arm64-v8a</abi>
    249     </abi-group>)xml";
    250 
    251   auto doc = test::BuildXmlDom(xml);
    252 
    253   PostProcessingConfiguration config;
    254   bool ok = abi_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
    255   ASSERT_TRUE(ok);
    256 
    257   EXPECT_EQ(1ul, config.abi_groups.size());
    258   ASSERT_EQ(1u, config.abi_groups.count("arm"));
    259 
    260   auto& out = config.abi_groups["arm"];
    261   ASSERT_THAT(out, ElementsAre(Abi::kArmV7a, Abi::kArm64V8a));
    262 }
    263 
    264 TEST_F(ConfigurationParserTest, ScreenDensityGroupAction) {
    265   static constexpr const char* xml = R"xml(
    266     <screen-density-group label="large">
    267       <screen-density>xhdpi</screen-density>
    268       <screen-density>
    269         xxhdpi
    270       </screen-density>
    271       <screen-density>xxxhdpi</screen-density>
    272     </screen-density-group>)xml";
    273 
    274   auto doc = test::BuildXmlDom(xml);
    275 
    276   PostProcessingConfiguration config;
    277   bool ok =
    278       screen_density_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
    279   ASSERT_TRUE(ok);
    280 
    281   EXPECT_EQ(1ul, config.screen_density_groups.size());
    282   ASSERT_EQ(1u, config.screen_density_groups.count("large"));
    283 
    284   ConfigDescription xhdpi;
    285   xhdpi.density = ResTable_config::DENSITY_XHIGH;
    286   ConfigDescription xxhdpi;
    287   xxhdpi.density = ResTable_config::DENSITY_XXHIGH;
    288   ConfigDescription xxxhdpi;
    289   xxxhdpi.density = ResTable_config::DENSITY_XXXHIGH;
    290 
    291   auto& out = config.screen_density_groups["large"];
    292   ASSERT_THAT(out, ElementsAre(xhdpi, xxhdpi, xxxhdpi));
    293 }
    294 
    295 TEST_F(ConfigurationParserTest, LocaleGroupAction) {
    296   static constexpr const char* xml = R"xml(
    297     <locale-group label="europe">
    298       <locale lang="en"/>
    299       <locale lang="es"/>
    300       <locale lang="fr"/>
    301       <locale lang="de"/>
    302     </locale-group>)xml";
    303 
    304   auto doc = test::BuildXmlDom(xml);
    305 
    306   PostProcessingConfiguration config;
    307   bool ok = locale_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
    308   ASSERT_TRUE(ok);
    309 
    310   ASSERT_EQ(1ul, config.locale_groups.size());
    311   ASSERT_EQ(1u, config.locale_groups.count("europe"));
    312 
    313   auto& out = config.locale_groups["europe"];
    314 
    315   Locale en;
    316   en.lang = std::string("en");
    317   Locale es;
    318   es.lang = std::string("es");
    319   Locale fr;
    320   fr.lang = std::string("fr");
    321   Locale de;
    322   de.lang = std::string("de");
    323 
    324   ASSERT_THAT(out, ElementsAre(en, es, fr, de));
    325 }
    326 
    327 TEST_F(ConfigurationParserTest, AndroidSdkGroupAction) {
    328   static constexpr const char* xml = R"xml(
    329     <android-sdk-group label="19">
    330       <android-sdk
    331           minSdkVersion="19"
    332           targetSdkVersion="24"
    333           maxSdkVersion="25">
    334         <manifest>
    335           <!--- manifest additions here XSLT? TODO -->
    336         </manifest>
    337       </android-sdk>
    338     </android-sdk-group>)xml";
    339 
    340   auto doc = test::BuildXmlDom(xml);
    341 
    342   PostProcessingConfiguration config;
    343   bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
    344   ASSERT_TRUE(ok);
    345 
    346   ASSERT_EQ(1ul, config.android_sdk_groups.size());
    347   ASSERT_EQ(1u, config.android_sdk_groups.count("19"));
    348 
    349   auto& out = config.android_sdk_groups["19"];
    350 
    351   AndroidSdk sdk;
    352   sdk.min_sdk_version = std::string("19");
    353   sdk.target_sdk_version = std::string("24");
    354   sdk.max_sdk_version = std::string("25");
    355   sdk.manifest = AndroidManifest();
    356 
    357   ASSERT_EQ(1ul, out.size());
    358   ASSERT_EQ(sdk, out[0]);
    359 }
    360 
    361 TEST_F(ConfigurationParserTest, GlTextureGroupAction) {
    362   static constexpr const char* xml = R"xml(
    363     <gl-texture-group label="dxt1">
    364       <gl-texture name="GL_EXT_texture_compression_dxt1">
    365         <texture-path>assets/dxt1/main/*</texture-path>
    366         <texture-path>
    367           assets/dxt1/test/*
    368         </texture-path>
    369       </gl-texture>
    370     </gl-texture-group>)xml";
    371 
    372   auto doc = test::BuildXmlDom(xml);
    373 
    374   PostProcessingConfiguration config;
    375   bool ok = gl_texture_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
    376   ASSERT_TRUE(ok);
    377 
    378   EXPECT_EQ(1ul, config.gl_texture_groups.size());
    379   ASSERT_EQ(1u, config.gl_texture_groups.count("dxt1"));
    380 
    381   auto& out = config.gl_texture_groups["dxt1"];
    382 
    383   GlTexture texture{
    384       std::string("GL_EXT_texture_compression_dxt1"),
    385       {"assets/dxt1/main/*", "assets/dxt1/test/*"}
    386   };
    387 
    388   ASSERT_EQ(1ul, out.size());
    389   ASSERT_EQ(texture, out[0]);
    390 }
    391 
    392 TEST_F(ConfigurationParserTest, DeviceFeatureGroupAction) {
    393   static constexpr const char* xml = R"xml(
    394     <device-feature-group label="low-latency">
    395       <supports-feature>android.hardware.audio.low_latency</supports-feature>
    396       <supports-feature>
    397         android.hardware.audio.pro
    398       </supports-feature>
    399     </device-feature-group>)xml";
    400 
    401   auto doc = test::BuildXmlDom(xml);
    402 
    403   PostProcessingConfiguration config;
    404   bool ok
    405       = device_feature_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
    406   ASSERT_TRUE(ok);
    407 
    408   EXPECT_EQ(1ul, config.device_feature_groups.size());
    409   ASSERT_EQ(1u, config.device_feature_groups.count("low-latency"));
    410 
    411   auto& out = config.device_feature_groups["low-latency"];
    412 
    413   DeviceFeature low_latency = "android.hardware.audio.low_latency";
    414   DeviceFeature pro = "android.hardware.audio.pro";
    415   ASSERT_THAT(out, ElementsAre(low_latency, pro));
    416 }
    417 
    418 TEST(ArtifactTest, Simple) {
    419   StdErrDiagnostics diag;
    420   Artifact x86;
    421   x86.abi_group = {"x86"};
    422 
    423   auto x86_result = x86.ToArtifactName("something.{abi}.apk", &diag);
    424   ASSERT_TRUE(x86_result);
    425   EXPECT_EQ(x86_result.value(), "something.x86.apk");
    426 
    427   Artifact arm;
    428   arm.abi_group = {"armeabi-v7a"};
    429 
    430   auto arm_result = arm.ToArtifactName("app.{abi}.apk", &diag);
    431   ASSERT_TRUE(arm_result);
    432   EXPECT_EQ(arm_result.value(), "app.armeabi-v7a.apk");
    433 }
    434 
    435 TEST(ArtifactTest, Complex) {
    436   StdErrDiagnostics diag;
    437   Artifact artifact;
    438   artifact.abi_group = {"mips64"};
    439   artifact.screen_density_group = {"ldpi"};
    440   artifact.device_feature_group = {"df1"};
    441   artifact.gl_texture_group = {"glx1"};
    442   artifact.locale_group = {"en-AU"};
    443   artifact.android_sdk_group = {"26"};
    444 
    445   auto result =
    446       artifact.ToArtifactName("app.{density}_{locale}_{feature}_{gl}.sdk{sdk}.{abi}.apk", &diag);
    447   ASSERT_TRUE(result);
    448   EXPECT_EQ(result.value(), "app.ldpi_en-AU_df1_glx1.sdk26.mips64.apk");
    449 }
    450 
    451 TEST(ArtifactTest, Missing) {
    452   StdErrDiagnostics diag;
    453   Artifact x86;
    454   x86.abi_group = {"x86"};
    455 
    456   EXPECT_FALSE(x86.ToArtifactName("something.{density}.apk", &diag));
    457   EXPECT_FALSE(x86.ToArtifactName("something.apk", &diag));
    458 }
    459 
    460 TEST(ArtifactTest, Empty) {
    461   StdErrDiagnostics diag;
    462   Artifact artifact;
    463 
    464   EXPECT_FALSE(artifact.ToArtifactName("something.{density}.apk", &diag));
    465   EXPECT_TRUE(artifact.ToArtifactName("something.apk", &diag));
    466 }
    467 
    468 }  // namespace
    469 }  // namespace aapt
    470