• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 package com.android.contacts.model;
17 
18 import android.content.ContentProvider;
19 import android.content.ContentResolver;
20 import android.database.Cursor;
21 import android.database.MatrixCursor;
22 import android.net.Uri;
23 import android.os.CancellationSignal;
24 import android.provider.ContactsContract;
25 import android.provider.ContactsContract.RawContacts;
26 import android.support.annotation.Nullable;
27 import android.test.AndroidTestCase;
28 import android.test.mock.MockContentResolver;
29 import android.test.suitebuilder.annotation.SmallTest;
30 
31 import com.android.contacts.test.mocks.MockContentProvider;
32 import com.android.contacts.tests.FakeDeviceAccountTypeFactory;
33 import com.android.contacts.util.DeviceLocalAccountTypeFactory;
34 
35 import java.util.Arrays;
36 import java.util.Collections;
37 import java.util.HashMap;
38 import java.util.HashSet;
39 import java.util.List;
40 import java.util.Map;
41 
42 @SmallTest
43 public class Cp2DeviceLocalAccountLocatorTests extends AndroidTestCase {
44 
45     // Basic smoke test that just checks that it doesn't throw when loading from CP2. We don't
46     // care what CP2 actually contains for this.
testShouldNotCrash()47     public void testShouldNotCrash() {
48         final DeviceLocalAccountLocator sut = new Cp2DeviceLocalAccountLocator(
49                 getContext().getContentResolver(),
50                 new DeviceLocalAccountTypeFactory.Default(getContext()),
51                 Collections.<String>emptySet());
52         sut.getDeviceLocalAccounts();
53         // We didn't throw so it passed
54     }
55 
test_getDeviceLocalAccounts_returnsEmptyListWhenQueryReturnsNull()56     public void test_getDeviceLocalAccounts_returnsEmptyListWhenQueryReturnsNull() {
57         final DeviceLocalAccountLocator sut = createWithQueryResult(null);
58         assertTrue(sut.getDeviceLocalAccounts().isEmpty());
59     }
60 
test_getDeviceLocalAccounts_returnsEmptyListWhenNoRawContactsHaveDeviceType()61     public void test_getDeviceLocalAccounts_returnsEmptyListWhenNoRawContactsHaveDeviceType() {
62         final DeviceLocalAccountLocator sut = createWithQueryResult(queryResult(
63                         "user", "com.example",
64                         "user", "com.example",
65                         "user", "com.example"));
66         assertTrue(sut.getDeviceLocalAccounts().isEmpty());
67     }
68 
test_getDeviceLocalAccounts_returnsListWithItemForNullAccount()69     public void test_getDeviceLocalAccounts_returnsListWithItemForNullAccount() {
70         final DeviceLocalAccountLocator sut = createWithQueryResult(queryResult(
71                 "user", "com.example",
72                 null, null,
73                 "user", "com.example",
74                 null, null));
75 
76         assertEquals(1, sut.getDeviceLocalAccounts().size());
77     }
78 
test_getDeviceLocalAccounts_containsItemForEachDeviceAccount()79     public void test_getDeviceLocalAccounts_containsItemForEachDeviceAccount() {
80         final DeviceLocalAccountTypeFactory stubFactory = new FakeDeviceAccountTypeFactory()
81                 .withDeviceTypes(null, "vnd.sec.contact.phone")
82                 .withSimTypes("vnd.sec.contact.sim");
83         final DeviceLocalAccountLocator sut = createLocator(queryResult(
84                 "user", "com.example",
85                 "user", "com.example",
86                 "phone_account", "vnd.sec.contact.phone",
87                 null, null,
88                 "phone_account", "vnd.sec.contact.phone",
89                 "user", "com.example",
90                 null, null,
91                 "sim_account", "vnd.sec.contact.sim",
92                 "sim_account_2", "vnd.sec.contact.sim"
93         ), stubFactory);
94 
95 
96         assertEquals(4, sut.getDeviceLocalAccounts().size());
97     }
98 
test_getDeviceLocalAccounts_doesNotContainItemsForKnownAccountTypes()99     public void test_getDeviceLocalAccounts_doesNotContainItemsForKnownAccountTypes() {
100         final Cp2DeviceLocalAccountLocator sut = new Cp2DeviceLocalAccountLocator(
101                 getContext().getContentResolver(), new FakeDeviceAccountTypeFactory(),
102                 new HashSet<>(Arrays.asList("com.example", "com.example.1")));
103 
104         assertTrue("Selection should filter known accounts",
105                 sut.getSelection().contains("NOT IN (?,?)"));
106 
107         final List<String> args = Arrays.asList(sut.getSelectionArgs());
108         assertEquals(2, args.size());
109         assertTrue("Selection args is missing an expected value", args.contains("com.example"));
110         assertTrue("Selection args is missing an expected value", args.contains("com.example.1"));
111     }
112 
test_getDeviceLocalAccounts_includesAccountsFromSettings()113     public void test_getDeviceLocalAccounts_includesAccountsFromSettings() {
114         final DeviceLocalAccountTypeFactory stubFactory = new FakeDeviceAccountTypeFactory()
115                 .withDeviceTypes(null, "vnd.sec.contact.phone")
116                 .withSimTypes("vnd.sec.contact.sim");
117         final DeviceLocalAccountLocator sut = createLocator(new FakeContactsProvider()
118                 .withQueryResult(ContactsContract.Settings.CONTENT_URI, queryResult(
119                         "phone_account", "vnd.sec.contact.phone",
120                         "sim_account", "vnd.sec.contact.sim"
121                 )), stubFactory);
122 
123         assertEquals(2, sut.getDeviceLocalAccounts().size());
124     }
125 
test_getDeviceLocalAccounts_includesAccountsFromGroups()126     public void test_getDeviceLocalAccounts_includesAccountsFromGroups() {
127         final DeviceLocalAccountTypeFactory stubFactory = new FakeDeviceAccountTypeFactory()
128                 .withDeviceTypes(null, "vnd.sec.contact.phone")
129                 .withSimTypes("vnd.sec.contact.sim");
130         final DeviceLocalAccountLocator sut = createLocator(new FakeContactsProvider()
131                 .withQueryResult(ContactsContract.Groups.CONTENT_URI, queryResult(
132                         "phone_account", "vnd.sec.contact.phone",
133                         "sim_account", "vnd.sec.contact.sim"
134                 )), stubFactory);
135 
136         assertEquals(2, sut.getDeviceLocalAccounts().size());
137     }
138 
createWithQueryResult( Cursor cursor)139     private DeviceLocalAccountLocator createWithQueryResult(
140             Cursor cursor) {
141         return createLocator(cursor, new DeviceLocalAccountTypeFactory.Default(mContext));
142     }
143 
createLocator(ContentProvider contactsProvider, DeviceLocalAccountTypeFactory localAccountTypeFactory)144     private DeviceLocalAccountLocator createLocator(ContentProvider contactsProvider,
145             DeviceLocalAccountTypeFactory localAccountTypeFactory) {
146         final DeviceLocalAccountLocator locator = new Cp2DeviceLocalAccountLocator(
147                 createContentResolverWithProvider(contactsProvider),
148                 localAccountTypeFactory, Collections.<String>emptySet());
149         return locator;
150     }
151 
createLocator(Cursor cursor, DeviceLocalAccountTypeFactory localAccountTypeFactory)152     private DeviceLocalAccountLocator createLocator(Cursor cursor,
153             DeviceLocalAccountTypeFactory localAccountTypeFactory) {
154         final DeviceLocalAccountLocator locator = new Cp2DeviceLocalAccountLocator(
155                 createStubResolverWithContentQueryResult(cursor),
156                 localAccountTypeFactory,
157                 Collections.<String>emptySet());
158         return locator;
159     }
160 
createContentResolverWithProvider(ContentProvider contactsProvider)161     private ContentResolver createContentResolverWithProvider(ContentProvider contactsProvider) {
162         final MockContentResolver resolver = new MockContentResolver();
163         resolver.addProvider(ContactsContract.AUTHORITY, contactsProvider);
164         return resolver;
165     }
166 
createStubResolverWithContentQueryResult(Cursor cursor)167     private ContentResolver createStubResolverWithContentQueryResult(Cursor cursor) {
168         final MockContentResolver resolver = new MockContentResolver();
169         resolver.addProvider(ContactsContract.AUTHORITY, new FakeContactsProvider()
170                 .withDefaultQueryResult(cursor));
171         return resolver;
172     }
173 
queryResult(String... nameTypePairs)174     private Cursor queryResult(String... nameTypePairs) {
175         final MatrixCursor cursor = new MatrixCursor(new String[]
176                 { RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE, RawContacts.DATA_SET });
177         for (int i = 0; i < nameTypePairs.length; i+=2) {
178             cursor.newRow().add(nameTypePairs[i]).add(nameTypePairs[i+1])
179                     .add(null);
180         }
181         return cursor;
182     }
183 
184     private static class FakeContactsProvider extends MockContentProvider {
185         public Cursor mNextQueryResult;
186         public Map<Uri, Cursor> mNextResultMapping = new HashMap<>();
187 
FakeContactsProvider()188         public FakeContactsProvider() {}
189 
withDefaultQueryResult(Cursor cursor)190         public FakeContactsProvider withDefaultQueryResult(Cursor cursor) {
191             mNextQueryResult = cursor;
192             return this;
193         }
194 
withQueryResult(Uri uri, Cursor cursor)195         public FakeContactsProvider withQueryResult(Uri uri, Cursor cursor) {
196             mNextResultMapping.put(uri, cursor);
197             return this;
198         }
199 
200         @Override
query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)201         public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
202                 String sortOrder) {
203             return query(uri, projection, selection, selectionArgs, sortOrder, null);
204         }
205 
206         @Nullable
207         @Override
query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal)208         public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
209                 String sortOrder, CancellationSignal cancellationSignal) {
210             final Cursor result = mNextResultMapping.get(uri);
211             if (result == null) {
212                 return mNextQueryResult;
213             } else {
214                 return result;
215             }
216         }
217     }
218 }
219