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