history_contents_provider_unittest.cc revision 4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7
1// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/file_util.h" 6#include "base/path_service.h" 7#include "base/string_util.h" 8#include "base/utf_string_conversions.h" 9#include "chrome/browser/autocomplete/autocomplete.h" 10#include "chrome/browser/autocomplete/autocomplete_match.h" 11#include "chrome/browser/autocomplete/history_contents_provider.h" 12#include "chrome/browser/bookmarks/bookmark_model.h" 13#include "chrome/browser/browser_thread.h" 14#include "chrome/browser/history/history.h" 15#include "chrome/test/testing_profile.h" 16#include "testing/gtest/include/gtest/gtest.h" 17 18using base::Time; 19using base::TimeDelta; 20 21namespace { 22 23struct TestEntry { 24 const char* url; 25 const char* title; 26 const char* body; 27} test_entries[] = { 28 {"http://www.google.com/1", "PAGEONE 1", "FOO some body text"}, 29 {"http://www.google.com/2", "PAGEONE 2", "FOO some more blah blah"}, 30 {"http://www.google.com/3", "PAGETHREE 3", "BAR some hello world for you"}, 31}; 32 33class HistoryContentsProviderTest : public testing::Test, 34 public ACProviderListener { 35 public: 36 HistoryContentsProviderTest() 37 : ui_thread_(BrowserThread::UI, &message_loop_), 38 file_thread_(BrowserThread::FILE, &message_loop_) {} 39 40 void RunQuery(const AutocompleteInput& input, 41 bool minimal_changes) { 42 provider_->Start(input, minimal_changes); 43 44 // When we're waiting for asynchronous messages, we have to spin the message 45 // loop. This will be exited in the OnProviderUpdate function when complete. 46 if (!input.synchronous_only()) 47 MessageLoop::current()->Run(); 48 } 49 50 const ACMatches& matches() const { return provider_->matches(); } 51 52 TestingProfile* profile() const { return profile_.get(); } 53 54 HistoryContentsProvider* provider() const { return provider_.get(); } 55 56 private: 57 // testing::Test 58 virtual void SetUp() { 59 profile_.reset(new TestingProfile()); 60 profile_->CreateHistoryService(false, false); 61 62 HistoryService* history_service = 63 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); 64 65 // Populate history. 66 for (size_t i = 0; i < arraysize(test_entries); i++) { 67 // We need the ID scope and page ID so that the visit tracker can find it. 68 // We just use the index for the page ID below. 69 const void* id_scope = reinterpret_cast<void*>(1); 70 GURL url(test_entries[i].url); 71 72 // Add everything in order of time. We don't want to have a time that 73 // is "right now" or it will nondeterministically appear in the results. 74 Time t = Time::Now() - TimeDelta::FromDays(arraysize(test_entries) + i); 75 76 history_service->AddPage(url, t, id_scope, i, GURL(), 77 PageTransition::LINK, history::RedirectList(), 78 history::SOURCE_BROWSED, false); 79 history_service->SetPageTitle(url, UTF8ToUTF16(test_entries[i].title)); 80 history_service->SetPageContents(url, UTF8ToUTF16(test_entries[i].body)); 81 } 82 83 provider_ = new HistoryContentsProvider(this, profile_.get()); 84 } 85 86 virtual void TearDown() { 87 provider_ = NULL; 88 profile_.reset(NULL); 89 } 90 91 // ACProviderListener 92 virtual void OnProviderUpdate(bool updated_matches) { 93 // When we quit, the test will get back control. 94 MessageLoop::current()->Quit(); 95 } 96 97 MessageLoopForUI message_loop_; 98 BrowserThread ui_thread_; 99 BrowserThread file_thread_; 100 101 std::wstring history_dir_; 102 103 scoped_ptr<TestingProfile> profile_; 104 scoped_refptr<HistoryContentsProvider> provider_; 105}; 106 107TEST_F(HistoryContentsProviderTest, Body) { 108 AutocompleteInput input(L"FOO", std::wstring(), true, false, true, false); 109 RunQuery(input, false); 110 111 // The results should be the first two pages, in decreasing order. 112 const ACMatches& m = matches(); 113 ASSERT_EQ(2U, m.size()); 114 EXPECT_EQ(test_entries[0].url, m[0].destination_url.spec()); 115 EXPECT_STREQ(test_entries[0].title, WideToUTF8(m[0].description).c_str()); 116 EXPECT_EQ(test_entries[1].url, m[1].destination_url.spec()); 117 EXPECT_STREQ(test_entries[1].title, WideToUTF8(m[1].description).c_str()); 118} 119 120TEST_F(HistoryContentsProviderTest, Title) { 121 AutocompleteInput input(L"PAGEONE", std::wstring(), true, false, true, false); 122 RunQuery(input, false); 123 124 // The results should be the first two pages. 125 const ACMatches& m = matches(); 126 ASSERT_EQ(2U, m.size()); 127 EXPECT_EQ(test_entries[0].url, m[0].destination_url.spec()); 128 EXPECT_STREQ(test_entries[0].title, WideToUTF8(m[0].description).c_str()); 129 EXPECT_EQ(test_entries[1].url, m[1].destination_url.spec()); 130 EXPECT_STREQ(test_entries[1].title, WideToUTF8(m[1].description).c_str()); 131} 132 133// The "minimal changes" flag should mean that we don't re-query the DB. 134TEST_F(HistoryContentsProviderTest, MinimalChanges) { 135 // A minimal changes request when there have been no real queries should 136 // give us no results. 137 AutocompleteInput sync_input(L"PAGEONE", std::wstring(), true, false, true, 138 true); 139 RunQuery(sync_input, true); 140 const ACMatches& m1 = matches(); 141 EXPECT_EQ(0U, m1.size()); 142 143 // Now do a "regular" query to get the results. 144 AutocompleteInput async_input(L"PAGEONE", std::wstring(), true, false, true, 145 false); 146 RunQuery(async_input, false); 147 const ACMatches& m2 = matches(); 148 EXPECT_EQ(2U, m2.size()); 149 150 // Now do a minimal one where we want synchronous results, and the results 151 // should still be there. 152 RunQuery(sync_input, true); 153 const ACMatches& m3 = matches(); 154 EXPECT_EQ(2U, m3.size()); 155} 156 157// Tests that the BookmarkModel is queried correctly. 158TEST_F(HistoryContentsProviderTest, Bookmarks) { 159 profile()->CreateBookmarkModel(false); 160 profile()->BlockUntilBookmarkModelLoaded(); 161 162 // Add a bookmark. 163 GURL bookmark_url("http://www.google.com/4"); 164 profile()->GetBookmarkModel()->SetURLStarred(bookmark_url, 165 ASCIIToUTF16("bar"), true); 166 167 // Ask for synchronous. This should only get the bookmark. 168 AutocompleteInput sync_input(L"bar", std::wstring(), true, false, true, true); 169 RunQuery(sync_input, false); 170 const ACMatches& m1 = matches(); 171 ASSERT_EQ(1U, m1.size()); 172 EXPECT_EQ(bookmark_url, m1[0].destination_url); 173 EXPECT_EQ(L"bar", m1[0].description); 174 EXPECT_TRUE(m1[0].starred); 175 176 // Ask for async. We should get the bookmark immediately. 177 AutocompleteInput async_input(L"bar", std::wstring(), true, false, true, 178 false); 179 provider()->Start(async_input, false); 180 const ACMatches& m2 = matches(); 181 ASSERT_EQ(1U, m2.size()); 182 EXPECT_EQ(bookmark_url, m2[0].destination_url); 183 184 // Run the message loop (needed for async history results). 185 MessageLoop::current()->Run(); 186 187 // We should two urls now, bookmark_url and http://www.google.com/3. 188 const ACMatches& m3 = matches(); 189 ASSERT_EQ(2U, m3.size()); 190 if (bookmark_url == m3[0].destination_url) { 191 EXPECT_EQ("http://www.google.com/3", m3[1].destination_url.spec()); 192 } else { 193 EXPECT_EQ(bookmark_url, m3[1].destination_url); 194 EXPECT_EQ("http://www.google.com/3", m3[0].destination_url.spec()); 195 } 196} 197 198} // namespace 199