This source file includes following definitions.
- NthResultIs
 
- QueryHistory
 
- TestPaging
 
- AddEntryToHistory
 
- SetUp
 
- TearDown
 
- QueryHistoryComplete
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/history/history_service.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::Time;
using base::TimeDelta;
namespace history {
namespace {
struct TestEntry {
  const char* url;
  const char* title;
  const int days_ago;
  Time time;  
} test_entries[] = {
  
  
  {"http://example.com/", "Other", 180},
  
  
  
  {"http://www.google.com/1", "Title PAGEONE FOO some text", 10},
  {"http://www.google.com/3", "Title PAGETHREE BAR some hello world", 8},
  {"http://www.google.com/2", "Title PAGETWO FOO some more blah blah blah", 9},
  
  {"http://example.com/", "Other", 6},
  {"http://www.google.com/6", "Title I'm the second oldest", 13},
  {"http://www.google.com/4", "Title four", 12},
  {"http://www.google.com/5", "Title five", 11},
};
bool NthResultIs(const QueryResults& results,
                 int n,  
                 int test_entry_index) {  
  if (static_cast<int>(results.size()) <= n)
    return false;
  const URLResult& result = results[n];
  
  if (result.visit_time() != test_entries[test_entry_index].time)
    return false;
  
  return result.url() == GURL(test_entries[test_entry_index].url) &&
         result.title() ==
             base::UTF8ToUTF16(test_entries[test_entry_index].title);
}
}  
class HistoryQueryTest : public testing::Test {
 public:
  HistoryQueryTest() : page_id_(0) {
  }
  
  void QueryHistory(const std::string& text_query,
                    const QueryOptions& options,
                    QueryResults* results) {
    history_->QueryHistory(
        base::UTF8ToUTF16(text_query), options, &consumer_,
        base::Bind(&HistoryQueryTest::QueryHistoryComplete,
                   base::Unretained(this)));
    
    base::MessageLoop::current()->Run();
    results->Swap(&last_query_results_);
  }
  
  
  
  void TestPaging(const std::string& query_text,
                  const int* expected_results,
                  int results_length) {
    ASSERT_TRUE(history_.get());
    QueryOptions options;
    QueryResults results;
    options.max_count = 1;
    for (int i = 0; i < results_length; i++) {
      SCOPED_TRACE(testing::Message() << "i = " << i);
      QueryHistory(query_text, options, &results);
      ASSERT_EQ(1U, results.size());
      EXPECT_TRUE(NthResultIs(results, 0, expected_results[i]));
      options.end_time = results.back().visit_time();
    }
    QueryHistory(query_text, options, &results);
    EXPECT_EQ(0U, results.size());
    
    options.max_count = 2;
    options.end_time = base::Time();
    for (int i = 0; i < results_length / 2; i++) {
      SCOPED_TRACE(testing::Message() << "i = " << i);
      QueryHistory(query_text, options, &results);
      ASSERT_EQ(2U, results.size());
      EXPECT_TRUE(NthResultIs(results, 0, expected_results[i * 2]));
      EXPECT_TRUE(NthResultIs(results, 1, expected_results[i * 2 + 1]));
      options.end_time = results.back().visit_time();
    }
    
    
    TestEntry duplicates[] = {
      { "http://www.google.com/x",  query_text.c_str(), 1, },
      { "http://www.google.com/y",  query_text.c_str(), 1, }
    };
    AddEntryToHistory(duplicates[0]);
    AddEntryToHistory(duplicates[1]);
    
    options.end_time = base::Time();
    do {
      QueryHistory(query_text, options, &results);
      ASSERT_NE(options.end_time, results.back().visit_time());
      options.end_time = results.back().visit_time();
    } while (!results.reached_beginning());
  }
 protected:
  scoped_ptr<HistoryService> history_;
  
