michael@0: package org.mozilla.gecko.tests; michael@0: michael@0: import java.util.ArrayList; michael@0: import java.util.Random; michael@0: michael@0: import org.mozilla.gecko.db.BrowserContract; michael@0: michael@0: import android.content.ContentProviderOperation; michael@0: import android.content.ContentProviderResult; michael@0: import android.content.ContentUris; michael@0: import android.content.ContentValues; michael@0: import android.content.OperationApplicationException; michael@0: import android.database.Cursor; michael@0: import android.net.Uri; michael@0: import android.os.Build; michael@0: import android.util.Log; michael@0: michael@0: /* michael@0: * This test is meant to exercise all operations exposed by Fennec's michael@0: * history and bookmarks content provider. It does so in an isolated michael@0: * environment (see ContentProviderTest) without affecting any UI-related michael@0: * code. michael@0: */ michael@0: public class testBrowserProvider extends ContentProviderTest { michael@0: private long mMobileFolderId; michael@0: michael@0: private void loadMobileFolderId() throws Exception { michael@0: Cursor c = null; michael@0: try { michael@0: c = getBookmarkByGuid(BrowserContract.Bookmarks.MOBILE_FOLDER_GUID); michael@0: mAsserter.is(c.moveToFirst(), true, "Mobile bookmarks folder is present"); michael@0: michael@0: mMobileFolderId = c.getLong(c.getColumnIndex(BrowserContract.Bookmarks._ID)); michael@0: } finally { michael@0: if (c != null) { michael@0: c.close(); michael@0: } michael@0: } michael@0: } michael@0: michael@0: private void ensureEmptyDatabase() throws Exception { michael@0: Cursor c = null; michael@0: michael@0: String guid = BrowserContract.Bookmarks.GUID; michael@0: michael@0: mProvider.delete(appendUriParam(BrowserContract.Bookmarks.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"), michael@0: guid + " != ? AND " + michael@0: guid + " != ? AND " + michael@0: guid + " != ? AND " + michael@0: guid + " != ? AND " + michael@0: guid + " != ? AND " + michael@0: guid + " != ? AND " + michael@0: guid + " != ?", michael@0: new String[] { BrowserContract.Bookmarks.PLACES_FOLDER_GUID, michael@0: BrowserContract.Bookmarks.MOBILE_FOLDER_GUID, michael@0: BrowserContract.Bookmarks.MENU_FOLDER_GUID, michael@0: BrowserContract.Bookmarks.TAGS_FOLDER_GUID, michael@0: BrowserContract.Bookmarks.TOOLBAR_FOLDER_GUID, michael@0: BrowserContract.Bookmarks.UNFILED_FOLDER_GUID, michael@0: BrowserContract.Bookmarks.READING_LIST_FOLDER_GUID }); michael@0: michael@0: c = mProvider.query(appendUriParam(BrowserContract.Bookmarks.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), null, null, null, null); michael@0: assertCountIsAndClose(c, 7, "All non-special bookmarks and folders were deleted"); michael@0: michael@0: mProvider.delete(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"), null, null); michael@0: c = mProvider.query(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), null, null, null, null); michael@0: assertCountIsAndClose(c, 0, "All history entries were deleted"); michael@0: michael@0: /** michael@0: * There's no reason why the following two parts should fail. michael@0: * But sometimes they do, and I'm not going to spend the time michael@0: * to figure out why in an unrelated bug. michael@0: */ michael@0: michael@0: mProvider.delete(appendUriParam(BrowserContract.Favicons.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"), null, null); michael@0: c = mProvider.query(appendUriParam(BrowserContract.Favicons.CONTENT_URI, michael@0: BrowserContract.PARAM_SHOW_DELETED, "1"), michael@0: null, null, null, null); michael@0: michael@0: if (c.getCount() > 0) { michael@0: mAsserter.dumpLog("Unexpected favicons in ensureEmptyDatabase."); michael@0: } michael@0: c.close(); michael@0: michael@0: mAsserter.dumpLog("ensureEmptyDatabase: Favicon deletion completed."); // Bug 968951 debug. michael@0: // assertCountIsAndClose(c, 0, "All favicons were deleted"); michael@0: michael@0: mProvider.delete(appendUriParam(BrowserContract.Thumbnails.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"), null, null); michael@0: c = mProvider.query(appendUriParam(BrowserContract.Thumbnails.CONTENT_URI, michael@0: BrowserContract.PARAM_SHOW_DELETED, "1"), michael@0: null, null, null, null); michael@0: michael@0: if (c.getCount() > 0) { michael@0: mAsserter.dumpLog("Unexpected thumbnails in ensureEmptyDatabase."); michael@0: } michael@0: c.close(); michael@0: michael@0: mAsserter.dumpLog("ensureEmptyDatabase: Thumbnail deletion completed."); // Bug 968951 debug. michael@0: // assertCountIsAndClose(c, 0, "All thumbnails were deleted"); michael@0: } michael@0: michael@0: private ContentValues createBookmark(String title, String url, long parentId, michael@0: int type, int position, String tags, String description, String keyword) throws Exception { michael@0: ContentValues bookmark = new ContentValues(); michael@0: michael@0: bookmark.put(BrowserContract.Bookmarks.TITLE, title); michael@0: bookmark.put(BrowserContract.Bookmarks.URL, url); michael@0: bookmark.put(BrowserContract.Bookmarks.PARENT, parentId); michael@0: bookmark.put(BrowserContract.Bookmarks.TYPE, type); michael@0: bookmark.put(BrowserContract.Bookmarks.POSITION, position); michael@0: bookmark.put(BrowserContract.Bookmarks.TAGS, tags); michael@0: bookmark.put(BrowserContract.Bookmarks.DESCRIPTION, description); michael@0: bookmark.put(BrowserContract.Bookmarks.KEYWORD, keyword); michael@0: michael@0: return bookmark; michael@0: } michael@0: michael@0: private ContentValues createOneBookmark() throws Exception { michael@0: return createBookmark("Example", "http://example.com", mMobileFolderId, michael@0: BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); michael@0: } michael@0: michael@0: private Cursor getBookmarksByParent(long parent) throws Exception { michael@0: // Order by position. michael@0: return mProvider.query(BrowserContract.Bookmarks.CONTENT_URI, null, michael@0: BrowserContract.Bookmarks.PARENT + " = ?", michael@0: new String[] { String.valueOf(parent) }, michael@0: BrowserContract.Bookmarks.POSITION); michael@0: } michael@0: michael@0: private Cursor getBookmarkByGuid(String guid) throws Exception { michael@0: return mProvider.query(BrowserContract.Bookmarks.CONTENT_URI, null, michael@0: BrowserContract.Bookmarks.GUID + " = ?", michael@0: new String[] { guid }, michael@0: null); michael@0: } michael@0: michael@0: private Cursor getBookmarkById(long id) throws Exception { michael@0: return getBookmarkById(BrowserContract.Bookmarks.CONTENT_URI, id, null); michael@0: } michael@0: michael@0: private Cursor getBookmarkById(long id, String[] projection) throws Exception { michael@0: return getBookmarkById(BrowserContract.Bookmarks.CONTENT_URI, id, projection); michael@0: } michael@0: michael@0: private Cursor getBookmarkById(Uri bookmarksUri, long id) throws Exception { michael@0: return getBookmarkById(bookmarksUri, id, null); michael@0: } michael@0: michael@0: private Cursor getBookmarkById(Uri bookmarksUri, long id, String[] projection) throws Exception { michael@0: return mProvider.query(bookmarksUri, projection, michael@0: BrowserContract.Bookmarks._ID + " = ?", michael@0: new String[] { String.valueOf(id) }, michael@0: null); michael@0: } michael@0: michael@0: private ContentValues createHistoryEntry(String title, String url, int visits, long lastVisited) throws Exception { michael@0: ContentValues historyEntry = new ContentValues(); michael@0: michael@0: historyEntry.put(BrowserContract.History.TITLE, title); michael@0: historyEntry.put(BrowserContract.History.URL, url); michael@0: historyEntry.put(BrowserContract.History.VISITS, visits); michael@0: historyEntry.put(BrowserContract.History.DATE_LAST_VISITED, lastVisited); michael@0: michael@0: return historyEntry; michael@0: } michael@0: michael@0: private ContentValues createFaviconEntry(String pageUrl, String data) throws Exception { michael@0: ContentValues faviconEntry = new ContentValues(); michael@0: michael@0: faviconEntry.put(BrowserContract.Favicons.PAGE_URL, pageUrl); michael@0: faviconEntry.put(BrowserContract.Favicons.URL, pageUrl + "/favicon.ico"); michael@0: faviconEntry.put(BrowserContract.Favicons.DATA, data.getBytes("UTF8")); michael@0: michael@0: return faviconEntry; michael@0: } michael@0: michael@0: private ContentValues createThumbnailEntry(String pageUrl, String data) throws Exception { michael@0: ContentValues thumbnailEntry = new ContentValues(); michael@0: michael@0: thumbnailEntry.put(BrowserContract.Thumbnails.URL, pageUrl); michael@0: thumbnailEntry.put(BrowserContract.Thumbnails.DATA, data.getBytes("UTF8")); michael@0: michael@0: return thumbnailEntry; michael@0: } michael@0: michael@0: private ContentValues createOneHistoryEntry() throws Exception { michael@0: return createHistoryEntry("Example", "http://example.com", 10, System.currentTimeMillis()); michael@0: } michael@0: michael@0: private Cursor getHistoryEntryById(long id) throws Exception { michael@0: return getHistoryEntryById(BrowserContract.History.CONTENT_URI, id, null); michael@0: } michael@0: michael@0: private Cursor getHistoryEntryById(long id, String[] projection) throws Exception { michael@0: return getHistoryEntryById(BrowserContract.History.CONTENT_URI, id, projection); michael@0: } michael@0: michael@0: private Cursor getHistoryEntryById(Uri historyUri, long id) throws Exception { michael@0: return getHistoryEntryById(historyUri, id, null); michael@0: } michael@0: michael@0: private Cursor getHistoryEntryById(Uri historyUri, long id, String[] projection) throws Exception { michael@0: return mProvider.query(historyUri, projection, michael@0: BrowserContract.History._ID + " = ?", michael@0: new String[] { String.valueOf(id) }, michael@0: null); michael@0: } michael@0: michael@0: private Cursor getFaviconsByUrl(String url) throws Exception { michael@0: return mProvider.query(BrowserContract.Combined.CONTENT_URI, null, michael@0: BrowserContract.Combined.URL + " = ?", michael@0: new String[] { url }, michael@0: null); michael@0: } michael@0: michael@0: private Cursor getThumbnailByUrl(String url) throws Exception { michael@0: return mProvider.query(BrowserContract.Thumbnails.CONTENT_URI, null, michael@0: BrowserContract.Thumbnails.URL + " = ?", michael@0: new String[] { url }, michael@0: null); michael@0: } michael@0: michael@0: @Override michael@0: public void setUp() throws Exception { michael@0: super.setUp(sBrowserProviderCallable, BrowserContract.AUTHORITY, "browser.db"); michael@0: michael@0: mTests.add(new TestSpecialFolders()); michael@0: michael@0: mTests.add(new TestInsertBookmarks()); michael@0: mTests.add(new TestInsertBookmarksFavicons()); michael@0: mTests.add(new TestDeleteBookmarks()); michael@0: mTests.add(new TestDeleteBookmarksFavicons()); michael@0: mTests.add(new TestUpdateBookmarks()); michael@0: mTests.add(new TestUpdateBookmarksFavicons()); michael@0: mTests.add(new TestPositionBookmarks()); michael@0: michael@0: mTests.add(new TestInsertHistory()); michael@0: mTests.add(new TestInsertHistoryFavicons()); michael@0: mTests.add(new TestDeleteHistory()); michael@0: mTests.add(new TestDeleteHistoryFavicons()); michael@0: mTests.add(new TestUpdateHistory()); michael@0: mTests.add(new TestUpdateHistoryFavicons()); michael@0: mTests.add(new TestUpdateOrInsertHistory()); michael@0: mTests.add(new TestInsertHistoryThumbnails()); michael@0: mTests.add(new TestUpdateHistoryThumbnails()); michael@0: mTests.add(new TestDeleteHistoryThumbnails()); michael@0: michael@0: mTests.add(new TestBatchOperations()); michael@0: michael@0: mTests.add(new TestCombinedView()); michael@0: mTests.add(new TestCombinedViewDisplay()); michael@0: mTests.add(new TestCombinedViewWithDeletedBookmark()); michael@0: mTests.add(new TestCombinedViewWithDeletedReadingListItem()); michael@0: mTests.add(new TestExpireHistory()); michael@0: michael@0: mTests.add(new TestBrowserProviderNotifications()); michael@0: } michael@0: michael@0: public void testBrowserProvider() throws Exception { michael@0: loadMobileFolderId(); michael@0: michael@0: for (int i = 0; i < mTests.size(); i++) { michael@0: Runnable test = mTests.get(i); michael@0: michael@0: final String testName = test.getClass().getSimpleName(); michael@0: setTestName(testName); michael@0: ensureEmptyDatabase(); michael@0: mAsserter.dumpLog("testBrowserProvider: Database empty - Starting " + testName + "."); michael@0: test.run(); michael@0: } michael@0: } michael@0: michael@0: private class TestBatchOperations extends TestCase { michael@0: static final int TESTCOUNT = 100; michael@0: michael@0: public void testApplyBatch() throws Exception { michael@0: ArrayList mOperations michael@0: = new ArrayList(); michael@0: michael@0: // Test a bunch of inserts with applyBatch michael@0: ContentValues values = new ContentValues(); michael@0: ContentProviderOperation.Builder builder = null; michael@0: michael@0: for (int i = 0; i < TESTCOUNT; i++) { michael@0: values.clear(); michael@0: values.put(BrowserContract.History.VISITS, i); michael@0: values.put(BrowserContract.History.TITLE, "Test" + i); michael@0: values.put(BrowserContract.History.URL, "http://www.test.org/" + i); michael@0: michael@0: // Insert michael@0: builder = ContentProviderOperation.newInsert(BrowserContract.History.CONTENT_URI); michael@0: builder.withValues(values); michael@0: // Queue the operation michael@0: mOperations.add(builder.build()); michael@0: } michael@0: michael@0: ContentProviderResult[] applyResult = michael@0: mProvider.applyBatch(mOperations); michael@0: michael@0: boolean allFound = true; michael@0: for (int i = 0; i < TESTCOUNT; i++) { michael@0: Cursor cursor = mProvider.query(BrowserContract.History.CONTENT_URI, michael@0: null, michael@0: BrowserContract.History.URL + " = ?", michael@0: new String[] { "http://www.test.org/" + i }, michael@0: null); michael@0: michael@0: if (!cursor.moveToFirst()) michael@0: allFound = false; michael@0: cursor.close(); michael@0: } michael@0: mAsserter.is(allFound, true, "Found all batchApply entries"); michael@0: mOperations.clear(); michael@0: michael@0: // Update all visits to 1 michael@0: values.clear(); michael@0: values.put(BrowserContract.History.VISITS, 1); michael@0: for (int i = 0; i < TESTCOUNT; i++) { michael@0: builder = ContentProviderOperation.newUpdate(BrowserContract.History.CONTENT_URI); michael@0: builder.withSelection(BrowserContract.History.URL + " = ?", michael@0: new String[] {"http://www.test.org/" + i}); michael@0: builder.withValues(values); michael@0: builder.withExpectedCount(1); michael@0: // Queue the operation michael@0: mOperations.add(builder.build()); michael@0: } michael@0: michael@0: boolean seenException = false; michael@0: try { michael@0: applyResult = mProvider.applyBatch(mOperations); michael@0: } catch (OperationApplicationException ex) { michael@0: seenException = true; michael@0: } michael@0: mAsserter.is(seenException, false, "Batch updating succeded"); michael@0: mOperations.clear(); michael@0: michael@0: // Delete all visits michael@0: for (int i = 0; i < TESTCOUNT; i++) { michael@0: builder = ContentProviderOperation.newDelete(BrowserContract.History.CONTENT_URI); michael@0: builder.withSelection(BrowserContract.History.URL + " = ?", michael@0: new String[] {"http://www.test.org/" + i}); michael@0: builder.withExpectedCount(1); michael@0: // Queue the operation michael@0: mOperations.add(builder.build()); michael@0: } michael@0: try { michael@0: applyResult = mProvider.applyBatch(mOperations); michael@0: } catch (OperationApplicationException ex) { michael@0: seenException = true; michael@0: } michael@0: mAsserter.is(seenException, false, "Batch deletion succeeded"); michael@0: } michael@0: michael@0: // Force a Constraint error, see if later operations still apply correctly michael@0: public void testApplyBatchErrors() throws Exception { michael@0: ArrayList mOperations michael@0: = new ArrayList(); michael@0: michael@0: // Test a bunch of inserts with applyBatch michael@0: ContentProviderOperation.Builder builder = null; michael@0: ContentValues values = createFaviconEntry("http://www.test.org", "FAVICON"); michael@0: builder = ContentProviderOperation.newInsert(BrowserContract.Favicons.CONTENT_URI); michael@0: builder.withValues(values); michael@0: mOperations.add(builder.build()); michael@0: michael@0: // Make a duplicate, this will fail because of a UNIQUE constraint michael@0: builder = ContentProviderOperation.newInsert(BrowserContract.Favicons.CONTENT_URI); michael@0: builder.withValues(values); michael@0: mOperations.add(builder.build()); michael@0: michael@0: // This is valid and should be in the table afterwards michael@0: values.put(BrowserContract.Favicons.URL, "http://www.test.org/valid.ico"); michael@0: builder = ContentProviderOperation.newInsert(BrowserContract.Favicons.CONTENT_URI); michael@0: builder.withValues(values); michael@0: mOperations.add(builder.build()); michael@0: michael@0: boolean seenException = false; michael@0: michael@0: try { michael@0: ContentProviderResult[] applyResult = michael@0: mProvider.applyBatch(mOperations); michael@0: } catch (OperationApplicationException ex) { michael@0: seenException = true; michael@0: } michael@0: michael@0: // This test may need to go away if Bug 717428 is fixed. michael@0: mAsserter.is(seenException, true, "Expected failure in favicons table"); michael@0: michael@0: boolean allFound = true; michael@0: Cursor cursor = mProvider.query(BrowserContract.Favicons.CONTENT_URI, michael@0: null, michael@0: BrowserContract.Favicons.URL + " = ?", michael@0: new String[] { "http://www.test.org/valid.ico" }, michael@0: null); michael@0: michael@0: if (!cursor.moveToFirst()) michael@0: allFound = false; michael@0: cursor.close(); michael@0: michael@0: mAsserter.is(allFound, true, "Found all applyBatch (with error) entries"); michael@0: } michael@0: michael@0: public void testBulkInsert() throws Exception { michael@0: // Test a bunch of inserts with bulkInsert michael@0: ContentValues allVals[] = new ContentValues[TESTCOUNT]; michael@0: for (int i = 0; i < TESTCOUNT; i++) { michael@0: allVals[i] = new ContentValues(); michael@0: allVals[i].put(BrowserContract.History.URL, i); michael@0: allVals[i].put(BrowserContract.History.TITLE, "Test" + i); michael@0: allVals[i].put(BrowserContract.History.URL, "http://www.test.org/" + i); michael@0: } michael@0: michael@0: int inserts = mProvider.bulkInsert(BrowserContract.History.CONTENT_URI, allVals); michael@0: mAsserter.is(inserts, TESTCOUNT, "Excepted number of inserts matches"); michael@0: michael@0: boolean allFound = true; michael@0: for (int i = 0; i < TESTCOUNT; i++) { michael@0: Cursor cursor = mProvider.query(BrowserContract.History.CONTENT_URI, michael@0: null, michael@0: BrowserContract.History.URL + " = ?", michael@0: new String[] { "http://www.test.org/" + i }, michael@0: null); michael@0: michael@0: if (!cursor.moveToFirst()) michael@0: allFound = false; michael@0: cursor.close(); michael@0: } michael@0: mAsserter.is(allFound, true, "Found all bulkInsert entries"); michael@0: } michael@0: michael@0: @Override michael@0: public void test() throws Exception { michael@0: testApplyBatch(); michael@0: // Clean up michael@0: ensureEmptyDatabase(); michael@0: michael@0: testBulkInsert(); michael@0: ensureEmptyDatabase(); michael@0: michael@0: testApplyBatchErrors(); michael@0: } michael@0: } michael@0: michael@0: private class TestSpecialFolders extends TestCase { michael@0: @Override michael@0: public void test() throws Exception { michael@0: Cursor c = mProvider.query(BrowserContract.Bookmarks.CONTENT_URI, michael@0: new String[] { BrowserContract.Bookmarks._ID, michael@0: BrowserContract.Bookmarks.GUID, michael@0: BrowserContract.Bookmarks.PARENT }, michael@0: BrowserContract.Bookmarks.GUID + " = ? OR " + michael@0: BrowserContract.Bookmarks.GUID + " = ? OR " + michael@0: BrowserContract.Bookmarks.GUID + " = ? OR " + michael@0: BrowserContract.Bookmarks.GUID + " = ? OR " + michael@0: BrowserContract.Bookmarks.GUID + " = ? OR " + michael@0: BrowserContract.Bookmarks.GUID + " = ? OR " + michael@0: BrowserContract.Bookmarks.GUID + " = ?", michael@0: new String[] { BrowserContract.Bookmarks.PLACES_FOLDER_GUID, michael@0: BrowserContract.Bookmarks.MOBILE_FOLDER_GUID, michael@0: BrowserContract.Bookmarks.MENU_FOLDER_GUID, michael@0: BrowserContract.Bookmarks.TAGS_FOLDER_GUID, michael@0: BrowserContract.Bookmarks.TOOLBAR_FOLDER_GUID, michael@0: BrowserContract.Bookmarks.UNFILED_FOLDER_GUID, michael@0: BrowserContract.Bookmarks.READING_LIST_FOLDER_GUID }, michael@0: null); michael@0: michael@0: mAsserter.is(c.getCount(), 7, "Right number of special folders"); michael@0: michael@0: int rootId = BrowserContract.Bookmarks.FIXED_ROOT_ID; michael@0: int readingListId = BrowserContract.Bookmarks.FIXED_READING_LIST_ID; michael@0: michael@0: while (c.moveToNext()) { michael@0: int id = c.getInt(c.getColumnIndex(BrowserContract.Bookmarks._ID)); michael@0: String guid = c.getString(c.getColumnIndex(BrowserContract.Bookmarks.GUID)); michael@0: int parentId = c.getInt(c.getColumnIndex(BrowserContract.Bookmarks.PARENT)); michael@0: michael@0: if (guid.equals(BrowserContract.Bookmarks.PLACES_FOLDER_GUID)) { michael@0: mAsserter.is(new Integer(id), new Integer(rootId), "The id of places folder is correct"); michael@0: } else if (guid.equals(BrowserContract.Bookmarks.READING_LIST_FOLDER_GUID)) { michael@0: mAsserter.is(new Integer(id), new Integer(readingListId), "The id of reading list folder is correct"); michael@0: } michael@0: michael@0: mAsserter.is(new Integer(parentId), new Integer(rootId), michael@0: "The PARENT of the " + guid + " special folder is correct"); michael@0: } michael@0: michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestInsertBookmarks extends TestCase { michael@0: private long insertWithNullCol(String colName) throws Exception { michael@0: ContentValues b = createOneBookmark(); michael@0: b.putNull(colName); michael@0: long id = -1; michael@0: michael@0: try { michael@0: id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); michael@0: } catch (Exception e) {} michael@0: michael@0: return id; michael@0: } michael@0: michael@0: @Override michael@0: public void test() throws Exception { michael@0: ContentValues b = createOneBookmark(); michael@0: long id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); michael@0: Cursor c = getBookmarkById(id); michael@0: michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found"); michael@0: michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TITLE)), b.getAsString(BrowserContract.Bookmarks.TITLE), michael@0: "Inserted bookmark has correct title"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.URL)), b.getAsString(BrowserContract.Bookmarks.URL), michael@0: "Inserted bookmark has correct URL"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TAGS)), b.getAsString(BrowserContract.Bookmarks.TAGS), michael@0: "Inserted bookmark has correct tags"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.KEYWORD)), b.getAsString(BrowserContract.Bookmarks.KEYWORD), michael@0: "Inserted bookmark has correct keyword"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.DESCRIPTION)), b.getAsString(BrowserContract.Bookmarks.DESCRIPTION), michael@0: "Inserted bookmark has correct description"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.POSITION)), b.getAsString(BrowserContract.Bookmarks.POSITION), michael@0: "Inserted bookmark has correct position"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TYPE)), b.getAsString(BrowserContract.Bookmarks.TYPE), michael@0: "Inserted bookmark has correct type"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.PARENT)), b.getAsString(BrowserContract.Bookmarks.PARENT), michael@0: "Inserted bookmark has correct parent ID"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.IS_DELETED)), String.valueOf(0), michael@0: "Inserted bookmark has correct is-deleted state"); michael@0: michael@0: id = insertWithNullCol(BrowserContract.Bookmarks.POSITION); michael@0: mAsserter.is(new Long(id), new Long(-1), michael@0: "Should not be able to insert bookmark with null position"); michael@0: michael@0: id = insertWithNullCol(BrowserContract.Bookmarks.TYPE); michael@0: mAsserter.is(new Long(id), new Long(-1), michael@0: "Should not be able to insert bookmark with null type"); michael@0: michael@0: if (Build.VERSION.SDK_INT >= 8 && michael@0: Build.VERSION.SDK_INT < 16) { michael@0: b = createOneBookmark(); michael@0: b.put(BrowserContract.Bookmarks.PARENT, -1); michael@0: id = -1; michael@0: michael@0: try { michael@0: id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); michael@0: } catch (Exception e) {} michael@0: michael@0: mAsserter.is(new Long(id), new Long(-1), michael@0: "Should not be able to insert bookmark with invalid parent"); michael@0: } michael@0: michael@0: b = createOneBookmark(); michael@0: b.remove(BrowserContract.Bookmarks.TYPE); michael@0: id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); michael@0: c = getBookmarkById(id); michael@0: michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found"); michael@0: michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TYPE)), String.valueOf(BrowserContract.Bookmarks.TYPE_BOOKMARK), michael@0: "Inserted bookmark has correct default type"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestInsertBookmarksFavicons extends TestCase { michael@0: @Override michael@0: public void test() throws Exception { michael@0: ContentValues b = createOneBookmark(); michael@0: michael@0: final String favicon = "FAVICON"; michael@0: final String pageUrl = b.getAsString(BrowserContract.Bookmarks.URL); michael@0: michael@0: long id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); michael@0: michael@0: // Insert the favicon into the favicons table michael@0: mProvider.insert(BrowserContract.Favicons.CONTENT_URI, createFaviconEntry(pageUrl, favicon)); michael@0: michael@0: Cursor c = getBookmarkById(id, new String[] { BrowserContract.Bookmarks.FAVICON }); michael@0: michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found"); michael@0: michael@0: mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Bookmarks.FAVICON)), "UTF8"), michael@0: favicon, "Inserted bookmark has corresponding favicon image"); michael@0: c.close(); michael@0: michael@0: c = getFaviconsByUrl(pageUrl); michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted favicon found"); michael@0: michael@0: mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"), michael@0: favicon, "Inserted favicon has corresponding favicon image"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestDeleteBookmarks extends TestCase { michael@0: private long insertOneBookmark() throws Exception { michael@0: ContentValues b = createOneBookmark(); michael@0: long id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); michael@0: michael@0: Cursor c = getBookmarkById(id); michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found"); michael@0: c.close(); michael@0: michael@0: return id; michael@0: } michael@0: michael@0: @Override michael@0: public void test() throws Exception { michael@0: long id = insertOneBookmark(); michael@0: michael@0: int deleted = mProvider.delete(BrowserContract.Bookmarks.CONTENT_URI, michael@0: BrowserContract.Bookmarks._ID + " = ?", michael@0: new String[] { String.valueOf(id) }); michael@0: michael@0: mAsserter.is((deleted == 1), true, "Inserted bookmark was deleted"); michael@0: michael@0: Cursor c = getBookmarkById(appendUriParam(BrowserContract.Bookmarks.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), id); michael@0: mAsserter.is(c.moveToFirst(), true, "Deleted bookmark was only marked as deleted"); michael@0: c.close(); michael@0: michael@0: deleted = mProvider.delete(appendUriParam(BrowserContract.Bookmarks.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"), michael@0: BrowserContract.Bookmarks._ID + " = ?", michael@0: new String[] { String.valueOf(id) }); michael@0: michael@0: mAsserter.is((deleted == 1), true, "Inserted bookmark was deleted"); michael@0: michael@0: c = getBookmarkById(appendUriParam(BrowserContract.Bookmarks.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), id); michael@0: mAsserter.is(c.moveToFirst(), false, "Inserted bookmark is now actually deleted"); michael@0: c.close(); michael@0: michael@0: id = insertOneBookmark(); michael@0: michael@0: deleted = mProvider.delete(ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, id), null, null); michael@0: mAsserter.is((deleted == 1), true, michael@0: "Inserted bookmark was deleted using URI with id"); michael@0: michael@0: c = getBookmarkById(id); michael@0: mAsserter.is(c.moveToFirst(), false, michael@0: "Inserted bookmark can't be found after deletion using URI with ID"); michael@0: c.close(); michael@0: michael@0: if (Build.VERSION.SDK_INT >= 8 && michael@0: Build.VERSION.SDK_INT < 16) { michael@0: ContentValues b = createBookmark("Folder", null, mMobileFolderId, michael@0: BrowserContract.Bookmarks.TYPE_FOLDER, 0, "folderTags", "folderDescription", "folderKeyword"); michael@0: michael@0: long parentId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); michael@0: c = getBookmarkById(parentId); michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted bookmarks folder found"); michael@0: c.close(); michael@0: michael@0: b = createBookmark("Example", "http://example.com", parentId, michael@0: BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); michael@0: michael@0: id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); michael@0: c = getBookmarkById(id); michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found"); michael@0: c.close(); michael@0: michael@0: deleted = 0; michael@0: try { michael@0: Uri uri = ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, parentId); michael@0: deleted = mProvider.delete(appendUriParam(uri, BrowserContract.PARAM_IS_SYNC, "1"), null, null); michael@0: } catch(Exception e) {} michael@0: michael@0: mAsserter.is((deleted == 0), true, michael@0: "Should not be able to delete folder that causes orphan bookmarks"); michael@0: } michael@0: } michael@0: } michael@0: michael@0: private class TestDeleteBookmarksFavicons extends TestCase { michael@0: @Override michael@0: public void test() throws Exception { michael@0: ContentValues b = createOneBookmark(); michael@0: michael@0: final String pageUrl = b.getAsString(BrowserContract.Bookmarks.URL); michael@0: long id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); michael@0: michael@0: // Insert the favicon into the favicons table michael@0: mProvider.insert(BrowserContract.Favicons.CONTENT_URI, createFaviconEntry(pageUrl, "FAVICON")); michael@0: michael@0: Cursor c = getFaviconsByUrl(pageUrl); michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted favicon found"); michael@0: c.close(); michael@0: michael@0: mProvider.delete(ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, id), null, null); michael@0: michael@0: c = getFaviconsByUrl(pageUrl); michael@0: mAsserter.is(c.moveToFirst(), false, "Favicon is deleted with last reference to it"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestUpdateBookmarks extends TestCase { michael@0: private int updateWithNullCol(long id, String colName) throws Exception { michael@0: ContentValues u = new ContentValues(); michael@0: u.putNull(colName); michael@0: michael@0: int updated = 0; michael@0: michael@0: try { michael@0: updated = mProvider.update(BrowserContract.Bookmarks.CONTENT_URI, u, michael@0: BrowserContract.Bookmarks._ID + " = ?", michael@0: new String[] { String.valueOf(id) }); michael@0: } catch (Exception e) {} michael@0: michael@0: return updated; michael@0: } michael@0: michael@0: @Override michael@0: public void test() throws Exception { michael@0: ContentValues b = createOneBookmark(); michael@0: long id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); michael@0: michael@0: Cursor c = getBookmarkById(id); michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found"); michael@0: michael@0: long dateCreated = c.getLong(c.getColumnIndex(BrowserContract.Bookmarks.DATE_CREATED)); michael@0: long dateModified = c.getLong(c.getColumnIndex(BrowserContract.Bookmarks.DATE_MODIFIED)); michael@0: michael@0: ContentValues u = new ContentValues(); michael@0: u.put(BrowserContract.Bookmarks.TITLE, b.getAsString(BrowserContract.Bookmarks.TITLE) + "CHANGED"); michael@0: u.put(BrowserContract.Bookmarks.URL, b.getAsString(BrowserContract.Bookmarks.URL) + "/more/stuff"); michael@0: u.put(BrowserContract.Bookmarks.TAGS, b.getAsString(BrowserContract.Bookmarks.TAGS) + "CHANGED"); michael@0: u.put(BrowserContract.Bookmarks.DESCRIPTION, b.getAsString(BrowserContract.Bookmarks.DESCRIPTION) + "CHANGED"); michael@0: u.put(BrowserContract.Bookmarks.KEYWORD, b.getAsString(BrowserContract.Bookmarks.KEYWORD) + "CHANGED"); michael@0: u.put(BrowserContract.Bookmarks.TYPE, BrowserContract.Bookmarks.TYPE_FOLDER); michael@0: u.put(BrowserContract.Bookmarks.POSITION, 10); michael@0: michael@0: int updated = mProvider.update(BrowserContract.Bookmarks.CONTENT_URI, u, michael@0: BrowserContract.Bookmarks._ID + " = ?", michael@0: new String[] { String.valueOf(id) }); michael@0: michael@0: mAsserter.is((updated == 1), true, "Inserted bookmark was updated"); michael@0: c.close(); michael@0: michael@0: c = getBookmarkById(id); michael@0: mAsserter.is(c.moveToFirst(), true, "Updated bookmark found"); michael@0: michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TITLE)), u.getAsString(BrowserContract.Bookmarks.TITLE), michael@0: "Inserted bookmark has correct title"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.URL)), u.getAsString(BrowserContract.Bookmarks.URL), michael@0: "Inserted bookmark has correct URL"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TAGS)), u.getAsString(BrowserContract.Bookmarks.TAGS), michael@0: "Inserted bookmark has correct tags"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.KEYWORD)), u.getAsString(BrowserContract.Bookmarks.KEYWORD), michael@0: "Inserted bookmark has correct keyword"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.DESCRIPTION)), u.getAsString(BrowserContract.Bookmarks.DESCRIPTION), michael@0: "Inserted bookmark has correct description"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.POSITION)), u.getAsString(BrowserContract.Bookmarks.POSITION), michael@0: "Inserted bookmark has correct position"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TYPE)), u.getAsString(BrowserContract.Bookmarks.TYPE), michael@0: "Inserted bookmark has correct type"); michael@0: michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Bookmarks.DATE_CREATED))), michael@0: new Long(dateCreated), michael@0: "Updated bookmark has same creation date"); michael@0: michael@0: mAsserter.isnot(new Long(c.getLong(c.getColumnIndex(BrowserContract.Bookmarks.DATE_MODIFIED))), michael@0: new Long(dateModified), michael@0: "Updated bookmark has new modification date"); michael@0: michael@0: updated = updateWithNullCol(id, BrowserContract.Bookmarks.POSITION); michael@0: mAsserter.is((updated > 0), false, michael@0: "Should not be able to update bookmark with null position"); michael@0: michael@0: updated = updateWithNullCol(id, BrowserContract.Bookmarks.TYPE); michael@0: mAsserter.is((updated > 0), false, michael@0: "Should not be able to update bookmark with null type"); michael@0: michael@0: u = new ContentValues(); michael@0: u.put(BrowserContract.Bookmarks.URL, "http://examples2.com"); michael@0: michael@0: updated = mProvider.update(ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, id), u, null, null); michael@0: c.close(); michael@0: michael@0: c = getBookmarkById(id); michael@0: mAsserter.is(c.moveToFirst(), true, "Updated bookmark found"); michael@0: michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.URL)), u.getAsString(BrowserContract.Bookmarks.URL), michael@0: "Updated bookmark has correct URL using URI with id"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestUpdateBookmarksFavicons extends TestCase { michael@0: @Override michael@0: public void test() throws Exception { michael@0: ContentValues b = createOneBookmark(); michael@0: michael@0: final String favicon = "FAVICON"; michael@0: final String newFavicon = "NEW_FAVICON"; michael@0: final String pageUrl = b.getAsString(BrowserContract.Bookmarks.URL); michael@0: michael@0: mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b); michael@0: michael@0: // Insert the favicon into the favicons table michael@0: ContentValues f = createFaviconEntry(pageUrl, favicon); michael@0: long faviconId = ContentUris.parseId(mProvider.insert(BrowserContract.Favicons.CONTENT_URI, f)); michael@0: michael@0: Cursor c = getFaviconsByUrl(pageUrl); michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted favicon found"); michael@0: michael@0: mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"), michael@0: favicon, "Inserted favicon has corresponding favicon image"); michael@0: michael@0: ContentValues u = createFaviconEntry(pageUrl, newFavicon); michael@0: mProvider.update(BrowserContract.Favicons.CONTENT_URI, u, null, null); michael@0: c.close(); michael@0: michael@0: c = getFaviconsByUrl(pageUrl); michael@0: mAsserter.is(c.moveToFirst(), true, "Updated favicon found"); michael@0: michael@0: mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"), michael@0: newFavicon, "Updated favicon has corresponding favicon image"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Create a folder of one thousand and one bookmarks, then impose an order michael@0: * on them. michael@0: * michael@0: * Verify that the reordering worked by querying. michael@0: */ michael@0: private class TestPositionBookmarks extends TestCase { michael@0: michael@0: public String makeGUID(final long in) { michael@0: String part = String.valueOf(in); michael@0: return "aaaaaaaaaaaa".substring(0, (12 - part.length())) + part; michael@0: } michael@0: michael@0: public void compareCursorToItems(final Cursor c, final String[] items, final int count) { michael@0: mAsserter.is(c.moveToFirst(), true, "Folder has children."); michael@0: michael@0: int posColumn = c.getColumnIndex(BrowserContract.Bookmarks.POSITION); michael@0: int guidColumn = c.getColumnIndex(BrowserContract.Bookmarks.GUID); michael@0: int i = 0; michael@0: michael@0: while (!c.isAfterLast()) { michael@0: String guid = c.getString(guidColumn); michael@0: long pos = c.getLong(posColumn); michael@0: if ((pos != i) || (guid == null) || (!guid.equals(items[i]))) { michael@0: mAsserter.is(pos, (long) i, "Position matches sequence."); michael@0: mAsserter.is(guid, items[i], "GUID matches sequence."); michael@0: } michael@0: ++i; michael@0: c.moveToNext(); michael@0: } michael@0: michael@0: mAsserter.is(i, count, "Folder has the right number of children."); michael@0: c.close(); michael@0: } michael@0: michael@0: public static final int NUMBER_OF_CHILDREN = 1001; michael@0: @Override michael@0: public void test() throws Exception { michael@0: // Create the containing folder. michael@0: ContentValues folder = createBookmark("FolderFolder", "", mMobileFolderId, michael@0: BrowserContract.Bookmarks.TYPE_FOLDER, 0, "", michael@0: "description", "keyword"); michael@0: folder.put(BrowserContract.Bookmarks.GUID, "folderfolder"); michael@0: long folderId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, folder)); michael@0: michael@0: mAsserter.dumpLog("TestPositionBookmarks: Folder inserted"); // Bug 968951 debug. michael@0: michael@0: // Create the children. michael@0: String[] items = new String[NUMBER_OF_CHILDREN]; michael@0: michael@0: // Reuse the same ContentValues. michael@0: ContentValues item = createBookmark("Test Bookmark", "http://example.com", folderId, michael@0: BrowserContract.Bookmarks.TYPE_FOLDER, 0, "", michael@0: "description", "keyword"); michael@0: michael@0: for (int i = 0; i < NUMBER_OF_CHILDREN; ++i) { michael@0: String guid = makeGUID(i); michael@0: items[i] = guid; michael@0: item.put(BrowserContract.Bookmarks.GUID, guid); michael@0: item.put(BrowserContract.Bookmarks.POSITION, i); michael@0: item.put(BrowserContract.Bookmarks.URL, "http://example.com/" + guid); michael@0: item.put(BrowserContract.Bookmarks.TITLE, "Test Bookmark " + guid); michael@0: mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, item); michael@0: } michael@0: michael@0: mAsserter.dumpLog("TestPositionBookmarks: Bookmarks inserted"); // Bug 968951 debug. michael@0: michael@0: Cursor c; michael@0: michael@0: // Verify insertion. michael@0: c = getBookmarksByParent(folderId); michael@0: mAsserter.dumpLog("TestPositionBookmarks: Got bookmarks by parent"); // Bug 968951 debug. michael@0: compareCursorToItems(c, items, NUMBER_OF_CHILDREN); michael@0: c.close(); michael@0: michael@0: // Now permute the items array. michael@0: Random rand = new Random(); michael@0: for (int i = 0; i < NUMBER_OF_CHILDREN; ++i) { michael@0: final int newPosition = rand.nextInt(NUMBER_OF_CHILDREN); michael@0: final String switched = items[newPosition]; michael@0: items[newPosition] = items[i]; michael@0: items[i] = switched; michael@0: } michael@0: michael@0: // Impose the positions. michael@0: long updated = mProvider.update(BrowserContract.Bookmarks.POSITIONS_CONTENT_URI, null, null, items); michael@0: mAsserter.is(updated, (long) NUMBER_OF_CHILDREN, "Updated " + NUMBER_OF_CHILDREN + " positions."); michael@0: michael@0: // Verify that the database was updated. michael@0: c = getBookmarksByParent(folderId); michael@0: compareCursorToItems(c, items, NUMBER_OF_CHILDREN); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestInsertHistory extends TestCase { michael@0: private long insertWithNullCol(String colName) throws Exception { michael@0: ContentValues h = createOneHistoryEntry(); michael@0: h.putNull(colName); michael@0: long id = -1; michael@0: michael@0: try { michael@0: id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); michael@0: } catch (Exception e) {} michael@0: michael@0: return id; michael@0: } michael@0: michael@0: @Override michael@0: public void test() throws Exception { michael@0: ContentValues h = createOneHistoryEntry(); michael@0: long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); michael@0: Cursor c = getHistoryEntryById(id); michael@0: michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted history entry found"); michael@0: michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), h.getAsString(BrowserContract.History.TITLE), michael@0: "Inserted history entry has correct title"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.URL)), h.getAsString(BrowserContract.History.URL), michael@0: "Inserted history entry has correct URL"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.VISITS)), h.getAsString(BrowserContract.History.VISITS), michael@0: "Inserted history entry has correct number of visits"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.DATE_LAST_VISITED)), h.getAsString(BrowserContract.History.DATE_LAST_VISITED), michael@0: "Inserted history entry has correct last visited date"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.IS_DELETED)), String.valueOf(0), michael@0: "Inserted history entry has correct is-deleted state"); michael@0: michael@0: id = insertWithNullCol(BrowserContract.History.URL); michael@0: mAsserter.is(new Long(id), new Long(-1), michael@0: "Should not be able to insert history with null URL"); michael@0: michael@0: id = insertWithNullCol(BrowserContract.History.VISITS); michael@0: mAsserter.is(new Long(id), new Long(-1), michael@0: "Should not be able to insert history with null number of visits"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestInsertHistoryFavicons extends TestCase { michael@0: @Override michael@0: public void test() throws Exception { michael@0: ContentValues h = createOneHistoryEntry(); michael@0: michael@0: final String favicon = "FAVICON"; michael@0: final String pageUrl = h.getAsString(BrowserContract.History.URL); michael@0: michael@0: long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); michael@0: michael@0: // Insert the favicon into the favicons table michael@0: mProvider.insert(BrowserContract.Favicons.CONTENT_URI, createFaviconEntry(pageUrl, favicon)); michael@0: michael@0: Cursor c = getHistoryEntryById(id, new String[] { BrowserContract.History.FAVICON }); michael@0: michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted history entry found"); michael@0: michael@0: mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.History.FAVICON)), "UTF8"), michael@0: favicon, "Inserted history entry has corresponding favicon image"); michael@0: c.close(); michael@0: michael@0: c = getFaviconsByUrl(pageUrl); michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted favicon found"); michael@0: michael@0: mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"), michael@0: favicon, "Inserted favicon has corresponding favicon image"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestDeleteHistory extends TestCase { michael@0: private long insertOneHistoryEntry() throws Exception { michael@0: ContentValues h = createOneHistoryEntry(); michael@0: long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); michael@0: michael@0: Cursor c = getHistoryEntryById(id); michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted history entry found"); michael@0: c.close(); michael@0: michael@0: return id; michael@0: } michael@0: michael@0: @Override michael@0: public void test() throws Exception { michael@0: long id = insertOneHistoryEntry(); michael@0: michael@0: int deleted = mProvider.delete(BrowserContract.History.CONTENT_URI, michael@0: BrowserContract.History._ID + " = ?", michael@0: new String[] { String.valueOf(id) }); michael@0: michael@0: mAsserter.is((deleted == 1), true, "Inserted history entry was deleted"); michael@0: michael@0: Cursor c = getHistoryEntryById(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), id); michael@0: mAsserter.is(c.moveToFirst(), true, "Deleted history entry was only marked as deleted"); michael@0: michael@0: deleted = mProvider.delete(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"), michael@0: BrowserContract.History._ID + " = ?", michael@0: new String[] { String.valueOf(id) }); michael@0: michael@0: mAsserter.is((deleted == 1), true, "Inserted history entry was deleted"); michael@0: c.close(); michael@0: michael@0: c = getHistoryEntryById(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), id); michael@0: mAsserter.is(c.moveToFirst(), false, "Inserted history is now actually deleted"); michael@0: michael@0: id = insertOneHistoryEntry(); michael@0: michael@0: deleted = mProvider.delete(ContentUris.withAppendedId(BrowserContract.History.CONTENT_URI, id), null, null); michael@0: mAsserter.is((deleted == 1), true, michael@0: "Inserted history entry was deleted using URI with id"); michael@0: c.close(); michael@0: michael@0: c = getHistoryEntryById(id); michael@0: mAsserter.is(c.moveToFirst(), false, michael@0: "Inserted history entry can't be found after deletion using URI with ID"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestDeleteHistoryFavicons extends TestCase { michael@0: @Override michael@0: public void test() throws Exception { michael@0: ContentValues h = createOneHistoryEntry(); michael@0: michael@0: long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); michael@0: final String pageUrl = h.getAsString(BrowserContract.History.URL); michael@0: michael@0: // Insert the favicon into the favicons table michael@0: mProvider.insert(BrowserContract.Favicons.CONTENT_URI, createFaviconEntry(pageUrl, "FAVICON")); michael@0: michael@0: Cursor c = getFaviconsByUrl(pageUrl); michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted favicon found"); michael@0: michael@0: mProvider.delete(ContentUris.withAppendedId(BrowserContract.History.CONTENT_URI, id), null, null); michael@0: c.close(); michael@0: michael@0: c = getFaviconsByUrl(pageUrl); michael@0: mAsserter.is(c.moveToFirst(), false, "Favicon is deleted with last reference to it"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestUpdateHistory extends TestCase { michael@0: private int updateWithNullCol(long id, String colName) throws Exception { michael@0: ContentValues u = new ContentValues(); michael@0: u.putNull(colName); michael@0: michael@0: int updated = 0; michael@0: michael@0: try { michael@0: updated = mProvider.update(BrowserContract.History.CONTENT_URI, u, michael@0: BrowserContract.History._ID + " = ?", michael@0: new String[] { String.valueOf(id) }); michael@0: } catch (Exception e) {} michael@0: michael@0: return updated; michael@0: } michael@0: michael@0: @Override michael@0: public void test() throws Exception { michael@0: ContentValues h = createOneHistoryEntry(); michael@0: long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); michael@0: michael@0: Cursor c = getHistoryEntryById(id); michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted history entry found"); michael@0: michael@0: long dateCreated = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED)); michael@0: long dateModified = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED)); michael@0: michael@0: ContentValues u = new ContentValues(); michael@0: u.put(BrowserContract.History.VISITS, h.getAsInteger(BrowserContract.History.VISITS) + 1); michael@0: u.put(BrowserContract.History.DATE_LAST_VISITED, System.currentTimeMillis()); michael@0: u.put(BrowserContract.History.TITLE, h.getAsString(BrowserContract.History.TITLE) + "CHANGED"); michael@0: u.put(BrowserContract.History.URL, h.getAsString(BrowserContract.History.URL) + "/more/stuff"); michael@0: michael@0: int updated = mProvider.update(BrowserContract.History.CONTENT_URI, u, michael@0: BrowserContract.History._ID + " = ?", michael@0: new String[] { String.valueOf(id) }); michael@0: michael@0: mAsserter.is((updated == 1), true, "Inserted history entry was updated"); michael@0: c.close(); michael@0: michael@0: c = getHistoryEntryById(id); michael@0: mAsserter.is(c.moveToFirst(), true, "Updated history entry found"); michael@0: michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), u.getAsString(BrowserContract.History.TITLE), michael@0: "Updated history entry has correct title"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.URL)), u.getAsString(BrowserContract.History.URL), michael@0: "Updated history entry has correct URL"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.VISITS)), u.getAsString(BrowserContract.History.VISITS), michael@0: "Updated history entry has correct number of visits"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.DATE_LAST_VISITED)), u.getAsString(BrowserContract.History.DATE_LAST_VISITED), michael@0: "Updated history entry has correct last visited date"); michael@0: michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED))), michael@0: new Long(dateCreated), michael@0: "Updated history entry has same creation date"); michael@0: michael@0: mAsserter.isnot(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED))), michael@0: new Long(dateModified), michael@0: "Updated history entry has new modification date"); michael@0: michael@0: updated = updateWithNullCol(id, BrowserContract.History.URL); michael@0: mAsserter.is((updated > 0), false, michael@0: "Should not be able to update history with null URL"); michael@0: michael@0: updated = updateWithNullCol(id, BrowserContract.History.VISITS); michael@0: mAsserter.is((updated > 0), false, michael@0: "Should not be able to update history with null number of visits"); michael@0: michael@0: u = new ContentValues(); michael@0: u.put(BrowserContract.History.URL, "http://examples2.com"); michael@0: michael@0: updated = mProvider.update(ContentUris.withAppendedId(BrowserContract.History.CONTENT_URI, id), u, null, null); michael@0: c.close(); michael@0: michael@0: c = getHistoryEntryById(id); michael@0: mAsserter.is(c.moveToFirst(), true, "Updated history entry found"); michael@0: michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.URL)), u.getAsString(BrowserContract.History.URL), michael@0: "Updated history entry has correct URL using URI with id"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestUpdateHistoryFavicons extends TestCase { michael@0: @Override michael@0: public void test() throws Exception { michael@0: ContentValues h = createOneHistoryEntry(); michael@0: michael@0: final String favicon = "FAVICON"; michael@0: final String newFavicon = "NEW_FAVICON"; michael@0: final String pageUrl = h.getAsString(BrowserContract.History.URL); michael@0: michael@0: mProvider.insert(BrowserContract.History.CONTENT_URI, h); michael@0: michael@0: // Insert the favicon into the favicons table michael@0: mProvider.insert(BrowserContract.Favicons.CONTENT_URI, createFaviconEntry(pageUrl, favicon)); michael@0: michael@0: Cursor c = getFaviconsByUrl(pageUrl); michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted favicon found"); michael@0: michael@0: mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"), michael@0: favicon, "Inserted favicon has corresponding favicon image"); michael@0: michael@0: ContentValues u = createFaviconEntry(pageUrl, newFavicon); michael@0: michael@0: mProvider.update(BrowserContract.Favicons.CONTENT_URI, u, null, null); michael@0: c.close(); michael@0: michael@0: c = getFaviconsByUrl(pageUrl); michael@0: mAsserter.is(c.moveToFirst(), true, "Updated favicon found"); michael@0: michael@0: mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"), michael@0: newFavicon, "Updated favicon has corresponding favicon image"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestUpdateOrInsertHistory extends TestCase { michael@0: private final String TEST_URL_1 = "http://example.com"; michael@0: private final String TEST_URL_2 = "http://example.org"; michael@0: private final String TEST_TITLE = "Example"; michael@0: michael@0: private long getHistoryEntryIdByUrl(String url) { michael@0: Cursor c = mProvider.query(BrowserContract.History.CONTENT_URI, michael@0: new String[] { BrowserContract.History._ID }, michael@0: BrowserContract.History.URL + " = ?", michael@0: new String[] { url }, michael@0: null); michael@0: c.moveToFirst(); michael@0: long id = c.getLong(0); michael@0: c.close(); michael@0: michael@0: return id; michael@0: } michael@0: michael@0: @Override michael@0: public void test() throws Exception { michael@0: Uri updateHistoryUri = BrowserContract.History.CONTENT_URI.buildUpon(). michael@0: appendQueryParameter("increment_visits", "true").build(); michael@0: Uri updateOrInsertHistoryUri = BrowserContract.History.CONTENT_URI.buildUpon(). michael@0: appendQueryParameter("insert_if_needed", "true"). michael@0: appendQueryParameter("increment_visits", "true").build(); michael@0: michael@0: // Update a non-existent history entry, without specifying visits or title michael@0: ContentValues values = new ContentValues(); michael@0: values.put(BrowserContract.History.URL, TEST_URL_1); michael@0: michael@0: int updated = mProvider.update(updateHistoryUri, values, michael@0: BrowserContract.History.URL + " = ?", michael@0: new String[] { TEST_URL_1 }); michael@0: mAsserter.is((updated == 0), true, "History entry was not updated"); michael@0: Cursor c = mProvider.query(BrowserContract.History.CONTENT_URI, null, null, null, null); michael@0: mAsserter.is(c.moveToFirst(), false, "History entry was not inserted"); michael@0: c.close(); michael@0: michael@0: // Now let's try with update-or-insert. michael@0: updated = mProvider.update(updateOrInsertHistoryUri, values, michael@0: BrowserContract.History.URL + " = ?", michael@0: new String[] { TEST_URL_1 }); michael@0: mAsserter.is((updated == 1), true, "History entry was inserted"); michael@0: michael@0: long id = getHistoryEntryIdByUrl(TEST_URL_1); michael@0: c = getHistoryEntryById(id); michael@0: mAsserter.is(c.moveToFirst(), true, "History entry was inserted"); michael@0: michael@0: long dateCreated = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED)); michael@0: long dateModified = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED)); michael@0: michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.VISITS))), new Long(1), michael@0: "Inserted history entry has correct default number of visits"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), TEST_URL_1, michael@0: "Inserted history entry has correct default title"); michael@0: michael@0: // Update the history entry, without specifying an additional visit count michael@0: values = new ContentValues(); michael@0: values.put(BrowserContract.History.DATE_LAST_VISITED, System.currentTimeMillis()); michael@0: values.put(BrowserContract.History.TITLE, TEST_TITLE); michael@0: michael@0: updated = mProvider.update(updateOrInsertHistoryUri, values, michael@0: BrowserContract.History._ID + " = ?", michael@0: new String[] { String.valueOf(id) }); michael@0: mAsserter.is((updated == 1), true, "Inserted history entry was updated"); michael@0: c.close(); michael@0: michael@0: c = getHistoryEntryById(id); michael@0: mAsserter.is(c.moveToFirst(), true, "Updated history entry found"); michael@0: michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), TEST_TITLE, michael@0: "Updated history entry has correct title"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.VISITS))), new Long(2), michael@0: "Updated history entry has correct number of visits"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED))), new Long(dateCreated), michael@0: "Updated history entry has same creation date"); michael@0: mAsserter.isnot(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED))), new Long(dateModified), michael@0: "Updated history entry has new modification date"); michael@0: michael@0: // Create a new history entry, specifying visits and history michael@0: values = new ContentValues(); michael@0: values.put(BrowserContract.History.URL, TEST_URL_2); michael@0: values.put(BrowserContract.History.TITLE, TEST_TITLE); michael@0: values.put(BrowserContract.History.VISITS, 10); michael@0: michael@0: updated = mProvider.update(updateOrInsertHistoryUri, values, michael@0: BrowserContract.History.URL + " = ?", michael@0: new String[] { values.getAsString(BrowserContract.History.URL) }); michael@0: mAsserter.is((updated == 1), true, "History entry was inserted"); michael@0: michael@0: id = getHistoryEntryIdByUrl(TEST_URL_2); michael@0: c.close(); michael@0: michael@0: c = getHistoryEntryById(id); michael@0: mAsserter.is(c.moveToFirst(), true, "History entry was inserted"); michael@0: michael@0: dateCreated = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED)); michael@0: dateModified = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED)); michael@0: michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.VISITS))), new Long(10), michael@0: "Inserted history entry has correct specified number of visits"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), TEST_TITLE, michael@0: "Inserted history entry has correct specified title"); michael@0: michael@0: // Update the history entry, specifying additional visit count michael@0: values = new ContentValues(); michael@0: values.put(BrowserContract.History.VISITS, 10); michael@0: michael@0: updated = mProvider.update(updateOrInsertHistoryUri, values, michael@0: BrowserContract.History._ID + " = ?", michael@0: new String[] { String.valueOf(id) }); michael@0: mAsserter.is((updated == 1), true, "Inserted history entry was updated"); michael@0: c.close(); michael@0: michael@0: c = getHistoryEntryById(id); michael@0: mAsserter.is(c.moveToFirst(), true, "Updated history entry found"); michael@0: michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), TEST_TITLE, michael@0: "Updated history entry has correct unchanged title"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.URL)), TEST_URL_2, michael@0: "Updated history entry has correct unchanged URL"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.VISITS))), new Long(20), michael@0: "Updated history entry has correct number of visits"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED))), new Long(dateCreated), michael@0: "Updated history entry has same creation date"); michael@0: mAsserter.isnot(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED))), new Long(dateModified), michael@0: "Updated history entry has new modification date"); michael@0: c.close(); michael@0: michael@0: } michael@0: } michael@0: michael@0: private class TestInsertHistoryThumbnails extends TestCase { michael@0: @Override michael@0: public void test() throws Exception { michael@0: ContentValues h = createOneHistoryEntry(); michael@0: michael@0: final String thumbnail = "THUMBNAIL"; michael@0: final String pageUrl = h.getAsString(BrowserContract.History.URL); michael@0: michael@0: long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); michael@0: michael@0: // Insert the thumbnail into the thumbnails table michael@0: mProvider.insert(BrowserContract.Thumbnails.CONTENT_URI, createThumbnailEntry(pageUrl, thumbnail)); michael@0: michael@0: Cursor c = getThumbnailByUrl(pageUrl); michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted thumbnail found"); michael@0: michael@0: mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Thumbnails.DATA)), "UTF8"), michael@0: thumbnail, "Inserted thumbnail has corresponding thumbnail image"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestUpdateHistoryThumbnails extends TestCase { michael@0: @Override michael@0: public void test() throws Exception { michael@0: ContentValues h = createOneHistoryEntry(); michael@0: michael@0: final String thumbnail = "THUMBNAIL"; michael@0: final String newThumbnail = "NEW_THUMBNAIL"; michael@0: final String pageUrl = h.getAsString(BrowserContract.History.URL); michael@0: michael@0: mProvider.insert(BrowserContract.History.CONTENT_URI, h); michael@0: michael@0: // Insert the thumbnail into the thumbnails table michael@0: mProvider.insert(BrowserContract.Thumbnails.CONTENT_URI, createThumbnailEntry(pageUrl, thumbnail)); michael@0: michael@0: Cursor c = getThumbnailByUrl(pageUrl); michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted thumbnail found"); michael@0: michael@0: mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Thumbnails.DATA)), "UTF8"), michael@0: thumbnail, "Inserted thumbnail has corresponding thumbnail image"); michael@0: michael@0: ContentValues u = createThumbnailEntry(pageUrl, newThumbnail); michael@0: michael@0: mProvider.update(BrowserContract.Thumbnails.CONTENT_URI, u, null, null); michael@0: c.close(); michael@0: michael@0: c = getThumbnailByUrl(pageUrl); michael@0: mAsserter.is(c.moveToFirst(), true, "Updated thumbnail found"); michael@0: michael@0: mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Thumbnails.DATA)), "UTF8"), michael@0: newThumbnail, "Updated thumbnail has corresponding thumbnail image"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestDeleteHistoryThumbnails extends TestCase { michael@0: @Override michael@0: public void test() throws Exception { michael@0: ContentValues h = createOneHistoryEntry(); michael@0: michael@0: long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); michael@0: final String pageUrl = h.getAsString(BrowserContract.History.URL); michael@0: michael@0: // Insert the thumbnail into the thumbnails table michael@0: mProvider.insert(BrowserContract.Thumbnails.CONTENT_URI, createThumbnailEntry(pageUrl, "THUMBNAIL")); michael@0: michael@0: Cursor c = getThumbnailByUrl(pageUrl); michael@0: mAsserter.is(c.moveToFirst(), true, "Inserted thumbnail found"); michael@0: michael@0: mProvider.delete(ContentUris.withAppendedId(BrowserContract.History.CONTENT_URI, id), null, null); michael@0: c.close(); michael@0: michael@0: c = getThumbnailByUrl(pageUrl); michael@0: mAsserter.is(c.moveToFirst(), false, "Thumbnail is deleted with last reference to it"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestCombinedView extends TestCase { michael@0: @Override michael@0: public void test() throws Exception { michael@0: final String TITLE_1 = "Test Page 1"; michael@0: final String TITLE_2 = "Test Page 2"; michael@0: final String TITLE_3_HISTORY = "Test Page 3 (History Entry)"; michael@0: final String TITLE_3_BOOKMARK = "Test Page 3 (Bookmark Entry)"; michael@0: final String TITLE_3_BOOKMARK2 = "Test Page 3 (Bookmark Entry 2)"; michael@0: michael@0: final String URL_1 = "http://example1.com"; michael@0: final String URL_2 = "http://example2.com"; michael@0: final String URL_3 = "http://example3.com"; michael@0: michael@0: final int VISITS = 10; michael@0: final long LAST_VISITED = System.currentTimeMillis(); michael@0: michael@0: // Create a basic history entry michael@0: ContentValues basicHistory = createHistoryEntry(TITLE_1, URL_1, VISITS, LAST_VISITED); michael@0: long basicHistoryId = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, basicHistory)); michael@0: michael@0: // Create a basic bookmark entry michael@0: ContentValues basicBookmark = createBookmark(TITLE_2, URL_2, mMobileFolderId, michael@0: BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); michael@0: long basicBookmarkId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, basicBookmark)); michael@0: michael@0: // Create a history entry and bookmark entry with the same URL to michael@0: // represent a visited bookmark michael@0: ContentValues combinedHistory = createHistoryEntry(TITLE_3_HISTORY, URL_3, VISITS, LAST_VISITED); michael@0: long combinedHistoryId = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, combinedHistory)); michael@0: michael@0: michael@0: ContentValues combinedBookmark = createBookmark(TITLE_3_BOOKMARK, URL_3, mMobileFolderId, michael@0: BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); michael@0: long combinedBookmarkId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, combinedBookmark)); michael@0: michael@0: ContentValues combinedBookmark2 = createBookmark(TITLE_3_BOOKMARK2, URL_3, mMobileFolderId, michael@0: BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); michael@0: long combinedBookmarkId2 = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, combinedBookmark2)); michael@0: michael@0: // Create a bookmark folder to make sure it _doesn't_ show up in the results michael@0: ContentValues folderBookmark = createBookmark("", "", mMobileFolderId, michael@0: BrowserContract.Bookmarks.TYPE_FOLDER, 0, "tags", "description", "keyword"); michael@0: mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, folderBookmark); michael@0: michael@0: // Sort entries by url so we can check them individually michael@0: Cursor c = mProvider.query(BrowserContract.Combined.CONTENT_URI, null, "", null, BrowserContract.Combined.URL); michael@0: michael@0: mAsserter.is(c.getCount(), 3, "3 combined entries found"); michael@0: michael@0: // First combined entry is basic history entry michael@0: mAsserter.is(c.moveToFirst(), true, "Found basic history entry"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined._ID))), new Long(0), michael@0: "Combined _id column should always be 0"); michael@0: // TODO: Should we change BrowserProvider to make this return -1, not 0? michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID))), new Long(0), michael@0: "Bookmark id should be 0 for basic history entry"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.HISTORY_ID))), new Long(basicHistoryId), michael@0: "Basic history entry has correct history id"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.TITLE)), TITLE_1, michael@0: "Basic history entry has correct title"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.URL)), URL_1, michael@0: "Basic history entry has correct url"); michael@0: mAsserter.is(c.getInt(c.getColumnIndex(BrowserContract.Combined.VISITS)), VISITS, michael@0: "Basic history entry has correct number of visits"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.DATE_LAST_VISITED))), new Long(LAST_VISITED), michael@0: "Basic history entry has correct last visit time"); michael@0: michael@0: // Second combined entry is basic bookmark entry michael@0: mAsserter.is(c.moveToNext(), true, "Found basic bookmark entry"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined._ID))), new Long(0), michael@0: "Combined _id column should always be 0"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID))), new Long(basicBookmarkId), michael@0: "Basic bookmark entry has correct bookmark id"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.HISTORY_ID))), new Long(-1), michael@0: "History id should be -1 for basic bookmark entry"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.TITLE)), TITLE_2, michael@0: "Basic bookmark entry has correct title"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.URL)), URL_2, michael@0: "Basic bookmark entry has correct url"); michael@0: mAsserter.is(c.getInt(c.getColumnIndex(BrowserContract.Combined.VISITS)), -1, michael@0: "Visits should be -1 for basic bookmark entry"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.DATE_LAST_VISITED))), new Long(-1), michael@0: "Basic entry has correct last visit time"); michael@0: michael@0: // Third combined entry is a combined history/bookmark entry michael@0: mAsserter.is(c.moveToNext(), true, "Found third combined entry"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined._ID))), new Long(0), michael@0: "Combined _id column should always be 0"); michael@0: // The bookmark data (bookmark_id and title) associated with the combined entry is non-deterministic, michael@0: // it might end up with data coming from any of the matching bookmark entries. michael@0: mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID)) == combinedBookmarkId || michael@0: c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID)) == combinedBookmarkId2, true, michael@0: "Combined entry has correct bookmark id"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.TITLE)).equals(TITLE_3_BOOKMARK) || michael@0: c.getString(c.getColumnIndex(BrowserContract.Combined.TITLE)).equals(TITLE_3_BOOKMARK2), true, michael@0: "Combined entry has title corresponding to bookmark entry"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.HISTORY_ID))), new Long(combinedHistoryId), michael@0: "Combined entry has correct history id"); michael@0: mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.URL)), URL_3, michael@0: "Combined entry has correct url"); michael@0: mAsserter.is(c.getInt(c.getColumnIndex(BrowserContract.Combined.VISITS)), VISITS, michael@0: "Combined entry has correct number of visits"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.DATE_LAST_VISITED))), new Long(LAST_VISITED), michael@0: "Combined entry has correct last visit time"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestCombinedViewDisplay extends TestCase { michael@0: @Override michael@0: public void test() throws Exception { michael@0: final String TITLE_1 = "Test Page 1"; michael@0: final String TITLE_2 = "Test Page 2"; michael@0: final String TITLE_3_HISTORY = "Test Page 3 (History Entry)"; michael@0: final String TITLE_3_BOOKMARK = "Test Page 3 (Bookmark Entry)"; michael@0: final String TITLE_4 = "Test Page 4"; michael@0: michael@0: final String URL_1 = "http://example.com"; michael@0: final String URL_2 = "http://example.org"; michael@0: final String URL_3 = "http://examples2.com"; michael@0: final String URL_4 = "http://readinglist.com"; michael@0: michael@0: final int VISITS = 10; michael@0: final long LAST_VISITED = System.currentTimeMillis(); michael@0: michael@0: // Create a basic history entry michael@0: ContentValues basicHistory = createHistoryEntry(TITLE_1, URL_1, VISITS, LAST_VISITED); michael@0: ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, basicHistory)); michael@0: michael@0: // Create a basic bookmark entry michael@0: ContentValues basicBookmark = createBookmark(TITLE_2, URL_2, mMobileFolderId, michael@0: BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); michael@0: mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, basicBookmark); michael@0: michael@0: // Create a history entry and bookmark entry with the same URL to michael@0: // represent a visited bookmark michael@0: ContentValues combinedHistory = createHistoryEntry(TITLE_3_HISTORY, URL_3, VISITS, LAST_VISITED); michael@0: mProvider.insert(BrowserContract.History.CONTENT_URI, combinedHistory); michael@0: michael@0: ContentValues combinedBookmark = createBookmark(TITLE_3_BOOKMARK, URL_3, mMobileFolderId, michael@0: BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); michael@0: mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, combinedBookmark); michael@0: michael@0: // Create a reading list entries michael@0: int readingListId = BrowserContract.Bookmarks.FIXED_READING_LIST_ID; michael@0: ContentValues readingListItem = createBookmark(TITLE_3_BOOKMARK, URL_3, readingListId, michael@0: BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); michael@0: long readingListItemId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, readingListItem)); michael@0: michael@0: ContentValues readingListItem2 = createBookmark(TITLE_4, URL_4, readingListId, michael@0: BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); michael@0: long readingListItemId2 = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, readingListItem2)); michael@0: michael@0: Cursor c = mProvider.query(BrowserContract.Combined.CONTENT_URI, null, "", null, null); michael@0: mAsserter.is(c.getCount(), 4, "4 combined entries found"); michael@0: michael@0: while (c.moveToNext()) { michael@0: long id = c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID)); michael@0: michael@0: int display = c.getInt(c.getColumnIndex(BrowserContract.Combined.DISPLAY)); michael@0: int expectedDisplay = (id == readingListItemId || id == readingListItemId2 ? BrowserContract.Combined.DISPLAY_READER : BrowserContract.Combined.DISPLAY_NORMAL); michael@0: michael@0: mAsserter.is(new Integer(display), new Integer(expectedDisplay), michael@0: "Combined display column should always be DISPLAY_READER for the reading list item"); michael@0: } michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestCombinedViewWithDeletedBookmark extends TestCase { michael@0: @Override michael@0: public void test() throws Exception { michael@0: final String TITLE = "Test Page 1"; michael@0: final String URL = "http://example.com"; michael@0: final int VISITS = 10; michael@0: final long LAST_VISITED = System.currentTimeMillis(); michael@0: michael@0: // Create a combined history entry michael@0: ContentValues combinedHistory = createHistoryEntry(TITLE, URL, VISITS, LAST_VISITED); michael@0: mProvider.insert(BrowserContract.History.CONTENT_URI, combinedHistory); michael@0: michael@0: // Create a combined bookmark entry michael@0: ContentValues combinedBookmark = createBookmark(TITLE, URL, mMobileFolderId, michael@0: BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); michael@0: long combinedBookmarkId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, combinedBookmark)); michael@0: michael@0: Cursor c = mProvider.query(BrowserContract.Combined.CONTENT_URI, null, "", null, null); michael@0: mAsserter.is(c.getCount(), 1, "1 combined entry found"); michael@0: michael@0: mAsserter.is(c.moveToFirst(), true, "Found combined entry with bookmark id"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID))), new Long(combinedBookmarkId), michael@0: "Bookmark id should be set correctly on combined entry"); michael@0: michael@0: int deleted = mProvider.delete(BrowserContract.Bookmarks.CONTENT_URI, michael@0: BrowserContract.Bookmarks._ID + " = ?", michael@0: new String[] { String.valueOf(combinedBookmarkId) }); michael@0: michael@0: mAsserter.is((deleted == 1), true, "Inserted combined bookmark was deleted"); michael@0: c.close(); michael@0: michael@0: c = mProvider.query(BrowserContract.Combined.CONTENT_URI, null, "", null, null); michael@0: mAsserter.is(c.getCount(), 1, "1 combined entry found"); michael@0: michael@0: mAsserter.is(c.moveToFirst(), true, "Found combined entry without bookmark id"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID))), new Long(0), michael@0: "Bookmark id should not be set to removed bookmark id"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestCombinedViewWithDeletedReadingListItem extends TestCase { michael@0: @Override michael@0: public void test() throws Exception { michael@0: final String TITLE = "Test Page 1"; michael@0: final String URL = "http://example.com"; michael@0: final int VISITS = 10; michael@0: final long LAST_VISITED = System.currentTimeMillis(); michael@0: michael@0: // Create a combined history entry michael@0: ContentValues combinedHistory = createHistoryEntry(TITLE, URL, VISITS, LAST_VISITED); michael@0: mProvider.insert(BrowserContract.History.CONTENT_URI, combinedHistory); michael@0: michael@0: // Create a combined bookmark entry michael@0: int readingListId = BrowserContract.Bookmarks.FIXED_READING_LIST_ID; michael@0: ContentValues combinedReadingListItem = createBookmark(TITLE, URL, readingListId, michael@0: BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); michael@0: long combinedReadingListItemId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, combinedReadingListItem)); michael@0: michael@0: Cursor c = mProvider.query(BrowserContract.Combined.CONTENT_URI, null, "", null, null); michael@0: mAsserter.is(c.getCount(), 1, "1 combined entry found"); michael@0: michael@0: mAsserter.is(c.moveToFirst(), true, "Found combined entry with bookmark id"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID))), new Long(combinedReadingListItemId), michael@0: "Bookmark id should be set correctly on combined entry"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.DISPLAY))), new Long(BrowserContract.Combined.DISPLAY_READER), michael@0: "Combined entry should have reader display type"); michael@0: michael@0: int deleted = mProvider.delete(BrowserContract.Bookmarks.CONTENT_URI, michael@0: BrowserContract.Bookmarks._ID + " = ?", michael@0: new String[] { String.valueOf(combinedReadingListItemId) }); michael@0: michael@0: mAsserter.is((deleted == 1), true, "Inserted combined reading list item was deleted"); michael@0: c.close(); michael@0: michael@0: c = mProvider.query(BrowserContract.Combined.CONTENT_URI, null, "", null, null); michael@0: mAsserter.is(c.getCount(), 1, "1 combined entry found"); michael@0: michael@0: mAsserter.is(c.moveToFirst(), true, "Found combined entry without bookmark id"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID))), new Long(0), michael@0: "Bookmark id should not be set to removed bookmark id"); michael@0: mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.DISPLAY))), new Long(BrowserContract.Combined.DISPLAY_NORMAL), michael@0: "Combined entry should have reader display type"); michael@0: c.close(); michael@0: } michael@0: } michael@0: michael@0: private class TestExpireHistory extends TestCase { michael@0: private void createFakeHistory(long timeShift, int count) { michael@0: // Insert a bunch of very new entries michael@0: ContentValues[] allVals = new ContentValues[count]; michael@0: long time = System.currentTimeMillis() - timeShift; michael@0: for (int i = 0; i < count; i++) { michael@0: allVals[i] = new ContentValues(); michael@0: allVals[i].put(BrowserContract.History.TITLE, "Test " + i); michael@0: allVals[i].put(BrowserContract.History.URL, "http://www.test.org/" + i); michael@0: allVals[i].put(BrowserContract.History.VISITS, i); michael@0: allVals[i].put(BrowserContract.History.DATE_LAST_VISITED, time); michael@0: } michael@0: michael@0: int inserts = mProvider.bulkInsert(BrowserContract.History.CONTENT_URI, allVals); michael@0: mAsserter.is(inserts, count, "Expected number of inserts matches"); michael@0: michael@0: // inserting a new entry sets the date created and modified automatically michael@0: // reset all of them michael@0: for (int i = 0; i < count; i++) { michael@0: ContentValues cv = new ContentValues(); michael@0: cv.put(BrowserContract.History.DATE_CREATED, time); michael@0: cv.put(BrowserContract.History.DATE_MODIFIED, time); michael@0: mProvider.update(BrowserContract.History.CONTENT_URI, cv, BrowserContract.History.URL + " = ?", michael@0: new String[] { "http://www.test.org/" + i }); michael@0: } michael@0: michael@0: Cursor c = mProvider.query(BrowserContract.History.CONTENT_URI, null, "", null, null); michael@0: michael@0: assertCountIsAndClose(c, count, count + " history entries found"); michael@0: michael@0: // add thumbnails for each entry michael@0: allVals = new ContentValues[count]; michael@0: for (int i = 0; i < count; i++) { michael@0: allVals[i] = new ContentValues(); michael@0: allVals[i].put(BrowserContract.Thumbnails.DATA, i); michael@0: allVals[i].put(BrowserContract.Thumbnails.URL, "http://www.test.org/" + i); michael@0: } michael@0: michael@0: inserts = mProvider.bulkInsert(BrowserContract.Thumbnails.CONTENT_URI, allVals); michael@0: mAsserter.is(inserts, count, "Expected number of inserts matches"); michael@0: michael@0: c = mProvider.query(BrowserContract.Thumbnails.CONTENT_URI, null, null, null, null); michael@0: assertCountIsAndClose(c, count, count + " thumbnails entries found"); michael@0: } michael@0: michael@0: @Override michael@0: public void test() throws Exception { michael@0: final int count = 3000; michael@0: final int thumbCount = 15; michael@0: michael@0: // insert a bunch of new entries michael@0: createFakeHistory(0, count); michael@0: michael@0: // expiring with a normal priority should not delete new entries michael@0: Uri url = appendUriParam(BrowserContract.History.CONTENT_OLD_URI, BrowserContract.PARAM_EXPIRE_PRIORITY, "NORMAL"); michael@0: mProvider.delete(url, null, null); michael@0: Cursor c = mProvider.query(BrowserContract.History.CONTENT_URI, null, "", null, null); michael@0: assertCountIsAndClose(c, count, count + " history entries found"); michael@0: michael@0: // expiring with a normal priority should delete all but 10 thumbnails michael@0: c = mProvider.query(BrowserContract.Thumbnails.CONTENT_URI, null, null, null, null); michael@0: assertCountIsAndClose(c, thumbCount, thumbCount + " thumbnails found"); michael@0: michael@0: ensureEmptyDatabase(); michael@0: michael@0: // Insert a bunch of new entries. michael@0: createFakeHistory(0, count); michael@0: michael@0: // Expiring with a aggressive priority should leave 500 entries. michael@0: url = appendUriParam(BrowserContract.History.CONTENT_OLD_URI, BrowserContract.PARAM_EXPIRE_PRIORITY, "AGGRESSIVE"); michael@0: mProvider.delete(url, null, null); michael@0: michael@0: c = mProvider.query(BrowserContract.History.CONTENT_URI, null, "", null, null); michael@0: assertCountIsAndClose(c, 500, "500 history entries found"); michael@0: michael@0: // Expiring with a aggressive priority should delete all but 10 thumbnails. michael@0: c = mProvider.query(BrowserContract.Thumbnails.CONTENT_URI, null, null, null, null); michael@0: assertCountIsAndClose(c, thumbCount, thumbCount + " thumbnails found"); michael@0: michael@0: ensureEmptyDatabase(); michael@0: michael@0: // Insert a bunch of entries with an old time created/modified. michael@0: long time = 1000L * 60L * 60L * 24L * 30L * 3L; michael@0: createFakeHistory(time, count); michael@0: michael@0: // Expiring with an normal priority should remove at most 1000 entries, michael@0: // entries leaving at least 2000. michael@0: url = appendUriParam(BrowserContract.History.CONTENT_OLD_URI, BrowserContract.PARAM_EXPIRE_PRIORITY, "NORMAL"); michael@0: mProvider.delete(url, null, null); michael@0: michael@0: c = mProvider.query(BrowserContract.History.CONTENT_URI, null, "", null, null); michael@0: assertCountIsAndClose(c, 2000, "2000 history entries found"); michael@0: michael@0: // Expiring with a normal priority should delete all but 10 thumbnails. michael@0: c = mProvider.query(BrowserContract.Thumbnails.CONTENT_URI, null, null, null, null); michael@0: assertCountIsAndClose(c, thumbCount, thumbCount + " thumbnails found"); michael@0: michael@0: ensureEmptyDatabase(); michael@0: // insert a bunch of entries with an old time created/modified michael@0: time = 1000L * 60L * 60L * 24L * 30L * 3L; michael@0: createFakeHistory(time, count); michael@0: michael@0: // Expiring with an aggressive priority should remove old michael@0: // entries, leaving at least 500. michael@0: url = appendUriParam(BrowserContract.History.CONTENT_OLD_URI, BrowserContract.PARAM_EXPIRE_PRIORITY, "AGGRESSIVE"); michael@0: mProvider.delete(url, null, null); michael@0: c = mProvider.query(BrowserContract.History.CONTENT_URI, null, "", null, null); michael@0: assertCountIsAndClose(c, 500, "500 history entries found"); michael@0: michael@0: // expiring with an aggressive priority should delete all but 10 thumbnails michael@0: c = mProvider.query(BrowserContract.Thumbnails.CONTENT_URI, null, null, null, null); michael@0: assertCountIsAndClose(c, thumbCount, thumbCount + " thumbnails found"); michael@0: } michael@0: } michael@0: michael@0: /* michael@0: * Verify that insert, update, delete, and bulkInsert operations michael@0: * notify the ambient content resolver. Each operation calls the michael@0: * content resolver notifyChange method synchronously, so it is michael@0: * okay to test sequentially. michael@0: */ michael@0: private class TestBrowserProviderNotifications extends TestCase { michael@0: public static final String LOGTAG = "TestBPNotifications"; michael@0: michael@0: protected void ensureOnlyChangeNotifiedStartsWith(Uri expectedUri, String operation) { michael@0: if (expectedUri == null) { michael@0: throw new IllegalArgumentException("expectedUri must not be null"); michael@0: } michael@0: michael@0: if (mResolver.notifyChangeList.size() != 1) { michael@0: // Log to help post-mortem debugging michael@0: Log.w(LOGTAG, "after operation, notifyChangeList = " + mResolver.notifyChangeList); michael@0: } michael@0: michael@0: mAsserter.is(Long.valueOf(mResolver.notifyChangeList.size()), michael@0: Long.valueOf(1), michael@0: "Content observer was notified exactly once by " + operation); michael@0: michael@0: Uri uri = mResolver.notifyChangeList.poll(); michael@0: michael@0: mAsserter.isnot(uri, michael@0: null, michael@0: "Notification from " + operation + " was valid"); michael@0: michael@0: mAsserter.ok(uri.toString().startsWith(expectedUri.toString()), michael@0: "Content observer was notified exactly once by " + operation, michael@0: uri.toString() + " starts with expected prefix " + expectedUri); michael@0: } michael@0: michael@0: @Override michael@0: public void test() throws Exception { michael@0: // Insert michael@0: final ContentValues h = createOneHistoryEntry(); michael@0: michael@0: mResolver.notifyChangeList.clear(); michael@0: long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); michael@0: michael@0: mAsserter.isnot(Long.valueOf(id), michael@0: Long.valueOf(-1), michael@0: "Inserted item has valid id"); michael@0: michael@0: ensureOnlyChangeNotifiedStartsWith(BrowserContract.History.CONTENT_URI, "insert"); michael@0: michael@0: // Update michael@0: mResolver.notifyChangeList.clear(); michael@0: h.put(BrowserContract.History.TITLE, "http://newexample.com"); michael@0: michael@0: long numUpdated = mProvider.update(BrowserContract.History.CONTENT_URI, h, michael@0: BrowserContract.History._ID + " = ?", michael@0: new String[] { String.valueOf(id) }); michael@0: michael@0: mAsserter.is(Long.valueOf(numUpdated), michael@0: Long.valueOf(1), michael@0: "Correct number of items are updated"); michael@0: michael@0: ensureOnlyChangeNotifiedStartsWith(BrowserContract.History.CONTENT_URI, "update"); michael@0: michael@0: // Delete michael@0: mResolver.notifyChangeList.clear(); michael@0: long numDeleted = mProvider.delete(BrowserContract.History.CONTENT_URI, null, null); michael@0: michael@0: mAsserter.is(Long.valueOf(numDeleted), michael@0: Long.valueOf(1), michael@0: "Correct number of items are deleted"); michael@0: michael@0: ensureOnlyChangeNotifiedStartsWith(BrowserContract.History.CONTENT_URI, "delete"); michael@0: michael@0: // Bulk insert michael@0: final ContentValues[] hs = new ContentValues[] { createOneHistoryEntry() }; michael@0: michael@0: mResolver.notifyChangeList.clear(); michael@0: long numBulkInserted = mProvider.bulkInsert(BrowserContract.History.CONTENT_URI, hs); michael@0: michael@0: mAsserter.is(Long.valueOf(numBulkInserted), michael@0: Long.valueOf(1), michael@0: "Correct number of items are bulkInserted"); michael@0: michael@0: ensureOnlyChangeNotifiedStartsWith(BrowserContract.History.CONTENT_URI, "bulkInsert"); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Assert that the provided cursor has the expected number of rows, michael@0: * closing the cursor afterwards. michael@0: */ michael@0: private void assertCountIsAndClose(Cursor c, int expectedCount, String message) { michael@0: try { michael@0: mAsserter.is(c.getCount(), expectedCount, message); michael@0: } finally { michael@0: c.close(); michael@0: } michael@0: } michael@0: }