diff options
Diffstat (limited to 'tests/src/com/android/providers/contacts/PhotoStoreTest.java')
-rw-r--r-- | tests/src/com/android/providers/contacts/PhotoStoreTest.java | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/tests/src/com/android/providers/contacts/PhotoStoreTest.java b/tests/src/com/android/providers/contacts/PhotoStoreTest.java new file mode 100644 index 0000000..9b7c50d --- /dev/null +++ b/tests/src/com/android/providers/contacts/PhotoStoreTest.java @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2011 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.android.providers.contacts.ContactsDatabaseHelper.Tables; +import com.android.providers.contacts.tests.R; + +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.provider.ContactsContract; +import android.provider.ContactsContract.PhotoFiles; +import android.test.mock.MockContentResolver; +import android.test.suitebuilder.annotation.LargeTest; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static com.android.providers.contacts.ContactsActor.PACKAGE_GREY; + +/** + * Tests for {@link PhotoStore}. + */ +@LargeTest +public class PhotoStoreTest extends PhotoLoadingTestCase { + + private ContactsActor mActor; + private SynchronousContactsProvider2 mProvider; + private SQLiteDatabase mDb; + + // The object under test. + private PhotoStore mPhotoStore; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mActor = new ContactsActor(getContext(), PACKAGE_GREY, SynchronousContactsProvider2.class, + ContactsContract.AUTHORITY); + mProvider = ((SynchronousContactsProvider2) mActor.provider); + mPhotoStore = mProvider.getPhotoStore(); + mProvider.wipeData(); + mDb = mProvider.getDatabaseHelper(getContext()).getReadableDatabase(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + mPhotoStore.clear(); + } + + public void testStoreThumbnailPhoto() throws IOException { + byte[] photo = loadPhotoFromResource(R.drawable.earth_small, PhotoSize.ORIGINAL); + + // Since the photo is already thumbnail-sized, no file will be stored. + assertEquals(0, mPhotoStore.insert(new PhotoProcessor(photo, 256, 96))); + } + + public void testStoreMediumPhoto() throws IOException { + runStorageTestForResource(R.drawable.earth_normal); + } + + public void testStoreLargePhoto() throws IOException { + runStorageTestForResource(R.drawable.earth_large); + } + + public void testStoreHugePhoto() throws IOException { + runStorageTestForResource(R.drawable.earth_huge); + } + + /** + * Runs the following steps: + * - Loads the given photo resource. + * - Inserts it into the photo store. + * - Checks that the photo has a photo file ID. + * - Loads the expected display photo for the resource. + * - Gets the photo entry from the photo store. + * - Loads the photo entry's file content from disk. + * - Compares the expected photo content to the disk content. + * - Queries the contacts provider for the photo file entry, checks for its + * existence, and matches it up against the expected metadata. + * - Checks that the total storage taken up by the photo store is equal to + * the size of the photo. + * @param resourceId The resource ID of the photo file to test. + */ + public void runStorageTestForResource(int resourceId) throws IOException { + byte[] photo = loadPhotoFromResource(resourceId, PhotoSize.ORIGINAL); + long photoFileId = mPhotoStore.insert(new PhotoProcessor(photo, 256, 96)); + assertTrue(photoFileId != 0); + + byte[] expectedStoredVersion = loadPhotoFromResource(resourceId, PhotoSize.DISPLAY_PHOTO); + File storedFile = new File(mPhotoStore.get(photoFileId).path); + assertTrue(storedFile.exists()); + byte[] storedVersion = readInputStreamFully(new FileInputStream(storedFile)); + assertEquals(Hex.encodeHex(expectedStoredVersion, false), + Hex.encodeHex(storedVersion, false)); + + Cursor c = mDb.query(Tables.PHOTO_FILES, + new String[]{PhotoFiles.HEIGHT, PhotoFiles.WIDTH, PhotoFiles.FILESIZE}, + PhotoFiles._ID + "=?", new String[]{String.valueOf(photoFileId)}, null, null, null); + try { + assertEquals(1, c.getCount()); + c.moveToFirst(); + assertEquals(256, c.getInt(0)); + assertEquals(256, c.getInt(1)); + assertEquals(expectedStoredVersion.length, c.getInt(2)); + } finally { + c.close(); + } + + assertEquals(expectedStoredVersion.length, mPhotoStore.getTotalSize()); + } + + public void testRemoveEntry() throws IOException { + byte[] photo = loadPhotoFromResource(R.drawable.earth_normal, PhotoSize.ORIGINAL); + long photoFileId = mPhotoStore.insert(new PhotoProcessor(photo, 256, 96)); + PhotoStore.Entry entry = mPhotoStore.get(photoFileId); + assertTrue(new File(entry.path).exists()); + + mPhotoStore.remove(photoFileId); + + // Check that the file has been deleted. + assertFalse(new File(entry.path).exists()); + + // Check that the database record has also been removed. + Cursor c = mDb.query(Tables.PHOTO_FILES, new String[]{PhotoFiles._ID}, + PhotoFiles._ID + "=?", new String[]{String.valueOf(photoFileId)}, null, null, null); + try { + assertEquals(0, c.getCount()); + } finally { + c.close(); + } + } + + public void testCleanup() throws IOException { + // Load some photos into the store. + Set<Long> photoFileIds = new HashSet<Long>(); + Map<Integer, Long> resourceIdToPhotoMap = new HashMap<Integer, Long>(); + int[] resourceIds = new int[] { + R.drawable.earth_normal, R.drawable.earth_large, R.drawable.earth_huge + }; + for (int resourceId : resourceIds) { + long photoFileId = mPhotoStore.insert( + new PhotoProcessor(loadPhotoFromResource(resourceId, PhotoSize.ORIGINAL), + 256, 96)); + resourceIdToPhotoMap.put(resourceId, photoFileId); + photoFileIds.add(photoFileId); + } + assertFalse(photoFileIds.contains(0L)); + assertEquals(3, photoFileIds.size()); + + // Run cleanup with the indication that only the large and huge photos are in use, along + // with a bogus photo file ID that isn't in the photo store. + long bogusPhotoFileId = 42; + Set<Long> photoFileIdsInUse = new HashSet<Long>(); + photoFileIdsInUse.add(resourceIdToPhotoMap.get(R.drawable.earth_large)); + photoFileIdsInUse.add(resourceIdToPhotoMap.get(R.drawable.earth_huge)); + photoFileIdsInUse.add(bogusPhotoFileId); + + Set<Long> photoIdsToCleanup = mPhotoStore.cleanup(photoFileIdsInUse); + + // The set of photo IDs to clean up should consist of the bogus photo file ID. + assertEquals(1, photoIdsToCleanup.size()); + assertTrue(photoIdsToCleanup.contains(bogusPhotoFileId)); + + // The entry for the normal-sized photo should have been cleaned up, since it isn't being + // used. + long normalPhotoId = resourceIdToPhotoMap.get(R.drawable.earth_normal); + assertNull(mPhotoStore.get(normalPhotoId)); + + // Check that the database record has also been removed. + Cursor c = mDb.query(Tables.PHOTO_FILES, new String[]{PhotoFiles._ID}, + PhotoFiles._ID + "=?", new String[]{String.valueOf(normalPhotoId)}, + null, null, null); + try { + assertEquals(0, c.getCount()); + } finally { + c.close(); + } + } +} |