  int32 page_id_;
  void AddEntryToHistory(const TestEntry& entry) {
    
    const void* id_scope = reinterpret_cast<void*>(1);
    GURL url(entry.url);
    history_->AddPage(url, entry.time, id_scope, page_id_++, GURL(),
                      history::RedirectList(), content::PAGE_TRANSITION_LINK,
                      history::SOURCE_BROWSED, false);
    history_->SetPageTitle(url, base::UTF8ToUTF16(entry.title));
  }
 private:
  virtual void SetUp() {
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
    history_dir_ = temp_dir_.path().AppendASCII("HistoryTest");
    ASSERT_TRUE(base::CreateDirectory(history_dir_));
    history_.reset(new HistoryService);
    if (!history_->Init(history_dir_, NULL)) {
      history_.reset();  
      return;
    }
    
    Time now = Time::Now().LocalMidnight();
    for (size_t i = 0; i < arraysize(test_entries); i++) {
      test_entries[i].time =
          now - (test_entries[i].days_ago * TimeDelta::FromDays(1));
      AddEntryToHistory(test_entries[i]);
    }
  }
  virtual void TearDown() {
    if (history_) {
      history_->SetOnBackendDestroyTask(base::MessageLoop::QuitClosure());
      history_->Cleanup();
      history_.reset();
      base::MessageLoop::current()->Run();  
    }
  }
  void QueryHistoryComplete(HistoryService::Handle, QueryResults* results) {
    results->Swap(&last_query_results_);
    base::MessageLoop::current()->Quit();  
  }
  base::ScopedTempDir temp_dir_;
  base::MessageLoop message_loop_;
  base::FilePath history_dir_;
  CancelableRequestConsumer consumer_;
  
  
  QueryResults last_query_results_;
  DISALLOW_COPY_AND_ASSIGN(HistoryQueryTest);
};
TEST_F(HistoryQueryTest, Basic) {
  ASSERT_TRUE(history_.get());
  QueryOptions options;
  QueryResults results;
  
  
  QueryHistory(std::string(), options, &results);
  EXPECT_EQ(7U, results.size());
  EXPECT_TRUE(NthResultIs(results, 0, 4));
  EXPECT_TRUE(NthResultIs(results, 1, 2));
  EXPECT_TRUE(NthResultIs(results, 2, 3));
  EXPECT_TRUE(NthResultIs(results, 3, 1));
  EXPECT_TRUE(NthResultIs(results, 4, 7));
  EXPECT_TRUE(NthResultIs(results, 5, 6));
  EXPECT_TRUE(NthResultIs(results, 6, 5));
  
  
  options.begin_time = test_entries[3].time;
  options.end_time = test_entries[2].time;
  QueryHistory(std::string(), options, &results);
  EXPECT_EQ(1U, results.size());
  EXPECT_TRUE(NthResultIs(results, 0, 3));
}
TEST_F(HistoryQueryTest, BasicCount) {
  ASSERT_TRUE(history_.get());
  QueryOptions options;
  QueryResults results;
  
  
  options.max_count = 2;
  QueryHistory(std::string(), options, &results);
  EXPECT_EQ(2U, results.size());
  EXPECT_TRUE(NthResultIs(results, 0, 4));
  EXPECT_TRUE(NthResultIs(results, 1, 2));
}
TEST_F(HistoryQueryTest, ReachedBeginning) {
  ASSERT_TRUE(history_.get());
  QueryOptions options;
  QueryResults results;
  QueryHistory(std::string(), options, &results);
  EXPECT_TRUE(results.reached_beginning());
  QueryHistory("some", options, &results);
  EXPECT_TRUE(results.reached_beginning());
  options.begin_time = test_entries[1].time;
  QueryHistory(std::string(), options, &results);
  EXPECT_FALSE(results.reached_beginning());
  QueryHistory("some", options, &results);
  EXPECT_FALSE(results.reached_beginning());
  
  options.begin_time = test_entries[0].time + TimeDelta::FromMicroseconds(1);
  QueryHistory(std::string(), options, &results);
  EXPECT_FALSE(results.reached_beginning());
  QueryHistory("some", options, &results);
  EXPECT_FALSE(results.reached_beginning());
  
  options.begin_time = test_entries[0].time;
  QueryHistory(std::string(), options, &results);
  EXPECT_TRUE(results.reached_beginning());
  QueryHistory("some", options, &results);
  EXPECT_TRUE(results.reached_beginning());
  
  options.begin_time = test_entries[0].time - TimeDelta::FromMicroseconds(1);
  QueryHistory(std::string(), options, &results);
  EXPECT_TRUE(results.reached_beginning());
  QueryHistory("some", options, &results);
  EXPECT_TRUE(results.reached_beginning());
  
  options.max_count = 1;
  QueryHistory(std::string(), options, &results);
  EXPECT_FALSE(results.reached_beginning());
  QueryHistory("some", options, &results);
  EXPECT_FALSE(results.reached_beginning());
  
  
  options.max_count = 100;
  QueryHistory(std::string(), options, &results);
  EXPECT_TRUE(results.reached_beginning());
  options.max_count = results.size();
  QueryHistory(std::string(), options, &results);
  EXPECT_TRUE(results.reached_beginning());
  options.max_count = 100;
  QueryHistory("some", options, &results);
  EXPECT_TRUE(results.reached_beginning());
  options.max_count = results.size();
  QueryHistory("some", options, &results);
  EXPECT_TRUE(results.reached_beginning());
}
TEST_F(HistoryQueryTest, TextSearch) {
  ASSERT_TRUE(history_.get());
  QueryOptions options;
  QueryResults results;
  
  
  
  QueryHistory("some", options, &results);
  EXPECT_EQ(3U, results.size());
  EXPECT_TRUE(NthResultIs(results, 0, 2));
  EXPECT_TRUE(NthResultIs(results, 1, 3));
  EXPECT_TRUE(NthResultIs(results, 2, 1));
  
  QueryHistory("PAGETWO", options, &results);
  EXPECT_EQ(1U, results.size());
  EXPECT_TRUE(NthResultIs(results, 0, 3));
  
  
  options.begin_time = test_entries[1].time;
  options.end_time = test_entries[3].time;
  QueryHistory("some", options, &results);
  EXPECT_EQ(1U, results.size());
  EXPECT_TRUE(NthResultIs(results, 0, 1));
}
TEST_F(HistoryQueryTest, TextSearchPrefix) {
  ASSERT_TRUE(history_.get());
  QueryOptions options;
  QueryResults results;
  
  
  QueryHistory("PAGET", options, &results);
  EXPECT_EQ(2U, results.size());
  EXPECT_TRUE(NthResultIs(results, 0, 2));
  EXPECT_TRUE(NthResultIs(results, 1, 3));
}
TEST_F(HistoryQueryTest, TextSearchCount) {
  ASSERT_TRUE(history_.get());
  QueryOptions options;
  QueryResults results;
  
  
  options.max_count = 2;
  QueryHistory("some", options, &results);
  EXPECT_EQ(2U, results.size());
  EXPECT_TRUE(NthResultIs(results, 0, 2));
  EXPECT_TRUE(NthResultIs(results, 1, 3));
  
  
  
  options.max_count = 1;
  QueryHistory("FOO", options, &results);
  EXPECT_EQ(1U, results.size());
  EXPECT_TRUE(NthResultIs(results, 0, 3));
}
TEST_F(HistoryQueryTest, TextSearchArchived) {
  ASSERT_TRUE(history_.get());
  URLRows urls_to_add;
  URLRow row1(GURL("http://foo.bar/"));
  row1.set_title(base::UTF8ToUTF16("archived title same"));
  row1.set_last_visit(Time::Now() - TimeDelta::FromDays(365));
  urls_to_add.push_back(row1);
  URLRow row2(GURL("http://foo.bar/"));
  row2.set_title(base::UTF8ToUTF16("nonarchived title same"));
  row2.set_last_visit(Time::Now());
  urls_to_add.push_back(row2);
  history_->AddPagesWithDetails(urls_to_add, history::SOURCE_BROWSED);
  QueryOptions options;
  QueryResults results;
  
  
  
  QueryHistory("archived", options, &results);
  ASSERT_EQ(1U, results.size());
  EXPECT_TRUE(row1.url() == results[0].url());
  EXPECT_TRUE(row1.title() == results[0].title());
  
  
  QueryHistory("same", options, &results);
  ASSERT_EQ(2U, results.size());
  EXPECT_TRUE(row2.url() == results[0].url());
  EXPECT_TRUE(row2.title() == results[0].title());
  EXPECT_TRUE(row1.url() == results[1].url());
  EXPECT_TRUE(row1.title() == results[1].title());
}
TEST_F(HistoryQueryTest, TextSearchIDN) {
  ASSERT_TRUE(history_.get());
  QueryOptions options;
  QueryResults results;
  TestEntry entry = { "http://xn--d1abbgf6aiiy.xn--p1ai/",  "Nothing", 0, };
  AddEntryToHistory(entry);
  struct QueryEntry {
    std::string query;
    size_t results_size;
  } queries[] = {
    { "bad query", 0 },
    { std::string("xn--d1abbgf6aiiy.xn--p1ai"), 1 },
    { base::WideToUTF8(std::wstring(L"\u043f\u0440\u0435\u0437") +
                       L"\u0438\u0434\u0435\u043d\u0442.\u0440\u0444"), 1, },
  };
  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(queries); ++i) {
    QueryHistory(queries[i].query, options, &results);
    EXPECT_EQ(queries[i].results_size, results.size());
  }
}
TEST_F(HistoryQueryTest, Paging) {
  
  
  int expected_results[] = { 4, 2, 3, 1, 7, 6, 5, 0 };
  TestPaging(std::string(), expected_results, arraysize(expected_results));
}
TEST_F(HistoryQueryTest, TextSearchPaging) {
  
  
  
  int expected_results[] = { 2, 3, 1, 7, 6, 5 };
  TestPaging("title", expected_results, arraysize(expected_results));
}
}