1/*
2 * Copyright (C) 2015 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.messaging.util;
18
19import android.content.ContentProviderOperation;
20import android.content.ContentValues;
21import android.database.Cursor;
22import android.net.Uri;
23import android.provider.ContactsContract;
24import android.provider.ContactsContract.Contacts;
25import android.test.suitebuilder.annotation.LargeTest;
26import android.text.TextUtils;
27
28import com.android.messaging.BugleTestCase;
29import com.android.messaging.FakeFactory;
30
31import org.junit.Assert;
32
33import java.util.ArrayList;
34
35/*
36 * Class for testing ContactUtil.
37 */
38@LargeTest
39public class ContactUtilTest extends BugleTestCase {
40    private static final String TEST_NAME_PREFIX = "BugleTest:";
41
42    @Override
43    protected void setUp() throws Exception {
44        super.setUp();
45
46        // TODO: This test will actually mess with contacts on your phone.
47        // Ideally we would use a fake content provider to give us contact data...
48        FakeFactory.registerWithoutFakeContext(getTestContext());
49
50        // add test contacts.
51        addTestContact("John", "650-123-1233", "john@gmail.com", false);
52        addTestContact("Joe", "(650)123-1233", "joe@gmail.com", false);
53        addTestContact("Jim", "650 123 1233", "jim@gmail.com", false);
54        addTestContact("Samantha", "650-123-1235", "samantha@gmail.com", true);
55        addTestContact("Adrienne", "650-123-1236", "adrienne@gmail.com", true);
56    }
57
58    @Override
59    protected void tearDown() throws Exception {
60        deleteTestContacts();
61        super.tearDown();
62    }
63
64    /**
65     * Add a test contact based on contact name, phone and email.
66     */
67    private void addTestContact(
68            final String name, final String phone, final String email, final boolean starred)
69            throws Exception {
70        final ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
71
72        ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
73                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
74                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
75                .build());
76
77        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
78                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
79                .withValue(ContactsContract.Data.MIMETYPE,
80                        ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
81                .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
82                        TEST_NAME_PREFIX + name).build());
83
84        if (phone != null) {
85            ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
86                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
87                    .withValue(ContactsContract.Data.MIMETYPE,
88                            ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
89                    .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
90                    .withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
91                            ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
92                    .build());
93        }
94
95        if (email != null) {
96            ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
97                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
98                    .withValue(ContactsContract.Data.MIMETYPE,
99                            ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
100                    .withValue(ContactsContract.CommonDataKinds.Email.DATA, email)
101                    .withValue(ContactsContract.CommonDataKinds.Email.TYPE,
102                            ContactsContract.CommonDataKinds.Email.TYPE_WORK)
103                    .build());
104        }
105
106        mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
107
108        // Star the whole contact if needed.
109        if (starred) {
110            final ContentValues values = new ContentValues();
111            values.put(Contacts.STARRED, 1);
112            getContext().getContentResolver().update(Contacts.CONTENT_URI, values,
113                    Contacts.DISPLAY_NAME + "= ?", new String[] { TEST_NAME_PREFIX + name });
114        }
115    }
116
117    /**
118     * Remove test contacts added during test setup.
119     */
120    private void deleteTestContacts() {
121        final Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
122                Uri.encode(TEST_NAME_PREFIX));
123        final Cursor cur =
124                mContext.getContentResolver().query(contactUri, null, null, null, null);
125        try {
126            if (cur.moveToFirst()) {
127                do {
128                    final String lookupKey = cur.getString(cur.getColumnIndex(Contacts.LOOKUP_KEY));
129                    final Uri uri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey);
130                    mContext.getContentResolver().delete(uri, null, null);
131                } while (cur.moveToNext());
132            }
133        } catch (final Exception e) {
134            System.out.println(e.getStackTrace());
135        }
136    }
137
138    /**
139     * Verify ContactUtil.getPhone will return all phones, including the ones added for test.
140     */
141    public void ingoredTestGetPhones() {
142        final Cursor cur = ContactUtil.getPhones(getContext())
143                .performSynchronousQuery();
144
145        LogUtil.i(LogUtil.BUGLE_TAG, "testGetPhones: Number of phones on the device:" +
146                cur.getCount());
147
148        verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
149        verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
150        verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
151        verifyCursorContains(cur, TEST_NAME_PREFIX + "Samantha");
152        verifyCursorContains(cur, TEST_NAME_PREFIX + "Adrienne");
153    }
154
155    /**
156     * Verify ContactUtil.filterPhone will work on name based matches.
157     */
158    public void ingoredTestFilterPhonesByName() {
159        final Cursor cur = ContactUtil.filterPhones(getContext(), TEST_NAME_PREFIX)
160                .performSynchronousQuery();
161
162        if (cur.getCount() != 5) {
163            Assert.fail("Cursor should have size of 5");
164            return;
165        }
166
167        verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
168        verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
169        verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
170        verifyCursorContains(cur, TEST_NAME_PREFIX + "Samantha");
171        verifyCursorContains(cur, TEST_NAME_PREFIX + "Adrienne");
172    }
173
174    /**
175     * Verify ContactUtil.filterPhone will work on partial number matches.
176     */
177    public void ingoredTestFilterPhonesByPartialNumber() {
178        final String[] filters = new String[] { "650123", "650-123", "(650)123", "650 123" };
179
180        for (final String filter : filters) {
181            final Cursor cur = ContactUtil.filterPhones(getContext(), filter)
182                    .performSynchronousQuery();
183
184            LogUtil.i(LogUtil.BUGLE_TAG, "testFilterPhonesByPartialNumber: Number of phones:" +
185                    cur.getCount());
186
187            verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
188            verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
189            verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
190            verifyCursorContains(cur, TEST_NAME_PREFIX + "Samantha");
191            verifyCursorContains(cur, TEST_NAME_PREFIX + "Adrienne");
192        }
193    }
194
195    /**
196     * Verify ContactUtil.filterPhone will work on full number matches.
197     */
198    public void ingoredTestFilterPhonesByFullNumber() {
199        final String[] filters = new String[] {
200                "6501231233", "650-123-1233", "(650)123-1233", "650 123 1233" };
201
202        for (final String filter : filters) {
203            final Cursor cur = ContactUtil.filterPhones(getContext(), filter)
204                    .performSynchronousQuery();
205
206            LogUtil.i(LogUtil.BUGLE_TAG, "testFilterPhonesByFullNumber: Number of phones:" +
207                    cur.getCount());
208
209            verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
210            verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
211            verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
212        }
213    }
214
215    /**
216     * Verify ContactUtil.lookPhone will work on number including area code.
217     */
218    public void ingoredTestLookupPhoneWithAreaCode() {
219        final String[] filters = new String[] {
220                "6501231233", "650-123-1233", "(650)123-1233", "650 123 1233" };
221
222        for (final String filter : filters) {
223            final Cursor cur = ContactUtil.lookupPhone(getContext(), filter)
224                    .performSynchronousQuery();
225
226            LogUtil.i(LogUtil.BUGLE_TAG, "testLookupPhoneWithAreaCode: Number of phones:" +
227                    cur.getCount());
228
229            verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
230            verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
231            verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
232        }
233    }
234
235    /**
236     * Verify ContactUtil.lookPhone will work on number without area code.
237     */
238    public void ingoredTestLookupPhoneWithoutAreaCode() {
239        final String[] filters = new String[] {
240                "1231233", "123-1233", "123 1233" };
241
242        for (final String filter : filters) {
243            final Cursor cur = ContactUtil.lookupPhone(getContext(), filter)
244                    .performSynchronousQuery();
245
246            LogUtil.i(LogUtil.BUGLE_TAG, "testLookupPhoneWithoutAreaCode: Number of phones:" +
247                    cur.getCount());
248
249            verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
250            verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
251            verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
252        }
253    }
254
255    public void ingoredTestGetFrequentPhones() {
256        final Cursor cur = ContactUtil.getFrequentContacts(getContext())
257                .performSynchronousQuery();
258
259        LogUtil.i(LogUtil.BUGLE_TAG, "testGetFrequentPhones: Number of phones on the device:" +
260                cur.getCount());
261
262        verifyCursorContains(cur, TEST_NAME_PREFIX + "Samantha");
263        verifyCursorContains(cur, TEST_NAME_PREFIX + "Adrienne");
264    }
265
266    /**
267     * Verify ContactUtil.filterEmails will work on partial email.
268     */
269    public void ingoredTestFilterEmails() {
270        final Cursor cur = ContactUtil.filterEmails(getContext(), "john@")
271                .performSynchronousQuery();
272
273        LogUtil.i(LogUtil.BUGLE_TAG, "testFilterEmails: Number of emails:" +
274                cur.getCount());
275
276        verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
277    }
278
279    /**
280     * Verify ContactUtil.lookupEmail will work on full email.
281     */
282    public void ingoredTestLookupEmail() {
283        final Cursor cur = ContactUtil.lookupEmail(getContext(), "john@gmail.com")
284                .performSynchronousQuery();
285
286        LogUtil.i(LogUtil.BUGLE_TAG, "testLookupEmail: Number of emails:" +
287                cur.getCount());
288
289        verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
290    }
291
292    /**
293     * Utility method to check whether cursor contains a particular contact.
294     */
295    private void verifyCursorContains(final Cursor cursor, final String nameToVerify) {
296        if (cursor.moveToFirst()) {
297            do {
298                final String name = cursor.getString(ContactUtil.INDEX_DISPLAY_NAME);
299                if (TextUtils.equals(name, nameToVerify)) {
300                    return;
301                }
302            } while (cursor.moveToNext());
303        }
304        Assert.fail("Cursor should have " + nameToVerify);
305    }
306}
307