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 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 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 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 386 TEST(UtilTest, RegularExperssions) { 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 394 } // namespace aapt 395