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