blob: 34a6537d9f2a910d8b4a44a79cacba4a9136e2c4 [file] [log] [blame]
Shane Farmer74cdea32017-05-12 16:22:36 -07001/*
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
Shane Farmer74cdea32017-05-12 16:22:36 -070021#include "androidfw/ResourceTypes.h"
22
23#include "test/Test.h"
24#include "xml/XmlDom.h"
25
26namespace aapt {
27namespace {
28
Adam Lesinski6b372992017-08-09 10:54:23 -070029using ::android::ResTable_config;
Shane Farmer74cdea32017-05-12 16:22:36 -070030using configuration::Abi;
31using configuration::AndroidSdk;
Shane Farmer9f0e7f12017-06-22 12:26:44 -070032using configuration::Artifact;
Shane Farmer280be342017-06-21 15:20:15 -070033using configuration::PostProcessingConfiguration;
Shane Farmer74cdea32017-05-12 16:22:36 -070034using configuration::DeviceFeature;
35using configuration::GlTexture;
36using configuration::Locale;
37using configuration::AndroidManifest;
Adam Lesinski6b372992017-08-09 10:54:23 -070038using ::testing::ElementsAre;
Shane Farmer74cdea32017-05-12 16:22:36 -070039using xml::Element;
40using xml::NodeCast;
41
42constexpr 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
123class ConfigurationParserTest : public ConfigurationParser, public ::testing::Test {
124 public:
125 ConfigurationParserTest() : ConfigurationParser("") {}
126
127 protected:
128 StdErrDiagnostics diag_;
129};
130
Shane Farmerb1027272017-06-14 09:10:28 -0700131TEST_F(ConfigurationParserTest, ForPath_NoFile) {
132 auto result = ConfigurationParser::ForPath("./does_not_exist.xml");
133 EXPECT_FALSE(result);
134}
135
Shane Farmer74cdea32017-05-12 16:22:36 -0700136TEST_F(ConfigurationParserTest, ValidateFile) {
137 auto parser = ConfigurationParser::ForContents(kValidConfig).WithDiagnostics(&diag_);
138 auto result = parser.Parse();
139 ASSERT_TRUE(result);
Shane Farmer280be342017-06-21 15:20:15 -0700140 PostProcessingConfiguration& value = result.value();
Shane Farmer74cdea32017-05-12 16:22:36 -0700141 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
171TEST_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
179TEST_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
Shane Farmer280be342017-06-21 15:20:15 -0700191 PostProcessingConfiguration config;
Adam Lesinski6b372992017-08-09 10:54:23 -0700192 bool ok = artifact_handler_(&config, NodeCast<Element>(doc->root.get()), &diag_);
Shane Farmer74cdea32017-05-12 16:22:36 -0700193 ASSERT_TRUE(ok);
194
195 EXPECT_EQ(1ul, config.artifacts.size());
196
Shane Farmer57669432017-06-19 12:52:04 -0700197 auto& artifact = config.artifacts.front();
Shane Farmer74cdea32017-05-12 16:22:36 -0700198 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());
Shane Farmer57669432017-06-19 12:52:04 -0700205
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());
Shane Farmer74cdea32017-05-12 16:22:36 -0700220}
221
222TEST_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
Shane Farmer280be342017-06-21 15:20:15 -0700230 PostProcessingConfiguration config;
Shane Farmer74cdea32017-05-12 16:22:36 -0700231 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
240TEST_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
Shane Farmer280be342017-06-21 15:20:15 -0700253 PostProcessingConfiguration config;
Shane Farmer74cdea32017-05-12 16:22:36 -0700254 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
264TEST_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
Shane Farmer280be342017-06-21 15:20:15 -0700276 PostProcessingConfiguration config;
Shane Farmer74cdea32017-05-12 16:22:36 -0700277 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
295TEST_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
Shane Farmer280be342017-06-21 15:20:15 -0700306 PostProcessingConfiguration config;
Shane Farmer74cdea32017-05-12 16:22:36 -0700307 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
327TEST_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
Shane Farmer280be342017-06-21 15:20:15 -0700342 PostProcessingConfiguration config;
Shane Farmer74cdea32017-05-12 16:22:36 -0700343 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
361TEST_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
Shane Farmer280be342017-06-21 15:20:15 -0700374 PostProcessingConfiguration config;
Shane Farmer74cdea32017-05-12 16:22:36 -0700375 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
392TEST_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
Shane Farmer280be342017-06-21 15:20:15 -0700403 PostProcessingConfiguration config;
Shane Farmer74cdea32017-05-12 16:22:36 -0700404 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
Shane Farmer1a21b8c2017-07-21 09:42:42 -0700418// Artifact name parser test cases.
419
Shane Farmer9f0e7f12017-06-22 12:26:44 -0700420TEST(ArtifactTest, Simple) {
421 StdErrDiagnostics diag;
422 Artifact x86;
423 x86.abi_group = {"x86"};
424
425 auto x86_result = x86.ToArtifactName("something.{abi}.apk", &diag);
426 ASSERT_TRUE(x86_result);
427 EXPECT_EQ(x86_result.value(), "something.x86.apk");
428
429 Artifact arm;
430 arm.abi_group = {"armeabi-v7a"};
431
432 auto arm_result = arm.ToArtifactName("app.{abi}.apk", &diag);
433 ASSERT_TRUE(arm_result);
434 EXPECT_EQ(arm_result.value(), "app.armeabi-v7a.apk");
435}
436
437TEST(ArtifactTest, Complex) {
438 StdErrDiagnostics diag;
439 Artifact artifact;
440 artifact.abi_group = {"mips64"};
441 artifact.screen_density_group = {"ldpi"};
442 artifact.device_feature_group = {"df1"};
443 artifact.gl_texture_group = {"glx1"};
444 artifact.locale_group = {"en-AU"};
445 artifact.android_sdk_group = {"26"};
446
447 auto result =
448 artifact.ToArtifactName("app.{density}_{locale}_{feature}_{gl}.sdk{sdk}.{abi}.apk", &diag);
449 ASSERT_TRUE(result);
450 EXPECT_EQ(result.value(), "app.ldpi_en-AU_df1_glx1.sdk26.mips64.apk");
451}
452
453TEST(ArtifactTest, Missing) {
454 StdErrDiagnostics diag;
455 Artifact x86;
456 x86.abi_group = {"x86"};
457
458 EXPECT_FALSE(x86.ToArtifactName("something.{density}.apk", &diag));
459 EXPECT_FALSE(x86.ToArtifactName("something.apk", &diag));
460}
461
462TEST(ArtifactTest, Empty) {
463 StdErrDiagnostics diag;
464 Artifact artifact;
465
466 EXPECT_FALSE(artifact.ToArtifactName("something.{density}.apk", &diag));
467 EXPECT_TRUE(artifact.ToArtifactName("something.apk", &diag));
468}
469
Shane Farmer1a21b8c2017-07-21 09:42:42 -0700470TEST(ArtifactTest, Repeated) {
471 StdErrDiagnostics diag;
472 Artifact artifact;
473 artifact.screen_density_group = {"mdpi"};
474
475 EXPECT_TRUE(artifact.ToArtifactName("something.{density}.apk", &diag));
476 EXPECT_FALSE(artifact.ToArtifactName("something.{density}.{density}.apk", &diag));
477}
478
479TEST(ArtifactTest, Nesting) {
480 StdErrDiagnostics diag;
481 Artifact x86;
482 x86.abi_group = {"x86"};
483
484 EXPECT_FALSE(x86.ToArtifactName("something.{abi{density}}.apk", &diag));
485
486 const Maybe<std::string>& name = x86.ToArtifactName("something.{abi{abi}}.apk", &diag);
487 EXPECT_TRUE(name);
488 EXPECT_EQ(name.value(), "something.{abix86}.apk");
489}
490
491TEST(ArtifactTest, Recursive) {
492 StdErrDiagnostics diag;
493 Artifact artifact;
494 artifact.device_feature_group = {"{gl}"};
495 artifact.gl_texture_group = {"glx1"};
496
497 EXPECT_FALSE(artifact.ToArtifactName("app.{feature}.{gl}.apk", &diag));
498
499 artifact.device_feature_group = {"df1"};
500 artifact.gl_texture_group = {"{feature}"};
501 {
502 const auto& result = artifact.ToArtifactName("app.{feature}.{gl}.apk", &diag);
503 EXPECT_TRUE(result);
504 EXPECT_EQ(result.value(), "app.df1.{feature}.apk");
505 }
506
507 // This is an invalid case, but should be the only possible case due to the ordering of
508 // replacement.
509 artifact.device_feature_group = {"{gl}"};
510 artifact.gl_texture_group = {"glx1"};
511 {
512 const auto& result = artifact.ToArtifactName("app.{feature}.apk", &diag);
513 EXPECT_TRUE(result);
514 EXPECT_EQ(result.value(), "app.glx1.apk");
515 }
516}
517
Shane Farmer74cdea32017-05-12 16:22:36 -0700518} // namespace
519} // namespace aapt