• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
ConfigurationParserTest()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