Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
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;
1001 }
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();
1037 }
1038 }
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();
1060 }
1061 }
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;
1077 }
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();
1143 }
1144 }
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();
1177 }
1178 }
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;
1196 }
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();
1309 }
1310 }
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();
1331 }
1332 }
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();
1365 }
1366 }
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();
1388 }
1389 }
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();
1496 }
1497 }
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");
1555 }
1556 c.close();
1557 }
1558 }
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();
1598 }
1599 }
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();
1644 }
1645 }
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);
1658 }
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 });
1671 }
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);
1683 }
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");
1690 }
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");
1759 }
1760 }
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");
1774 }
1776 if (mResolver.notifyChangeList.size() != 1) {
1777 // Log to help post-mortem debugging
1778 Log.w(LOGTAG, "after operation, notifyChangeList = " + mResolver.notifyChangeList);
1779 }
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);
1794 }
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");
1845 }
1846 }
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();
1857 }
1858 }
1859 }