/* * Copyright (C) 2009 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 com.android.providers.contacts.NameSplitter.Name; import android.provider.ContactsContract.FullNameStyle; import android.provider.ContactsContract.PhoneticNameStyle; import android.test.suitebuilder.annotation.SmallTest; import java.util.Locale; import junit.framework.TestCase; /** * Tests for {@link NameSplitter}. * * Run the test like this: * * adb shell am instrument -e class com.android.providers.contacts.NameSplitterTest -w \ * com.android.providers.contacts.tests/android.test.InstrumentationTestRunner * */ @SmallTest public class NameSplitterTest extends TestCase { private NameSplitter mNameSplitter; @Override protected void setUp() throws Exception { super.setUp(); createNameSplitter(Locale.US); } private void createNameSplitter(Locale locale) { mNameSplitter = new NameSplitter("Mr, Ms, Mrs", "d', st, st., von", "Jr., M.D., MD, D.D.S.", "&, AND", locale); } public void testNull() { assertSplitName(null, null, null, null, null, null); assertJoinedName(null, null, null, null, null, null); } public void testEmpty() { assertSplitName("", null, null, null, null, null); assertJoinedName(null, null, null, null, null, null); } public void testSpaces() { assertSplitName(" ", null, null, null, null, null); assertJoinedName(null, null, null, null, null, null); } public void testFamilyName() { assertSplitName("Smith", null, "Smith", null, null, null); assertJoinedName("Smith", null, "Smith", null, null, null); } public void testIgnoreSuffix() { assertSplitName("Ms MD", "Ms", null, null, "MD", null); assertJoinedName("Ms MD", "Ms", null, null, "MD", null); } public void testGivenFamilyName() { assertSplitName("John Smith", null, "John", null, "Smith", null); assertJoinedName("John Smith", null, "John", null, "Smith", null); } public void testGivenMiddleFamilyName() { assertSplitName("John Edward Smith", null, "John", "Edward", "Smith", null); assertJoinedName("John Edward Smith", null, "John", "Edward", "Smith", null); } public void testThreeNamesAndFamilyName() { assertSplitName("John Edward Kevin Smith", null, "John Edward", "Kevin", "Smith", null); assertJoinedName("John Edward Kevin Smith", null, "John Edward", "Kevin", "Smith", null); } public void testPrefixFivenFamilyName() { assertSplitName("Mr. John Smith", "Mr.", "John", null, "Smith", null); assertJoinedName("Mr John Smith", "Mr", "John", null, "Smith", null); assertSplitName("Mr.John Smith", "Mr.", "John", null, "Smith", null); assertJoinedName("Mr John Smith", "Mr", "John", null, "Smith", null); } public void testFivenFamilyNameSuffix() { assertSplitName("John Smith Jr", null, "John", null, "Smith", "Jr"); assertJoinedName("John Smith, Jr.", null, "John", null, "Smith", "Jr"); } public void testGivenFamilyNameSuffixWithDot() { assertSplitName("John Smith M.D.", null, "John", null, "Smith", "M.D."); assertJoinedName("John Smith, M.D.", null, "John", null, "Smith", "M.D."); assertSplitName("John Smith D D S", null, "John", null, "Smith", "D D S"); assertJoinedName("John Smith, D D S", null, "John", null, "Smith", "D D S"); } public void testGivenSuffixFamilyName() { assertSplitName("John von Smith", null, "John", null, "von Smith", null); assertJoinedName("John von Smith", null, "John", null, "von Smith", null); } public void testGivenSuffixFamilyNameWithDot() { assertSplitName("John St.Smith", null, "John", null, "St. Smith", null); assertJoinedName("John St. Smith", null, "John", null, "St. Smith", null); } public void testPrefixGivenMiddleFamily() { assertSplitName("Mr. John Kevin Smith", "Mr.", "John", "Kevin", "Smith", null); assertJoinedName("Mr John Kevin Smith", "Mr", "John", "Kevin", "Smith", null); assertSplitName("Mr.John Kevin Smith", "Mr.", "John", "Kevin", "Smith", null); assertJoinedName("Mr. John Kevin Smith", "Mr.", "John", "Kevin", "Smith", null); } public void testPrefixGivenMiddleFamilySuffix() { assertSplitName("Mr. John Kevin Smith Jr.", "Mr.", "John", "Kevin", "Smith", "Jr."); assertJoinedName("Mr John Kevin Smith, Jr.", "Mr", "John", "Kevin", "Smith", "Jr"); } public void testPrefixGivenMiddlePrefixFamilySuffixWrongCapitalization() { assertSplitName("MR. john keVin VON SmiTh JR.", "MR.", "john", "keVin", "VON SmiTh", "JR."); assertJoinedName("MR john keVin VON SmiTh, JR.", "MR", "john", "keVin", "VON SmiTh", "JR"); } public void testPrefixFamilySuffix() { assertSplitName("von Smith Jr.", null, null, null, "von Smith", "Jr."); assertJoinedName("von Smith, Jr.", null, null, null, "von Smith", "Jr"); } public void testFamilyNameGiven() { assertSplitName("Smith, John", null, "John", null, "Smith", null); assertSplitName("Smith , John", null, "John", null, "Smith", null); assertSplitName("Smith, John Kimble", null, "John", "Kimble", "Smith", null); assertSplitName("Smith, John K.", null, "John", "K.", "Smith", null); assertSplitName("Smith, John, Jr.", null, "John", null, "Smith", "Jr."); assertSplitName("Smith, John Kimble, Jr.", null, "John", "Kimble", "Smith", "Jr."); assertSplitName("von Braun, John, Jr.", null, "John", null, "von Braun", "Jr."); assertSplitName("von Braun, John Kimble, Jr.", null, "John", "Kimble", "von Braun", "Jr."); } public void testTwoNamesAndFamilyNameWithAmpersand() { assertSplitName("John & Edward Smith", null, "John & Edward", null, "Smith", null); assertJoinedName("John & Edward Smith", null, "John & Edward", null, "Smith", null); assertSplitName("John and Edward Smith", null, "John and Edward", null, "Smith", null); assertSplitName("Smith, John and Edward", null, "John and Edward", null, "Smith", null); assertJoinedName("John and Edward Smith", null, "John and Edward", null, "Smith", null); } public void testWithMiddleInitialAndNoDot() { assertSplitName("John E. Smith", null, "John", "E.", "Smith", null); assertJoinedName("John E Smith", null, "John", "E", "Smith", null); } public void testWithLongGivenNameAndDot() { assertSplitName("John Ed. K. Smith", null, "John Ed.", "K.", "Smith", null); assertJoinedName("John Ed. K Smith", null, "John Ed.", "K", "Smith", null); } public void testGuessFullNameStyleEmpty() { assertFullNameStyle(FullNameStyle.UNDEFINED, null); assertFullNameStyle(FullNameStyle.UNDEFINED, ""); } public void testGuessFullNameStyleWestern() { // Latin letters assertFullNameStyle(FullNameStyle.WESTERN, "John Doe"); // Starts with a Latin letter, but contains Japanese letters assertFullNameStyle(FullNameStyle.JAPANESE, "A\u3080\u308D\u306A\u307F\u3048"); // Starts with an Extended Latin letter "Latin Capital Ligature OE" assertFullNameStyle(FullNameStyle.WESTERN, "\u0152uvre"); // Non-letters don't make a difference. This one starts with a vertical line assertFullNameStyle(FullNameStyle.WESTERN, "\uFF5C.?+Smith"); } public void testGuessFullNameStyleJapanese() { createNameSplitter(Locale.JAPAN); // Hiragana: always Japanese assertFullNameStyle(FullNameStyle.JAPANESE, "\u3042\u3080\u308D\u306A\u307F\u3048"); // Katakana: always Japanese assertFullNameStyle(FullNameStyle.JAPANESE, "\u30A2\u30E0\u30ED \u30CA\u30DF\u30A8"); // Half-width Katakana: always Japanese assertFullNameStyle(FullNameStyle.JAPANESE, "\uFF71\uFF91\uFF9B \uFF85\uFF90\uFF74"); // Kanji: we cannot tell if this is Japanese, Chinese or Korean, but we are // in Locale.JAPAN, so assume Japanese assertFullNameStyle(FullNameStyle.JAPANESE, "\u5B89\u5BA4\u5948\u7F8E\u6075"); // TODO: mix // Accompanied by a phonetic name in Hiragana, we can safely assume that the // name is Japanese assertFullNameStyle(FullNameStyle.JAPANESE, "\u5B89\u5BA4\u5948\u7F8E\u6075", "\u3042\u3080\u308D", null, "\u306A\u307F\u3048"); // Starts with a latin letter - not Western assertFullNameStyle(FullNameStyle.JAPANESE, "A\u3080\u308D\u306A\u307F\u3048"); } public void testGuessFullNameStyleChinese() { createNameSplitter(Locale.CHINA); // Hanzi: we cannot tell if this is Chinese, Japanese or Korean, // but we are in Locale.CHINA, so assume this is Chinese assertFullNameStyle(FullNameStyle.CHINESE, "\u675C\u9D51"); // Accompanied by a phonetic name in Pinyin, we can safely assume that the // name is Chinese assertFullNameStyle(FullNameStyle.CHINESE, "\u675C\u9D51", "du4", null, "juan1"); // Non-letters don't make a difference. This one starts with a vertical line assertFullNameStyle(FullNameStyle.CHINESE, "\uFF5C--(\u675C\u9D51)"); } public void testGuessPhoneticNameStyle() { // Hiragana assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, "\u3042\u3080\u308D", null, null); assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, null, "\u3042\u3080\u308D", null); assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, null, null, "\u306A\u307F\u3048"); assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, "\u3042\u3080\u308D", null, "\u306A\u307F\u3048"); // Katakana assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, "\u30A2\u30E0\u30ED", null, "\u30CA\u30DF\u30A8"); // Half-width Katakana assertPhoneticNameStyle(PhoneticNameStyle.JAPANESE, "\u30A2\u30E0\u30ED", null, "\u30CA\u30DF\u30A8"); // Chinese assertPhoneticNameStyle(PhoneticNameStyle.PINYIN, "du4", null, "juan1"); } public void testSplitJapaneseName() { createNameSplitter(Locale.JAPAN); // One word is interpreted as given name only assertSplitName("\u3042\u3080\u308D", null, "\u3042\u3080\u308D", null, null, null); // Two words are interpreted as family + give name assertSplitName("\u3042\u3080\u308D \u306A\u307F\u3048", null, "\u306A\u307F\u3048", null, "\u3042\u3080\u308D", null); // Multiple words are interpreted as "family - given names" assertSplitName("\u3042\u3080\u308D \u3068\u304A\u308B \u306A\u307F\u3048", null, "\u3068\u304A\u308B \u306A\u307F\u3048", null, "\u3042\u3080\u308D", null); // Hanzi characters without spaces: lump them all in the given name assertSplitName("\u6BB5\u5C0F\u6D9B", null, "\u6BB5\u5C0F\u6D9B", null, null, null); } public void testSplitChineseName() { createNameSplitter(Locale.CHINA); // Two Hanzi characters: familyName+givenName assertSplitName("\u6BB5\u5C0F", null, "\u5C0F", null, "\u6BB5", null); // Two Hanzi characters: familyName+middleName+givenName assertSplitName("\u6BB5\u5C0F\u6D9B", null, "\u6D9B", "\u5C0F", "\u6BB5", null); // Two Hanzi characters: familyName(2)+middleName+givenName assertSplitName("\u6BB5\u5C0F\u6D9B\u6D9C", null, "\u6D9C", "\u6D9B", "\u6BB5\u5C0F", null); } public void testJoinJapaneseName() { createNameSplitter(Locale.JAPAN); assertJoinedName("\u3042\u3080\u308D", FullNameStyle.JAPANESE, null, "\u3042\u3080\u308D", null, null, null, true); // Given-name-first flag is ignored for CJK locales assertJoinedName("\u3084\u307E\u3056\u304D \u3068\u304A\u308B", FullNameStyle.JAPANESE, null, "\u3068\u304A\u308B", null, "\u3084\u307E\u3056\u304D", null, false); assertJoinedName("\u3084\u307E\u3056\u304D \u3068\u304A\u308B \u3068\u304A\u308B", FullNameStyle.JAPANESE, null, "\u3068\u304A\u308B", "\u3068\u304A\u308B", "\u3084\u307E\u3056\u304D", null, false); } public void testJoinChineseName() { createNameSplitter(Locale.CHINA); // Given-name-first flag is ignored for CJK locales assertJoinedName("\u6BB5\u5C0F\u6D9B", FullNameStyle.CHINESE, null, "\u6D9B", "\u5C0F", "\u6BB5", null, true); assertJoinedName("\u6BB5\u5C0F\u6D9B", FullNameStyle.CHINESE, null, "\u6D9B", "\u5C0F", "\u6BB5", null, false); } private void assertSplitName(String fullName, String prefix, String givenNames, String middleName, String familyName, String suffix) { final Name name = new Name(); mNameSplitter.split(name, fullName); assertEquals(prefix, name.getPrefix()); assertEquals(givenNames, name.getGivenNames()); assertEquals(middleName, name.getMiddleName()); assertEquals(familyName, name.getFamilyName()); assertEquals(suffix, name.getSuffix()); } private void assertJoinedName(String expected, String prefix, String givenNames, String middleName, String familyName, String suffix) { assertJoinedName(expected, FullNameStyle.WESTERN, prefix, givenNames, middleName, familyName, suffix, true); } private void assertJoinedName(String expected, int nameStyle, String prefix, String givenNames, String middleName, String familyName, String suffix, boolean givenNameFirst) { Name name = new Name(); name.fullNameStyle = nameStyle; name.prefix = prefix; name.givenNames = givenNames; name.middleName = middleName; name.familyName = familyName; name.suffix = suffix; String actual = mNameSplitter.join(name, givenNameFirst, true); assertEquals(expected, actual); } private void assertFullNameStyle(int expectedFullNameStyle, String fullName) { Name name = new Name(); mNameSplitter.split(name, fullName); mNameSplitter.guessNameStyle(name); assertEquals(expectedFullNameStyle, name.fullNameStyle); } private void assertFullNameStyle(int expectedFullNameStyle, String fullName, String phoneticFamilyName, String phoneticMiddleName, String phoneticGivenName) { Name name = new Name(); mNameSplitter.split(name, fullName); name.phoneticFamilyName = phoneticFamilyName; name.phoneticMiddleName = phoneticMiddleName; name.phoneticGivenName = phoneticGivenName; mNameSplitter.guessNameStyle(name); assertEquals(expectedFullNameStyle, name.fullNameStyle); } private void assertPhoneticNameStyle(int expectedPhoneticNameStyle, String phoneticFamilyName, String phoneticMiddleName, String phoneticGivenName) { Name name = new Name(); name.phoneticFamilyName = phoneticFamilyName; name.phoneticMiddleName = phoneticMiddleName; name.phoneticGivenName = phoneticGivenName; mNameSplitter.guessNameStyle(name); assertEquals(expectedPhoneticNameStyle, name.phoneticNameStyle); } public void testSplitKoreanName() { createNameSplitter(Locale.KOREA); // Lee - Sang Il assertSplitName("\uC774\uC0C1\uC77C", null, "\uC0C1\uC77C", null, "\uC774", null); // Dok Go - Young Jae assertSplitName("\uB3C5\uACE0\uC601\uC7AC", null, "\uC601\uC7AC", null, "\uB3C5\uACE0", null); } }