mobile/android/base/tests/testBrowserProvider.java

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 package org.mozilla.gecko.tests;
     3 import java.util.ArrayList;
     4 import java.util.Random;
     6 import org.mozilla.gecko.db.BrowserContract;
     8 import android.content.ContentProviderOperation;
     9 import android.content.ContentProviderResult;
    10 import android.content.ContentUris;
    11 import android.content.ContentValues;
    12 import android.content.OperationApplicationException;
    13 import android.database.Cursor;
    14 import android.net.Uri;
    15 import android.os.Build;
    16 import android.util.Log;
    18 /*
    19  * This test is meant to exercise all operations exposed by Fennec's
    20  * history and bookmarks content provider. It does so in an isolated
    21  * environment (see ContentProviderTest) without affecting any UI-related
    22  * code.
    23  */
    24 public class testBrowserProvider extends ContentProviderTest {
    25     private long mMobileFolderId;
    27     private void loadMobileFolderId() throws Exception {
    28         Cursor c = null;
    29         try {
    30             c = getBookmarkByGuid(BrowserContract.Bookmarks.MOBILE_FOLDER_GUID);
    31             mAsserter.is(c.moveToFirst(), true, "Mobile bookmarks folder is present");
    33             mMobileFolderId = c.getLong(c.getColumnIndex(BrowserContract.Bookmarks._ID));
    34         } finally {
    35             if (c != null) {
    36                 c.close();
    37             }
    38         }
    39     }
    41     private void ensureEmptyDatabase() throws Exception {
    42         Cursor c = null;
    44         String guid = BrowserContract.Bookmarks.GUID;
    46         mProvider.delete(appendUriParam(BrowserContract.Bookmarks.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"),
    47                          guid + " != ? AND " +
    48                          guid + " != ? AND " +
    49                          guid + " != ? AND " +
    50                          guid + " != ? AND " +
    51                          guid + " != ? AND " +
    52                          guid + " != ? AND " +
    53                          guid + " != ?",
    54                          new String[] { BrowserContract.Bookmarks.PLACES_FOLDER_GUID,
    55                                         BrowserContract.Bookmarks.MOBILE_FOLDER_GUID,
    56                                         BrowserContract.Bookmarks.MENU_FOLDER_GUID,
    57                                         BrowserContract.Bookmarks.TAGS_FOLDER_GUID,
    58                                         BrowserContract.Bookmarks.TOOLBAR_FOLDER_GUID,
    59                                         BrowserContract.Bookmarks.UNFILED_FOLDER_GUID,
    60                                         BrowserContract.Bookmarks.READING_LIST_FOLDER_GUID });
    62         c = mProvider.query(appendUriParam(BrowserContract.Bookmarks.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), null, null, null, null);
    63         assertCountIsAndClose(c, 7, "All non-special bookmarks and folders were deleted");
    65         mProvider.delete(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"), null, null);
    66         c = mProvider.query(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), null, null, null, null);
    67         assertCountIsAndClose(c, 0, "All history entries were deleted");
    69         /**
    70          * There's no reason why the following two parts should fail.
    71          * But sometimes they do, and I'm not going to spend the time
    72          * to figure out why in an unrelated bug.
    73          */
    75         mProvider.delete(appendUriParam(BrowserContract.Favicons.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"), null, null);
    76         c = mProvider.query(appendUriParam(BrowserContract.Favicons.CONTENT_URI,
    77                                            BrowserContract.PARAM_SHOW_DELETED, "1"),
    78                                            null, null, null, null);
    80         if (c.getCount() > 0) {
    81           mAsserter.dumpLog("Unexpected favicons in ensureEmptyDatabase.");
    82         }
    83         c.close();
    85         mAsserter.dumpLog("ensureEmptyDatabase: Favicon deletion completed."); // Bug 968951 debug.
    86         // assertCountIsAndClose(c, 0, "All favicons were deleted");
    88         mProvider.delete(appendUriParam(BrowserContract.Thumbnails.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"), null, null);
    89         c = mProvider.query(appendUriParam(BrowserContract.Thumbnails.CONTENT_URI,
    90                                            BrowserContract.PARAM_SHOW_DELETED, "1"),
    91                                            null, null, null, null);
    93         if (c.getCount() > 0) {
    94           mAsserter.dumpLog("Unexpected thumbnails in ensureEmptyDatabase.");
    95         }
    96         c.close();
    98         mAsserter.dumpLog("ensureEmptyDatabase: Thumbnail deletion completed."); // Bug 968951 debug.
    99         // assertCountIsAndClose(c, 0, "All thumbnails were deleted");
   100     }
   102     private ContentValues createBookmark(String title, String url, long parentId,
   103             int type, int position, String tags, String description, String keyword) throws Exception {
   104         ContentValues bookmark = new ContentValues();
   106         bookmark.put(BrowserContract.Bookmarks.TITLE, title);
   107         bookmark.put(BrowserContract.Bookmarks.URL, url);
   108         bookmark.put(BrowserContract.Bookmarks.PARENT, parentId);
   109         bookmark.put(BrowserContract.Bookmarks.TYPE, type);
   110         bookmark.put(BrowserContract.Bookmarks.POSITION, position);
   111         bookmark.put(BrowserContract.Bookmarks.TAGS, tags);
   112         bookmark.put(BrowserContract.Bookmarks.DESCRIPTION, description);
   113         bookmark.put(BrowserContract.Bookmarks.KEYWORD, keyword);
   115         return bookmark;
   116     }
   118     private ContentValues createOneBookmark() throws Exception {
   119         return createBookmark("Example", "http://example.com", mMobileFolderId,
   120                 BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword");
   121     }
   123     private Cursor getBookmarksByParent(long parent) throws Exception {
   124         // Order by position.
   125         return mProvider.query(BrowserContract.Bookmarks.CONTENT_URI, null,
   126                                BrowserContract.Bookmarks.PARENT + " = ?",
   127                                new String[] { String.valueOf(parent) },
   128                                BrowserContract.Bookmarks.POSITION);
   129     }
   131     private Cursor getBookmarkByGuid(String guid) throws Exception {
   132         return mProvider.query(BrowserContract.Bookmarks.CONTENT_URI, null,
   133                                BrowserContract.Bookmarks.GUID + " = ?",
   134                                new String[] { guid },
   135                                null);
   136     }
   138     private Cursor getBookmarkById(long id) throws Exception {
   139         return getBookmarkById(BrowserContract.Bookmarks.CONTENT_URI, id, null);
   140     }
   142     private Cursor getBookmarkById(long id, String[] projection) throws Exception {
   143         return getBookmarkById(BrowserContract.Bookmarks.CONTENT_URI, id, projection);
   144     }
   146     private Cursor getBookmarkById(Uri bookmarksUri, long id) throws Exception {
   147         return getBookmarkById(bookmarksUri, id, null);
   148     }
   150     private Cursor getBookmarkById(Uri bookmarksUri, long id, String[] projection) throws Exception {
   151         return mProvider.query(bookmarksUri, projection,
   152                                BrowserContract.Bookmarks._ID + " = ?",
   153                                new String[] { String.valueOf(id) },
   154                                null);
   155     }
   157     private ContentValues createHistoryEntry(String title, String url, int visits, long lastVisited) throws Exception {
   158         ContentValues historyEntry = new ContentValues();
   160         historyEntry.put(BrowserContract.History.TITLE, title);
   161         historyEntry.put(BrowserContract.History.URL, url);
   162         historyEntry.put(BrowserContract.History.VISITS, visits);
   163         historyEntry.put(BrowserContract.History.DATE_LAST_VISITED, lastVisited);
   165         return historyEntry;
   166     }
   168     private ContentValues createFaviconEntry(String pageUrl, String data) throws Exception {
   169         ContentValues faviconEntry = new ContentValues();
   171         faviconEntry.put(BrowserContract.Favicons.PAGE_URL, pageUrl);
   172         faviconEntry.put(BrowserContract.Favicons.URL, pageUrl + "/favicon.ico");
   173         faviconEntry.put(BrowserContract.Favicons.DATA, data.getBytes("UTF8"));
   175         return faviconEntry;
   176     }
   178     private ContentValues createThumbnailEntry(String pageUrl, String data) throws Exception {
   179         ContentValues thumbnailEntry = new ContentValues();
   181         thumbnailEntry.put(BrowserContract.Thumbnails.URL, pageUrl);
   182         thumbnailEntry.put(BrowserContract.Thumbnails.DATA, data.getBytes("UTF8"));
   184         return thumbnailEntry;
   185     }
   187     private ContentValues createOneHistoryEntry() throws Exception {
   188         return createHistoryEntry("Example", "http://example.com", 10, System.currentTimeMillis());
   189     }
   191     private Cursor getHistoryEntryById(long id) throws Exception {
   192         return getHistoryEntryById(BrowserContract.History.CONTENT_URI, id, null);
   193     }
   195     private Cursor getHistoryEntryById(long id, String[] projection) throws Exception {
   196         return getHistoryEntryById(BrowserContract.History.CONTENT_URI, id, projection);
   197     }
   199     private Cursor getHistoryEntryById(Uri historyUri, long id) throws Exception {
   200         return getHistoryEntryById(historyUri, id, null);
   201     }
   203     private Cursor getHistoryEntryById(Uri historyUri, long id, String[] projection) throws Exception {
   204         return mProvider.query(historyUri, projection,
   205                                BrowserContract.History._ID + " = ?",
   206                                new String[] { String.valueOf(id) },
   207                                null);
   208     }
   210     private Cursor getFaviconsByUrl(String url) throws Exception {
   211         return mProvider.query(BrowserContract.Combined.CONTENT_URI, null,
   212                                BrowserContract.Combined.URL + " = ?",
   213                                new String[] { url },
   214                                null);
   215     }
   217     private Cursor getThumbnailByUrl(String url) throws Exception {
   218         return mProvider.query(BrowserContract.Thumbnails.CONTENT_URI, null,
   219                                BrowserContract.Thumbnails.URL + " = ?",
   220                                new String[] { url },
   221                                null);
   222     }
   224     @Override
   225     public void setUp() throws Exception {
   226         super.setUp(sBrowserProviderCallable, BrowserContract.AUTHORITY, "browser.db");
   228         mTests.add(new TestSpecialFolders());
   230         mTests.add(new TestInsertBookmarks());
   231         mTests.add(new TestInsertBookmarksFavicons());
   232         mTests.add(new TestDeleteBookmarks());
   233         mTests.add(new TestDeleteBookmarksFavicons());
   234         mTests.add(new TestUpdateBookmarks());
   235         mTests.add(new TestUpdateBookmarksFavicons());
   236         mTests.add(new TestPositionBookmarks());
   238         mTests.add(new TestInsertHistory());
   239         mTests.add(new TestInsertHistoryFavicons());
   240         mTests.add(new TestDeleteHistory());
   241         mTests.add(new TestDeleteHistoryFavicons());
   242         mTests.add(new TestUpdateHistory());
   243         mTests.add(new TestUpdateHistoryFavicons());
   244         mTests.add(new TestUpdateOrInsertHistory());
   245         mTests.add(new TestInsertHistoryThumbnails());
   246         mTests.add(new TestUpdateHistoryThumbnails());
   247         mTests.add(new TestDeleteHistoryThumbnails());
   249         mTests.add(new TestBatchOperations());
   251         mTests.add(new TestCombinedView());
   252         mTests.add(new TestCombinedViewDisplay());
   253         mTests.add(new TestCombinedViewWithDeletedBookmark());
   254         mTests.add(new TestCombinedViewWithDeletedReadingListItem());
   255         mTests.add(new TestExpireHistory());
   257         mTests.add(new TestBrowserProviderNotifications());
   258     }
   260     public void testBrowserProvider() throws Exception {
   261         loadMobileFolderId();
   263         for (int i = 0; i < mTests.size(); i++) {
   264             Runnable test = mTests.get(i);
   266             final String testName = test.getClass().getSimpleName();
   267             setTestName(testName);
   268             ensureEmptyDatabase();
   269             mAsserter.dumpLog("testBrowserProvider: Database empty - Starting " + testName + ".");
   270             test.run();
   271         }
   272     }
   274     private class TestBatchOperations extends TestCase {
   275         static final int TESTCOUNT = 100;
   277         public void testApplyBatch() throws Exception {
   278             ArrayList<ContentProviderOperation> mOperations
   279                 = new ArrayList<ContentProviderOperation>();
   281             // Test a bunch of inserts with applyBatch
   282             ContentValues values = new ContentValues();
   283             ContentProviderOperation.Builder builder = null;
   285             for (int i = 0; i < TESTCOUNT; i++) {
   286                 values.clear();
   287                 values.put(BrowserContract.History.VISITS, i);
   288                 values.put(BrowserContract.History.TITLE, "Test" + i);
   289                 values.put(BrowserContract.History.URL, "http://www.test.org/" + i);
   291                 // Insert
   292                 builder = ContentProviderOperation.newInsert(BrowserContract.History.CONTENT_URI);
   293                 builder.withValues(values);
   294                 // Queue the operation
   295                 mOperations.add(builder.build());
   296             }
   298             ContentProviderResult[] applyResult =
   299                 mProvider.applyBatch(mOperations);
   301             boolean allFound = true;
   302             for (int i = 0; i < TESTCOUNT; i++) {
   303                 Cursor cursor = mProvider.query(BrowserContract.History.CONTENT_URI,
   304                                                 null,
   305                                                 BrowserContract.History.URL + " = ?",
   306                                                 new String[] { "http://www.test.org/" + i },
   307                                                 null);
   309                 if (!cursor.moveToFirst())
   310                     allFound = false;
   311                 cursor.close();
   312             }
   313             mAsserter.is(allFound, true, "Found all batchApply entries");
   314             mOperations.clear();
   316             // Update all visits to 1
   317             values.clear();
   318             values.put(BrowserContract.History.VISITS, 1);
   319             for (int i = 0; i < TESTCOUNT; i++) {
   320                 builder = ContentProviderOperation.newUpdate(BrowserContract.History.CONTENT_URI);
   321                 builder.withSelection(BrowserContract.History.URL  + " = ?",
   322                                       new String[] {"http://www.test.org/" + i});
   323                 builder.withValues(values);
   324                 builder.withExpectedCount(1);
   325                 // Queue the operation
   326                 mOperations.add(builder.build());
   327             }
   329             boolean seenException = false;
   330             try {
   331                 applyResult = mProvider.applyBatch(mOperations);
   332             } catch (OperationApplicationException ex) {
   333                 seenException = true;
   334             }
   335             mAsserter.is(seenException, false, "Batch updating succeded");
   336             mOperations.clear();
   338             // Delete all visits
   339             for (int i = 0; i < TESTCOUNT; i++) {
   340                 builder = ContentProviderOperation.newDelete(BrowserContract.History.CONTENT_URI);
   341                 builder.withSelection(BrowserContract.History.URL  + " = ?",
   342                                       new String[] {"http://www.test.org/" + i});
   343                 builder.withExpectedCount(1);
   344                 // Queue the operation
   345                 mOperations.add(builder.build());
   346             }
   347             try {
   348                 applyResult = mProvider.applyBatch(mOperations);
   349             } catch (OperationApplicationException ex) {
   350                 seenException = true;
   351             }
   352             mAsserter.is(seenException, false, "Batch deletion succeeded");
   353         }
   355         // Force a Constraint error, see if later operations still apply correctly
   356         public void testApplyBatchErrors() throws Exception {
   357             ArrayList<ContentProviderOperation> mOperations
   358                 = new ArrayList<ContentProviderOperation>();
   360             // Test a bunch of inserts with applyBatch
   361             ContentProviderOperation.Builder builder = null;
   362             ContentValues values = createFaviconEntry("http://www.test.org", "FAVICON");
   363             builder = ContentProviderOperation.newInsert(BrowserContract.Favicons.CONTENT_URI);
   364             builder.withValues(values);
   365             mOperations.add(builder.build());
   367             // Make a duplicate, this will fail because of a UNIQUE constraint
   368             builder = ContentProviderOperation.newInsert(BrowserContract.Favicons.CONTENT_URI);
   369             builder.withValues(values);
   370             mOperations.add(builder.build());
   372             // This is valid and should be in the table afterwards
   373             values.put(BrowserContract.Favicons.URL, "http://www.test.org/valid.ico");
   374             builder = ContentProviderOperation.newInsert(BrowserContract.Favicons.CONTENT_URI);
   375             builder.withValues(values);
   376             mOperations.add(builder.build());
   378             boolean seenException = false;
   380             try {
   381                 ContentProviderResult[] applyResult =
   382                     mProvider.applyBatch(mOperations);
   383             } catch (OperationApplicationException ex) {
   384                 seenException = true;
   385             }
   387             // This test may need to go away if Bug 717428 is fixed.
   388             mAsserter.is(seenException, true, "Expected failure in favicons table");
   390             boolean allFound = true;
   391             Cursor cursor = mProvider.query(BrowserContract.Favicons.CONTENT_URI,
   392                                             null,
   393                                             BrowserContract.Favicons.URL + " = ?",
   394                                             new String[] { "http://www.test.org/valid.ico" },
   395                                             null);
   397             if (!cursor.moveToFirst())
   398                 allFound = false;
   399             cursor.close();
   401             mAsserter.is(allFound, true, "Found all applyBatch (with error) entries");
   402         }
   404         public void testBulkInsert() throws Exception {
   405             // Test a bunch of inserts with bulkInsert
   406             ContentValues allVals[] = new ContentValues[TESTCOUNT];
   407             for (int i = 0; i < TESTCOUNT; i++) {
   408                 allVals[i] = new ContentValues();
   409                 allVals[i].put(BrowserContract.History.URL, i);
   410                 allVals[i].put(BrowserContract.History.TITLE, "Test" + i);
   411                 allVals[i].put(BrowserContract.History.URL, "http://www.test.org/" + i);
   412             }
   414             int inserts = mProvider.bulkInsert(BrowserContract.History.CONTENT_URI, allVals);
   415             mAsserter.is(inserts, TESTCOUNT, "Excepted number of inserts matches");
   417             boolean allFound = true;
   418             for (int i = 0; i < TESTCOUNT; i++) {
   419                 Cursor cursor = mProvider.query(BrowserContract.History.CONTENT_URI,
   420                                                 null,
   421                                                 BrowserContract.History.URL + " = ?",
   422                                                 new String[] { "http://www.test.org/" + i },
   423                                                 null);
   425                 if (!cursor.moveToFirst())
   426                     allFound = false;
   427                 cursor.close();
   428             }
   429             mAsserter.is(allFound, true, "Found all bulkInsert entries");
   430         }
   432         @Override
   433         public void test() throws Exception {
   434             testApplyBatch();
   435             // Clean up
   436             ensureEmptyDatabase();
   438             testBulkInsert();
   439             ensureEmptyDatabase();
   441             testApplyBatchErrors();
   442         }
   443     }
   445     private class TestSpecialFolders extends TestCase {
   446         @Override
   447         public void test() throws Exception {
   448             Cursor c = mProvider.query(BrowserContract.Bookmarks.CONTENT_URI,
   449                                        new String[] { BrowserContract.Bookmarks._ID,
   450                                                       BrowserContract.Bookmarks.GUID,
   451                                                       BrowserContract.Bookmarks.PARENT },
   452                                        BrowserContract.Bookmarks.GUID + " = ? OR " +
   453                                        BrowserContract.Bookmarks.GUID + " = ? OR " +
   454                                        BrowserContract.Bookmarks.GUID + " = ? OR " +
   455                                        BrowserContract.Bookmarks.GUID + " = ? OR " +
   456                                        BrowserContract.Bookmarks.GUID + " = ? OR " +
   457                                        BrowserContract.Bookmarks.GUID + " = ? OR " +
   458                                        BrowserContract.Bookmarks.GUID + " = ?",
   459                                        new String[] { BrowserContract.Bookmarks.PLACES_FOLDER_GUID,
   460                                                       BrowserContract.Bookmarks.MOBILE_FOLDER_GUID,
   461                                                       BrowserContract.Bookmarks.MENU_FOLDER_GUID,
   462                                                       BrowserContract.Bookmarks.TAGS_FOLDER_GUID,
   463                                                       BrowserContract.Bookmarks.TOOLBAR_FOLDER_GUID,
   464                                                       BrowserContract.Bookmarks.UNFILED_FOLDER_GUID,
   465                                                       BrowserContract.Bookmarks.READING_LIST_FOLDER_GUID },
   466                                        null);
   468             mAsserter.is(c.getCount(), 7, "Right number of special folders");
   470             int rootId = BrowserContract.Bookmarks.FIXED_ROOT_ID;
   471             int readingListId = BrowserContract.Bookmarks.FIXED_READING_LIST_ID;
   473             while (c.moveToNext()) {
   474                 int id = c.getInt(c.getColumnIndex(BrowserContract.Bookmarks._ID));
   475                 String guid = c.getString(c.getColumnIndex(BrowserContract.Bookmarks.GUID));
   476                 int parentId = c.getInt(c.getColumnIndex(BrowserContract.Bookmarks.PARENT));
   478                 if (guid.equals(BrowserContract.Bookmarks.PLACES_FOLDER_GUID)) {
   479                     mAsserter.is(new Integer(id), new Integer(rootId), "The id of places folder is correct");
   480                 } else if (guid.equals(BrowserContract.Bookmarks.READING_LIST_FOLDER_GUID)) {
   481                     mAsserter.is(new Integer(id), new Integer(readingListId), "The id of reading list folder is correct");
   482                 }
   484                 mAsserter.is(new Integer(parentId), new Integer(rootId),
   485                              "The PARENT of the " + guid + " special folder is correct");
   486             }
   488             c.close();
   489         }
   490     }
   492     private class TestInsertBookmarks extends TestCase {
   493         private long insertWithNullCol(String colName) throws Exception {
   494             ContentValues b = createOneBookmark();
   495             b.putNull(colName);
   496             long id = -1;
   498             try {
   499                 id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b));
   500             } catch (Exception e) {}
   502             return id;
   503         }
   505         @Override
   506         public void test() throws Exception {
   507             ContentValues b = createOneBookmark();
   508             long id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b));
   509             Cursor c = getBookmarkById(id);
   511             mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found");
   513             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TITLE)), b.getAsString(BrowserContract.Bookmarks.TITLE),
   514                          "Inserted bookmark has correct title");
   515             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.URL)), b.getAsString(BrowserContract.Bookmarks.URL),
   516                          "Inserted bookmark has correct URL");
   517             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TAGS)), b.getAsString(BrowserContract.Bookmarks.TAGS),
   518                          "Inserted bookmark has correct tags");
   519             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.KEYWORD)), b.getAsString(BrowserContract.Bookmarks.KEYWORD),
   520                          "Inserted bookmark has correct keyword");
   521             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.DESCRIPTION)), b.getAsString(BrowserContract.Bookmarks.DESCRIPTION),
   522                          "Inserted bookmark has correct description");
   523             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.POSITION)), b.getAsString(BrowserContract.Bookmarks.POSITION),
   524                          "Inserted bookmark has correct position");
   525             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TYPE)), b.getAsString(BrowserContract.Bookmarks.TYPE),
   526                          "Inserted bookmark has correct type");
   527             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.PARENT)), b.getAsString(BrowserContract.Bookmarks.PARENT),
   528                          "Inserted bookmark has correct parent ID");
   529             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.IS_DELETED)), String.valueOf(0),
   530                          "Inserted bookmark has correct is-deleted state");
   532             id = insertWithNullCol(BrowserContract.Bookmarks.POSITION);
   533             mAsserter.is(new Long(id), new Long(-1),
   534                          "Should not be able to insert bookmark with null position");
   536             id = insertWithNullCol(BrowserContract.Bookmarks.TYPE);
   537             mAsserter.is(new Long(id), new Long(-1),
   538                          "Should not be able to insert bookmark with null type");
   540             if (Build.VERSION.SDK_INT >= 8 &&
   541                 Build.VERSION.SDK_INT < 16) {
   542                 b = createOneBookmark();
   543                 b.put(BrowserContract.Bookmarks.PARENT, -1);
   544                 id = -1;
   546                 try {
   547                     id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b));
   548                 } catch (Exception e) {}
   550                 mAsserter.is(new Long(id), new Long(-1),
   551                              "Should not be able to insert bookmark with invalid parent");
   552             }
   554             b = createOneBookmark();
   555             b.remove(BrowserContract.Bookmarks.TYPE);
   556             id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b));
   557             c = getBookmarkById(id);
   559             mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found");
   561             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TYPE)), String.valueOf(BrowserContract.Bookmarks.TYPE_BOOKMARK),
   562                          "Inserted bookmark has correct default type");
   563             c.close();
   564         }
   565     }
   567     private class TestInsertBookmarksFavicons extends TestCase {
   568         @Override
   569         public void test() throws Exception {
   570             ContentValues b = createOneBookmark();
   572             final String favicon = "FAVICON";
   573             final String pageUrl = b.getAsString(BrowserContract.Bookmarks.URL);
   575             long id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b));
   577             // Insert the favicon into the favicons table
   578             mProvider.insert(BrowserContract.Favicons.CONTENT_URI, createFaviconEntry(pageUrl, favicon));
   580             Cursor c = getBookmarkById(id, new String[] { BrowserContract.Bookmarks.FAVICON });
   582             mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found");
   584             mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Bookmarks.FAVICON)), "UTF8"),
   585                          favicon, "Inserted bookmark has corresponding favicon image");
   586             c.close();
   588             c = getFaviconsByUrl(pageUrl);
   589             mAsserter.is(c.moveToFirst(), true, "Inserted favicon found");
   591             mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"),
   592                          favicon, "Inserted favicon has corresponding favicon image");
   593             c.close();
   594         }
   595     }
   597     private class TestDeleteBookmarks extends TestCase {
   598         private long insertOneBookmark() throws Exception {
   599             ContentValues b = createOneBookmark();
   600             long id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b));
   602             Cursor c = getBookmarkById(id);
   603             mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found");
   604             c.close();
   606             return id;
   607         }
   609         @Override
   610         public void test() throws Exception {
   611             long id = insertOneBookmark();
   613             int deleted = mProvider.delete(BrowserContract.Bookmarks.CONTENT_URI,
   614                                            BrowserContract.Bookmarks._ID + " = ?",
   615                                            new String[] { String.valueOf(id) });
   617             mAsserter.is((deleted == 1), true, "Inserted bookmark was deleted");
   619             Cursor c = getBookmarkById(appendUriParam(BrowserContract.Bookmarks.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), id);
   620             mAsserter.is(c.moveToFirst(), true, "Deleted bookmark was only marked as deleted");
   621             c.close();
   623             deleted = mProvider.delete(appendUriParam(BrowserContract.Bookmarks.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"),
   624                                        BrowserContract.Bookmarks._ID + " = ?",
   625                                        new String[] { String.valueOf(id) });
   627             mAsserter.is((deleted == 1), true, "Inserted bookmark was deleted");
   629             c = getBookmarkById(appendUriParam(BrowserContract.Bookmarks.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), id);
   630             mAsserter.is(c.moveToFirst(), false, "Inserted bookmark is now actually deleted");
   631             c.close();
   633             id = insertOneBookmark();
   635             deleted = mProvider.delete(ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, id), null, null);
   636             mAsserter.is((deleted == 1), true,
   637                          "Inserted bookmark was deleted using URI with id");
   639             c = getBookmarkById(id);
   640             mAsserter.is(c.moveToFirst(), false,
   641                          "Inserted bookmark can't be found after deletion using URI with ID");
   642             c.close();
   644             if (Build.VERSION.SDK_INT >= 8 &&
   645                 Build.VERSION.SDK_INT < 16) {
   646                 ContentValues b = createBookmark("Folder", null, mMobileFolderId,
   647                         BrowserContract.Bookmarks.TYPE_FOLDER, 0, "folderTags", "folderDescription", "folderKeyword");
   649                 long parentId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b));
   650                 c = getBookmarkById(parentId);
   651                 mAsserter.is(c.moveToFirst(), true, "Inserted bookmarks folder found");
   652                 c.close();
   654                 b = createBookmark("Example", "http://example.com", parentId,
   655                         BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword");
   657                 id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b));
   658                 c = getBookmarkById(id);
   659                 mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found");
   660                 c.close();
   662                 deleted = 0;
   663                 try {
   664                     Uri uri = ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, parentId);
   665                     deleted = mProvider.delete(appendUriParam(uri, BrowserContract.PARAM_IS_SYNC, "1"), null, null);
   666                 } catch(Exception e) {}
   668                 mAsserter.is((deleted == 0), true,
   669                              "Should not be able to delete folder that causes orphan bookmarks");
   670             }
   671         }
   672     }
   674     private class TestDeleteBookmarksFavicons extends TestCase {
   675         @Override
   676         public void test() throws Exception {
   677             ContentValues b = createOneBookmark();
   679             final String pageUrl = b.getAsString(BrowserContract.Bookmarks.URL);
   680             long id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b));
   682             // Insert the favicon into the favicons table
   683             mProvider.insert(BrowserContract.Favicons.CONTENT_URI, createFaviconEntry(pageUrl, "FAVICON"));
   685             Cursor c = getFaviconsByUrl(pageUrl);
   686             mAsserter.is(c.moveToFirst(), true, "Inserted favicon found");
   687             c.close();
   689             mProvider.delete(ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, id), null, null);
   691             c = getFaviconsByUrl(pageUrl);
   692             mAsserter.is(c.moveToFirst(), false, "Favicon is deleted with last reference to it");
   693             c.close();
   694         }
   695     }
   697     private class TestUpdateBookmarks extends TestCase {
   698         private int updateWithNullCol(long id, String colName) throws Exception {
   699             ContentValues u = new ContentValues();
   700             u.putNull(colName);
   702             int updated = 0;
   704             try {
   705                 updated = mProvider.update(BrowserContract.Bookmarks.CONTENT_URI, u,
   706                                            BrowserContract.Bookmarks._ID + " = ?",
   707                                            new String[] { String.valueOf(id) });
   708             } catch (Exception e) {}
   710             return updated;
   711         }
   713         @Override
   714         public void test() throws Exception {
   715             ContentValues b = createOneBookmark();
   716             long id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b));
   718             Cursor c = getBookmarkById(id);
   719             mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found");
   721             long dateCreated = c.getLong(c.getColumnIndex(BrowserContract.Bookmarks.DATE_CREATED));
   722             long dateModified = c.getLong(c.getColumnIndex(BrowserContract.Bookmarks.DATE_MODIFIED));
   724             ContentValues u = new ContentValues();
   725             u.put(BrowserContract.Bookmarks.TITLE, b.getAsString(BrowserContract.Bookmarks.TITLE) + "CHANGED");
   726             u.put(BrowserContract.Bookmarks.URL, b.getAsString(BrowserContract.Bookmarks.URL) + "/more/stuff");
   727             u.put(BrowserContract.Bookmarks.TAGS, b.getAsString(BrowserContract.Bookmarks.TAGS) + "CHANGED");
   728             u.put(BrowserContract.Bookmarks.DESCRIPTION, b.getAsString(BrowserContract.Bookmarks.DESCRIPTION) + "CHANGED");
   729             u.put(BrowserContract.Bookmarks.KEYWORD, b.getAsString(BrowserContract.Bookmarks.KEYWORD) + "CHANGED");
   730             u.put(BrowserContract.Bookmarks.TYPE, BrowserContract.Bookmarks.TYPE_FOLDER);
   731             u.put(BrowserContract.Bookmarks.POSITION, 10);
   733             int updated = mProvider.update(BrowserContract.Bookmarks.CONTENT_URI, u,
   734                                            BrowserContract.Bookmarks._ID + " = ?",
   735                                            new String[] { String.valueOf(id) });
   737             mAsserter.is((updated == 1), true, "Inserted bookmark was updated");
   738             c.close();
   740             c = getBookmarkById(id);
   741             mAsserter.is(c.moveToFirst(), true, "Updated bookmark found");
   743             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TITLE)), u.getAsString(BrowserContract.Bookmarks.TITLE),
   744                          "Inserted bookmark has correct title");
   745             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.URL)), u.getAsString(BrowserContract.Bookmarks.URL),
   746                          "Inserted bookmark has correct URL");
   747             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TAGS)), u.getAsString(BrowserContract.Bookmarks.TAGS),
   748                          "Inserted bookmark has correct tags");
   749             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.KEYWORD)), u.getAsString(BrowserContract.Bookmarks.KEYWORD),
   750                          "Inserted bookmark has correct keyword");
   751             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.DESCRIPTION)), u.getAsString(BrowserContract.Bookmarks.DESCRIPTION),
   752                          "Inserted bookmark has correct description");
   753             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.POSITION)), u.getAsString(BrowserContract.Bookmarks.POSITION),
   754                          "Inserted bookmark has correct position");
   755             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TYPE)), u.getAsString(BrowserContract.Bookmarks.TYPE),
   756                          "Inserted bookmark has correct type");
   758             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Bookmarks.DATE_CREATED))),
   759                          new Long(dateCreated),
   760                          "Updated bookmark has same creation date");
   762             mAsserter.isnot(new Long(c.getLong(c.getColumnIndex(BrowserContract.Bookmarks.DATE_MODIFIED))),
   763                             new Long(dateModified),
   764                             "Updated bookmark has new modification date");
   766             updated = updateWithNullCol(id, BrowserContract.Bookmarks.POSITION);
   767             mAsserter.is((updated > 0), false,
   768                          "Should not be able to update bookmark with null position");
   770             updated = updateWithNullCol(id, BrowserContract.Bookmarks.TYPE);
   771             mAsserter.is((updated > 0), false,
   772                          "Should not be able to update bookmark with null type");
   774             u = new ContentValues();
   775             u.put(BrowserContract.Bookmarks.URL, "http://examples2.com");
   777             updated = mProvider.update(ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, id), u, null, null);
   778             c.close();
   780             c = getBookmarkById(id);
   781             mAsserter.is(c.moveToFirst(), true, "Updated bookmark found");
   783             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.URL)), u.getAsString(BrowserContract.Bookmarks.URL),
   784                          "Updated bookmark has correct URL using URI with id");
   785             c.close();
   786         }
   787     }
   789     private class TestUpdateBookmarksFavicons extends TestCase {
   790         @Override
   791         public void test() throws Exception {
   792             ContentValues b = createOneBookmark();
   794             final String favicon = "FAVICON";
   795             final String newFavicon = "NEW_FAVICON";
   796             final String pageUrl = b.getAsString(BrowserContract.Bookmarks.URL);
   798             mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b);
   800             // Insert the favicon into the favicons table
   801             ContentValues f = createFaviconEntry(pageUrl, favicon);
   802             long faviconId = ContentUris.parseId(mProvider.insert(BrowserContract.Favicons.CONTENT_URI, f));
   804             Cursor c = getFaviconsByUrl(pageUrl);
   805             mAsserter.is(c.moveToFirst(), true, "Inserted favicon found");
   807             mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"),
   808                          favicon, "Inserted favicon has corresponding favicon image");
   810             ContentValues u = createFaviconEntry(pageUrl, newFavicon);
   811             mProvider.update(BrowserContract.Favicons.CONTENT_URI, u, null, null);
   812             c.close();
   814             c = getFaviconsByUrl(pageUrl);
   815             mAsserter.is(c.moveToFirst(), true, "Updated favicon found");
   817             mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"),
   818                          newFavicon, "Updated favicon has corresponding favicon image");
   819             c.close();
   820         }
   821     }
   823     /**
   824      * Create a folder of one thousand and one bookmarks, then impose an order
   825      * on them.
   826      *
   827      * Verify that the reordering worked by querying.
   828      */
   829     private class TestPositionBookmarks extends TestCase {
   831         public String makeGUID(final long in) {
   832             String part = String.valueOf(in);
   833             return "aaaaaaaaaaaa".substring(0, (12 - part.length())) + part;
   834         }
   836         public void compareCursorToItems(final Cursor c, final String[] items, final int count) {
   837             mAsserter.is(c.moveToFirst(), true, "Folder has children.");
   839             int posColumn = c.getColumnIndex(BrowserContract.Bookmarks.POSITION);
   840             int guidColumn = c.getColumnIndex(BrowserContract.Bookmarks.GUID);
   841             int i = 0;
   843             while (!c.isAfterLast()) {
   844                 String guid = c.getString(guidColumn);
   845                 long pos = c.getLong(posColumn);
   846                 if ((pos != i) || (guid == null) || (!guid.equals(items[i]))) {
   847                     mAsserter.is(pos, (long) i, "Position matches sequence.");
   848                     mAsserter.is(guid, items[i], "GUID matches sequence.");
   849                 }
   850                 ++i;
   851                 c.moveToNext();
   852             }
   854             mAsserter.is(i, count, "Folder has the right number of children.");
   855             c.close();
   856         }
   858         public static final int NUMBER_OF_CHILDREN = 1001;
   859         @Override
   860         public void test() throws Exception {
   861             // Create the containing folder.
   862             ContentValues folder = createBookmark("FolderFolder", "", mMobileFolderId,
   863                                                   BrowserContract.Bookmarks.TYPE_FOLDER, 0, "",
   864                                                   "description", "keyword");
   865             folder.put(BrowserContract.Bookmarks.GUID, "folderfolder");
   866             long folderId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, folder));
   868             mAsserter.dumpLog("TestPositionBookmarks: Folder inserted"); // Bug 968951 debug.
   870             // Create the children.
   871             String[] items = new String[NUMBER_OF_CHILDREN];
   873             // Reuse the same ContentValues.
   874             ContentValues item = createBookmark("Test Bookmark", "http://example.com", folderId,
   875                                                 BrowserContract.Bookmarks.TYPE_FOLDER, 0, "",
   876                                                 "description", "keyword");
   878             for (int i = 0; i < NUMBER_OF_CHILDREN; ++i) {
   879                 String guid = makeGUID(i);
   880                 items[i] = guid;
   881                 item.put(BrowserContract.Bookmarks.GUID, guid);
   882                 item.put(BrowserContract.Bookmarks.POSITION, i);
   883                 item.put(BrowserContract.Bookmarks.URL, "http://example.com/" + guid);
   884                 item.put(BrowserContract.Bookmarks.TITLE, "Test Bookmark " + guid);
   885                 mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, item);
   886             }
   888             mAsserter.dumpLog("TestPositionBookmarks: Bookmarks inserted"); // Bug 968951 debug.
   890             Cursor c;
   892             // Verify insertion.
   893             c = getBookmarksByParent(folderId);
   894             mAsserter.dumpLog("TestPositionBookmarks: Got bookmarks by parent"); // Bug 968951 debug.
   895             compareCursorToItems(c, items, NUMBER_OF_CHILDREN);
   896             c.close();
   898             // Now permute the items array.
   899             Random rand = new Random();
   900             for (int i = 0; i < NUMBER_OF_CHILDREN; ++i) {
   901                 final int newPosition = rand.nextInt(NUMBER_OF_CHILDREN);
   902                 final String switched = items[newPosition];
   903                 items[newPosition] = items[i];
   904                 items[i] = switched;
   905             }
   907             // Impose the positions.
   908             long updated = mProvider.update(BrowserContract.Bookmarks.POSITIONS_CONTENT_URI, null, null, items);
   909             mAsserter.is(updated, (long) NUMBER_OF_CHILDREN, "Updated " + NUMBER_OF_CHILDREN + " positions.");
   911             // Verify that the database was updated.
   912             c = getBookmarksByParent(folderId);
   913             compareCursorToItems(c, items, NUMBER_OF_CHILDREN);
   914             c.close();
   915         }
   916     }
   918     private class TestInsertHistory extends TestCase {
   919         private long insertWithNullCol(String colName) throws Exception {
   920             ContentValues h = createOneHistoryEntry();
   921             h.putNull(colName);
   922             long id = -1;
   924             try {
   925                 id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h));
   926             } catch (Exception e) {}
   928             return id;
   929         }
   931         @Override
   932         public void test() throws Exception {
   933             ContentValues h = createOneHistoryEntry();
   934             long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h));
   935             Cursor c = getHistoryEntryById(id);
   937             mAsserter.is(c.moveToFirst(), true, "Inserted history entry found");
   939             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), h.getAsString(BrowserContract.History.TITLE),
   940                          "Inserted history entry has correct title");
   941             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.URL)), h.getAsString(BrowserContract.History.URL),
   942                          "Inserted history entry has correct URL");
   943             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.VISITS)), h.getAsString(BrowserContract.History.VISITS),
   944                          "Inserted history entry has correct number of visits");
   945             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.DATE_LAST_VISITED)), h.getAsString(BrowserContract.History.DATE_LAST_VISITED),
   946                          "Inserted history entry has correct last visited date");
   947             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.IS_DELETED)), String.valueOf(0),
   948                          "Inserted history entry has correct is-deleted state");
   950             id = insertWithNullCol(BrowserContract.History.URL);
   951             mAsserter.is(new Long(id), new Long(-1),
   952                          "Should not be able to insert history with null URL");
   954             id = insertWithNullCol(BrowserContract.History.VISITS);
   955             mAsserter.is(new Long(id), new Long(-1),
   956                          "Should not be able to insert history with null number of visits");
   957             c.close();
   958         }
   959     }
   961     private class TestInsertHistoryFavicons extends TestCase {
   962         @Override
   963         public void test() throws Exception {
   964             ContentValues h = createOneHistoryEntry();
   966             final String favicon = "FAVICON";
   967             final String pageUrl = h.getAsString(BrowserContract.History.URL);
   969             long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h));
   971             // Insert the favicon into the favicons table
   972             mProvider.insert(BrowserContract.Favicons.CONTENT_URI, createFaviconEntry(pageUrl, favicon));
   974             Cursor c = getHistoryEntryById(id, new String[] { BrowserContract.History.FAVICON });
   976             mAsserter.is(c.moveToFirst(), true, "Inserted history entry found");
   978             mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.History.FAVICON)), "UTF8"),
   979                          favicon, "Inserted history entry has corresponding favicon image");
   980             c.close();
   982             c = getFaviconsByUrl(pageUrl);
   983             mAsserter.is(c.moveToFirst(), true, "Inserted favicon found");
   985             mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"),
   986                          favicon, "Inserted favicon has corresponding favicon image");
   987             c.close();
   988         }
   989     }
   991     private class TestDeleteHistory extends TestCase {
   992         private long insertOneHistoryEntry() throws Exception {
   993             ContentValues h = createOneHistoryEntry();
   994             long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h));
   996             Cursor c = getHistoryEntryById(id);
   997             mAsserter.is(c.moveToFirst(), true, "Inserted history entry found");
   998             c.close();
  1000             return id;
  1003         @Override
  1004         public void test() throws Exception {
  1005             long id = insertOneHistoryEntry();
  1007             int deleted = mProvider.delete(BrowserContract.History.CONTENT_URI,
  1008                                            BrowserContract.History._ID + " = ?",
  1009                                            new String[] { String.valueOf(id) });
  1011             mAsserter.is((deleted == 1), true, "Inserted history entry was deleted");
  1013             Cursor c = getHistoryEntryById(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), id);
  1014             mAsserter.is(c.moveToFirst(), true, "Deleted history entry was only marked as deleted");
  1016             deleted = mProvider.delete(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"),
  1017                                        BrowserContract.History._ID + " = ?",
  1018                                        new String[] { String.valueOf(id) });
  1020             mAsserter.is((deleted == 1), true, "Inserted history entry was deleted");
  1021             c.close();
  1023             c = getHistoryEntryById(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), id);
  1024             mAsserter.is(c.moveToFirst(), false, "Inserted history is now actually deleted");
  1026             id = insertOneHistoryEntry();
  1028             deleted = mProvider.delete(ContentUris.withAppendedId(BrowserContract.History.CONTENT_URI, id), null, null);
  1029             mAsserter.is((deleted == 1), true,
  1030                          "Inserted history entry was deleted using URI with id");
  1031             c.close();
  1033             c = getHistoryEntryById(id);
  1034             mAsserter.is(c.moveToFirst(), false,
  1035                          "Inserted history entry can't be found after deletion using URI with ID");
  1036             c.close();
  1040     private class TestDeleteHistoryFavicons extends TestCase {
  1041         @Override
  1042         public void test() throws Exception {
  1043             ContentValues h = createOneHistoryEntry();
  1045             long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h));
  1046             final String pageUrl = h.getAsString(BrowserContract.History.URL);
  1048             // Insert the favicon into the favicons table
  1049             mProvider.insert(BrowserContract.Favicons.CONTENT_URI, createFaviconEntry(pageUrl, "FAVICON"));
  1051             Cursor c = getFaviconsByUrl(pageUrl);
  1052             mAsserter.is(c.moveToFirst(), true, "Inserted favicon found");
  1054             mProvider.delete(ContentUris.withAppendedId(BrowserContract.History.CONTENT_URI, id), null, null);
  1055             c.close();
  1057             c = getFaviconsByUrl(pageUrl);
  1058             mAsserter.is(c.moveToFirst(), false, "Favicon is deleted with last reference to it");
  1059             c.close();
  1063     private class TestUpdateHistory extends TestCase {
  1064         private int updateWithNullCol(long id, String colName) throws Exception {
  1065             ContentValues u = new ContentValues();
  1066             u.putNull(colName);
  1068             int updated = 0;
  1070             try {
  1071                 updated = mProvider.update(BrowserContract.History.CONTENT_URI, u,
  1072                                            BrowserContract.History._ID + " = ?",
  1073                                            new String[] { String.valueOf(id) });
  1074             } catch (Exception e) {}
  1076             return updated;
  1079         @Override
  1080         public void test() throws Exception {
  1081             ContentValues h = createOneHistoryEntry();
  1082             long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h));
  1084             Cursor c = getHistoryEntryById(id);
  1085             mAsserter.is(c.moveToFirst(), true, "Inserted history entry found");
  1087             long dateCreated = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED));
  1088             long dateModified = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED));
  1090             ContentValues u = new ContentValues();
  1091             u.put(BrowserContract.History.VISITS, h.getAsInteger(BrowserContract.History.VISITS) + 1);
  1092             u.put(BrowserContract.History.DATE_LAST_VISITED, System.currentTimeMillis());
  1093             u.put(BrowserContract.History.TITLE, h.getAsString(BrowserContract.History.TITLE) + "CHANGED");
  1094             u.put(BrowserContract.History.URL, h.getAsString(BrowserContract.History.URL) + "/more/stuff");
  1096             int updated = mProvider.update(BrowserContract.History.CONTENT_URI, u,
  1097                                            BrowserContract.History._ID + " = ?",
  1098                                            new String[] { String.valueOf(id) });
  1100             mAsserter.is((updated == 1), true, "Inserted history entry was updated");
  1101             c.close();
  1103             c = getHistoryEntryById(id);
  1104             mAsserter.is(c.moveToFirst(), true, "Updated history entry found");
  1106             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), u.getAsString(BrowserContract.History.TITLE),
  1107                          "Updated history entry has correct title");
  1108             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.URL)), u.getAsString(BrowserContract.History.URL),
  1109                          "Updated history entry has correct URL");
  1110             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.VISITS)), u.getAsString(BrowserContract.History.VISITS),
  1111                          "Updated history entry has correct number of visits");
  1112             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.DATE_LAST_VISITED)), u.getAsString(BrowserContract.History.DATE_LAST_VISITED),
  1113                          "Updated history entry has correct last visited date");
  1115             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED))),
  1116                          new Long(dateCreated),
  1117                          "Updated history entry has same creation date");
  1119             mAsserter.isnot(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED))),
  1120                             new Long(dateModified),
  1121                             "Updated history entry has new modification date");
  1123             updated = updateWithNullCol(id, BrowserContract.History.URL);
  1124             mAsserter.is((updated > 0), false,
  1125                          "Should not be able to update history with null URL");
  1127             updated = updateWithNullCol(id, BrowserContract.History.VISITS);
  1128             mAsserter.is((updated > 0), false,
  1129                          "Should not be able to update history with null number of visits");
  1131             u = new ContentValues();
  1132             u.put(BrowserContract.History.URL, "http://examples2.com");
  1134             updated = mProvider.update(ContentUris.withAppendedId(BrowserContract.History.CONTENT_URI, id), u, null, null);
  1135             c.close();
  1137             c = getHistoryEntryById(id);
  1138             mAsserter.is(c.moveToFirst(), true, "Updated history entry found");
  1140             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.URL)), u.getAsString(BrowserContract.History.URL),
  1141                          "Updated history entry has correct URL using URI with id");
  1142             c.close();
  1146     private class TestUpdateHistoryFavicons extends TestCase {
  1147         @Override
  1148         public void test() throws Exception {
  1149             ContentValues h = createOneHistoryEntry();
  1151             final String favicon = "FAVICON";
  1152             final String newFavicon = "NEW_FAVICON";
  1153             final String pageUrl = h.getAsString(BrowserContract.History.URL);
  1155             mProvider.insert(BrowserContract.History.CONTENT_URI, h);
  1157             // Insert the favicon into the favicons table
  1158             mProvider.insert(BrowserContract.Favicons.CONTENT_URI, createFaviconEntry(pageUrl, favicon));
  1160             Cursor c = getFaviconsByUrl(pageUrl);
  1161             mAsserter.is(c.moveToFirst(), true, "Inserted favicon found");
  1163             mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"),
  1164                          favicon, "Inserted favicon has corresponding favicon image");
  1166             ContentValues u = createFaviconEntry(pageUrl, newFavicon);
  1168             mProvider.update(BrowserContract.Favicons.CONTENT_URI, u, null, null);
  1169             c.close();
  1171             c = getFaviconsByUrl(pageUrl);
  1172             mAsserter.is(c.moveToFirst(), true, "Updated favicon found");
  1174             mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"),
  1175                          newFavicon, "Updated favicon has corresponding favicon image");
  1176             c.close();
  1180     private class TestUpdateOrInsertHistory extends TestCase {
  1181         private final String TEST_URL_1 = "http://example.com";
  1182         private final String TEST_URL_2 = "http://example.org";
  1183         private final String TEST_TITLE = "Example";
  1185         private long getHistoryEntryIdByUrl(String url) {
  1186             Cursor c = mProvider.query(BrowserContract.History.CONTENT_URI,
  1187                                        new String[] { BrowserContract.History._ID },
  1188                                        BrowserContract.History.URL + " = ?",
  1189                                        new String[] { url },
  1190                                        null);
  1191             c.moveToFirst();
  1192             long id = c.getLong(0);
  1193             c.close();
  1195             return id;
  1198         @Override
  1199         public void test() throws Exception {
  1200             Uri updateHistoryUri = BrowserContract.History.CONTENT_URI.buildUpon().
  1201                 appendQueryParameter("increment_visits", "true").build();
  1202             Uri updateOrInsertHistoryUri = BrowserContract.History.CONTENT_URI.buildUpon().
  1203                 appendQueryParameter("insert_if_needed", "true").
  1204                 appendQueryParameter("increment_visits", "true").build();
  1206             // Update a non-existent history entry, without specifying visits or title
  1207             ContentValues values = new ContentValues();
  1208             values.put(BrowserContract.History.URL, TEST_URL_1);
  1210             int updated = mProvider.update(updateHistoryUri, values,
  1211                                            BrowserContract.History.URL + " = ?",
  1212                                            new String[] { TEST_URL_1 });
  1213             mAsserter.is((updated == 0), true, "History entry was not updated");
  1214             Cursor c = mProvider.query(BrowserContract.History.CONTENT_URI, null, null, null, null);
  1215             mAsserter.is(c.moveToFirst(), false, "History entry was not inserted");
  1216             c.close();
  1218             // Now let's try with update-or-insert.
  1219             updated = mProvider.update(updateOrInsertHistoryUri, values,
  1220                                            BrowserContract.History.URL + " = ?",
  1221                                            new String[] { TEST_URL_1 });
  1222             mAsserter.is((updated == 1), true, "History entry was inserted");
  1224             long id = getHistoryEntryIdByUrl(TEST_URL_1);
  1225             c = getHistoryEntryById(id);
  1226             mAsserter.is(c.moveToFirst(), true, "History entry was inserted");
  1228             long dateCreated = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED));
  1229             long dateModified = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED));
  1231             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.VISITS))), new Long(1),
  1232                          "Inserted history entry has correct default number of visits");
  1233             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), TEST_URL_1,
  1234                          "Inserted history entry has correct default title");
  1236             // Update the history entry, without specifying an additional visit count
  1237             values = new ContentValues();
  1238             values.put(BrowserContract.History.DATE_LAST_VISITED, System.currentTimeMillis());
  1239             values.put(BrowserContract.History.TITLE, TEST_TITLE);
  1241             updated = mProvider.update(updateOrInsertHistoryUri, values,
  1242                                        BrowserContract.History._ID + " = ?",
  1243                                        new String[] { String.valueOf(id) });
  1244             mAsserter.is((updated == 1), true, "Inserted history entry was updated");
  1245             c.close();
  1247             c = getHistoryEntryById(id);
  1248             mAsserter.is(c.moveToFirst(), true, "Updated history entry found");
  1250             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), TEST_TITLE,
  1251                          "Updated history entry has correct title");
  1252             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.VISITS))), new Long(2),
  1253                          "Updated history entry has correct number of visits");
  1254             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED))), new Long(dateCreated),
  1255                          "Updated history entry has same creation date");
  1256             mAsserter.isnot(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED))), new Long(dateModified),
  1257                             "Updated history entry has new modification date");
  1259             // Create a new history entry, specifying visits and history
  1260             values = new ContentValues();
  1261             values.put(BrowserContract.History.URL, TEST_URL_2);
  1262             values.put(BrowserContract.History.TITLE, TEST_TITLE);
  1263             values.put(BrowserContract.History.VISITS, 10);
  1265             updated = mProvider.update(updateOrInsertHistoryUri, values,
  1266                                            BrowserContract.History.URL + " = ?",
  1267                                            new String[] { values.getAsString(BrowserContract.History.URL) });
  1268             mAsserter.is((updated == 1), true, "History entry was inserted");
  1270             id = getHistoryEntryIdByUrl(TEST_URL_2);
  1271             c.close();
  1273             c = getHistoryEntryById(id);
  1274             mAsserter.is(c.moveToFirst(), true, "History entry was inserted");
  1276             dateCreated = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED));
  1277             dateModified = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED));
  1279             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.VISITS))), new Long(10),
  1280                          "Inserted history entry has correct specified number of visits");
  1281             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), TEST_TITLE,
  1282                          "Inserted history entry has correct specified title");
  1284             // Update the history entry, specifying additional visit count
  1285             values = new ContentValues();
  1286             values.put(BrowserContract.History.VISITS, 10);
  1288             updated = mProvider.update(updateOrInsertHistoryUri, values,
  1289                                        BrowserContract.History._ID + " = ?",
  1290                                        new String[] { String.valueOf(id) });
  1291             mAsserter.is((updated == 1), true, "Inserted history entry was updated");
  1292             c.close();
  1294             c = getHistoryEntryById(id);
  1295             mAsserter.is(c.moveToFirst(), true, "Updated history entry found");
  1297             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), TEST_TITLE,
  1298                          "Updated history entry has correct unchanged title");
  1299             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.URL)), TEST_URL_2,
  1300                          "Updated history entry has correct unchanged URL");
  1301             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.VISITS))), new Long(20),
  1302                          "Updated history entry has correct number of visits");
  1303             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED))), new Long(dateCreated),
  1304                          "Updated history entry has same creation date");
  1305             mAsserter.isnot(new Long(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED))), new Long(dateModified),
  1306                             "Updated history entry has new modification date");
  1307             c.close();
  1312     private class TestInsertHistoryThumbnails extends TestCase {
  1313         @Override
  1314         public void test() throws Exception {
  1315             ContentValues h = createOneHistoryEntry();
  1317             final String thumbnail = "THUMBNAIL";
  1318             final String pageUrl = h.getAsString(BrowserContract.History.URL);
  1320             long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h));
  1322             // Insert the thumbnail into the thumbnails table
  1323             mProvider.insert(BrowserContract.Thumbnails.CONTENT_URI, createThumbnailEntry(pageUrl, thumbnail));
  1325             Cursor c = getThumbnailByUrl(pageUrl);
  1326             mAsserter.is(c.moveToFirst(), true, "Inserted thumbnail found");
  1328             mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Thumbnails.DATA)), "UTF8"),
  1329                          thumbnail, "Inserted thumbnail has corresponding thumbnail image");
  1330             c.close();
  1334     private class TestUpdateHistoryThumbnails extends TestCase {
  1335         @Override
  1336         public void test() throws Exception {
  1337             ContentValues h = createOneHistoryEntry();
  1339             final String thumbnail = "THUMBNAIL";
  1340             final String newThumbnail = "NEW_THUMBNAIL";
  1341             final String pageUrl = h.getAsString(BrowserContract.History.URL);
  1343             mProvider.insert(BrowserContract.History.CONTENT_URI, h);
  1345             // Insert the thumbnail into the thumbnails table
  1346             mProvider.insert(BrowserContract.Thumbnails.CONTENT_URI, createThumbnailEntry(pageUrl, thumbnail));
  1348             Cursor c = getThumbnailByUrl(pageUrl);
  1349             mAsserter.is(c.moveToFirst(), true, "Inserted thumbnail found");
  1351             mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Thumbnails.DATA)), "UTF8"),
  1352                          thumbnail, "Inserted thumbnail has corresponding thumbnail image");
  1354             ContentValues u = createThumbnailEntry(pageUrl, newThumbnail);
  1356             mProvider.update(BrowserContract.Thumbnails.CONTENT_URI, u, null, null);
  1357             c.close();
  1359             c = getThumbnailByUrl(pageUrl);
  1360             mAsserter.is(c.moveToFirst(), true, "Updated thumbnail found");
  1362             mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Thumbnails.DATA)), "UTF8"),
  1363                          newThumbnail, "Updated thumbnail has corresponding thumbnail image");
  1364             c.close();
  1368     private class TestDeleteHistoryThumbnails extends TestCase {
  1369         @Override
  1370         public void test() throws Exception {
  1371             ContentValues h = createOneHistoryEntry();
  1373             long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h));
  1374             final String pageUrl = h.getAsString(BrowserContract.History.URL);
  1376             // Insert the thumbnail into the thumbnails table
  1377             mProvider.insert(BrowserContract.Thumbnails.CONTENT_URI, createThumbnailEntry(pageUrl, "THUMBNAIL"));
  1379             Cursor c = getThumbnailByUrl(pageUrl);
  1380             mAsserter.is(c.moveToFirst(), true, "Inserted thumbnail found");
  1382             mProvider.delete(ContentUris.withAppendedId(BrowserContract.History.CONTENT_URI, id), null, null);
  1383             c.close();
  1385             c = getThumbnailByUrl(pageUrl);
  1386             mAsserter.is(c.moveToFirst(), false, "Thumbnail is deleted with last reference to it");
  1387             c.close();
  1391     private class TestCombinedView extends TestCase {
  1392         @Override
  1393         public void test() throws Exception {
  1394             final String TITLE_1 = "Test Page 1";
  1395             final String TITLE_2 = "Test Page 2";
  1396             final String TITLE_3_HISTORY = "Test Page 3 (History Entry)";
  1397             final String TITLE_3_BOOKMARK = "Test Page 3 (Bookmark Entry)";
  1398             final String TITLE_3_BOOKMARK2 = "Test Page 3 (Bookmark Entry 2)";
  1400             final String URL_1 = "http://example1.com";
  1401             final String URL_2 = "http://example2.com";
  1402             final String URL_3 = "http://example3.com";
  1404             final int VISITS = 10;
  1405             final long LAST_VISITED = System.currentTimeMillis();
  1407             // Create a basic history entry
  1408             ContentValues basicHistory = createHistoryEntry(TITLE_1, URL_1, VISITS, LAST_VISITED);
  1409             long basicHistoryId = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, basicHistory));
  1411             // Create a basic bookmark entry
  1412             ContentValues basicBookmark = createBookmark(TITLE_2, URL_2, mMobileFolderId,
  1413                 BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword");
  1414             long basicBookmarkId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, basicBookmark));
  1416             // Create a history entry and bookmark entry with the same URL to
  1417             // represent a visited bookmark
  1418             ContentValues combinedHistory = createHistoryEntry(TITLE_3_HISTORY, URL_3, VISITS, LAST_VISITED);
  1419             long combinedHistoryId = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, combinedHistory));
  1422             ContentValues combinedBookmark = createBookmark(TITLE_3_BOOKMARK, URL_3, mMobileFolderId,
  1423                 BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword");
  1424             long combinedBookmarkId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, combinedBookmark));
  1426             ContentValues combinedBookmark2 = createBookmark(TITLE_3_BOOKMARK2, URL_3, mMobileFolderId,
  1427                 BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword");
  1428             long combinedBookmarkId2 = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, combinedBookmark2));
  1430             // Create a bookmark folder to make sure it _doesn't_ show up in the results
  1431             ContentValues folderBookmark = createBookmark("", "", mMobileFolderId,
  1432                 BrowserContract.Bookmarks.TYPE_FOLDER, 0, "tags", "description", "keyword");
  1433             mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, folderBookmark);
  1435             // Sort entries by url so we can check them individually
  1436             Cursor c = mProvider.query(BrowserContract.Combined.CONTENT_URI, null, "", null, BrowserContract.Combined.URL);
  1438             mAsserter.is(c.getCount(), 3, "3 combined entries found");
  1440             // First combined entry is basic history entry
  1441             mAsserter.is(c.moveToFirst(), true, "Found basic history entry");
  1442             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined._ID))), new Long(0),
  1443                          "Combined _id column should always be 0");
  1444             // TODO: Should we change BrowserProvider to make this return -1, not 0?
  1445             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID))), new Long(0),
  1446                          "Bookmark id should be 0 for basic history entry");
  1447             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.HISTORY_ID))), new Long(basicHistoryId),
  1448                          "Basic history entry has correct history id");
  1449             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.TITLE)), TITLE_1,
  1450                          "Basic history entry has correct title");
  1451             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.URL)), URL_1,
  1452                          "Basic history entry has correct url");
  1453             mAsserter.is(c.getInt(c.getColumnIndex(BrowserContract.Combined.VISITS)), VISITS,
  1454                          "Basic history entry has correct number of visits");
  1455             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.DATE_LAST_VISITED))), new Long(LAST_VISITED),
  1456                          "Basic history entry has correct last visit time");
  1458             // Second combined entry is basic bookmark entry
  1459             mAsserter.is(c.moveToNext(), true, "Found basic bookmark entry");
  1460             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined._ID))), new Long(0),
  1461                          "Combined _id column should always be 0");
  1462             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID))), new Long(basicBookmarkId),
  1463                          "Basic bookmark entry has correct bookmark id");
  1464             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.HISTORY_ID))), new Long(-1),
  1465                          "History id should be -1 for basic bookmark entry");
  1466             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.TITLE)), TITLE_2,
  1467                          "Basic bookmark entry has correct title");
  1468             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.URL)), URL_2,
  1469                          "Basic bookmark entry has correct url");
  1470             mAsserter.is(c.getInt(c.getColumnIndex(BrowserContract.Combined.VISITS)), -1,
  1471                          "Visits should be -1 for basic bookmark entry");
  1472             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.DATE_LAST_VISITED))), new Long(-1),
  1473                          "Basic entry has correct last visit time");
  1475             // Third combined entry is a combined history/bookmark entry
  1476             mAsserter.is(c.moveToNext(), true, "Found third combined entry");
  1477             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined._ID))), new Long(0),
  1478                          "Combined _id column should always be 0");
  1479             // The bookmark data (bookmark_id and title) associated with the combined entry is non-deterministic,
  1480             // it might end up with data coming from any of the matching bookmark entries.
  1481             mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID)) == combinedBookmarkId ||
  1482                          c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID)) == combinedBookmarkId2, true,
  1483                          "Combined entry has correct bookmark id");
  1484             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.TITLE)).equals(TITLE_3_BOOKMARK) ||
  1485                          c.getString(c.getColumnIndex(BrowserContract.Combined.TITLE)).equals(TITLE_3_BOOKMARK2), true,
  1486                          "Combined entry has title corresponding to bookmark entry");
  1487             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.HISTORY_ID))), new Long(combinedHistoryId),
  1488                          "Combined entry has correct history id");
  1489             mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.URL)), URL_3,
  1490                          "Combined entry has correct url");
  1491             mAsserter.is(c.getInt(c.getColumnIndex(BrowserContract.Combined.VISITS)), VISITS,
  1492                          "Combined entry has correct number of visits");
  1493             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.DATE_LAST_VISITED))), new Long(LAST_VISITED),
  1494                          "Combined entry has correct last visit time");
  1495             c.close();
  1499     private class TestCombinedViewDisplay extends TestCase {
  1500         @Override
  1501         public void test() throws Exception {
  1502             final String TITLE_1 = "Test Page 1";
  1503             final String TITLE_2 = "Test Page 2";
  1504             final String TITLE_3_HISTORY = "Test Page 3 (History Entry)";
  1505             final String TITLE_3_BOOKMARK = "Test Page 3 (Bookmark Entry)";
  1506             final String TITLE_4 = "Test Page 4";
  1508             final String URL_1 = "http://example.com";
  1509             final String URL_2 = "http://example.org";
  1510             final String URL_3 = "http://examples2.com";
  1511             final String URL_4 = "http://readinglist.com";
  1513             final int VISITS = 10;
  1514             final long LAST_VISITED = System.currentTimeMillis();
  1516             // Create a basic history entry
  1517             ContentValues basicHistory = createHistoryEntry(TITLE_1, URL_1, VISITS, LAST_VISITED);
  1518             ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, basicHistory));
  1520             // Create a basic bookmark entry
  1521             ContentValues basicBookmark = createBookmark(TITLE_2, URL_2, mMobileFolderId,
  1522                 BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword");
  1523             mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, basicBookmark);
  1525             // Create a history entry and bookmark entry with the same URL to
  1526             // represent a visited bookmark
  1527             ContentValues combinedHistory = createHistoryEntry(TITLE_3_HISTORY, URL_3, VISITS, LAST_VISITED);
  1528             mProvider.insert(BrowserContract.History.CONTENT_URI, combinedHistory);
  1530             ContentValues combinedBookmark = createBookmark(TITLE_3_BOOKMARK, URL_3, mMobileFolderId,
  1531                 BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword");
  1532             mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, combinedBookmark);
  1534             // Create a reading list entries
  1535             int readingListId = BrowserContract.Bookmarks.FIXED_READING_LIST_ID;
  1536             ContentValues readingListItem = createBookmark(TITLE_3_BOOKMARK, URL_3, readingListId,
  1537                 BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword");
  1538             long readingListItemId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, readingListItem));
  1540             ContentValues readingListItem2 = createBookmark(TITLE_4, URL_4, readingListId,
  1541                 BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword");
  1542             long readingListItemId2 = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, readingListItem2));
  1544             Cursor c = mProvider.query(BrowserContract.Combined.CONTENT_URI, null, "", null, null);
  1545             mAsserter.is(c.getCount(), 4, "4 combined entries found");
  1547             while (c.moveToNext()) {
  1548                 long id = c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID));
  1550                 int display = c.getInt(c.getColumnIndex(BrowserContract.Combined.DISPLAY));
  1551                 int expectedDisplay = (id == readingListItemId || id == readingListItemId2 ? BrowserContract.Combined.DISPLAY_READER : BrowserContract.Combined.DISPLAY_NORMAL);
  1553                 mAsserter.is(new Integer(display), new Integer(expectedDisplay),
  1554                                  "Combined display column should always be DISPLAY_READER for the reading list item");
  1556             c.close();
  1560     private class TestCombinedViewWithDeletedBookmark extends TestCase {
  1561         @Override
  1562         public void test() throws Exception {
  1563             final String TITLE = "Test Page 1";
  1564             final String URL = "http://example.com";
  1565             final int VISITS = 10;
  1566             final long LAST_VISITED = System.currentTimeMillis();
  1568             // Create a combined history entry
  1569             ContentValues combinedHistory = createHistoryEntry(TITLE, URL, VISITS, LAST_VISITED);
  1570             mProvider.insert(BrowserContract.History.CONTENT_URI, combinedHistory);
  1572             // Create a combined bookmark entry
  1573             ContentValues combinedBookmark = createBookmark(TITLE, URL, mMobileFolderId,
  1574                 BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword");
  1575             long combinedBookmarkId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, combinedBookmark));
  1577             Cursor c = mProvider.query(BrowserContract.Combined.CONTENT_URI, null, "", null, null);
  1578             mAsserter.is(c.getCount(), 1, "1 combined entry found");
  1580             mAsserter.is(c.moveToFirst(), true, "Found combined entry with bookmark id");
  1581             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID))), new Long(combinedBookmarkId),
  1582                          "Bookmark id should be set correctly on combined entry");
  1584             int deleted = mProvider.delete(BrowserContract.Bookmarks.CONTENT_URI,
  1585                                            BrowserContract.Bookmarks._ID + " = ?",
  1586                                            new String[] { String.valueOf(combinedBookmarkId) });
  1588             mAsserter.is((deleted == 1), true, "Inserted combined bookmark was deleted");
  1589             c.close();
  1591             c = mProvider.query(BrowserContract.Combined.CONTENT_URI, null, "", null, null);
  1592             mAsserter.is(c.getCount(), 1, "1 combined entry found");
  1594             mAsserter.is(c.moveToFirst(), true, "Found combined entry without bookmark id");
  1595             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID))), new Long(0),
  1596                          "Bookmark id should not be set to removed bookmark id");
  1597             c.close();
  1601     private class TestCombinedViewWithDeletedReadingListItem extends TestCase {
  1602         @Override
  1603         public void test() throws Exception {
  1604             final String TITLE = "Test Page 1";
  1605             final String URL = "http://example.com";
  1606             final int VISITS = 10;
  1607             final long LAST_VISITED = System.currentTimeMillis();
  1609             // Create a combined history entry
  1610             ContentValues combinedHistory = createHistoryEntry(TITLE, URL, VISITS, LAST_VISITED);
  1611             mProvider.insert(BrowserContract.History.CONTENT_URI, combinedHistory);
  1613             // Create a combined bookmark entry
  1614             int readingListId = BrowserContract.Bookmarks.FIXED_READING_LIST_ID;
  1615             ContentValues combinedReadingListItem = createBookmark(TITLE, URL, readingListId,
  1616                 BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword");
  1617             long combinedReadingListItemId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, combinedReadingListItem));
  1619             Cursor c = mProvider.query(BrowserContract.Combined.CONTENT_URI, null, "", null, null);
  1620             mAsserter.is(c.getCount(), 1, "1 combined entry found");
  1622             mAsserter.is(c.moveToFirst(), true, "Found combined entry with bookmark id");
  1623             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID))), new Long(combinedReadingListItemId),
  1624                          "Bookmark id should be set correctly on combined entry");
  1625             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.DISPLAY))), new Long(BrowserContract.Combined.DISPLAY_READER),
  1626                          "Combined entry should have reader display type");
  1628             int deleted = mProvider.delete(BrowserContract.Bookmarks.CONTENT_URI,
  1629                                            BrowserContract.Bookmarks._ID + " = ?",
  1630                                            new String[] { String.valueOf(combinedReadingListItemId) });
  1632             mAsserter.is((deleted == 1), true, "Inserted combined reading list item was deleted");
  1633             c.close();
  1635             c = mProvider.query(BrowserContract.Combined.CONTENT_URI, null, "", null, null);
  1636             mAsserter.is(c.getCount(), 1, "1 combined entry found");
  1638             mAsserter.is(c.moveToFirst(), true, "Found combined entry without bookmark id");
  1639             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID))), new Long(0),
  1640                          "Bookmark id should not be set to removed bookmark id");
  1641             mAsserter.is(new Long(c.getLong(c.getColumnIndex(BrowserContract.Combined.DISPLAY))), new Long(BrowserContract.Combined.DISPLAY_NORMAL),
  1642                          "Combined entry should have reader display type");
  1643             c.close();
  1647     private class TestExpireHistory extends TestCase {
  1648         private void createFakeHistory(long timeShift, int count) {
  1649             // Insert a bunch of very new entries
  1650             ContentValues[] allVals = new ContentValues[count];
  1651             long time = System.currentTimeMillis() - timeShift;
  1652             for (int i = 0; i < count; i++) {
  1653                 allVals[i] = new ContentValues();
  1654                 allVals[i].put(BrowserContract.History.TITLE, "Test " + i);
  1655                 allVals[i].put(BrowserContract.History.URL, "http://www.test.org/" + i);
  1656                 allVals[i].put(BrowserContract.History.VISITS, i);
  1657                 allVals[i].put(BrowserContract.History.DATE_LAST_VISITED, time);
  1660             int inserts = mProvider.bulkInsert(BrowserContract.History.CONTENT_URI, allVals);
  1661             mAsserter.is(inserts, count, "Expected number of inserts matches");
  1663             // inserting a new entry sets the date created and modified automatically
  1664             // reset all of them
  1665             for (int i = 0; i < count; i++) {
  1666                 ContentValues cv = new ContentValues();
  1667                 cv.put(BrowserContract.History.DATE_CREATED, time);
  1668                 cv.put(BrowserContract.History.DATE_MODIFIED, time);
  1669                 mProvider.update(BrowserContract.History.CONTENT_URI, cv, BrowserContract.History.URL + " = ?",
  1670                                  new String[] { "http://www.test.org/" + i });
  1673             Cursor c = mProvider.query(BrowserContract.History.CONTENT_URI, null, "", null, null);
  1675             assertCountIsAndClose(c, count, count + " history entries found");
  1677             // add thumbnails for each entry
  1678             allVals = new ContentValues[count];
  1679             for (int i = 0; i < count; i++) {
  1680                 allVals[i] = new ContentValues();
  1681                 allVals[i].put(BrowserContract.Thumbnails.DATA, i);
  1682                 allVals[i].put(BrowserContract.Thumbnails.URL, "http://www.test.org/" + i);
  1685             inserts = mProvider.bulkInsert(BrowserContract.Thumbnails.CONTENT_URI, allVals);
  1686             mAsserter.is(inserts, count, "Expected number of inserts matches");
  1688             c = mProvider.query(BrowserContract.Thumbnails.CONTENT_URI, null, null, null, null);
  1689             assertCountIsAndClose(c, count, count + " thumbnails entries found");
  1692         @Override
  1693         public void test() throws Exception {
  1694             final int count = 3000;
  1695             final int thumbCount = 15;
  1697             // insert a bunch of new entries
  1698             createFakeHistory(0, count);
  1700             // expiring with a normal priority should not delete new entries
  1701             Uri url = appendUriParam(BrowserContract.History.CONTENT_OLD_URI, BrowserContract.PARAM_EXPIRE_PRIORITY, "NORMAL");
  1702             mProvider.delete(url, null, null);
  1703             Cursor c = mProvider.query(BrowserContract.History.CONTENT_URI, null, "", null, null);
  1704             assertCountIsAndClose(c, count, count + " history entries found");
  1706             // expiring with a normal priority should delete all but 10 thumbnails
  1707             c = mProvider.query(BrowserContract.Thumbnails.CONTENT_URI, null, null, null, null);
  1708             assertCountIsAndClose(c, thumbCount, thumbCount + " thumbnails found");
  1710             ensureEmptyDatabase();
  1712             // Insert a bunch of new entries.
  1713             createFakeHistory(0, count);
  1715             // Expiring with a aggressive priority should leave 500 entries.
  1716             url = appendUriParam(BrowserContract.History.CONTENT_OLD_URI, BrowserContract.PARAM_EXPIRE_PRIORITY, "AGGRESSIVE");
  1717             mProvider.delete(url, null, null);
  1719             c = mProvider.query(BrowserContract.History.CONTENT_URI, null, "", null, null);
  1720             assertCountIsAndClose(c, 500, "500 history entries found");
  1722             // Expiring with a aggressive priority should delete all but 10 thumbnails.
  1723             c = mProvider.query(BrowserContract.Thumbnails.CONTENT_URI, null, null, null, null);
  1724             assertCountIsAndClose(c, thumbCount, thumbCount + " thumbnails found");
  1726             ensureEmptyDatabase();
  1728             // Insert a bunch of entries with an old time created/modified.
  1729             long time = 1000L * 60L * 60L * 24L * 30L * 3L;
  1730             createFakeHistory(time, count);
  1732             // Expiring with an normal priority should remove at most 1000 entries,
  1733             // entries leaving at least 2000.
  1734             url = appendUriParam(BrowserContract.History.CONTENT_OLD_URI, BrowserContract.PARAM_EXPIRE_PRIORITY, "NORMAL");
  1735             mProvider.delete(url, null, null);
  1737             c = mProvider.query(BrowserContract.History.CONTENT_URI, null, "", null, null);
  1738             assertCountIsAndClose(c, 2000, "2000 history entries found");
  1740             // Expiring with a normal priority should delete all but 10 thumbnails.
  1741             c = mProvider.query(BrowserContract.Thumbnails.CONTENT_URI, null, null, null, null);
  1742             assertCountIsAndClose(c, thumbCount, thumbCount + " thumbnails found");
  1744             ensureEmptyDatabase();
  1745             // insert a bunch of entries with an old time created/modified
  1746             time = 1000L * 60L * 60L * 24L * 30L * 3L;
  1747             createFakeHistory(time, count);
  1749             // Expiring with an aggressive priority should remove old
  1750             // entries, leaving at least 500.
  1751             url = appendUriParam(BrowserContract.History.CONTENT_OLD_URI, BrowserContract.PARAM_EXPIRE_PRIORITY, "AGGRESSIVE");
  1752             mProvider.delete(url, null, null);
  1753             c = mProvider.query(BrowserContract.History.CONTENT_URI, null, "", null, null);
  1754             assertCountIsAndClose(c, 500, "500 history entries found");
  1756             // expiring with an aggressive priority should delete all but 10 thumbnails
  1757             c = mProvider.query(BrowserContract.Thumbnails.CONTENT_URI, null, null, null, null);
  1758             assertCountIsAndClose(c, thumbCount, thumbCount + " thumbnails found");
  1762     /*
  1763      * Verify that insert, update, delete, and bulkInsert operations
  1764      * notify the ambient content resolver.  Each operation calls the
  1765      * content resolver notifyChange method synchronously, so it is
  1766      * okay to test sequentially.
  1767      */
  1768     private class TestBrowserProviderNotifications extends TestCase {
  1769         public static final String LOGTAG = "TestBPNotifications";
  1771         protected void ensureOnlyChangeNotifiedStartsWith(Uri expectedUri, String operation) {
  1772             if (expectedUri == null) {
  1773                 throw new IllegalArgumentException("expectedUri must not be null");
  1776             if (mResolver.notifyChangeList.size() != 1) {
  1777                 // Log to help post-mortem debugging
  1778                 Log.w(LOGTAG, "after operation, notifyChangeList = " + mResolver.notifyChangeList);
  1781             mAsserter.is(Long.valueOf(mResolver.notifyChangeList.size()),
  1782                          Long.valueOf(1),
  1783                          "Content observer was notified exactly once by " + operation);
  1785             Uri uri = mResolver.notifyChangeList.poll();
  1787             mAsserter.isnot(uri,
  1788                             null,
  1789                             "Notification from " + operation + " was valid");
  1791             mAsserter.ok(uri.toString().startsWith(expectedUri.toString()),
  1792                          "Content observer was notified exactly once by " + operation,
  1793                          uri.toString() + " starts with expected prefix " + expectedUri);
  1796         @Override
  1797         public void test() throws Exception {
  1798             // Insert
  1799             final ContentValues h = createOneHistoryEntry();
  1801             mResolver.notifyChangeList.clear();
  1802             long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h));
  1804             mAsserter.isnot(Long.valueOf(id),
  1805                             Long.valueOf(-1),
  1806                             "Inserted item has valid id");
  1808             ensureOnlyChangeNotifiedStartsWith(BrowserContract.History.CONTENT_URI, "insert");
  1810             // Update
  1811             mResolver.notifyChangeList.clear();
  1812             h.put(BrowserContract.History.TITLE, "http://newexample.com");
  1814             long numUpdated = mProvider.update(BrowserContract.History.CONTENT_URI, h,
  1815                                                BrowserContract.History._ID + " = ?",
  1816                                                new String[] { String.valueOf(id) });
  1818             mAsserter.is(Long.valueOf(numUpdated),
  1819                          Long.valueOf(1),
  1820                          "Correct number of items are updated");
  1822             ensureOnlyChangeNotifiedStartsWith(BrowserContract.History.CONTENT_URI, "update");
  1824             // Delete
  1825             mResolver.notifyChangeList.clear();
  1826             long numDeleted = mProvider.delete(BrowserContract.History.CONTENT_URI, null, null);
  1828             mAsserter.is(Long.valueOf(numDeleted),
  1829                          Long.valueOf(1),
  1830                          "Correct number of items are deleted");
  1832             ensureOnlyChangeNotifiedStartsWith(BrowserContract.History.CONTENT_URI, "delete");
  1834             // Bulk insert
  1835             final ContentValues[] hs = new ContentValues[] { createOneHistoryEntry() };
  1837             mResolver.notifyChangeList.clear();
  1838             long numBulkInserted = mProvider.bulkInsert(BrowserContract.History.CONTENT_URI, hs);
  1840             mAsserter.is(Long.valueOf(numBulkInserted),
  1841                          Long.valueOf(1),
  1842                          "Correct number of items are bulkInserted");
  1844             ensureOnlyChangeNotifiedStartsWith(BrowserContract.History.CONTENT_URI, "bulkInsert");
  1848     /**
  1849      * Assert that the provided cursor has the expected number of rows,
  1850      * closing the cursor afterwards.
  1851      */
  1852     private void assertCountIsAndClose(Cursor c, int expectedCount, String message) {
  1853         try {
  1854             mAsserter.is(c.getCount(), expectedCount, message);
  1855         } finally {
  1856             c.close();

mercurial