summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-10 23:44:50 +0000
committershess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-10 23:44:50 +0000
commit43ffdd8281b45450b010d8d3f44c6e7c4a55c216 (patch)
treea07179891a2c81c7fc7a69c984efacb1665a38e9
parent3b3a16b5915710431a8bad1d53dbf4867d8d1393 (diff)
downloadchromium_src-43ffdd8281b45450b010d8d3f44c6e7c4a55c216.zip
chromium_src-43ffdd8281b45450b010d8d3f44c6e7c4a55c216.tar.gz
chromium_src-43ffdd8281b45450b010d8d3f44c6e7c4a55c216.tar.bz2
Rewrite Thumbnail and Top Sites test with golden files.
Previously, the tests manually changes the current schema to look like an old schema, then targetted specific implementation functions. Change to instead create the schema from a golden file, testing that Init() works correctly, and the expected data is in place. BUG=none R=pkotwicz@chromium.org, sky@chromium.org Review URL: https://codereview.chromium.org/23536014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@222400 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/history/history_database.h4
-rw-r--r--chrome/browser/history/thumbnail_database.cc8
-rw-r--r--chrome/browser/history/thumbnail_database.h9
-rw-r--r--chrome/browser/history/thumbnail_database_unittest.cc546
-rw-r--r--chrome/browser/history/top_sites_database.cc5
-rw-r--r--chrome/browser/history/top_sites_database.h3
-rw-r--r--chrome/browser/history/top_sites_database_unittest.cc120
-rw-r--r--chrome/chrome_tests_unit.gypi2
-rw-r--r--chrome/test/data/History/Favicons.v3.history.sql (renamed from chrome/test/data/History/history.20.sql)14
-rw-r--r--chrome/test/data/History/Favicons.v3.sql16
-rw-r--r--chrome/test/data/History/Favicons.v4.sql21
-rw-r--r--chrome/test/data/History/Favicons.v5.sql21
-rw-r--r--chrome/test/data/History/Favicons.v6.sql26
-rw-r--r--chrome/test/data/History/Favicons.v7.sql26
-rw-r--r--chrome/test/data/History/TopSites.v1.sql13
-rw-r--r--chrome/test/data/History/TopSites.v2.sql13
-rw-r--r--chrome/test/data/History/thumbnails.3.sql9
-rw-r--r--sql/sql.gyp2
-rw-r--r--sql/test/test_helpers.cc75
-rw-r--r--sql/test/test_helpers.h45
20 files changed, 626 insertions, 352 deletions
diff --git a/chrome/browser/history/history_database.h b/chrome/browser/history/history_database.h
index 7c631cf..c0e27dc 100644
--- a/chrome/browser/history/history_database.h
+++ b/chrome/browser/history/history_database.h
@@ -172,7 +172,9 @@ class HistoryDatabase : public DownloadDatabase,
#endif
friend class ::HistoryQuickProviderTest;
friend class InMemoryURLIndexTest;
- FRIEND_TEST_ALL_PREFIXES(IconMappingMigrationTest, TestIconMappingMigration);
+ // This thumbnail migration test sidesteps full Init() to directly
+ // open |db_|.
+ FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version3);
// Overridden from URLDatabase:
virtual sql::Connection& GetDB() OVERRIDE;
diff --git a/chrome/browser/history/thumbnail_database.cc b/chrome/browser/history/thumbnail_database.cc
index 59d60a1..3014338 100644
--- a/chrome/browser/history/thumbnail_database.cc
+++ b/chrome/browser/history/thumbnail_database.cc
@@ -271,7 +271,15 @@ void DatabaseErrorCallback(sql::Connection* db,
namespace history {
+// Version 7: 911a634d/r209424 by qsr@chromium.org on 2013-07-01
+// Version 6: 610f923b/r152367 by pkotwicz@chromium.org on 2012-08-20
+// Version 5: e2ee8ae9/r105004 by groby@chromium.org on 2011-10-12
+// Version 4: 5f104d76/r77288 by sky@chromium.org on 2011-03-08
+// Version 3: 09911bf3/r15 by initial.commit on 2008-07-26
+
// Version number of the database.
+// NOTE(shess): When changing the version, add a new golden file for
+// the new version and a test to verify that Init() works with it.
static const int kCurrentVersionNumber = 7;
static const int kCompatibleVersionNumber = 7;
diff --git a/chrome/browser/history/thumbnail_database.h b/chrome/browser/history/thumbnail_database.h
index d407897..6db3b9c 100644
--- a/chrome/browser/history/thumbnail_database.h
+++ b/chrome/browser/history/thumbnail_database.h
@@ -252,10 +252,11 @@ class ThumbnailDatabase {
friend class ExpireHistoryBackend;
FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest,
GetFaviconAfterMigrationToTopSites);
- FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, UpgradeToVersion4);
- FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, UpgradeToVersion5);
- FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, UpgradeToVersion6);
- FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, UpgradeToVersion7);
+ FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version3);
+ FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version4);
+ FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version5);
+ FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version6);
+ FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version7);
FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, RetainDataForPageUrls);
FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, MigrationIconMapping);
diff --git a/chrome/browser/history/thumbnail_database_unittest.cc b/chrome/browser/history/thumbnail_database_unittest.cc
index 75758e7..6d420b0 100644
--- a/chrome/browser/history/thumbnail_database_unittest.cc
+++ b/chrome/browser/history/thumbnail_database_unittest.cc
@@ -6,48 +6,144 @@
#include <vector>
#include "base/basictypes.h"
-#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted_memory.h"
#include "base/path_service.h"
#include "chrome/browser/history/history_database.h"
-#include "chrome/browser/history/history_unittest_base.h"
#include "chrome/browser/history/thumbnail_database.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
-#include "chrome/common/thumbnail_score.h"
#include "chrome/test/base/testing_profile.h"
-#include "chrome/tools/profiles/thumbnail-inl.h"
+#include "sql/connection.h"
+#include "sql/statement.h"
+#include "sql/test/test_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/gfx/codec/jpeg_codec.h"
#include "url/gurl.h"
-using base::Time;
-using base::TimeDelta;
-
namespace history {
namespace {
-// data we'll put into the thumbnail database
-static const unsigned char blob1[] =
+// Blobs for the bitmap tests. These aren't real bitmaps. Golden
+// database files store the same blobs (see VersionN tests).
+const unsigned char kBlob1[] =
"12346102356120394751634516591348710478123649165419234519234512349134";
-static const unsigned char blob2[] =
+const unsigned char kBlob2[] =
"goiwuegrqrcomizqyzkjalitbahxfjytrqvpqeroicxmnlkhlzunacxaneviawrtxcywhgef";
-static const unsigned char blob3[] =
- "3716871354098370776510470746794707624107647054607467847164027";
-const double kBoringness = 0.25;
-const double kWorseBoringness = 0.50;
-const double kBetterBoringness = 0.10;
-const double kTotallyBoring = 1.0;
-const int64 kPage1 = 1234;
+// Page and icon urls shared by tests. Present in golden database
+// files (see VersionN tests).
+const GURL kPageUrl1 = GURL("http://google.com/");
+const GURL kPageUrl2 = GURL("http://yahoo.com/");
+const GURL kPageUrl3 = GURL("http://www.google.com/");
+const GURL kPageUrl4 = GURL("http://www.google.com/blank.html");
+
+const GURL kIconUrl1 = GURL("http://www.google.com/favicon.ico");
+const GURL kIconUrl2 = GURL("http://www.yahoo.com/favicon.ico");
+const GURL kIconUrl3 = GURL("http://www.google.com/touch.ico");
const gfx::Size kSmallSize = gfx::Size(16, 16);
const gfx::Size kLargeSize = gfx::Size(32, 32);
+// Create the test database at |db_path| from the golden file at
+// |ascii_path| in the "History/" subdir of the test data dir.
+WARN_UNUSED_RESULT bool CreateDatabaseFromSQL(const base::FilePath &db_path,
+ const char* ascii_path) {
+ base::FilePath sql_path;
+ if (!PathService::Get(chrome::DIR_TEST_DATA, &sql_path))
+ return false;
+ sql_path = sql_path.AppendASCII("History").AppendASCII(ascii_path);
+ return sql::test::CreateDatabaseFromSQL(db_path, sql_path);
+}
+
+// Verify that the up-to-date database has the expected tables and
+// columns. Functional tests only check whether the things which
+// should be there are, but do not check if extraneous items are
+// present. Any extraneous items have the potential to interact
+// negatively with future schema changes.
+void VerifyTablesAndColumns(sql::Connection* db) {
+ // [meta], [favicons], [favicon_bitmaps], and [icon_mapping].
+ EXPECT_EQ(4u, sql::test::CountSQLTables(db));
+
+ // Implicit index on [meta], index on [favicons], index on
+ // [favicon_bitmaps], two indices on [icon_mapping].
+ EXPECT_EQ(5u, sql::test::CountSQLIndices(db));
+
+ // [key] and [value].
+ EXPECT_EQ(2u, sql::test::CountTableColumns(db, "meta"));
+
+ // [id], [url], and [icon_type].
+ EXPECT_EQ(3u, sql::test::CountTableColumns(db, "favicons"));
+
+ // [id], [icon_id], [last_updated], [image_data], [width], and [height].
+ EXPECT_EQ(6u, sql::test::CountTableColumns(db, "favicon_bitmaps"));
+
+ // [id], [page_url], and [icon_id].
+ EXPECT_EQ(3u, sql::test::CountTableColumns(db, "icon_mapping"));
+}
+
+// Helper to check that an expected mapping exists.
+WARN_UNUSED_RESULT bool CheckPageHasIcon(
+ ThumbnailDatabase* db,
+ const GURL& page_url,
+ chrome::IconType expected_icon_type,
+ const GURL& expected_icon_url,
+ const gfx::Size& expected_icon_size,
+ size_t expected_icon_contents_size,
+ const unsigned char* expected_icon_contents) {
+ std::vector<IconMapping> icon_mappings;
+ if (!db->GetIconMappingsForPageURL(page_url, &icon_mappings)) {
+ ADD_FAILURE() << "failed GetIconMappingsForPageURL()";
+ return false;
+ }
+
+ // Scan for the expected type.
+ std::vector<IconMapping>::const_iterator iter = icon_mappings.begin();
+ for (; iter != icon_mappings.end(); ++iter) {
+ if (iter->icon_type == expected_icon_type)
+ break;
+ }
+ if (iter == icon_mappings.end()) {
+ ADD_FAILURE() << "failed to find |expected_icon_type|";
+ return false;
+ }
+
+ if (expected_icon_url != iter->icon_url) {
+ EXPECT_EQ(expected_icon_url, iter->icon_url);
+ return false;
+ }
+
+ std::vector<FaviconBitmap> favicon_bitmaps;
+ if (!db->GetFaviconBitmaps(iter->icon_id, &favicon_bitmaps)) {
+ ADD_FAILURE() << "failed GetFaviconBitmaps()";
+ return false;
+ }
+
+ if (1 != favicon_bitmaps.size()) {
+ EXPECT_EQ(1u, favicon_bitmaps.size());
+ return false;
+ }
+
+ if (expected_icon_size != favicon_bitmaps[0].pixel_size) {
+ EXPECT_EQ(expected_icon_size, favicon_bitmaps[0].pixel_size);
+ return false;
+ }
+
+ if (expected_icon_contents_size != favicon_bitmaps[0].bitmap_data->size()) {
+ EXPECT_EQ(expected_icon_contents_size,
+ favicon_bitmaps[0].bitmap_data->size());
+ return false;
+ }
+
+ if (memcmp(favicon_bitmaps[0].bitmap_data->front(),
+ expected_icon_contents, expected_icon_contents_size)) {
+ ADD_FAILURE() << "failed to match |expected_icon_contents|";
+ return false;
+ }
+ return true;
+}
+
} // namespace
class ThumbnailDatabaseTest : public testing::Test {
@@ -57,58 +153,35 @@ class ThumbnailDatabaseTest : public testing::Test {
virtual ~ThumbnailDatabaseTest() {
}
+ // Initialize a thumbnail database instance from the SQL file at
+ // |golden_path| in the "History/" subdirectory of test data.
+ // |url_db| is passed into Init().
+ // TODO(shess): If/when version3 is deprecated, url_db can be removed
+ // from Init(). At that point CreateDatabaseFromSQL() can be inlined.
+ scoped_ptr<ThumbnailDatabase> LoadFromGolden(const char* golden_path,
+ URLDatabase* url_db) {
+ if (!CreateDatabaseFromSQL(file_name_, golden_path)) {
+ ADD_FAILURE() << "Failed loading " << golden_path;
+ return scoped_ptr<ThumbnailDatabase>();
+ }
+
+ scoped_ptr<ThumbnailDatabase> db(new ThumbnailDatabase());
+ EXPECT_EQ(sql::INIT_OK, db->Init(file_name_, NULL, url_db));
+ db->BeginTransaction();
+
+ return db.Pass();
+ }
+
protected:
virtual void SetUp() {
// Get a temporary directory for the test DB files.
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- file_name_ = temp_dir_.path().AppendASCII("TestThumbnails.db");
- new_file_name_ = temp_dir_.path().AppendASCII("TestFavicons.db");
- history_db_name_ = temp_dir_.path().AppendASCII("TestHistory.db");
- google_bitmap_.reset(
- gfx::JPEGCodec::Decode(kGoogleThumbnail, sizeof(kGoogleThumbnail)));
+ file_name_ = temp_dir_.path().AppendASCII("TestFavicons.db");
}
- scoped_ptr<SkBitmap> google_bitmap_;
-
base::ScopedTempDir temp_dir_;
base::FilePath file_name_;
- base::FilePath new_file_name_;
- base::FilePath history_db_name_;
-};
-
-class IconMappingMigrationTest : public HistoryUnitTestBase {
- public:
- IconMappingMigrationTest() {
- }
- virtual ~IconMappingMigrationTest() {
- }
-
- protected:
- virtual void SetUp() {
- profile_.reset(new TestingProfile);
-
- base::FilePath data_path;
- ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path));
- data_path = data_path.AppendASCII("History");
-
- history_db_name_ = profile_->GetPath().Append(chrome::kHistoryFilename);
- ASSERT_NO_FATAL_FAILURE(
- ExecuteSQLScript(data_path.AppendASCII("history.20.sql"),
- history_db_name_));
- thumbnail_db_name_ =
- profile_->GetPath().Append(chrome::kFaviconsFilename);
- ASSERT_NO_FATAL_FAILURE(
- ExecuteSQLScript(data_path.AppendASCII("thumbnails.3.sql"),
- thumbnail_db_name_));
- }
-
- protected:
- base::FilePath history_db_name_;
- base::FilePath thumbnail_db_name_;
-
- private:
- scoped_ptr<TestingProfile> profile_;
};
TEST_F(ThumbnailDatabaseTest, AddIconMapping) {
@@ -116,7 +189,7 @@ TEST_F(ThumbnailDatabaseTest, AddIconMapping) {
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
- std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
+ std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
GURL url("http://google.com");
@@ -170,7 +243,7 @@ TEST_F(ThumbnailDatabaseTest, DeleteIconMappings) {
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
- std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
+ std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
GURL url("http://google.com");
@@ -202,7 +275,7 @@ TEST_F(ThumbnailDatabaseTest, GetIconMappingsForPageURL) {
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
- std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
+ std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
GURL url("http://google.com");
@@ -225,190 +298,6 @@ TEST_F(ThumbnailDatabaseTest, GetIconMappingsForPageURL) {
EXPECT_EQ(id2, icon_mappings[1].icon_id);
}
-// Test upgrading database to version 4.
-TEST_F(ThumbnailDatabaseTest, UpgradeToVersion4) {
- ThumbnailDatabase db;
- ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
- db.BeginTransaction();
-
- const char* name = "favicons";
- std::string sql;
- sql.append("DROP TABLE IF EXISTS ");
- sql.append(name);
- EXPECT_TRUE(db.db_.Execute(sql.c_str()));
-
- sql.resize(0);
- sql.append("CREATE TABLE ");
- sql.append(name);
- sql.append("("
- "id INTEGER PRIMARY KEY,"
- "url LONGVARCHAR NOT NULL,"
- "last_updated INTEGER DEFAULT 0,"
- "image_data BLOB)");
- EXPECT_TRUE(db.db_.Execute(sql.c_str()));
-
- EXPECT_TRUE(db.UpgradeToVersion4());
-
- GURL url("http://google.com");
-
- sql::Statement statement;
- statement.Assign(db.db_.GetCachedStatement(SQL_FROM_HERE,
- "INSERT INTO favicons (url, icon_type) VALUES (?, ?)"));
- statement.BindString(0, URLDatabase::GURLToDatabaseURL(url));
- statement.BindInt(1, chrome::TOUCH_ICON);
- EXPECT_TRUE(statement.Run());
-
- statement.Assign(db.db_.GetCachedStatement(SQL_FROM_HERE,
- "SELECT icon_type FROM favicons"));
- EXPECT_TRUE(statement.Step());
-
- EXPECT_EQ(chrome::TOUCH_ICON,
- static_cast<chrome::IconType>(statement.ColumnInt(0)));
-}
-
-// Test upgrading database to version 5.
-TEST_F(ThumbnailDatabaseTest, UpgradeToVersion5) {
- ThumbnailDatabase db;
- ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
- db.BeginTransaction();
-
- const char* name = "favicons";
- std::string sql;
- sql.append("DROP TABLE IF EXISTS ");
- sql.append(name);
- EXPECT_TRUE(db.db_.Execute(sql.c_str()));
-
- sql.resize(0);
- sql.append("CREATE TABLE ");
- sql.append(name);
- sql.append("("
- "id INTEGER PRIMARY KEY,"
- "url LONGVARCHAR NOT NULL,"
- "last_updated INTEGER DEFAULT 0,"
- "image_data BLOB,"
- "icon_type INTEGER DEFAULT 1)");
- ASSERT_TRUE(db.db_.Execute(sql.c_str()));
-
- ASSERT_TRUE(db.UpgradeToVersion5());
-
- sql = "SELECT sizes FROM favicons";
- EXPECT_TRUE(db.db_.Execute(sql.c_str()));
-}
-
-// Test upgrading database to version 6.
-TEST_F(ThumbnailDatabaseTest, UpgradeToVersion6) {
- ThumbnailDatabase db;
- ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
- db.BeginTransaction();
-
- const char* name = "favicons";
- std::string sql;
- sql.append("DROP TABLE IF EXISTS ");
- sql.append(name);
- EXPECT_TRUE(db.db_.Execute(sql.c_str()));
-
- sql.clear();
- sql.append("CREATE TABLE ");
- sql.append(name);
- sql.append("("
- "id INTEGER PRIMARY KEY,"
- "url LONGVARCHAR NOT NULL,"
- "last_updated INTEGER DEFAULT 0,"
- "image_data BLOB,"
- "icon_type INTEGER DEFAULT 1,"
- "sizes LONGVARCHAR)");
- EXPECT_TRUE(db.db_.Execute(sql.c_str()));
-
- int favicon_id = 1;
- GURL url("http://google.com");
- int64 last_updated = Time::Now().ToInternalValue();
- std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
- scoped_refptr<base::RefCountedBytes> bitmap_data(
- new base::RefCountedBytes(data));
-
- sql::Statement statement;
- statement.Assign(db.db_.GetCachedStatement(SQL_FROM_HERE,
- "INSERT INTO favicons (id, url, last_updated, image_data, icon_type, "
- "sizes) VALUES (?, ?, ?, ?, ?, ?)"));
- statement.BindInt(0, favicon_id);
- statement.BindString(1, URLDatabase::GURLToDatabaseURL(url));
- statement.BindInt64(2, last_updated);
- statement.BindBlob(3, bitmap_data->front(),
- static_cast<int>(bitmap_data->size()));
- statement.BindInt(4, chrome::TOUCH_ICON);
- statement.BindCString(5, "Data which happened to be there");
- EXPECT_TRUE(statement.Run());
-
- EXPECT_TRUE(db.UpgradeToVersion6());
-
- statement.Assign(db.db_.GetCachedStatement(SQL_FROM_HERE,
- "SELECT id, url, icon_type, sizes FROM favicons"));
- EXPECT_TRUE(statement.Step());
- EXPECT_EQ(favicon_id, statement.ColumnInt(0));
- EXPECT_EQ(url, GURL(statement.ColumnString(1)));
- EXPECT_EQ(chrome::TOUCH_ICON, statement.ColumnInt(2));
- // Any previous data in sizes should be cleared.
- EXPECT_EQ(std::string(), statement.ColumnString(3));
-
- statement.Assign(db.db_.GetCachedStatement(SQL_FROM_HERE,
- "SELECT icon_id, last_updated, image_data, width, height "
- "FROM favicon_bitmaps"));
- EXPECT_TRUE(statement.Step());
- EXPECT_EQ(favicon_id, statement.ColumnInt(0));
- EXPECT_EQ(last_updated, statement.ColumnInt64(1));
- EXPECT_EQ(static_cast<int>(bitmap_data->size()),
- statement.ColumnByteLength(2));
- EXPECT_EQ(0, statement.ColumnInt(3));
- EXPECT_EQ(0, statement.ColumnInt(4));
-}
-
-// Test upgrading database to version 7.
-TEST_F(ThumbnailDatabaseTest, UpgradeToVersion7) {
- ThumbnailDatabase db;
- ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
- db.BeginTransaction();
-
- const char* name = "favicons";
- std::string sql;
- sql.append("DROP TABLE IF EXISTS ");
- sql.append(name);
- EXPECT_TRUE(db.db_.Execute(sql.c_str()));
-
- sql.clear();
- sql.append("CREATE TABLE ");
- sql.append(name);
- sql.append("("
- "id INTEGER PRIMARY KEY,"
- "url LONGVARCHAR NOT NULL,"
- "icon_type INTEGER DEFAULT 1,"
- "sizes LONGVARCHAR)");
- EXPECT_TRUE(db.db_.Execute(sql.c_str()));
-
- int favicon_id = 1;
- GURL url("http://google.com");
-
- sql::Statement statement;
- statement.Assign(db.db_.GetCachedStatement(SQL_FROM_HERE,
- "INSERT INTO favicons (id, url, icon_type, sizes) "
- "VALUES (?, ?, ?, ?)"));
- statement.BindInt(0, favicon_id);
- statement.BindString(1, URLDatabase::GURLToDatabaseURL(url));
- statement.BindInt(2, chrome::TOUCH_ICON);
- statement.BindCString(3, "Data which happened to be there");
- EXPECT_TRUE(statement.Run());
-
- EXPECT_TRUE(db.UpgradeToVersion7());
-
- EXPECT_FALSE(db.db_.DoesColumnExist("favicons", "sizes"));
-
- statement.Assign(db.db_.GetCachedStatement(SQL_FROM_HERE,
- "SELECT id, url, icon_type FROM favicons"));
- EXPECT_TRUE(statement.Step());
- EXPECT_EQ(favicon_id, statement.ColumnInt(0));
- EXPECT_EQ(url, GURL(statement.ColumnString(1)));
- EXPECT_EQ(chrome::TOUCH_ICON, statement.ColumnInt(2));
-}
-
TEST_F(ThumbnailDatabaseTest, RetainDataForPageUrls) {
ThumbnailDatabase db;
@@ -416,7 +305,7 @@ TEST_F(ThumbnailDatabaseTest, RetainDataForPageUrls) {
db.BeginTransaction();
- std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
+ std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
GURL unkept_url("http://google.com/favicon2.ico");
@@ -465,10 +354,10 @@ TEST_F(ThumbnailDatabaseTest, DeleteFavicon) {
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
- std::vector<unsigned char> data1(blob1, blob1 + sizeof(blob1));
+ std::vector<unsigned char> data1(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon1(
new base::RefCountedBytes(data1));
- std::vector<unsigned char> data2(blob2, blob2 + sizeof(blob2));
+ std::vector<unsigned char> data2(kBlob2, kBlob2 + sizeof(kBlob2));
scoped_refptr<base::RefCountedBytes> favicon2(
new base::RefCountedBytes(data2));
@@ -490,7 +379,7 @@ TEST_F(ThumbnailDatabaseTest, GetIconMappingsForPageURLForReturnOrder) {
db.BeginTransaction();
// Add a favicon
- std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
+ std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
GURL page_url("http://google.com");
@@ -512,7 +401,7 @@ TEST_F(ThumbnailDatabaseTest, GetIconMappingsForPageURLForReturnOrder) {
EXPECT_EQ(icon_url, icon_mappings.front().icon_url);
// Add a touch icon
- std::vector<unsigned char> data2(blob2, blob2 + sizeof(blob2));
+ std::vector<unsigned char> data2(kBlob2, kBlob2 + sizeof(kBlob2));
scoped_refptr<base::RefCountedBytes> favicon2 =
new base::RefCountedBytes(data);
@@ -558,7 +447,7 @@ TEST_F(ThumbnailDatabaseTest, GetIconMappingsForPageURLWithIconType) {
db.BeginTransaction();
GURL url("http://google.com");
- std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
+ std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
base::Time time = base::Time::Now();
@@ -621,7 +510,7 @@ TEST_F(ThumbnailDatabaseTest, HasMappingFor) {
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
- std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
+ std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
// Add a favicon which will have icon_mappings
@@ -672,7 +561,7 @@ TEST_F(ThumbnailDatabaseTest, CloneIconMappings) {
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
- std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
+ std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
// Add a favicon which will have icon_mappings
@@ -732,60 +621,12 @@ TEST_F(ThumbnailDatabaseTest, CloneIconMappings) {
EXPECT_EQ(id2, icon_mapping[1].icon_id);
}
-TEST_F(IconMappingMigrationTest, TestIconMappingMigration) {
- HistoryDatabase history_db;
- ASSERT_TRUE(history_db.db_.Open(history_db_name_));
- history_db.BeginTransaction();
-
- const GURL icon1 = GURL("http://www.google.com/favicon.ico");
- const GURL icon2 = GURL("http://www.yahoo.com/favicon.ico");
-
- ThumbnailDatabase db;
- ASSERT_EQ(sql::INIT_OK, db.Init(thumbnail_db_name_, NULL, &history_db));
- db.BeginTransaction();
-
- // Migration should be done.
- // Test one icon_mapping.
- GURL page_url1 = GURL("http://google.com/");
- std::vector<IconMapping> icon_mappings;
- EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url1, &icon_mappings));
- ASSERT_EQ(1u, icon_mappings.size());
- EXPECT_EQ(chrome::FAVICON, icon_mappings[0].icon_type);
- EXPECT_EQ(page_url1, icon_mappings[0].page_url);
- EXPECT_EQ(1, icon_mappings[0].icon_id);
- EXPECT_EQ(icon1, icon_mappings[0].icon_url);
-
- // Test a page which has the same icon.
- GURL page_url3 = GURL("http://www.google.com/");
- icon_mappings.clear();
- EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url3, &icon_mappings));
- ASSERT_EQ(1u, icon_mappings.size());
- EXPECT_EQ(chrome::FAVICON, icon_mappings[0].icon_type);
- EXPECT_EQ(page_url3, icon_mappings[0].page_url);
- EXPECT_EQ(1, icon_mappings[0].icon_id);
- EXPECT_EQ(icon1, icon_mappings[0].icon_url);
-
- // Test a icon_mapping with different IconID.
- GURL page_url2 = GURL("http://yahoo.com/");
- icon_mappings.clear();
- EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url2, &icon_mappings));
- ASSERT_EQ(1u, icon_mappings.size());
- EXPECT_EQ(chrome::FAVICON, icon_mappings[0].icon_type);
- EXPECT_EQ(page_url2, icon_mappings[0].page_url);
- EXPECT_EQ(2, icon_mappings[0].icon_id);
- EXPECT_EQ(icon2, icon_mappings[0].icon_url);
-
- // Test a page without icon
- GURL page_url4 = GURL("http://www.google.com/blank.html");
- EXPECT_FALSE(db.GetIconMappingsForPageURL(page_url4, NULL));
-}
-
TEST_F(ThumbnailDatabaseTest, IconMappingEnumerator) {
ThumbnailDatabase db;
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
- std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
+ std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
GURL url("http://google.com");
@@ -858,4 +699,97 @@ TEST_F(ThumbnailDatabaseTest, IconMappingEnumerator) {
EXPECT_FALSE(enumerator2.GetNextIconMapping(&icon_mapping));
}
+// Test loading version 3 database.
+TEST_F(ThumbnailDatabaseTest, Version3) {
+ base::FilePath history_db_name =
+ temp_dir_.path().AppendASCII("TestHistory.db");
+ ASSERT_TRUE(CreateDatabaseFromSQL(history_db_name,
+ "Favicons.v3.history.sql"));
+
+ HistoryDatabase history_db;
+ ASSERT_TRUE(history_db.db_.Open(history_db_name));
+ history_db.BeginTransaction();
+
+ scoped_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v3.sql",
+ &history_db);
+ ASSERT_TRUE(db.get() != NULL);
+ VerifyTablesAndColumns(&db->db_);
+
+ // Test results of icon-mapping migration. Version 3 only stored
+ // |FAVICON| type.
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl1, chrome::FAVICON,
+ kIconUrl1, gfx::Size(), sizeof(kBlob1), kBlob1));
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl2, chrome::FAVICON,
+ kIconUrl2, gfx::Size(), sizeof(kBlob2), kBlob2));
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl3, chrome::FAVICON,
+ kIconUrl1, gfx::Size(), sizeof(kBlob1), kBlob1));
+
+ // Page 4 is in urls database, ends up with no favicon.
+ EXPECT_FALSE(db->GetIconMappingsForPageURL(kPageUrl4, NULL));
+}
+
+// Test loading version 4 database.
+TEST_F(ThumbnailDatabaseTest, Version4) {
+ scoped_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v4.sql", NULL);
+ ASSERT_TRUE(db.get() != NULL);
+ VerifyTablesAndColumns(&db->db_);
+
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl1, chrome::FAVICON,
+ kIconUrl1, gfx::Size(), sizeof(kBlob1), kBlob1));
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl2, chrome::FAVICON,
+ kIconUrl2, gfx::Size(), sizeof(kBlob2), kBlob2));
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl3, chrome::FAVICON,
+ kIconUrl1, gfx::Size(), sizeof(kBlob1), kBlob1));
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl3, chrome::TOUCH_ICON,
+ kIconUrl3, gfx::Size(), sizeof(kBlob2), kBlob2));
+}
+
+// Test loading version 5 database.
+TEST_F(ThumbnailDatabaseTest, Version5) {
+ scoped_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v5.sql", NULL);
+ ASSERT_TRUE(db.get() != NULL);
+ VerifyTablesAndColumns(&db->db_);
+
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl1, chrome::FAVICON,
+ kIconUrl1, gfx::Size(), sizeof(kBlob1), kBlob1));
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl2, chrome::FAVICON,
+ kIconUrl2, gfx::Size(), sizeof(kBlob2), kBlob2));
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl3, chrome::FAVICON,
+ kIconUrl1, gfx::Size(), sizeof(kBlob1), kBlob1));
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl3, chrome::TOUCH_ICON,
+ kIconUrl3, gfx::Size(), sizeof(kBlob2), kBlob2));
+}
+
+// Test loading version 6 database.
+TEST_F(ThumbnailDatabaseTest, Version6) {
+ scoped_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v6.sql", NULL);
+ ASSERT_TRUE(db.get() != NULL);
+ VerifyTablesAndColumns(&db->db_);
+
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl1, chrome::FAVICON,
+ kIconUrl1, kLargeSize, sizeof(kBlob1), kBlob1));
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl2, chrome::FAVICON,
+ kIconUrl2, kLargeSize, sizeof(kBlob2), kBlob2));
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl3, chrome::FAVICON,
+ kIconUrl1, kLargeSize, sizeof(kBlob1), kBlob1));
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl3, chrome::TOUCH_ICON,
+ kIconUrl3, kLargeSize, sizeof(kBlob2), kBlob2));
+}
+
+// Test loading version 7 database.
+TEST_F(ThumbnailDatabaseTest, Version7) {
+ scoped_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v7.sql", NULL);
+ ASSERT_TRUE(db.get() != NULL);
+ VerifyTablesAndColumns(&db->db_);
+
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl1, chrome::FAVICON,
+ kIconUrl1, kLargeSize, sizeof(kBlob1), kBlob1));
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl2, chrome::FAVICON,
+ kIconUrl2, kLargeSize, sizeof(kBlob2), kBlob2));
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl3, chrome::FAVICON,
+ kIconUrl1, kLargeSize, sizeof(kBlob1), kBlob1));
+ EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl3, chrome::TOUCH_ICON,
+ kIconUrl3, kLargeSize, sizeof(kBlob2), kBlob2));
+}
+
} // namespace history
diff --git a/chrome/browser/history/top_sites_database.cc b/chrome/browser/history/top_sites_database.cc
index c87c108..5c1939f 100644
--- a/chrome/browser/history/top_sites_database.cc
+++ b/chrome/browser/history/top_sites_database.cc
@@ -14,8 +14,13 @@
namespace history {
+// Version 2: eb0b24e6/r87284 by satorux@chromium.org on 2011-05-31
+// Version 1: 809cc4d8/r64072 by sky@chromium.org on 2010-10-27
+
// From the version 1 to 2, one column was added. Old versions of Chrome
// should be able to read version 2 files just fine.
+// NOTE(shess): When changing the version, add a new golden file for
+// the new version and a test to verify that Init() works with it.
static const int kVersionNumber = 2;
TopSitesDatabase::TopSitesDatabase() {
diff --git a/chrome/browser/history/top_sites_database.h b/chrome/browser/history/top_sites_database.h
index 5823938..053f03b 100644
--- a/chrome/browser/history/top_sites_database.h
+++ b/chrome/browser/history/top_sites_database.h
@@ -58,7 +58,8 @@ class TopSitesDatabase {
bool RemoveURL(const MostVisitedURL& url);
private:
- FRIEND_TEST_ALL_PREFIXES(TopSitesDatabaseTest, UpgradeToVersion2);
+ FRIEND_TEST_ALL_PREFIXES(TopSitesDatabaseTest, Version1);
+ FRIEND_TEST_ALL_PREFIXES(TopSitesDatabaseTest, Version2);
// Creates the thumbnail table, returning true if the table already exists
// or was successfully created.
diff --git a/chrome/browser/history/top_sites_database_unittest.cc b/chrome/browser/history/top_sites_database_unittest.cc
index 872b1df..bcd119a 100644
--- a/chrome/browser/history/top_sites_database_unittest.cc
+++ b/chrome/browser/history/top_sites_database_unittest.cc
@@ -4,9 +4,54 @@
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/path_service.h"
#include "chrome/browser/history/top_sites_database.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/tools/profiles/thumbnail-inl.h"
+#include "sql/connection.h"
+#include "sql/statement.h"
+#include "sql/test/test_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace {
+
+// URL with url_rank 0 in golden files.
+const GURL kUrl = GURL("http://www.google.com/");
+
+// Create the test database at |db_path| from the golden file at
+// |ascii_path| in the "History/" subdir of the test data dir.
+WARN_UNUSED_RESULT bool CreateDatabaseFromSQL(const base::FilePath &db_path,
+ const char* ascii_path) {
+ base::FilePath sql_path;
+ if (!PathService::Get(chrome::DIR_TEST_DATA, &sql_path))
+ return false;
+ sql_path = sql_path.AppendASCII("History").AppendASCII(ascii_path);
+ return sql::test::CreateDatabaseFromSQL(db_path, sql_path);
+}
+
+// Verify that the up-to-date database has the expected tables and
+// columns. Functional tests only check whether the things which
+// should be there are, but do not check if extraneous items are
+// present. Any extraneous items have the potential to interact
+// negatively with future schema changes.
+void VerifyTablesAndColumns(sql::Connection* db) {
+ // [meta] and [thumbnails].
+ EXPECT_EQ(2u, sql::test::CountSQLTables(db));
+
+ // Implicit index on [meta], index on [thumbnails].
+ EXPECT_EQ(2u, sql::test::CountSQLIndices(db));
+
+ // [key] and [value].
+ EXPECT_EQ(2u, sql::test::CountTableColumns(db, "meta"));
+
+ // [url], [url_rank], [title], [thumbnail], [redirects],
+ // [boring_score], [good_clipping], [at_top], [last_updated], and
+ // [load_completed].
+ EXPECT_EQ(10u, sql::test::CountTableColumns(db, "thumbnails"));
+}
+
+} // namespace
+
namespace history {
class TopSitesDatabaseTest : public testing::Test {
@@ -21,35 +66,58 @@ class TopSitesDatabaseTest : public testing::Test {
base::FilePath file_name_;
};
-TEST_F(TopSitesDatabaseTest, UpgradeToVersion2) {
+TEST_F(TopSitesDatabaseTest, Version1) {
+ ASSERT_TRUE(CreateDatabaseFromSQL(file_name_, "TopSites.v1.sql"));
+
TopSitesDatabase db;
ASSERT_TRUE(db.Init(file_name_));
- // Create a version 1 table. SQLite doesn't support DROP COLUMN with
- // ALTER TABLE. Hence, we recreate a table here.
- ASSERT_TRUE(db.db_->Execute("DROP TABLE IF EXISTS thumbnails"));
- ASSERT_TRUE(db.db_->Execute("CREATE TABLE thumbnails ("
- "url LONGVARCHAR PRIMARY KEY,"
- "url_rank INTEGER ,"
- "title LONGVARCHAR,"
- "thumbnail BLOB,"
- "redirects LONGVARCHAR,"
- "boring_score DOUBLE DEFAULT 1.0, "
- "good_clipping INTEGER DEFAULT 0, "
- "at_top INTEGER DEFAULT 0, "
- "last_updated INTEGER DEFAULT 0)"));
- db.meta_table_.SetVersionNumber(1);
-
- // Make sure the table meets the version 1 criteria.
- ASSERT_EQ(1, db.meta_table_.GetVersionNumber());
- ASSERT_FALSE(db.db_->DoesColumnExist("thumbnails", "load_completed"));
-
- // Upgrade to version 2.
- ASSERT_TRUE(db.UpgradeToVersion2());
-
- // Make sure the table meets the version 2 criteria.
- ASSERT_EQ(2, db.meta_table_.GetVersionNumber());
- ASSERT_TRUE(db.db_->DoesColumnExist("thumbnails", "load_completed"));
+ VerifyTablesAndColumns(db.db_.get());
+
+ // Basic operational check.
+ MostVisitedURLList urls;
+ std::map<GURL, Images> thumbnails;
+ db.GetPageThumbnails(&urls, &thumbnails);
+ ASSERT_EQ(3u, urls.size());
+ ASSERT_EQ(3u, thumbnails.size());
+ EXPECT_EQ(kUrl, urls[0].url); // [0] because of url_rank.
+ // kGoogleThumbnail includes nul terminator.
+ ASSERT_EQ(sizeof(kGoogleThumbnail) - 1,
+ thumbnails[urls[0].url].thumbnail->size());
+ EXPECT_TRUE(!memcmp(thumbnails[urls[0].url].thumbnail->front(),
+ kGoogleThumbnail, sizeof(kGoogleThumbnail) - 1));
+
+ ASSERT_TRUE(db.RemoveURL(urls[1]));
+ db.GetPageThumbnails(&urls, &thumbnails);
+ ASSERT_EQ(2u, urls.size());
+ ASSERT_EQ(2u, thumbnails.size());
+}
+
+TEST_F(TopSitesDatabaseTest, Version2) {
+ ASSERT_TRUE(CreateDatabaseFromSQL(file_name_, "TopSites.v2.sql"));
+
+ TopSitesDatabase db;
+ ASSERT_TRUE(db.Init(file_name_));
+
+ VerifyTablesAndColumns(db.db_.get());
+
+ // Basic operational check.
+ MostVisitedURLList urls;
+ std::map<GURL, Images> thumbnails;
+ db.GetPageThumbnails(&urls, &thumbnails);
+ ASSERT_EQ(3u, urls.size());
+ ASSERT_EQ(3u, thumbnails.size());
+ EXPECT_EQ(kUrl, urls[0].url); // [0] because of url_rank.
+ // kGoogleThumbnail includes nul terminator.
+ ASSERT_EQ(sizeof(kGoogleThumbnail) - 1,
+ thumbnails[urls[0].url].thumbnail->size());
+ EXPECT_TRUE(!memcmp(thumbnails[urls[0].url].thumbnail->front(),
+ kGoogleThumbnail, sizeof(kGoogleThumbnail) - 1));
+
+ ASSERT_TRUE(db.RemoveURL(urls[1]));
+ db.GetPageThumbnails(&urls, &thumbnails);
+ ASSERT_EQ(2u, urls.size());
+ ASSERT_EQ(2u, thumbnails.size());
}
} // namespace history
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index bb4d526..84aa65c 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -24,6 +24,8 @@
'../net/net.gyp:net',
'../net/net.gyp:net_test_support',
'../skia/skia.gyp:skia',
+ '../sql/sql.gyp:sql',
+ '../sql/sql.gyp:test_support_sql',
'../sync/sync.gyp:sync',
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
diff --git a/chrome/test/data/History/history.20.sql b/chrome/test/data/History/Favicons.v3.history.sql
index 2adb73c..1c072d5 100644
--- a/chrome/test/data/History/history.20.sql
+++ b/chrome/test/data/History/Favicons.v3.history.sql
@@ -1,11 +1,15 @@
+-- unit_tests --gtest_filter=ThumbnailDatabaseTest.Version3
+--
+-- .dump that portion of the History database needed to migrate a
+-- Favicons version 3 database. See also Favicons.v3.sql.
BEGIN TRANSACTION;
CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY,value LONGVARCHAR);
INSERT INTO "meta" VALUES('version','20');
INSERT INTO "meta" VALUES('last_compatible_version','16');
CREATE TABLE urls(id INTEGER PRIMARY KEY,url LONGVARCHAR,title LONGVARCHAR,visit_count INTEGER DEFAULT 0 NOT NULL,typed_count INTEGER DEFAULT 0 NOT NULL,last_visit_time INTEGER NOT NULL,hidden INTEGER DEFAULT 0 NOT NULL,favicon_id INTEGER DEFAULT 0 NOT NULL);
-INSERT INTO "urls" VALUES(1,'http://google.com/','Google',1,1,$1,0,1);
-INSERT INTO "urls" VALUES(2,'http://www.google.com/','Google',1,0,$1,0,1);
-INSERT INTO "urls" VALUES(3,'http://www.google.com/blank.html','',1,0,$1,1,0);
-INSERT INTO "urls" VALUES(4,'http://yahoo.com/','Yahoo!',1,1,$1,0,2);
-INSERT INTO "urls" VALUES(5,'http://www.yahoo.com/','Yahoo!',1,0,$1,0,2);
+INSERT INTO "urls" VALUES(1,'http://google.com/','Google',1,1,0,0,1);
+INSERT INTO "urls" VALUES(2,'http://www.google.com/','Google',1,0,0,0,1);
+INSERT INTO "urls" VALUES(3,'http://www.google.com/blank.html','',1,0,0,1,0);
+INSERT INTO "urls" VALUES(4,'http://yahoo.com/','Yahoo!',1,1,0,0,2);
+INSERT INTO "urls" VALUES(5,'http://www.yahoo.com/','Yahoo!',1,0,0,0,2);
COMMIT;
diff --git a/chrome/test/data/History/Favicons.v3.sql b/chrome/test/data/History/Favicons.v3.sql
new file mode 100644
index 0000000..1cdfc6f
--- /dev/null
+++ b/chrome/test/data/History/Favicons.v3.sql
@@ -0,0 +1,16 @@
+-- unit_tests --gtest_filter=ThumbnailDatabaseTest.Version3
+--
+-- .dump of a version 3 Favicons database. Version 3 contained a
+-- table [thumbnails] which was migrated to [Top Sites] database, and
+-- the [favicons] rows were referenced by the [urls.favicon_id] table
+-- in this history database. See Favicons.v3.history.sql.
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO "meta" VALUES('version','3');
+INSERT INTO "meta" VALUES('last_compatible_version','3');
+CREATE TABLE favicons(id INTEGER PRIMARY KEY,url LONGVARCHAR NOT NULL,last_updated INTEGER DEFAULT 0,image_data BLOB);
+INSERT INTO "favicons" VALUES(1,'http://www.google.com/favicon.ico',1287424416,X'313233343631303233353631323033393437353136333435313635393133343837313034373831323336343931363534313932333435313932333435313233343931333400');
+INSERT INTO "favicons" VALUES(2,'http://www.yahoo.com/favicon.ico',1287424428,X'676F6977756567727172636F6D697A71797A6B6A616C697462616878666A7974727176707165726F6963786D6E6C6B686C7A756E616378616E65766961777274786379776867656600');
+CREATE TABLE thumbnails(url_id INTEGER PRIMARY KEY,boring_score DOUBLE DEFAULT 1.0,good_clipping INTEGER DEFAULT 0,at_top INTEGER DEFAULT 0,last_updated INTEGER DEFAULT 0,data BLOB);
+CREATE INDEX favicons_url ON favicons(url);
+COMMIT;
diff --git a/chrome/test/data/History/Favicons.v4.sql b/chrome/test/data/History/Favicons.v4.sql
new file mode 100644
index 0000000..d2549bf
--- /dev/null
+++ b/chrome/test/data/History/Favicons.v4.sql
@@ -0,0 +1,21 @@
+-- unit_tests --gtest_filter=ThumbnailDatabaseTest.Version4
+--
+-- .dump of a version 4 Favicons database.
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO "meta" VALUES('version','4');
+INSERT INTO "meta" VALUES('last_compatible_version','4');
+CREATE TABLE favicons(id INTEGER PRIMARY KEY,url LONGVARCHAR NOT NULL,last_updated INTEGER DEFAULT 0,image_data BLOB,icon_type INTEGER DEFAULT 1);
+INSERT INTO "favicons" VALUES(1,'http://www.google.com/favicon.ico',1287424416,X'313233343631303233353631323033393437353136333435313635393133343837313034373831323336343931363534313932333435313932333435313233343931333400',1);
+INSERT INTO "favicons" VALUES(2,'http://www.google.com/touch.ico',1287424416,X'676F6977756567727172636F6D697A71797A6B6A616C697462616878666A7974727176707165726F6963786D6E6C6B686C7A756E616378616E65766961777274786379776867656600',2);
+INSERT INTO "favicons" VALUES(3,'http://www.yahoo.com/favicon.ico',1287424428,X'676F6977756567727172636F6D697A71797A6B6A616C697462616878666A7974727176707165726F6963786D6E6C6B686C7A756E616378616E65766961777274786379776867656600',1);
+CREATE TABLE icon_mapping(id INTEGER PRIMARY KEY,page_url LONGVARCHAR NOT NULL,icon_id INTEGER);
+INSERT INTO "icon_mapping" VALUES(1,'http://google.com/',1);
+INSERT INTO "icon_mapping" VALUES(2,'http://www.google.com/',1);
+INSERT INTO "icon_mapping" VALUES(3,'http://www.google.com/',2);
+INSERT INTO "icon_mapping" VALUES(4,'http://yahoo.com/',3);
+INSERT INTO "icon_mapping" VALUES(5,'http://www.yahoo.com/',3);
+CREATE INDEX favicons_url ON favicons(url);
+CREATE INDEX icon_mapping_page_url_idx ON icon_mapping(page_url);
+CREATE INDEX icon_mapping_icon_id_idx ON icon_mapping(icon_id);
+COMMIT;
diff --git a/chrome/test/data/History/Favicons.v5.sql b/chrome/test/data/History/Favicons.v5.sql
new file mode 100644
index 0000000..655d282
--- /dev/null
+++ b/chrome/test/data/History/Favicons.v5.sql
@@ -0,0 +1,21 @@
+-- unit_tests --gtest_filter=ThumbnailDatabaseTest.Version5
+--
+-- .dump of a version 5 Favicons database.
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO "meta" VALUES('version','5');
+INSERT INTO "meta" VALUES('last_compatible_version','5');
+CREATE TABLE favicons(id INTEGER PRIMARY KEY,url LONGVARCHAR NOT NULL,last_updated INTEGER DEFAULT 0,image_data BLOB,icon_type INTEGER DEFAULT 1,sizes LONGVARCHAR);
+INSERT INTO "favicons" VALUES(1,'http://www.google.com/favicon.ico',1287424416,X'313233343631303233353631323033393437353136333435313635393133343837313034373831323336343931363534313932333435313932333435313233343931333400',1,'32 32');
+INSERT INTO "favicons" VALUES(2,'http://www.google.com/touch.ico',1287424428,X'676F6977756567727172636F6D697A71797A6B6A616C697462616878666A7974727176707165726F6963786D6E6C6B686C7A756E616378616E65766961777274786379776867656600',2,'32 32');
+INSERT INTO "favicons" VALUES(3,'http://www.yahoo.com/favicon.ico',1287424428,X'676F6977756567727172636F6D697A71797A6B6A616C697462616878666A7974727176707165726F6963786D6E6C6B686C7A756E616378616E65766961777274786379776867656600',1,'32 32');
+CREATE TABLE icon_mapping(id INTEGER PRIMARY KEY,page_url LONGVARCHAR NOT NULL,icon_id INTEGER);
+INSERT INTO "icon_mapping" VALUES(1,'http://google.com/',1);
+INSERT INTO "icon_mapping" VALUES(2,'http://www.google.com/',1);
+INSERT INTO "icon_mapping" VALUES(3,'http://www.google.com/',2);
+INSERT INTO "icon_mapping" VALUES(4,'http://yahoo.com/',3);
+INSERT INTO "icon_mapping" VALUES(5,'http://www.yahoo.com/',3);
+CREATE INDEX favicons_url ON favicons(url);
+CREATE INDEX icon_mapping_page_url_idx ON icon_mapping(page_url);
+CREATE INDEX icon_mapping_icon_id_idx ON icon_mapping(icon_id);
+COMMIT;
diff --git a/chrome/test/data/History/Favicons.v6.sql b/chrome/test/data/History/Favicons.v6.sql
new file mode 100644
index 0000000..c27125b
--- /dev/null
+++ b/chrome/test/data/History/Favicons.v6.sql
@@ -0,0 +1,26 @@
+-- unit_tests --gtest_filter=ThumbnailDatabaseTest.Version6
+--
+-- .dump of a version 6 Favicons database.
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO "meta" VALUES('version','6');
+INSERT INTO "meta" VALUES('last_compatible_version','6');
+CREATE TABLE favicons(id INTEGER PRIMARY KEY,url LONGVARCHAR NOT NULL,icon_type INTEGER DEFAULT 1,sizes LONGVARCHAR);
+INSERT INTO "favicons" VALUES(1,'http://www.google.com/favicon.ico',1,'32 32');
+INSERT INTO "favicons" VALUES(2,'http://www.google.com/touch.ico',2,'32 32');
+INSERT INTO "favicons" VALUES(3,'http://www.yahoo.com/favicon.ico',1,'32 32');
+CREATE TABLE favicon_bitmaps(id INTEGER PRIMARY KEY,icon_id INTEGER NOT NULL,last_updated INTEGER DEFAULT 0,image_data BLOB,width INTEGER DEFAULT 0,height INTEGER DEFAULT 0);
+INSERT INTO "favicon_bitmaps" VALUES(1,1,1287424416,X'313233343631303233353631323033393437353136333435313635393133343837313034373831323336343931363534313932333435313932333435313233343931333400',32,32);
+INSERT INTO "favicon_bitmaps" VALUES(2,2,1287424428,X'676F6977756567727172636F6D697A71797A6B6A616C697462616878666A7974727176707165726F6963786D6E6C6B686C7A756E616378616E65766961777274786379776867656600',32,32);
+INSERT INTO "favicon_bitmaps" VALUES(3,3,1287424428,X'676F6977756567727172636F6D697A71797A6B6A616C697462616878666A7974727176707165726F6963786D6E6C6B686C7A756E616378616E65766961777274786379776867656600',32,32);
+CREATE TABLE icon_mapping(id INTEGER PRIMARY KEY,page_url LONGVARCHAR NOT NULL,icon_id INTEGER);
+INSERT INTO "icon_mapping" VALUES(1,'http://google.com/',1);
+INSERT INTO "icon_mapping" VALUES(2,'http://www.google.com/',1);
+INSERT INTO "icon_mapping" VALUES(3,'http://www.google.com/',2);
+INSERT INTO "icon_mapping" VALUES(4,'http://yahoo.com/',3);
+INSERT INTO "icon_mapping" VALUES(5,'http://www.yahoo.com/',3);
+CREATE INDEX favicons_url ON favicons(url);
+CREATE INDEX favicon_bitmaps_icon_id ON favicon_bitmaps(icon_id);
+CREATE INDEX icon_mapping_page_url_idx ON icon_mapping(page_url);
+CREATE INDEX icon_mapping_icon_id_idx ON icon_mapping(icon_id);
+COMMIT;
diff --git a/chrome/test/data/History/Favicons.v7.sql b/chrome/test/data/History/Favicons.v7.sql
new file mode 100644
index 0000000..8b0fd2c
--- /dev/null
+++ b/chrome/test/data/History/Favicons.v7.sql
@@ -0,0 +1,26 @@
+-- unit_tests --gtest_filter=ThumbnailDatabaseTest.Version7
+--
+-- .dump of a version 7 Favicons database.
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO "meta" VALUES('version','7');
+INSERT INTO "meta" VALUES('last_compatible_version','7');
+CREATE TABLE favicons(id INTEGER PRIMARY KEY,url LONGVARCHAR NOT NULL,icon_type INTEGER DEFAULT 1);
+INSERT INTO "favicons" VALUES(1,'http://www.google.com/favicon.ico',1);
+INSERT INTO "favicons" VALUES(2,'http://www.google.com/touch.ico',2);
+INSERT INTO "favicons" VALUES(3,'http://www.yahoo.com/favicon.ico',1);
+CREATE TABLE favicon_bitmaps(id INTEGER PRIMARY KEY,icon_id INTEGER NOT NULL,last_updated INTEGER DEFAULT 0,image_data BLOB,width INTEGER DEFAULT 0,height INTEGER DEFAULT 0);
+INSERT INTO "favicon_bitmaps" VALUES(1,1,1287424416,X'313233343631303233353631323033393437353136333435313635393133343837313034373831323336343931363534313932333435313932333435313233343931333400',32,32);
+INSERT INTO "favicon_bitmaps" VALUES(2,2,1287424428,X'676F6977756567727172636F6D697A71797A6B6A616C697462616878666A7974727176707165726F6963786D6E6C6B686C7A756E616378616E65766961777274786379776867656600',32,32);
+INSERT INTO "favicon_bitmaps" VALUES(3,3,1287424428,X'676F6977756567727172636F6D697A71797A6B6A616C697462616878666A7974727176707165726F6963786D6E6C6B686C7A756E616378616E65766961777274786379776867656600',32,32);
+CREATE TABLE icon_mapping(id INTEGER PRIMARY KEY,page_url LONGVARCHAR NOT NULL,icon_id INTEGER);
+INSERT INTO "icon_mapping" VALUES(1,'http://google.com/',1);
+INSERT INTO "icon_mapping" VALUES(2,'http://www.google.com/',1);
+INSERT INTO "icon_mapping" VALUES(3,'http://www.google.com/',2);
+INSERT INTO "icon_mapping" VALUES(4,'http://yahoo.com/',3);
+INSERT INTO "icon_mapping" VALUES(5,'http://www.yahoo.com/',3);
+CREATE INDEX favicons_url ON favicons(url);
+CREATE INDEX favicon_bitmaps_icon_id ON favicon_bitmaps(icon_id);
+CREATE INDEX icon_mapping_page_url_idx ON icon_mapping(page_url);
+CREATE INDEX icon_mapping_icon_id_idx ON icon_mapping(icon_id);
+COMMIT;
diff --git a/chrome/test/data/History/TopSites.v1.sql b/chrome/test/data/History/TopSites.v1.sql
new file mode 100644
index 0000000..1ae8cd7
--- /dev/null
+++ b/chrome/test/data/History/TopSites.v1.sql
@@ -0,0 +1,13 @@
+-- unit_tests --gtest_filter=TopSitesDatabaseTest.Version1
+--
+-- .dump of a version 1 "Top Sites" database. The Google thumbnail
+-- matches kGoogleThumbnail from thumbnail-inl.h.
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO "meta" VALUES('version','1');
+INSERT INTO "meta" VALUES('last_compatible_version','1');
+CREATE TABLE thumbnails (url LONGVARCHAR PRIMARY KEY,url_rank INTEGER ,title LONGVARCHAR,thumbnail BLOB,redirects LONGVARCHAR,boring_score DOUBLE DEFAULT 1.0, good_clipping INTEGER DEFAULT 0, at_top INTEGER DEFAULT 0, last_updated INTEGER DEFAULT 0);
+INSERT INTO "thumbnails" VALUES('http://www.google.com/chrome/intl/en/welcome.html',1,'Welcome to Chromium',NULL,'http://www.google.com/chrome/intl/en/welcome.html',1.0,0,0,13022203361871994);
+INSERT INTO "thumbnails" VALUES('https://chrome.google.com/webstore?hl=en',2,'Chrome Web Store',NULL,'https://chrome.google.com/webstore?hl=en',1.0,0,0,13022203361875499);
+INSERT INTO "thumbnails" VALUES('http://www.google.com/',0,'Google',X'ffd8ffe000104a46494600010100000100010000ffdb0043000302020302020303030304030304050805050404050a070706080c0a0c0c0b0a0b0b0d0e12100d0e110e0b0b1016101113141515150c0f171816141812141514ffdb00430103040405040509050509140d0b0d1414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414ffc0001108008800c403012200021101031101ffc4001f0000010501010101010100000000000000000102030405060708090a0bffc400b5100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9faffc4001f0100030101010101010101010000000000000102030405060708090a0bffc400b51100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda000c03010002110311003f00fd269bc157f27899f564f146b3140d324bfd98b2c46d805099400c65829dac4fcd9f9cf200188750f06ebd75a8493dbf8baf6ce1791dc5bac71b2a827214123381d3e9f9d767456d4eaca93bc6df349fe626ae72fadf86356d527824b5f115de98238d119615560e54e4b1046327a1e318a6eb9e15d6354b9825b4f12de69612211bc702a32c878f98ee5383c76f535d55156b1138dad6d3c97f90ac725ad784759d46fd6e6d3c4f7ba6a845468225568d88182704704f5e2a4d6bc2fabea57265b6f125de9c86158bcb855186e19cbf2bd4e7e9c74aea68a1622a2b6da792ff0020e54735aa786f56beb88e4b7f10dd58a2c6a8638d518311d5b91d4d6dd95b4b67018da57b83bddf7ccf96f998b6de00e06703d80ebd6ad5159caa4a4945f4f243b586664feeaffdf5ff00d6a3327f757fefaffeb53e8acc633327f757fefaff00eb51993fbabff7d7ff005a9f450033327f757fefaffeb51993fbabff007d7ff5ab90f8bbf11a0f853f0ff54f124d01bb7b6091c16c1b6f9b33b848d73d8166193e99ac9bcf0b7c44b8f0fc33da78e23b6d770b23c1269b03d913c164c6df331d467766b78d26e2a726926edadfa6fb5fba3373d5c56ad1e8b993fbabff007d7ff5a8cc9fdd5ffbebff00ad5c3789be33f877c24f7e2f5aeae2df4b648f54bdb1b7334160cc01fdf15e570086380768209c66b5f53f885a3e992c885e6bb586249e796ce2332431b8cab315ec473c678e7a115e7d4c4d1a49b9c92b7fc1ff0027f73ec763c3564949c5d9edf87f9afbd773a2cc9fdd5ffbebff00ad4664feeaff00df5ffd6af3ff0019fc77f08f81ec65bcbcbc96f2d20485e7b8b08fce8a1597fd5191c1da81b83924000824804679ff000c7c5596cbc63e3e8b59bdb8bbb4b7d52d2cb49d3d624f3b74968b3346a06327976258f014f3c574d4bd28c2725a4b67f2bff97de8e35352a8a94756ff00c9bfd19ec1993fbabff7d7ff005a8cc9fdd5ff00bebffad5ce781be20e97f10f4e37da38b87b65792195a68f618a646daf13027218119f4208209cd74d52a4a4aeb6379c254e4e1356686664feeaff00df5ffd6a3327f757fefaff00eb53e8aa206664feeaff00df5ffd6ae7fc4be19d475e9a27b5f116a5a1840014b030957c1279f32263dc7423a0f7cf47452038993c07ad3b964f1c6bb1038f9545a91d31fc56e68aeda8a7715828a28a430a28a2800a28a2800a28a2800a28a2800a2a87fc241a5e587f695a6549523cf5e083823af5068fedfd2ffe82569ff7fd7fc6a799771d99cd7c61f86365f183e1e6ade15bdb892cd6f155a2ba8865e095183c6e077c328c8ee3238cd709ae695f17bc43e03baf0f4f6d61a76bc96cd0db789748d6a4851e5da5566687cbdc3fbc537119ef5ec1fdbfa5ff00d04ad3feff00aff8d1fdbfa5ff00d04ad3feff00aff8d75d3c5ca9c542e9a4eeafd1e9f9d95d6c632a2a4dcbbe878c697f06bc53e17b5f1ee95637765aa69de33dd713dcdfbb799657125bac12e571fbd421030e54f639eb5d1e83f0e359f014379a76886db51d32f34fb6b406f242af04914021de460ef5650a7190462bd13fb7f4bffa095a7fdff5ff001a3fb7f4bffa095a7fdff5ff001af1ea616854494ba79f74d3fc1bfe923d3a98baf57e27f87a6beba2fe9b3e39f17782a5d23c2be32b7f0ada5e789bc3fa60834df1adacf751c097ff0066895e636fb8128e10a06e402148da7a9f41d67e06eb9e2eb9d43c4fa3cba632dd6ab67afe9767a8a33453c42cc40f6f70b8f9772313919c1c715eaf7fe04f87ba96bf71ad5c5a696fa9dc10679bcf03ce20601750d863803920f4aeb135cd2a34555d46cd55460013a600fcebd4c54e857a34e8a5650db5f2492dfa5b47a6965b2479f875530f5feb09fbcaff008dd3fbd37a7cf72b78461be874385751d36cf49bb3cbdad8c9e6469ff02dab9fae2b6aa87f6fe97ff412b4ff00bfebfe347f6fe97ff412b4ff00bfebfe358292ee68eeddec5fa2a87f6fe97ff412b4ff00bfebfe34b2ebba6c0c164d46d2362a1c069d412a7a1ebd3deaa3ef3b4752762f5159dff091693c7fc4cecf9e9fe909cfeb57a19a3b8892589d658dc655d0e430f506a9c651dd00fa28a2a4028a28a0028a28a0028a28a0028a28a0028a28a00cdb1d36e34eb7f221b888c61dd87990927e662c790c3d6ac7977bff003f107fdf86ff00e2ead5151c8bfa6cae6663eb9a8dde89a4dcdf3c90cab0aee28b0364f38fefd793cffb4f68f69007ba59ad98bf96237b09492d9c60152437afca4f1cd7b45d5b5bea16cd0ce893c120c946e430073fe159bff086e859c7f65db67fdc152e1d9fe23523cbcfed25a7473491cd05c40cb2796b9d3e57dfe846c270383d7078e9d2af0f8f111d1e3d4c59cc6d9dc2605a3f98bf2b312537670029e80e78c6722bd05bc21a0a0cb69b6aa3dd053c78434431ec1a65b6dceec041d69723ee1cde47974ffb47d8db246d2da5d279a47943fb3e526453fc430781c1e1b078e9d29a9fb4ae9334124d1ef92343b7e5b297716cb02bb49ce415e7200191cd7a87fc21fa0e14ff0066dafcdd3e41cd1ff087e843fe6196bd71f7051c8fb87379187e02f8807e202ddc96452386058db74b6ce84962e31b598118d9dc77aeb7cbbdff009f883fefc37ff1751e9da2d868e643656915a99701cc6b82d8ce33f4c9fceaf55282ebf9b173157cbbdff9f883fefc37ff00175e69e3ef046a9aaeb91dc59e8d6ba8a08d10cf2ac24e4673c4849039edfae2bd568aebc3d67869fb486afceffe64cbde56678ee87e08d42c6091af3c0da55f3b3305b7963b558e3008c32900fdee49e3d3f0f5eb7b78ad20486089218506d48e350aaa3d001d2a4a2b4c46267887792b7a5ff56c951b0514515c850514514005145140051451400514514005145140052119183d296992ab3c4ea8fe5b95215f19da7b1c77a00e426f843e13b850afa6c85463817938e01071c3f4c8191d0e39a9d3e1778691b77f67b31dd905ae24f97d87cdd3be2aa43e08f11432961e38bf923c604725ac2707180738c93fa64938e9890f837c43e4e078ceefce0a54486d23c6371232bd0900819e38519ef9ebf634ff00e7eafba5fe44ddf63407c3fd07ed97b746c99e7bc0e2667b895b76fceec02d85ea718c632718a862f869e1e827b7956d25dd6ec1a206ea521581273f7b9ce79ce4600150c5e1ed574a82fae350f185c3db7d9650649a18a2580f5f37776da01ebf5ac183cc9628648fe29c12c687cb2ca2d8ac876f009cfdec60f047d292a54ef6f68bee97f90eefb1beff000b7c3a6d7ecf15a4b6f0e41d915c498e3381824e073d07b7a0a897e117860c16d14d673dcadbb33c666bc9890c58b13f7f9393deab5a687aa6b123dce9fe3d7b8814ec75b68629103617b8270780719fe23c7231a53785b5a9b4a8edc78aef12ed26f33ed6b6f102cbcfc85718239fd07e3a34b9153f6cb97b7bda7e02f3b0d6f85fe1a680446c65281f78ff004c9f21b00641df9e805741a5699068da7c1656a19608576a0772ed8f72793f8d736de12f103468078bee52405b320b48cee076e060e4718f4ee6b6bc35a55f68fa60b7d43569759b80c5bed3344b1b63038c2f1ebf9d613a708c6ea69bedafea877f23568a28ac061451450014514500145145001451450014514500145145001451450014514500145145003648d268d91d43a302acac32083d411559749b158bcb1656e23c83b044b8cfd3156e8a00af67616ba746d1dadb436c8c77158630809c019c0ef803f2ab14514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451401fffd9','https://www.google.com/ http://www.google.com/',0.836942538593482,1,1,13022203426208198);
+COMMIT;
diff --git a/chrome/test/data/History/TopSites.v2.sql b/chrome/test/data/History/TopSites.v2.sql
new file mode 100644
index 0000000..1022b12
--- /dev/null
+++ b/chrome/test/data/History/TopSites.v2.sql
@@ -0,0 +1,13 @@
+-- unit_tests --gtest_filter=TopSitesDatabaseTest.Version2
+--
+-- .dump of a version 2 "Top Sites" database. The Google thumbnail
+-- matches kGoogleThumbnail from thumbnail-inl.h.
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO "meta" VALUES('version','2');
+INSERT INTO "meta" VALUES('last_compatible_version','2');
+CREATE TABLE thumbnails (url LONGVARCHAR PRIMARY KEY,url_rank INTEGER ,title LONGVARCHAR,thumbnail BLOB,redirects LONGVARCHAR,boring_score DOUBLE DEFAULT 1.0, good_clipping INTEGER DEFAULT 0, at_top INTEGER DEFAULT 0, last_updated INTEGER DEFAULT 0, load_completed INTEGER DEFAULT 0);
+INSERT INTO "thumbnails" VALUES('http://www.google.com/chrome/intl/en/welcome.html',1,'Welcome to Chromium',NULL,'http://www.google.com/chrome/intl/en/welcome.html',1.0,0,0,13022203361871994,0);
+INSERT INTO "thumbnails" VALUES('https://chrome.google.com/webstore?hl=en',2,'Chrome Web Store',NULL,'https://chrome.google.com/webstore?hl=en',1.0,0,0,13022203361875499,0);
+INSERT INTO "thumbnails" VALUES('http://www.google.com/',0,'Google',X'ffd8ffe000104a46494600010100000100010000ffdb0043000302020302020303030304030304050805050404050a070706080c0a0c0c0b0a0b0b0d0e12100d0e110e0b0b1016101113141515150c0f171816141812141514ffdb00430103040405040509050509140d0b0d1414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414ffc0001108008800c403012200021101031101ffc4001f0000010501010101010100000000000000000102030405060708090a0bffc400b5100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9faffc4001f0100030101010101010101010000000000000102030405060708090a0bffc400b51100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda000c03010002110311003f00fd269bc157f27899f564f146b3140d324bfd98b2c46d805099400c65829dac4fcd9f9cf200188750f06ebd75a8493dbf8baf6ce1791dc5bac71b2a827214123381d3e9f9d767456d4eaca93bc6df349fe626ae72fadf86356d527824b5f115de98238d119615560e54e4b1046327a1e318a6eb9e15d6354b9825b4f12de69612211bc702a32c878f98ee5383c76f535d55156b1138dad6d3c97f90ac725ad784759d46fd6e6d3c4f7ba6a845468225568d88182704704f5e2a4d6bc2fabea57265b6f125de9c86158bcb855186e19cbf2bd4e7e9c74aea68a1622a2b6da792ff0020e54735aa786f56beb88e4b7f10dd58a2c6a8638d518311d5b91d4d6dd95b4b67018da57b83bddf7ccf96f998b6de00e06703d80ebd6ad5159caa4a4945f4f243b586664feeaffdf5ff00d6a3327f757fefaffeb53e8acc633327f757fefaff00eb51993fbabff7d7ff005a9f450033327f757fefaffeb51993fbabff007d7ff5ab90f8bbf11a0f853f0ff54f124d01bb7b6091c16c1b6f9b33b848d73d8166193e99ac9bcf0b7c44b8f0fc33da78e23b6d770b23c1269b03d913c164c6df331d467766b78d26e2a726926edadfa6fb5fba3373d5c56ad1e8b993fbabff007d7ff5a8cc9fdd5ffbebff00ad5c3789be33f877c24f7e2f5aeae2df4b648f54bdb1b7334160cc01fdf15e570086380768209c66b5f53f885a3e992c885e6bb586249e796ce2332431b8cab315ec473c678e7a115e7d4c4d1a49b9c92b7fc1ff0027f73ec763c3564949c5d9edf87f9afbd773a2cc9fdd5ffbebff00ad4664feeaff00df5ffd6af3ff0019fc77f08f81ec65bcbcbc96f2d20485e7b8b08fce8a1597fd5191c1da81b83924000824804679ff000c7c5596cbc63e3e8b59bdb8bbb4b7d52d2cb49d3d624f3b74968b3346a06327976258f014f3c574d4bd28c2725a4b67f2bff97de8e35352a8a94756ff00c9bfd19ec1993fbabff7d7ff005a8cc9fdd5ff00bebffad5ce781be20e97f10f4e37da38b87b65792195a68f618a646daf13027218119f4208209cd74d52a4a4aeb6379c254e4e1356686664feeaff00df5ffd6a3327f757fefaff00eb53e8aa206664feeaff00df5ffd6ae7fc4be19d475e9a27b5f116a5a1840014b030957c1279f32263dc7423a0f7cf47452038993c07ad3b964f1c6bb1038f9545a91d31fc56e68aeda8a7715828a28a430a28a2800a28a2800a28a2800a28a2800a2a87fc241a5e587f695a6549523cf5e083823af5068fedfd2ffe82569ff7fd7fc6a799771d99cd7c61f86365f183e1e6ade15bdb892cd6f155a2ba8865e095183c6e077c328c8ee3238cd709ae695f17bc43e03baf0f4f6d61a76bc96cd0db789748d6a4851e5da5566687cbdc3fbc537119ef5ec1fdbfa5ff00d04ad3feff00aff8d1fdbfa5ff00d04ad3feff00aff8d75d3c5ca9c542e9a4eeafd1e9f9d95d6c632a2a4dcbbe878c697f06bc53e17b5f1ee95637765aa69de33dd713dcdfbb799657125bac12e571fbd421030e54f639eb5d1e83f0e359f014379a76886db51d32f34fb6b406f242af04914021de460ef5650a7190462bd13fb7f4bffa095a7fdff5ff001a3fb7f4bffa095a7fdff5ff001af1ea616854494ba79f74d3fc1bfe923d3a98baf57e27f87a6beba2fe9b3e39f17782a5d23c2be32b7f0ada5e789bc3fa60834df1adacf751c097ff0066895e636fb8128e10a06e402148da7a9f41d67e06eb9e2eb9d43c4fa3cba632dd6ab67afe9767a8a33453c42cc40f6f70b8f9772313919c1c715eaf7fe04f87ba96bf71ad5c5a696fa9dc10679bcf03ce20601750d863803920f4aeb135cd2a34555d46cd55460013a600fcebd4c54e857a34e8a5650db5f2492dfa5b47a6965b2479f875530f5feb09fbcaff008dd3fbd37a7cf72b78461be874385751d36cf49bb3cbdad8c9e6469ff02dab9fae2b6aa87f6fe97ff412b4ff00bfebfe347f6fe97ff412b4ff00bfebfe358292ee68eeddec5fa2a87f6fe97ff412b4ff00bfebfe34b2ebba6c0c164d46d2362a1c069d412a7a1ebd3deaa3ef3b4752762f5159dff091693c7fc4cecf9e9fe909cfeb57a19a3b8892589d658dc655d0e430f506a9c651dd00fa28a2a4028a28a0028a28a0028a28a0028a28a0028a28a00cdb1d36e34eb7f221b888c61dd87990927e662c790c3d6ac7977bff003f107fdf86ff00e2ead5151c8bfa6cae6663eb9a8dde89a4dcdf3c90cab0aee28b0364f38fefd793cffb4f68f69007ba59ad98bf96237b09492d9c60152437afca4f1cd7b45d5b5bea16cd0ce893c120c946e430073fe159bff086e859c7f65db67fdc152e1d9fe23523cbcfed25a7473491cd05c40cb2796b9d3e57dfe846c270383d7078e9d2af0f8f111d1e3d4c59cc6d9dc2605a3f98bf2b312537670029e80e78c6722bd05bc21a0a0cb69b6aa3dd053c78434431ec1a65b6dceec041d69723ee1cde47974ffb47d8db246d2da5d279a47943fb3e526453fc430781c1e1b078e9d29a9fb4ae9334124d1ef92343b7e5b297716cb02bb49ce415e7200191cd7a87fc21fa0e14ff0066dafcdd3e41cd1ff087e843fe6196bd71f7051c8fb87379187e02f8807e202ddc96452386058db74b6ce84962e31b598118d9dc77aeb7cbbdff009f883fefc37ff1751e9da2d868e643656915a99701cc6b82d8ce33f4c9fceaf55282ebf9b173157cbbdff9f883fefc37ff00175e69e3ef046a9aaeb91dc59e8d6ba8a08d10cf2ac24e4673c4849039edfae2bd568aebc3d67869fb486afceffe64cbde56678ee87e08d42c6091af3c0da55f3b3305b7963b558e3008c32900fdee49e3d3f0f5eb7b78ad20486089218506d48e350aaa3d001d2a4a2b4c46267887792b7a5ff56c951b0514515c850514514005145140051451400514514005145140052119183d296992ab3c4ea8fe5b95215f19da7b1c77a00e426f843e13b850afa6c85463817938e01071c3f4c8191d0e39a9d3e1778691b77f67b31dd905ae24f97d87cdd3be2aa43e08f11432961e38bf923c604725ac2707180738c93fa64938e9890f837c43e4e078ceefce0a54486d23c6371232bd0900819e38519ef9ebf634ff00e7eafba5fe44ddf63407c3fd07ed97b746c99e7bc0e2667b895b76fceec02d85ea718c632718a862f869e1e827b7956d25dd6ec1a206ea521581273f7b9ce79ce4600150c5e1ed574a82fae350f185c3db7d9650649a18a2580f5f37776da01ebf5ac183cc9628648fe29c12c687cb2ca2d8ac876f009cfdec60f047d292a54ef6f68bee97f90eefb1beff000b7c3a6d7ecf15a4b6f0e41d915c498e3381824e073d07b7a0a897e117860c16d14d673dcadbb33c666bc9890c58b13f7f9393deab5a687aa6b123dce9fe3d7b8814ec75b68629103617b8270780719fe23c7231a53785b5a9b4a8edc78aef12ed26f33ed6b6f102cbcfc85718239fd07e3a34b9153f6cb97b7bda7e02f3b0d6f85fe1a680446c65281f78ff004c9f21b00641df9e805741a5699068da7c1656a19608576a0772ed8f72793f8d736de12f103468078bee52405b320b48cee076e060e4718f4ee6b6bc35a55f68fa60b7d43569759b80c5bed3344b1b63038c2f1ebf9d613a708c6ea69bedafea877f23568a28ac061451450014514500145145001451450014514500145145001451450014514500145145003648d268d91d43a302acac32083d411559749b158bcb1656e23c83b044b8cfd3156e8a00af67616ba746d1dadb436c8c77158630809c019c0ef803f2ab14514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451400514514005145140051451401fffd9','https://www.google.com/ http://www.google.com/',0.836942538593482,1,1,13022203426208198,1);
+COMMIT;
diff --git a/chrome/test/data/History/thumbnails.3.sql b/chrome/test/data/History/thumbnails.3.sql
deleted file mode 100644
index ab7d395..0000000
--- a/chrome/test/data/History/thumbnails.3.sql
+++ /dev/null
@@ -1,9 +0,0 @@
-BEGIN TRANSACTION;
-CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY,value LONGVARCHAR);
-INSERT INTO "meta" VALUES('version','3');
-INSERT INTO "meta" VALUES('last_compatible_version','3');
-CREATE TABLE favicons(id INTEGER PRIMARY KEY,url LONGVARCHAR NOT NULL,last_updated INTEGER DEFAULT 0,image_data BLOB);
-INSERT INTO "favicons" VALUES(1,'http://www.google.com/favicon.ico',1287424416,X'FFD8FFE000104A46494600010100000100010000FFDB0043000302020302020303030304030304050805050404050A070706080C0A0C0C0B0A0B0B0D0E12100D0E110E0B0B1016101113141515150C0F171816141812141514FFDB00430103040405040509050509140D0B0D1414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414FFC00011080002000203012200021101031101FFC4001F0000010501010101010100000000000000000102030405060708090A0BFFC400B5100002010303020403050504040000017D01020300041105122131410613516107227114328191A1082342B1C11552D1F02433627282090A161718191A25262728292A3435363738393A434445464748494A535455565758595A636465666768696A737475767778797A838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE1E2E3E4E5E6E7E8E9EAF1F2F3F4F5F6F7F8F9FAFFC4001F0100030101010101010101010000000000000102030405060708090A0BFFC400B51100020102040403040705040400010277000102031104052131061241510761711322328108144291A1B1C109233352F0156272D10A162434E125F11718191A262728292A35363738393A434445464748494A535455565758595A636465666768696A737475767778797A82838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE2E3E4E5E6E7E8E9EAF2F3F4F5F6F7F8F9FAFFDA000C03010002110311003F00F9D28A28AFC30FF54CFFD9');
-INSERT INTO "favicons" VALUES(2,'http://www.yahoo.com/favicon.ico',1287424428,X'FFD8FFE000104A46494600010100000100010000FFDB0043000302020302020303030304030304050805050404050A070706080C0A0C0C0B0A0B0B0D0E12100D0E110E0B0B1016101113141515150C0F171816141812141514FFDB00430103040405040509050509140D0B0D1414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414FFC00011080003000303012200021101031101FFC4001F0000010501010101010100000000000000000102030405060708090A0BFFC400B5100002010303020403050504040000017D01020300041105122131410613516107227114328191A1082342B1C11552D1F02433627282090A161718191A25262728292A3435363738393A434445464748494A535455565758595A636465666768696A737475767778797A838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE1E2E3E4E5E6E7E8E9EAF1F2F3F4F5F6F7F8F9FAFFC4001F0100030101010101010101010000000000000102030405060708090A0BFFC400B51100020102040403040705040400010277000102031104052131061241510761711322328108144291A1B1C109233352F0156272D10A162434E125F11718191A262728292A35363738393A434445464748494A535455565758595A636465666768696A737475767778797A82838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE2E3E4E5E6E7E8E9EAF2F3F4F5F6F7F8F9FAFFDA000C03010002110311003F00F9D28A28AFC30FF54CFFD9');
-CREATE INDEX favicons_url ON favicons(url);
-COMMIT;
diff --git a/sql/sql.gyp b/sql/sql.gyp
index 861a1dd..7add51c 100644
--- a/sql/sql.gyp
+++ b/sql/sql.gyp
@@ -62,6 +62,8 @@
'test/error_callback_support.h',
'test/scoped_error_ignorer.cc',
'test/scoped_error_ignorer.h',
+ 'test/test_helpers.cc',
+ 'test/test_helpers.h',
],
'include_dirs': [
'..',
diff --git a/sql/test/test_helpers.cc b/sql/test/test_helpers.cc
new file mode 100644
index 0000000..607f146
--- /dev/null
+++ b/sql/test/test_helpers.cc
@@ -0,0 +1,75 @@
+// Copyright 2013 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 "sql/test/test_helpers.h"
+
+#include <string>
+
+#include "base/file_util.h"
+#include "sql/connection.h"
+#include "sql/statement.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+size_t CountSQLItemsOfType(sql::Connection* db, const char* type) {
+ const char kTypeSQL[] = "SELECT COUNT(*) FROM sqlite_master WHERE type = ?";
+ sql::Statement s(db->GetUniqueStatement(kTypeSQL));
+ s.BindCString(0, type);
+ EXPECT_TRUE(s.Step());
+ return s.ColumnInt(0);
+}
+
+} // namespace
+
+namespace sql {
+namespace test {
+
+size_t CountSQLTables(sql::Connection* db) {
+ return CountSQLItemsOfType(db, "table");
+}
+
+size_t CountSQLIndices(sql::Connection* db) {
+ return CountSQLItemsOfType(db, "index");
+}
+
+size_t CountTableColumns(sql::Connection* db, const char* table) {
+ // TODO(shess): sql::Connection::QuoteForSQL() would make sense.
+ std::string quoted_table;
+ {
+ const char kQuoteSQL[] = "SELECT quote(?)";
+ sql::Statement s(db->GetUniqueStatement(kQuoteSQL));
+ s.BindCString(0, table);
+ EXPECT_TRUE(s.Step());
+ quoted_table = s.ColumnString(0);
+ }
+
+ std::string sql = "PRAGMA table_info(" + quoted_table + ")";
+ sql::Statement s(db->GetUniqueStatement(sql.c_str()));
+ size_t rows = 0;
+ while (s.Step()) {
+ ++rows;
+ }
+ EXPECT_TRUE(s.Succeeded());
+ return rows;
+}
+
+bool CreateDatabaseFromSQL(const base::FilePath& db_path,
+ const base::FilePath& sql_path) {
+ if (base::PathExists(db_path) || !base::PathExists(sql_path))
+ return false;
+
+ std::string sql;
+ if (!base::ReadFileToString(sql_path, &sql))
+ return false;
+
+ sql::Connection db;
+ if (!db.Open(db_path))
+ return false;
+
+ return db.Execute(sql.c_str());
+}
+
+} // namespace test
+} // namespace sql
diff --git a/sql/test/test_helpers.h b/sql/test/test_helpers.h
new file mode 100644
index 0000000..2e01ecd
--- /dev/null
+++ b/sql/test/test_helpers.h
@@ -0,0 +1,45 @@
+// Copyright 2013 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.
+
+#ifndef SQL_TEST_TEST_HELPERS_H_
+#define SQL_TEST_TEST_HELPERS_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+
+// Collection of test-only convenience functions.
+
+namespace base {
+class FilePath;
+}
+
+namespace sql {
+class Connection;
+}
+
+namespace sql {
+namespace test {
+
+// Return the number of tables in sqlite_master.
+size_t CountSQLTables(sql::Connection* db) WARN_UNUSED_RESULT;
+
+// Return the number of indices in sqlite_master.
+size_t CountSQLIndices(sql::Connection* db) WARN_UNUSED_RESULT;
+
+// Returns the number of columns in the named table. 0 indicates an
+// error (probably no such table).
+size_t CountTableColumns(sql::Connection* db, const char* table)
+ WARN_UNUSED_RESULT;
+
+// Creates a SQLite database at |db_path| from the sqlite .dump output
+// at |sql_path|. Returns false if |db_path| already exists, or if
+// sql_path does not exist or cannot be read, or if there is an error
+// executing the statements.
+bool CreateDatabaseFromSQL(const base::FilePath& db_path,
+ const base::FilePath& sql_path) WARN_UNUSED_RESULT;
+
+} // namespace test
+} // namespace sql
+
+#endif // SQL_TEST_TEST_HELPERS_H_