• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TEST(ConfigLocaleTest,packAndUnpack2LetterLanguage)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 
TEST(ConfigLocaleTest,packAndUnpack2LetterRegion)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 
TEST(ConfigLocaleTest,packAndUnpack3LetterLanguage)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 
TEST(ConfigLocaleTest,packAndUnpack3LetterLanguageAtOffset16)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 
TEST(ConfigLocaleTest,packAndUnpack3LetterRegion)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 
fillIn(const char * lang,const char * country,const char * script,const char * variant,ResTable_config * out)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 
TEST(ConfigLocaleTest,IsMoreSpecificThan)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 
TEST(ConfigLocaleTest,setLocale)178 TEST(ConfigLocaleTest, setLocale) {
179     ResTable_config test;
180     test.setBcp47Locale("en-US");
181     EXPECT_EQ('e', test.language[0]);
182     EXPECT_EQ('n', test.language[1]);
183     EXPECT_EQ('U', test.country[0]);
184     EXPECT_EQ('S', test.country[1]);
185     EXPECT_TRUE(test.localeScriptWasComputed);
186     EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
187     EXPECT_EQ(0, test.localeVariant[0]);
188 
189     test.setBcp47Locale("eng-419");
190     char out[4] = {1, 1, 1, 1};
191     test.unpackLanguage(out);
192     EXPECT_EQ('e', out[0]);
193     EXPECT_EQ('n', out[1]);
194     EXPECT_EQ('g', out[2]);
195     EXPECT_EQ(0, out[3]);
196     memset(out, 1, 4);
197     test.unpackRegion(out);
198     EXPECT_EQ('4', out[0]);
199     EXPECT_EQ('1', out[1]);
200     EXPECT_EQ('9', out[2]);
201 
202     test.setBcp47Locale("en-Latn-419");
203     EXPECT_EQ('e', test.language[0]);
204     EXPECT_EQ('n', test.language[1]);
205     EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
206     EXPECT_FALSE(test.localeScriptWasComputed);
207     memset(out, 1, 4);
208     test.unpackRegion(out);
209     EXPECT_EQ('4', out[0]);
210     EXPECT_EQ('1', out[1]);
211     EXPECT_EQ('9', out[2]);
212 
213     test.setBcp47Locale("de-1901");
214     memset(out, 1, 4);
215     test.unpackLanguage(out);
216     EXPECT_EQ('d', out[0]);
217     EXPECT_EQ('e', out[1]);
218     EXPECT_EQ('\0', out[2]);
219     EXPECT_TRUE(test.localeScriptWasComputed);
220     EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
221     memset(out, 1, 4);
222     test.unpackRegion(out);
223     EXPECT_EQ('\0', out[0]);
224     EXPECT_EQ(0, strcmp("1901", test.localeVariant));
225 
226     test.setBcp47Locale("de-Latn-1901");
227     memset(out, 1, 4);
228     test.unpackLanguage(out);
229     EXPECT_EQ('d', out[0]);
230     EXPECT_EQ('e', out[1]);
231     EXPECT_EQ('\0', out[2]);
232     EXPECT_FALSE(test.localeScriptWasComputed);
233     EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
234     memset(out, 1, 4);
235     test.unpackRegion(out);
236     EXPECT_EQ('\0', out[0]);
237     EXPECT_EQ(0, strcmp("1901", test.localeVariant));
238 }
239 
TEST(ConfigLocaleTest,computeScript)240 TEST(ConfigLocaleTest, computeScript) {
241     ResTable_config config;
242 
243     fillIn(NULL, NULL, NULL, NULL, &config);
244     EXPECT_EQ(0, memcmp("\0\0\0\0", config.localeScript, 4));
245 
246     fillIn("zh", "TW", NULL, NULL, &config);
247     EXPECT_EQ(0, memcmp("Hant", config.localeScript, 4));
248 
249     fillIn("zh", "CN", NULL, NULL, &config);
250     EXPECT_EQ(0, memcmp("Hans", config.localeScript, 4));
251 
252     fillIn("az", NULL, NULL, NULL, &config);
253     EXPECT_EQ(0, memcmp("Latn", config.localeScript, 4));
254 
255     fillIn("az", "AZ", NULL, NULL, &config);
256     EXPECT_EQ(0, memcmp("Latn", config.localeScript, 4));
257 
258     fillIn("az", "IR", NULL, NULL, &config);
259     EXPECT_EQ(0, memcmp("Arab", config.localeScript, 4));
260 
261     fillIn("peo", NULL, NULL, NULL, &config);
262     EXPECT_EQ(0, memcmp("Xpeo", config.localeScript, 4));
263 
264     fillIn("qaa", NULL, NULL, NULL, &config);
265     EXPECT_EQ(0, memcmp("\0\0\0\0", config.localeScript, 4));
266 }
267 
TEST(ConfigLocaleTest,getBcp47Locale_script)268 TEST(ConfigLocaleTest, getBcp47Locale_script) {
269     ResTable_config config;
270     fillIn("en", NULL, "Latn", NULL, &config);
271 
272     char out[RESTABLE_MAX_LOCALE_LEN];
273     config.localeScriptWasComputed = false;
274     config.getBcp47Locale(out);
275     EXPECT_EQ(0, strcmp("en-Latn", out));
276 
277     config.localeScriptWasComputed = true;
278     config.getBcp47Locale(out);
279     EXPECT_EQ(0, strcmp("en", out));
280 }
281 
TEST(ConfigLocaleTest,getBcp47Locale_canonicalize)282 TEST(ConfigLocaleTest, getBcp47Locale_canonicalize) {
283     ResTable_config config;
284     char out[RESTABLE_MAX_LOCALE_LEN];
285 
286     fillIn("tl", NULL, NULL, NULL, &config);
287     config.getBcp47Locale(out);
288     EXPECT_EQ(0, strcmp("tl", out));
289     config.getBcp47Locale(out, true /* canonicalize */);
290     EXPECT_EQ(0, strcmp("fil", out));
291 
292     fillIn("tl", "PH", NULL, NULL, &config);
293     config.getBcp47Locale(out);
294     EXPECT_EQ(0, strcmp("tl-PH", out));
295     config.getBcp47Locale(out, true /* canonicalize */);
296     EXPECT_EQ(0, strcmp("fil-PH", out));
297 }
298 
TEST(ConfigLocaleTest,match)299 TEST(ConfigLocaleTest, match) {
300     ResTable_config supported, requested;
301 
302     fillIn(NULL, NULL, NULL, NULL, &supported);
303     fillIn("fr", "CA", NULL, NULL, &requested);
304     // Empty locale matches everything (as a default).
305     EXPECT_TRUE(supported.match(requested));
306 
307     fillIn("en", "CA", NULL, NULL, &supported);
308     fillIn("fr", "CA", NULL, NULL, &requested);
309     // Different languages don't match.
310     EXPECT_FALSE(supported.match(requested));
311 
312     fillIn("tl", "PH", NULL, NULL, &supported);
313     fillIn("fil", "PH", NULL, NULL, &requested);
314     // Equivalent languages match.
315     EXPECT_TRUE(supported.match(requested));
316 
317     fillIn("qaa", "FR", NULL, NULL, &supported);
318     fillIn("qaa", "CA", NULL, NULL, &requested);
319     // If we can't infer the scripts, different regions don't match.
320     EXPECT_FALSE(supported.match(requested));
321 
322     fillIn("qaa", "FR", "Latn", NULL, &supported);
323     fillIn("qaa", "CA", NULL, NULL, &requested);
324     // If we can't infer any of the scripts, different regions don't match.
325     EXPECT_FALSE(supported.match(requested));
326 
327     fillIn("qaa", "FR", NULL, NULL, &supported);
328     fillIn("qaa", "CA", "Latn", NULL, &requested);
329     // If we can't infer any of the scripts, different regions don't match.
330     EXPECT_FALSE(supported.match(requested));
331 
332     fillIn("qaa", NULL, NULL, NULL, &supported);
333     fillIn("qaa", "CA", NULL, NULL, &requested);
334     // language-only resources still support language+region requests, even if we can't infer the
335     // script.
336     EXPECT_TRUE(supported.match(requested));
337 
338     fillIn("qaa", "CA", NULL, NULL, &supported);
339     fillIn("qaa", "CA", NULL, NULL, &requested);
340     // Even if we can't infer the scripts, exactly equal locales match.
341     EXPECT_TRUE(supported.match(requested));
342 
343     fillIn("az", NULL, NULL, NULL, &supported);
344     fillIn("az", NULL, "Latn", NULL, &requested);
345     // If the resolved scripts are the same, it doesn't matter if they were explicitly provided
346     // or not, and they match.
347     EXPECT_TRUE(supported.match(requested));
348 
349     fillIn("az", NULL, NULL, NULL, &supported);
350     fillIn("az", NULL, "Cyrl", NULL, &requested);
351     // If the resolved scripts are different, they don't match.
352     EXPECT_FALSE(supported.match(requested));
353 
354     fillIn("az", NULL, NULL, NULL, &supported);
355     fillIn("az", "IR", NULL, NULL, &requested);
356     // If the resolved scripts are different, they don't match.
357     EXPECT_FALSE(supported.match(requested));
358 
359     fillIn("az", "IR", NULL, NULL, &supported);
360     fillIn("az", NULL, "Arab", NULL, &requested);
361     // If the resolved scripts are the same, it doesn't matter if they were explicitly provided
362     // or not, and they match.
363     EXPECT_TRUE(supported.match(requested));
364 
365     fillIn("en", NULL, NULL, NULL, &supported);
366     fillIn("en", "XA", NULL, NULL, &requested);
367     // en-XA is a pseudo-locale, and English resources are not a match for it.
368     EXPECT_FALSE(supported.match(requested));
369 
370     fillIn("en", "XA", NULL, NULL, &supported);
371     fillIn("en", NULL, NULL, NULL, &requested);
372     // en-XA is a pseudo-locale, and its resources don't support English locales.
373     EXPECT_FALSE(supported.match(requested));
374 
375     fillIn("en", "XA", NULL, NULL, &supported);
376     fillIn("en", "XA", NULL, NULL, &requested);
377     // Even if they are pseudo-locales, exactly equal locales match.
378     EXPECT_TRUE(supported.match(requested));
379 
380     fillIn("ar", NULL, NULL, NULL, &supported);
381     fillIn("ar", "XB", NULL, NULL, &requested);
382     // ar-XB is a pseudo-locale, and Arabic resources are not a match for it.
383     EXPECT_FALSE(supported.match(requested));
384 
385     fillIn("ar", "XB", NULL, NULL, &supported);
386     fillIn("ar", NULL, NULL, NULL, &requested);
387     // ar-XB is a pseudo-locale, and its resources don't support Arabic locales.
388     EXPECT_FALSE(supported.match(requested));
389 
390     fillIn("ar", "XB", NULL, NULL, &supported);
391     fillIn("ar", "XB", NULL, NULL, &requested);
392     // Even if they are pseudo-locales, exactly equal locales match.
393     EXPECT_TRUE(supported.match(requested));
394 }
395 
TEST(ConfigLocaleTest,match_emptyScript)396 TEST(ConfigLocaleTest, match_emptyScript) {
397     ResTable_config supported, requested;
398 
399     fillIn("fr", "FR", NULL, NULL, &supported);
400     fillIn("fr", "CA", NULL, NULL, &requested);
401 
402     // emulate packages built with older AAPT
403     memset(supported.localeScript, '\0', 4);
404     supported.localeScriptWasComputed = false;
405 
406     EXPECT_TRUE(supported.match(requested));
407 }
408 
TEST(ConfigLocaleTest,isLocaleBetterThan_basics)409 TEST(ConfigLocaleTest, isLocaleBetterThan_basics) {
410     ResTable_config config1, config2, request;
411 
412     fillIn(NULL, NULL, NULL, NULL, &request);
413     fillIn("fr", "FR", NULL, NULL, &config1);
414     fillIn("fr", "CA", NULL, NULL, &config2);
415     EXPECT_FALSE(config1.isLocaleBetterThan(config2, &request));
416     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
417 
418     fillIn("fr", "CA", NULL, NULL, &request);
419     fillIn(NULL, NULL, NULL, NULL, &config1);
420     fillIn(NULL, NULL, NULL, NULL, &config2);
421     EXPECT_FALSE(config1.isLocaleBetterThan(config2, &request));
422     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
423 
424     fillIn("fr", "CA", NULL, NULL, &request);
425     fillIn("fr", "FR", NULL, NULL, &config1);
426     fillIn(NULL, NULL, NULL, NULL, &config2);
427     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
428     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
429 
430     fillIn("de", "DE", NULL, NULL, &request);
431     fillIn("de", "DE", NULL, NULL, &config1);
432     fillIn("de", "DE", NULL, "1901", &config2);
433     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
434     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
435 
436     fillIn("de", "DE", NULL, NULL, &request);
437     fillIn("de", "DE", NULL, "1901", &config1);
438     fillIn("de", "DE", NULL, "1996", &config2);
439     EXPECT_FALSE(config1.isLocaleBetterThan(config2, &request));
440     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
441 
442     fillIn("de", "DE", NULL, "1901", &request);
443     fillIn("de", "DE", NULL, "1901", &config1);
444     fillIn("de", "DE", NULL, NULL, &config2);
445     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
446     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
447 
448     fillIn("de", "DE", NULL, "1901", &request);
449     fillIn("de", "DE", NULL, "1996", &config1);
450     fillIn("de", "DE", NULL, NULL, &config2);
451     EXPECT_FALSE(config1.isLocaleBetterThan(config2, &request));
452     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
453 
454     fillIn("fil", "PH", NULL, NULL, &request);
455     fillIn("tl", "PH", NULL, NULL, &config1);
456     fillIn("fil", "US", NULL, NULL, &config2);
457     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
458     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
459 
460     fillIn("fil", "PH", NULL, "fonipa", &request);
461     fillIn("tl", "PH", NULL, "fonipa", &config1);
462     fillIn("fil", "PH", NULL, NULL, &config2);
463     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
464     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
465 
466     fillIn("fil", "PH", NULL, NULL, &request);
467     fillIn("fil", "PH", NULL, NULL, &config1);
468     fillIn("tl", "PH", NULL, NULL, &config2);
469     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
470     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
471 }
472 
TEST(ConfigLocaleTest,isLocaleBetterThan_regionComparison)473 TEST(ConfigLocaleTest, isLocaleBetterThan_regionComparison) {
474     ResTable_config config1, config2, request;
475 
476     fillIn("es", "AR", NULL, NULL, &request);
477     fillIn("es", "419", NULL, NULL, &config1);
478     fillIn("es", "419", NULL, NULL, &config2);
479     // Both supported locales are the same, so none is better than the other.
480     EXPECT_FALSE(config1.isLocaleBetterThan(config2, &request));
481     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
482 
483     fillIn("es", "AR", NULL, NULL, &request);
484     fillIn("es", "AR", NULL, NULL, &config1);
485     fillIn("es", "419", NULL, NULL, &config2);
486     // An exact locale match is better than a parent.
487     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
488     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
489 
490     fillIn("es", "AR", NULL, NULL, &request);
491     fillIn("es", "419", NULL, NULL, &config1);
492     fillIn("es", NULL, NULL, NULL, &config2);
493     // A closer parent is better.
494     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
495     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
496 
497     fillIn("es", "AR", NULL, NULL, &request);
498     fillIn("es", "419", NULL, NULL, &config1);
499     fillIn("es", "ES", NULL, NULL, &config2);
500     // A parent is better than a non-parent representative locale.
501     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
502     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
503 
504     fillIn("es", "AR", NULL, NULL, &request);
505     fillIn("es", NULL, NULL, NULL, &config1);
506     fillIn("es", "ES", NULL, NULL, &config2);
507     // A parent is better than a non-parent representative locale.
508     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
509     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
510 
511     fillIn("es", "AR", NULL, NULL, &request);
512     fillIn("es", "PE", NULL, NULL, &config1);
513     fillIn("es", "ES", NULL, NULL, &config2);
514     // A closer locale is better.
515     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
516     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
517 
518     fillIn("es", "AR", NULL, NULL, &request);
519     fillIn("es", "US", NULL, NULL, &config1);
520     fillIn("es", NULL, NULL, NULL, &config2);
521     // Special case for Latin American Spanish: es-MX and es-US are
522     // pseudo-parents of all Latin Ameircan Spanish locales.
523     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
524     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
525 
526     fillIn("es", "MX", NULL, NULL, &request);
527     fillIn("es", "US", NULL, NULL, &config1);
528     fillIn("es", NULL, NULL, NULL, &config2);
529     // Special case for Latin American Spanish: es-MX and es-US are
530     // pseudo-parents of all Latin Ameircan Spanish locales.
531     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
532     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
533 
534     fillIn("es", "AR", NULL, NULL, &request);
535     fillIn("es", "MX", NULL, NULL, &config1);
536     fillIn("es", NULL, NULL, NULL, &config2);
537     // Special case for Latin American Spanish: es-MX and es-US are
538     // pseudo-parents of all Latin Ameircan Spanish locales.
539     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
540     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
541 
542     fillIn("es", "US", NULL, NULL, &request);
543     fillIn("es", "MX", NULL, NULL, &config1);
544     fillIn("es", NULL, NULL, NULL, &config2);
545     // Special case for Latin American Spanish: es-MX and es-US are
546     // pseudo-parents of all Latin Ameircan Spanish locales.
547     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
548     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
549 
550     fillIn("es", "AR", NULL, NULL, &request);
551     fillIn("es", "419", NULL, NULL, &config1);
552     fillIn("es", "MX", NULL, NULL, &config2);
553     // Even though es-MX and es-US are pseudo-parents of all Latin Ameircan
554     // Spanish locales, es-419 is a closer parent.
555     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
556     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
557 
558     fillIn("es", "US", NULL, NULL, &request);
559     fillIn("es", "419", NULL, NULL, &config1);
560     fillIn("es", "MX", NULL, NULL, &config2);
561     // Even though es-MX and es-US are pseudo-parents of all Latin Ameircan
562     // Spanish locales, es-419 is a closer parent.
563     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
564     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
565 
566     fillIn("es", "MX", NULL, NULL, &request);
567     fillIn("es", "419", NULL, NULL, &config1);
568     fillIn("es", "US", NULL, NULL, &config2);
569     // Even though es-MX and es-US are pseudo-parents of all Latin Ameircan
570     // Spanish locales, es-419 is a closer parent.
571     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
572     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
573 
574     fillIn("es", "AR", NULL, NULL, &request);
575     fillIn("es", "MX", NULL, NULL, &config1);
576     fillIn("es", "BO", NULL, NULL, &config2);
577     // Special case for Latin American Spanish: es-MX and es-US are
578     // pseudo-parents of all Latin Ameircan Spanish locales.
579     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
580     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
581 
582     fillIn("es", "AR", NULL, NULL, &request);
583     fillIn("es", "US", NULL, NULL, &config1);
584     fillIn("es", "BO", NULL, NULL, &config2);
585     // Special case for Latin American Spanish: es-MX and es-US are
586     // pseudo-parents of all Latin Ameircan Spanish locales.
587     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
588     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
589 
590     fillIn("es", "IC", NULL, NULL, &request);
591     fillIn("es", "ES", NULL, NULL, &config1);
592     fillIn("es", "GQ", NULL, NULL, &config2);
593     // A representative locale is better if they are equidistant.
594     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
595     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
596 
597     fillIn("es", "AR", NULL, NULL, &request);
598     fillIn("es", "MX", NULL, NULL, &config1);
599     fillIn("es", "US", NULL, NULL, &config2);
600     // If all is equal, the locale earlier in the dictionary is better.
601     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
602     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
603 
604     fillIn("es", "GQ", NULL, NULL, &request);
605     fillIn("es", "IC", NULL, NULL, &config1);
606     fillIn("es", "419", NULL, NULL, &config2);
607     // If all is equal, the locale earlier in the dictionary is better and
608     // letters are better than numbers.
609     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
610     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
611 
612     fillIn("en", "GB", NULL, NULL, &request);
613     fillIn("en", "001", NULL, NULL, &config1);
614     fillIn("en", NULL, NULL, NULL, &config2);
615     // A closer parent is better.
616     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
617     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
618 
619     fillIn("en", "PR", NULL, NULL, &request);
620     fillIn("en", NULL, NULL, NULL, &config1);
621     fillIn("en", "001", NULL, NULL, &config2);
622     // A parent is better than a non-parent.
623     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
624     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
625 
626     fillIn("en", "DE", NULL, NULL, &request);
627     fillIn("en", "150", NULL, NULL, &config1);
628     fillIn("en", "001", NULL, NULL, &config2);
629     // A closer parent is better.
630     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
631     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
632 
633     fillIn("en", "IN", NULL, NULL, &request);
634     fillIn("en", "AU", NULL, NULL, &config1);
635     fillIn("en", "US", NULL, NULL, &config2);
636     // A closer locale is better.
637     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
638     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
639 
640     fillIn("en", "PR", NULL, NULL, &request);
641     fillIn("en", "001", NULL, NULL, &config1);
642     fillIn("en", "GB", NULL, NULL, &config2);
643     // A closer locale is better.
644     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
645     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
646 
647     fillIn("en", "IN", NULL, NULL, &request);
648     fillIn("en", "GB", NULL, NULL, &config1);
649     fillIn("en", "AU", NULL, NULL, &config2);
650     // A representative locale is better if they are equidistant.
651     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
652     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
653 
654     fillIn("en", "IN", NULL, NULL, &request);
655     fillIn("en", "AU", NULL, NULL, &config1);
656     fillIn("en", "CA", NULL, NULL, &config2);
657     // If all is equal, the locale earlier in the dictionary is better.
658     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
659     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
660 
661     fillIn("pt", "MZ", NULL, NULL, &request);
662     fillIn("pt", "PT", NULL, NULL, &config1);
663     fillIn("pt", NULL, NULL, NULL, &config2);
664     // A closer parent is better.
665     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
666     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
667 
668     fillIn("pt", "MZ", NULL, NULL, &request);
669     fillIn("pt", "PT", NULL, NULL, &config1);
670     fillIn("pt", "BR", NULL, NULL, &config2);
671     // A parent is better than a non-parent.
672     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
673     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
674 
675     fillIn("zh", "MO", "Hant", NULL, &request);
676     fillIn("zh", "HK", "Hant", NULL, &config1);
677     fillIn("zh", "TW", "Hant", NULL, &config2);
678     // A parent is better than a non-parent.
679     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
680     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
681 
682     fillIn("zh", "US", "Hant", NULL, &request);
683     fillIn("zh", "TW", "Hant", NULL, &config1);
684     fillIn("zh", "HK", "Hant", NULL, &config2);
685     // A representative locale is better if they are equidistant.
686     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
687     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
688 
689     fillIn("ar", "DZ", NULL, NULL, &request);
690     fillIn("ar", "015", NULL, NULL, &config1);
691     fillIn("ar", NULL, NULL, NULL, &config2);
692     // A closer parent is better.
693     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
694     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
695 
696     fillIn("ar", "EG", NULL, NULL, &request);
697     fillIn("ar", NULL, NULL, NULL, &config1);
698     fillIn("ar", "015", NULL, NULL, &config2);
699     // A parent is better than a non-parent.
700     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
701     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
702 
703     fillIn("ar", "QA", NULL, NULL, &request);
704     fillIn("ar", "EG", NULL, NULL, &config1);
705     fillIn("ar", "BH", NULL, NULL, &config2);
706     // A representative locale is better if they are equidistant.
707     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
708     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
709 
710     fillIn("ar", "QA", NULL, NULL, &request);
711     fillIn("ar", "SA", NULL, NULL, &config1);
712     fillIn("ar", "015", NULL, NULL, &config2);
713     // If all is equal, the locale earlier in the dictionary is better and
714     // letters are better than numbers.
715     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
716     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
717 }
718 
719 // Default resources are considered better matches for US English
720 // and US-like English locales than International English locales
TEST(ConfigLocaleTest,isLocaleBetterThan_UsEnglishIsSpecial)721 TEST(ConfigLocaleTest, isLocaleBetterThan_UsEnglishIsSpecial) {
722     ResTable_config config1, config2, request;
723 
724     fillIn("en", "US", NULL, NULL, &request);
725     fillIn(NULL, NULL, NULL, NULL, &config1);
726     fillIn("en", "001", NULL, NULL, &config2);
727     // default is better than International English
728     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
729     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
730 
731     fillIn("en", "US", NULL, NULL, &request);
732     fillIn(NULL, NULL, NULL, NULL, &config1);
733     fillIn("en", "GB", NULL, NULL, &config2);
734     // default is better than British English
735     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
736     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
737 
738     fillIn("en", "PR", NULL, NULL, &request);
739     fillIn(NULL, NULL, NULL, NULL, &config1);
740     fillIn("en", "001", NULL, NULL, &config2);
741     // Even for Puerto Rico, default is better than International English
742     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
743     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
744 
745     fillIn("en", "US", NULL, NULL, &request);
746     fillIn("en", NULL, NULL, NULL, &config1);
747     fillIn(NULL, NULL, NULL, NULL, &config2);
748     // "English" is better than default, since it's a parent of US English
749     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
750     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
751 
752     fillIn("en", "PR", NULL, NULL, &request);
753     fillIn("en", NULL, NULL, NULL, &config1);
754     fillIn(NULL, NULL, NULL, NULL, &config2);
755     // "English" is better than default, since it's a parent of Puerto Rico English
756     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
757     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
758 
759     fillIn("en", "US", NULL, NULL, &request);
760     fillIn(NULL, NULL, NULL, NULL, &config1);
761     fillIn("en", "PR", NULL, NULL, &config2);
762     // For US English itself, we prefer default to its siblings in the parent tree
763     EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
764     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
765 }
766 
767 }  // namespace android
768