1 /* 2 * Copyright (C) 2014 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 <androidfw/LocaleData.h> 18 #include <androidfw/ResourceTypes.h> 19 #include <utils/Log.h> 20 #include <utils/String8.h> 21 22 #include <gtest/gtest.h> 23 namespace android { 24 25 TEST(ConfigLocaleTest, packAndUnpack2LetterLanguage) { 26 ResTable_config config; 27 config.packLanguage("en"); 28 29 EXPECT_EQ('e', config.language[0]); 30 EXPECT_EQ('n', config.language[1]); 31 32 char out[4] = {1, 1, 1, 1}; 33 config.unpackLanguage(out); 34 EXPECT_EQ('e', out[0]); 35 EXPECT_EQ('n', out[1]); 36 EXPECT_EQ(0, out[2]); 37 EXPECT_EQ(0, out[3]); 38 39 memset(out, 1, sizeof(out)); 40 config.locale = 0; 41 config.unpackLanguage(out); 42 EXPECT_EQ(0, out[0]); 43 EXPECT_EQ(0, out[1]); 44 EXPECT_EQ(0, out[2]); 45 EXPECT_EQ(0, out[3]); 46 } 47 48 TEST(ConfigLocaleTest, packAndUnpack2LetterRegion) { 49 ResTable_config config; 50 config.packRegion("US"); 51 52 EXPECT_EQ('U', config.country[0]); 53 EXPECT_EQ('S', config.country[1]); 54 55 char out[4] = {1, 1, 1, 1}; 56 config.unpackRegion(out); 57 EXPECT_EQ('U', out[0]); 58 EXPECT_EQ('S', out[1]); 59 EXPECT_EQ(0, out[2]); 60 EXPECT_EQ(0, out[3]); 61 } 62 63 TEST(ConfigLocaleTest, packAndUnpack3LetterLanguage) { 64 ResTable_config config; 65 config.packLanguage("eng"); 66 67 // 1-00110-01 101-00100 68 EXPECT_EQ('\x99', config.language[0]); 69 EXPECT_EQ('\xA4', config.language[1]); 70 71 char out[4] = {1, 1, 1, 1}; 72 config.unpackLanguage(out); 73 EXPECT_EQ('e', out[0]); 74 EXPECT_EQ('n', out[1]); 75 EXPECT_EQ('g', out[2]); 76 EXPECT_EQ(0, out[3]); 77 } 78 79 TEST(ConfigLocaleTest, packAndUnpack3LetterLanguageAtOffset16) { 80 ResTable_config config; 81 config.packLanguage("tgp"); 82 83 // We had a bug where we would accidentally mask 84 // the 5th bit of both bytes 85 // 86 // packed[0] = 1011 1100 87 // packed[1] = 1101 0011 88 // 89 // which is equivalent to: 90 // 1 [0] [1] [2] 91 // 1-01111-00110-10011 92 EXPECT_EQ(char(0xbc), config.language[0]); 93 EXPECT_EQ(char(0xd3), config.language[1]); 94 95 char out[4] = {1, 1, 1, 1}; 96 config.unpackLanguage(out); 97 EXPECT_EQ('t', out[0]); 98 EXPECT_EQ('g', out[1]); 99 EXPECT_EQ('p', out[2]); 100 EXPECT_EQ(0, out[3]); 101 } 102 103 TEST(ConfigLocaleTest, packAndUnpack3LetterRegion) { 104 ResTable_config config; 105 config.packRegion("419"); 106 107 char out[4] = {1, 1, 1, 1}; 108 config.unpackRegion(out); 109 110 EXPECT_EQ('4', out[0]); 111 EXPECT_EQ('1', out[1]); 112 EXPECT_EQ('9', out[2]); 113 } 114 115 /* static */ void fillIn(const char* lang, const char* country, 116 const char* script, const char* variant, ResTable_config* out) { 117 memset(out, 0, sizeof(ResTable_config)); 118 if (lang != NULL) { 119 out->packLanguage(lang); 120 } 121 122 if (country != NULL) { 123 out->packRegion(country); 124 } 125 126 if (script != NULL) { 127 memcpy(out->localeScript, script, 4); 128 out->localeScriptWasComputed = false; 129 } else { 130 out->computeScript(); 131 out->localeScriptWasComputed = true; 132 } 133 134 if (variant != NULL) { 135 memcpy(out->localeVariant, variant, strlen(variant)); 136 } 137 } 138 139 TEST(ConfigLocaleTest, IsMoreSpecificThan) { 140 ResTable_config l; 141 ResTable_config r; 142 143 fillIn("en", NULL, NULL, NULL, &l); 144 fillIn(NULL, NULL, NULL, NULL, &r); 145 146 EXPECT_TRUE(l.isMoreSpecificThan(r)); 147 EXPECT_FALSE(r.isMoreSpecificThan(l)); 148 149 fillIn("eng", NULL, NULL, NULL, &l); 150 EXPECT_TRUE(l.isMoreSpecificThan(r)); 151 EXPECT_FALSE(r.isMoreSpecificThan(l)); 152 153 fillIn("eng", "419", NULL, NULL, &r); 154 EXPECT_FALSE(l.isMoreSpecificThan(r)); 155 EXPECT_TRUE(r.isMoreSpecificThan(l)); 156 157 fillIn("en", NULL, NULL, NULL, &l); 158 fillIn("en", "US", NULL, NULL, &r); 159 EXPECT_FALSE(l.isMoreSpecificThan(r)); 160 EXPECT_TRUE(r.isMoreSpecificThan(l)); 161 162 fillIn("en", "US", NULL, NULL, &l); 163 fillIn("en", "US", "Latn", NULL, &r); 164 EXPECT_FALSE(l.isMoreSpecificThan(r)); 165 EXPECT_TRUE(r.isMoreSpecificThan(l)); 166 167 fillIn("en", "US", NULL, NULL, &l); 168 fillIn("en", "US", NULL, "POSIX", &r); 169 EXPECT_FALSE(l.isMoreSpecificThan(r)); 170 EXPECT_TRUE(r.isMoreSpecificThan(l)); 171 172 fillIn("en", "US", "Latn", NULL, &l); 173 fillIn("en", "US", NULL, "POSIX", &r); 174 EXPECT_FALSE(l.isMoreSpecificThan(r)); 175 EXPECT_TRUE(r.isMoreSpecificThan(l)); 176 177 fillIn("ar", "EG", NULL, NULL, &l); 178 fillIn("ar", "EG", NULL, NULL, &r); 179 memcpy(&r.localeNumberingSystem, "latn", 4); 180 EXPECT_FALSE(l.isMoreSpecificThan(r)); 181 EXPECT_TRUE(r.isMoreSpecificThan(l)); 182 183 fillIn("en", "US", NULL, NULL, &l); 184 fillIn("es", "ES", NULL, NULL, &r); 185 186 EXPECT_FALSE(l.isMoreSpecificThan(r)); 187 EXPECT_FALSE(r.isMoreSpecificThan(l)); 188 } 189 190 TEST(ConfigLocaleTest, setLocale) { 191 ResTable_config test; 192 test.setBcp47Locale("en-US"); 193 EXPECT_EQ('e', test.language[0]); 194 EXPECT_EQ('n', test.language[1]); 195 EXPECT_EQ('U', test.country[0]); 196 EXPECT_EQ('S', test.country[1]); 197 EXPECT_TRUE(test.localeScriptWasComputed); 198 EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4)); 199 EXPECT_EQ(0, test.localeVariant[0]); 200 EXPECT_EQ(0, test.localeNumberingSystem[0]); 201 202 test.setBcp47Locale("eng-419"); 203 char out[4] = {1, 1, 1, 1}; 204 test.unpackLanguage(out); 205 EXPECT_EQ('e', out[0]); 206 EXPECT_EQ('n', out[1]); 207 EXPECT_EQ('g', out[2]); 208 EXPECT_EQ(0, out[3]); 209 memset(out, 1, 4); 210 test.unpackRegion(out); 211 EXPECT_EQ('4', out[0]); 212 EXPECT_EQ('1', out[1]); 213 EXPECT_EQ('9', out[2]); 214 EXPECT_EQ(0, test.localeNumberingSystem[0]); 215 216 test.setBcp47Locale("en-Latn-419"); 217 EXPECT_EQ('e', test.language[0]); 218 EXPECT_EQ('n', test.language[1]); 219 EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4)); 220 EXPECT_FALSE(test.localeScriptWasComputed); 221 memset(out, 1, 4); 222 test.unpackRegion(out); 223 EXPECT_EQ('4', out[0]); 224 EXPECT_EQ('1', out[1]); 225 EXPECT_EQ('9', out[2]); 226 EXPECT_EQ(0, test.localeNumberingSystem[0]); 227 228 test.setBcp47Locale("de-1901"); 229 memset(out, 1, 4); 230 test.unpackLanguage(out); 231 EXPECT_EQ('d', out[0]); 232 EXPECT_EQ('e', out[1]); 233 EXPECT_EQ('\0', out[2]); 234 EXPECT_TRUE(test.localeScriptWasComputed); 235 EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4)); 236 memset(out, 1, 4); 237 test.unpackRegion(out); 238 EXPECT_EQ('\0', out[0]); 239 EXPECT_EQ(0, strcmp("1901", test.localeVariant)); 240 EXPECT_EQ(0, test.localeNumberingSystem[0]); 241 242 test.setBcp47Locale("de-Latn-1901"); 243 memset(out, 1, 4); 244 test.unpackLanguage(out); 245 EXPECT_EQ('d', out[0]); 246 EXPECT_EQ('e', out[1]); 247 EXPECT_EQ('\0', out[2]); 248 EXPECT_FALSE(test.localeScriptWasComputed); 249 EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4)); 250 memset(out, 1, 4); 251 test.unpackRegion(out); 252 EXPECT_EQ('\0', out[0]); 253 EXPECT_EQ(0, strcmp("1901", test.localeVariant)); 254 EXPECT_EQ(0, test.localeNumberingSystem[0]); 255 256 test.setBcp47Locale("ar-EG-u-nu-latn"); 257 EXPECT_EQ('a', test.language[0]); 258 EXPECT_EQ('r', test.language[1]); 259 EXPECT_EQ('E', test.country[0]); 260 EXPECT_EQ('G', test.country[1]); 261 EXPECT_TRUE(test.localeScriptWasComputed); 262 EXPECT_EQ(0, memcmp("Arab", test.localeScript, 4)); 263 EXPECT_EQ(0, test.localeVariant[0]); 264 EXPECT_EQ(0, memcmp("latn", test.localeNumberingSystem, 4)); 265 266 test.setBcp47Locale("ar-EG-u"); 267 EXPECT_EQ(0, test.localeNumberingSystem[0]); 268 269 test.setBcp47Locale("ar-EG-u-nu"); 270 EXPECT_EQ(0, test.localeNumberingSystem[0]); 271 272 test.setBcp47Locale("ar-EG-u-attr-nu-latn"); 273 EXPECT_EQ(0, memcmp("latn", test.localeNumberingSystem, 4)); 274 275 test.setBcp47Locale("ar-EG-u-ca-gregory-nu-latn"); 276 EXPECT_EQ(0, memcmp("latn", test.localeNumberingSystem, 4)); 277 278 test.setBcp47Locale("ar-EG-u-nu-latn-ca-gregory"); 279 EXPECT_EQ(0, memcmp("latn", test.localeNumberingSystem, 4)); 280 281 test.setBcp47Locale("ar-EG-u-nu-toolongnumsys"); 282 EXPECT_EQ(0, test.localeNumberingSystem[0]); 283 284 test.setBcp47Locale("ar-EG-u-nu-latn-nu-arab"); 285 EXPECT_EQ(0, memcmp("latn", test.localeNumberingSystem, 4)); 286 287 test.setBcp47Locale("ar-EG-u-co-nu-latn"); 288 EXPECT_EQ(0, test.localeNumberingSystem[0]); 289 290 test.setBcp47Locale("ar-u-co-abcd-attr-nu-latn"); 291 EXPECT_EQ(0, test.localeNumberingSystem[0]); 292 } 293 294 TEST(ConfigLocaleTest, computeScript) { 295 ResTable_config config; 296 297 fillIn(NULL, NULL, NULL, NULL, &config); 298 EXPECT_EQ(0, memcmp("\0\0\0\0", config.localeScript, 4)); 299 300 fillIn("zh", "TW", NULL, NULL, &config); 301 EXPECT_EQ(0, memcmp("Hant", config.localeScript, 4)); 302 303 fillIn("zh", "CN", NULL, NULL, &config); 304 EXPECT_EQ(0, memcmp("Hans", config.localeScript, 4)); 305 306 fillIn("az", NULL, NULL, NULL, &config); 307 EXPECT_EQ(0, memcmp("Latn", config.localeScript, 4)); 308 309 fillIn("az", "AZ", NULL, NULL, &config); 310 EXPECT_EQ(0, memcmp("Latn", config.localeScript, 4)); 311 312 fillIn("az", "IR", NULL, NULL, &config); 313 EXPECT_EQ(0, memcmp("Arab", config.localeScript, 4)); 314 315 fillIn("peo", NULL, NULL, NULL, &config); 316 EXPECT_EQ(0, memcmp("Xpeo", config.localeScript, 4)); 317 318 fillIn("qaa", NULL, NULL, NULL, &config); 319 EXPECT_EQ(0, memcmp("\0\0\0\0", config.localeScript, 4)); 320 } 321 322 TEST(ConfigLocaleTest, getBcp47Locale_script) { 323 ResTable_config config; 324 fillIn("en", NULL, "Latn", NULL, &config); 325 326 char out[RESTABLE_MAX_LOCALE_LEN]; 327 config.localeScriptWasComputed = false; 328 config.getBcp47Locale(out); 329 EXPECT_EQ(0, strcmp("en-Latn", out)); 330 331 config.localeScriptWasComputed = true; 332 config.getBcp47Locale(out); 333 EXPECT_EQ(0, strcmp("en", out)); 334 } 335 336 TEST(ConfigLocaleTest, getBcp47Locale_numberingSystem) { 337 ResTable_config config; 338 fillIn("en", NULL, NULL, NULL, &config); 339 340 char out[RESTABLE_MAX_LOCALE_LEN]; 341 342 memcpy(&config.localeNumberingSystem, "latn", 4); 343 config.getBcp47Locale(out); 344 EXPECT_EQ(0, strcmp("en-u-nu-latn", out)); 345 346 fillIn("sr", "SR", "Latn", NULL, &config); 347 memcpy(&config.localeNumberingSystem, "latn", 4); 348 config.getBcp47Locale(out); 349 EXPECT_EQ(0, strcmp("sr-Latn-SR-u-nu-latn", out)); 350 } 351 352 TEST(ConfigLocaleTest, getBcp47Locale_canonicalize) { 353 ResTable_config config; 354 char out[RESTABLE_MAX_LOCALE_LEN]; 355 356 fillIn("tl", NULL, NULL, NULL, &config); 357 config.getBcp47Locale(out); 358 EXPECT_EQ(0, strcmp("tl", out)); 359 config.getBcp47Locale(out, true /* canonicalize */); 360 EXPECT_EQ(0, strcmp("fil", out)); 361 362 fillIn("tl", "PH", NULL, NULL, &config); 363 config.getBcp47Locale(out); 364 EXPECT_EQ(0, strcmp("tl-PH", out)); 365 config.getBcp47Locale(out, true /* canonicalize */); 366 EXPECT_EQ(0, strcmp("fil-PH", out)); 367 } 368 369 TEST(ConfigLocaleTest, match) { 370 ResTable_config supported, requested; 371 372 fillIn(NULL, NULL, NULL, NULL, &supported); 373 fillIn("fr", "CA", NULL, NULL, &requested); 374 // Empty locale matches everything (as a default). 375 EXPECT_TRUE(supported.match(requested)); 376 377 fillIn("en", "CA", NULL, NULL, &supported); 378 fillIn("fr", "CA", NULL, NULL, &requested); 379 // Different languages don't match. 380 EXPECT_FALSE(supported.match(requested)); 381 382 fillIn("tl", "PH", NULL, NULL, &supported); 383 fillIn("fil", "PH", NULL, NULL, &requested); 384 // Equivalent languages match. 385 EXPECT_TRUE(supported.match(requested)); 386 387 fillIn("qaa", "FR", NULL, NULL, &supported); 388 fillIn("qaa", "CA", NULL, NULL, &requested); 389 // If we can't infer the scripts, different regions don't match. 390 EXPECT_FALSE(supported.match(requested)); 391 392 fillIn("qaa", "FR", "Latn", NULL, &supported); 393 fillIn("qaa", "CA", NULL, NULL, &requested); 394 // If we can't infer any of the scripts, different regions don't match. 395 EXPECT_FALSE(supported.match(requested)); 396 397 fillIn("qaa", "FR", NULL, NULL, &supported); 398 fillIn("qaa", "CA", "Latn", NULL, &requested); 399 // If we can't infer any of the scripts, different regions don't match. 400 EXPECT_FALSE(supported.match(requested)); 401 402 fillIn("qaa", NULL, NULL, NULL, &supported); 403 fillIn("qaa", "CA", NULL, NULL, &requested); 404 // language-only resources still support language+region requests, even if we can't infer the 405 // script. 406 EXPECT_TRUE(supported.match(requested)); 407 408 fillIn("qaa", "CA", NULL, NULL, &supported); 409 fillIn("qaa", "CA", NULL, NULL, &requested); 410 // Even if we can't infer the scripts, exactly equal locales match. 411 EXPECT_TRUE(supported.match(requested)); 412 413 fillIn("az", NULL, NULL, NULL, &supported); 414 fillIn("az", NULL, "Latn", NULL, &requested); 415 // If the resolved scripts are the same, it doesn't matter if they were explicitly provided 416 // or not, and they match. 417 EXPECT_TRUE(supported.match(requested)); 418 419 fillIn("az", NULL, NULL, NULL, &supported); 420 fillIn("az", NULL, "Cyrl", NULL, &requested); 421 // If the resolved scripts are different, they don't match. 422 EXPECT_FALSE(supported.match(requested)); 423 424 fillIn("az", NULL, NULL, NULL, &supported); 425 fillIn("az", "IR", NULL, NULL, &requested); 426 // If the resolved scripts are different, they don't match. 427 EXPECT_FALSE(supported.match(requested)); 428 429 fillIn("az", "IR", NULL, NULL, &supported); 430 fillIn("az", NULL, "Arab", NULL, &requested); 431 // If the resolved scripts are the same, it doesn't matter if they were explicitly provided 432 // or not, and they match. 433 EXPECT_TRUE(supported.match(requested)); 434 435 fillIn("en", NULL, NULL, NULL, &supported); 436 fillIn("en", "XA", NULL, NULL, &requested); 437 // en-XA is a pseudo-locale, and English resources are not a match for it. 438 EXPECT_FALSE(supported.match(requested)); 439 440 fillIn("en", "XA", NULL, NULL, &supported); 441 fillIn("en", NULL, NULL, NULL, &requested); 442 // en-XA is a pseudo-locale, and its resources don't support English locales. 443 EXPECT_FALSE(supported.match(requested)); 444 445 fillIn("en", "XA", NULL, NULL, &supported); 446 fillIn("en", "XA", NULL, NULL, &requested); 447 // Even if they are pseudo-locales, exactly equal locales match. 448 EXPECT_TRUE(supported.match(requested)); 449 450 fillIn("ar", NULL, NULL, NULL, &supported); 451 fillIn("ar", "XB", NULL, NULL, &requested); 452 // ar-XB is a pseudo-locale, and Arabic resources are not a match for it. 453 EXPECT_FALSE(supported.match(requested)); 454 455 fillIn("ar", "XB", NULL, NULL, &supported); 456 fillIn("ar", NULL, NULL, NULL, &requested); 457 // ar-XB is a pseudo-locale, and its resources don't support Arabic locales. 458 EXPECT_FALSE(supported.match(requested)); 459 460 fillIn("ar", "XB", NULL, NULL, &supported); 461 fillIn("ar", "XB", NULL, NULL, &requested); 462 // Even if they are pseudo-locales, exactly equal locales match. 463 EXPECT_TRUE(supported.match(requested)); 464 465 fillIn("ar", "EG", NULL, NULL, &supported); 466 fillIn("ar", "TN", NULL, NULL, &requested); 467 memcpy(&supported.localeNumberingSystem, "latn", 4); 468 EXPECT_TRUE(supported.match(requested)); 469 } 470 471 TEST(ConfigLocaleTest, match_emptyScript) { 472 ResTable_config supported, requested; 473 474 fillIn("fr", "FR", NULL, NULL, &supported); 475 fillIn("fr", "CA", NULL, NULL, &requested); 476 477 // emulate packages built with older AAPT 478 memset(supported.localeScript, '\0', 4); 479 supported.localeScriptWasComputed = false; 480 481 EXPECT_TRUE(supported.match(requested)); 482 } 483 484 TEST(ConfigLocaleTest, isLocaleBetterThan_basics) { 485 ResTable_config config1, config2, request; 486 487 fillIn(NULL, NULL, NULL, NULL, &request); 488 fillIn("fr", "FR", NULL, NULL, &config1); 489 fillIn("fr", "CA", NULL, NULL, &config2); 490 EXPECT_FALSE(config1.isLocaleBetterThan(config2, &request)); 491 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 492 493 fillIn("fr", "CA", NULL, NULL, &request); 494 fillIn(NULL, NULL, NULL, NULL, &config1); 495 fillIn(NULL, NULL, NULL, NULL, &config2); 496 EXPECT_FALSE(config1.isLocaleBetterThan(config2, &request)); 497 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 498 499 fillIn("fr", "CA", NULL, NULL, &request); 500 fillIn("fr", "FR", NULL, NULL, &config1); 501 fillIn(NULL, NULL, NULL, NULL, &config2); 502 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 503 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 504 505 fillIn("de", "DE", NULL, NULL, &request); 506 fillIn("de", "DE", NULL, NULL, &config1); 507 fillIn("de", "DE", NULL, "1901", &config2); 508 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 509 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 510 511 fillIn("de", "DE", NULL, NULL, &request); 512 fillIn("de", "DE", NULL, "1901", &config1); 513 fillIn("de", "DE", NULL, "1996", &config2); 514 EXPECT_FALSE(config1.isLocaleBetterThan(config2, &request)); 515 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 516 517 fillIn("de", "DE", NULL, "1901", &request); 518 fillIn("de", "DE", NULL, "1901", &config1); 519 fillIn("de", "DE", NULL, NULL, &config2); 520 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 521 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 522 523 fillIn("de", "DE", NULL, "1901", &request); 524 fillIn("de", "DE", NULL, "1996", &config1); 525 fillIn("de", "DE", NULL, NULL, &config2); 526 EXPECT_FALSE(config1.isLocaleBetterThan(config2, &request)); 527 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 528 529 fillIn("fil", "PH", NULL, NULL, &request); 530 fillIn("tl", "PH", NULL, NULL, &config1); 531 fillIn("fil", "US", NULL, NULL, &config2); 532 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 533 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 534 535 fillIn("fil", "PH", NULL, "fonipa", &request); 536 fillIn("tl", "PH", NULL, "fonipa", &config1); 537 fillIn("fil", "PH", NULL, NULL, &config2); 538 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 539 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 540 541 fillIn("fil", "PH", NULL, NULL, &request); 542 fillIn("fil", "PH", NULL, NULL, &config1); 543 fillIn("tl", "PH", NULL, NULL, &config2); 544 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 545 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 546 } 547 548 TEST(ConfigLocaleTest, isLocaleBetterThan_regionComparison) { 549 ResTable_config config1, config2, request; 550 551 fillIn("es", "AR", NULL, NULL, &request); 552 fillIn("es", "419", NULL, NULL, &config1); 553 fillIn("es", "419", NULL, NULL, &config2); 554 // Both supported locales are the same, so none is better than the other. 555 EXPECT_FALSE(config1.isLocaleBetterThan(config2, &request)); 556 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 557 558 fillIn("es", "AR", NULL, NULL, &request); 559 fillIn("es", "AR", NULL, NULL, &config1); 560 fillIn("es", "419", NULL, NULL, &config2); 561 // An exact locale match is better than a parent. 562 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 563 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 564 565 fillIn("es", "AR", NULL, NULL, &request); 566 fillIn("es", "419", NULL, NULL, &config1); 567 fillIn("es", NULL, NULL, NULL, &config2); 568 // A closer parent is better. 569 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 570 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 571 572 fillIn("es", "AR", NULL, NULL, &request); 573 fillIn("es", "419", NULL, NULL, &config1); 574 fillIn("es", "ES", NULL, NULL, &config2); 575 // A parent is better than a non-parent representative locale. 576 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 577 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 578 579 fillIn("es", "AR", NULL, NULL, &request); 580 fillIn("es", NULL, NULL, NULL, &config1); 581 fillIn("es", "ES", NULL, NULL, &config2); 582 // A parent is better than a non-parent representative locale. 583 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 584 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 585 586 fillIn("es", "AR", NULL, NULL, &request); 587 fillIn("es", "PE", NULL, NULL, &config1); 588 fillIn("es", "ES", NULL, NULL, &config2); 589 // A closer locale is better. 590 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 591 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 592 593 fillIn("es", "AR", NULL, NULL, &request); 594 fillIn("es", "US", NULL, NULL, &config1); 595 fillIn("es", NULL, NULL, NULL, &config2); 596 // Special case for Latin American Spanish: es-MX and es-US are 597 // pseudo-parents of all Latin Ameircan Spanish locales. 598 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 599 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 600 601 fillIn("es", "MX", NULL, NULL, &request); 602 fillIn("es", "US", NULL, NULL, &config1); 603 fillIn("es", NULL, NULL, NULL, &config2); 604 // Special case for Latin American Spanish: es-MX and es-US are 605 // pseudo-parents of all Latin Ameircan Spanish locales. 606 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 607 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 608 609 fillIn("es", "AR", NULL, NULL, &request); 610 fillIn("es", "MX", NULL, NULL, &config1); 611 fillIn("es", NULL, NULL, NULL, &config2); 612 // Special case for Latin American Spanish: es-MX and es-US are 613 // pseudo-parents of all Latin Ameircan Spanish locales. 614 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 615 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 616 617 fillIn("es", "US", NULL, NULL, &request); 618 fillIn("es", "MX", NULL, NULL, &config1); 619 fillIn("es", NULL, NULL, NULL, &config2); 620 // Special case for Latin American Spanish: es-MX and es-US are 621 // pseudo-parents of all Latin Ameircan Spanish locales. 622 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 623 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 624 625 fillIn("es", "AR", NULL, NULL, &request); 626 fillIn("es", "419", NULL, NULL, &config1); 627 fillIn("es", "MX", NULL, NULL, &config2); 628 // Even though es-MX and es-US are pseudo-parents of all Latin Ameircan 629 // Spanish locales, es-419 is a closer parent. 630 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 631 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 632 633 fillIn("es", "US", NULL, NULL, &request); 634 fillIn("es", "419", NULL, NULL, &config1); 635 fillIn("es", "MX", NULL, NULL, &config2); 636 // Even though es-MX and es-US are pseudo-parents of all Latin Ameircan 637 // Spanish locales, es-419 is a closer parent. 638 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 639 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 640 641 fillIn("es", "MX", NULL, NULL, &request); 642 fillIn("es", "419", NULL, NULL, &config1); 643 fillIn("es", "US", NULL, NULL, &config2); 644 // Even though es-MX and es-US are pseudo-parents of all Latin Ameircan 645 // Spanish locales, es-419 is a closer parent. 646 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 647 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 648 649 fillIn("es", "AR", NULL, NULL, &request); 650 fillIn("es", "MX", NULL, NULL, &config1); 651 fillIn("es", "BO", NULL, NULL, &config2); 652 // Special case for Latin American Spanish: es-MX and es-US are 653 // pseudo-parents of all Latin Ameircan Spanish locales. 654 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 655 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 656 657 fillIn("es", "AR", NULL, NULL, &request); 658 fillIn("es", "US", NULL, NULL, &config1); 659 fillIn("es", "BO", NULL, NULL, &config2); 660 // Special case for Latin American Spanish: es-MX and es-US are 661 // pseudo-parents of all Latin Ameircan Spanish locales. 662 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 663 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 664 665 fillIn("es", "IC", NULL, NULL, &request); 666 fillIn("es", "ES", NULL, NULL, &config1); 667 fillIn("es", "GQ", NULL, NULL, &config2); 668 // A representative locale is better if they are equidistant. 669 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 670 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 671 672 fillIn("es", "AR", NULL, NULL, &request); 673 fillIn("es", "MX", NULL, NULL, &config1); 674 fillIn("es", "US", NULL, NULL, &config2); 675 // If all is equal, the locale earlier in the dictionary is better. 676 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 677 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 678 679 fillIn("es", "GQ", NULL, NULL, &request); 680 fillIn("es", "IC", NULL, NULL, &config1); 681 fillIn("es", "419", NULL, NULL, &config2); 682 // If all is equal, the locale earlier in the dictionary is better and 683 // letters are better than numbers. 684 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 685 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 686 687 fillIn("en", "GB", NULL, NULL, &request); 688 fillIn("en", "001", NULL, NULL, &config1); 689 fillIn("en", NULL, NULL, NULL, &config2); 690 // A closer parent is better. 691 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 692 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 693 694 fillIn("en", "PR", NULL, NULL, &request); 695 fillIn("en", NULL, NULL, NULL, &config1); 696 fillIn("en", "001", NULL, NULL, &config2); 697 // A parent is better than a non-parent. 698 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 699 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 700 701 fillIn("en", "DE", NULL, NULL, &request); 702 fillIn("en", "150", NULL, NULL, &config1); 703 fillIn("en", "001", NULL, NULL, &config2); 704 // A closer parent is better. 705 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 706 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 707 708 fillIn("en", "IN", NULL, NULL, &request); 709 fillIn("en", "AU", NULL, NULL, &config1); 710 fillIn("en", "US", NULL, NULL, &config2); 711 // A closer locale is better. 712 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 713 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 714 715 fillIn("en", "PR", NULL, NULL, &request); 716 fillIn("en", "001", NULL, NULL, &config1); 717 fillIn("en", "GB", NULL, NULL, &config2); 718 // A closer locale is better. 719 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 720 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 721 722 fillIn("en", "IN", NULL, NULL, &request); 723 fillIn("en", "GB", NULL, NULL, &config1); 724 fillIn("en", "AU", NULL, NULL, &config2); 725 // A representative locale is better if they are equidistant. 726 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 727 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 728 729 fillIn("en", "IN", NULL, NULL, &request); 730 fillIn("en", "AU", NULL, NULL, &config1); 731 fillIn("en", "CA", NULL, NULL, &config2); 732 // If all is equal, the locale earlier in the dictionary is better. 733 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 734 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 735 736 fillIn("pt", "MZ", NULL, NULL, &request); 737 fillIn("pt", "PT", NULL, NULL, &config1); 738 fillIn("pt", NULL, NULL, NULL, &config2); 739 // A closer parent is better. 740 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 741 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 742 743 fillIn("pt", "MZ", NULL, NULL, &request); 744 fillIn("pt", "PT", NULL, NULL, &config1); 745 fillIn("pt", "BR", NULL, NULL, &config2); 746 // A parent is better than a non-parent. 747 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 748 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 749 750 fillIn("zh", "MO", "Hant", NULL, &request); 751 fillIn("zh", "HK", "Hant", NULL, &config1); 752 fillIn("zh", "TW", "Hant", NULL, &config2); 753 // A parent is better than a non-parent. 754 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 755 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 756 757 fillIn("zh", "US", "Hant", NULL, &request); 758 fillIn("zh", "TW", "Hant", NULL, &config1); 759 fillIn("zh", "HK", "Hant", NULL, &config2); 760 // A representative locale is better if they are equidistant. 761 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 762 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 763 764 fillIn("ar", "DZ", NULL, NULL, &request); 765 fillIn("ar", "015", NULL, NULL, &config1); 766 fillIn("ar", NULL, NULL, NULL, &config2); 767 // A closer parent is better. 768 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 769 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 770 771 fillIn("ar", "EG", NULL, NULL, &request); 772 fillIn("ar", NULL, NULL, NULL, &config1); 773 fillIn("ar", "015", NULL, NULL, &config2); 774 // A parent is better than a non-parent. 775 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 776 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 777 778 fillIn("ar", "QA", NULL, NULL, &request); 779 fillIn("ar", "EG", NULL, NULL, &config1); 780 fillIn("ar", "BH", NULL, NULL, &config2); 781 // A representative locale is better if they are equidistant. 782 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 783 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 784 785 fillIn("ar", "QA", NULL, NULL, &request); 786 fillIn("ar", "SA", NULL, NULL, &config1); 787 fillIn("ar", "015", NULL, NULL, &config2); 788 // If all is equal, the locale earlier in the dictionary is better and 789 // letters are better than numbers. 790 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 791 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 792 } 793 794 TEST(ConfigLocaleTest, isLocaleBetterThan_numberingSystem) { 795 ResTable_config config1, config2, request; 796 797 fillIn("ar", "EG", NULL, NULL, &request); 798 memcpy(&request.localeNumberingSystem, "latn", 4); 799 fillIn("ar", NULL, NULL, NULL, &config1); 800 memcpy(&config1.localeNumberingSystem, "latn", 4); 801 fillIn("ar", NULL, NULL, NULL, &config2); 802 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 803 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 804 805 fillIn("ar", "EG", NULL, NULL, &request); 806 memcpy(&request.localeNumberingSystem, "latn", 4); 807 fillIn("ar", "TN", NULL, NULL, &config1); 808 memcpy(&config1.localeNumberingSystem, "latn", 4); 809 fillIn("ar", NULL, NULL, NULL, &config2); 810 EXPECT_TRUE(config2.isLocaleBetterThan(config1, &request)); 811 EXPECT_FALSE(config1.isLocaleBetterThan(config2, &request)); 812 } 813 814 // Default resources are considered better matches for US English 815 // and US-like English locales than International English locales 816 TEST(ConfigLocaleTest, isLocaleBetterThan_UsEnglishIsSpecial) { 817 ResTable_config config1, config2, request; 818 819 fillIn("en", "US", NULL, NULL, &request); 820 fillIn(NULL, NULL, NULL, NULL, &config1); 821 fillIn("en", "001", NULL, NULL, &config2); 822 // default is better than International English 823 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 824 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 825 826 fillIn("en", "US", NULL, NULL, &request); 827 fillIn(NULL, NULL, NULL, NULL, &config1); 828 fillIn("en", "GB", NULL, NULL, &config2); 829 // default is better than British English 830 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 831 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 832 833 fillIn("en", "PR", NULL, NULL, &request); 834 fillIn(NULL, NULL, NULL, NULL, &config1); 835 fillIn("en", "001", NULL, NULL, &config2); 836 // Even for Puerto Rico, default is better than International English 837 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 838 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 839 840 fillIn("en", "US", NULL, NULL, &request); 841 fillIn("en", NULL, NULL, NULL, &config1); 842 fillIn(NULL, NULL, NULL, NULL, &config2); 843 // "English" is better than default, since it's a parent of US English 844 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 845 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 846 847 fillIn("en", "PR", NULL, NULL, &request); 848 fillIn("en", NULL, NULL, NULL, &config1); 849 fillIn(NULL, NULL, NULL, NULL, &config2); 850 // "English" is better than default, since it's a parent of Puerto Rico English 851 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 852 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 853 854 fillIn("en", "US", NULL, NULL, &request); 855 fillIn(NULL, NULL, NULL, NULL, &config1); 856 fillIn("en", "PR", NULL, NULL, &config2); 857 // For US English itself, we prefer default to its siblings in the parent tree 858 EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); 859 EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); 860 } 861 862 } // namespace android 863