Home | History | Annotate | Download | only in contacts
      1 /*
      2  * Copyright (C) 2009 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.provider.ContactsContract.PhoneticNameStyle;
     21 import android.test.suitebuilder.annotation.SmallTest;
     22 
     23 import com.android.providers.contacts.NameSplitter.Name;
     24 
     25 import junit.framework.TestCase;
     26 
     27 import java.util.Locale;
     28 
     29 /**
     30  * Tests for {@link NameSplitter}.
     31  *
     32  * Run the test like this:
     33  * <code>
     34  * adb shell am instrument -e class com.android.providers.contacts.NameSplitterTest -w \
     35  *         com.android.providers.contacts.tests/android.test.InstrumentationTestRunner
     36  * </code>
     37  */
     38 @SmallTest
     39 public class NameSplitterTest extends TestCase {
     40     private NameSplitter mNameSplitter;
     41 
     42     @Override
     43     protected void setUp() throws Exception {
     44         super.setUp();
     45         createNameSplitter(Locale.US);
     46     }
     47 
     48     private void createNameSplitter(Locale locale) {
     49         mNameSplitter = new NameSplitter("Mr, Ms, Mrs", "d', st, st., von", "Jr., M.D., MD, D.D.S.",
     50                 "&, AND", locale);
     51     }
     52 
     53     public void testNull() {
     54         assertSplitName(null, null, null, null, null, null);
     55         assertJoinedName(null, null, null, null, null, null);
     56     }
     57 
     58     public void testEmpty() {
     59         assertSplitName("", null, null, null, null, null);
     60         assertJoinedName(null, null, null, null, null, null);
     61     }
     62 
     63     public void testSpaces() {
     64         assertSplitName(" ", null, null, null, null, null);
     65         assertJoinedName(null, null, null, null, null, null);
     66     }
     67 
     68     public void testFamilyName() {
     69         assertSplitName("Smith", null, "Smith", null, null, null);
     70         assertJoinedName("Smith", null, "Smith", null, null, null);
     71     }
     72 
     73     public void testIgnoreSuffix() {
     74         assertSplitName("Ms MD", "Ms", null, null, "MD", null);
     75         assertJoinedName("Ms MD", "Ms", null, null, "MD", null);
     76     }
     77 
     78     public void testGivenFamilyName() {
     79         assertSplitName("John Smith", null, "John", null, "Smith", null);
     80         assertJoinedName("John Smith", null, "John", null, "Smith", null);
     81     }
     82 
     83     public void testGivenMiddleFamilyName() {
     84         assertSplitName("John Edward Smith", null, "John", "Edward", "Smith", null);
     85         assertJoinedName("John Edward Smith", null, "John", "Edward", "Smith", null);
     86     }
     87 
     88     public void testThreeNamesAndFamilyName() {
     89         assertSplitName("John Edward Kevin Smith", null, "John Edward", "Kevin", "Smith", null);
     90         assertJoinedName("John Edward Kevin Smith", null, "John Edward", "Kevin", "Smith", null);
     91     }
     92 
     93     public void testPrefixFivenFamilyName() {
     94         assertSplitName("Mr. John Smith", "Mr.", "John", null, "Smith", null);
     95         assertJoinedName("Mr John Smith", "Mr", "John", null, "Smith", null);
     96         assertSplitName("Mr.John Smith", "Mr.", "John", null, "Smith", null);
     97         assertJoinedName("Mr John Smith", "Mr", "John", null, "Smith", null);
     98     }
     99 
    100     public void testFivenFamilyNameSuffix() {
    101         assertSplitName("John Smith Jr", null, "John", null, "Smith", "Jr");
    102         assertJoinedName("John Smith, Jr.", null, "John", null, "Smith", "Jr");
    103     }
    104 
    105     public void testGivenFamilyNameSuffixWithDot() {
    106         assertSplitName("John Smith M.D.", null, "John", null, "Smith", "M.D.");
    107         assertJoinedName("John Smith, M.D.", null, "John", null, "Smith", "M.D.");
    108         assertSplitName("John Smith D D S", null, "John", null, "Smith", "D D S");
    109         assertJoinedName("John Smith, D D S", null, "John", null, "Smith", "D D S");
    110     }
    111 
    112     public void testGivenSuffixFamilyName() {
    113         assertSplitName("John von Smith", null, "John", null, "von Smith", null);
    114         assertJoinedName("John von Smith", null, "John", null, "von Smith", null);
    115     }
    116 
    117     public void testGivenSuffixFamilyNameWithDot() {
    118         assertSplitName("John St.Smith", null, "John", null, "St. Smith", null);
    119         assertJoinedName("John St. Smith", null, "John", null, "St. Smith", null);
    120     }
    121 
    122     public void testPrefixGivenMiddleFamily() {
    123         assertSplitName("Mr. John Kevin Smith", "Mr.", "John", "Kevin", "Smith", null);
    124         assertJoinedName("Mr John Kevin Smith", "Mr", "John", "Kevin", "Smith", null);
    125         assertSplitName("Mr.John Kevin Smith", "Mr.", "John", "Kevin", "Smith", null);
    126         assertJoinedName("Mr. John Kevin Smith", "Mr.", "John", "Kevin", "Smith", null);
    127     }
    128 
    129     public void testPrefixGivenMiddleFamilySuffix() {
    130         assertSplitName("Mr. John Kevin Smith Jr.", "Mr.", "John", "Kevin", "Smith", "Jr.");
    131         assertJoinedName("Mr John Kevin Smith, Jr.", "Mr", "John", "Kevin", "Smith", "Jr");
    132     }
    133 
    134     public void testPrefixGivenMiddlePrefixFamilySuffixWrongCapitalization() {
    135         assertSplitName("MR. john keVin VON SmiTh JR.", "MR.", "john", "keVin", "VON SmiTh", "JR.");
    136         assertJoinedName("MR john keVin VON SmiTh, JR.", "MR", "john", "keVin", "VON SmiTh", "JR");
    137     }
    138 
    139     public void testPrefixFamilySuffix() {
    140         assertSplitName("von Smith Jr.", null, null, null, "von Smith", "Jr.");
    141         assertJoinedName("von Smith, Jr.", null, null, null, "von Smith", "Jr");
    142     }
    143 
    144     public void testFamilyNameGiven() {
    145         assertSplitName("Smith, John", null, "John", null, "Smith", null);
    146         assertSplitName("Smith  , John", null, "John", null, "Smith", null);
    147         assertSplitName("Smith, John Kimble", null, "John", "Kimble", "Smith", null);
    148         assertSplitName("Smith, John K.", null, "John", "K.", "Smith", null);
    149         assertSplitName("Smith, John, Jr.", null, "John", null, "Smith", "Jr.");
    150         assertSplitName("Smith, John Kimble, Jr.", null, "John", "Kimble", "Smith", "Jr.");
    151         assertSplitName("von Braun, John, Jr.", null, "John", null, "von Braun", "Jr.");
    152         assertSplitName("von Braun, John Kimble, Jr.", null, "John", "Kimble", "von Braun", "Jr.");
    153     }
    154 
    155     public void testTwoNamesAndFamilyNameWithAmpersand() {
    156         assertSplitName("John & Edward Smith", null, "John & Edward", null, "Smith", null);
    157         assertJoinedName("John & Edward Smith", null, "John & Edward", null, "Smith", null);
    158         assertSplitName("John and Edward Smith", null, "John and Edward", null, "Smith", null);
    159         assertSplitName("Smith, John and Edward", null, "John and Edward", null, "Smith", null);
    160         assertJoinedName("John and Edward Smith", null, "John and Edward", null, "Smith", null);
    161     }
    162 
    163     public void testWithMiddleInitialAndNoDot() {
    164         assertSplitName("John E. Smith", null, "John", "E.", "Smith", null);
    165         assertJoinedName("John E Smith", null, "John", "E", "Smith", null);
    166     }
    167 
    168     public void testWithLongGivenNameAndDot() {
    169         assertSplitName("John Ed. K. Smith", null, "John Ed.", "K.", "Smith", null);
    170         assertJoinedName("John Ed. K Smith", null, "John Ed.", "K", "Smith", null);
    171     }
    172 
    173     public void testGuessFullNameStyleEmpty() {
    174         assertFullNameStyle(FullNameStyle.UNDEFINED, null);
    175         assertFullNameStyle(FullNameStyle.UNDEFINED, "");
    176     }
    177 
    178     public void testGuessFullNameStyleWestern() {
    179 
    180         // Latin letters
    181         assertFullNameStyle(FullNameStyle.WESTERN, "John Doe");
    182 
    183         // Starts with a Latin letter, but contains Japanese letters
    184         assertFullNameStyle(FullNameStyle.JAPANESE, "A\u3080\u308D\u306A\u307F\u3048");
    185 
    186         // Starts with an Extended Latin letter "Latin Capital Ligature OE"
    187         assertFullNameStyle(FullNameStyle.WESTERN, "\u0152uvre");
    188 
    189         // Non-letters don't make a difference. This one starts with a vertical line
    190         assertFullNameStyle(FullNameStyle.WESTERN, "\uFF5C.?+Smith");
    191     }
    192 
    193     public void testGuessFullNameStyleJapanese() {
    194         createNameSplitter(Locale.JAPAN);
    195 
    196         // Hiragana: always Japanese
    197         assertFullNameStyle(FullNameStyle.JAPANESE, "\u3042\u3080\u308D\u306A\u307F\u3048");
    198 
    199         // Katakana: always Japanese
    200         assertFullNameStyle(FullNameStyle.JAPANESE, "\u30A2\u30E0\u30ED \u30CA\u30DF\u30A8");
    201 
    202         // Half-width Katakana: always Japanese
    203         assertFullNameStyle(FullNameStyle.JAPANESE, "\uFF71\uFF91\uFF9B \uFF85\uFF90\uFF74");
    204 
    205         // Kanji: we cannot tell if this is Japanese, Chinese or Korean, but we are
    206         // in Locale.JAPAN, so assume Japanese
    207         assertFullNameStyle(FullNameStyle.JAPANESE, "\u5B89\u5BA4\u5948\u7F8E\u6075");
    208 
    209         // TODO: mix
    210 
    211         // Accompanied by a phonetic name in Hiragana, we can safely assume that the
    212         // name is Japanese
    213         assertFullNameStyle(FullNameStyle.JAPANESE, "\u5B89\u5BA4\u5948\u7F8E\u6075",
    214                 "\u3042\u3080\u308D", null, "\u306A\u307F\u3048");
    215 
    216         // Starts with a latin letter - not Western
    217         assertFullNameStyle(FullNameStyle.JAPANESE, "A\u3080\u308D\u306A\u307F\u3048");
    218     }
    219 
    220     public void testGuessFullNameStyleChinese() {
    221         createNameSplitter(Locale.CHINA);
    222 
    223         // Hanzi: we cannot tell if this is Chinese, Japanese or Korean,
    224         // but we are in Locale.CHINA, so assume this is Chinese
    225         assertFullNameStyle(FullNameStyle.CHINESE, "\u675C\u9D51");
    226 
    227         // Accompanied by a phonetic name in Pinyin, we can safely assume that the
    228         // name is Chinese
    229         assertFullNameStyle(FullNameStyle.CHINESE, "\u675C\u9D51",
    230                 "du4", null, "juan1");
    231 
    232         // Non-letters don't make a difference. This one starts with a vertical line
    233         assertFullNameStyle(FullNameStyle.CHINESE, "\uFF5C--(\u675C\u9D51)");
    234     }
    235 
    236 
    237     public void testGuessPhoneticNameStyle() {
    238 
    239         // Hiragana
    240         assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, "\u3042\u3080\u308D", null, null);
    241         assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, null, "\u3042\u3080\u308D", null);
    242         assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, null, null, "\u306A\u307F\u3048");
    243         assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, "\u3042\u3080\u308D", null,
    244                 "\u306A\u307F\u3048");
    245 
    246         // Katakana
    247         assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, "\u30A2\u30E0\u30ED", null,
    248                 "\u30CA\u30DF\u30A8");
    249 
    250         // Half-width Katakana
    251         assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, "\u30A2\u30E0\u30ED", null,
    252                 "\u30CA\u30DF\u30A8");
    253 
    254         // Chinese
    255         assertPhoneticNameStyle(PhoneticNameStyle.PINYIN, "du4", null, "juan1");
    256     }
    257 
    258     public void testSplitJapaneseName() {
    259         createNameSplitter(Locale.JAPAN);
    260 
    261         // One word is interpreted as given name only
    262         assertSplitName("\u3042\u3080\u308D", null, "\u3042\u3080\u308D", null, null, null);
    263 
    264         // Two words are interpreted as family + give name
    265         assertSplitName("\u3042\u3080\u308D \u306A\u307F\u3048", null, "\u306A\u307F\u3048", null,
    266                 "\u3042\u3080\u308D", null);
    267 
    268         // Multiple words are interpreted as "family - given names"
    269         assertSplitName("\u3042\u3080\u308D \u3068\u304A\u308B \u306A\u307F\u3048", null,
    270                 "\u3068\u304A\u308B \u306A\u307F\u3048", null, "\u3042\u3080\u308D", null);
    271 
    272         // Hanzi characters without spaces: lump them all in the given name
    273         assertSplitName("\u6BB5\u5C0F\u6D9B", null, "\u6BB5\u5C0F\u6D9B", null, null, null);
    274     }
    275 
    276     public void testSplitChineseName() {
    277         createNameSplitter(Locale.CHINA);
    278 
    279         // Two Hanzi characters: familyName+givenName
    280         assertSplitName("\u6BB5\u5C0F", null, "\u5C0F", null, "\u6BB5", null);
    281 
    282         // Two Hanzi characters: familyName+middleName+givenName
    283         assertSplitName("\u6BB5\u5C0F\u6D9B", null, "\u6D9B", "\u5C0F", "\u6BB5", null);
    284 
    285         // Two Hanzi characters: familyName(2)+middleName+givenName
    286         assertSplitName("\u6BB5\u5C0F\u6D9B\u6D9C", null, "\u6D9C", "\u6D9B", "\u6BB5\u5C0F", null);
    287     }
    288 
    289     public void testJoinJapaneseName() {
    290         createNameSplitter(Locale.JAPAN);
    291 
    292         assertJoinedName("\u3042\u3080\u308D", FullNameStyle.JAPANESE, null, "\u3042\u3080\u308D",
    293                 null, null, null, true);
    294 
    295         // Given-name-first flag is ignored for CJK locales
    296         assertJoinedName("\u3084\u307E\u3056\u304D \u3068\u304A\u308B", FullNameStyle.JAPANESE,
    297                 null, "\u3068\u304A\u308B", null, "\u3084\u307E\u3056\u304D", null, false);
    298         assertJoinedName("\u3084\u307E\u3056\u304D \u3068\u304A\u308B \u3068\u304A\u308B",
    299                 FullNameStyle.JAPANESE, null, "\u3068\u304A\u308B", "\u3068\u304A\u308B",
    300                 "\u3084\u307E\u3056\u304D", null, false);
    301     }
    302 
    303     public void testJoinChineseName() {
    304         createNameSplitter(Locale.CHINA);
    305 
    306         // Given-name-first flag is ignored for CJK locales
    307         assertJoinedName("\u6BB5\u5C0F\u6D9B", FullNameStyle.CHINESE, null,
    308                 "\u6D9B", "\u5C0F", "\u6BB5", null, true);
    309         assertJoinedName("\u6BB5\u5C0F\u6D9B", FullNameStyle.CHINESE, null,
    310                 "\u6D9B", "\u5C0F", "\u6BB5", null, false);
    311     }
    312 
    313     private void assertSplitName(String fullName, String prefix, String givenNames,
    314             String middleName, String familyName, String suffix) {
    315         final Name name = new Name();
    316         mNameSplitter.split(name, fullName);
    317         assertEquals(prefix, name.getPrefix());
    318         assertEquals(givenNames, name.getGivenNames());
    319         assertEquals(middleName, name.getMiddleName());
    320         assertEquals(familyName, name.getFamilyName());
    321         assertEquals(suffix, name.getSuffix());
    322     }
    323 
    324     private void assertJoinedName(String expected, String prefix, String givenNames,
    325             String middleName, String familyName, String suffix) {
    326         assertJoinedName(expected, FullNameStyle.WESTERN, prefix, givenNames, middleName,
    327                 familyName, suffix, true);
    328     }
    329 
    330     private void assertJoinedName(String expected, int nameStyle, String prefix, String givenNames,
    331             String middleName, String familyName, String suffix, boolean givenNameFirst) {
    332         Name name = new Name();
    333         name.fullNameStyle = nameStyle;
    334         name.prefix = prefix;
    335         name.givenNames = givenNames;
    336         name.middleName = middleName;
    337         name.familyName = familyName;
    338         name.suffix = suffix;
    339         String actual = mNameSplitter.join(name, givenNameFirst, true);
    340         assertEquals(expected, actual);
    341     }
    342 
    343     private void assertFullNameStyle(int expectedFullNameStyle, String fullName) {
    344         Name name = new Name();
    345         mNameSplitter.split(name, fullName);
    346         mNameSplitter.guessNameStyle(name);
    347 
    348         assertEquals(expectedFullNameStyle, name.fullNameStyle);
    349     }
    350 
    351     private void assertFullNameStyle(int expectedFullNameStyle, String fullName,
    352             String phoneticFamilyName, String phoneticMiddleName, String phoneticGivenName) {
    353         Name name = new Name();
    354         mNameSplitter.split(name, fullName);
    355         name.phoneticFamilyName = phoneticFamilyName;
    356         name.phoneticMiddleName = phoneticMiddleName;
    357         name.phoneticGivenName = phoneticGivenName;
    358 
    359         mNameSplitter.guessNameStyle(name);
    360 
    361         assertEquals(expectedFullNameStyle, name.fullNameStyle);
    362     }
    363 
    364     private void assertPhoneticNameStyle(int expectedPhoneticNameStyle, String phoneticFamilyName,
    365             String phoneticMiddleName, String phoneticGivenName) {
    366         Name name = new Name();
    367         name.phoneticFamilyName = phoneticFamilyName;
    368         name.phoneticMiddleName = phoneticMiddleName;
    369         name.phoneticGivenName = phoneticGivenName;
    370 
    371         mNameSplitter.guessNameStyle(name);
    372 
    373         assertEquals(expectedPhoneticNameStyle, name.phoneticNameStyle);
    374     }
    375 
    376     public void testSplitKoreanName() {
    377         createNameSplitter(Locale.KOREA);
    378 
    379         // Lee - Sang Il
    380         assertSplitName("\uC774\uC0C1\uC77C", null, "\uC0C1\uC77C", null, "\uC774", null);
    381         // Dok Go - Young Jae
    382         assertSplitName("\uB3C5\uACE0\uC601\uC7AC",
    383                 null, "\uC601\uC7AC", null, "\uB3C5\uACE0", null);
    384     }
    385 }
    386