blob: 1913a2ddb1c6e739f1e28164bfb99f02569c02b4 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.providers.contacts;
import android.provider.ContactsContract.FullNameStyle;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
@SmallTest
public class ContactLocaleUtilsTest extends AndroidTestCase {
private static final String TAG = "ContactLocaleUtilsTest";
private static final String PHONE_NUMBER_1 = "+1 (650) 555-1212";
private static final String PHONE_NUMBER_2 = "650-555-1212";
private static final String LATIN_NAME = "John Smith";
private static final String LATIN_NAME_2 = "John Paul Jones";
private static final String KANJI_NAME = "\u65e5";
private static final String ARABIC_NAME = "\u0646\u0648\u0631"; /* Noor */
private static final String CHINESE_NAME = "\u675C\u9D51";
private static final String SERBIAN_NAME = "\u0408\u0435\u043B\u0435\u043D\u0430";
private static final String UKRAINIAN_NAME = "\u0406";
private static final String UKRAINIAN_NAME_2 = "\u0407";
private static final String UKRAINIAN_NAME_3 = "\u0490";
private static final String CHINESE_LATIN_MIX_NAME_1 = "D\u675C\u9D51";
private static final String CHINESE_LATIN_MIX_NAME_2 = "MARY \u675C\u9D51";
private static final String[] CHINESE_NAME_KEY = {"\u9D51", "\u675C\u9D51", "JUAN", "DUJUAN",
"J", "DJ"};
private static final String[] CHINESE_LATIN_MIX_NAME_1_KEY = {"\u9D51", "\u675C\u9D51",
"D \u675C\u9D51", "JUAN", "DUJUAN", "J", "DJ", "D DUJUAN", "DDJ"};
private static final String[] CHINESE_LATIN_MIX_NAME_2_KEY = {"\u9D51", "\u675C\u9D51",
"MARY \u675C\u9D51", "JUAN", "DUJUAN", "MARY DUJUAN", "J", "DJ", "MDJ"};
private static final String[] LATIN_NAME_KEY = {"John Smith", "Smith", "JS", "S"};
private static final String[] LATIN_NAME_KEY_2 = {
"John Paul Jones", "Paul Jones", "Jones", "JPJ", "PJ", "J"};
private static final String[] LABELS_EN_US = {
"\u2026", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
"#", ""};
private static final String[] LABELS_JA_JP = {
"", "\u3042", "\u304B", "\u3055", "\u305F", "\u306A", "\u306F",
"\u307E", "\u3084", "\u3089", "\u308F", "\u4ED6",
"", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
"#", ""};
private static final String[] LABELS_ZH_TW = {
"", "1\u5283", "2\u5283", "3\u5283", "4\u5283", "5\u5283", "6\u5283",
"7\u5283", "8\u5283", "9\u5283", "10\u5283", "11\u5283", "12\u5283",
"13\u5283", "14\u5283", "15\u5283", "16\u5283", "17\u5283", "18\u5283",
"19\u5283", "20\u5283", "21\u5283", "22\u5283", "23\u5283", "24\u5283",
"25\u5283", "26\u5283", "27\u5283", "28\u5283", "29\u5283", "30\u5283",
"31\u5283", "32\u5283", "33\u5283",
"35\u5283", "36\u5283", "39\u5283", "48\u5283",
"", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
"#", ""};
private static final String[] LABELS_KO = {
"", "\u3131", "\u3134", "\u3137", "\u3139", "\u3141", "\u3142",
"\u3145", "\u3147", "\u3148", "\u314A", "\u314B", "\u314C", "\u314D",
"\u314E",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
"#", ""};
private static final String[] LABELS_AR = {
"\u2026", "\u0627", "\u0628", "\u062a", "\u062b", "\u062c", "\u062d",
"\u062e", "\u062f", "\u0630", "\u0631", "\u0632", "\u0633", "\u0634",
"\u0635", "\u0636", "\u0637", "\u0638", "\u0639", "\u063a", "\u0641",
"\u0642", "\u0643", "\u0644", "\u0645", "\u0646", "\u0647", "\u0648",
"\u064a",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
"#", ""};
private static final String JAPANESE_MISC = "\u4ed6";
private static final Locale LOCALE_ARABIC = new Locale("ar");
private static final Locale LOCALE_SERBIAN = new Locale("sr");
private static final Locale LOCALE_UKRAINIAN = new Locale("uk");
private boolean hasSimplifiedChineseCollator;
private boolean hasTraditionalChineseCollator;
private boolean hasJapaneseCollator;
private boolean hasKoreanCollator;
private boolean hasArabicCollator;
private boolean hasGermanCollator;
private boolean hasSerbianCollator;
private boolean hasUkrainianCollator;
@Override
protected void setUp() throws Exception {
super.setUp();
final Locale locale[] = Collator.getAvailableLocales();
for (int i = 0; i < locale.length; i++) {
if (LocaleSet.isLocaleSimplifiedChinese(locale[i])) {
hasSimplifiedChineseCollator = true;
} else if (LocaleSet.isLocaleTraditionalChinese(locale[i])) {
hasTraditionalChineseCollator = true;
} else if (locale[i].equals(Locale.JAPAN)) {
hasJapaneseCollator = true;
} else if (locale[i].equals(Locale.KOREA)) {
hasKoreanCollator = true;
} else if (locale[i].equals(LOCALE_ARABIC)) {
hasArabicCollator = true;
} else if (locale[i].equals(Locale.GERMANY)) {
hasGermanCollator = true;
} else if (locale[i].equals(LOCALE_SERBIAN)) {
hasSerbianCollator = true;
} else if (locale[i].equals(LOCALE_UKRAINIAN)) {
hasUkrainianCollator = true;
}
}
}
private String getLabel(String name) {
ContactLocaleUtils utils = ContactLocaleUtils.getInstance();
int bucketIndex = utils.getBucketIndex(name);
return utils.getBucketLabel(bucketIndex);
}
private Iterator<String> getNameLookupKeys(String name, int nameStyle) {
ContactLocaleUtils utils = ContactLocaleUtils.getInstance();
return utils.getNameLookupKeys(name, nameStyle);
}
private ArrayList<String> getLabels() {
ContactLocaleUtils utils = ContactLocaleUtils.getInstance();
return utils.getLabels();
}
public void testEnglishContactLocaleUtils() throws Exception {
ContactLocaleUtils.setLocale(Locale.ENGLISH);
assertEquals("#", getLabel(PHONE_NUMBER_1));
assertEquals("#", getLabel(PHONE_NUMBER_2));
assertEquals("J", getLabel(LATIN_NAME));
assertEquals("\u2026", getLabel(CHINESE_NAME));
assertEquals("D", getLabel(CHINESE_LATIN_MIX_NAME_1));
assertEquals("B", getLabel("Bob Smith"));
if (hasArabicCollator) {
assertEquals("\u0646", getLabel(ARABIC_NAME));
}
if (hasSerbianCollator) {
assertEquals("\u0408", getLabel(SERBIAN_NAME));
}
if (hasUkrainianCollator) {
// Updated in CLDR 27/ICU 55:
// http://cldr.unicode.org/index/downloads/cldr-27#TOC-Changes-to-Collation
assertEquals("\u0406", getLabel(UKRAINIAN_NAME));
}
assertNull(getNameLookupKeys(LATIN_NAME, FullNameStyle.UNDEFINED));
verifyLabels(getLabels(), LABELS_EN_US);
}
public void testJapaneseContactLocaleUtils() throws Exception {
if (!hasJapaneseCollator) {
Log.w(TAG, "Japanese collator not found; skipping test");
return;
}
ContactLocaleUtils.setLocale(Locale.JAPAN);
assertEquals("#", getLabel(PHONE_NUMBER_1));
assertEquals("#", getLabel(PHONE_NUMBER_2));
assertEquals(JAPANESE_MISC, getLabel(KANJI_NAME));
assertEquals("J", getLabel(LATIN_NAME));
assertEquals(JAPANESE_MISC, getLabel(CHINESE_NAME));
assertEquals("D", getLabel(CHINESE_LATIN_MIX_NAME_1));
assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CJK));
assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CHINESE));
assertEquals("B", getLabel("Bob Smith"));
verifyLabels(getLabels(), LABELS_JA_JP);
}
public void testChineseContactLocaleUtils() throws Exception {
if (!hasSimplifiedChineseCollator) {
Log.w(TAG, "Simplified Chinese collator not found; skipping test");
return;
}
ContactLocaleUtils.setLocale(Locale.SIMPLIFIED_CHINESE);
assertEquals("#", getLabel(PHONE_NUMBER_1));
assertEquals("#", getLabel(PHONE_NUMBER_2));
assertEquals("J", getLabel(LATIN_NAME));
assertEquals("D", getLabel(CHINESE_NAME));
assertEquals("D", getLabel(CHINESE_LATIN_MIX_NAME_1));
assertEquals("B", getLabel("Bob Smith"));
verifyLabels(getLabels(), LABELS_EN_US);
if (hasTraditionalChineseCollator) {
ContactLocaleUtils.setLocale(Locale.TRADITIONAL_CHINESE);
assertEquals("#", getLabel(PHONE_NUMBER_1));
assertEquals("#", getLabel(PHONE_NUMBER_2));
assertEquals("J", getLabel(LATIN_NAME));
assertEquals("7\u5283", getLabel(CHINESE_NAME));
assertEquals("D", getLabel(CHINESE_LATIN_MIX_NAME_1));
} else {
Log.w(TAG, "Traditional Chinese collator not found");
}
ContactLocaleUtils.setLocale(Locale.SIMPLIFIED_CHINESE);
Iterator<String> keys = getNameLookupKeys(CHINESE_NAME,
FullNameStyle.CHINESE);
verifyKeys(keys, CHINESE_NAME_KEY);
keys = getNameLookupKeys(CHINESE_LATIN_MIX_NAME_1, FullNameStyle.CHINESE);
verifyKeys(keys, CHINESE_LATIN_MIX_NAME_1_KEY);
keys = getNameLookupKeys(CHINESE_LATIN_MIX_NAME_2, FullNameStyle.CHINESE);
verifyKeys(keys, CHINESE_LATIN_MIX_NAME_2_KEY);
if (hasTraditionalChineseCollator) {
ContactLocaleUtils.setLocale(Locale.TRADITIONAL_CHINESE);
assertEquals("B", getLabel("Bob Smith"));
verifyLabels(getLabels(), LABELS_ZH_TW);
}
}
public void testPinyinEnabledSecondaryLocale() throws Exception {
if (!hasSimplifiedChineseCollator) {
Log.w(TAG, "Simplified Chinese collator not found; skipping test");
return;
}
ContactLocaleUtils.setLocales(
new LocaleSet(Locale.ENGLISH, Locale.SIMPLIFIED_CHINESE));
assertEquals("D", getLabel(CHINESE_NAME));
Iterator<String> keys = getNameLookupKeys(CHINESE_NAME,
FullNameStyle.CHINESE);
verifyKeys(keys, CHINESE_NAME_KEY);
}
public void testPinyinDisabledSecondaryLocale() throws Exception {
if (!hasSimplifiedChineseCollator) {
Log.w(TAG, "Simplified Chinese collator not found; skipping test");
return;
}
ContactLocaleUtils.setLocales(
new LocaleSet(Locale.ENGLISH, Locale.JAPAN));
assertEquals("", getLabel(CHINESE_NAME));
assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CHINESE));
assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CJK));
}
public void testChineseStyleNameWithDifferentLocale() throws Exception {
if (!hasSimplifiedChineseCollator) {
Log.w(TAG, "Simplified Chinese collator not found; skipping test");
return;
}
ContactLocaleUtils.setLocale(Locale.ENGLISH);
assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CHINESE));
assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CJK));
ContactLocaleUtils.setLocale(Locale.SIMPLIFIED_CHINESE);
Iterator<String> keys = getNameLookupKeys(CHINESE_NAME,
FullNameStyle.CJK);
verifyKeys(keys, CHINESE_NAME_KEY);
keys = getNameLookupKeys(LATIN_NAME, FullNameStyle.WESTERN);
verifyKeys(keys, LATIN_NAME_KEY);
keys = getNameLookupKeys(LATIN_NAME_2, FullNameStyle.WESTERN);
verifyKeys(keys, LATIN_NAME_KEY_2);
if (hasTraditionalChineseCollator) {
ContactLocaleUtils.setLocale(Locale.TRADITIONAL_CHINESE);
assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CJK));
}
}
public void testKoreanContactLocaleUtils() throws Exception {
if (!hasKoreanCollator) {
Log.w(TAG, "Korean collator not found; skipping test");
return;
}
ContactLocaleUtils.setLocale(Locale.KOREA);
assertEquals("\u3131", getLabel("\u1100"));
assertEquals("\u3131", getLabel("\u3131"));
assertEquals("\u3131", getLabel("\u1101"));
assertEquals("\u314e", getLabel("\u1161"));
assertEquals("B", getLabel("Bob Smith"));
verifyLabels(getLabels(), LABELS_KO);
}
public void testArabicContactLocaleUtils() throws Exception {
if (!hasArabicCollator) {
Log.w(TAG, "Arabic collator not found; skipping test");
return;
}
ContactLocaleUtils.setLocale(LOCALE_ARABIC);
assertEquals("\u0646", getLabel(ARABIC_NAME));
assertEquals("B", getLabel("Bob Smith"));
verifyLabels(getLabels(), LABELS_AR);
}
public void testSerbianContactLocaleUtils() throws Exception {
if (!hasSerbianCollator) {
Log.w(TAG, "Serbian collator not found; skipping test");
return;
}
ContactLocaleUtils.setLocale(LOCALE_SERBIAN);
assertEquals("\u0408", getLabel(SERBIAN_NAME));
assertEquals("B", getLabel("Bob Smith"));
}
public void testUkrainianContactLocaleUtils() throws Exception {
if (!hasUkrainianCollator) {
Log.w(TAG, "Ukrainian collator not found; skipping test");
return;
}
ContactLocaleUtils.setLocale(LOCALE_UKRAINIAN);
assertEquals("\u0407", getLabel(UKRAINIAN_NAME));
assertEquals("\u0490", getLabel(UKRAINIAN_NAME_2));
assertEquals("B", getLabel("Bob Smith"));
}
public void testGermanContactLocaleUtils() throws Exception {
if (!hasGermanCollator) {
return;
}
ContactLocaleUtils.setLocale(Locale.GERMANY);
assertEquals("S", getLabel("Sacher"));
// ICU 51 has labels Sch and St. These were removed in ICU 52
assertEquals("S", getLabel("Schiller"));
assertEquals("S", getLabel("Steiff"));
verifyLabels(getLabels(), LABELS_EN_US);
}
private void verifyKeys(final Iterator<String> resultKeys, final String[] expectedKeys)
throws Exception {
HashSet<String> allKeys = new HashSet<String>();
while (resultKeys.hasNext()) {
allKeys.add(resultKeys.next());
}
assertEquals(new HashSet<String>(Arrays.asList(expectedKeys)), allKeys);
}
// Verify that the initial set of resultLabels matches the expectedLabels.
// Ignore the (large) number of secondary locale labels that make up the
// tail labels in the result set right before the final "#" and "" buckets.
private void verifyLabels(final ArrayList<String> resultLabels,
final String[] expectedLabels) throws Exception {
final List<String> expectedLabelList = Arrays.asList(expectedLabels);
final int numLabels = expectedLabelList.size() - 2;
assertEquals(expectedLabelList.subList(0, numLabels),
resultLabels.subList(0, numLabels));
}
}