Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(552)

Side by Side Diff: chrome/browser/ui/app_list/search/history_unittest.cc

Issue 15875007: app_list: Search result launch history and boost. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix guest mode crash Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 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/basictypes.h"
6 #include "base/bind.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/message_loop.h"
9 #include "base/run_loop.h"
10 #include "base/stringprintf.h"
11 #include "base/timer.h"
12 #include "chrome/browser/ui/app_list/search/history.h"
13 #include "chrome/browser/ui/app_list/search/history_data.h"
14 #include "chrome/browser/ui/app_list/search/history_data_observer.h"
15 #include "chrome/browser/ui/app_list/search/history_data_store.h"
16 #include "chrome/test/base/testing_profile.h"
17 #include "content/public/test/test_browser_thread.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace app_list {
21 namespace test {
22
23 namespace {
24
25 const size_t kMaxEntry = 3;
26 const size_t kMaxSecondary = 2;
27
28 class HistoryDataLoadWaiter : public HistoryDataObserver {
29 public:
30 explicit HistoryDataLoadWaiter(HistoryData* data) : data_(data) {}
31 virtual ~HistoryDataLoadWaiter() {}
32
33 void Wait(int wait_time_ms) {
James Cook 2013/05/23 21:51:08 This is not waiting in the normal case, it's just
xiyuan 2013/05/23 22:38:13 It is a normal wait. I usually like to put a limit
34 data_->AddObserver(this);
35
36 timer_.Start(FROM_HERE,
37 base::TimeDelta::FromMilliseconds(wait_time_ms),
38 this,
39 &HistoryDataLoadWaiter::OnTimeOut);
40
41 run_loop_.reset(new base::RunLoop);
42 run_loop_->Run();
43
44 data_->RemoveObserver(this);
45 }
46
47 private:
48 void OnTimeOut() {
49 run_loop_->Quit();
50 }
51
52 // HistoryDataObserver overrides:
53 virtual void OnHistoryDataLoadedFromStore() OVERRIDE {
54 run_loop_->Quit();
55 }
56
57 HistoryData* data_; // Not owned.
58 scoped_ptr<base::RunLoop> run_loop_;
59 base::OneShotTimer<HistoryDataLoadWaiter> timer_;
60
61 DISALLOW_COPY_AND_ASSIGN(HistoryDataLoadWaiter);
62 };
63
64 class StoreFlushWaiter {
65 public:
66 explicit StoreFlushWaiter(HistoryDataStore* store) : store_(store) {}
67 ~StoreFlushWaiter() {}
68
69 void Wait(int wait_time_ms) {
James Cook 2013/05/23 21:51:08 ditto
xiyuan 2013/05/23 22:38:13 Done.
70 store_->Flush(
71 base::Bind(&StoreFlushWaiter::OnFlushed, base::Unretained(this)));
72
73 timer_.Start(FROM_HERE,
74 base::TimeDelta::FromMilliseconds(wait_time_ms),
75 this,
76 &StoreFlushWaiter::OnTimeOut);
77
78 run_loop_.reset(new base::RunLoop);
79 run_loop_->Run();
80 }
81
82 private:
83 void OnTimeOut() {
84 run_loop_->Quit();
85 }
86
87 void OnFlushed() {
88 run_loop_->Quit();
89 }
90
91 HistoryDataStore* store_; // Not owned.
James Cook 2013/05/23 21:51:08 I like ownership comments!
92 scoped_ptr<base::RunLoop> run_loop_;
93 base::OneShotTimer<StoreFlushWaiter> timer_;
94
95 DISALLOW_COPY_AND_ASSIGN(StoreFlushWaiter);
96 };
97
98 } // namespace
99
100 class SearchHistoryTest : public testing::Test {
101 public:
102 SearchHistoryTest()
103 : ui_thread_(content::BrowserThread::UI, &message_loop_) {}
104 virtual ~SearchHistoryTest() {}
105
106 // testing::Test overrides:
107 virtual void SetUp() OVERRIDE {
108 profile_.reset(new TestingProfile);
109 CreateHistory();
110 }
111 virtual void TearDown() OVERRIDE {
112 Flush();
113 }
114
115 void CreateHistory() {
116 history_.reset(new History(profile_.get()));
117
118 // Replace |data_| with test params.
119 history_->data_->RemoveObserver(history_.get());
120 history_->data_.reset(new HistoryData(history_->store_,
121 kMaxEntry,
122 kMaxSecondary));
123 history_->data_->AddObserver(history_.get());
124
125 HistoryDataLoadWaiter waiter(history_->data_.get());
126 waiter.Wait(1000);
127 ASSERT_TRUE(history_->IsReady());
128 }
129
130 void Flush() {
131 StoreFlushWaiter waiter(history_->store_.get());
132 waiter.Wait(1000);
133 }
134
135 size_t GetKnownResults(const std::string& query) {
136 known_results_ = history()->GetKnownResults(query).Pass();
137 return known_results_->size();
138 }
139
140 KnownResultType GetResultType(const std::string& result_id) {
141 return known_results_->find(result_id) != known_results_->end()
142 ? (*known_results_.get())[result_id]
143 : UNKNOWN_RESULT;
144 }
145
146 History* history() { return history_.get(); }
147 const HistoryData::Associations& associations() const {
148 return history_->data_->associations();
149 }
150
151 private:
152 MessageLoopForUI message_loop_;
153 content::TestBrowserThread ui_thread_;
154 scoped_ptr<TestingProfile> profile_;
155
156 scoped_ptr<History> history_;
157 scoped_ptr<KnownResults> known_results_;
158
159 DISALLOW_COPY_AND_ASSIGN(SearchHistoryTest);
160 };
161
162 TEST_F(SearchHistoryTest, Persistence) {
163 // Ensure it's empty.
164 EXPECT_EQ(0u, GetKnownResults("cal"));
165
166 // Add one launch event.
167 history()->AddLaunchEvent("cal", "calendar");
168 EXPECT_EQ(1u, GetKnownResults("cal"));
169
170 // Flush and recreate the history object.
171 Flush();
172 CreateHistory();
173
174 // History should be initialized with data just added.
175 EXPECT_EQ(1u, GetKnownResults("cal"));
176 }
177
178 TEST_F(SearchHistoryTest, PerfectAndPrefixMatch) {
179 const char kQuery[] = "cal";
180 const char kQueryPrefix[] = "c";
181 const char kPrimary[] = "calendar";
182 const char kSecondary[] = "calculator";
183
184 history()->AddLaunchEvent(kQuery, kPrimary);
185 history()->AddLaunchEvent(kQuery, kSecondary);
186
187 EXPECT_EQ(2u, GetKnownResults(kQuery));
188 EXPECT_EQ(PERFECT_PRIMARY, GetResultType(kPrimary));
189 EXPECT_EQ(PERFECT_SECONDARY, GetResultType(kSecondary));
190
191 EXPECT_EQ(2u, GetKnownResults(kQueryPrefix));
192 EXPECT_EQ(PREFIX_PRIMARY, GetResultType(kPrimary));
193 EXPECT_EQ(PREFIX_SECONDARY, GetResultType(kSecondary));
194 }
195
196 TEST_F(SearchHistoryTest, StickyPrimary) {
197 const char kQuery[] = "cal";
198 const char kPrimary[] = "calendar";
199 const char kSecondary[] = "calculator";
200 const char kOther[] = "other";
201
202 // Add two launch events. kPrimary becomes primary.
203 history()->AddLaunchEvent(kQuery, kPrimary);
204 history()->AddLaunchEvent(kQuery, kSecondary);
205
206 EXPECT_EQ(2u, GetKnownResults(kQuery));
207 EXPECT_EQ(PERFECT_PRIMARY, GetResultType(kPrimary));
208 EXPECT_EQ(PERFECT_SECONDARY, GetResultType(kSecondary));
209
210 // These launch events should not change primary.
211 history()->AddLaunchEvent(kQuery, kPrimary);
212 history()->AddLaunchEvent(kQuery, kSecondary);
213 history()->AddLaunchEvent(kQuery, kPrimary);
214 history()->AddLaunchEvent(kQuery, kSecondary);
215 history()->AddLaunchEvent(kQuery, kPrimary);
216 history()->AddLaunchEvent(kQuery, kSecondary);
217 history()->AddLaunchEvent(kQuery, kOther);
218 history()->AddLaunchEvent(kQuery, kSecondary);
219 history()->AddLaunchEvent(kQuery, kOther);
220 history()->AddLaunchEvent(kQuery, kSecondary);
221 history()->AddLaunchEvent(kQuery, kOther);
222
223 EXPECT_EQ(3u, GetKnownResults(kQuery));
224 EXPECT_EQ(PERFECT_PRIMARY, GetResultType(kPrimary));
225 EXPECT_EQ(PERFECT_SECONDARY, GetResultType(kSecondary));
226 EXPECT_EQ(PERFECT_SECONDARY, GetResultType(kOther));
227 }
228
229 TEST_F(SearchHistoryTest, PromoteSecondary) {
230 const char kQuery[] = "cal";
231 const char kPrimary[] = "calendar";
232 const char kSecondary[] = "calculator";
233
234 history()->AddLaunchEvent(kQuery, kPrimary);
235 history()->AddLaunchEvent(kQuery, kSecondary);
236
237 EXPECT_EQ(2u, GetKnownResults(kQuery));
238 EXPECT_EQ(PERFECT_PRIMARY, GetResultType(kPrimary));
239 EXPECT_EQ(PERFECT_SECONDARY, GetResultType(kSecondary));
240
241 // The 2nd launch in a row promotes it to be primary.
242 history()->AddLaunchEvent(kQuery, kSecondary);
243
244 EXPECT_EQ(2u, GetKnownResults(kQuery));
245 EXPECT_EQ(PERFECT_PRIMARY, GetResultType(kSecondary));
246 EXPECT_EQ(PERFECT_SECONDARY, GetResultType(kPrimary));
247 }
248
249 TEST_F(SearchHistoryTest, MaxEntry) {
250 for (size_t i = 0; i < kMaxEntry; ++i) {
251 std::string query = base::StringPrintf("%d", static_cast<int>(i));
252 history()->AddLaunchEvent(query, "app");
253 }
254 EXPECT_EQ(kMaxEntry, associations().size());
255
256 // Oldest entries still exists.
257 EXPECT_TRUE(associations().find("0") != associations().end());
258 EXPECT_TRUE(associations().find("1") != associations().end());
259
260 // Touches the oldest and 2nd oldest becomes oldest now..
261 history()->AddLaunchEvent("0", "app");
262
263 // Adds one more
264 history()->AddLaunchEvent("extra", "app");
265
266 // Number of entries are capped to kMaxEntry.
267 EXPECT_EQ(kMaxEntry, associations().size());
268
269 // Oldest entry is trimmed.
270 EXPECT_FALSE(associations().find("1") != associations().end());
271
272 // The touched oldest survived.
273 EXPECT_TRUE(associations().find("0") != associations().end());
274 }
275
276 TEST_F(SearchHistoryTest, MaxSecondary) {
277 const char kQuery[] = "query";
278 history()->AddLaunchEvent(kQuery, "primary");
279 for (size_t i = 0; i < kMaxSecondary; ++i) {
280 std::string result_id = base::StringPrintf("%d", static_cast<int>(i));
281 history()->AddLaunchEvent(kQuery, result_id);
282 }
283
284 EXPECT_EQ(kMaxSecondary + 1, GetKnownResults(kQuery));
285 EXPECT_EQ(PERFECT_SECONDARY, GetResultType("0"));
286 EXPECT_EQ(PERFECT_SECONDARY, GetResultType("1"));
287
288 // Touches the oldest secondary.
289 history()->AddLaunchEvent(kQuery, "0");
290
291 // Adds one more.
292 history()->AddLaunchEvent(kQuery, "extra");
293
294 // Total number of results is capped.
295 EXPECT_EQ(kMaxSecondary + 1, GetKnownResults(kQuery));
296
297 // The oldest secondary is gone.
298 EXPECT_EQ(UNKNOWN_RESULT, GetResultType("1"));
299
300 // Touched oldest survived.
301 EXPECT_EQ(PERFECT_SECONDARY, GetResultType("0"));
302 }
303
304 } // namespace test
305 } // namespace app_list
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698