blob: b500629f20ee51f6780bbd94589a0f8a10de938c [file] [log] [blame]
/*
* Copyright (C) 2020 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.ims.rcs.uce.eab;
import static android.provider.ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.SharedPreferences;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.test.mock.MockContentResolver;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.rule.provider.ProviderTestRule;
import com.android.ims.ImsTestBase;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class EabContactSyncControllerTest extends ImsTestBase {
private static final String TAG = "EabContactDataSyncServiceTest";
FakeContactProvider mFakeContactProvider = new FakeContactProvider();
@Rule
public ProviderTestRule mProviderTestRule = new ProviderTestRule.Builder(
EabProvider.class, EabProvider.AUTHORITY).build();
@Mock private SharedPreferences mSharedPreferences;
@Mock private SharedPreferences.Editor mSharedPreferencesEditor;
@Before
public void setUp() throws Exception {
super.setUp();
MockContentResolver mockContentResolver =
(MockContentResolver) mProviderTestRule.getResolver();
ProviderInfo providerInfo = new ProviderInfo();
providerInfo.authority = ContactsContract.AUTHORITY;
mFakeContactProvider.attachInfo(mContext, providerInfo);
mockContentResolver.addProvider(providerInfo.authority, mFakeContactProvider);
doReturn("com.android.phone.tests").when(mContext).getPackageName();
doReturn(mProviderTestRule.getResolver()).when(mContext).getContentResolver();
doReturn(mSharedPreferences).when(mContext).getSharedPreferences(anyString(), anyInt());
doReturn(0L).when(mSharedPreferences).getLong(anyString(), anyInt());
doReturn(mSharedPreferencesEditor).when(mSharedPreferences).edit();
doReturn(mSharedPreferencesEditor).when(mSharedPreferencesEditor).putLong(anyString(),
anyLong());
}
@After
public void tearDown() throws Exception {
super.tearDown();
mFakeContactProvider.clearData();
mContext.getContentResolver().delete(EabProvider.CONTACT_URI, null, null);
}
@Test
public void testContactDeletedCase() {
insertContactToEabProvider(1, 2, 3, "123456");
insertDeletedContactToContactProvider(1, 1);
new EabContactSyncController().syncContactToEabProvider(mContext);
Cursor result = mProviderTestRule.getResolver().query(
EabProvider.CONTACT_URI,
null,
null,
null);
assertEquals(0, result.getCount());
}
@Test
public void testMultipleContactsDeletedCase() {
// Insert 3 contacts in EabProvider
insertContactToEabProvider(1, 1, 1, "123456");
insertContactToEabProvider(2, 2, 2, "1234567");
insertContactToEabProvider(3, 3, 3, "12345678");
// Insert 2 deleted contacts
insertDeletedContactToContactProvider(1, 1);
insertDeletedContactToContactProvider(2, 1);
new EabContactSyncController().syncContactToEabProvider(mContext);
// Make sure only 1 contact in Eab DB
Cursor result = mProviderTestRule.getResolver().query(
EabProvider.CONTACT_URI,
null,
null,
null);
assertEquals(1, result.getCount());
}
@Test
public void testPhoneNumberDeletedCase() {
insertContactToEabProvider(1, 1, 2, "123456");
insertContactToEabProvider(1, 1, 3, "1234567");
insertContactToEabProvider(1, 1, 4, "12345678");
// Delete phone number 12345678
insertContactToContactProvider(1, 1, 2, "123456");
insertContactToContactProvider(1, 1, 3, "1234567");
new EabContactSyncController().syncContactToEabProvider(mContext);
Cursor result = mProviderTestRule.getResolver().query(
EabProvider.CONTACT_URI,
null,
null,
null);
assertEquals(2, result.getCount());
}
@Test
public void testPhoneNumberUpdatedCase() {
insertContactToEabProvider(1, 1, 2, "123456");
insertContactToEabProvider(1, 1, 3, "1234567");
insertContactToEabProvider(1, 1, 4, "12345678");
// Update phone number to 1,2,3
insertContactToContactProvider(1, 1, 2, "1");
insertContactToContactProvider(1, 1, 3, "2");
insertContactToContactProvider(1, 1, 4, "3");
new EabContactSyncController().syncContactToEabProvider(mContext);
Cursor result = mProviderTestRule.getResolver().query(
EabProvider.CONTACT_URI,
null,
null,
null,
EabProvider.ContactColumns.DATA_ID);
result.moveToFirst();
assertEquals(3, result.getCount());
assertEquals("1",
result.getString(result.getColumnIndex(EabProvider.ContactColumns.PHONE_NUMBER)));
result.moveToNext();
assertEquals("2",
result.getString(result.getColumnIndex(EabProvider.ContactColumns.PHONE_NUMBER)));
result.moveToNext();
assertEquals("3",
result.getString(result.getColumnIndex(EabProvider.ContactColumns.PHONE_NUMBER)));
}
private void insertDeletedContactToContactProvider(int contactId, int timestamp) {
ContentValues values = new ContentValues();
values.put(ContactsContract.DeletedContacts.CONTACT_ID, contactId);
values.put(ContactsContract.DeletedContacts.CONTACT_DELETED_TIMESTAMP, timestamp);
mContext.getContentResolver().insert(
ContactsContract.DeletedContacts.CONTENT_URI, values);
}
private void insertContactToContactProvider(
int contactId, int rawContactId, int dataId, String number) {
ContentValues values = new ContentValues();
values.put(ContactsContract.Data._ID, dataId);
values.put(EabProvider.ContactColumns.CONTACT_ID, contactId);
values.put(ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID, rawContactId);
values.put(ContactsContract.Data.MIMETYPE, CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, number);
values.put(ContactsContract.CommonDataKinds.Phone.CONTACT_LAST_UPDATED_TIMESTAMP, 1);
mContext.getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
}
private void insertContactToEabProvider(int contactId,
int rawContactId, int dataId, String phoneNumber) {
ContentValues values = new ContentValues();
values.put(EabProvider.ContactColumns.CONTACT_ID, contactId);
values.put(EabProvider.ContactColumns.RAW_CONTACT_ID, rawContactId);
values.put(EabProvider.ContactColumns.DATA_ID, dataId);
values.put(EabProvider.ContactColumns.PHONE_NUMBER, phoneNumber);
mContext.getContentResolver().insert(EabProvider.CONTACT_URI, values);
}
/**
* Create a fake contact provider that store ContentValues in hashmap when invoke insert()
* and convert to cursor when invoke query()
*/
public static class FakeContactProvider extends ContentProvider {
private final HashMap<Uri, List<ContentValues>> mFakeProviderData = new HashMap<>();
public FakeContactProvider() {
}
public void clearData() {
mFakeProviderData.clear();
}
@Override
public boolean onCreate() {
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
return convertContentValuesToCursor(mFakeProviderData.get(uri));
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
List<ContentValues> allDataList =
mFakeProviderData.computeIfAbsent(uri, k -> new ArrayList<>());
allDataList.add(new ContentValues(values));
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values,
@Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
private Cursor convertContentValuesToCursor(List<ContentValues> valuesList) {
if (valuesList != null) {
MatrixCursor result =
new MatrixCursor(valuesList.get(0).keySet().toArray(new String[0]));
for (ContentValues contentValue : valuesList) {
MatrixCursor.RowBuilder builder = result.newRow();
for (String key : contentValue.keySet()) {
builder.add(key, contentValue.get(key));
}
}
return result;
} else {
return new MatrixCursor(new String[0]);
}
}
}
}