• 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 "Util.h"
18 
19 #include "android-base/stringprintf.h"
20 
21 #include "AppInfo.h"
22 #include "split/TableSplitter.h"
23 #include "test/Builders.h"
24 #include "test/Test.h"
25 #include "util/Files.h"
26 
27 using ::android::ConfigDescription;
28 
29 namespace aapt {
30 
31 #ifdef _WIN32
32 #define CREATE_PATH(path) android::base::StringPrintf(";%s", path)
33 #else
34 #define CREATE_PATH(path) android::base::StringPrintf(":%s", path)
35 #endif
36 
37 #define EXPECT_CONFIG_EQ(constraints, config) \
38     EXPECT_EQ(constraints.configs.size(), 1); \
39     EXPECT_EQ(*constraints.configs.begin(), config); \
40     constraints.configs.clear();
41 
TEST(UtilTest,SplitNamesAreSanitized)42 TEST(UtilTest, SplitNamesAreSanitized) {
43     AppInfo app_info{"com.pkg"};
44     SplitConstraints split_constraints{
45         {test::ParseConfigOrDie("en-rUS-land"), test::ParseConfigOrDie("b+sr+Latn")}};
46 
47     const auto doc = GenerateSplitManifest(app_info, split_constraints);
48     const auto &root = doc->root;
49     EXPECT_EQ(root->name, "manifest");
50     // split names cannot contain hyphens or plus signs.
51     EXPECT_EQ(root->FindAttribute("", "split")->value, "config.b_sr_Latn_en_rUS_land");
52     // but we should use resource qualifiers verbatim in 'targetConfig'.
53     EXPECT_EQ(root->FindAttribute("", "targetConfig")->value, "b+sr+Latn,en-rUS-land");
54 }
55 
TEST(UtilTest,LongVersionCodeDefined)56 TEST (UtilTest, LongVersionCodeDefined) {
57   auto doc = test::BuildXmlDom(R"(
58       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
59         package="com.android.aapt.test" android:versionCode="0x1" android:versionCodeMajor="0x1">
60       </manifest>)");
61   SetLongVersionCode(doc->root.get(), 42);
62 
63   auto version_code = doc->root->FindAttribute(xml::kSchemaAndroid, "versionCode");
64   ASSERT_NE(version_code, nullptr);
65   EXPECT_EQ(version_code->value, "0x0000002a");
66 
67   ASSERT_NE(version_code->compiled_value, nullptr);
68   auto compiled_version_code = ValueCast<BinaryPrimitive>(version_code->compiled_value.get());
69   ASSERT_NE(compiled_version_code, nullptr);
70   EXPECT_EQ(compiled_version_code->value.data, 42U);
71 
72   auto version_code_major = doc->root->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
73   EXPECT_EQ(version_code_major, nullptr);
74 }
75 
76 TEST (UtilTest, LongVersionCodeUndefined) {
77   auto doc = test::BuildXmlDom(R"(
78         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
79           package="com.android.aapt.test">
80         </manifest>)");
81   SetLongVersionCode(doc->root.get(), 420000000000);
82 
83   auto version_code = doc->root->FindAttribute(xml::kSchemaAndroid, "versionCode");
84   ASSERT_NE(version_code, nullptr);
85   EXPECT_EQ(version_code->value, "0xc9f36800");
86 
87   ASSERT_NE(version_code->compiled_value, nullptr);
88   auto compiled_version_code = ValueCast<BinaryPrimitive>(version_code->compiled_value.get());
89   ASSERT_NE(compiled_version_code, nullptr);
90   EXPECT_EQ(compiled_version_code->value.data, 0xc9f36800);
91 
92   auto version_code_major = doc->root->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
93   ASSERT_NE(version_code_major, nullptr);
94   EXPECT_EQ(version_code_major->value, "0x00000061");
95 
96   ASSERT_NE(version_code_major->compiled_value, nullptr);
97   auto compiled_version_code_major = ValueCast<BinaryPrimitive>(
98       version_code_major->compiled_value.get());
99   ASSERT_NE(compiled_version_code_major, nullptr);
100   EXPECT_EQ(compiled_version_code_major->value.data, 0x61);
101 }
102 
103 
104 TEST (UtilTest, ParseSplitParameters) {
105   IDiagnostics* diagnostics = test::ContextBuilder().Build().get()->GetDiagnostics();
106   std::string path;
107   SplitConstraints constraints;
108   ConfigDescription expected_configuration;
109 
110   // ========== Test IMSI ==========
111   // mcc: 'mcc[0-9]{3}'
112   // mnc: 'mnc[0-9]{1,3}'
113   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("mcc310"),
114                                   diagnostics, &path, &constraints));
115   expected_configuration = test::ConfigDescriptionBuilder()
116       .setMcc(0x0136)
117       .Build();
118   EXPECT_CONFIG_EQ(constraints, expected_configuration);
119 
120   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("mcc310-mnc004"),
121                                   diagnostics, &path, &constraints));
122   expected_configuration = test::ConfigDescriptionBuilder()
123       .setMcc(0x0136)
124       .setMnc(0x0004)
125       .Build();
126   EXPECT_CONFIG_EQ(constraints, expected_configuration);
127 
128   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("mcc310-mnc000"),
129                                   diagnostics, &path, &constraints));
130   expected_configuration = test::ConfigDescriptionBuilder()
131       .setMcc(0x0136)
132       .setMnc(0xFFFF)
133       .Build();
134   EXPECT_CONFIG_EQ(constraints, expected_configuration);
135 
136   // ========== Test LOCALE ==========
137   // locale: '[a-z]{2,3}(-r[a-z]{2})?'
138   // locale: 'b+[a-z]{2,3}(+[a-z[0-9]]{2})?'
139   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("es"),
140                                   diagnostics, &path, &constraints));
141   expected_configuration = test::ConfigDescriptionBuilder()
142       .setLanguage(0x6573)
143       .Build();
144   EXPECT_CONFIG_EQ(constraints, expected_configuration);
145 
146   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("fr-rCA"),
147                                   diagnostics, &path, &constraints));
148   expected_configuration = test::ConfigDescriptionBuilder()
149       .setLanguage(0x6672)
150       .setCountry(0x4341)
151       .Build();
152   EXPECT_CONFIG_EQ(constraints, expected_configuration);
153 
154   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("b+es+419"),
155                                   diagnostics, &path, &constraints));
156   expected_configuration = test::ConfigDescriptionBuilder()
157       .setLanguage(0x6573)
158       .setCountry(0xA424)
159       .Build();
160   EXPECT_CONFIG_EQ(constraints, expected_configuration);
161 
162   // ========== Test SCREEN_TYPE ==========
163   // orientation: '(port|land|square)'
164   // touchscreen: '(notouch|stylus|finger)'
165   // density" '(anydpi|nodpi|ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|[0-9]*dpi)'
166   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("square"),
167                                   diagnostics, &path, &constraints));
168   expected_configuration = test::ConfigDescriptionBuilder()
169       .setOrientation(0x03)
170       .Build();
171   EXPECT_CONFIG_EQ(constraints, expected_configuration);
172 
173   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("stylus"),
174                                   diagnostics, &path, &constraints));
175   expected_configuration = test::ConfigDescriptionBuilder()
176       .setTouchscreen(0x02)
177       .Build();
178   EXPECT_CONFIG_EQ(constraints, expected_configuration);
179 
180   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("xxxhdpi"),
181                                   diagnostics, &path, &constraints));
182   expected_configuration = test::ConfigDescriptionBuilder()
183       .setDensity(0x0280)
184       .setSdkVersion(0x0004) // version [any density requires donut]
185       .Build();
186   EXPECT_CONFIG_EQ(constraints, expected_configuration);
187 
188   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("land-xhdpi-finger"),
189                                   diagnostics, &path, &constraints));
190   expected_configuration = test::ConfigDescriptionBuilder()
191       .setOrientation(0x02)
192       .setTouchscreen(0x03)
193       .setDensity(0x0140)
194       .setSdkVersion(0x0004) // version [any density requires donut]
195       .Build();
196   EXPECT_CONFIG_EQ(constraints, expected_configuration);
197 
198   // ========== Test INPUT ==========
199   // keyboard: '(nokeys|qwerty|12key)'
200   // navigation: '(nonav|dpad|trackball|wheel)'
201   // inputFlags: '(keysexposed|keyshidden|keyssoft)'
202   // inputFlags: '(navexposed|navhidden)'
203   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("qwerty"),
204                                   diagnostics, &path, &constraints));
205   expected_configuration = test::ConfigDescriptionBuilder()
206       .setKeyboard(0x02)
207       .Build();
208   EXPECT_CONFIG_EQ(constraints, expected_configuration);
209 
210   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("dpad"),
211                                   diagnostics, &path, &constraints));
212   expected_configuration = test::ConfigDescriptionBuilder()
213       .setNavigation(0x02)
214       .Build();
215   EXPECT_CONFIG_EQ(constraints, expected_configuration);
216 
217   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("keyssoft-navhidden"),
218                                   diagnostics, &path, &constraints));
219   expected_configuration = test::ConfigDescriptionBuilder()
220       .setInputFlags(0x0B)
221       .Build();
222   EXPECT_CONFIG_EQ(constraints, expected_configuration);
223 
224   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("keyshidden-nokeys-navexposed-trackball"),
225                                   diagnostics, &path, &constraints));
226   expected_configuration = test::ConfigDescriptionBuilder()
227       .setKeyboard(0x01)
228       .setNavigation(0x03)
229       .setInputFlags(0x06)
230       .Build();
231   EXPECT_CONFIG_EQ(constraints, expected_configuration);
232 
233   // ========== Test SCREEN_SIZE ==========
234   // screenWidth/screenHeight: '[0-9]+x[0-9]+'
235   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("1920x1080"),
236                                   diagnostics, &path, &constraints));
237   expected_configuration = test::ConfigDescriptionBuilder()
238       .setScreenWidth(0x0780)
239       .setScreenHeight(0x0438)
240       .Build();
241   EXPECT_CONFIG_EQ(constraints, expected_configuration);
242 
243   // ========== Test VERSION ==========
244   // version 'v[0-9]+'
245 
246   // ========== Test SCREEN_CONFIG ==========
247   // screenLayout [direction]: '(ldltr|ldrtl)'
248   // screenLayout [size]: '(small|normal|large|xlarge)'
249   // screenLayout [long]: '(long|notlong)'
250   // uiMode [type]: '(desk|car|television|appliance|watch|vrheadset)'
251   // uiMode [night]: '(night|notnight)'
252   // smallestScreenWidthDp: 'sw[0-9]dp'
253   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("ldrtl"),
254                                   diagnostics, &path, &constraints));
255   expected_configuration = test::ConfigDescriptionBuilder()
256       .setScreenLayout(0x80)
257       .Build();
258   EXPECT_CONFIG_EQ(constraints, expected_configuration);
259 
260   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("small"),
261                                   diagnostics, &path, &constraints));
262   expected_configuration = test::ConfigDescriptionBuilder()
263       .setScreenLayout(0x01)
264       .setSdkVersion(0x0004) // screenLayout (size) requires donut
265       .Build();
266   EXPECT_CONFIG_EQ(constraints, expected_configuration);
267 
268   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("notlong"),
269                                   diagnostics, &path, &constraints));
270   expected_configuration = test::ConfigDescriptionBuilder()
271       .setScreenLayout(0x10)
272       .setSdkVersion(0x0004) // screenLayout (long) requires donut
273       .Build();
274   EXPECT_CONFIG_EQ(constraints, expected_configuration);
275 
276   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("ldltr-normal-long"),
277                                       diagnostics, &path, &constraints));
278   expected_configuration = test::ConfigDescriptionBuilder()
279       .setScreenLayout(0x62)
280       .setSdkVersion(0x0004) // screenLayout (size|long) requires donut
281       .Build();
282   EXPECT_CONFIG_EQ(constraints, expected_configuration);
283 
284   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("car"),
285                                   diagnostics, &path, &constraints));
286   expected_configuration = test::ConfigDescriptionBuilder()
287       .setUiMode(0x03)
288       .setSdkVersion(0x0008) // uiMode requires froyo
289       .Build();
290   EXPECT_CONFIG_EQ(constraints, expected_configuration);
291 
292   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("vrheadset"),
293                                   diagnostics, &path, &constraints));
294   expected_configuration = test::ConfigDescriptionBuilder()
295       .setUiMode(0x07)
296       .setSdkVersion(0x001A) // uiMode 'vrheadset' requires oreo
297       .Build();
298   EXPECT_CONFIG_EQ(constraints, expected_configuration);
299 
300   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("television-night"),
301                                   diagnostics, &path, &constraints));
302   expected_configuration = test::ConfigDescriptionBuilder()
303       .setUiMode(0x24)
304       .setSdkVersion(0x0008) // uiMode requires froyo
305       .Build();
306   EXPECT_CONFIG_EQ(constraints, expected_configuration);
307 
308   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("sw1920dp"),
309                                   diagnostics, &path, &constraints));
310   expected_configuration = test::ConfigDescriptionBuilder()
311       .setSmallestScreenWidthDp(0x0780)
312       .setSdkVersion(0x000D) // smallestScreenWidthDp requires honeycomb mr2
313       .Build();
314   EXPECT_CONFIG_EQ(constraints, expected_configuration);
315 
316   // ========== Test SCREEN_SIZE_DP ==========
317   // screenWidthDp: 'w[0-9]dp'
318   // screenHeightDp: 'h[0-9]dp'
319   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("w1920dp"),
320                                   diagnostics, &path, &constraints));
321   expected_configuration = test::ConfigDescriptionBuilder()
322       .setScreenWidthDp(0x0780)
323       .setSdkVersion(0x000D) // screenWidthDp requires honeycomb mr2
324       .Build();
325   EXPECT_CONFIG_EQ(constraints, expected_configuration);
326 
327   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("h1080dp"),
328                                   diagnostics, &path, &constraints));
329   expected_configuration = test::ConfigDescriptionBuilder()
330       .setScreenHeightDp(0x0438)
331       .setSdkVersion(0x000D) // screenHeightDp requires honeycomb mr2
332       .Build();
333   EXPECT_CONFIG_EQ(constraints, expected_configuration);
334 
335   // ========== Test SCREEN_CONFIG_2 ==========
336   // screenLayout2: '(round|notround)'
337   // colorMode: '(widecg|nowidecg)'
338   // colorMode: '(highhdr|lowdr)'
339   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("round"),
340                                   diagnostics, &path, &constraints));
341   expected_configuration = test::ConfigDescriptionBuilder()
342       .setScreenLayout2(0x02)
343       .setSdkVersion(0x0017) // screenLayout2 (round) requires marshmallow
344       .Build();
345   EXPECT_CONFIG_EQ(constraints, expected_configuration);
346 
347   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("widecg-highdr"),
348                                   diagnostics, &path, &constraints));
349   expected_configuration = test::ConfigDescriptionBuilder()
350       .setColorMode(0x0A)
351       .setSdkVersion(0x001A) // colorMode (hdr|colour gamut) requires oreo
352       .Build();
353   EXPECT_CONFIG_EQ(constraints, expected_configuration);
354 }
355 
TEST(UtilTest,AdjustSplitConstraintsForMinSdk)356 TEST (UtilTest, AdjustSplitConstraintsForMinSdk) {
357   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
358 
359   IDiagnostics* diagnostics = context.get()->GetDiagnostics();
360   std::vector<SplitConstraints> test_constraints;
361   std::string path;
362 
363   test_constraints.push_back({});
364   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("v7"),
365                                   diagnostics, &path, &test_constraints.back()));
366   test_constraints.push_back({});
367   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("xhdpi"),
368                                   diagnostics, &path, &test_constraints.back()));
369   EXPECT_EQ(test_constraints.size(), 2);
370   EXPECT_EQ(test_constraints[0].name, "v7");
371   EXPECT_EQ(test_constraints[0].configs.size(), 1);
372   EXPECT_NE(*test_constraints[0].configs.begin(), ConfigDescription::DefaultConfig());
373   EXPECT_EQ(test_constraints[1].name, "xhdpi");
374   EXPECT_EQ(test_constraints[1].configs.size(), 1);
375   EXPECT_NE(*test_constraints[0].configs.begin(), ConfigDescription::DefaultConfig());
376 
377   auto adjusted_contraints = AdjustSplitConstraintsForMinSdk(26, test_constraints);
378   EXPECT_EQ(adjusted_contraints.size(), 2);
379   EXPECT_EQ(adjusted_contraints[0].name, "v7");
380   EXPECT_EQ(adjusted_contraints[0].configs.size(), 0);
381   EXPECT_EQ(adjusted_contraints[1].name, "xhdpi");
382   EXPECT_EQ(adjusted_contraints[1].configs.size(), 1);
383   EXPECT_NE(*adjusted_contraints[1].configs.begin(), ConfigDescription::DefaultConfig());
384 }
385 
TEST(UtilTest,RegularExperssionsSimple)386 TEST (UtilTest, RegularExperssionsSimple) {
387   std::string valid(".bc$");
388   std::regex expression = GetRegularExpression(valid);
389   EXPECT_TRUE(std::regex_search("file.abc", expression));
390   EXPECT_TRUE(std::regex_search("file.123bc", expression));
391   EXPECT_FALSE(std::regex_search("abc.zip", expression));
392 }
393 
TEST(UtilTest,RegularExpressionComplex)394 TEST (UtilTest, RegularExpressionComplex) {
395   std::string valid("\\.(d|D)(e|E)(x|X)$");
396   std::regex expression = GetRegularExpression(valid);
397   EXPECT_TRUE(std::regex_search("file.dex", expression));
398   EXPECT_TRUE(std::regex_search("file.DEX", expression));
399   EXPECT_TRUE(std::regex_search("file.dEx", expression));
400   EXPECT_FALSE(std::regex_search("file.dexx", expression));
401   EXPECT_FALSE(std::regex_search("dex.file", expression));
402   EXPECT_FALSE(std::regex_search("file.adex", expression));
403 }
404 
TEST(UtilTest,RegularExpressionNonEnglish)405 TEST (UtilTest, RegularExpressionNonEnglish) {
406   std::string valid("\\.(k|K)(o|O)(ń|Ń)(c|C)(ó|Ó)(w|W)(k|K)(a|A)$");
407   std::regex expression = GetRegularExpression(valid);
408   EXPECT_TRUE(std::regex_search("file.końcówka", expression));
409   EXPECT_TRUE(std::regex_search("file.KOŃCÓWKA", expression));
410   EXPECT_TRUE(std::regex_search("file.kOńcÓwkA", expression));
411   EXPECT_FALSE(std::regex_search("file.koncowka", expression));
412 }
413 
414 }  // namespace aapt
415