This source file includes following definitions.
- succeeded_
- OnCacheSaveFinished
- file_thread_
- GetDB
- GetPrivateData
- ClearPrivateData
- set_history_dir
- GetCacheFilePath
- PostRestoreFromCacheFileTask
- PostSaveToCacheFileTask
- Observe
- scheme_whitelist
- UpdateURL
- DeleteURL
- SetUp
- TestDBName
- CheckTerm
- ExpectPrivateDataNotEmpty
- ExpectPrivateDataEmpty
- ExpectMapOfContainersIdentical
- ExpectPrivateDataEqual
- TestDBName
- 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
- SetUp
- set_history_dir
- GetCacheFilePath
- TEST_F
#include <algorithm>
#include <fstream>
#include "base/auto_reset.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/autocomplete/autocomplete_provider.h"
#include "chrome/browser/bookmarks/bookmark_test_helpers.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/history/history_backend.h"
#include "chrome/browser/history/history_database.h"
#include "chrome/browser/history/history_notifications.h"
#include "chrome/browser/history/history_service.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/history/in_memory_url_index.h"
#include "chrome/browser/history/in_memory_url_index_types.h"
#include "chrome/browser/history/url_index_private_data.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/history_index_restore_observer.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "content/public/test/test_browser_thread.h"
#include "sql/transaction.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::ASCIIToUTF16;
using content::BrowserThread;
namespace history {
class CacheFileSaverObserver : public InMemoryURLIndex::SaveCacheObserver {
public:
explicit CacheFileSaverObserver(base::MessageLoop* loop);
virtual void OnCacheSaveFinished(bool succeeded) OVERRIDE;
base::MessageLoop* loop_;
bool succeeded_;
DISALLOW_COPY_AND_ASSIGN(CacheFileSaverObserver);
};
CacheFileSaverObserver::CacheFileSaverObserver(base::MessageLoop* loop)
: loop_(loop),
succeeded_(false) {
DCHECK(loop);
}
void CacheFileSaverObserver::OnCacheSaveFinished(bool succeeded) {
succeeded_ = succeeded;
loop_->Quit();
}
class InMemoryURLIndexTest : public testing::Test {
public:
InMemoryURLIndexTest();
protected:
virtual void SetUp();
virtual base::FilePath::StringType TestDBName() const;
void CheckTerm(const URLIndexPrivateData::SearchTermCacheMap& cache,
base::string16 term) const;
sql::Connection& GetDB();
URLIndexPrivateData* GetPrivateData() const;
void ClearPrivateData();
void set_history_dir(const base::FilePath& dir_path);
bool GetCacheFilePath(base::FilePath* file_path) const;
void PostRestoreFromCacheFileTask();
void PostSaveToCacheFileTask();
void Observe(int notification_type,
const content::NotificationSource& source,
const content::NotificationDetails& details);
const std::set<std::string>& scheme_whitelist();
bool UpdateURL(const URLRow& row);
bool DeleteURL(const GURL& url);
void ExpectPrivateDataNotEmpty(const URLIndexPrivateData& data);
void ExpectPrivateDataEmpty(const URLIndexPrivateData& data);
void ExpectPrivateDataEqual(const URLIndexPrivateData& expected,
const URLIndexPrivateData& actual);
base::MessageLoopForUI message_loop_;
content::TestBrowserThread ui_thread_;
content::TestBrowserThread file_thread_;
TestingProfile profile_;
HistoryService* history_service_;
scoped_ptr<InMemoryURLIndex> url_index_;
HistoryDatabase* history_database_;
};
InMemoryURLIndexTest::InMemoryURLIndexTest()
: ui_thread_(content::BrowserThread::UI, &message_loop_),
file_thread_(content::BrowserThread::FILE, &message_loop_) {
}
sql::Connection& InMemoryURLIndexTest::GetDB() {
return history_database_->GetDB();
}
URLIndexPrivateData* InMemoryURLIndexTest::GetPrivateData() const {
DCHECK(url_index_->private_data());
return url_index_->private_data();
}
void InMemoryURLIndexTest::ClearPrivateData() {
return url_index_->ClearPrivateData();
}
void InMemoryURLIndexTest::set_history_dir(const base::FilePath& dir_path) {
return url_index_->set_history_dir(dir_path);
}
bool InMemoryURLIndexTest::GetCacheFilePath(base::FilePath* file_path) const {
DCHECK(file_path);
return url_index_->GetCacheFilePath(file_path);
}
void InMemoryURLIndexTest::PostRestoreFromCacheFileTask() {
url_index_->PostRestoreFromCacheFileTask();
}
void InMemoryURLIndexTest::PostSaveToCacheFileTask() {
url_index_->PostSaveToCacheFileTask();
}
void InMemoryURLIndexTest::Observe(
int notification_type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
url_index_->Observe(notification_type, source, details);
}
const std::set<std::string>& InMemoryURLIndexTest::scheme_whitelist() {
return url_index_->scheme_whitelist();
}
bool InMemoryURLIndexTest::UpdateURL(const URLRow& row) {
return GetPrivateData()->UpdateURL(
history_service_, row, url_index_->languages_,
url_index_->scheme_whitelist_);
}
bool InMemoryURLIndexTest::DeleteURL(const GURL& url) {
return GetPrivateData()->DeleteURL(url);
}
void InMemoryURLIndexTest::SetUp() {
ASSERT_TRUE(profile_.CreateHistoryService(true, false));
profile_.CreateBookmarkModel(true);
test::WaitForBookmarkModelToLoad(&profile_);
profile_.BlockUntilHistoryProcessesPendingRequests();
profile_.BlockUntilHistoryIndexIsRefreshed();
history_service_ = HistoryServiceFactory::GetForProfile(
&profile_, Profile::EXPLICIT_ACCESS);
ASSERT_TRUE(history_service_);
HistoryBackend* backend = history_service_->history_backend_.get();
history_database_ = backend->db();
base::FilePath history_proto_path;
PathService::Get(chrome::DIR_TEST_DATA, &history_proto_path);
history_proto_path = history_proto_path.Append(
FILE_PATH_LITERAL("History"));
history_proto_path = history_proto_path.Append(TestDBName());
EXPECT_TRUE(base::PathExists(history_proto_path));
std::ifstream proto_file(history_proto_path.value().c_str());
static const size_t kCommandBufferMaxSize = 2048;
char sql_cmd_line[kCommandBufferMaxSize];
sql::Connection& db(GetDB());
ASSERT_TRUE(db.is_open());
{
sql::Transaction transaction(&db);
transaction.Begin();
while (!proto_file.eof()) {
proto_file.getline(sql_cmd_line, kCommandBufferMaxSize);
if (!proto_file.eof()) {
if (sql_cmd_line[0] >= 'A' && sql_cmd_line[0] <= 'Z') {
std::string sql_cmd(sql_cmd_line);
sql::Statement sql_stmt(db.GetUniqueStatement(sql_cmd_line));
EXPECT_TRUE(sql_stmt.Run());
}
}
}
transaction.Commit();
}
sql::Statement statement(db.GetUniqueStatement(
"SELECT" HISTORY_URL_ROW_FIELDS "FROM urls;"));
ASSERT_TRUE(statement.is_valid());
base::Time time_right_now = base::Time::NowFromSystemTime();
base::TimeDelta day_delta = base::TimeDelta::FromDays(1);
{
sql::Transaction transaction(&db);
transaction.Begin();
while (statement.Step()) {
URLRow row;
history_database_->FillURLRow(statement, &row);
base::Time last_visit = time_right_now;
for (int64 i = row.last_visit().ToInternalValue(); i > 0; --i)
last_visit -= day_delta;
row.set_last_visit(last_visit);
history_database_->UpdateURLRow(row.id(), row);
}
transaction.Commit();
}
statement.Assign(db.GetUniqueStatement(
"SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits;"));
ASSERT_TRUE(statement.is_valid());
{
sql::Transaction transaction(&db);
transaction.Begin();
while (statement.Step()) {
VisitRow row;
history_database_->FillVisitRow(statement, &row);
base::Time last_visit = time_right_now;
for (int64 i = row.visit_time.ToInternalValue(); i > 0; --i)
last_visit -= day_delta;
row.visit_time = last_visit;
history_database_->UpdateVisitRow(row);
}
transaction.Commit();
}
url_index_.reset(
new InMemoryURLIndex(&profile_, base::FilePath(), "en,ja,hi,zh"));
url_index_->Init();
url_index_->RebuildFromHistory(history_database_);
}
base::FilePath::StringType InMemoryURLIndexTest::TestDBName() const {
return FILE_PATH_LITERAL("url_history_provider_test.db.txt");
}
void InMemoryURLIndexTest::CheckTerm(
const URLIndexPrivateData::SearchTermCacheMap& cache,
base::string16 term) const {
URLIndexPrivateData::SearchTermCacheMap::const_iterator cache_iter(
cache.find(term));
ASSERT_TRUE(cache.end() != cache_iter)
<< "Cache does not contain '" << term << "' but should.";
URLIndexPrivateData::SearchTermCacheItem cache_item = cache_iter->second;
EXPECT_TRUE(cache_item.used_)
<< "Cache item '" << term << "' should be marked as being in use.";
}
void InMemoryURLIndexTest::ExpectPrivateDataNotEmpty(
const URLIndexPrivateData& data) {
EXPECT_FALSE(data.word_list_.empty());
EXPECT_TRUE(data.available_words_.empty());
EXPECT_FALSE(data.word_map_.empty());
EXPECT_FALSE(data.char_word_map_.empty());
EXPECT_FALSE(data.word_id_history_map_.empty());
EXPECT_FALSE(data.history_id_word_map_.empty());
EXPECT_FALSE(data.history_info_map_.empty());
}
void InMemoryURLIndexTest::ExpectPrivateDataEmpty(
const URLIndexPrivateData& data) {
EXPECT_TRUE(data.word_list_.empty());
EXPECT_TRUE(data.available_words_.empty());
EXPECT_TRUE(data.word_map_.empty());
EXPECT_TRUE(data.char_word_map_.empty());
EXPECT_TRUE(data.word_id_history_map_.empty());
EXPECT_TRUE(data.history_id_word_map_.empty());
EXPECT_TRUE(data.history_info_map_.empty());
}
template<typename T>
void ExpectMapOfContainersIdentical(const T& expected, const T& actual) {
ASSERT_EQ(expected.size(), actual.size());
for (typename T::const_iterator expected_iter = expected.begin();
expected_iter != expected.end(); ++expected_iter) {
typename T::const_iterator actual_iter = actual.find(expected_iter->first);
ASSERT_TRUE(actual.end() != actual_iter);
typename T::mapped_type const& expected_values(expected_iter->second);
typename T::mapped_type const& actual_values(actual_iter->second);
ASSERT_EQ(expected_values.size(), actual_values.size());
for (typename T::mapped_type::const_iterator set_iter =
expected_values.begin(); set_iter != expected_values.end(); ++set_iter)
EXPECT_EQ(actual_values.count(*set_iter),
expected_values.count(*set_iter));
}
}
void InMemoryURLIndexTest::ExpectPrivateDataEqual(
const URLIndexPrivateData& expected,
const URLIndexPrivateData& actual) {
EXPECT_EQ(expected.word_list_.size(), actual.word_list_.size());
EXPECT_EQ(expected.word_map_.size(), actual.word_map_.size());
EXPECT_EQ(expected.char_word_map_.size(), actual.char_word_map_.size());
EXPECT_EQ(expected.word_id_history_map_.size(),
actual.word_id_history_map_.size());
EXPECT_EQ(expected.history_id_word_map_.size(),
actual.history_id_word_map_.size());
EXPECT_EQ(expected.history_info_map_.size(), actual.history_info_map_.size());
EXPECT_EQ(expected.word_starts_map_.size(), actual.word_starts_map_.size());
size_t count = expected.word_list_.size();
for (size_t i = 0; i < count; ++i)
EXPECT_EQ(expected.word_list_[i], actual.word_list_[i]);
ExpectMapOfContainersIdentical(expected.char_word_map_,
actual.char_word_map_);
ExpectMapOfContainersIdentical(expected.word_id_history_map_,
actual.word_id_history_map_);
ExpectMapOfContainersIdentical(expected.history_id_word_map_,
actual.history_id_word_map_);
for (HistoryInfoMap::const_iterator expected_info =
expected.history_info_map_.begin();
expected_info != expected.history_info_map_.end(); ++expected_info) {
HistoryInfoMap::const_iterator actual_info =
actual.history_info_map_.find(expected_info->first);
ASSERT_TRUE(actual_info != actual.history_info_map_.end());
const URLRow& expected_row(expected_info->second.url_row);
const URLRow& actual_row(actual_info->second.url_row);
EXPECT_EQ(expected_row.visit_count(), actual_row.visit_count());
EXPECT_EQ(expected_row.typed_count(), actual_row.typed_count());
EXPECT_EQ(expected_row.last_visit(), actual_row.last_visit());
EXPECT_EQ(expected_row.url(), actual_row.url());
const VisitInfoVector& expected_visits(expected_info->second.visits);
const VisitInfoVector& actual_visits(actual_info->second.visits);
EXPECT_EQ(expected_visits.size(), actual_visits.size());
for (size_t i = 0;
i < std::min(expected_visits.size(), actual_visits.size()); ++i) {
EXPECT_EQ(expected_visits[i].first, actual_visits[i].first);
EXPECT_EQ(expected_visits[i].second, actual_visits[i].second);
}
}
for (WordStartsMap::const_iterator expected_starts =
expected.word_starts_map_.begin();
expected_starts != expected.word_starts_map_.end();
++expected_starts) {
WordStartsMap::const_iterator actual_starts =
actual.word_starts_map_.find(expected_starts->first);
ASSERT_TRUE(actual_starts != actual.word_starts_map_.end());
const RowWordStarts& expected_word_starts(expected_starts->second);
const RowWordStarts& actual_word_starts(actual_starts->second);
EXPECT_EQ(expected_word_starts.url_word_starts_.size(),
actual_word_starts.url_word_starts_.size());
EXPECT_TRUE(std::equal(expected_word_starts.url_word_starts_.begin(),
expected_word_starts.url_word_starts_.end(),
actual_word_starts.url_word_starts_.begin()));
EXPECT_EQ(expected_word_starts.title_word_starts_.size(),
actual_word_starts.title_word_starts_.size());
EXPECT_TRUE(std::equal(expected_word_starts.title_word_starts_.begin(),
expected_word_starts.title_word_starts_.end(),
actual_word_starts.title_word_starts_.begin()));
}
}
class LimitedInMemoryURLIndexTest : public InMemoryURLIndexTest {
protected:
virtual base::FilePath::StringType TestDBName() const OVERRIDE;
};
base::FilePath::StringType LimitedInMemoryURLIndexTest::TestDBName() const {
return FILE_PATH_LITERAL("url_history_provider_test_limited.db.txt");
}
TEST_F(LimitedInMemoryURLIndexTest, Initialization) {
sql::Statement statement(GetDB().GetUniqueStatement("SELECT * FROM urls;"));
ASSERT_TRUE(statement.is_valid());
uint64 row_count = 0;
while (statement.Step()) ++row_count;
EXPECT_EQ(1U, row_count);
url_index_.reset(
new InMemoryURLIndex(&profile_, base::FilePath(), "en,ja,hi,zh"));
url_index_->Init();
url_index_->RebuildFromHistory(history_database_);
URLIndexPrivateData& private_data(*GetPrivateData());
EXPECT_EQ(1U, private_data.history_info_map_.size());
EXPECT_EQ(35U, private_data.char_word_map_.size());
EXPECT_EQ(17U, private_data.word_map_.size());
}
#if defined(OS_WIN)
#define MAYBE_Retrieval DISABLED_Retrieval
#else
#define MAYBE_Retrieval Retrieval
#endif
TEST_F(InMemoryURLIndexTest, MAYBE_Retrieval) {
ScoredHistoryMatches matches = url_index_->HistoryItemsForTerms(
ASCIIToUTF16("DrudgeReport"), base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_EQ(5, matches[0].url_info.id());
EXPECT_EQ("http://drudgereport.com/", matches[0].url_info.url().spec());
EXPECT_EQ(ASCIIToUTF16("DRUDGE REPORT 2010"), matches[0].url_info.title());
EXPECT_TRUE(matches[0].can_inline());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("DrudgeReport "),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_EQ(5, matches[0].url_info.id());
EXPECT_EQ("http://drudgereport.com/", matches[0].url_info.url().spec());
EXPECT_EQ(ASCIIToUTF16("DRUDGE REPORT 2010"), matches[0].url_info.title());
EXPECT_FALSE(matches[0].can_inline());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("drudge"),
base::string16::npos);
ASSERT_EQ(2U, matches.size());
EXPECT_GE(matches[0].raw_score(), matches[1].raw_score());
matches = url_index_->HistoryItemsForTerms(
ASCIIToUTF16("Nearly Perfect Result"), base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_GT(matches[0].raw_score(), 900);
EXPECT_EQ(32, matches[0].url_info.id());
EXPECT_EQ("https://nearlyperfectresult.com/",
matches[0].url_info.url().spec());
EXPECT_EQ(ASCIIToUTF16("Practically Perfect Search Result"),
matches[0].url_info.title());
EXPECT_FALSE(matches[0].can_inline());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("qui c"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_LT(matches[0].raw_score(), 500);
EXPECT_EQ(33, matches[0].url_info.id());
EXPECT_EQ("http://quiteuselesssearchresultxyz.com/",
matches[0].url_info.url().spec());
EXPECT_EQ(ASCIIToUTF16("Practically Useless Search Result"),
matches[0].url_info.title());
EXPECT_FALSE(matches[0].can_inline());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("Mice"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_EQ(30, matches[0].url_info.id());
EXPECT_FALSE(matches[0].can_inline());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("1% wikipedia"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_EQ(35, matches[0].url_info.id());
EXPECT_EQ("http://en.wikipedia.org/wiki/1%25_rule_(Internet_culture)",
matches[0].url_info.url().spec());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("fubar"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_EQ(34, matches[0].url_info.id());
EXPECT_EQ("http://fubarfubarandfubar.com/", matches[0].url_info.url().spec());
EXPECT_EQ(ASCIIToUTF16("Situation Normal -- FUBARED"),
matches[0].url_info.title());
EXPECT_TRUE(matches[0].can_inline());
}
TEST_F(InMemoryURLIndexTest, CursorPositionRetrieval) {
ScoredHistoryMatches matches = url_index_->HistoryItemsForTerms(
ASCIIToUTF16("DrudReport"), base::string16::npos);
ASSERT_EQ(0U, matches.size());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("DrudReport"), 10u);
ASSERT_EQ(0U, matches.size());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("DrudReport"), 4u);
ASSERT_EQ(1U, matches.size());
EXPECT_EQ("http://drudgereport.com/", matches[0].url_info.url().spec());
EXPECT_EQ(ASCIIToUTF16("DRUDGE REPORT 2010"), matches[0].url_info.title());
matches = url_index_->HistoryItemsForTerms(
ASCIIToUTF16("MORTGAGERATE DROPS"), base::string16::npos);
ASSERT_EQ(0U, matches.size());
matches = url_index_->HistoryItemsForTerms(
ASCIIToUTF16("MORTGAGERATE DROPS"), 18u);
ASSERT_EQ(0U, matches.size());
matches = url_index_->HistoryItemsForTerms(
ASCIIToUTF16("MORTGAGERATE DROPS"), 8u);
ASSERT_EQ(1U, matches.size());
EXPECT_EQ("http://www.reuters.com/article/idUSN0839880620100708",
matches[0].url_info.url().spec());
EXPECT_EQ(ASCIIToUTF16(
"UPDATE 1-US 30-yr mortgage rate drops to new record low | Reuters"),
matches[0].url_info.title());
}
TEST_F(InMemoryURLIndexTest, URLPrefixMatching) {
ScoredHistoryMatches matches = url_index_->HistoryItemsForTerms(
ASCIIToUTF16("drudgere"), base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_TRUE(matches[0].can_inline());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("drudgere"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_TRUE(matches[0].can_inline());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("www.atdmt"),
base::string16::npos);
EXPECT_EQ(0U, matches.size());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("atdmt"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_FALSE(matches[0].can_inline());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("view.atdmt"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_TRUE(matches[0].can_inline());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("view.atdmt"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_TRUE(matches[0].can_inline());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("cnn.com"),
base::string16::npos);
ASSERT_EQ(2U, matches.size());
EXPECT_TRUE(matches[0].can_inline() != matches[1].can_inline());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("www.cnn.com"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_TRUE(matches[0].can_inline());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("ww.cnn.com"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
matches =
url_index_->HistoryItemsForTerms(ASCIIToUTF16("www.cnn.com"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_TRUE(matches[0].can_inline());
matches =
url_index_->HistoryItemsForTerms(ASCIIToUTF16("tp://www.cnn.com"),
base::string16::npos);
ASSERT_EQ(0U, matches.size());
}
TEST_F(InMemoryURLIndexTest, ProperStringMatching) {
ScoredHistoryMatches matches = url_index_->HistoryItemsForTerms(
ASCIIToUTF16("atdmt view"), base::string16::npos);
ASSERT_EQ(1U, matches.size());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("atdmt.view"),
base::string16::npos);
ASSERT_EQ(0U, matches.size());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("view.atdmt"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
}
TEST_F(InMemoryURLIndexTest, HugeResultSet) {
for (URLID row_id = 5000; row_id < 6000; ++row_id) {
URLRow new_row(GURL("http://www.brokeandaloneinmanitoba.com/"), row_id);
new_row.set_last_visit(base::Time::Now());
EXPECT_TRUE(UpdateURL(new_row));
}
ScoredHistoryMatches matches =
url_index_->HistoryItemsForTerms(ASCIIToUTF16("b"), base::string16::npos);
URLIndexPrivateData& private_data(*GetPrivateData());
ASSERT_EQ(AutocompleteProvider::kMaxMatches, matches.size());
ASSERT_EQ(1008U, private_data.pre_filter_item_count_);
ASSERT_EQ(500U, private_data.post_filter_item_count_);
ASSERT_EQ(AutocompleteProvider::kMaxMatches,
private_data.post_scoring_item_count_);
}
#if defined(OS_WIN)
#define MAYBE_TitleSearch DISABLED_TitleSearch
#else
#define MAYBE_TitleSearch TitleSearch
#endif
TEST_F(InMemoryURLIndexTest, MAYBE_TitleSearch) {
EXPECT_EQ(29U, GetPrivateData()->history_info_map_.size());
ScoredHistoryMatches matches = url_index_->HistoryItemsForTerms(
ASCIIToUTF16("MORTGAGE RATE DROPS"), base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_EQ(1, matches[0].url_info.id());
EXPECT_EQ("http://www.reuters.com/article/idUSN0839880620100708",
matches[0].url_info.url().spec());
EXPECT_EQ(ASCIIToUTF16(
"UPDATE 1-US 30-yr mortgage rate drops to new record low | Reuters"),
matches[0].url_info.title());
}
TEST_F(InMemoryURLIndexTest, TitleChange) {
base::string16 original_terms =
ASCIIToUTF16("lebronomics could high taxes influence");
ScoredHistoryMatches matches =
url_index_->HistoryItemsForTerms(original_terms, base::string16::npos);
ASSERT_EQ(1U, matches.size());
const URLID expected_id = 3;
EXPECT_EQ(expected_id, matches[0].url_info.id());
EXPECT_EQ("http://www.businessandmedia.org/articles/2010/20100708120415.aspx",
matches[0].url_info.url().spec());
EXPECT_EQ(ASCIIToUTF16(
"LeBronomics: Could High Taxes Influence James' Team Decision?"),
matches[0].url_info.title());
URLRow old_row(matches[0].url_info);
base::string16 new_terms = ASCIIToUTF16("does eat oats little lambs ivy");
matches = url_index_->HistoryItemsForTerms(new_terms, base::string16::npos);
ASSERT_EQ(0U, matches.size());
old_row.set_title(ASCIIToUTF16("Does eat oats and little lambs eat ivy"));
EXPECT_TRUE(UpdateURL(old_row));
matches = url_index_->HistoryItemsForTerms(new_terms, base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_EQ(expected_id, matches[0].url_info.id());
matches =
url_index_->HistoryItemsForTerms(original_terms, base::string16::npos);
ASSERT_EQ(0U, matches.size());
}
TEST_F(InMemoryURLIndexTest, NonUniqueTermCharacterSets) {
ScoredHistoryMatches matches =
url_index_->HistoryItemsForTerms(ASCIIToUTF16("ABRA"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_EQ(28, matches[0].url_info.id());
EXPECT_EQ("http://www.ddj.com/windows/184416623",
matches[0].url_info.url().spec());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("ABRACAD"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_EQ(28, matches[0].url_info.id());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("ABRACADABRA"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_EQ(28, matches[0].url_info.id());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("ABRACADABR"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_EQ(28, matches[0].url_info.id());
matches = url_index_->HistoryItemsForTerms(ASCIIToUTF16("ABRACA"),
base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_EQ(28, matches[0].url_info.id());
}
TEST_F(InMemoryURLIndexTest, TypedCharacterCaching) {
typedef URLIndexPrivateData::SearchTermCacheMap::iterator CacheIter;
typedef URLIndexPrivateData::SearchTermCacheItem CacheItem;
URLIndexPrivateData::SearchTermCacheMap& cache(
GetPrivateData()->search_term_cache_);
EXPECT_EQ(0U, cache.size());
url_index_->HistoryItemsForTerms(ASCIIToUTF16("r"), base::string16::npos);
EXPECT_EQ(0U, cache.size());
url_index_->HistoryItemsForTerms(ASCIIToUTF16("r re"), base::string16::npos);
ASSERT_EQ(1U, cache.size());
CheckTerm(cache, ASCIIToUTF16("re"));
url_index_->HistoryItemsForTerms(ASCIIToUTF16("r re reco"),
base::string16::npos);
ASSERT_EQ(2U, cache.size());
CheckTerm(cache, ASCIIToUTF16("re"));
CheckTerm(cache, ASCIIToUTF16("reco"));
url_index_->HistoryItemsForTerms(ASCIIToUTF16("mort"), base::string16::npos);
ASSERT_EQ(1U, cache.size());
CheckTerm(cache, ASCIIToUTF16("mort"));
url_index_->HistoryItemsForTerms(ASCIIToUTF16("mort reco"),
base::string16::npos);
ASSERT_EQ(2U, cache.size());
CheckTerm(cache, ASCIIToUTF16("mort"));
CheckTerm(cache, ASCIIToUTF16("reco"));
url_index_->HistoryItemsForTerms(ASCIIToUTF16("mort rec"),
base::string16::npos);
ASSERT_EQ(2U, cache.size());
CheckTerm(cache, ASCIIToUTF16("mort"));
CheckTerm(cache, ASCIIToUTF16("rec"));
}
TEST_F(InMemoryURLIndexTest, AddNewRows) {
URLID new_row_id = 87654321;
EXPECT_TRUE(url_index_->HistoryItemsForTerms(
ASCIIToUTF16("brokeandalone"), base::string16::npos).empty());
URLRow new_row(GURL("http://www.brokeandaloneinmanitoba.com/"), new_row_id++);
new_row.set_last_visit(base::Time::Now());
EXPECT_TRUE(UpdateURL(new_row));
EXPECT_EQ(1U, url_index_->HistoryItemsForTerms(
ASCIIToUTF16("brokeandalone"), base::string16::npos).size());
EXPECT_FALSE(UpdateURL(new_row));
EXPECT_EQ(1U, url_index_->HistoryItemsForTerms(
ASCIIToUTF16("brokeandalone"), base::string16::npos).size());
URLRow unqualified_row(GURL("http://www.brokeandaloneinmanitoba.com/"),
new_row_id++);
EXPECT_FALSE(UpdateURL(new_row));
}
TEST_F(InMemoryURLIndexTest, DeleteRows) {
ScoredHistoryMatches matches = url_index_->HistoryItemsForTerms(
ASCIIToUTF16("DrudgeReport"), base::string16::npos);
ASSERT_EQ(1U, matches.size());
EXPECT_TRUE(DeleteURL(matches[0].url_info.url()));
EXPECT_TRUE(url_index_->HistoryItemsForTerms(
ASCIIToUTF16("DrudgeReport"), base::string16::npos).empty());
GURL url("http://www.hokeypokey.com/putyourrightfootin.html");
EXPECT_FALSE(DeleteURL(url));
}
TEST_F(InMemoryURLIndexTest, ExpireRow) {
ScoredHistoryMatches matches = url_index_->HistoryItemsForTerms(
ASCIIToUTF16("DrudgeReport"), base::string16::npos);
ASSERT_EQ(1U, matches.size());
URLsDeletedDetails deleted_details;
deleted_details.all_history = false;
deleted_details.rows.push_back(matches[0].url_info);
Observe(chrome::NOTIFICATION_HISTORY_URLS_DELETED,
content::Source<InMemoryURLIndexTest>(this),
content::Details<history::HistoryDetails>(&deleted_details));
EXPECT_TRUE(url_index_->HistoryItemsForTerms(
ASCIIToUTF16("DrudgeReport"), base::string16::npos).empty());
}
TEST_F(InMemoryURLIndexTest, WhitelistedURLs) {
struct TestData {
const std::string url_spec;
const bool expected_is_whitelisted;
} data[] = {
{ "about:histograms", true },
{ "chrome://settings", true },
{ "file://localhost/Users/joeschmoe/sekrets", true },
{ "ftp://public.mycompany.com/myfile.txt", true },
{ "http://www.google.com/translate", true },
{ "https://www.gmail.com/", true },
{ "mailto:support@google.com", true },
{ "aaa://www.dummyhost.com;frammy", false },
{ "aaas://www.dummyhost.com;frammy", false },
{ "acap://suzie@somebody.com", false },
{ "cap://cal.example.com/Company/Holidays", false },
{ "cid:foo4*foo1@bar.net", false },
{ "crid://example.com/foobar", false },
{ "data:image/png;base64,iVBORw0KGgoAAAANSUhE=", false },
{ "dict://dict.org/d:shortcake:", false },
{ "dns://192.168.1.1/ftp.example.org?type=A", false },
{ "fax:+358.555.1234567", false },
{ "geo:13.4125,103.8667", false },
{ "go:Mercedes%20Benz", false },
{ "gopher://farnsworth.ca:666/gopher", false },
{ "h323:farmer-john;sixpence", false },
{ "iax:johnQ@example.com/12022561414", false },
{ "icap://icap.net/service?mode=translate&lang=french", false },
{ "im:fred@example.com", false },
{ "imap://michael@minbari.org/users.*", false },
{ "info:ddc/22/eng//004.678", false },
{ "ipp://example.com/printer/fox", false },
{ "iris:dreg1//example.com/local/myhosts", false },
{ "iris.beep:dreg1//example.com/local/myhosts", false },
{ "iris.lws:dreg1//example.com/local/myhosts", false },
{ "iris.xpc:dreg1//example.com/local/myhosts", false },
{ "iris.xpcs:dreg1//example.com/local/myhosts", false },
{ "ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,c=US", false },
{ "mid:foo4%25foo1@bar.net", false },
{ "modem:+3585551234567;type=v32b?7e1;type=v110", false },
{ "msrp://atlanta.example.com:7654/jshA7weztas;tcp", false },
{ "msrps://atlanta.example.com:7654/jshA7weztas;tcp", false },
{ "news:colorectal.info.banned", false },
{ "nfs://server/d/e/f", false },
{ "nntp://www.example.com:6543/info.comp.lies/1234", false },
{ "pop://rg;AUTH=+APOP@mail.mycompany.com:8110", false },
{ "pres:fred@example.com", false },
{ "prospero://host.dom//pros/name", false },
{ "rsync://syler@lost.com/Source", false },
{ "rtsp://media.example.com:554/twister/audiotrack", false },
{ "service:acap://some.where.net;authentication=KERBEROSV4", false },
{ "shttp://www.terces.com/secret", false },
{ "sieve://example.com//script", false },
{ "sip:+1-212-555-1212:1234@gateway.com;user=phone", false },
{ "sips:+1-212-555-1212:1234@gateway.com;user=phone", false },
{ "sms:+15105551212?body=hello%20there", false },
{ "snmp://tester5@example.com:8161/bridge1;800002b804616263", false },
{ "soap.beep://stockquoteserver.example.com/StockQuote", false },
{ "soap.beeps://stockquoteserver.example.com/StockQuote", false },
{ "tag:blogger.com,1999:blog-555", false },
{ "tel:+358-555-1234567;postd=pp22", false },
{ "telnet://mayor_margie:one2rule4All@www.mycity.com:6789/", false },
{ "tftp://example.com/mystartupfile", false },
{ "tip://123.123.123.123/?urn:xopen:xid", false },
{ "tv:nbc.com", false },
{ "urn:foo:A123,456", false },
{ "vemmi://zeus.mctel.fr/demo", false },
{ "wais://www.mydomain.net:8765/mydatabase", false },
{ "xmpp:node@example.com", false },
{ "xmpp://guest@example.com", false },
};
URLIndexPrivateData& private_data(*GetPrivateData());
const std::set<std::string>& whitelist(scheme_whitelist());
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
GURL url(data[i].url_spec);
EXPECT_EQ(data[i].expected_is_whitelisted,
private_data.URLSchemeIsWhitelisted(url, whitelist));
}
}
TEST_F(InMemoryURLIndexTest, ReadVisitsFromHistory) {
const HistoryInfoMap& history_info_map = GetPrivateData()->history_info_map_;
HistoryInfoMap::const_iterator entry = history_info_map.find(1);
ASSERT_TRUE(entry != history_info_map.end());
{
const VisitInfoVector& visits = entry->second.visits;
EXPECT_EQ(3u, visits.size());
EXPECT_EQ(0u, visits[0].second);
EXPECT_EQ(1u, visits[1].second);
EXPECT_EQ(0u, visits[2].second);
}
entry = history_info_map.find(35);
ASSERT_TRUE(entry != history_info_map.end());
{
const VisitInfoVector& visits = entry->second.visits;
EXPECT_EQ(2u, visits.size());
EXPECT_EQ(1u, visits[0].second);
EXPECT_EQ(1u, visits[1].second);
}
entry = history_info_map.find(32);
ASSERT_TRUE(entry != history_info_map.end());
{
const VisitInfoVector& visits = entry->second.visits;
EXPECT_EQ(10u, visits.size());
for (size_t i = 0; i < visits.size(); ++i)
EXPECT_EQ(0u, visits[i].second);
}
}
TEST_F(InMemoryURLIndexTest, CacheSaveRestore) {
base::ScopedTempDir temp_directory;
ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
set_history_dir(temp_directory.path());
URLIndexPrivateData& private_data(*GetPrivateData());
EXPECT_FALSE(private_data.word_list_.empty());
EXPECT_TRUE(private_data.available_words_.empty());
EXPECT_FALSE(private_data.word_map_.empty());
EXPECT_FALSE(private_data.char_word_map_.empty());
EXPECT_FALSE(private_data.word_id_history_map_.empty());
EXPECT_FALSE(private_data.history_id_word_map_.empty());
EXPECT_FALSE(private_data.history_info_map_.empty());
EXPECT_FALSE(private_data.word_starts_map_.empty());
EXPECT_EQ(0, private_data.restored_cache_version_);
scoped_refptr<URLIndexPrivateData> old_data(private_data.Duplicate());
const base::Time rebuild_time = private_data.last_time_rebuilt_from_history_;
CacheFileSaverObserver save_observer(&message_loop_);
url_index_->set_save_cache_observer(&save_observer);
PostSaveToCacheFileTask();
message_loop_.Run();
EXPECT_TRUE(save_observer.succeeded_);
ClearPrivateData();
EXPECT_TRUE(private_data.word_list_.empty());
EXPECT_TRUE(private_data.available_words_.empty());
EXPECT_TRUE(private_data.word_map_.empty());
EXPECT_TRUE(private_data.char_word_map_.empty());
EXPECT_TRUE(private_data.word_id_history_map_.empty());
EXPECT_TRUE(private_data.history_id_word_map_.empty());
EXPECT_TRUE(private_data.history_info_map_.empty());
EXPECT_TRUE(private_data.word_starts_map_.empty());
HistoryIndexRestoreObserver restore_observer(
base::Bind(&base::MessageLoop::Quit, base::Unretained(&message_loop_)));
url_index_->set_restore_cache_observer(&restore_observer);
PostRestoreFromCacheFileTask();
message_loop_.Run();
EXPECT_TRUE(restore_observer.succeeded());
URLIndexPrivateData& new_data(*GetPrivateData());
EXPECT_GT(new_data.restored_cache_version_, 0);
EXPECT_EQ(rebuild_time, new_data.last_time_rebuilt_from_history_);
ExpectPrivateDataEqual(*old_data.get(), new_data);
}
TEST_F(InMemoryURLIndexTest, RebuildFromHistoryIfCacheOld) {
base::ScopedTempDir temp_directory;
ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
set_history_dir(temp_directory.path());
URLIndexPrivateData& private_data(*GetPrivateData());
EXPECT_FALSE(private_data.word_list_.empty());
EXPECT_TRUE(private_data.available_words_.empty());
EXPECT_FALSE(private_data.word_map_.empty());
EXPECT_FALSE(private_data.char_word_map_.empty());
EXPECT_FALSE(private_data.word_id_history_map_.empty());
EXPECT_FALSE(private_data.history_id_word_map_.empty());
EXPECT_FALSE(private_data.history_info_map_.empty());
EXPECT_FALSE(private_data.word_starts_map_.empty());
EXPECT_EQ(0, private_data.restored_cache_version_);
const base::Time fake_rebuild_time =
base::Time::Now() - base::TimeDelta::FromDays(30);
private_data.last_time_rebuilt_from_history_ = fake_rebuild_time;
scoped_refptr<URLIndexPrivateData> old_data(private_data.Duplicate());
CacheFileSaverObserver save_observer(&message_loop_);
url_index_->set_save_cache_observer(&save_observer);
PostSaveToCacheFileTask();
message_loop_.Run();
EXPECT_TRUE(save_observer.succeeded_);
ClearPrivateData();
EXPECT_TRUE(private_data.word_list_.empty());
EXPECT_TRUE(private_data.available_words_.empty());
EXPECT_TRUE(private_data.word_map_.empty());
EXPECT_TRUE(private_data.char_word_map_.empty());
EXPECT_TRUE(private_data.word_id_history_map_.empty());
EXPECT_TRUE(private_data.history_id_word_map_.empty());
EXPECT_TRUE(private_data.history_info_map_.empty());
EXPECT_TRUE(private_data.word_starts_map_.empty());
HistoryIndexRestoreObserver restore_observer(
base::Bind(&base::MessageLoop::Quit, base::Unretained(&message_loop_)));
url_index_->set_restore_cache_observer(&restore_observer);
PostRestoreFromCacheFileTask();
message_loop_.Run();
EXPECT_TRUE(restore_observer.succeeded());
URLIndexPrivateData& new_data(*GetPrivateData());
EXPECT_EQ(0, new_data.restored_cache_version_);
EXPECT_NE(fake_rebuild_time, new_data.last_time_rebuilt_from_history_);
ExpectPrivateDataEqual(*old_data.get(), new_data);
}
class InMemoryURLIndexCacheTest : public testing::Test {
public:
InMemoryURLIndexCacheTest() {}
protected:
virtual void SetUp() OVERRIDE;
void set_history_dir(const base::FilePath& dir_path);
bool GetCacheFilePath(base::FilePath* file_path) const;
base::ScopedTempDir temp_dir_;
scoped_ptr<InMemoryURLIndex> url_index_;
};
void InMemoryURLIndexCacheTest::SetUp() {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
base::FilePath path(temp_dir_.path());
url_index_.reset(
new InMemoryURLIndex(NULL, path, "en,ja,hi,zh"));
}
void InMemoryURLIndexCacheTest::set_history_dir(
const base::FilePath& dir_path) {
return url_index_->set_history_dir(dir_path);
}
bool InMemoryURLIndexCacheTest::GetCacheFilePath(
base::FilePath* file_path) const {
DCHECK(file_path);
return url_index_->GetCacheFilePath(file_path);
}
TEST_F(InMemoryURLIndexCacheTest, CacheFilePath) {
base::FilePath expectedPath =
temp_dir_.path().Append(FILE_PATH_LITERAL("History Provider Cache"));
std::vector<base::FilePath::StringType> expected_parts;
expectedPath.GetComponents(&expected_parts);
base::FilePath full_file_path;
ASSERT_TRUE(GetCacheFilePath(&full_file_path));
std::vector<base::FilePath::StringType> actual_parts;
full_file_path.GetComponents(&actual_parts);
ASSERT_EQ(expected_parts.size(), actual_parts.size());
size_t count = expected_parts.size();
for (size_t i = 0; i < count; ++i)
EXPECT_EQ(expected_parts[i], actual_parts[i]);
set_history_dir(base::FilePath());
}
}