// Copyright (c) 2011 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. #include <vector> #include "base/file_util.h" #include "base/path_service.h" #include "base/string_util.h" #include "base/memory/scoped_temp_dir.h" #include "base/utf_string_conversions.h" #include "chrome/browser/history/history.h" #include "chrome/browser/history/starred_url_database.h" #include "chrome/common/chrome_paths.h" #include "testing/gtest/include/gtest/gtest.h" namespace history { class StarredURLDatabaseTest : public testing::Test, public StarredURLDatabase { public: StarredURLDatabaseTest() { } void AddPage(const GURL& url) { URLRow row(url); row.set_visit_count(1); EXPECT_TRUE(AddURL(row)); } void CompareEntryByID(const StarredEntry& entry) { DCHECK(entry.id != 0); StarredEntry db_value; EXPECT_TRUE(GetStarredEntry(entry.id, &db_value)); EXPECT_EQ(entry.id, db_value.id); EXPECT_TRUE(entry.title == db_value.title); EXPECT_EQ(entry.date_added.ToTimeT(), db_value.date_added.ToTimeT()); EXPECT_EQ(entry.folder_id, db_value.folder_id); EXPECT_EQ(entry.parent_folder_id, db_value.parent_folder_id); EXPECT_EQ(entry.visual_order, db_value.visual_order); EXPECT_EQ(entry.type, db_value.type); EXPECT_EQ(entry.url_id, db_value.url_id); if (entry.type == StarredEntry::URL) EXPECT_TRUE(entry.url == db_value.url); } int GetStarredEntryCount() { DCHECK(db_.is_open()); std::vector<StarredEntry> entries; GetAllStarredEntries(&entries); return static_cast<int>(entries.size()); } StarID CreateStarredEntry(StarredEntry* entry) { return StarredURLDatabase::CreateStarredEntry(entry); } bool GetStarredEntry(StarID star_id, StarredEntry* entry) { return StarredURLDatabase::GetStarredEntry(star_id, entry); } bool EnsureStarredIntegrity() { return StarredURLDatabase::EnsureStarredIntegrity(); } private: // Test setup. void SetUp() { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); db_file_ = temp_dir_.path().AppendASCII("VisitTest.db"); file_util::Delete(db_file_, false); // Copy db file over that contains starred table. FilePath old_history_path; PathService::Get(chrome::DIR_TEST_DATA, &old_history_path); old_history_path = old_history_path.AppendASCII("bookmarks"); old_history_path = old_history_path.Append( FILE_PATH_LITERAL("History_with_empty_starred")); file_util::CopyFile(old_history_path, db_file_); EXPECT_TRUE(db_.Open(db_file_)); // Initialize the tables for this test. CreateURLTable(false); CreateMainURLIndex(); EnsureStarredIntegrity(); } void TearDown() { db_.Close(); } // Provided for URL/StarredURLDatabase. virtual sql::Connection& GetDB() { return db_; } ScopedTempDir temp_dir_; FilePath db_file_; sql::Connection db_; }; //----------------------------------------------------------------------------- TEST_F(StarredURLDatabaseTest, FixOrphanedFolder) { const int initial_count = GetStarredEntryCount(); // Create a folder that isn't parented to the other/bookmark folders. StarredEntry g_entry; g_entry.type = StarredEntry::USER_FOLDER; g_entry.parent_folder_id = 100; g_entry.visual_order = 10; g_entry.folder_id = 100; CreateStarredEntry(&g_entry); ASSERT_TRUE(EnsureStarredIntegrity()); // Make sure no new entries were added. ASSERT_EQ(initial_count + 1, GetStarredEntryCount()); // Make sure the folder was moved to the bookmark bar folder. ASSERT_TRUE(GetStarredEntry(g_entry.id, &g_entry)); ASSERT_EQ(HistoryService::kBookmarkBarID, g_entry.parent_folder_id); ASSERT_EQ(0, g_entry.visual_order); } TEST_F(StarredURLDatabaseTest, FixOrphanedBookmarks) { const int initial_count = GetStarredEntryCount(); // Create two bookmarks that aren't in a random folder no on the bookmark bar. StarredEntry entry1; entry1.parent_folder_id = 100; entry1.visual_order = 10; entry1.url = GURL("http://google.com/1"); CreateStarredEntry(&entry1); StarredEntry entry2; entry2.parent_folder_id = 101; entry2.visual_order = 20; entry2.url = GURL("http://google.com/2"); CreateStarredEntry(&entry2); ASSERT_TRUE(EnsureStarredIntegrity()); // Make sure no new entries were added. ASSERT_EQ(initial_count + 2, GetStarredEntryCount()); // Make sure the entries were moved to the bookmark bar and the visual order // order was updated appropriately. ASSERT_TRUE(GetStarredEntry(entry1.id, &entry1)); ASSERT_EQ(HistoryService::kBookmarkBarID, entry1.parent_folder_id); ASSERT_TRUE(GetStarredEntry(entry2.id, &entry2)); ASSERT_EQ(HistoryService::kBookmarkBarID, entry2.parent_folder_id); ASSERT_TRUE((entry1.visual_order == 0 && entry2.visual_order == 1) || (entry1.visual_order == 1 && entry2.visual_order == 0)); } TEST_F(StarredURLDatabaseTest, FixFolderCycleDepth0) { const int initial_count = GetStarredEntryCount(); // Create a folder that is parented to itself. StarredEntry entry1; entry1.folder_id = entry1.parent_folder_id = 100; entry1.visual_order = 10; entry1.type = StarredEntry::USER_FOLDER; CreateStarredEntry(&entry1); ASSERT_TRUE(EnsureStarredIntegrity()); // Make sure no new entries were added. ASSERT_EQ(initial_count + 1, GetStarredEntryCount()); // Make sure the folder were moved to the bookmark bar and the visual order // order was updated appropriately. ASSERT_TRUE(GetStarredEntry(entry1.id, &entry1)); ASSERT_EQ(HistoryService::kBookmarkBarID, entry1.parent_folder_id); ASSERT_EQ(0, entry1.visual_order); } TEST_F(StarredURLDatabaseTest, FixFolderCycleDepth1) { const int initial_count = GetStarredEntryCount(); StarredEntry entry1; entry1.folder_id = 100; entry1.parent_folder_id = 101; entry1.visual_order = 10; entry1.type = StarredEntry::USER_FOLDER; CreateStarredEntry(&entry1); StarredEntry entry2; entry2.folder_id = 101; entry2.parent_folder_id = 100; entry2.visual_order = 11; entry2.type = StarredEntry::USER_FOLDER; CreateStarredEntry(&entry2); ASSERT_TRUE(EnsureStarredIntegrity()); // Make sure no new entries were added. ASSERT_EQ(initial_count + 2, GetStarredEntryCount()); // Because the folders caused a cycle, entry1 is moved the bookmark bar, which // breaks the cycle. ASSERT_TRUE(GetStarredEntry(entry1.id, &entry1)); ASSERT_TRUE(GetStarredEntry(entry2.id, &entry2)); ASSERT_EQ(HistoryService::kBookmarkBarID, entry1.parent_folder_id); ASSERT_EQ(100, entry2.parent_folder_id); ASSERT_EQ(0, entry1.visual_order); ASSERT_EQ(0, entry2.visual_order); } TEST_F(StarredURLDatabaseTest, FixVisualOrder) { const int initial_count = GetStarredEntryCount(); // Star two urls. StarredEntry entry1; entry1.url = GURL("http://google.com/1"); entry1.parent_folder_id = HistoryService::kBookmarkBarID; entry1.visual_order = 5; CreateStarredEntry(&entry1); // Add url2 and star it. StarredEntry entry2; entry2.url = GURL("http://google.com/2"); entry2.parent_folder_id = HistoryService::kBookmarkBarID; entry2.visual_order = 10; CreateStarredEntry(&entry2); ASSERT_TRUE(EnsureStarredIntegrity()); // Make sure no new entries were added. ASSERT_EQ(initial_count + 2, GetStarredEntryCount()); StarredEntry entry; ASSERT_TRUE(GetStarredEntry(entry1.id, &entry)); entry1.visual_order = 0; CompareEntryByID(entry1); ASSERT_TRUE(GetStarredEntry(entry2.id, &entry)); entry2.visual_order = 1; CompareEntryByID(entry2); } TEST_F(StarredURLDatabaseTest, FixDuplicateFolderIDs) { const int initial_count = GetStarredEntryCount(); // Create two folders with the same folder id. StarredEntry entry1; entry1.type = StarredEntry::USER_FOLDER; entry1.folder_id = 10; entry1.parent_folder_id = HistoryService::kBookmarkBarID; CreateStarredEntry(&entry1); StarredEntry entry2 = entry1; CreateStarredEntry(&entry2); ASSERT_TRUE(EnsureStarredIntegrity()); // Make sure only one folder exists. ASSERT_EQ(initial_count + 1, GetStarredEntryCount()); StarredEntry entry; ASSERT_TRUE(GetStarredEntry(entry1.id, &entry) || GetStarredEntry(entry2.id, &entry)); } TEST_F(StarredURLDatabaseTest, RemoveStarredEntriesWithEmptyURL) { const int initial_count = GetStarredEntryCount(); StarredEntry entry; entry.url = GURL("http://google.com"); entry.title = UTF8ToUTF16("FOO"); entry.parent_folder_id = HistoryService::kBookmarkBarID; ASSERT_NE(0, CreateStarredEntry(&entry)); // Remove the URL. DeleteURLRow(entry.url_id); // Fix up the table. ASSERT_TRUE(EnsureStarredIntegrity()); // The entry we just created should have been nuked. ASSERT_EQ(initial_count, GetStarredEntryCount()); } } // namespace history