ConfigurationParser_test.cpp revision 280be34fa6311de90dff6c595a147fd5a182223d
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::PostProcessingConfiguration;
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  PostProcessingConfiguration& 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  PostProcessingConfiguration 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.front();
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  // Perform a second action to ensure we get 2 artifacts.
209  static constexpr const char* second = R"xml(
210    <artifact
211        abi-group="other"
212        screen-density-group="large"
213        locale-group="europe"
214        android-sdk-group="19"
215        gl-texture-group="dxt1"
216        device-feature-group="low-latency"/>)xml";
217  doc = test::BuildXmlDom(second);
218
219  ok = artifact_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
220  ASSERT_TRUE(ok);
221  EXPECT_EQ(2ul, config.artifacts.size());
222}
223
224TEST_F(ConfigurationParserTest, ArtifactFormatAction) {
225  static constexpr const char* xml = R"xml(
226    <artifact-format>
227      ${base}.${abi}.${screen-density}.${locale}.${sdk}.${gl}.${feature}.release
228    </artifact-format>)xml";
229
230  auto doc = test::BuildXmlDom(xml);
231
232  PostProcessingConfiguration config;
233  bool ok = artifact_format_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
234  ASSERT_TRUE(ok);
235  ASSERT_TRUE(config.artifact_format);
236  EXPECT_EQ(
237      "${base}.${abi}.${screen-density}.${locale}.${sdk}.${gl}.${feature}.release",
238      static_cast<std::string>(config.artifact_format.value())
239  );
240}
241
242TEST_F(ConfigurationParserTest, AbiGroupAction) {
243  static constexpr const char* xml = R"xml(
244    <abi-group label="arm">
245      <!-- First comment. -->
246      <abi>
247        armeabi-v7a
248      </abi>
249      <!-- Another comment. -->
250      <abi>arm64-v8a</abi>
251    </abi-group>)xml";
252
253  auto doc = test::BuildXmlDom(xml);
254
255  PostProcessingConfiguration config;
256  bool ok = abi_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
257  ASSERT_TRUE(ok);
258
259  EXPECT_EQ(1ul, config.abi_groups.size());
260  ASSERT_EQ(1u, config.abi_groups.count("arm"));
261
262  auto& out = config.abi_groups["arm"];
263  ASSERT_THAT(out, ElementsAre(Abi::kArmV7a, Abi::kArm64V8a));
264}
265
266TEST_F(ConfigurationParserTest, ScreenDensityGroupAction) {
267  static constexpr const char* xml = R"xml(
268    <screen-density-group label="large">
269      <screen-density>xhdpi</screen-density>
270      <screen-density>
271        xxhdpi
272      </screen-density>
273      <screen-density>xxxhdpi</screen-density>
274    </screen-density-group>)xml";
275
276  auto doc = test::BuildXmlDom(xml);
277
278  PostProcessingConfiguration config;
279  bool ok =
280      screen_density_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
281  ASSERT_TRUE(ok);
282
283  EXPECT_EQ(1ul, config.screen_density_groups.size());
284  ASSERT_EQ(1u, config.screen_density_groups.count("large"));
285
286  ConfigDescription xhdpi;
287  xhdpi.density = ResTable_config::DENSITY_XHIGH;
288  ConfigDescription xxhdpi;
289  xxhdpi.density = ResTable_config::DENSITY_XXHIGH;
290  ConfigDescription xxxhdpi;
291  xxxhdpi.density = ResTable_config::DENSITY_XXXHIGH;
292
293  auto& out = config.screen_density_groups["large"];
294  ASSERT_THAT(out, ElementsAre(xhdpi, xxhdpi, xxxhdpi));
295}
296
297TEST_F(ConfigurationParserTest, LocaleGroupAction) {
298  static constexpr const char* xml = R"xml(
299    <locale-group label="europe">
300      <locale lang="en"/>
301      <locale lang="es"/>
302      <locale lang="fr"/>
303      <locale lang="de"/>
304    </locale-group>)xml";
305
306  auto doc = test::BuildXmlDom(xml);
307
308  PostProcessingConfiguration config;
309  bool ok = locale_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
310  ASSERT_TRUE(ok);
311
312  ASSERT_EQ(1ul, config.locale_groups.size());
313  ASSERT_EQ(1u, config.locale_groups.count("europe"));
314
315  auto& out = config.locale_groups["europe"];
316
317  Locale en;
318  en.lang = std::string("en");
319  Locale es;
320  es.lang = std::string("es");
321  Locale fr;
322  fr.lang = std::string("fr");
323  Locale de;
324  de.lang = std::string("de");
325
326  ASSERT_THAT(out, ElementsAre(en, es, fr, de));
327}
328
329TEST_F(ConfigurationParserTest, AndroidSdkGroupAction) {
330  static constexpr const char* xml = R"xml(
331    <android-sdk-group label="19">
332      <android-sdk
333          minSdkVersion="19"
334          targetSdkVersion="24"
335          maxSdkVersion="25">
336        <manifest>
337          <!--- manifest additions here XSLT? TODO -->
338        </manifest>
339      </android-sdk>
340    </android-sdk-group>)xml";
341
342  auto doc = test::BuildXmlDom(xml);
343
344  PostProcessingConfiguration config;
345  bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
346  ASSERT_TRUE(ok);
347
348  ASSERT_EQ(1ul, config.android_sdk_groups.size());
349  ASSERT_EQ(1u, config.android_sdk_groups.count("19"));
350
351  auto& out = config.android_sdk_groups["19"];
352
353  AndroidSdk sdk;
354  sdk.min_sdk_version = std::string("19");
355  sdk.target_sdk_version = std::string("24");
356  sdk.max_sdk_version = std::string("25");
357  sdk.manifest = AndroidManifest();
358
359  ASSERT_EQ(1ul, out.size());
360  ASSERT_EQ(sdk, out[0]);
361}
362
363TEST_F(ConfigurationParserTest, GlTextureGroupAction) {
364  static constexpr const char* xml = R"xml(
365    <gl-texture-group label="dxt1">
366      <gl-texture name="GL_EXT_texture_compression_dxt1">
367        <texture-path>assets/dxt1/main/*</texture-path>
368        <texture-path>
369          assets/dxt1/test/*
370        </texture-path>
371      </gl-texture>
372    </gl-texture-group>)xml";
373
374  auto doc = test::BuildXmlDom(xml);
375
376  PostProcessingConfiguration config;
377  bool ok = gl_texture_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
378  ASSERT_TRUE(ok);
379
380  EXPECT_EQ(1ul, config.gl_texture_groups.size());
381  ASSERT_EQ(1u, config.gl_texture_groups.count("dxt1"));
382
383  auto& out = config.gl_texture_groups["dxt1"];
384
385  GlTexture texture{
386      std::string("GL_EXT_texture_compression_dxt1"),
387      {"assets/dxt1/main/*", "assets/dxt1/test/*"}
388  };
389
390  ASSERT_EQ(1ul, out.size());
391  ASSERT_EQ(texture, out[0]);
392}
393
394TEST_F(ConfigurationParserTest, DeviceFeatureGroupAction) {
395  static constexpr const char* xml = R"xml(
396    <device-feature-group label="low-latency">
397      <supports-feature>android.hardware.audio.low_latency</supports-feature>
398      <supports-feature>
399        android.hardware.audio.pro
400      </supports-feature>
401    </device-feature-group>)xml";
402
403  auto doc = test::BuildXmlDom(xml);
404
405  PostProcessingConfiguration config;
406  bool ok
407      = device_feature_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
408  ASSERT_TRUE(ok);
409
410  EXPECT_EQ(1ul, config.device_feature_groups.size());
411  ASSERT_EQ(1u, config.device_feature_groups.count("low-latency"));
412
413  auto& out = config.device_feature_groups["low-latency"];
414
415  DeviceFeature low_latency = "android.hardware.audio.low_latency";
416  DeviceFeature pro = "android.hardware.audio.pro";
417  ASSERT_THAT(out, ElementsAre(low_latency, pro));
418}
419
420}  // namespace
421}  // namespace aapt
422