aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorJigar Thakkar <jigarthakkar@google.com>2022-12-14 07:53:27 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2022-12-14 07:53:27 +0000
commitf947c4389ec214e41f69b0316b79244059fe7447 (patch)
tree6c64902e335a0c5138ad777c167bb477bfe83851 /tests
parente30855b643858e352d25a3ae3cdf6e415f9a1866 (diff)
parenta5fbbbda6c950365ff56ddfa5f9f5bb9f8b5bc2f (diff)
downloadContactsProvider-f947c4389ec214e41f69b0316b79244059fe7447.tar.gz
Merge changes I643a9704,Id78e7662
* changes: Add unit tests for clone ContactsProvider reads Redirect queries from clone to parent ContactsProvider
Diffstat (limited to 'tests')
-rw-r--r--tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java67
-rw-r--r--tests/src/com/android/providers/contacts/CloneContactsProvider2Test.java195
-rw-r--r--tests/src/com/android/providers/contacts/ContactsProvider2Test.java65
-rw-r--r--tests/src/com/android/providers/contacts/util/UserUtilsTest.java45
4 files changed, 296 insertions, 76 deletions
diff --git a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
index 20d6a15e..e8920530 100644
--- a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
@@ -70,6 +70,8 @@ import com.android.providers.contacts.util.Hex;
import com.android.providers.contacts.util.MockClock;
import com.google.android.collect.Sets;
+import java.io.FileInputStream;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
@@ -1419,6 +1421,71 @@ public abstract class BaseContactsProvider2Test extends PhotoLoadingTestCase {
getContactsProvider().getProfileProviderForTest().getDatabaseHelper(), values);
}
+ protected class VCardTestUriCreator {
+ private String mLookup1;
+ private String mLookup2;
+
+ public VCardTestUriCreator(String lookup1, String lookup2) {
+ super();
+ mLookup1 = lookup1;
+ mLookup2 = lookup2;
+ }
+
+ public Uri getUri1() {
+ return Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, mLookup1);
+ }
+
+ public Uri getUri2() {
+ return Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, mLookup2);
+ }
+
+ public Uri getCombinedUri() {
+ return Uri.withAppendedPath(Contacts.CONTENT_MULTI_VCARD_URI,
+ Uri.encode(mLookup1 + ":" + mLookup2));
+ }
+ }
+
+ protected VCardTestUriCreator createVCardTestContacts() {
+ final long rawContactId1 = RawContactUtil.createRawContact(mResolver, mAccount,
+ RawContacts.SOURCE_ID, "4:12");
+ DataUtil.insertStructuredName(mResolver, rawContactId1, "John", "Doe");
+
+ final long rawContactId2 = RawContactUtil.createRawContact(mResolver, mAccount,
+ RawContacts.SOURCE_ID, "3:4%121");
+ DataUtil.insertStructuredName(mResolver, rawContactId2, "Jane", "Doh");
+
+ final long contactId1 = queryContactId(rawContactId1);
+ final long contactId2 = queryContactId(rawContactId2);
+ final Uri contact1Uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId1);
+ final Uri contact2Uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId2);
+ final String lookup1 =
+ Uri.encode(Contacts.getLookupUri(mResolver, contact1Uri).getPathSegments().get(2));
+ final String lookup2 =
+ Uri.encode(Contacts.getLookupUri(mResolver, contact2Uri).getPathSegments().get(2));
+ return new VCardTestUriCreator(lookup1, lookup2);
+ }
+
+ protected String readToEnd(FileInputStream inputStream) {
+ try {
+ System.out.println("DECLARED INPUT STREAM LENGTH: " + inputStream.available());
+ int ch;
+ StringBuilder stringBuilder = new StringBuilder();
+ int index = 0;
+ while (true) {
+ ch = inputStream.read();
+ System.out.println("READ CHARACTER: " + index + " " + ch);
+ if (ch == -1) {
+ break;
+ }
+ stringBuilder.append((char)ch);
+ index++;
+ }
+ return stringBuilder.toString();
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
/**
* A contact in the database, and the attributes used to create it. Construct using
* {@link GoldenContactBuilder#build()}.
diff --git a/tests/src/com/android/providers/contacts/CloneContactsProvider2Test.java b/tests/src/com/android/providers/contacts/CloneContactsProvider2Test.java
index 18c6cb76..48a00da2 100644
--- a/tests/src/com/android/providers/contacts/CloneContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/CloneContactsProvider2Test.java
@@ -17,28 +17,50 @@
package com.android.providers.contacts;
import static com.android.providers.contacts.ContactsActor.MockUserManager.CLONE_PROFILE_USER;
+import static com.android.providers.contacts.ContactsActor.MockUserManager.PRIMARY_USER;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.spy;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.OperationApplicationException;
+import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
+import android.provider.CallLog;
import android.provider.ContactsContract;
+import android.util.Log;
+
import androidx.test.filters.MediumTest;
import androidx.test.filters.SdkSuppress;
+import com.android.providers.contacts.testutil.DataUtil;
+import com.android.providers.contacts.testutil.RawContactUtil;
+
+import org.junit.Assert;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
import java.util.ArrayList;
+import java.util.Set;
@MediumTest
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
public class CloneContactsProvider2Test extends BaseContactsProvider2Test {
private ContactsActor mCloneContactsActor;
+ private SynchronousContactsProvider2 mCloneContactsProvider;
private SynchronousContactsProvider2 getCloneContactsProvider() {
return (SynchronousContactsProvider2) mCloneContactsActor.provider;
@@ -55,7 +77,8 @@ public class CloneContactsProvider2Test extends BaseContactsProvider2Test {
mCloneContactsActor.mockUserManager.setUsers(ContactsActor.MockUserManager.PRIMARY_USER,
CLONE_PROFILE_USER);
mCloneContactsActor.mockUserManager.myUser = CLONE_PROFILE_USER.id;
- getCloneContactsProvider().wipeData();
+ mCloneContactsProvider = spy(getCloneContactsProvider());
+ mCloneContactsProvider.wipeData();
}
private ContentValues getSampleContentValues() {
@@ -67,17 +90,43 @@ public class CloneContactsProvider2Test extends BaseContactsProvider2Test {
return values;
}
+ private void getCloneContactsProviderWithMockedCallToParent(Uri uri) {
+ Cursor primaryProfileCursor = mActor.provider.query(uri,
+ null /* projection */, null /* queryArgs */, null /* cancellationSignal */);
+ assertNotNull(primaryProfileCursor);
+ doReturn(primaryProfileCursor).when(mCloneContactsProvider)
+ .queryContactsProviderForUser(eq(uri), any(), any(), any(), any(),
+ any(), eq(PRIMARY_USER));
+ }
+
+ private void getCloneContactsProviderWithMockedOpenAssetFileCall(Uri uri)
+ throws FileNotFoundException {
+ AssetFileDescriptor fileDescriptor = mActor.provider.openAssetFile(uri, "r");
+ doReturn(fileDescriptor).when(mCloneContactsProvider)
+ .openAssetFileThroughParentProvider(eq(uri), eq("r"));
+ }
+
+ private String getCursorValue(Cursor c, String columnName) {
+ return c.getString(c.getColumnIndex(columnName));
+ }
+
private void assertEqualContentValues(ContentValues contentValues, Cursor cursor) {
- assertEquals(contentValues.get(ContactsContract.RawContacts.ACCOUNT_NAME),
- cursor.getString(cursor.getColumnIndex(ContactsContract.RawContacts.ACCOUNT_NAME)));
- assertEquals(contentValues.get(ContactsContract.RawContacts.ACCOUNT_TYPE),
- cursor.getString(cursor.getColumnIndex(ContactsContract.RawContacts.ACCOUNT_TYPE)));
- assertEquals(contentValues.get(ContactsContract.RawContacts.CUSTOM_RINGTONE),
- cursor.getString(cursor.getColumnIndex(
- ContactsContract.RawContacts.CUSTOM_RINGTONE)));
- assertEquals(contentValues.get(ContactsContract.RawContacts.STARRED),
- cursor.getString(cursor.getColumnIndex(
- ContactsContract.RawContacts.STARRED)));
+ for (String key: contentValues.getValues().keySet()) {
+ assertEquals(contentValues.get(key), getCursorValue(cursor, key));
+ }
+ }
+
+ private void assertRawContactsCursorEquals(Cursor expectedCursor, Cursor actualCursor,
+ Set<String> columnNames) {
+ assertNotNull(actualCursor);
+ assertEquals(expectedCursor.getCount(), actualCursor.getCount());
+ while (actualCursor.moveToNext()) {
+ expectedCursor.moveToNext();
+ for (String key: columnNames) {
+ assertEquals(getCursorValue(expectedCursor, key),
+ getCursorValue(actualCursor, key));
+ }
+ }
}
private void assertRejectedApplyBatchResults(ContentProviderResult[] res,
@@ -279,4 +328,128 @@ public class CloneContactsProvider2Test extends BaseContactsProvider2Test {
assertNotNull(authResponse);
assertEquals(Bundle.EMPTY, authResponse);
}
+
+ public void testCloneContactsProviderReads_callerNotInAllowlist() {
+ // Insert raw contact through the primary clone provider
+ ContentValues inputContentValues = getSampleContentValues();
+ long rawContactId = insertRawContactsThroughPrimaryProvider(inputContentValues);
+ Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI,
+ rawContactId);
+
+ // Mock call to parent profile contacts provider to return the correct result containing all
+ // contacts in the parent profile.
+ getCloneContactsProviderWithMockedCallToParent(uri);
+
+ // Mock call to ensure the caller package is not in the app-cloning allowlist
+ doReturn(false)
+ .when(mCloneContactsProvider).isAppAllowedToUseParentUsersContacts(any());
+
+ // Test clone contacts provider read with the uri of the contact added above
+ mCloneContactsProvider.query(uri,
+ null /* projection */, null /* queryArgs */, null /* cancellationSignal */);
+
+ // Check that the call passed through to the local query instead of redirecting to the
+ // parent provider
+ verify(mCloneContactsProvider, times(1))
+ .queryDirectoryIfNecessary(any(), any(), any(), any(), any(), any());
+ }
+
+ public void testContactsProviderReads_callerInAllowlist() {
+ // Insert raw contact through the primary clone provider
+ ContentValues inputContentValues = getSampleContentValues();
+ long rawContactId = insertRawContactsThroughPrimaryProvider(inputContentValues);
+ Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI,
+ rawContactId);
+
+ // Mock call to parent profile contacts provider to return the correct result containing all
+ // contacts in the parent profile.
+ getCloneContactsProviderWithMockedCallToParent(uri);
+
+ // Mock call to ensure the caller package is in the app-cloning allowlist
+ doReturn(true)
+ .when(mCloneContactsProvider).isAppAllowedToUseParentUsersContacts(any());
+
+ // Test clone contacts provider read with the uri of the contact added above
+ Cursor cursor = mCloneContactsProvider.query(uri,
+ null /* projection */, null /* queryArgs */, null /* cancellationSignal */);
+
+ // Check that the call did not pass through to the local query and instead redirected to the
+ // parent provider
+ verify(mCloneContactsProvider, times(0))
+ .queryDirectoryIfNecessary(any(), any(), any(), any(), any(), any());
+ assertNotNull(cursor);
+ Cursor primaryProfileCursor = mActor.provider.query(uri,
+ null /* projection */, null /* queryArgs */, null /* cancellationSignal */);
+ assertNotNull(primaryProfileCursor);
+ assertRawContactsCursorEquals(primaryProfileCursor, cursor,
+ inputContentValues.getValues().keySet());
+ }
+
+ public void testQueryPrimaryProfileProvider_callingFromParentUser() {
+ ContentValues inputContentValues = getSampleContentValues();
+ long rawContactId = insertRawContactsThroughPrimaryProvider(inputContentValues);
+ Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI,
+ rawContactId);
+
+ // Fetch primary contacts provider and call method to redirect to parent provider
+ final ContactsProvider2 primaryCP2 = (ContactsProvider2) getProvider();
+ Cursor cursor = primaryCP2.queryParentProfileContactsProvider(uri,
+ null /* projection */, null /* selection */, null /* selectionArgs */,
+ null /* sortOrder */, null /* cancellationSignal */);
+
+ // Assert that empty cursor is returned
+ assertNotNull(cursor);
+ assertEquals(0, cursor.getCount());
+ }
+
+ public void testQueryPrimaryProfileProvider_incorrectAuthority() {
+ ContentValues inputContentValues = getSampleContentValues();
+ insertRawContactsThroughPrimaryProvider(inputContentValues);
+
+ Assert.assertThrows(IllegalArgumentException.class, () ->
+ mCloneContactsProvider.queryParentProfileContactsProvider(CallLog.CONTENT_URI,
+ null /* projection */, null /* selection */, null /* selectionArgs */,
+ null /* sortOrder */, null /* cancellationSignal */));
+ }
+
+ public void testOpenAssetFileMultiVCard() throws IOException {
+ final VCardTestUriCreator contacts = createVCardTestContacts();
+
+ // Mock call to parent profile contacts provider to return the correct asset file
+ getCloneContactsProviderWithMockedOpenAssetFileCall(contacts.getCombinedUri());
+
+ // Mock call to ensure the caller package is in the app-cloning allowlist
+ doReturn(true)
+ .when(mCloneContactsProvider).isAppAllowedToUseParentUsersContacts(any());
+
+ final AssetFileDescriptor descriptor =
+ mCloneContactsProvider.openAssetFile(contacts.getCombinedUri(), "r");
+ final FileInputStream inputStream = descriptor.createInputStream();
+ String data = readToEnd(inputStream);
+ inputStream.close();
+ descriptor.close();
+
+ // Ensure that the resulting VCard has both contacts
+ assertTrue(data.contains("N:Doe;John;;;"));
+ assertTrue(data.contains("N:Doh;Jane;;;"));
+ }
+
+ public void testOpenAssetFileMultiVCard_callerNotInAllowlist() throws IOException {
+ final VCardTestUriCreator contacts = createVCardTestContacts();
+
+ // Mock call to parent profile contacts provider to return the correct asset file
+ getCloneContactsProviderWithMockedOpenAssetFileCall(contacts.getCombinedUri());
+
+ // Mock call to ensure the caller package is not in the app-cloning allowlist
+ doReturn(false)
+ .when(mCloneContactsProvider).isAppAllowedToUseParentUsersContacts(any());
+
+ final AssetFileDescriptor descriptor =
+ mCloneContactsProvider.openAssetFile(contacts.getCombinedUri(), "r");
+
+ // Check that the call passed through to the local call instead of redirecting to the
+ // parent provider
+ verify(mCloneContactsProvider, times(1))
+ .openAssetFile(eq(contacts.getCombinedUri()), any());
+ }
}
diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
index b625ac4a..69ae0fb2 100644
--- a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
@@ -8163,50 +8163,6 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test {
assertEquals("default", helper.getProperty("existent1", "default"));
}
- private class VCardTestUriCreator {
- private String mLookup1;
- private String mLookup2;
-
- public VCardTestUriCreator(String lookup1, String lookup2) {
- super();
- mLookup1 = lookup1;
- mLookup2 = lookup2;
- }
-
- public Uri getUri1() {
- return Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, mLookup1);
- }
-
- public Uri getUri2() {
- return Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, mLookup2);
- }
-
- public Uri getCombinedUri() {
- return Uri.withAppendedPath(Contacts.CONTENT_MULTI_VCARD_URI,
- Uri.encode(mLookup1 + ":" + mLookup2));
- }
- }
-
- private VCardTestUriCreator createVCardTestContacts() {
- final long rawContactId1 = RawContactUtil.createRawContact(mResolver, mAccount,
- RawContacts.SOURCE_ID, "4:12");
- DataUtil.insertStructuredName(mResolver, rawContactId1, "John", "Doe");
-
- final long rawContactId2 = RawContactUtil.createRawContact(mResolver, mAccount,
- RawContacts.SOURCE_ID, "3:4%121");
- DataUtil.insertStructuredName(mResolver, rawContactId2, "Jane", "Doh");
-
- final long contactId1 = queryContactId(rawContactId1);
- final long contactId2 = queryContactId(rawContactId2);
- final Uri contact1Uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId1);
- final Uri contact2Uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId2);
- final String lookup1 =
- Uri.encode(Contacts.getLookupUri(mResolver, contact1Uri).getPathSegments().get(2));
- final String lookup2 =
- Uri.encode(Contacts.getLookupUri(mResolver, contact2Uri).getPathSegments().get(2));
- return new VCardTestUriCreator(lookup1, lookup2);
- }
-
public void testQueryMultiVCard() {
// No need to create any contacts here, because the query for multiple vcards
// does not go into the database at all
@@ -9688,27 +9644,6 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test {
return c;
}
- private String readToEnd(FileInputStream inputStream) {
- try {
- System.out.println("DECLARED INPUT STREAM LENGTH: " + inputStream.available());
- int ch;
- StringBuilder stringBuilder = new StringBuilder();
- int index = 0;
- while (true) {
- ch = inputStream.read();
- System.out.println("READ CHARACTER: " + index + " " + ch);
- if (ch == -1) {
- break;
- }
- stringBuilder.append((char)ch);
- index++;
- }
- return stringBuilder.toString();
- } catch (IOException e) {
- return null;
- }
- }
-
private void assertQueryParameter(String uriString, String parameter, String expectedValue) {
assertEquals(expectedValue, ContactsProvider2.getQueryParameter(
Uri.parse(uriString), parameter));
diff --git a/tests/src/com/android/providers/contacts/util/UserUtilsTest.java b/tests/src/com/android/providers/contacts/util/UserUtilsTest.java
index 072df377..c672697a 100644
--- a/tests/src/com/android/providers/contacts/util/UserUtilsTest.java
+++ b/tests/src/com/android/providers/contacts/util/UserUtilsTest.java
@@ -18,6 +18,7 @@ package com.android.providers.contacts.util;
import static com.android.providers.contacts.ContactsActor.PACKAGE_GREY;
import android.content.Context;
+import android.os.UserHandle;
import android.provider.ContactsContract;
import android.test.suitebuilder.annotation.SmallTest;
@@ -101,14 +102,58 @@ public class UserUtilsTest extends FixedAndroidTestCase {
um.myUser = MockUserManager.PRIMARY_USER.id;
assertFalse(UserUtils.shouldUseParentsContacts(c));
+ assertFalse(UserUtils.shouldUseParentsContacts(c,
+ MockUserManager.PRIMARY_USER.getUserHandle()));
um.myUser = MockUserManager.SECONDARY_USER.id;
assertFalse(UserUtils.shouldUseParentsContacts(c));
+ assertFalse(UserUtils.shouldUseParentsContacts(c,
+ MockUserManager.SECONDARY_USER.getUserHandle()));
um.myUser = MockUserManager.CORP_USER.id;
assertFalse(UserUtils.shouldUseParentsContacts(c));
+ assertFalse(UserUtils.shouldUseParentsContacts(c,
+ MockUserManager.CORP_USER.getUserHandle()));
um.myUser = MockUserManager.CLONE_PROFILE_USER.id;
assertTrue(UserUtils.shouldUseParentsContacts(c));
+ assertTrue(UserUtils.shouldUseParentsContacts(c,
+ MockUserManager.CLONE_PROFILE_USER.getUserHandle()));
+
+ }
+
+ public void testIsParentUser() {
+ final Context c = mActor.getProviderContext();
+ final MockUserManager um = mActor.mockUserManager;
+ um.setUsers(MockUserManager.PRIMARY_USER, MockUserManager.SECONDARY_USER,
+ MockUserManager.CLONE_PROFILE_USER, MockUserManager.CORP_USER);
+
+ UserHandle primaryProfileUserHandle = MockUserManager.PRIMARY_USER.getUserHandle();
+ UserHandle cloneUserHandle = MockUserManager.CLONE_PROFILE_USER.getUserHandle();
+ UserHandle corpUserHandle = MockUserManager.CORP_USER.getUserHandle();
+
+ assertTrue(UserUtils.isParentUser(c, primaryProfileUserHandle, cloneUserHandle));
+ assertTrue(UserUtils.isParentUser(c, primaryProfileUserHandle, corpUserHandle));
+ assertFalse(UserUtils.isParentUser(c, primaryProfileUserHandle, primaryProfileUserHandle));
+ assertFalse(UserUtils.isParentUser(c, cloneUserHandle, cloneUserHandle));
+ assertFalse(UserUtils.isParentUser(c, cloneUserHandle, primaryProfileUserHandle));
+ assertFalse(UserUtils.isParentUser(c, corpUserHandle, primaryProfileUserHandle));
+ }
+
+ public void testGetProfileParent() {
+ final Context c = mActor.getProviderContext();
+ final MockUserManager um = mActor.mockUserManager;
+
+ um.setUsers(MockUserManager.PRIMARY_USER, MockUserManager.SECONDARY_USER,
+ MockUserManager.CLONE_PROFILE_USER, MockUserManager.CORP_USER);
+
+ um.myUser = MockUserManager.PRIMARY_USER.id;
+ assertNull(UserUtils.getProfileParentUser(c));
+
+ um.myUser = MockUserManager.CLONE_PROFILE_USER.id;
+ assertEquals(MockUserManager.PRIMARY_USER, UserUtils.getProfileParentUser(c));
+
+ um.myUser = MockUserManager.CORP_USER.id;
+ assertEquals(MockUserManager.PRIMARY_USER, UserUtils.getProfileParentUser(c));
}
}