blob: be76ea7da9569137e0ccac5d859d7b4fde368933 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.bookmarks;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.SmallTest;
import android.support.test.rule.UiThreadTestRule;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.RetryOnFailure;
import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.test.ChromeBrowserTestRule;
import org.chromium.chrome.test.util.BookmarkTestUtil;
import org.chromium.components.bookmarks.BookmarkId;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
/**
* Tests for {@link BookmarkModel}, the data layer of bookmarks.
*/
@RetryOnFailure(message = "crbug.com/740786")
@RunWith(BaseJUnit4ClassRunner.class)
public class BookmarkModelTest {
@Rule
public final RuleChain mChain =
RuleChain.outerRule(new ChromeBrowserTestRule()).around(new UiThreadTestRule());
private static final int TIMEOUT_MS = 5000;
private BookmarkModel mBookmarkModel;
private BookmarkId mMobileNode;
private BookmarkId mOtherNode;
private BookmarkId mDesktopNode;
@Before
public void setUp() {
TestThreadUtils.runOnUiThreadBlocking(() -> {
Profile profile = Profile.getLastUsedRegularProfile();
mBookmarkModel = new BookmarkModel(profile);
mBookmarkModel.loadEmptyPartnerBookmarkShimForTesting();
});
BookmarkTestUtil.waitForBookmarkModelLoaded();
TestThreadUtils.runOnUiThreadBlocking(() -> {
mMobileNode = mBookmarkModel.getMobileFolderId();
mDesktopNode = mBookmarkModel.getDesktopFolderId();
mOtherNode = mBookmarkModel.getOtherFolderId();
});
}
@Test
@SmallTest
@UiThreadTest
@Feature({"Bookmark"})
public void testBookmarkPropertySetters() {
BookmarkId folderA = mBookmarkModel.addFolder(mMobileNode, 0, "a");
BookmarkId bookmarkA = addBookmark(mDesktopNode, 0, "a", "http://a.com");
BookmarkId bookmarkB = addBookmark(mMobileNode, 0, "a", "http://a.com");
BookmarkId bookmarkC = addBookmark(mOtherNode, 0, "a", "http://a.com");
BookmarkId bookmarkD = addBookmark(folderA, 0, "a", "http://a.com");
mBookmarkModel.setBookmarkTitle(folderA, "hauri");
Assert.assertEquals("hauri", mBookmarkModel.getBookmarkTitle(folderA));
mBookmarkModel.setBookmarkTitle(bookmarkA, "auri");
mBookmarkModel.setBookmarkUrl(bookmarkA, "http://auri.org/");
verifyBookmark(bookmarkA, "auri", "http://auri.org/", false, mDesktopNode);
mBookmarkModel.setBookmarkTitle(bookmarkB, "lauri");
mBookmarkModel.setBookmarkUrl(bookmarkB, "http://lauri.org/");
verifyBookmark(bookmarkB, "lauri", "http://lauri.org/", false, mMobileNode);
mBookmarkModel.setBookmarkTitle(bookmarkC, "mauri");
mBookmarkModel.setBookmarkUrl(bookmarkC, "http://mauri.org/");
verifyBookmark(bookmarkC, "mauri", "http://mauri.org/", false, mOtherNode);
mBookmarkModel.setBookmarkTitle(bookmarkD, "kauri");
mBookmarkModel.setBookmarkUrl(bookmarkD, "http://kauri.org/");
verifyBookmark(bookmarkD, "kauri", "http://kauri.org/", false, folderA);
}
@Test
@SmallTest
@UiThreadTest
@Feature({"Bookmark"})
public void testMoveBookmarks() {
BookmarkId bookmarkA = addBookmark(mDesktopNode, 0, "a", "http://a.com");
BookmarkId bookmarkB = addBookmark(mOtherNode, 0, "b", "http://b.com");
BookmarkId bookmarkC = addBookmark(mMobileNode, 0, "c", "http://c.com");
BookmarkId folderA = mBookmarkModel.addFolder(mOtherNode, 0, "fa");
BookmarkId folderB = mBookmarkModel.addFolder(mDesktopNode, 0, "fb");
BookmarkId folderC = mBookmarkModel.addFolder(mMobileNode, 0, "fc");
BookmarkId bookmarkAA = addBookmark(folderA, 0, "aa", "http://aa.com");
BookmarkId folderAA = mBookmarkModel.addFolder(folderA, 0, "faa");
HashSet<BookmarkId> movedBookmarks = new HashSet<BookmarkId>(6);
movedBookmarks.add(bookmarkA);
movedBookmarks.add(bookmarkB);
movedBookmarks.add(bookmarkC);
movedBookmarks.add(folderC);
movedBookmarks.add(folderB);
movedBookmarks.add(bookmarkAA);
mBookmarkModel.moveBookmarks(new ArrayList<BookmarkId>(movedBookmarks), folderAA);
// Order of the moved bookmarks is not tested.
verifyBookmarkListNoOrder(mBookmarkModel.getChildIDs(folderAA, true, true), movedBookmarks);
}
@Test
@SmallTest
@UiThreadTest
@Feature({"Bookmark"})
public void testMoveBookmarksToSameFolder() {
BookmarkId folder = mBookmarkModel.addFolder(mMobileNode, 0, "fc");
BookmarkId bookmarkA = addBookmark(folder, 0, "a", "http://a.com");
BookmarkId bookmarkB = addBookmark(folder, 1, "b", "http://b.com");
HashSet<BookmarkId> movedBookmarks = new HashSet<BookmarkId>(2);
movedBookmarks.add(bookmarkA);
movedBookmarks.add(bookmarkB);
mBookmarkModel.moveBookmarks(new ArrayList<BookmarkId>(movedBookmarks), folder);
// Order of the moved bookmarks is not tested.
verifyBookmarkListNoOrder(mBookmarkModel.getChildIDs(folder, true, true), movedBookmarks);
}
@Test
@SmallTest
@UiThreadTest
@Feature({"Bookmark"})
public void testDeleteBookmarks() {
BookmarkId bookmarkA = addBookmark(mDesktopNode, 0, "a", "http://a.com");
BookmarkId bookmarkB = addBookmark(mOtherNode, 0, "b", "http://b.com");
BookmarkId bookmarkC = addBookmark(mMobileNode, 0, "c", "http://c.com");
// Dete a single bookmark
mBookmarkModel.deleteBookmarks(bookmarkA);
Assert.assertNull(mBookmarkModel.getBookmarkById(bookmarkA));
Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkB));
Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkC));
mBookmarkModel.undo();
Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkA));
// Delete and undo deletion of multiple bookmarks.
mBookmarkModel.deleteBookmarks(bookmarkA, bookmarkB);
Assert.assertNull(mBookmarkModel.getBookmarkById(bookmarkA));
Assert.assertNull(mBookmarkModel.getBookmarkById(bookmarkB));
Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkC));
mBookmarkModel.undo();
Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkA));
Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkB));
Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkC));
}
@Test
@SmallTest
@UiThreadTest
@Feature({"Bookmark"})
public void testDeleteBookmarksRepeatedly() {
BookmarkId bookmarkA = addBookmark(mDesktopNode, 0, "a", "http://a.com");
BookmarkId bookmarkB = addBookmark(mOtherNode, 0, "b", "http://b.com");
BookmarkId bookmarkC = addBookmark(mMobileNode, 0, "c", "http://c.com");
mBookmarkModel.deleteBookmarks(bookmarkA);
// This line is problematic, see: https://crbug.com/824559
mBookmarkModel.deleteBookmarks(bookmarkA, bookmarkB);
Assert.assertNull(mBookmarkModel.getBookmarkById(bookmarkA));
Assert.assertNull(mBookmarkModel.getBookmarkById(bookmarkB));
Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkC));
// Only bookmark B should be undeleted here.
mBookmarkModel.undo();
Assert.assertNull(mBookmarkModel.getBookmarkById(bookmarkA));
Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkB));
Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkC));
}
@Test
@SmallTest
@UiThreadTest
@Feature({"Bookmark"})
public void testGetChildIDs() {
BookmarkId folderA = mBookmarkModel.addFolder(mMobileNode, 0, "fa");
HashSet<BookmarkId> expectedChildren = new HashSet<>();
expectedChildren.add(addBookmark(folderA, 0, "a", "http://a.com"));
expectedChildren.add(addBookmark(folderA, 0, "a", "http://a.com"));
expectedChildren.add(addBookmark(folderA, 0, "a", "http://a.com"));
expectedChildren.add(addBookmark(folderA, 0, "a", "http://a.com"));
BookmarkId folderAA = mBookmarkModel.addFolder(folderA, 0, "faa");
// urls only
verifyBookmarkListNoOrder(
mBookmarkModel.getChildIDs(folderA, false, true), expectedChildren);
// folders only
verifyBookmarkListNoOrder(mBookmarkModel.getChildIDs(folderA, true, false),
new HashSet<BookmarkId>(Arrays.asList(folderAA)));
// folders and urls
expectedChildren.add(folderAA);
verifyBookmarkListNoOrder(
mBookmarkModel.getChildIDs(folderA, true, true), expectedChildren);
}
// Moved from BookmarkBridgeTest
@Test
@SmallTest
@UiThreadTest
@Feature({"Bookmark"})
public void testAddBookmarksAndFolders() {
BookmarkId bookmarkA = addBookmark(mDesktopNode, 0, "a", "http://a.com");
verifyBookmark(bookmarkA, "a", "http://a.com/", false, mDesktopNode);
BookmarkId bookmarkB = addBookmark(mOtherNode, 0, "b", "http://b.com");
verifyBookmark(bookmarkB, "b", "http://b.com/", false, mOtherNode);
BookmarkId bookmarkC = addBookmark(mMobileNode, 0, "c", "http://c.com");
verifyBookmark(bookmarkC, "c", "http://c.com/", false, mMobileNode);
BookmarkId folderA = mBookmarkModel.addFolder(mOtherNode, 0, "fa");
verifyBookmark(folderA, "fa", null, true, mOtherNode);
BookmarkId folderB = mBookmarkModel.addFolder(mDesktopNode, 0, "fb");
verifyBookmark(folderB, "fb", null, true, mDesktopNode);
BookmarkId folderC = mBookmarkModel.addFolder(mMobileNode, 0, "fc");
verifyBookmark(folderC, "fc", null, true, mMobileNode);
BookmarkId bookmarkAA = addBookmark(folderA, 0, "aa", "http://aa.com");
verifyBookmark(bookmarkAA, "aa", "http://aa.com/", false, folderA);
BookmarkId folderAA = mBookmarkModel.addFolder(folderA, 0, "faa");
verifyBookmark(folderAA, "faa", null, true, folderA);
}
private BookmarkId addBookmark(final BookmarkId parent, final int index, final String title,
final String url) {
final AtomicReference<BookmarkId> result = new AtomicReference<BookmarkId>();
final Semaphore semaphore = new Semaphore(0);
TestThreadUtils.runOnUiThreadBlocking(() -> {
result.set(mBookmarkModel.addBookmark(parent, index, title, url));
semaphore.release();
});
try {
if (semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
return result.get();
} else {
return null;
}
} catch (InterruptedException e) {
return null;
}
}
private void verifyBookmark(BookmarkId idToVerify, String expectedTitle,
String expectedUrl, boolean isFolder, BookmarkId expectedParent) {
Assert.assertNotNull(idToVerify);
BookmarkItem item = mBookmarkModel.getBookmarkById(idToVerify);
Assert.assertEquals(expectedTitle, item.getTitle());
Assert.assertEquals(isFolder, item.isFolder());
if (!isFolder) Assert.assertEquals(expectedUrl, item.getUrl());
Assert.assertEquals(expectedParent, item.getParentId());
}
/**
* Before using this helper method, always make sure @param listToVerify does not contain
* duplicates.
*/
private void verifyBookmarkListNoOrder(List<BookmarkId> listToVerify,
HashSet<BookmarkId> expectedIds) {
HashSet<BookmarkId> expectedIdsCopy = new HashSet<>(expectedIds);
Assert.assertEquals(expectedIdsCopy.size(), listToVerify.size());
for (BookmarkId id : listToVerify) {
Assert.assertNotNull(id);
Assert.assertTrue("List contains wrong element: ", expectedIdsCopy.contains(id));
expectedIdsCopy.remove(id);
}
Assert.assertTrue(
"List does not contain some expected bookmarks: ", expectedIdsCopy.isEmpty());
}
}