diff options
author | Dmitri Plotnikov <dplotnikov@google.com> | 2010-08-05 10:53:44 -0700 |
---|---|---|
committer | Dmitri Plotnikov <dplotnikov@google.com> | 2010-08-05 10:53:44 -0700 |
commit | 72e3003a810fb4793a1513d17a40f8ab83d7d0af (patch) | |
tree | a439533bcb9125890acb6cf4eb57adc4e2da27bf /tests | |
parent | a549eb3c9627862a3e45d910d5c981191086a949 (diff) | |
download | packages_providers_ContactsProvider-72e3003a810fb4793a1513d17a40f8ab83d7d0af.zip packages_providers_ContactsProvider-72e3003a810fb4793a1513d17a40f8ab83d7d0af.tar.gz packages_providers_ContactsProvider-72e3003a810fb4793a1513d17a40f8ab83d7d0af.tar.bz2 |
Introducing ContactDirectoryManager
Changing the contact directory registration protocol.
Now directory providers are mostly passive,
ContactsProvider2 is in control.
Change-Id: I93815f7dc0a30fde35d70c5fd48bb1a924076ff5
Diffstat (limited to 'tests')
5 files changed, 531 insertions, 250 deletions
diff --git a/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java b/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java new file mode 100644 index 0000000..a608a4a --- /dev/null +++ b/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java @@ -0,0 +1,430 @@ +/* + * Copyright (C) 2010 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.providers.contacts; + +import com.google.android.collect.Lists; + +import android.accounts.Account; +import android.content.ContentValues; +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.ProviderInfo; +import android.database.Cursor; +import android.database.MatrixCursor; +import android.net.Uri; +import android.os.Bundle; +import android.provider.ContactsContract; +import android.provider.ContactsContract.Contacts; +import android.provider.ContactsContract.Directory; +import android.provider.ContactsContract.RawContacts; +import android.test.mock.MockContentProvider; +import android.test.suitebuilder.annotation.LargeTest; + +/** + * Unit tests for {@link ContactDirectoryManager}. Run the test like this: + * <code>adb shell am instrument -e class com.android.providers.contacts.ContactsProvider2Test -w \ * com.android.providers.contacts.tests/android.test.InstrumentationTestRunner * </code> + */ +@LargeTest +public class ContactDirectoryManagerTest extends BaseContactsProvider2Test { + + private ContactsMockPackageManager mPackageManager; + + private ContactsProvider2 mProvider; + + private ContactDirectoryManager mDirectoryManager; + + public static class MockContactDirectoryProvider extends MockContentProvider { + + private String mAuthority; + + private MatrixCursor mResponse; + + @Override + public void attachInfo(Context context, ProviderInfo info) { + mAuthority = info.authority; + } + + public MatrixCursor createResponseCursor() { + mResponse = new MatrixCursor( + new String[] { Directory.ACCOUNT_NAME, Directory.ACCOUNT_TYPE, + Directory.DISPLAY_NAME, Directory.TYPE_RESOURCE_ID, + Directory.EXPORT_SUPPORT, Directory.SHORTCUT_SUPPORT, }); + + return mResponse; + } + + @Override + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, + String sortOrder) { + + if (uri.toString().equals("content://" + mAuthority + "/directories")) { + return mResponse; + } else if (uri.toString().startsWith("content://" + mAuthority + "/contacts")) { + MatrixCursor cursor = new MatrixCursor( + new String[] { "projection", "selection", "selectionArgs", "sortOrder", + "accountName", "accountType"}); + cursor.addRow(new Object[] { + Lists.newArrayList(projection).toString(), + selection, + Lists.newArrayList(selectionArgs).toString(), + sortOrder, + uri.getQueryParameter(RawContacts.ACCOUNT_NAME), + uri.getQueryParameter(RawContacts.ACCOUNT_TYPE), + }); + return cursor; + } + + fail("Unexpected uri: " + uri); + return null; + } + } + + @Override + public void setUp() throws Exception { + super.setUp(); + + mProvider = (ContactsProvider2) getProvider(); + mDirectoryManager = mProvider.getContactDirectoryManager(); + + mPackageManager = (ContactsMockPackageManager) getProvider() + .getContext().getPackageManager(); + } + + public void testScanAllProviders() throws Exception { + mPackageManager.setInstalledPackages( + Lists.newArrayList( + createProviderPackage("test.package1", "authority1"), + createProviderPackage("test.package2", "authority2"))); + + MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider( + MockContactDirectoryProvider.class, "authority1"); + + MatrixCursor response1 = provider1.createResponseCursor(); + addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1, + Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE); + addDirectoryRow(response1, "account-name2", "account-type2", "display-name2", 2, + Directory.EXPORT_SUPPORT_ANY_ACCOUNT, Directory.SHORTCUT_SUPPORT_DATA_ITEMS_ONLY); + + MockContactDirectoryProvider provider2 = (MockContactDirectoryProvider) addProvider( + MockContactDirectoryProvider.class, "authority2"); + + MatrixCursor response2 = provider2.createResponseCursor(); + addDirectoryRow(response2, "account-name3", "account-type3", "display-name3", 3, + Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL); + + mDirectoryManager.scanAllPackages(); + + Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); + assertEquals(5, cursor.getCount()); + + cursor.moveToPosition(2); + assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1", + "display-name1", 1, Directory.EXPORT_SUPPORT_NONE); + + cursor.moveToNext(); + assertDirectoryRow(cursor, "test.package1", "authority1", "account-name2", "account-type2", + "display-name2", 2, Directory.EXPORT_SUPPORT_ANY_ACCOUNT); + + cursor.moveToNext(); + assertDirectoryRow(cursor, "test.package2", "authority2", "account-name3", "account-type3", + "display-name3", 3, Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY); + + cursor.close(); + } + + public void testPackageInstalled() throws Exception { + mPackageManager.setInstalledPackages( + Lists.newArrayList(createProviderPackage("test.package1", "authority1"))); + + MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider( + MockContactDirectoryProvider.class, "authority1"); + + MatrixCursor response1 = provider1.createResponseCursor(); + addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1, + Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE); + + mDirectoryManager.scanAllPackages(); + + // At this point the manager has discovered a single directory (plus two + // standard ones). + Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); + assertEquals(3, cursor.getCount()); + cursor.close(); + + // Pretend to install another package + MockContactDirectoryProvider provider2 = (MockContactDirectoryProvider) addProvider( + MockContactDirectoryProvider.class, "authority2"); + + MatrixCursor response2 = provider2.createResponseCursor(); + addDirectoryRow(response2, "account-name3", "account-type3", "display-name3", 3, + Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL); + + mPackageManager.getInstalledPackages(0).add( + createProviderPackage("test.package2", "authority2")); + + mProvider.onPackageChanged("test.package2"); + + cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); + assertEquals(4, cursor.getCount()); + + cursor.moveToPosition(2); + assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1", + "display-name1", 1, Directory.EXPORT_SUPPORT_NONE); + + cursor.moveToNext(); + assertDirectoryRow(cursor, "test.package2", "authority2", "account-name3", "account-type3", + "display-name3", 3, Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY); + + cursor.close(); + } + + public void testPackageUninstalled() throws Exception { + mPackageManager.setInstalledPackages( + Lists.newArrayList( + createProviderPackage("test.package1", "authority1"), + createProviderPackage("test.package2", "authority2"))); + + MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider( + MockContactDirectoryProvider.class, "authority1"); + + MatrixCursor response1 = provider1.createResponseCursor(); + addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1, + Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE); + + MockContactDirectoryProvider provider2 = (MockContactDirectoryProvider) addProvider( + MockContactDirectoryProvider.class, "authority2"); + + MatrixCursor response2 = provider2.createResponseCursor(); + addDirectoryRow(response2, "account-name3", "account-type3", "display-name3", 3, + Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL); + + mDirectoryManager.scanAllPackages(); + + // At this point the manager has discovered two custom directories. + Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); + assertEquals(4, cursor.getCount()); + cursor.close(); + + // Pretend to uninstall one of the packages + mPackageManager.getInstalledPackages(0).remove(1); + + mProvider.onPackageChanged("test.package2"); + + cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); + assertEquals(3, cursor.getCount()); + + cursor.moveToPosition(2); + assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1", + "display-name1", 1, Directory.EXPORT_SUPPORT_NONE); + + cursor.close(); + } + + public void testPackageReplaced() throws Exception { + mPackageManager.setInstalledPackages( + Lists.newArrayList( + createProviderPackage("test.package1", "authority1"), + createProviderPackage("test.package2", "authority2"))); + + MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider( + MockContactDirectoryProvider.class, "authority1"); + + MatrixCursor response1 = provider1.createResponseCursor(); + addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1, + Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE); + + MockContactDirectoryProvider provider2 = (MockContactDirectoryProvider) addProvider( + MockContactDirectoryProvider.class, "authority2"); + + MatrixCursor response2 = provider2.createResponseCursor(); + addDirectoryRow(response2, "account-name3", "account-type3", "display-name3", 3, + Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL); + + mDirectoryManager.scanAllPackages(); + + // At this point the manager has discovered two custom directories. + Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); + assertEquals(4, cursor.getCount()); + cursor.close(); + + // Pretend to replace the package with a different provider inside + MatrixCursor response3 = provider2.createResponseCursor(); + addDirectoryRow(response3, "account-name4", "account-type4", "display-name4", 4, + Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE); + + mProvider.onPackageChanged("test.package2"); + + cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); + assertEquals(4, cursor.getCount()); + + cursor.moveToPosition(2); + assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1", + "display-name1", 1, Directory.EXPORT_SUPPORT_NONE); + + cursor.moveToNext(); + assertDirectoryRow(cursor, "test.package2", "authority2", "account-name4", "account-type4", + "display-name4", 4, Directory.EXPORT_SUPPORT_NONE); + + cursor.close(); + } + + public void testAccountRemoval() throws Exception { + mPackageManager.setInstalledPackages( + Lists.newArrayList( + createProviderPackage("test.package1", "authority1"), + createProviderPackage("test.package2", "authority2"))); + + MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider( + MockContactDirectoryProvider.class, "authority1"); + + ((ContactsProvider2)getProvider()).onAccountsUpdated( + new Account[]{ + new Account("account-name1", "account-type1"), + new Account("account-name2", "account-type2")}); + + MatrixCursor response1 = provider1.createResponseCursor(); + addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1, + Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE); + addDirectoryRow(response1, "account-name2", "account-type2", "display-name2", 2, + Directory.EXPORT_SUPPORT_ANY_ACCOUNT, Directory.SHORTCUT_SUPPORT_DATA_ITEMS_ONLY); + + mDirectoryManager.scanAllPackages(); + + ((ContactsProvider2)getProvider()).onAccountsUpdated( + new Account[]{new Account("account-name1", "account-type1")}); + + Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); + assertEquals(3, cursor.getCount()); + + cursor.moveToPosition(2); + assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1", + "display-name1", 1, Directory.EXPORT_SUPPORT_NONE); + + cursor.close(); + } + + public void testNotifyDirectoryChange() throws Exception { + mPackageManager.setInstalledPackages( + Lists.newArrayList(createProviderPackage("test.package1", "authority1"))); + + MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider( + MockContactDirectoryProvider.class, "authority1"); + + MatrixCursor response1 = provider1.createResponseCursor(); + addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1, + Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE); + + mDirectoryManager.scanAllPackages(); + + // Pretend to replace the package with a different provider inside + MatrixCursor response2 = provider1.createResponseCursor(); + addDirectoryRow(response2, "account-name2", "account-type2", "display-name2", 2, + Directory.EXPORT_SUPPORT_ANY_ACCOUNT, Directory.SHORTCUT_SUPPORT_FULL); + + ContactsContract.Directory.notifyDirectoryChange(mResolver); + + Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); + assertEquals(3, cursor.getCount()); + + cursor.moveToPosition(2); + assertDirectoryRow(cursor, "test.package1", "authority1", "account-name2", "account-type2", + "display-name2", 2, Directory.EXPORT_SUPPORT_ANY_ACCOUNT); + + cursor.close(); + } + + public void testForwardingToDirectoryProvider() throws Exception { + mPackageManager.setInstalledPackages( + Lists.newArrayList(createProviderPackage("test.package1", "authority1"))); + + MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider( + MockContactDirectoryProvider.class, "authority1"); + + MatrixCursor response1 = provider1.createResponseCursor(); + addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1, + Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE); + + mDirectoryManager.scanAllPackages(); + + Cursor cursor = mResolver.query( + Directory.CONTENT_URI, new String[] { Directory._ID }, null, null, null); + cursor.moveToPosition(2); + long directoryId = cursor.getLong(0); + cursor.close(); + + Uri contentUri = Contacts.CONTENT_URI.buildUpon().appendQueryParameter( + ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)).build(); + + // The request should be forwarded to TestProvider, which will simply + // package arguments and return them to us for verification + cursor = mResolver.query(contentUri, + new String[]{"f1", "f2"}, "query", new String[]{"s1", "s2"}, "so"); + assertNotNull(cursor); + assertEquals(1, cursor.getCount()); + cursor.moveToFirst(); + assertEquals("[f1, f2]", cursor.getString(cursor.getColumnIndex("projection"))); + assertEquals("query", cursor.getString(cursor.getColumnIndex("selection"))); + assertEquals("[s1, s2]", cursor.getString(cursor.getColumnIndex("selectionArgs"))); + assertEquals("so", cursor.getString(cursor.getColumnIndex("sortOrder"))); + assertEquals("account-name1", cursor.getString(cursor.getColumnIndex("accountName"))); + assertEquals("account-type1", cursor.getString(cursor.getColumnIndex("accountType"))); + cursor.close(); + } + + protected PackageInfo createProviderPackage(String packageName, String authority) { + PackageInfo providerPackage = new PackageInfo(); + providerPackage.packageName = packageName; + ProviderInfo providerInfo = new ProviderInfo(); + providerInfo.packageName = providerPackage.packageName; + providerInfo.authority = authority; + providerInfo.metaData = new Bundle(); + providerInfo.metaData.putBoolean("android.content.ContactDirectory", true); + providerPackage.providers = new ProviderInfo[] { providerInfo }; + return providerPackage; + } + + protected void addDirectoryRow(MatrixCursor cursor, String accountName, String accountType, + String displayName, int typeResourceId, int exportSupport, int shortcutSupport) { + Object[] row = new Object[cursor.getColumnCount()]; + row[cursor.getColumnIndex(Directory.ACCOUNT_NAME)] = accountName; + row[cursor.getColumnIndex(Directory.ACCOUNT_TYPE)] = accountType; + row[cursor.getColumnIndex(Directory.DISPLAY_NAME)] = displayName; + row[cursor.getColumnIndex(Directory.TYPE_RESOURCE_ID)] = typeResourceId; + row[cursor.getColumnIndex(Directory.EXPORT_SUPPORT)] = exportSupport; + row[cursor.getColumnIndex(Directory.SHORTCUT_SUPPORT)] = shortcutSupport; + cursor.addRow(row); + } + + protected void assertDirectoryRow(Cursor cursor, String packageName, String authority, + String accountName, String accountType, String displayName, int typeResourceId, + int exportSupport) { + ContentValues values = new ContentValues(); + values.put(Directory.PACKAGE_NAME, packageName); + values.put(Directory.DIRECTORY_AUTHORITY, authority); + values.put(Directory.ACCOUNT_NAME, accountName); + values.put(Directory.ACCOUNT_TYPE, accountType); + values.put(Directory.DISPLAY_NAME, displayName); + values.put(Directory.TYPE_RESOURCE_ID, typeResourceId); + values.put(Directory.EXPORT_SUPPORT, exportSupport); + + // TODO: uncomment once shortcut support is implemented + // values.put(Directory.SHORTCUT_SUPPORT, + // Directory.SHORTCUT_SUPPORT_DATA_ITEMS_ONLY); + + assertCursorValues(cursor, values); + } +} diff --git a/tests/src/com/android/providers/contacts/ContactsActor.java b/tests/src/com/android/providers/contacts/ContactsActor.java index ec18b15..b31748c 100644 --- a/tests/src/com/android/providers/contacts/ContactsActor.java +++ b/tests/src/com/android/providers/contacts/ContactsActor.java @@ -23,11 +23,11 @@ import android.content.ContentValues; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.content.pm.ProviderInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.database.Cursor; import android.net.Uri; -import android.os.Binder; import android.provider.BaseColumns; import android.provider.ContactsContract; import android.provider.ContactsContract.CommonDataKinds; @@ -41,11 +41,9 @@ import android.test.IsolatedContext; import android.test.RenamingDelegatingContext; import android.test.mock.MockContentResolver; import android.test.mock.MockContext; -import android.test.mock.MockPackageManager; import android.test.mock.MockResources; import android.util.TypedValue; -import java.util.HashMap; import java.util.Locale; /** @@ -94,7 +92,9 @@ public class ContactsActor { public ContentProvider addProvider(Class<? extends ContentProvider> providerClass, String authority) throws Exception { ContentProvider provider = providerClass.newInstance(); - provider.attachInfo(mProviderContext, null); + ProviderInfo info = new ProviderInfo(); + info.authority = authority; + provider.attachInfo(mProviderContext, info); resolver.addProvider(authority, provider); return provider; } @@ -112,7 +112,7 @@ public class ContactsActor { private static class RestrictionMockContext extends MockContext { private final Context mOverallContext; private final String mReportedPackageName; - private final RestrictionMockPackageManager mPackageManager; + private final ContactsMockPackageManager mPackageManager; private final ContentResolver mResolver; private final Resources mRes; @@ -125,7 +125,7 @@ public class ContactsActor { mReportedPackageName = reportedPackageName; mResolver = resolver; - mPackageManager = new RestrictionMockPackageManager(); + mPackageManager = new ContactsMockPackageManager(); mPackageManager.addPackage(1000, PACKAGE_GREY); mPackageManager.addPackage(2000, PACKAGE_RED); mPackageManager.addPackage(3000, PACKAGE_GREEN); @@ -220,52 +220,12 @@ public class ContactsActor { } } - private static String sCallingPackage = null; + static String sCallingPackage = null; void ensureCallingPackage() { sCallingPackage = this.packageName; } - /** - * Mock {@link PackageManager} that knows about a specific set of packages - * to help test security models. Because {@link Binder#getCallingUid()} - * can't be mocked, you'll have to find your mock-UID manually using your - * {@link Context#getPackageName()}. - */ - private static class RestrictionMockPackageManager extends MockPackageManager { - private final HashMap<Integer, String> mForward = new HashMap<Integer, String>(); - private final HashMap<String, Integer> mReverse = new HashMap<String, Integer>(); - - public RestrictionMockPackageManager() { - } - - /** - * Add a UID-to-package mapping, which is then stored internally. - */ - public void addPackage(int packageUid, String packageName) { - mForward.put(packageUid, packageName); - mReverse.put(packageName, packageUid); - } - - @Override - public String getNameForUid(int uid) { - return "name-for-uid"; - } - - @Override - public String[] getPackagesForUid(int uid) { - return new String[] { sCallingPackage }; - } - - @Override - public ApplicationInfo getApplicationInfo(String packageName, int flags) { - ApplicationInfo info = new ApplicationInfo(); - Integer uid = mReverse.get(packageName); - info.uid = (uid != null) ? uid : -1; - return info; - } - } - public long createContact(boolean isRestricted, String name) { ensureCallingPackage(); long contactId = createContact(isRestricted); diff --git a/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java b/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java new file mode 100644 index 0000000..edd5017 --- /dev/null +++ b/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2010 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.providers.contacts; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.os.Binder; +import android.test.mock.MockPackageManager; + +import java.util.HashMap; +import java.util.List; + +/** + * Mock {@link PackageManager} that knows about a specific set of packages + * to help test security models. Because {@link Binder#getCallingUid()} + * can't be mocked, you'll have to find your mock-UID manually using your + * {@link Context#getPackageName()}. + */ +public class ContactsMockPackageManager extends MockPackageManager { + private final HashMap<Integer, String> mForward = new HashMap<Integer, String>(); + private final HashMap<String, Integer> mReverse = new HashMap<String, Integer>(); + private List<PackageInfo> mPackages; + + public ContactsMockPackageManager() { + } + + /** + * Add a UID-to-package mapping, which is then stored internally. + */ + public void addPackage(int packageUid, String packageName) { + mForward.put(packageUid, packageName); + mReverse.put(packageName, packageUid); + } + + @Override + public String getNameForUid(int uid) { + return "name-for-uid"; + } + + @Override + public String[] getPackagesForUid(int uid) { + if (mPackages != null) { + return new String[] { mPackages.get(0).packageName }; + } else { + return new String[] { ContactsActor.sCallingPackage }; + } + } + + @Override + public ApplicationInfo getApplicationInfo(String packageName, int flags) { + ApplicationInfo info = new ApplicationInfo(); + Integer uid = mReverse.get(packageName); + info.uid = (uid != null) ? uid : -1; + return info; + } + + public void setInstalledPackages(List<PackageInfo> packages) { + this.mPackages = packages; + } + + @Override + public List<PackageInfo> getInstalledPackages(int flags) { + return mPackages; + } + + @Override + public PackageInfo getPackageInfo(String packageName, int flags) throws NameNotFoundException { + for (PackageInfo info : mPackages) { + if (info.packageName.equals(packageName)) { + return info; + } + } + throw new NameNotFoundException(); + } +} diff --git a/tests/src/com/android/providers/contacts/DirectoryTest.java b/tests/src/com/android/providers/contacts/DirectoryTest.java index 7940c61..adb3b34 100644 --- a/tests/src/com/android/providers/contacts/DirectoryTest.java +++ b/tests/src/com/android/providers/contacts/DirectoryTest.java @@ -16,21 +16,14 @@ package com.android.providers.contacts; -import com.google.android.collect.Lists; - import android.accounts.Account; import android.content.ContentUris; import android.content.ContentValues; -import android.content.Context; -import android.content.pm.ProviderInfo; import android.database.Cursor; -import android.database.MatrixCursor; import android.net.Uri; import android.provider.ContactsContract; import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Directory; -import android.provider.ContactsContract.Settings; -import android.test.mock.MockContentProvider; import android.test.suitebuilder.annotation.LargeTest; @@ -78,152 +71,6 @@ public class DirectoryTest extends BaseContactsProvider2Test { assertStoredValues(defaultDirectoryUri, values); } - public void testDirectoryInsert() { - ContentValues values = new ContentValues(); - values.put(Directory.PACKAGE_NAME, ContactsActor.PACKAGE_GREY); - values.put(Directory.DIRECTORY_AUTHORITY, "my_authority"); - values.put(Directory.TYPE_RESOURCE_ID, 42); - values.put(Directory.DISPLAY_NAME, "Universe"); - values.put(Directory.EXPORT_SUPPORT, Directory.EXPORT_SUPPORT_ANY_ACCOUNT); - values.put(Directory.ACCOUNT_NAME, "accountName"); - values.put(Directory.ACCOUNT_TYPE, "accountType"); - - mActor.ensureCallingPackage(); - - Uri uri = mResolver.insert(Directory.CONTENT_URI, values); - assertStoredValues(uri, values); - } - - public void testDirectoryInsertWrongPackage() { - ContentValues values = new ContentValues(); - values.put(Directory.PACKAGE_NAME, "wrong.package"); - values.put(Directory.DIRECTORY_AUTHORITY, "my_authority"); - - mActor.ensureCallingPackage(); - - try { - mResolver.insert(Directory.CONTENT_URI, values); - fail("Was expecting an IllegalArgumentException"); - } catch (IllegalArgumentException ex) { - // Expected - } - } - - public void testDirectoryUpdate() { - ContentValues values = new ContentValues(); - values.put(Directory.PACKAGE_NAME, ContactsActor.PACKAGE_GREY); - values.put(Directory.DIRECTORY_AUTHORITY, "my_authority"); - values.put(Directory.TYPE_RESOURCE_ID, 42); - values.put(Directory.DISPLAY_NAME, "Universe"); - values.put(Directory.EXPORT_SUPPORT, Directory.EXPORT_SUPPORT_ANY_ACCOUNT); - values.put(Directory.ACCOUNT_NAME, "accountName"); - values.put(Directory.ACCOUNT_TYPE, "accountType"); - - mActor.ensureCallingPackage(); - - Uri uri = mResolver.insert(Directory.CONTENT_URI, values); - - values.put(Directory.DIRECTORY_AUTHORITY, "different_authority"); - values.put(Directory.TYPE_RESOURCE_ID, 43); - values.put(Directory.DISPLAY_NAME, "Beyond Universe"); - values.put(Directory.EXPORT_SUPPORT, Directory.EXPORT_SUPPORT_NONE); - values.put(Directory.ACCOUNT_NAME, "newName"); - values.put(Directory.ACCOUNT_TYPE, "newType"); - - int count = mResolver.update(uri, values, null, null); - assertEquals(1, count); - assertStoredValues(uri, values); - } - - public void testDirectoryUpdateWrongPackage() { - ContentValues values = new ContentValues(); - values.put(Directory.PACKAGE_NAME, ContactsActor.PACKAGE_GREY); - values.put(Directory.DIRECTORY_AUTHORITY, "my_authority"); - - mActor.ensureCallingPackage(); - Uri uri = mResolver.insert(Directory.CONTENT_URI, values); - - values.put(Directory.DIRECTORY_AUTHORITY, "different_authority"); - - mActor.packageName = "different.package"; - mActor.ensureCallingPackage(); - - try { - mResolver.update(uri, values, null, null); - fail("Was expecting an IllegalArgumentException"); - } catch (IllegalArgumentException ex) { - // Expected - } - } - - public void testDirectorDelete() { - ContentValues values = new ContentValues(); - values.put(Directory.PACKAGE_NAME, ContactsActor.PACKAGE_GREY); - values.put(Directory.DIRECTORY_AUTHORITY, "my_authority"); - - mActor.ensureCallingPackage(); - - Uri uri = mResolver.insert(Directory.CONTENT_URI, values); - - mResolver.delete(uri, null, null); - - assertEquals(0, getCount(uri, null, null)); - } - - public void testDirectorDeleteWrongPackage() { - ContentValues values = new ContentValues(); - values.put(Directory.PACKAGE_NAME, ContactsActor.PACKAGE_GREY); - values.put(Directory.DIRECTORY_AUTHORITY, "my_authority"); - - mActor.ensureCallingPackage(); - Uri uri = mResolver.insert(Directory.CONTENT_URI, values); - - values.put(Directory.DIRECTORY_AUTHORITY, "different_authority"); - - mActor.packageName = "different.package"; - mActor.ensureCallingPackage(); - try { - mResolver.delete(uri, null, null); - fail("Was expecting an IllegalArgumentException"); - } catch (IllegalArgumentException ex) { - // Expected - } - } - - public void testAccountRemoval() { - ((ContactsProvider2)getProvider()).onAccountsUpdated( - new Account[]{new Account("accountName", "accountType")}); - - ContentValues values = new ContentValues(); - values.put(Directory.PACKAGE_NAME, ContactsActor.PACKAGE_GREY); - values.put(Directory.DIRECTORY_AUTHORITY, "my_authority"); - values.put(Directory.ACCOUNT_NAME, "accountName"); - values.put(Directory.ACCOUNT_TYPE, "accountType"); - - mActor.ensureCallingPackage(); - Uri uri = mResolver.insert(Directory.CONTENT_URI, values); - - ((ContactsProvider2)getProvider()).onAccountsUpdated( - new Account[]{new Account("name", "type")}); - - // Removing the account should trigger the removal of the directory - assertEquals(0, getCount(uri, null, null)); - } - - public void testPackageRemoval() { - ContentValues values = new ContentValues(); - values.put(Directory.PACKAGE_NAME, ContactsActor.PACKAGE_GREY); - values.put(Directory.DIRECTORY_AUTHORITY, "my_authority"); - - mActor.ensureCallingPackage(); - Uri uri = mResolver.insert(Directory.CONTENT_URI, values); - - ((ContactsProvider2)getProvider()).onPackageUninstalled(ContactsActor.PACKAGE_GREY); - - // Uninstalling the package should trigger the removal of the directory - assertEquals(0, getCount(uri, null, null)); - } - public void testForwardingToLocalContacts() { long contactId = queryContactId(createRawContactWithName()); @@ -278,55 +125,5 @@ public class DirectoryTest extends BaseContactsProvider2Test { assertEquals("Helen Parr", cursor.getString(1)); cursor.close(); } - - public void testForwardingToDirectoryProvider() throws Exception { - addProvider(TestProvider.class, "test_authority"); - - ContentValues values = new ContentValues(); - values.put(Directory.PACKAGE_NAME, ContactsActor.PACKAGE_GREY); - values.put(Directory.DIRECTORY_AUTHORITY, "test_authority"); - - mActor.ensureCallingPackage(); - Uri uri = mResolver.insert(Directory.CONTENT_URI, values); - long directoryId = ContentUris.parseId(uri); - - Uri contentUri = Contacts.CONTENT_URI.buildUpon().appendQueryParameter( - ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)).build(); - - // The request should be forwarded to TestProvider, which will simply - // package arguments and return them to us for verification - Cursor cursor = mResolver.query(contentUri, - new String[]{"f1", "f2"}, "query", new String[]{"s1", "s2"}, "so"); - assertNotNull(cursor); - assertEquals(1, cursor.getCount()); - cursor.moveToFirst(); - assertEquals("[f1, f2]", cursor.getString(cursor.getColumnIndex("projection"))); - assertEquals("query", cursor.getString(cursor.getColumnIndex("selection"))); - assertEquals("[s1, s2]", cursor.getString(cursor.getColumnIndex("selectionArgs"))); - assertEquals("so", cursor.getString(cursor.getColumnIndex("sortOrder"))); - cursor.close(); - } - - public static class TestProvider extends MockContentProvider { - - @Override - public void attachInfo(Context context, ProviderInfo info) { - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - MatrixCursor cursor = new MatrixCursor(new String[] { - "projection", "selection", "selectionArgs", "sortOrder" - }); - cursor.addRow(new Object[] { - Lists.newArrayList(projection).toString(), - selection, - Lists.newArrayList(selectionArgs).toString(), - sortOrder - }); - return cursor; - } - } } diff --git a/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java b/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java index 0248094..ba8b7f8 100644 --- a/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java +++ b/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java @@ -89,6 +89,10 @@ public class SynchronousContactsProvider2 extends ContactsProvider2 { } @Override + protected void startContactDirectoryManager() { + } + + @Override protected Account getDefaultAccount() { if (mAccount == null) { mAccount = new Account("androidtest@gmail.com", "com.google"); |