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