• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
setUp()43     protected void setUp() throws Exception {
44         super.setUp();
45         createNameSplitter(Locale.US);
46     }
47 
createNameSplitter(Locale locale)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 
testNull()53     public void testNull() {
54         assertSplitName(null, null, null, null, null, null);
55         assertJoinedName(null, null, null, null, null, null);
56     }
57 
testEmpty()58     public void testEmpty() {
59         assertSplitName("", null, null, null, null, null);
60         assertJoinedName(null, null, null, null, null, null);
61     }
62 
testSpaces()63     public void testSpaces() {
64         assertSplitName(" ", null, null, null, null, null);
65         assertJoinedName(null, null, null, null, null, null);
66     }
67 
testFamilyName()68     public void testFamilyName() {
69         assertSplitName("Smith", null, "Smith", null, null, null);
70         assertJoinedName("Smith", null, "Smith", null, null, null);
71     }
72 
testIgnoreSuffix()73     public void testIgnoreSuffix() {
74         assertSplitName("Ms MD", "Ms", null, null, "MD", null);
75         assertJoinedName("Ms MD", "Ms", null, null, "MD", null);
76     }
77 
testGivenFamilyName()78     public void testGivenFamilyName() {
79         assertSplitName("John Smith", null, "John", null, "Smith", null);
80         assertJoinedName("John Smith", null, "John", null, "Smith", null);
81     }
82 
testGivenMiddleFamilyName()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 
testThreeNamesAndFamilyName()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 
testPrefixFivenFamilyName()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 
testFivenFamilyNameSuffix()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 
testGivenFamilyNameSuffixWithDot()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 
testGivenSuffixFamilyName()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 
testGivenSuffixFamilyNameWithDot()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 
testPrefixGivenMiddleFamily()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 
testPrefixGivenMiddleFamilySuffix()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 
testPrefixGivenMiddlePrefixFamilySuffixWrongCapitalization()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 
testPrefixFamilySuffix()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 
testFamilyNameGiven()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 
testTwoNamesAndFamilyNameWithAmpersand()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 
testWithMiddleInitialAndNoDot()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 
testWithLongGivenNameAndDot()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 
testGuessFullNameStyleEmpty()173     public void testGuessFullNameStyleEmpty() {
174         assertFullNameStyle(FullNameStyle.UNDEFINED, null);
175         assertFullNameStyle(FullNameStyle.UNDEFINED, "");
176     }
177 
testGuessFullNameStyleWestern()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 
testGuessFullNameStyleJapanese()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 
testGuessFullNameStyleChinese()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 
testGuessFullNameStyleChineseMixed()236     public void testGuessFullNameStyleChineseMixed() {
237         createNameSplitter(Locale.CHINA);
238         // Both first and last names are Chinese.
239         assertFullNameStyle(FullNameStyle.CHINESE, "\u675C \u9D51");
240         // Last name is Chinese, first name is English.
241         assertFullNameStyle(FullNameStyle.CHINESE, "\u675C Juan");
242         // Last name is English, first name is Chinese.
243         assertFullNameStyle(FullNameStyle.CHINESE, "Du \u9D51");
244         // Both first and last names are English, prefix, middle, suffix are all Chinese.
245         Name name = new Name();
246         name.prefix = "\u524D";
247         name.givenNames = "Du";
248         name.middleName = "\u5C0F";
249         name.familyName = "Juan";
250         name.suffix = "\u540E";
251         mNameSplitter.guessNameStyle(name);
252         // guessFullNameStyle() only look at last and first name.
253         assertEquals(FullNameStyle.WESTERN, name.fullNameStyle);
254     }
255 
testGuessPhoneticNameStyle()256     public void testGuessPhoneticNameStyle() {
257 
258         // Hiragana
259         assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, "\u3042\u3080\u308D", null, null);
260         assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, null, "\u3042\u3080\u308D", null);
261         assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, null, null, "\u306A\u307F\u3048");
262         assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, "\u3042\u3080\u308D", null,
263                 "\u306A\u307F\u3048");
264 
265         // Katakana
266         assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, "\u30A2\u30E0\u30ED", null,
267                 "\u30CA\u30DF\u30A8");
268 
269         // Half-width Katakana
270         assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, "\u30A2\u30E0\u30ED", null,
271                 "\u30CA\u30DF\u30A8");
272 
273         // Chinese
274         assertPhoneticNameStyle(PhoneticNameStyle.PINYIN, "du4", null, "juan1");
275     }
276 
testSplitJapaneseName()277     public void testSplitJapaneseName() {
278         createNameSplitter(Locale.JAPAN);
279 
280         // One word is interpreted as given name only
281         assertSplitName("\u3042\u3080\u308D", null, "\u3042\u3080\u308D", null, null, null);
282 
283         // Two words are interpreted as family + give name
284         assertSplitName("\u3042\u3080\u308D \u306A\u307F\u3048", null, "\u306A\u307F\u3048", null,
285                 "\u3042\u3080\u308D", null);
286 
287         // Multiple words are interpreted as "family - given names"
288         assertSplitName("\u3042\u3080\u308D \u3068\u304A\u308B \u306A\u307F\u3048", null,
289                 "\u3068\u304A\u308B \u306A\u307F\u3048", null, "\u3042\u3080\u308D", null);
290 
291         // Hanzi characters without spaces: lump them all in the given name
292         assertSplitName("\u6BB5\u5C0F\u6D9B", null, "\u6BB5\u5C0F\u6D9B", null, null, null);
293     }
294 
testSplitChineseName()295     public void testSplitChineseName() {
296         createNameSplitter(Locale.CHINA);
297 
298         // Two Hanzi characters: familyName+givenName
299         assertSplitName("\u6BB5\u5C0F", null, "\u5C0F", null, "\u6BB5", null);
300 
301         // Two Hanzi characters: familyName+middleName+givenName
302         assertSplitName("\u6BB5\u5C0F\u6D9B", null, "\u6D9B", "\u5C0F", "\u6BB5", null);
303 
304         // Two Hanzi characters: familyName(2)+middleName+givenName
305         assertSplitName("\u6BB5\u5C0F\u6D9B\u6D9C", null, "\u6D9C", "\u6D9B", "\u6BB5\u5C0F", null);
306     }
307 
testJoinJapaneseName()308     public void testJoinJapaneseName() {
309         createNameSplitter(Locale.JAPAN);
310 
311         assertJoinedName("\u3042\u3080\u308D", FullNameStyle.JAPANESE, null, "\u3042\u3080\u308D",
312                 null, null, null, true);
313 
314         // Given-name-first flag is ignored for CJK locales
315         assertJoinedName("\u3084\u307E\u3056\u304D \u3068\u304A\u308B", FullNameStyle.JAPANESE,
316                 null, "\u3068\u304A\u308B", null, "\u3084\u307E\u3056\u304D", null, false);
317         assertJoinedName("\u3084\u307E\u3056\u304D \u3068\u304A\u308B \u3068\u304A\u308B",
318                 FullNameStyle.JAPANESE, null, "\u3068\u304A\u308B", "\u3068\u304A\u308B",
319                 "\u3084\u307E\u3056\u304D", null, false);
320     }
321 
testJoinChineseName()322     public void testJoinChineseName() {
323         createNameSplitter(Locale.CHINA);
324 
325         // Given-name-first flag is ignored for CJK locales
326         assertJoinedName("\u6BB5\u5C0F\u6D9B", FullNameStyle.CHINESE, null,
327                 "\u6D9B", "\u5C0F", "\u6BB5", null, true);
328         assertJoinedName("\u6BB5\u5C0F\u6D9B", FullNameStyle.CHINESE, null,
329                 "\u6D9B", "\u5C0F", "\u6BB5", null, false);
330     }
331 
assertSplitName(String fullName, String prefix, String givenNames, String middleName, String familyName, String suffix)332     private void assertSplitName(String fullName, String prefix, String givenNames,
333             String middleName, String familyName, String suffix) {
334         final Name name = new Name();
335         mNameSplitter.split(name, fullName);
336         assertEquals(prefix, name.getPrefix());
337         assertEquals(givenNames, name.getGivenNames());
338         assertEquals(middleName, name.getMiddleName());
339         assertEquals(familyName, name.getFamilyName());
340         assertEquals(suffix, name.getSuffix());
341     }
342 
assertJoinedName(String expected, String prefix, String givenNames, String middleName, String familyName, String suffix)343     private void assertJoinedName(String expected, String prefix, String givenNames,
344             String middleName, String familyName, String suffix) {
345         assertJoinedName(expected, FullNameStyle.WESTERN, prefix, givenNames, middleName,
346                 familyName, suffix, true);
347     }
348 
assertJoinedName(String expected, int nameStyle, String prefix, String givenNames, String middleName, String familyName, String suffix, boolean givenNameFirst)349     private void assertJoinedName(String expected, int nameStyle, String prefix, String givenNames,
350             String middleName, String familyName, String suffix, boolean givenNameFirst) {
351         Name name = new Name();
352         name.fullNameStyle = nameStyle;
353         name.prefix = prefix;
354         name.givenNames = givenNames;
355         name.middleName = middleName;
356         name.familyName = familyName;
357         name.suffix = suffix;
358         String actual = mNameSplitter.join(name, givenNameFirst, true);
359         assertEquals(expected, actual);
360     }
361 
assertFullNameStyle(int expectedFullNameStyle, String fullName)362     private void assertFullNameStyle(int expectedFullNameStyle, String fullName) {
363         Name name = new Name();
364         mNameSplitter.split(name, fullName);
365         mNameSplitter.guessNameStyle(name);
366 
367         assertEquals(expectedFullNameStyle, name.fullNameStyle);
368     }
369 
assertFullNameStyle(int expectedFullNameStyle, String fullName, String phoneticFamilyName, String phoneticMiddleName, String phoneticGivenName)370     private void assertFullNameStyle(int expectedFullNameStyle, String fullName,
371             String phoneticFamilyName, String phoneticMiddleName, String phoneticGivenName) {
372         Name name = new Name();
373         mNameSplitter.split(name, fullName);
374         name.phoneticFamilyName = phoneticFamilyName;
375         name.phoneticMiddleName = phoneticMiddleName;
376         name.phoneticGivenName = phoneticGivenName;
377 
378         mNameSplitter.guessNameStyle(name);
379 
380         assertEquals(expectedFullNameStyle, name.fullNameStyle);
381     }
382 
assertPhoneticNameStyle(int expectedPhoneticNameStyle, String phoneticFamilyName, String phoneticMiddleName, String phoneticGivenName)383     private void assertPhoneticNameStyle(int expectedPhoneticNameStyle, String phoneticFamilyName,
384             String phoneticMiddleName, String phoneticGivenName) {
385         Name name = new Name();
386         name.phoneticFamilyName = phoneticFamilyName;
387         name.phoneticMiddleName = phoneticMiddleName;
388         name.phoneticGivenName = phoneticGivenName;
389 
390         mNameSplitter.guessNameStyle(name);
391 
392         assertEquals(expectedPhoneticNameStyle, name.phoneticNameStyle);
393     }
394 
testSplitKoreanName()395     public void testSplitKoreanName() {
396         createNameSplitter(Locale.KOREA);
397 
398         // Lee - Sang Il
399         assertSplitName("\uC774\uC0C1\uC77C", null, "\uC0C1\uC77C", null, "\uC774", null);
400         // Dok Go - Young Jae
401         assertSplitName("\uB3C5\uACE0\uC601\uC7AC",
402                 null, "\uC601\uC7AC", null, "\uB3C5\uACE0", null);
403     }
404 }
405