Home | History | Annotate | Download | only in tests
      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