This source file includes following definitions.
- CreateDatabaseFromSQL
- VerifyTablesAndColumns
- VerifyDatabaseEmpty
- CheckPageHasIcon
- LoadFromGolden
- SetUp
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include <algorithm>
#include <vector>
#include "base/basictypes.h"
#include "base/files/file_enumerator.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/thumbnail_database.h"
#include "chrome/common/chrome_paths.h"
#include "sql/connection.h"
#include "sql/recovery.h"
#include "sql/test/scoped_error_ignorer.h"
#include "sql/test/test_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/sqlite/sqlite3.h"
#include "url/gurl.h"
namespace history {
namespace {
const unsigned char kBlob1[] =
    "12346102356120394751634516591348710478123649165419234519234512349134";
const unsigned char kBlob2[] =
    "goiwuegrqrcomizqyzkjalitbahxfjytrqvpqeroicxmnlkhlzunacxaneviawrtxcywhgef";
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);
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);
}
void VerifyTablesAndColumns(sql::Connection* db) {
  
  EXPECT_EQ(4u, sql::test::CountSQLTables(db));
  
  
  EXPECT_EQ(5u, sql::test::CountSQLIndices(db));
  
  EXPECT_EQ(2u, sql::test::CountTableColumns(db, "meta"));
  
  EXPECT_EQ(3u, sql::test::CountTableColumns(db, "favicons"));
  
  EXPECT_EQ(6u, sql::test::CountTableColumns(db, "favicon_bitmaps"));
  
  EXPECT_EQ(3u, sql::test::CountTableColumns(db, "icon_mapping"));
}
void VerifyDatabaseEmpty(sql::Connection* db) {
  size_t rows = 0;
  EXPECT_TRUE(sql::test::CountTableRows(db, "favicons", &rows));
  EXPECT_EQ(0u, rows);
  EXPECT_TRUE(sql::test::CountTableRows(db, "favicon_bitmaps", &rows));
  EXPECT_EQ(0u, rows);
  EXPECT_TRUE(sql::test::CountTableRows(db, "icon_mapping", &rows));
  EXPECT_EQ(0u, rows);
}
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;
  }
  
  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;
}
}  
class ThumbnailDatabaseTest : public testing::Test {
 public:
  ThumbnailDatabaseTest() {
  }
  virtual ~ThumbnailDatabaseTest() {
  }
  
  
  scoped_ptr<ThumbnailDatabase> LoadFromGolden(const char* golden_path) {
    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_));
    db->BeginTransaction();
    return db.Pass();
  }
 protected:
  virtual void SetUp() {
    
    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_));
  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_));
  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_));
  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_));
  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_));
  db.BeginTransaction();
  
  
  
  
  
  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);
  
  
  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));
  
  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));
  
  EXPECT_FALSE(db.GetFaviconIDForFaviconURL(kPageUrl2, false, NULL));
  
  EXPECT_EQ(original_schema, db.db_.GetSchema());
}
TEST_F(ThumbnailDatabaseTest, DeleteFavicon) {
  ThumbnailDatabase db;
  ASSERT_EQ(sql::INIT_OK, db.Init(file_name_));
  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_));
  db.BeginTransaction();
  
  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);
  
  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);
  
  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_F(ThumbnailDatabaseTest, GetIconMappingsForPageURLWithIconType) {
  ThumbnailDatabase db;
  ASSERT_EQ(sql::INIT_OK, db.Init(file_name_));
  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));
  
  
  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_));
  db.BeginTransaction();
  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(GURL("http://google.com"),
                                        chrome::FAVICON,
                                        favicon,
                                        time,
                                        gfx::Size());
  EXPECT_NE(id1, 0);
  
  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);
  
  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);
  
  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));
  
  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_));
  db.BeginTransaction();
  std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
  scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
  
  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());
  
  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());
  
  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));
  
  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);
  
  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, Version3) {
  scoped_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v3.sql");
  ASSERT_TRUE(db.get() != NULL);
  VerifyTablesAndColumns(&db->db_);
  
  VerifyDatabaseEmpty(&db->db_);
}
TEST_F(ThumbnailDatabaseTest, Version4) {
  scoped_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v4.sql");
  ASSERT_TRUE(db.get() != NULL);
  VerifyTablesAndColumns(&db->db_);
  
  VerifyDatabaseEmpty(&db->db_);
}
TEST_F(ThumbnailDatabaseTest, Version5) {
  scoped_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v5.sql");
  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_F(ThumbnailDatabaseTest, Version6) {
  scoped_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v6.sql");
  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_F(ThumbnailDatabaseTest, Version7) {
  scoped_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v7.sql");
  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_F(ThumbnailDatabaseTest, Recovery) {
  
  
  
  
  
  
  if (!sql::Recovery::FullRecoverySupported())
    return;
  
  {
    EXPECT_TRUE(CreateDatabaseFromSQL(file_name_, "Favicons.v7.sql"));
    sql::Connection raw_db;
    EXPECT_TRUE(raw_db.Open(file_name_));
    VerifyTablesAndColumns(&raw_db);
  }
  
  {
    ThumbnailDatabase db;
    ASSERT_EQ(sql::INIT_OK, db.Init(file_name_));
    EXPECT_TRUE(
        CheckPageHasIcon(&db, kPageUrl1, chrome::FAVICON,
                         kIconUrl1, kLargeSize, sizeof(kBlob1), kBlob1));
    EXPECT_TRUE(
        CheckPageHasIcon(&db, kPageUrl2, chrome::FAVICON,
                         kIconUrl2, kLargeSize, sizeof(kBlob2), kBlob2));
  }
  
  
  {
    sql::Connection raw_db;
    EXPECT_TRUE(raw_db.Open(file_name_));
    ASSERT_EQ("ok", sql::test::IntegrityCheck(&raw_db));
  }
  const char kIndexName[] = "icon_mapping_page_url_idx";
  const char kDeleteSql[] =
      "DELETE FROM icon_mapping WHERE page_url = 'http://yahoo.com/'";
  EXPECT_TRUE(
      sql::test::CorruptTableOrIndex(file_name_, kIndexName, kDeleteSql));
  
  {
    sql::Connection raw_db;
    EXPECT_TRUE(raw_db.Open(file_name_));
    ASSERT_NE("ok", sql::test::IntegrityCheck(&raw_db));
  }
  
  {
    sql::ScopedErrorIgnorer ignore_errors;
    ignore_errors.IgnoreError(SQLITE_CORRUPT);
    ThumbnailDatabase db;
    ASSERT_EQ(sql::INIT_OK, db.Init(file_name_));
    
    
    
    
    EXPECT_FALSE(db.GetIconMappingsForPageURL(kPageUrl2, NULL));
    ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
  }
  
  {
    sql::Connection raw_db;
    EXPECT_TRUE(raw_db.Open(file_name_));
    ASSERT_EQ("ok", sql::test::IntegrityCheck(&raw_db));
    
    VerifyTablesAndColumns(&raw_db);
  }
  
  {
    ThumbnailDatabase db;
    ASSERT_EQ(sql::INIT_OK, db.Init(file_name_));
    
    EXPECT_FALSE(db.GetIconMappingsForPageURL(kPageUrl2, NULL));
    
    EXPECT_TRUE(
        CheckPageHasIcon(&db, kPageUrl1, chrome::FAVICON,
                         kIconUrl1, kLargeSize, sizeof(kBlob1), kBlob1));
  }
  
  EXPECT_TRUE(sql::test::CorruptSizeInHeader(file_name_));
  
  {
    sql::ScopedErrorIgnorer ignore_errors;
    ignore_errors.IgnoreError(SQLITE_CORRUPT);
    sql::Connection raw_db;
    EXPECT_TRUE(raw_db.Open(file_name_));
    EXPECT_FALSE(raw_db.IsSQLValid("PRAGMA integrity_check"));
    ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
  }
  
  {
    sql::ScopedErrorIgnorer ignore_errors;
    ignore_errors.IgnoreError(SQLITE_CORRUPT);
    ThumbnailDatabase db;
    ASSERT_EQ(sql::INIT_OK, db.Init(file_name_));
    EXPECT_FALSE(db.GetIconMappingsForPageURL(kPageUrl2, NULL));
    EXPECT_TRUE(
        CheckPageHasIcon(&db, kPageUrl1, chrome::FAVICON,
                         kIconUrl1, kLargeSize, sizeof(kBlob1), kBlob1));
    ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
  }
}
TEST_F(ThumbnailDatabaseTest, Recovery6) {
  
  if (!sql::Recovery::FullRecoverySupported())
    return;
  
  
  EXPECT_TRUE(CreateDatabaseFromSQL(file_name_, "Favicons.v6.sql"));
  
  
  
  EXPECT_TRUE(sql::test::CorruptSizeInHeader(file_name_));
  
  {
    sql::ScopedErrorIgnorer ignore_errors;
    ignore_errors.IgnoreError(SQLITE_CORRUPT);
    sql::Connection raw_db;
    EXPECT_TRUE(raw_db.Open(file_name_));
    EXPECT_FALSE(raw_db.IsSQLValid("PRAGMA integrity_check"));
    ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
  }
  
  {
    sql::ScopedErrorIgnorer ignore_errors;
    ignore_errors.IgnoreError(SQLITE_CORRUPT);
    ThumbnailDatabase db;
    ASSERT_EQ(sql::INIT_OK, db.Init(file_name_));
    ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
  }
  
  
  {
    sql::Connection raw_db;
    EXPECT_TRUE(raw_db.Open(file_name_));
    ASSERT_EQ("ok", sql::test::IntegrityCheck(&raw_db));
    
    VerifyTablesAndColumns(&raw_db);
    
    VerifyDatabaseEmpty(&raw_db);
  }
}
TEST_F(ThumbnailDatabaseTest, Recovery5) {
  
  if (!sql::Recovery::FullRecoverySupported())
    return;
  
  
  EXPECT_TRUE(CreateDatabaseFromSQL(file_name_, "Favicons.v5.sql"));
  
  
  
  EXPECT_TRUE(sql::test::CorruptSizeInHeader(file_name_));
  
  {
    sql::ScopedErrorIgnorer ignore_errors;
    ignore_errors.IgnoreError(SQLITE_CORRUPT);
    sql::Connection raw_db;
    EXPECT_TRUE(raw_db.Open(file_name_));
    EXPECT_FALSE(raw_db.IsSQLValid("PRAGMA integrity_check"));
    ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
  }
  
  {
    sql::ScopedErrorIgnorer ignore_errors;
    ignore_errors.IgnoreError(SQLITE_CORRUPT);
    ThumbnailDatabase db;
    ASSERT_EQ(sql::INIT_OK, db.Init(file_name_));
    ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
  }
  
  
  {
    sql::Connection raw_db;
    EXPECT_TRUE(raw_db.Open(file_name_));
    ASSERT_EQ("ok", sql::test::IntegrityCheck(&raw_db));
    
    VerifyTablesAndColumns(&raw_db);
    
    VerifyDatabaseEmpty(&raw_db);
  }
}
TEST_F(ThumbnailDatabaseTest, WildSchema) {
  base::FilePath sql_path;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &sql_path));
  sql_path = sql_path.AppendASCII("History").AppendASCII("thumbnail_wild");
  base::FileEnumerator fe(
      sql_path, false, base::FileEnumerator::FILES, FILE_PATH_LITERAL("*.sql"));
  for (base::FilePath name = fe.Next(); !name.empty(); name = fe.Next()) {
    SCOPED_TRACE(name.BaseName().AsUTF8Unsafe());
    
    base::FilePath db_base_name =
        name.BaseName().ReplaceExtension(FILE_PATH_LITERAL("db"));
    base::FilePath db_path = file_name_.DirName().Append(db_base_name);
    ASSERT_TRUE(sql::test::CreateDatabaseFromSQL(db_path, name));
    
    
    
    ThumbnailDatabase db;
    ASSERT_EQ(sql::INIT_OK, db.Init(db_path));
    
    
    VerifyTablesAndColumns(&db.db_);
  }
}
}