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 
17 package com.android.messaging.util;
18 
19 import android.content.ContentProviderOperation;
20 import android.content.ContentValues;
21 import android.database.Cursor;
22 import android.net.Uri;
23 import android.provider.ContactsContract;
24 import android.provider.ContactsContract.Contacts;
25 import android.test.suitebuilder.annotation.LargeTest;
26 import android.text.TextUtils;
27 
28 import com.android.messaging.BugleTestCase;
29 import com.android.messaging.FakeFactory;
30 
31 import org.junit.Assert;
32 
33 import java.util.ArrayList;
34 
35 /*
36  * Class for testing ContactUtil.
37  */
38 @LargeTest
39 public class ContactUtilTest extends BugleTestCase {
40     private static final String TEST_NAME_PREFIX = "BugleTest:";
41 
42     @Override
setUp()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
tearDown()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      */
addTestContact( final String name, final String phone, final String email, final boolean starred)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      */
deleteTestContacts()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      */
ingoredTestGetPhones()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      */
ingoredTestFilterPhonesByName()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      */
ingoredTestFilterPhonesByPartialNumber()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      */
ingoredTestFilterPhonesByFullNumber()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      */
ingoredTestLookupPhoneWithAreaCode()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      */
ingoredTestLookupPhoneWithoutAreaCode()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 
ingoredTestGetFrequentPhones()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      */
ingoredTestFilterEmails()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      */
ingoredTestLookupEmail()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      */
verifyCursorContains(final Cursor cursor, final String nameToVerify)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