• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 package com.android.providers.contacts;
18 
19 import android.provider.ContactsContract.FullNameStyle;
20 import android.test.AndroidTestCase;
21 import android.test.suitebuilder.annotation.SmallTest;
22 import android.util.Log;
23 
24 import java.text.Collator;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Locale;
31 
32 @SmallTest
33 public class ContactLocaleUtilsTest extends AndroidTestCase {
34     private static final String TAG = "ContactLocaleUtilsTest";
35 
36     private static final String PHONE_NUMBER_1 = "+1 (650) 555-1212";
37     private static final String PHONE_NUMBER_2 = "650-555-1212";
38     private static final String LATIN_NAME = "John Smith";
39     private static final String LATIN_NAME_2 = "John Paul Jones";
40     private static final String KANJI_NAME = "\u65e5"; // 日
41     private static final String ARABIC_NAME = "\u0646\u0648\u0631"; /* Noor نور */
42     private static final String CHINESE_NAME = "\u675C\u9D51"; // 杜鵑
43     private static final String SERBIAN_NAME = "\u0408\u0435\u043B\u0435\u043D\u0430"; // Јелена
44     private static final String UKRAINIAN_NAME = "\u0406"; // І
45     private static final String UKRAINIAN_NAME_2 = "\u0407"; // Ї
46     private static final String UKRAINIAN_NAME_3 = "\u0490"; // Ґ
47     private static final String CHINESE_LATIN_MIX_NAME_1 = "D\u675C\u9D51"; // D杜鵑
48     private static final String CHINESE_LATIN_MIX_NAME_2 = "MARY \u675C\u9D51"; // MARY 杜鵑
49     private static final String[] CHINESE_NAME_KEY = {
50             "\u9D51",// 鵑
51             "\u675C\u9D51", // 杜鵑
52             "JUAN", "DUJUAN", "J", "DJ"};
53     private static final String[] CHINESE_LATIN_MIX_NAME_1_KEY = {
54             "\u9D51", // 鵑
55             "\u675C\u9D51", // 杜鵑
56             "D \u675C\u9D51", // D 杜鵑
57             "JUAN", "DUJUAN", "J", "DJ", "D DUJUAN", "DDJ"};
58     private static final String[] CHINESE_LATIN_MIX_NAME_2_KEY = {
59             "\u9D51", // 鵑
60             "\u675C\u9D51", // 杜鵑
61             "MARY \u675C\u9D51", // MARY 杜鵑
62             "JUAN", "DUJUAN", "MARY DUJUAN", "J", "DJ", "MDJ"};
63     private static final String[] LATIN_NAME_KEY = {"John Smith", "Smith", "JS", "S"};
64     private static final String[] LATIN_NAME_KEY_2 = {
65             "John Paul Jones", "Paul Jones", "Jones", "JPJ", "PJ", "J"};
66     private static final String[] LABELS_EN_US = {
67             "\u2026", // …
68             "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
69             "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
70             "#", ""};
71     private static final String[] LABELS_JA_JP = {
72         "…", "\u3042", "\u304B", "\u3055", "\u305F", "\u306A", "\u306F",
73         "\u307E", "\u3084", "\u3089", "\u308F", "\u4ED6",
74         "…", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
75         "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
76         "#", ""};
77     private static final String[] LABELS_ZH_TW = {
78         "…", "1\u5283", "2\u5283", "3\u5283", "4\u5283", "5\u5283", "6\u5283",
79         "7\u5283", "8\u5283", "9\u5283", "10\u5283", "11\u5283", "12\u5283",
80         "13\u5283", "14\u5283", "15\u5283", "16\u5283", "17\u5283", "18\u5283",
81         "19\u5283", "20\u5283", "21\u5283", "22\u5283", "23\u5283", "24\u5283",
82         "25\u5283", "26\u5283", "27\u5283", "28\u5283", "29\u5283", "30\u5283",
83         "31\u5283", "32\u5283", "33\u5283",
84         "35\u5283", "36\u5283", "39\u5283", "48\u5283",
85         "…", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
86         "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
87         "#", ""};
88     private static final String[] LABELS_KO = {
89         "…", "\u3131", "\u3134", "\u3137", "\u3139", "\u3141", "\u3142",
90         "\u3145", "\u3147", "\u3148", "\u314A", "\u314B", "\u314C", "\u314D",
91         "\u314E", "…",
92         "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
93         "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
94         "#", ""};
95     private static final String[] LABELS_AR = {
96         "\u2026", "\u0627", "\u0628", "\u062a", "\u062b", "\u062c", "\u062d",
97         "\u062e", "\u062f", "\u0630", "\u0631", "\u0632", "\u0633", "\u0634",
98         "\u0635", "\u0636", "\u0637", "\u0638", "\u0639", "\u063a", "\u0641",
99         "\u0642", "\u0643", "\u0644", "\u0645", "\u0646", "\u0647", "\u0648",
100         "\u064a",
101         "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
102         "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
103         "#", ""};
104 
105     private static final String JAPANESE_MISC = "\u4ed6"; // 他
106 
107     private static final Locale LOCALE_ARABIC = new Locale("ar");
108     private static final Locale LOCALE_SERBIAN = new Locale("sr");
109     private static final Locale LOCALE_UKRAINIAN = new Locale("uk");
110     private static final Locale LOCALE_SPANISH = new Locale("es");
111     private static final Locale LOCALE_GREEK = new Locale("el");
112 
113     private ContactLocaleUtils mTargetUtils;
114 
setLocales(Locale... locales)115     private void setLocales(Locale... locales) {
116         mTargetUtils = ContactLocaleUtils.newInstanceForTest(locales);
117     }
118 
getLabel(String name)119     private String getLabel(String name) {
120         int bucketIndex = mTargetUtils.getBucketIndex(name);
121         return mTargetUtils.getBucketLabel(bucketIndex);
122     }
123 
getNameLookupKeys(String name, int nameStyle)124     private Iterator<String> getNameLookupKeys(String name, int nameStyle) {
125         return mTargetUtils.getNameLookupKeys(name, nameStyle);
126     }
127 
getLabels()128     private ArrayList<String> getLabels() {
129         return mTargetUtils.getLabels();
130     }
131 
testEnglishContactLocaleUtils()132     public void testEnglishContactLocaleUtils() throws Exception {
133         setLocales(Locale.ENGLISH);
134         assertEquals("#", getLabel(PHONE_NUMBER_1));
135         assertEquals("#", getLabel(PHONE_NUMBER_2));
136         assertEquals("J", getLabel(LATIN_NAME));
137         assertEquals("\u2026", getLabel(CHINESE_NAME));
138         assertEquals("D", getLabel(CHINESE_LATIN_MIX_NAME_1));
139         assertEquals("B", getLabel("Bob Smith"));
140 
141         assertEquals("\u0646", getLabel(ARABIC_NAME));
142         assertEquals("\u0408", getLabel(SERBIAN_NAME));
143         // Updated in CLDR 27/ICU 55:
144         // http://cldr.unicode.org/index/downloads/cldr-27#TOC-Changes-to-Collation
145         assertEquals("\u0406", getLabel(UKRAINIAN_NAME));
146 
147         assertNull(getNameLookupKeys(LATIN_NAME, FullNameStyle.UNDEFINED));
148         verifyLabels(getLabels(), LABELS_EN_US);
149     }
150 
testJapaneseContactLocaleUtils()151     public void testJapaneseContactLocaleUtils() throws Exception {
152         setLocales(Locale.JAPAN);
153         assertEquals("#", getLabel(PHONE_NUMBER_1));
154         assertEquals("#", getLabel(PHONE_NUMBER_2));
155         assertEquals(JAPANESE_MISC, getLabel(KANJI_NAME));
156         assertEquals("J", getLabel(LATIN_NAME));
157         assertEquals(JAPANESE_MISC, getLabel(CHINESE_NAME));
158         assertEquals("D", getLabel(CHINESE_LATIN_MIX_NAME_1));
159 
160         assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CJK));
161         assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CHINESE));
162 
163         assertEquals("B", getLabel("Bob Smith"));
164         verifyLabels(getLabels(), LABELS_JA_JP);
165     }
166 
testChineseContactLocaleUtils()167     public void testChineseContactLocaleUtils() throws Exception {
168         setLocales(Locale.SIMPLIFIED_CHINESE);
169         assertEquals("#", getLabel(PHONE_NUMBER_1));
170         assertEquals("#", getLabel(PHONE_NUMBER_2));
171         assertEquals("J", getLabel(LATIN_NAME));
172         assertEquals("D", getLabel(CHINESE_NAME));
173         assertEquals("D", getLabel(CHINESE_LATIN_MIX_NAME_1));
174         assertEquals("B", getLabel("Bob Smith"));
175         verifyLabels(getLabels(), LABELS_EN_US);
176 
177         setLocales(Locale.TRADITIONAL_CHINESE);
178         assertEquals("#", getLabel(PHONE_NUMBER_1));
179         assertEquals("#", getLabel(PHONE_NUMBER_2));
180         assertEquals("J", getLabel(LATIN_NAME));
181         assertEquals("7\u5283", getLabel(CHINESE_NAME));
182         assertEquals("D", getLabel(CHINESE_LATIN_MIX_NAME_1));
183 
184         setLocales(Locale.SIMPLIFIED_CHINESE);
185         Iterator<String> keys = getNameLookupKeys(CHINESE_NAME,
186                 FullNameStyle.CHINESE);
187         verifyKeys(keys, CHINESE_NAME_KEY);
188 
189         keys = getNameLookupKeys(CHINESE_LATIN_MIX_NAME_1, FullNameStyle.CHINESE);
190         verifyKeys(keys, CHINESE_LATIN_MIX_NAME_1_KEY);
191 
192         keys = getNameLookupKeys(CHINESE_LATIN_MIX_NAME_2, FullNameStyle.CHINESE);
193         verifyKeys(keys, CHINESE_LATIN_MIX_NAME_2_KEY);
194 
195         setLocales(Locale.TRADITIONAL_CHINESE);
196         assertEquals("B", getLabel("Bob Smith"));
197         verifyLabels(getLabels(), LABELS_ZH_TW);
198     }
199 
testPinyinEnabledSecondaryLocale()200     public void testPinyinEnabledSecondaryLocale() throws Exception {
201         setLocales(Locale.ENGLISH, Locale.SIMPLIFIED_CHINESE);
202         assertEquals("D", getLabel(CHINESE_NAME));
203 
204         Iterator<String> keys = getNameLookupKeys(CHINESE_NAME,
205                 FullNameStyle.CHINESE);
206         verifyKeys(keys, CHINESE_NAME_KEY);
207     }
208 
testPinyinDisabledSecondaryLocale()209     public void testPinyinDisabledSecondaryLocale() throws Exception {
210         setLocales(Locale.ENGLISH, Locale.JAPAN);
211         assertEquals(JAPANESE_MISC, getLabel(CHINESE_NAME));
212 
213         assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CHINESE));
214         assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CJK));
215     }
216 
testChineseChinese()217     public void testChineseChinese() throws Exception {
218         setLocales(Locale.SIMPLIFIED_CHINESE, Locale.TRADITIONAL_CHINESE);
219         assertEquals("D", getLabel(CHINESE_NAME)); // Prefer pinyin
220 
221         setLocales(Locale.TRADITIONAL_CHINESE, Locale.SIMPLIFIED_CHINESE);
222         assertEquals("7\u5283", getLabel(CHINESE_NAME)); // 7劃 -- Prefer # of strokes
223     }
224 
testJapaneseChinese()225     public void testJapaneseChinese() throws Exception {
226         setLocales(Locale.JAPAN, Locale.TRADITIONAL_CHINESE);
227         assertEquals(JAPANESE_MISC, getLabel(CHINESE_NAME)); // Prefer Japanese
228 
229         setLocales(Locale.JAPAN, Locale.SIMPLIFIED_CHINESE);
230         assertEquals(JAPANESE_MISC, getLabel(CHINESE_NAME)); // Prefer Japanese
231     }
232 
testChineseStyleNameWithDifferentLocale()233     public void testChineseStyleNameWithDifferentLocale() throws Exception {
234         setLocales(Locale.ENGLISH);
235         assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CHINESE));
236         assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CJK));
237 
238         setLocales(Locale.SIMPLIFIED_CHINESE);
239         Iterator<String> keys = getNameLookupKeys(CHINESE_NAME,
240                 FullNameStyle.CJK);
241         verifyKeys(keys, CHINESE_NAME_KEY);
242         keys = getNameLookupKeys(LATIN_NAME, FullNameStyle.WESTERN);
243         verifyKeys(keys, LATIN_NAME_KEY);
244         keys = getNameLookupKeys(LATIN_NAME_2, FullNameStyle.WESTERN);
245         verifyKeys(keys, LATIN_NAME_KEY_2);
246 
247         setLocales(Locale.TRADITIONAL_CHINESE);
248         assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CJK));
249     }
250 
testKoreanContactLocaleUtils()251     public void testKoreanContactLocaleUtils() throws Exception {
252         setLocales(Locale.KOREA);
253         assertEquals("\u3131", getLabel("\u1100"));
254         assertEquals("\u3131", getLabel("\u3131"));
255         assertEquals("\u3131", getLabel("\u1101"));
256         assertEquals("\u314e", getLabel("\u1161"));
257         assertEquals("B", getLabel("Bob Smith"));
258         verifyLabels(getLabels(), LABELS_KO);
259     }
260 
testArabicContactLocaleUtils()261     public void testArabicContactLocaleUtils() throws Exception {
262         setLocales(LOCALE_ARABIC);
263         assertEquals("\u0646", getLabel(ARABIC_NAME));
264         assertEquals("B", getLabel("Bob Smith"));
265         verifyLabels(getLabels(), LABELS_AR);
266     }
267 
testSerbianContactLocaleUtils()268     public void testSerbianContactLocaleUtils() throws Exception {
269         setLocales(LOCALE_SERBIAN);
270         assertEquals("\u0408", getLabel(SERBIAN_NAME));
271         assertEquals("B", getLabel("Bob Smith"));
272     }
273 
testUkrainianContactLocaleUtils()274     public void testUkrainianContactLocaleUtils() throws Exception {
275         setLocales(LOCALE_UKRAINIAN);
276         assertEquals("\u0406", getLabel(UKRAINIAN_NAME));
277         assertEquals("\u0407", getLabel(UKRAINIAN_NAME_2));
278         assertEquals("\u0490", getLabel(UKRAINIAN_NAME_3));
279         assertEquals("B", getLabel("Bob Smith"));
280     }
281 
testGermanContactLocaleUtils()282     public void testGermanContactLocaleUtils() throws Exception {
283         setLocales(Locale.GERMANY);
284         assertEquals("S", getLabel("Sacher"));
285 
286         // ICU 51 has labels Sch and St. These were removed in ICU 52
287         assertEquals("S", getLabel("Schiller"));
288         assertEquals("S", getLabel("Steiff"));
289         verifyLabels(getLabels(), LABELS_EN_US);
290     }
291 
testOtherLocales()292     public void testOtherLocales() throws Exception {
293         setLocales(Locale.ENGLISH);
294 
295         assertEquals("N", getLabel("n"));
296         assertEquals("N", getLabel("ñ"));
297 
298         setLocales(LOCALE_SPANISH);
299 
300         assertEquals("N", getLabel("n"));
301         assertEquals("Ñ", getLabel("ñ"));
302 
303         setLocales(Locale.ENGLISH, LOCALE_SPANISH);
304 
305         assertEquals("N", getLabel("n"));
306         assertEquals("N", getLabel("ñ")); // TODO This should ideally return Ñ.
307 
308     }
309 
verifyKeys(final Iterator<String> resultKeys, final String[] expectedKeys)310     private void verifyKeys(final Iterator<String> resultKeys, final String[] expectedKeys)
311             throws Exception {
312         HashSet<String> allKeys = new HashSet<String>();
313         while (resultKeys.hasNext()) {
314             allKeys.add(resultKeys.next());
315         }
316         assertEquals(new HashSet<String>(Arrays.asList(expectedKeys)), allKeys);
317     }
318 
319     // Verify that the initial set of resultLabels matches the expectedLabels.
320     // Ignore the (large) number of secondary locale labels that make up the
321     // tail labels in the result set right before the final "#" and "" buckets.
verifyLabels(final ArrayList<String> resultLabels, final String[] expectedLabels)322     private void verifyLabels(final ArrayList<String> resultLabels,
323             final String[] expectedLabels) throws Exception {
324         final List<String> expectedLabelList = Arrays.asList(expectedLabels);
325         final int numLabels = expectedLabelList.size() - 2;
326         assertEquals(expectedLabelList.subList(0, numLabels),
327                 resultLabels.subList(0, numLabels));
328     }
329 }
330