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

Side by Side Diff: net/base/cookie_monster_perftest.cc

Issue 9703011: Move the cookie store implementation into its own directory. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: net/base/cookies/ -> net/cookies/ Created 8 years, 9 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
« no previous file with comments | « net/base/cookie_monster.cc ('k') | net/base/cookie_monster_store_test.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 <algorithm>
6
7 #include "base/bind.h"
8 #include "base/message_loop.h"
9 #include "base/perftimer.h"
10 #include "base/string_util.h"
11 #include "base/stringprintf.h"
12 #include "googleurl/src/gurl.h"
13 #include "net/base/cookie_monster.h"
14 #include "net/base/cookie_monster_store_test.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace {
18 class CookieMonsterTest : public testing::Test {
19 public:
20 CookieMonsterTest() : message_loop_(new MessageLoopForIO()) {}
21
22 private:
23 scoped_ptr<MessageLoop> message_loop_;
24 };
25 }
26
27 static const int kNumCookies = 20000;
28 static const char kCookieLine[] = "A = \"b=;\\\"\" ;secure;;;";
29
30 namespace net {
31
32 TEST(ParsedCookieTest, TestParseCookies) {
33 std::string cookie(kCookieLine);
34 PerfTimeLogger timer("Parsed_cookie_parse_cookies");
35 for (int i = 0; i < kNumCookies; ++i) {
36 CookieMonster::ParsedCookie pc(cookie);
37 EXPECT_TRUE(pc.IsValid());
38 }
39 timer.Done();
40 }
41
42 TEST(ParsedCookieTest, TestParseBigCookies) {
43 std::string cookie(3800, 'z');
44 cookie += kCookieLine;
45 PerfTimeLogger timer("Parsed_cookie_parse_big_cookies");
46 for (int i = 0; i < kNumCookies; ++i) {
47 CookieMonster::ParsedCookie pc(cookie);
48 EXPECT_TRUE(pc.IsValid());
49 }
50 timer.Done();
51 }
52
53 static const GURL kUrlGoogle("http://www.google.izzle");
54
55 class BaseCallback {
56 public:
57 BaseCallback() : has_run_(false) {}
58
59 protected:
60 void WaitForCallback() {
61 // Note that the performance tests currently all operate on a loaded cookie
62 // store (or, more precisely, one that has no backing persistent store).
63 // Therefore, callbacks will actually always complete synchronously. If the
64 // tests get more advanced we need to add other means of signaling
65 // completion.
66 MessageLoop::current()->RunAllPending();
67 EXPECT_TRUE(has_run_);
68 has_run_ = false;
69 }
70
71 void Run() {
72 has_run_ = true;
73 }
74
75 bool has_run_;
76 };
77
78
79 class SetCookieCallback : public BaseCallback {
80 public:
81 void SetCookie(
82 CookieMonster* cm, const GURL& gurl, const std::string& cookie) {
83 cm->SetCookieWithOptionsAsync(gurl, cookie, options_, base::Bind(
84 &SetCookieCallback::Run, base::Unretained(this)));
85 WaitForCallback();
86 }
87 private:
88 void Run(bool success) {
89 EXPECT_TRUE(success);
90 BaseCallback::Run();
91 }
92 net::CookieOptions options_;
93 };
94
95 class GetCookiesCallback : public BaseCallback {
96 public:
97 const std::string& GetCookies(CookieMonster* cm, const GURL& gurl) {
98 cm->GetCookiesWithOptionsAsync(gurl, options_, base::Bind(
99 &GetCookiesCallback::Run, base::Unretained(this)));
100 WaitForCallback();
101 return cookies_;
102 }
103
104 private:
105 void Run(const std::string& cookies) {
106 cookies_ = cookies;
107 BaseCallback::Run();
108 }
109 std::string cookies_;
110 net::CookieOptions options_;
111 };
112
113 class GetCookiesWithInfoCallback : public BaseCallback {
114 public:
115 const std::string& GetCookiesWithInfo(CookieMonster* cm, const GURL& gurl) {
116 cm->GetCookiesWithInfoAsync(gurl, options_, base::Bind(
117 &GetCookiesWithInfoCallback::Run,
118 base::Unretained(this)));
119 WaitForCallback();
120 return cookies_;
121 }
122
123 private:
124 void Run(
125 const std::string& cookie_line,
126 const std::vector<CookieStore::CookieInfo>& cookie_infos) {
127 cookies_ = cookie_line;
128 BaseCallback::Run();
129 }
130
131 std::string cookies_;
132 net::CookieOptions options_;
133 };
134
135
136 TEST_F(CookieMonsterTest, TestAddCookiesOnSingleHost) {
137 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
138 std::vector<std::string> cookies;
139 for (int i = 0; i < kNumCookies; i++) {
140 cookies.push_back(base::StringPrintf("a%03d=b", i));
141 }
142
143 SetCookieCallback setCookieCallback;
144
145 // Add a bunch of cookies on a single host
146 PerfTimeLogger timer("Cookie_monster_add_single_host");
147
148 for (std::vector<std::string>::const_iterator it = cookies.begin();
149 it != cookies.end(); ++it) {
150 setCookieCallback.SetCookie(cm, kUrlGoogle, *it);
151 }
152 timer.Done();
153
154 GetCookiesCallback getCookiesCallback;
155
156 PerfTimeLogger timer2("Cookie_monster_query_single_host");
157 for (std::vector<std::string>::const_iterator it = cookies.begin();
158 it != cookies.end(); ++it) {
159 getCookiesCallback.GetCookies(cm, kUrlGoogle);
160 }
161 timer2.Done();
162
163 PerfTimeLogger timer3("Cookie_monster_deleteall_single_host");
164 cm->DeleteAllAsync(CookieMonster::DeleteCallback());
165 MessageLoop::current()->RunAllPending();
166 timer3.Done();
167 }
168
169 TEST_F(CookieMonsterTest, TestAddCookieOnManyHosts) {
170 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
171 std::string cookie(kCookieLine);
172 std::vector<GURL> gurls; // just wanna have ffffuunnn
173 for (int i = 0; i < kNumCookies; ++i) {
174 gurls.push_back(GURL(base::StringPrintf("https://a%04d.izzle", i)));
175 }
176
177 SetCookieCallback setCookieCallback;
178
179 // Add a cookie on a bunch of host
180 PerfTimeLogger timer("Cookie_monster_add_many_hosts");
181 for (std::vector<GURL>::const_iterator it = gurls.begin();
182 it != gurls.end(); ++it) {
183 setCookieCallback.SetCookie(cm, *it, cookie);
184 }
185 timer.Done();
186
187 GetCookiesCallback getCookiesCallback;
188
189 PerfTimeLogger timer2("Cookie_monster_query_many_hosts");
190 for (std::vector<GURL>::const_iterator it = gurls.begin();
191 it != gurls.end(); ++it) {
192 getCookiesCallback.GetCookies(cm, *it);
193 }
194 timer2.Done();
195
196 PerfTimeLogger timer3("Cookie_monster_deleteall_many_hosts");
197 cm->DeleteAllAsync(CookieMonster::DeleteCallback());
198 MessageLoop::current()->RunAllPending();
199 timer3.Done();
200 }
201
202 TEST_F(CookieMonsterTest, TestGetCookiesWithInfo) {
203 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
204
205 std::vector<GURL> gurls;
206 for (int i = 0; i < kNumCookies; ++i)
207 gurls.push_back(GURL(base::StringPrintf("https://a%04d.izzle", i)));
208
209 SetCookieCallback setCookieCallback;
210
211 for (std::vector<GURL>::const_iterator it = gurls.begin();
212 it != gurls.end(); ++it) {
213 setCookieCallback.SetCookie(cm, *it, kCookieLine);
214 }
215
216 GetCookiesWithInfoCallback getCookiesCallback;
217
218 PerfTimeLogger timer("Cookie_monster_get_cookie_info");
219 for (std::vector<GURL>::const_iterator it = gurls.begin();
220 it != gurls.end(); ++it) {
221 getCookiesCallback.GetCookiesWithInfo(cm, *it);
222 }
223 timer.Done();
224 }
225
226 static int CountInString(const std::string& str, char c) {
227 return std::count(str.begin(), str.end(), c);
228 }
229
230 TEST_F(CookieMonsterTest, TestDomainTree) {
231 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
232 GetCookiesCallback getCookiesCallback;
233 SetCookieCallback setCookieCallback;
234 const char* domain_cookie_format_tree = "a=b; domain=%s";
235 const std::string domain_base("top.com");
236
237 std::vector<std::string> domain_list;
238
239 // Create a balanced binary tree of domains on which the cookie is set.
240 domain_list.push_back(domain_base);
241 for (int i1 = 0; i1 < 2; i1++) {
242 std::string domain_base_1((i1 ? "a." : "b.") + domain_base);
243 EXPECT_EQ("top.com", cm->GetKey(domain_base_1));
244 domain_list.push_back(domain_base_1);
245 for (int i2 = 0; i2 < 2; i2++) {
246 std::string domain_base_2((i2 ? "a." : "b.") + domain_base_1);
247 EXPECT_EQ("top.com", cm->GetKey(domain_base_2));
248 domain_list.push_back(domain_base_2);
249 for (int i3 = 0; i3 < 2; i3++) {
250 std::string domain_base_3((i3 ? "a." : "b.") + domain_base_2);
251 EXPECT_EQ("top.com", cm->GetKey(domain_base_3));
252 domain_list.push_back(domain_base_3);
253 for (int i4 = 0; i4 < 2; i4++) {
254 std::string domain_base_4((i4 ? "a." : "b.") + domain_base_3);
255 EXPECT_EQ("top.com", cm->GetKey(domain_base_4));
256 domain_list.push_back(domain_base_4);
257 }
258 }
259 }
260 }
261
262
263 EXPECT_EQ(31u, domain_list.size());
264 for (std::vector<std::string>::const_iterator it = domain_list.begin();
265 it != domain_list.end(); it++) {
266 GURL gurl("https://" + *it + "/");
267 const std::string cookie = base::StringPrintf(domain_cookie_format_tree,
268 it->c_str());
269 setCookieCallback.SetCookie(cm, gurl, cookie);
270 }
271 EXPECT_EQ(31u, cm->GetAllCookies().size());
272
273 GURL probe_gurl("https://b.a.b.a.top.com/");
274 std::string cookie_line = getCookiesCallback.GetCookies(cm, probe_gurl);
275 EXPECT_EQ(5, CountInString(cookie_line, '=')) << "Cookie line: " <<
276 cookie_line;
277 PerfTimeLogger timer("Cookie_monster_query_domain_tree");
278 for (int i = 0; i < kNumCookies; i++) {
279 getCookiesCallback.GetCookies(cm, probe_gurl);
280 }
281 timer.Done();
282 }
283
284 TEST_F(CookieMonsterTest, TestDomainLine) {
285 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
286 SetCookieCallback setCookieCallback;
287 GetCookiesCallback getCookiesCallback;
288 std::vector<std::string> domain_list;
289 GURL probe_gurl("https://b.a.b.a.top.com/");
290 std::string cookie_line;
291
292 // Create a line of 32 domain cookies such that all cookies stored
293 // by effective TLD+1 will apply to probe GURL.
294 // (TLD + 1 is the level above .com/org/net/etc, e.g. "top.com"
295 // or "google.com". "Effective" is added to include sites like
296 // bbc.co.uk, where the effetive TLD+1 is more than one level
297 // below the top level.)
298 domain_list.push_back("a.top.com");
299 domain_list.push_back("b.a.top.com");
300 domain_list.push_back("a.b.a.top.com");
301 domain_list.push_back("b.a.b.a.top.com");
302 EXPECT_EQ(4u, domain_list.size());
303
304 const char* domain_cookie_format_line = "a%03d=b; domain=%s";
305 for (int i = 0; i < 8; i++) {
306 for (std::vector<std::string>::const_iterator it = domain_list.begin();
307 it != domain_list.end(); it++) {
308 GURL gurl("https://" + *it + "/");
309 const std::string cookie = base::StringPrintf(domain_cookie_format_line,
310 i, it->c_str());
311 setCookieCallback.SetCookie(cm, gurl, cookie);
312 }
313 }
314
315 cookie_line = getCookiesCallback.GetCookies(cm, probe_gurl);
316 EXPECT_EQ(32, CountInString(cookie_line, '='));
317 PerfTimeLogger timer2("Cookie_monster_query_domain_line");
318 for (int i = 0; i < kNumCookies; i++) {
319 getCookiesCallback.GetCookies(cm, probe_gurl);
320 }
321 timer2.Done();
322 }
323
324 TEST_F(CookieMonsterTest, TestImport) {
325 scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
326 std::vector<CookieMonster::CanonicalCookie*> initial_cookies;
327 GetCookiesCallback getCookiesCallback;
328
329 // We want to setup a fairly large backing store, with 300 domains of 50
330 // cookies each. Creation times must be unique.
331 int64 time_tick(base::Time::Now().ToInternalValue());
332
333 for (int domain_num = 0; domain_num < 300; domain_num++) {
334 std::string domain_name(base::StringPrintf(".Domain_%d.com", domain_num));
335 std::string gurl("www" + domain_name);
336 for (int cookie_num = 0; cookie_num < 50; cookie_num++) {
337 std::string cookie_line(base::StringPrintf("Cookie_%d=1; Path=/",
338 cookie_num));
339 AddCookieToList(gurl, cookie_line,
340 base::Time::FromInternalValue(time_tick++),
341 &initial_cookies);
342 }
343 }
344
345 store->SetLoadExpectation(true, initial_cookies);
346
347 scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL));
348
349 // Import will happen on first access.
350 GURL gurl("www.google.com");
351 CookieOptions options;
352 PerfTimeLogger timer("Cookie_monster_import_from_store");
353 getCookiesCallback.GetCookies(cm, gurl);
354 timer.Done();
355
356 // Just confirm keys were set as expected.
357 EXPECT_EQ("domain_1.com", cm->GetKey("www.Domain_1.com"));
358 }
359
360 TEST_F(CookieMonsterTest, TestGetKey) {
361 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
362 PerfTimeLogger timer("Cookie_monster_get_key");
363 for (int i = 0; i < kNumCookies; i++)
364 cm->GetKey("www.google.com");
365 timer.Done();
366 }
367
368 // This test is probing for whether garbage collection happens when it
369 // shouldn't. This will not in general be visible functionally, since
370 // if GC runs twice in a row without any change to the store, the second
371 // GC run will not do anything the first one didn't. That's why this is
372 // a performance test. The test should be considered to pass if all the
373 // times reported are approximately the same--this indicates that no GC
374 // happened repeatedly for any case.
375 TEST_F(CookieMonsterTest, TestGCTimes) {
376 SetCookieCallback setCookieCallback;
377
378 const struct TestCase {
379 const char* name;
380 int num_cookies;
381 int num_old_cookies;
382 } test_cases[] = {
383 {
384 // A whole lot of recent cookies; gc shouldn't happen.
385 "all_recent",
386 CookieMonster::kMaxCookies * 2,
387 0,
388 }, {
389 // Some old cookies, but still overflowing max.
390 "mostly_recent",
391 CookieMonster::kMaxCookies * 2,
392 CookieMonster::kMaxCookies / 2,
393 }, {
394 // Old cookies enough to bring us right down to our purge line.
395 "balanced",
396 CookieMonster::kMaxCookies * 2,
397 CookieMonster::kMaxCookies + CookieMonster::kPurgeCookies + 1,
398 }, {
399 "mostly_old",
400 // Old cookies enough to bring below our purge line (which we
401 // shouldn't do).
402 CookieMonster::kMaxCookies * 2,
403 CookieMonster::kMaxCookies * 3 / 4,
404 }, {
405 "less_than_gc_thresh",
406 // Few enough cookies that gc shouldn't happen at all.
407 CookieMonster::kMaxCookies - 5,
408 0,
409 },
410 };
411 for (int ci = 0; ci < static_cast<int>(ARRAYSIZE_UNSAFE(test_cases)); ++ci) {
412 const TestCase& test_case(test_cases[ci]);
413 scoped_refptr<CookieMonster> cm(
414 CreateMonsterFromStoreForGC(
415 test_case.num_cookies, test_case.num_old_cookies,
416 CookieMonster::kSafeFromGlobalPurgeDays * 2));
417
418 GURL gurl("http://google.com");
419 std::string cookie_line("z=3");
420 // Trigger the Garbage collection we're allowed.
421 setCookieCallback.SetCookie(cm, gurl, cookie_line);
422
423 PerfTimeLogger timer((std::string("GC_") + test_case.name).c_str());
424 for (int i = 0; i < kNumCookies; i++)
425 setCookieCallback.SetCookie(cm, gurl, cookie_line);
426 timer.Done();
427 }
428 }
429
430 } // namespace
OLDNEW
« no previous file with comments | « net/base/cookie_monster.cc ('k') | net/base/cookie_monster_store_test.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698