blob: 38433eeb9433f18791749780f3bf1286095edbdb [file] [log] [blame]
// Copyright (c) 2012 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 <algorithm>
#include <vector>
#include "base/basictypes.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/thumbnail_database.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/testing_profile.h"
#include "sql/connection.h"
#include "sql/statement.h"
#include "sql/test/test_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace history {
namespace {
// 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";
const unsigned char kBlob2[] =
"goiwuegrqrcomizqyzkjalitbahxfjytrqvpqeroicxmnlkhlzunacxaneviawrtxcywhgef";
// 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 kPageUrl5 = GURL("http://www.bing.com/");
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 GURL kIconUrl5 = GURL("http://www.bing.com/favicon.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 {
public:
ThumbnailDatabaseTest() {
}
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("TestFavicons.db");
}
base::ScopedTempDir temp_dir_;
base::FilePath file_name_;
};
TEST_F(ThumbnailDatabaseTest, AddIconMapping) {
ThumbnailDatabase db;
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
GURL url("http://google.com");
base::Time time = base::Time::Now();
chrome::FaviconID id = db.AddFavicon(url,
chrome::TOUCH_ICON,
favicon,
time,
gfx::Size());
EXPECT_NE(0, id);
EXPECT_NE(0, db.AddIconMapping(url, id));
std::vector<IconMapping> icon_mappings;
EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mappings));
EXPECT_EQ(1u, icon_mappings.size());
EXPECT_EQ(url, icon_mappings.front().page_url);
EXPECT_EQ(id, icon_mappings.front().icon_id);
}
TEST_F(ThumbnailDatabaseTest, UpdateIconMapping) {
ThumbnailDatabase db;
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
GURL url("http://google.com");
chrome::FaviconID id =
db.AddFavicon(url, chrome::TOUCH_ICON);
EXPECT_LT(0, db.AddIconMapping(url, id));
std::vector<IconMapping> icon_mapping;
EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping));
ASSERT_EQ(1u, icon_mapping.size());
EXPECT_EQ(url, icon_mapping.front().page_url);
EXPECT_EQ(id, icon_mapping.front().icon_id);
GURL url1("http://www.google.com/");
chrome::FaviconID new_id =
db.AddFavicon(url1, chrome::TOUCH_ICON);
EXPECT_TRUE(db.UpdateIconMapping(icon_mapping.front().mapping_id, new_id));
icon_mapping.clear();
EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping));
ASSERT_EQ(1u, icon_mapping.size());
EXPECT_EQ(url, icon_mapping.front().page_url);
EXPECT_EQ(new_id, icon_mapping.front().icon_id);
EXPECT_NE(id, icon_mapping.front().icon_id);
}
TEST_F(ThumbnailDatabaseTest, DeleteIconMappings) {
ThumbnailDatabase db;
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
GURL url("http://google.com");
chrome::FaviconID id =
db.AddFavicon(url, chrome::TOUCH_ICON);
base::Time time = base::Time::Now();
db.AddFaviconBitmap(id, favicon, time, gfx::Size());
EXPECT_LT(0, db.AddIconMapping(url, id));
chrome::FaviconID id2 =
db.AddFavicon(url, chrome::FAVICON);
EXPECT_LT(0, db.AddIconMapping(url, id2));
ASSERT_NE(id, id2);
std::vector<IconMapping> icon_mapping;
EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping));
ASSERT_EQ(2u, icon_mapping.size());
EXPECT_EQ(icon_mapping.front().icon_type, chrome::TOUCH_ICON);
EXPECT_TRUE(db.GetIconMappingsForPageURL(url, chrome::FAVICON, NULL));
db.DeleteIconMappings(url);
EXPECT_FALSE(db.GetIconMappingsForPageURL(url, NULL));
EXPECT_FALSE(db.GetIconMappingsForPageURL(url, chrome::FAVICON, NULL));
}
TEST_F(ThumbnailDatabaseTest, GetIconMappingsForPageURL) {
ThumbnailDatabase db;
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
GURL url("http://google.com");
chrome::FaviconID id1 = db.AddFavicon(url, chrome::TOUCH_ICON);
base::Time time = base::Time::Now();
db.AddFaviconBitmap(id1, favicon, time, kSmallSize);
db.AddFaviconBitmap(id1, favicon, time, kLargeSize);
EXPECT_LT(0, db.AddIconMapping(url, id1));
chrome::FaviconID id2 = db.AddFavicon(url, chrome::FAVICON);
EXPECT_NE(id1, id2);
db.AddFaviconBitmap(id2, favicon, time, kSmallSize);
EXPECT_LT(0, db.AddIconMapping(url, id2));
std::vector<IconMapping> icon_mappings;
EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mappings));
ASSERT_EQ(2u, icon_mappings.size());
EXPECT_EQ(id1, icon_mappings[0].icon_id);
EXPECT_EQ(id2, icon_mappings[1].icon_id);
}
TEST_F(ThumbnailDatabaseTest, RetainDataForPageUrls) {
ThumbnailDatabase db;
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
// Build a database mapping kPageUrl1 -> kIconUrl1, kPageUrl2 ->
// kIconUrl2, kPageUrl3 -> kIconUrl1, and kPageUrl5 -> kIconUrl5.
// Then retain kPageUrl1, kPageUrl3, and kPageUrl5. kPageUrl2
// should go away, but the others should be retained correctly.
// TODO(shess): This would probably make sense as a golden file.
scoped_refptr<base::RefCountedStaticMemory> favicon1(
new base::RefCountedStaticMemory(kBlob1, sizeof(kBlob1)));
scoped_refptr<base::RefCountedStaticMemory> favicon2(
new base::RefCountedStaticMemory(kBlob2, sizeof(kBlob2)));
chrome::FaviconID kept_id1 = db.AddFavicon(kIconUrl1, chrome::FAVICON);
db.AddFaviconBitmap(kept_id1, favicon1, base::Time::Now(), kLargeSize);
db.AddIconMapping(kPageUrl1, kept_id1);
db.AddIconMapping(kPageUrl3, kept_id1);
chrome::FaviconID unkept_id = db.AddFavicon(kIconUrl2, chrome::FAVICON);
db.AddFaviconBitmap(unkept_id, favicon1, base::Time::Now(), kLargeSize);
db.AddIconMapping(kPageUrl2, unkept_id);
chrome::FaviconID kept_id2 = db.AddFavicon(kIconUrl5, chrome::FAVICON);
db.AddFaviconBitmap(kept_id2, favicon2, base::Time::Now(), kLargeSize);
db.AddIconMapping(kPageUrl5, kept_id2);
// RetainDataForPageUrls() uses schema manipulations for efficiency.
// Grab a copy of the schema to make sure the final schema matches.
const std::string original_schema = db.db_.GetSchema();
std::vector<GURL> pages_to_keep;
pages_to_keep.push_back(kPageUrl1);
pages_to_keep.push_back(kPageUrl3);
pages_to_keep.push_back(kPageUrl5);
EXPECT_TRUE(db.RetainDataForPageUrls(pages_to_keep));
// Mappings from the retained urls should be left.
EXPECT_TRUE(CheckPageHasIcon(&db, kPageUrl1, chrome::FAVICON,
kIconUrl1, kLargeSize, sizeof(kBlob1), kBlob1));
EXPECT_TRUE(CheckPageHasIcon(&db, kPageUrl3, chrome::FAVICON,
kIconUrl1, kLargeSize, sizeof(kBlob1), kBlob1));
EXPECT_TRUE(CheckPageHasIcon(&db, kPageUrl5, chrome::FAVICON,
kIconUrl5, kLargeSize, sizeof(kBlob2), kBlob2));
// The one not retained should be missing.
EXPECT_FALSE(db.GetFaviconIDForFaviconURL(kPageUrl2, false, NULL));
// Schema should be the same.
EXPECT_EQ(original_schema, db.db_.GetSchema());
}
// Tests that deleting a favicon deletes the favicon row and favicon bitmap
// rows from the database.
TEST_F(ThumbnailDatabaseTest, DeleteFavicon) {
ThumbnailDatabase db;
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
std::vector<unsigned char> data1(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon1(
new base::RefCountedBytes(data1));
std::vector<unsigned char> data2(kBlob2, kBlob2 + sizeof(kBlob2));
scoped_refptr<base::RefCountedBytes> favicon2(
new base::RefCountedBytes(data2));
GURL url("http://google.com");
chrome::FaviconID id = db.AddFavicon(url, chrome::FAVICON);
base::Time last_updated = base::Time::Now();
db.AddFaviconBitmap(id, favicon1, last_updated, kSmallSize);
db.AddFaviconBitmap(id, favicon2, last_updated, kLargeSize);
EXPECT_TRUE(db.GetFaviconBitmaps(id, NULL));
EXPECT_TRUE(db.DeleteFavicon(id));
EXPECT_FALSE(db.GetFaviconBitmaps(id, NULL));
}
TEST_F(ThumbnailDatabaseTest, GetIconMappingsForPageURLForReturnOrder) {
ThumbnailDatabase db;
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
// Add a favicon
std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
GURL page_url("http://google.com");
GURL icon_url("http://google.com/favicon.ico");
base::Time time = base::Time::Now();
chrome::FaviconID id = db.AddFavicon(icon_url,
chrome::FAVICON,
favicon,
time,
gfx::Size());
EXPECT_NE(0, db.AddIconMapping(page_url, id));
std::vector<IconMapping> icon_mappings;
EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url, &icon_mappings));
EXPECT_EQ(page_url, icon_mappings.front().page_url);
EXPECT_EQ(id, icon_mappings.front().icon_id);
EXPECT_EQ(chrome::FAVICON, icon_mappings.front().icon_type);
EXPECT_EQ(icon_url, icon_mappings.front().icon_url);
// Add a touch icon
std::vector<unsigned char> data2(kBlob2, kBlob2 + sizeof(kBlob2));
scoped_refptr<base::RefCountedBytes> favicon2 =
new base::RefCountedBytes(data);
chrome::FaviconID id2 = db.AddFavicon(icon_url,
chrome::TOUCH_ICON,
favicon2,
time,
gfx::Size());
EXPECT_NE(0, db.AddIconMapping(page_url, id2));
icon_mappings.clear();
EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url, &icon_mappings));
EXPECT_EQ(page_url, icon_mappings.front().page_url);
EXPECT_EQ(id2, icon_mappings.front().icon_id);
EXPECT_EQ(chrome::TOUCH_ICON, icon_mappings.front().icon_type);
EXPECT_EQ(icon_url, icon_mappings.front().icon_url);
// Add a touch precomposed icon
scoped_refptr<base::RefCountedBytes> favicon3 =
new base::RefCountedBytes(data2);
chrome::FaviconID id3 = db.AddFavicon(icon_url,
chrome::TOUCH_PRECOMPOSED_ICON,
favicon3,
time,
gfx::Size());
EXPECT_NE(0, db.AddIconMapping(page_url, id3));
icon_mappings.clear();
EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url, &icon_mappings));
EXPECT_EQ(page_url, icon_mappings.front().page_url);
EXPECT_EQ(id3, icon_mappings.front().icon_id);
EXPECT_EQ(chrome::TOUCH_PRECOMPOSED_ICON, icon_mappings.front().icon_type);
EXPECT_EQ(icon_url, icon_mappings.front().icon_url);
}
// Test result of GetIconMappingsForPageURL when an icon type is passed in.
TEST_F(ThumbnailDatabaseTest, GetIconMappingsForPageURLWithIconType) {
ThumbnailDatabase db;
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
GURL url("http://google.com");
std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
base::Time time = base::Time::Now();
chrome::FaviconID id1 = db.AddFavicon(url,
chrome::FAVICON,
favicon,
time,
gfx::Size());
EXPECT_NE(0, db.AddIconMapping(url, id1));
chrome::FaviconID id2 = db.AddFavicon(url,
chrome::TOUCH_ICON,
favicon,
time,
gfx::Size());
EXPECT_NE(0, db.AddIconMapping(url, id2));
chrome::FaviconID id3 = db.AddFavicon(url,
chrome::TOUCH_ICON,
favicon,
time,
gfx::Size());
EXPECT_NE(0, db.AddIconMapping(url, id3));
// Only the mappings for favicons of type TOUCH_ICON should be returned as
// TOUCH_ICON is a larger icon type than FAVICON.
std::vector<IconMapping> icon_mappings;
EXPECT_TRUE(db.GetIconMappingsForPageURL(
url,
chrome::FAVICON | chrome::TOUCH_ICON | chrome::TOUCH_PRECOMPOSED_ICON,
&icon_mappings));
EXPECT_EQ(2u, icon_mappings.size());
if (id2 == icon_mappings[0].icon_id) {
EXPECT_EQ(id3, icon_mappings[1].icon_id);
} else {
EXPECT_EQ(id3, icon_mappings[0].icon_id);
EXPECT_EQ(id2, icon_mappings[1].icon_id);
}
icon_mappings.clear();
EXPECT_TRUE(
db.GetIconMappingsForPageURL(url, chrome::TOUCH_ICON, &icon_mappings));
if (id2 == icon_mappings[0].icon_id) {
EXPECT_EQ(id3, icon_mappings[1].icon_id);
} else {
EXPECT_EQ(id3, icon_mappings[0].icon_id);
EXPECT_EQ(id2, icon_mappings[1].icon_id);
}
icon_mappings.clear();
EXPECT_TRUE(
db.GetIconMappingsForPageURL(url, chrome::FAVICON, &icon_mappings));
EXPECT_EQ(1u, icon_mappings.size());
EXPECT_EQ(id1, icon_mappings[0].icon_id);
}
TEST_F(ThumbnailDatabaseTest, HasMappingFor) {
ThumbnailDatabase db;
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
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
base::Time time = base::Time::Now();
chrome::FaviconID id1 = db.AddFavicon(GURL("http://google.com"),
chrome::FAVICON,
favicon,
time,
gfx::Size());
EXPECT_NE(id1, 0);
// Add another type of favicon
time = base::Time::Now();
chrome::FaviconID id2 = db.AddFavicon(GURL("http://www.google.com/icon"),
chrome::TOUCH_ICON,
favicon,
time,
gfx::Size());
EXPECT_NE(id2, 0);
// Add 3rd favicon
time = base::Time::Now();
chrome::FaviconID id3 = db.AddFavicon(GURL("http://www.google.com/icon"),
chrome::TOUCH_ICON,
favicon,
time,
gfx::Size());
EXPECT_NE(id3, 0);
// Add 2 icon mapping
GURL page_url("http://www.google.com");
EXPECT_TRUE(db.AddIconMapping(page_url, id1));
EXPECT_TRUE(db.AddIconMapping(page_url, id2));
EXPECT_TRUE(db.HasMappingFor(id1));
EXPECT_TRUE(db.HasMappingFor(id2));
EXPECT_FALSE(db.HasMappingFor(id3));
// Remove all mappings
db.DeleteIconMappings(page_url);
EXPECT_FALSE(db.HasMappingFor(id1));
EXPECT_FALSE(db.HasMappingFor(id2));
EXPECT_FALSE(db.HasMappingFor(id3));
}
TEST_F(ThumbnailDatabaseTest, CloneIconMappings) {
ThumbnailDatabase db;
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
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
chrome::FaviconID id1 = db.AddFavicon(
GURL("http://google.com"), chrome::FAVICON);
EXPECT_NE(0, id1);
base::Time time = base::Time::Now();
db.AddFaviconBitmap(id1, favicon, time, gfx::Size());
// Add another type of favicon
chrome::FaviconID id2 = db.AddFavicon(GURL("http://www.google.com/icon"),
chrome::TOUCH_ICON);
EXPECT_NE(0, id2);
time = base::Time::Now();
db.AddFaviconBitmap(id2, favicon, time, gfx::Size());
// Add 3rd favicon
chrome::FaviconID id3 = db.AddFavicon(GURL("http://www.google.com/icon"),
chrome::TOUCH_ICON);
EXPECT_NE(0, id3);
time = base::Time::Now();
db.AddFaviconBitmap(id3, favicon, time, gfx::Size());
GURL page1_url("http://page1.com");
EXPECT_TRUE(db.AddIconMapping(page1_url, id1));
EXPECT_TRUE(db.AddIconMapping(page1_url, id2));
GURL page2_url("http://page2.com");
EXPECT_TRUE(db.AddIconMapping(page2_url, id3));
// Test we do nothing with existing mappings.
std::vector<IconMapping> icon_mapping;
EXPECT_TRUE(db.GetIconMappingsForPageURL(page2_url, &icon_mapping));
ASSERT_EQ(1U, icon_mapping.size());
EXPECT_TRUE(db.CloneIconMappings(page1_url, page2_url));
icon_mapping.clear();
EXPECT_TRUE(db.GetIconMappingsForPageURL(page2_url, &icon_mapping));
ASSERT_EQ(1U, icon_mapping.size());
EXPECT_EQ(page2_url, icon_mapping[0].page_url);
EXPECT_EQ(id3, icon_mapping[0].icon_id);
// Test we clone if the new page has no mappings.
GURL page3_url("http://page3.com");
EXPECT_TRUE(db.CloneIconMappings(page1_url, page3_url));
icon_mapping.clear();
EXPECT_TRUE(db.GetIconMappingsForPageURL(page3_url, &icon_mapping));
ASSERT_EQ(2U, icon_mapping.size());
if (icon_mapping[0].icon_id == id2)
std::swap(icon_mapping[0], icon_mapping[1]);
EXPECT_EQ(page3_url, icon_mapping[0].page_url);
EXPECT_EQ(id1, icon_mapping[0].icon_id);
EXPECT_EQ(page3_url, icon_mapping[1].page_url);
EXPECT_EQ(id2, icon_mapping[1].icon_id);
}
TEST_F(ThumbnailDatabaseTest, IconMappingEnumerator) {
ThumbnailDatabase db;
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
db.BeginTransaction();
std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
GURL url("http://google.com");
GURL icon_url1("http://google.com/favicon.ico");
chrome::FaviconID touch_icon_id1 = db.AddFavicon(icon_url1,
chrome::TOUCH_ICON,
favicon,
base::Time::Now(),
gfx::Size());
ASSERT_NE(0, touch_icon_id1);
IconMappingID touch_mapping_id1 = db.AddIconMapping(url, touch_icon_id1);
ASSERT_NE(0, touch_mapping_id1);
chrome::FaviconID favicon_id1 = db.AddFavicon(icon_url1,
chrome::FAVICON,
favicon,
base::Time::Now(),
gfx::Size());
ASSERT_NE(0, favicon_id1);
IconMappingID favicon_mapping_id1 = db.AddIconMapping(url, favicon_id1);
ASSERT_NE(0, favicon_mapping_id1);
GURL url2("http://chromium.org");
GURL icon_url2("http://chromium.org/favicon.ico");
chrome::FaviconID favicon_id2 = db.AddFavicon(icon_url2,
chrome::FAVICON,
favicon,
base::Time::Now(),
gfx::Size());
ASSERT_NE(0, favicon_id2);
IconMappingID favicon_mapping_id2 = db.AddIconMapping(url2, favicon_id2);
ASSERT_NE(0, favicon_mapping_id2);
IconMapping icon_mapping;
ThumbnailDatabase::IconMappingEnumerator enumerator1;
ASSERT_TRUE(db.InitIconMappingEnumerator(chrome::FAVICON, &enumerator1));
// There are 2 favicon mappings.
bool has_favicon_mapping1 = false;
bool has_favicon_mapping2 = false;
int mapping_count = 0;
while (enumerator1.GetNextIconMapping(&icon_mapping)) {
mapping_count++;
if (favicon_mapping_id1 == icon_mapping.mapping_id) {
has_favicon_mapping1 = true;
EXPECT_EQ(url, icon_mapping.page_url);
EXPECT_EQ(favicon_id1, icon_mapping.icon_id);
EXPECT_EQ(icon_url1, icon_mapping.icon_url);
EXPECT_EQ(chrome::FAVICON, icon_mapping.icon_type);
} else if (favicon_mapping_id2 == icon_mapping.mapping_id) {
has_favicon_mapping2 = true;
EXPECT_EQ(url2, icon_mapping.page_url);
EXPECT_EQ(favicon_id2, icon_mapping.icon_id);
EXPECT_EQ(icon_url2, icon_mapping.icon_url);
EXPECT_EQ(chrome::FAVICON, icon_mapping.icon_type);
}
}
EXPECT_EQ(2, mapping_count);
EXPECT_TRUE(has_favicon_mapping1);
EXPECT_TRUE(has_favicon_mapping2);
ThumbnailDatabase::IconMappingEnumerator enumerator2;
ASSERT_TRUE(db.InitIconMappingEnumerator(chrome::TOUCH_ICON, &enumerator2));
ASSERT_TRUE(enumerator2.GetNextIconMapping(&icon_mapping));
EXPECT_EQ(touch_mapping_id1, icon_mapping.mapping_id);
EXPECT_EQ(url, icon_mapping.page_url);
EXPECT_EQ(touch_icon_id1, icon_mapping.icon_id);
EXPECT_EQ(icon_url1, icon_mapping.icon_url);
EXPECT_EQ(chrome::TOUCH_ICON, icon_mapping.icon_type);
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