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

Side by Side Diff: net/sdch/sdch_owner_unittest.cc

Issue 851503003: Update from https://crrev.com/311076 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 11 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
« no previous file with comments | « net/sdch/sdch_owner.cc ('k') | net/socket/client_socket_pool_manager_impl.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 2014 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/memory/memory_pressure_listener.h"
6 #include "base/run_loop.h"
7 #include "base/strings/stringprintf.h"
8 #include "base/test/simple_test_clock.h"
9 #include "net/base/net_log.h"
10 #include "net/base/sdch_manager.h"
11 #include "net/sdch/sdch_owner.h"
12 #include "net/url_request/url_request.h"
13 #include "net/url_request/url_request_context.h"
14 #include "net/url_request/url_request_error_job.h"
15 #include "net/url_request/url_request_job.h"
16 #include "net/url_request/url_request_job_factory.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace net {
20
21 static const char generic_url[] = "http://www.example.com";
22 static const char generic_domain[] = "www.example.com";
23
24 static std::string NewSdchDictionary(size_t dictionary_size) {
25 std::string dictionary;
26 dictionary.append("Domain: ");
27 dictionary.append(generic_domain);
28 dictionary.append("\n");
29 dictionary.append("\n");
30
31 size_t original_dictionary_size = dictionary.size();
32 dictionary.resize(dictionary_size);
33 for (size_t i = original_dictionary_size; i < dictionary_size; ++i)
34 dictionary[i] = static_cast<char>((i % 127) + 1);
35
36 return dictionary;
37 }
38
39 int outstanding_url_request_error_counting_jobs = 0;
40 base::Closure* empty_url_request_jobs_callback = 0;
41
42 // Variation of URLRequestErrorJob to count number of outstanding
43 // instances and notify when that goes to zero.
44 class URLRequestErrorCountingJob : public URLRequestJob {
45 public:
46 URLRequestErrorCountingJob(URLRequest* request,
47 NetworkDelegate* network_delegate,
48 int error)
49 : URLRequestJob(request, network_delegate),
50 error_(error),
51 weak_factory_(this) {
52 ++outstanding_url_request_error_counting_jobs;
53 }
54
55 void Start() override {
56 base::MessageLoop::current()->PostTask(
57 FROM_HERE, base::Bind(&URLRequestErrorCountingJob::StartAsync,
58 weak_factory_.GetWeakPtr()));
59 }
60
61 private:
62 ~URLRequestErrorCountingJob() override {
63 --outstanding_url_request_error_counting_jobs;
64 if (0 == outstanding_url_request_error_counting_jobs &&
65 empty_url_request_jobs_callback) {
66 empty_url_request_jobs_callback->Run();
67 }
68 }
69
70 void StartAsync() {
71 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, error_));
72 }
73
74 int error_;
75
76 base::WeakPtrFactory<URLRequestErrorCountingJob> weak_factory_;
77
78 DISALLOW_COPY_AND_ASSIGN(URLRequestErrorCountingJob);
79 };
80
81 static int error_jobs_created = 0;
82
83 class MockURLRequestJobFactory : public URLRequestJobFactory {
84 public:
85 MockURLRequestJobFactory() {}
86
87 ~MockURLRequestJobFactory() override {}
88
89 URLRequestJob* MaybeCreateJobWithProtocolHandler(
90 const std::string& scheme,
91 URLRequest* request,
92 NetworkDelegate* network_delegate) const override {
93 ++error_jobs_created;
94 return new URLRequestErrorCountingJob(request, network_delegate,
95 ERR_INTERNET_DISCONNECTED);
96 }
97
98 URLRequestJob* MaybeInterceptRedirect(URLRequest* request,
99 NetworkDelegate* network_delegate,
100 const GURL& location) const override {
101 return nullptr;
102 }
103
104 URLRequestJob* MaybeInterceptResponse(
105 URLRequest* request,
106 NetworkDelegate* network_delegate) const override {
107 return nullptr;
108 }
109
110 bool IsHandledProtocol(const std::string& scheme) const override {
111 return scheme == "http";
112 };
113
114 bool IsHandledURL(const GURL& url) const override {
115 return url.SchemeIs("http");
116 }
117
118 bool IsSafeRedirectTarget(const GURL& location) const override {
119 return false;
120 }
121 };
122
123 class SdchOwnerTest : public testing::Test {
124 public:
125 static const size_t kMaxSizeForTesting = 1000 * 50;
126 static const size_t kMinFetchSpaceForTesting = 500;
127
128 SdchOwnerTest()
129 : last_jobs_created_(error_jobs_created),
130 dictionary_creation_index_(0),
131 sdch_owner_(&sdch_manager_, &url_request_context_) {
132 // Any jobs created on this context will immediately error,
133 // which leaves the test in control of signals to SdchOwner.
134 url_request_context_.set_job_factory(&job_factory_);
135
136 // Reduce sizes to reduce time for string operations.
137 sdch_owner_.SetMaxTotalDictionarySize(kMaxSizeForTesting);
138 sdch_owner_.SetMinSpaceForDictionaryFetch(kMinFetchSpaceForTesting);
139 }
140
141 SdchManager& sdch_manager() { return sdch_manager_; }
142 SdchOwner& sdch_owner() { return sdch_owner_; }
143 BoundNetLog& bound_net_log() { return net_log_; }
144
145 int JobsRecentlyCreated() {
146 int result = error_jobs_created - last_jobs_created_;
147 last_jobs_created_ = error_jobs_created;
148 return result;
149 }
150
151 bool DictionaryPresentInManager(const std::string& server_hash) {
152 // Presumes all tests use generic url.
153 SdchProblemCode tmp;
154 scoped_ptr<SdchManager::DictionarySet> set(
155 sdch_manager_.GetDictionarySetByHash(GURL(generic_url), server_hash,
156 &tmp));
157 return !!set.get();
158 }
159
160 void SignalGetDictionaryAndClearJobs(GURL request_url, GURL dictionary_url) {
161 sdch_owner().OnGetDictionary(&sdch_manager_, request_url, dictionary_url);
162 if (outstanding_url_request_error_counting_jobs == 0)
163 return;
164 base::RunLoop run_loop;
165 base::Closure quit_closure(run_loop.QuitClosure());
166 empty_url_request_jobs_callback = &quit_closure;
167 run_loop.Run();
168 empty_url_request_jobs_callback = NULL;
169 }
170
171 // Create a unique (by hash) dictionary of the given size,
172 // associate it with a unique URL, add it to the manager through
173 // SdchOwner::OnDictionaryFetched(), and return whether that
174 // addition was successful or not.
175 bool CreateAndAddDictionary(size_t size, std::string* server_hash_p) {
176 GURL dictionary_url(
177 base::StringPrintf("%s/d%d", generic_url, dictionary_creation_index_));
178 std::string dictionary_text(NewSdchDictionary(size - 4));
179 dictionary_text += base::StringPrintf("%04d", dictionary_creation_index_);
180 ++dictionary_creation_index_;
181 std::string client_hash;
182 std::string server_hash;
183 SdchManager::GenerateHash(dictionary_text, &client_hash, &server_hash);
184
185 if (DictionaryPresentInManager(server_hash))
186 return false;
187 sdch_owner().OnDictionaryFetched(dictionary_text, dictionary_url, net_log_);
188 if (server_hash_p)
189 *server_hash_p = server_hash;
190 return DictionaryPresentInManager(server_hash);
191 }
192
193 private:
194 int last_jobs_created_;
195 BoundNetLog net_log_;
196 int dictionary_creation_index_;
197
198 // The dependencies of these objects (sdch_owner_ -> {sdch_manager_,
199 // url_request_context_}, url_request_context_->job_factory_) require
200 // this order for correct destruction semantics.
201 MockURLRequestJobFactory job_factory_;
202 URLRequestContext url_request_context_;
203 SdchManager sdch_manager_;
204 SdchOwner sdch_owner_;
205
206 DISALLOW_COPY_AND_ASSIGN(SdchOwnerTest);
207 };
208
209 // Does OnGetDictionary result in a fetch when there's enough space, and not
210 // when there's not?
211 TEST_F(SdchOwnerTest, OnGetDictionary_Fetching) {
212 GURL request_url(std::string(generic_url) + "/r1");
213
214 // Fetch generated when empty.
215 GURL dict_url1(std::string(generic_url) + "/d1");
216 EXPECT_EQ(0, JobsRecentlyCreated());
217 SignalGetDictionaryAndClearJobs(request_url, dict_url1);
218 EXPECT_EQ(1, JobsRecentlyCreated());
219
220 // Fetch generated when half full.
221 GURL dict_url2(std::string(generic_url) + "/d2");
222 std::string dictionary1(NewSdchDictionary(kMaxSizeForTesting / 2));
223 sdch_owner().OnDictionaryFetched(dictionary1, dict_url1, bound_net_log());
224 EXPECT_EQ(0, JobsRecentlyCreated());
225 SignalGetDictionaryAndClearJobs(request_url, dict_url2);
226 EXPECT_EQ(1, JobsRecentlyCreated());
227
228 // Fetch not generated when close to completely full.
229 GURL dict_url3(std::string(generic_url) + "/d3");
230 std::string dictionary2(NewSdchDictionary(
231 (kMaxSizeForTesting / 2 - kMinFetchSpaceForTesting / 2)));
232 sdch_owner().OnDictionaryFetched(dictionary2, dict_url2, bound_net_log());
233 EXPECT_EQ(0, JobsRecentlyCreated());
234 SignalGetDictionaryAndClearJobs(request_url, dict_url3);
235 EXPECT_EQ(0, JobsRecentlyCreated());
236 }
237
238 // Make sure attempts to add dictionaries do what they should.
239 TEST_F(SdchOwnerTest, OnDictionaryFetched_Fetching) {
240 GURL request_url(std::string(generic_url) + "/r1");
241 std::string client_hash;
242 std::string server_hash;
243
244 // Add successful when empty.
245 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, nullptr));
246 EXPECT_EQ(0, JobsRecentlyCreated());
247
248 // Add successful when half full.
249 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, nullptr));
250 EXPECT_EQ(0, JobsRecentlyCreated());
251
252 // Add unsuccessful when full.
253 EXPECT_FALSE(CreateAndAddDictionary(kMaxSizeForTesting / 2, nullptr));
254 EXPECT_EQ(0, JobsRecentlyCreated());
255 }
256
257 // Confirm auto-eviction happens if space is needed.
258 TEST_F(SdchOwnerTest, ConfirmAutoEviction) {
259 std::string server_hash_d1;
260 std::string server_hash_d2;
261 std::string server_hash_d3;
262
263 // Add two dictionaries, one recent, one more than a day in the past.
264 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d1));
265
266 scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock);
267 clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(2));
268 sdch_owner().SetClockForTesting(clock.Pass());
269
270 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d2));
271
272 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
273 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2));
274
275 // The addition of a new dictionary should succeed, evicting the old one.
276 clock.reset(new base::SimpleTestClock);
277 clock->SetNow(base::Time::Now());
278 sdch_owner().SetClockForTesting(clock.Pass());
279
280 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d3));
281 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
282 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2));
283 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3));
284 }
285
286 // Confirm auto-eviction happens if space is needed, with a more complicated
287 // situation
288 TEST_F(SdchOwnerTest, ConfirmAutoEviction_2) {
289 std::string server_hash_d1;
290 std::string server_hash_d2;
291 std::string server_hash_d3;
292
293 // Add dictionaries, one recent, two more than a day in the past that
294 // between them add up to the space needed.
295 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d1));
296
297 scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock);
298 clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(2));
299 sdch_owner().SetClockForTesting(clock.Pass());
300
301 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d2));
302 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d3));
303
304 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
305 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2));
306 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3));
307
308 // The addition of a new dictionary should succeed, evicting the old one.
309 clock.reset(new base::SimpleTestClock);
310 clock->SetNow(base::Time::Now());
311 sdch_owner().SetClockForTesting(clock.Pass());
312
313 std::string server_hash_d4;
314 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d4));
315 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
316 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2));
317 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d3));
318 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d4));
319 }
320
321 // Confirm if only one dictionary needs to be evicted it's the oldest.
322 TEST_F(SdchOwnerTest, ConfirmAutoEviction_Oldest) {
323 std::string server_hash_d1;
324 std::string server_hash_d2;
325 std::string server_hash_d3;
326
327 // Add dictionaries, one recent, one two days in the past, and one
328 // four days in the past.
329 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d1));
330
331 scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock);
332 clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(2));
333 sdch_owner().SetClockForTesting(clock.Pass());
334 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d2));
335
336 clock.reset(new base::SimpleTestClock);
337 clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(4));
338 sdch_owner().SetClockForTesting(clock.Pass());
339 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d3));
340
341 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
342 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2));
343 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3));
344
345 // The addition of a new dictionary should succeed, evicting only the
346 // oldest one.
347 clock.reset(new base::SimpleTestClock);
348 clock->SetNow(base::Time::Now());
349 sdch_owner().SetClockForTesting(clock.Pass());
350
351 std::string server_hash_d4;
352 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d4));
353 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
354 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2));
355 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d3));
356 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d4));
357 }
358
359 // Confirm using a dictionary changes eviction behavior properly.
360 TEST_F(SdchOwnerTest, UseChangesEviction) {
361 std::string server_hash_d1;
362 std::string server_hash_d2;
363 std::string server_hash_d3;
364
365 // Add dictionaries, one recent, one two days in the past, and one
366 // four days in the past.
367 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d1));
368
369 scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock);
370 clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(2));
371 sdch_owner().SetClockForTesting(clock.Pass());
372 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d2));
373
374 clock.reset(new base::SimpleTestClock);
375 clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(4));
376 sdch_owner().SetClockForTesting(clock.Pass());
377 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d3));
378
379 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
380 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2));
381 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3));
382
383 clock.reset(new base::SimpleTestClock);
384 clock->SetNow(base::Time::Now());
385 sdch_owner().SetClockForTesting(clock.Pass());
386
387 // Use the oldest dictionary.
388 sdch_owner().OnDictionaryUsed(&sdch_manager(), server_hash_d3);
389
390 // The addition of a new dictionary should succeed, evicting only the
391 // newer stale one.
392 std::string server_hash_d4;
393 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d4));
394 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
395 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2));
396 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3));
397 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d4));
398 }
399
400 // Confirm using a dictionary can prevent the addition of a new dictionary.
401 TEST_F(SdchOwnerTest, UsePreventsAddition) {
402 std::string server_hash_d1;
403 std::string server_hash_d2;
404 std::string server_hash_d3;
405
406 // Add dictionaries, one recent, one two days in the past, and one
407 // four days in the past.
408 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d1));
409
410 scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock);
411 clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(2));
412 sdch_owner().SetClockForTesting(clock.Pass());
413 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d2));
414
415 clock.reset(new base::SimpleTestClock);
416 clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(4));
417 sdch_owner().SetClockForTesting(clock.Pass());
418 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d3));
419
420 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
421 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2));
422 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3));
423
424 clock.reset(new base::SimpleTestClock);
425 clock->SetNow(base::Time::Now());
426 sdch_owner().SetClockForTesting(clock.Pass());
427
428 // Use the older dictionaries.
429 sdch_owner().OnDictionaryUsed(&sdch_manager(), server_hash_d2);
430 sdch_owner().OnDictionaryUsed(&sdch_manager(), server_hash_d3);
431
432 // The addition of a new dictionary should fail, not evicting anything.
433 std::string server_hash_d4;
434 EXPECT_FALSE(CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d4));
435 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
436 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2));
437 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3));
438 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d4));
439 }
440
441 // Confirm clear gets all the space back.
442 TEST_F(SdchOwnerTest, ClearReturnsSpace) {
443 std::string server_hash_d1;
444 std::string server_hash_d2;
445
446 // Take up all the space.
447 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting, &server_hash_d1));
448
449 // Addition should fail.
450 EXPECT_FALSE(CreateAndAddDictionary(kMaxSizeForTesting, &server_hash_d2));
451
452 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
453 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2));
454
455 sdch_manager().ClearData();
456 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d1));
457 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2));
458
459 // Addition should now succeed.
460 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting, nullptr));
461 }
462
463 // Confirm memory pressure gets all the space back.
464 TEST_F(SdchOwnerTest, MemoryPressureReturnsSpace) {
465 std::string server_hash_d1;
466 std::string server_hash_d2;
467
468 // Take up all the space.
469 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting, &server_hash_d1));
470
471 // Addition should fail.
472 EXPECT_FALSE(CreateAndAddDictionary(kMaxSizeForTesting, &server_hash_d2));
473
474 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
475 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2));
476
477 base::MemoryPressureListener::NotifyMemoryPressure(
478 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
479 // The notification may have (implementation note: does :-}) use a PostTask,
480 // so we drain the local message queue. This should be safe (i.e. not have
481 // an inifinite number of messages) in a unit test.
482 base::RunLoop().RunUntilIdle();
483
484 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d1));
485 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2));
486
487 // Addition should now succeed.
488 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting, nullptr));
489 }
490
491 } // namespace net
OLDNEW
« no previous file with comments | « net/sdch/sdch_owner.cc ('k') | net/socket/client_socket_pool_manager_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698