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/ResourceTypes.h>
18 #include <utils/Log.h>
19 #include <utils/String8.h>
20 
21 #include <gtest/gtest.h>
22 namespace android {
23 
TEST(ConfigLocaleTest,packAndUnpack2LetterLanguage)24 TEST(ConfigLocaleTest, packAndUnpack2LetterLanguage) {
25      ResTable_config config;
26      config.packLanguage("en");
27 
28      EXPECT_EQ('e', config.language[0]);
29      EXPECT_EQ('n', config.language[1]);
30 
31      char out[4] = { 1, 1, 1, 1};
32      config.unpackLanguage(out);
33      EXPECT_EQ('e', out[0]);
34      EXPECT_EQ('n', out[1]);
35      EXPECT_EQ(0, out[2]);
36      EXPECT_EQ(0, out[3]);
37 
38      memset(out, 1, sizeof(out));
39      config.locale = 0;
40      config.unpackLanguage(out);
41      EXPECT_EQ(0, out[0]);
42      EXPECT_EQ(0, out[1]);
43      EXPECT_EQ(0, out[2]);
44      EXPECT_EQ(0, out[3]);
45 }
46 
TEST(ConfigLocaleTest,packAndUnpack2LetterRegion)47 TEST(ConfigLocaleTest, packAndUnpack2LetterRegion) {
48      ResTable_config config;
49      config.packRegion("US");
50 
51      EXPECT_EQ('U', config.country[0]);
52      EXPECT_EQ('S', config.country[1]);
53 
54      char out[4] = { 1, 1, 1, 1};
55      config.unpackRegion(out);
56      EXPECT_EQ('U', out[0]);
57      EXPECT_EQ('S', out[1]);
58      EXPECT_EQ(0, out[2]);
59      EXPECT_EQ(0, out[3]);
60 }
61 
TEST(ConfigLocaleTest,packAndUnpack3LetterLanguage)62 TEST(ConfigLocaleTest, packAndUnpack3LetterLanguage) {
63      ResTable_config config;
64      config.packLanguage("eng");
65 
66      // 1-00110-01 101-00100
67      EXPECT_EQ('\x99', config.language[0]);
68      EXPECT_EQ('\xA4', config.language[1]);
69 
70      char out[4] = { 1, 1, 1, 1};
71      config.unpackLanguage(out);
72      EXPECT_EQ('e', out[0]);
73      EXPECT_EQ('n', out[1]);
74      EXPECT_EQ('g', out[2]);
75      EXPECT_EQ(0, out[3]);
76 }
77 
TEST(ConfigLocaleTest,packAndUnpack3LetterLanguageAtOffset16)78 TEST(ConfigLocaleTest, packAndUnpack3LetterLanguageAtOffset16) {
79      ResTable_config config;
80      config.packLanguage("tgp");
81 
82      // We had a bug where we would accidentally mask
83      // the 5th bit of both bytes
84      //
85      // packed[0] = 1011 1100
86      // packed[1] = 1101 0011
87      //
88      // which is equivalent to:
89      // 1  [0]   [1]   [2]
90      // 1-01111-00110-10011
91      EXPECT_EQ(char(0xbc), config.language[0]);
92      EXPECT_EQ(char(0xd3), config.language[1]);
93 
94      char out[4] = { 1, 1, 1, 1};
95      config.unpackLanguage(out);
96      EXPECT_EQ('t', out[0]);
97      EXPECT_EQ('g', out[1]);
98      EXPECT_EQ('p', out[2]);
99      EXPECT_EQ(0, out[3]);
100 }
101 
TEST(ConfigLocaleTest,packAndUnpack3LetterRegion)102 TEST(ConfigLocaleTest, packAndUnpack3LetterRegion) {
103      ResTable_config config;
104      config.packRegion("419");
105 
106      char out[4] = { 1, 1, 1, 1};
107      config.unpackRegion(out);
108 
109      EXPECT_EQ('4', out[0]);
110      EXPECT_EQ('1', out[1]);
111      EXPECT_EQ('9', out[2]);
112 }
113 
fillIn(const char * lang,const char * country,const char * script,const char * variant,ResTable_config * out)114 /* static */ void fillIn(const char* lang, const char* country,
115         const char* script, const char* variant, ResTable_config* out) {
116      memset(out, 0, sizeof(ResTable_config));
117      if (lang != NULL) {
118          out->packLanguage(lang);
119      }
120 
121      if (country != NULL) {
122          out->packRegion(country);
123      }
124 
125      if (script != NULL) {
126          memcpy(out->localeScript, script, 4);
127      }
128 
129      if (variant != NULL) {
130          memcpy(out->localeVariant, variant, strlen(variant));
131      }
132 }
133 
TEST(ConfigLocaleTest,IsMoreSpecificThan)134 TEST(ConfigLocaleTest, IsMoreSpecificThan) {
135     ResTable_config l;
136     ResTable_config r;
137 
138     fillIn("en", NULL, NULL, NULL, &l);
139     fillIn(NULL, NULL, NULL, NULL, &r);
140 
141     EXPECT_TRUE(l.isMoreSpecificThan(r));
142     EXPECT_FALSE(r.isMoreSpecificThan(l));
143 
144     fillIn("eng", NULL, NULL, NULL, &l);
145     EXPECT_TRUE(l.isMoreSpecificThan(r));
146     EXPECT_FALSE(r.isMoreSpecificThan(l));
147 
148     fillIn("eng", "419", NULL, NULL, &r);
149     EXPECT_FALSE(l.isMoreSpecificThan(r));
150     EXPECT_TRUE(r.isMoreSpecificThan(l));
151 
152     fillIn("en", NULL, NULL, NULL, &l);
153     fillIn("en", "US", NULL, NULL, &r);
154     EXPECT_FALSE(l.isMoreSpecificThan(r));
155     EXPECT_TRUE(r.isMoreSpecificThan(l));
156 
157     fillIn("en", "US", NULL, NULL, &l);
158     fillIn("en", "US", "Latn", 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", NULL, "POSIX", &r);
164     EXPECT_FALSE(l.isMoreSpecificThan(r));
165     EXPECT_TRUE(r.isMoreSpecificThan(l));
166 
167     fillIn("en", "US", "Latn", NULL, &l);
168     fillIn("en", "US", NULL, "POSIX", &r);
169     EXPECT_FALSE(l.isMoreSpecificThan(r));
170     EXPECT_TRUE(r.isMoreSpecificThan(l));
171 }
172 
TEST(ConfigLocaleTest,setLocale)173 TEST(ConfigLocaleTest, setLocale) {
174     ResTable_config test;
175     test.setBcp47Locale("en-US");
176     EXPECT_EQ('e', test.language[0]);
177     EXPECT_EQ('n', test.language[1]);
178     EXPECT_EQ('U', test.country[0]);
179     EXPECT_EQ('S', test.country[1]);
180     EXPECT_EQ(0, test.localeScript[0]);
181     EXPECT_EQ(0, test.localeVariant[0]);
182 
183     test.setBcp47Locale("eng-419");
184     char out[4] = { 1, 1, 1, 1};
185     test.unpackLanguage(out);
186     EXPECT_EQ('e', out[0]);
187     EXPECT_EQ('n', out[1]);
188     EXPECT_EQ('g', out[2]);
189     EXPECT_EQ(0, out[3]);
190     memset(out, 1, 4);
191     test.unpackRegion(out);
192     EXPECT_EQ('4', out[0]);
193     EXPECT_EQ('1', out[1]);
194     EXPECT_EQ('9', out[2]);
195 
196 
197     test.setBcp47Locale("en-Latn-419");
198     memset(out, 1, 4);
199     EXPECT_EQ('e', test.language[0]);
200     EXPECT_EQ('n', test.language[1]);
201 
202     EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
203     test.unpackRegion(out);
204     EXPECT_EQ('4', out[0]);
205     EXPECT_EQ('1', out[1]);
206     EXPECT_EQ('9', out[2]);
207 }
208 
209 }  // namespace android.
210