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
17package com.android.providers.contacts;
18
19import android.provider.ContactsContract.FullNameStyle;
20import android.test.suitebuilder.annotation.SmallTest;
21
22import junit.framework.TestCase;
23
24import java.text.Collator;
25import java.util.Arrays;
26import java.util.Locale;
27
28/**
29 * Unit tests for {@link NameLookupBuilder}.
30 *
31 * Run the test like this:
32 * <code>
33 * adb shell am instrument -e class com.android.providers.contacts.NameLookupBuilderTest -w \
34 *         com.android.providers.contacts.tests/android.test.InstrumentationTestRunner
35 * </code>
36 */
37@SmallTest
38public class NameLookupBuilderTest extends TestCase {
39
40    private static class TestNameLookupBuilder extends NameLookupBuilder {
41
42        StringBuilder sb = new StringBuilder();
43
44        public TestNameLookupBuilder(NameSplitter splitter) {
45            super(splitter);
46        }
47
48        @Override
49        protected String normalizeName(String name) {
50
51            // TO make the test more readable, simply return the name unnormalized
52            return name;
53        }
54
55        @Override
56        protected String[] getCommonNicknameClusters(String normalizedName) {
57            if (normalizedName.equals("Bill")) {
58                return new String[] {"*William"};
59            } else if (normalizedName.equals("Al")) {
60                return new String[] {"*Alex", "*Alice"};
61            }
62            return null;
63        }
64
65        public String inserted() {
66            return sb.toString();
67        }
68
69        @Override
70        protected void insertNameLookup(long rawContactId, long dataId, int lookupType,
71                String string) {
72            sb.append("(").append(lookupType).append(":").append(string).append(")");
73        }
74    }
75
76    private TestNameLookupBuilder mBuilder;
77
78    @Override
79    protected void setUp() throws Exception {
80        super.setUp();
81        mBuilder = new TestNameLookupBuilder(
82                new NameSplitter("Mr", "", "", "", Locale.getDefault()));
83    }
84
85    public void testEmptyName() {
86        mBuilder.insertNameLookup(0, 0, "", FullNameStyle.UNDEFINED);
87        assertEquals("", mBuilder.inserted());
88    }
89
90    public void testSingleUniqueName() {
91        mBuilder.insertNameLookup(0, 0, "Foo", FullNameStyle.UNDEFINED);
92        assertEquals("(0:Foo)(2:Foo)", mBuilder.inserted());
93    }
94
95    public void testSingleUniqueNameWithPrefix() {
96        mBuilder.insertNameLookup(0, 0, "Mr. Foo", FullNameStyle.UNDEFINED);
97        assertEquals("(0:Foo)(2:Foo)", mBuilder.inserted());
98    }
99
100    public void testTwoUniqueNames() {
101        mBuilder.insertNameLookup(0, 0, "Foo Bar", FullNameStyle.UNDEFINED);
102        assertEquals("(0:Foo.Bar)(2:FooBar)(1:Bar.Foo)(2:BarFoo)", mBuilder.inserted());
103    }
104
105    public void testThreeUniqueNames() {
106        mBuilder.insertNameLookup(0, 0, "Foo Bar Baz", FullNameStyle.UNDEFINED);
107
108        // All permutations
109        assertEquals(
110                "(0:Foo.Bar.Baz)(2:FooBarBaz)" +
111                "(1:Foo.Baz.Bar)(2:FooBazBar)" +
112
113                "(1:Bar.Foo.Baz)(2:BarFooBaz)" +
114                "(1:Bar.Baz.Foo)(2:BarBazFoo)" +
115
116                "(1:Baz.Bar.Foo)(2:BazBarFoo)" +
117                "(1:Baz.Foo.Bar)(2:BazFooBar)", mBuilder.inserted());
118    }
119
120    public void testFourUniqueNames() {
121        mBuilder.insertNameLookup(0, 0, "Foo Bar Baz Biz", FullNameStyle.UNDEFINED);
122
123        // All permutations
124        assertEquals(
125                "(0:Foo.Bar.Baz.Biz)(2:FooBarBazBiz)" +
126                "(1:Foo.Bar.Biz.Baz)(2:FooBarBizBaz)" +
127                "(1:Foo.Baz.Bar.Biz)(2:FooBazBarBiz)" +
128                "(1:Foo.Baz.Biz.Bar)(2:FooBazBizBar)" +
129                "(1:Foo.Biz.Baz.Bar)(2:FooBizBazBar)" +
130                "(1:Foo.Biz.Bar.Baz)(2:FooBizBarBaz)" +
131
132                "(1:Bar.Foo.Baz.Biz)(2:BarFooBazBiz)" +
133                "(1:Bar.Foo.Biz.Baz)(2:BarFooBizBaz)" +
134                "(1:Bar.Baz.Foo.Biz)(2:BarBazFooBiz)" +
135                "(1:Bar.Baz.Biz.Foo)(2:BarBazBizFoo)" +
136                "(1:Bar.Biz.Baz.Foo)(2:BarBizBazFoo)" +
137                "(1:Bar.Biz.Foo.Baz)(2:BarBizFooBaz)" +
138
139                "(1:Baz.Bar.Foo.Biz)(2:BazBarFooBiz)" +
140                "(1:Baz.Bar.Biz.Foo)(2:BazBarBizFoo)" +
141                "(1:Baz.Foo.Bar.Biz)(2:BazFooBarBiz)" +
142                "(1:Baz.Foo.Biz.Bar)(2:BazFooBizBar)" +
143                "(1:Baz.Biz.Foo.Bar)(2:BazBizFooBar)" +
144                "(1:Baz.Biz.Bar.Foo)(2:BazBizBarFoo)" +
145
146                "(1:Biz.Bar.Baz.Foo)(2:BizBarBazFoo)" +
147                "(1:Biz.Bar.Foo.Baz)(2:BizBarFooBaz)" +
148                "(1:Biz.Baz.Bar.Foo)(2:BizBazBarFoo)" +
149                "(1:Biz.Baz.Foo.Bar)(2:BizBazFooBar)" +
150                "(1:Biz.Foo.Baz.Bar)(2:BizFooBazBar)" +
151                "(1:Biz.Foo.Bar.Baz)(2:BizFooBarBaz)", mBuilder.inserted());
152    }
153
154    public void testSingleNickname() {
155        mBuilder.insertNameLookup(0, 0, "Bill", FullNameStyle.UNDEFINED);
156        assertEquals("(0:Bill)(2:Bill)(1:*William)", mBuilder.inserted());
157    }
158
159    public void testSingleNameWithTwoNicknames() {
160        mBuilder.insertNameLookup(0, 0, "Al", FullNameStyle.UNDEFINED);
161        assertEquals("(0:Al)(2:Al)(1:*Alex)(1:*Alice)", mBuilder.inserted());
162    }
163
164    public void testTwoNamesOneOfWhichIsNickname() {
165        mBuilder.insertNameLookup(0, 0, "Foo Al", FullNameStyle.UNDEFINED);
166        assertEquals(
167                "(0:Foo.Al)(2:FooAl)" +
168                "(1:Al.Foo)(2:AlFoo)" +
169                "(1:Foo.*Alex)(1:*Alex.Foo)" +
170                "(1:Foo.*Alice)(1:*Alice.Foo)", mBuilder.inserted());
171    }
172
173    public void testTwoNamesBothNickname() {
174        mBuilder.insertNameLookup(0, 0, "Bill Al", FullNameStyle.UNDEFINED);
175        assertEquals(
176                "(0:Bill.Al)(2:BillAl)" +
177                "(1:Al.Bill)(2:AlBill)" +
178                "(1:*William.Al)(1:Al.*William)" +
179                "(1:*William.*Alex)(1:*Alex.*William)" +
180                "(1:*William.*Alice)(1:*Alice.*William)" +
181                "(1:Bill.*Alex)(1:*Alex.Bill)" +
182                "(1:Bill.*Alice)(1:*Alice.Bill)", mBuilder.inserted());
183    }
184
185    public void testChineseName() {
186        // Only run this test when Chinese collation is supported
187        if (!Arrays.asList(Collator.getAvailableLocales()).contains(Locale.CHINA)) {
188            return;
189        }
190
191        mBuilder.insertNameLookup(0, 0, "\u695A\u8FAD", FullNameStyle.CHINESE);
192        assertEquals(
193                "(0:\u695A\u8FAD)" +
194                "(2:\u695A\u8FAD)",
195                mBuilder.inserted());
196    }
197
198    public void testKoreanName() {
199        // Only run this test when Korean collation is supported.
200        if (!Arrays.asList(Collator.getAvailableLocales()).contains(Locale.KOREA)) {
201            return;
202        }
203
204        // Lee Sang Il
205        mBuilder.insertNameLookup(0, 0, "\uC774\uC0C1\uC77C", FullNameStyle.KOREAN);
206        assertEquals(
207                "(0:\uC774\uC0C1\uC77C)" + // Lee Sang Il
208                "(2:\uC774\uC0C1\uC77C)",
209                mBuilder.inserted());
210    }
211
212    public void testKoreanNameWithTwoCharactersFamilyName() {
213        // Only run this test when Chinese collation is supported.
214        if (!Arrays.asList(Collator.getAvailableLocales()).contains(Locale.KOREA)) {
215            return;
216        }
217
218        // Sun Woo Young Nyeu
219        mBuilder.insertNameLookup(0, 0, "\uC120\uC6B0\uC6A9\uB140", FullNameStyle.KOREAN);
220        assertEquals(
221                "(0:\uC120\uC6B0\uC6A9\uB140)" + // Sun Woo Young Nyeu
222                "(2:\uC120\uC6B0\uC6A9\uB140)",  // Sun Woo Young Nyeu
223                mBuilder.inserted());
224    }
225
226    public void testMultiwordName() {
227        mBuilder.insertNameLookup(0, 0, "Jo Jeffrey John Jessy Longname", FullNameStyle.UNDEFINED);
228        String actual = mBuilder.inserted();
229
230        // Exact name
231        assertTrue(actual.contains("(0:Jo.Jeffrey.John.Jessy.Longname)"));
232
233        // Full collation key
234        assertTrue(actual.contains("(2:JoJeffreyJohnJessyLongname)"));
235
236        // Variant: four longest parts
237        assertTrue(actual.contains("(1:Longname.Jeffrey.Jessy.John)"));
238
239        // All individual words
240        assertTrue(actual.contains("(2:Jo"));
241        assertTrue(actual.contains("(2:Jeffrey"));
242        assertTrue(actual.contains("(2:John"));
243        assertTrue(actual.contains("(2:Jessy"));
244        assertTrue(actual.contains("(2:Longname"));
245    }
246}
247