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

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

Issue 901303002: Make SDCH dictionaries persistent across browser restart. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix cache control headers Created 5 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
« no previous file with comments | « net/sdch/sdch_owner.cc ('k') | net/url_request/sdch_dictionary_fetcher.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/memory/memory_pressure_listener.h" 5 #include "base/memory/memory_pressure_listener.h"
6 #include "base/prefs/testing_pref_store.h"
6 #include "base/run_loop.h" 7 #include "base/run_loop.h"
7 #include "base/strings/stringprintf.h" 8 #include "base/strings/stringprintf.h"
8 #include "base/test/simple_test_clock.h" 9 #include "base/test/simple_test_clock.h"
10 #include "base/values.h"
9 #include "net/base/net_log.h" 11 #include "net/base/net_log.h"
10 #include "net/base/sdch_manager.h" 12 #include "net/base/sdch_manager.h"
11 #include "net/sdch/sdch_owner.h" 13 #include "net/sdch/sdch_owner.h"
12 #include "net/url_request/url_request.h" 14 #include "net/url_request/url_request.h"
13 #include "net/url_request/url_request_context.h" 15 #include "net/url_request/url_request_context.h"
14 #include "net/url_request/url_request_error_job.h" 16 #include "net/url_request/url_request_error_job.h"
15 #include "net/url_request/url_request_job.h" 17 #include "net/url_request/url_request_job.h"
16 #include "net/url_request/url_request_job_factory.h" 18 #include "net/url_request/url_request_job_factory.h"
19 #include "net/url_request/url_request_test_util.h"
17 #include "testing/gtest/include/gtest/gtest.h" 20 #include "testing/gtest/include/gtest/gtest.h"
18 21
22 namespace {
23
24 bool GetDictionaryForURL(TestingPrefStore* store,
25 const GURL& url,
26 std::string* hash,
27 base::DictionaryValue** dict) {
28 base::Value* sdch_val = nullptr;
29 base::DictionaryValue* sdch_dict = nullptr;
30 if (!store->GetMutableValue("SDCH", &sdch_val))
31 return false;
32 if (!sdch_val->GetAsDictionary(&sdch_dict))
33 return false;
34
35 base::DictionaryValue* dicts_dict = nullptr;
36 if (!sdch_dict->GetDictionary("dictionaries", &dicts_dict))
37 return false;
38
39 base::DictionaryValue::Iterator it(*dicts_dict);
40 while (!it.IsAtEnd()) {
41 const base::DictionaryValue* d = nullptr;
42 if (!it.value().GetAsDictionary(&d))
43 continue;
44 std::string dict_url;
45 if (d->GetString("url", &dict_url) && dict_url == url.spec()) {
46 if (hash)
47 *hash = it.key();
48 if (dict)
49 dicts_dict->GetDictionary(it.key(), dict);
50 return true;
51 }
52 it.Advance();
53 }
54
55 return false;
56 }
57
58 } // namespace
59
19 namespace net { 60 namespace net {
20 61
21 static const char generic_url[] = "http://www.example.com"; 62 static const char generic_url[] = "http://www.example.com";
22 static const char generic_domain[] = "www.example.com"; 63 static const char generic_domain[] = "www.example.com";
23 64
24 static std::string NewSdchDictionary(size_t dictionary_size) { 65 static std::string NewSdchDictionary(size_t dictionary_size) {
25 std::string dictionary; 66 std::string dictionary;
26 dictionary.append("Domain: "); 67 dictionary.append("Domain: ");
27 dictionary.append(generic_domain); 68 dictionary.append(generic_domain);
28 dictionary.append("\n"); 69 dictionary.append("\n");
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 154
114 bool IsHandledURL(const GURL& url) const override { 155 bool IsHandledURL(const GURL& url) const override {
115 return url.SchemeIs("http"); 156 return url.SchemeIs("http");
116 } 157 }
117 158
118 bool IsSafeRedirectTarget(const GURL& location) const override { 159 bool IsSafeRedirectTarget(const GURL& location) const override {
119 return false; 160 return false;
120 } 161 }
121 }; 162 };
122 163
164 class MockSdchDictionaryFetcher : public SdchDictionaryFetcher {
165 public:
166 MockSdchDictionaryFetcher() : SdchDictionaryFetcher(&test_context_) {}
167 ~MockSdchDictionaryFetcher() {}
168
169 struct PendingRequest {
170 PendingRequest(const GURL& url,
171 const OnDictionaryFetchedCallback& callback)
172 : url_(url), callback_(callback) {}
173 GURL url_;
174 OnDictionaryFetchedCallback callback_;
175 };
176
177 virtual bool Schedule(const GURL& dictionary_url,
178 const OnDictionaryFetchedCallback& callback) {
179 if (!HasPendingRequest(dictionary_url)) {
180 requests_.push_back(PendingRequest(dictionary_url, callback));
181 return true;
182 }
183 return false;
184 }
185
186 virtual bool ScheduleReload(const GURL& dictionary_url,
187 const OnDictionaryFetchedCallback& callback) {
188 if (!HasPendingRequest(dictionary_url)) {
189 requests_.push_back(PendingRequest(dictionary_url, callback));
190 return true;
191 }
192 return false;
193 }
194
195 virtual void Cancel() {
196 requests_.clear();
197 }
198
199 bool HasPendingRequest(const GURL& dictionary_url) {
200 for (std::vector<PendingRequest>::iterator it = requests_.begin();
201 it != requests_.end(); ++it) {
202 if (it->url_ == dictionary_url)
203 return true;
204 }
205 return false;
206 }
207
208 bool CompletePendingRequest(const GURL& dictionary_url,
209 const std::string& dictionary_text,
210 const BoundNetLog& net_log) {
211 for (std::vector<PendingRequest>::iterator it = requests_.begin();
212 it != requests_.end(); ++it) {
213 if (it->url_ == dictionary_url) {
214 it->callback_.Run(dictionary_text, dictionary_url, net_log);
215 requests_.erase(it);
216 return true;
217 }
218 }
219 return false;
220 }
221
222 private:
223 TestURLRequestContext test_context_;
224 std::vector<PendingRequest> requests_;
225 DISALLOW_COPY_AND_ASSIGN(MockSdchDictionaryFetcher);
226 };
227
228 // File testing infrastructure summary:
229 // * NewSdchDictionary(): Creates a dictionary of a specific size.
230 // * URLRequestErrorCountingJob: A URLRequestJob that returns an error
231 // and counts the number of outstanding (started but not finished)
232 // jobs, and calls a global callback when that number transitions to zero.
233 // * MockURLRequestJobFactory: Factory to create the above jobs. Tracks
234 // the number of jobs created.
235 // * SdchOwnerTest: Interfaces
236 // * Access manager, owner, and net log
237 // * Return the number of jobs created in a time interval
238 // * Return dictionary present in the manager
239 // * Notify SdchOwner of an incoming dictionary (& wait until jobs clear)
240 // * Attempt to add a dictionary and test for success.
241 // Test patterns:
242 // * Let the owner know about a Get-Dictionary header and test for
243 // appropriate jobs being created.
244 // * Let the owner know that a dictionary was successfully fetched
245 // and test for appropriate outcome.
246 // * Either of the above, having previously added dictionaries to create
247 // a particular initial state.
123 class SdchOwnerTest : public testing::Test { 248 class SdchOwnerTest : public testing::Test {
124 public: 249 public:
125 static const size_t kMaxSizeForTesting = 1000 * 50; 250 static const size_t kMaxSizeForTesting = 1000 * 50;
126 static const size_t kMinFetchSpaceForTesting = 500; 251 static const size_t kMinFetchSpaceForTesting = 500;
127 252
128 SdchOwnerTest() 253 SdchOwnerTest()
129 : last_jobs_created_(error_jobs_created), 254 : last_jobs_created_(error_jobs_created),
130 dictionary_creation_index_(0), 255 dictionary_creation_index_(0),
256 pref_store_(new TestingPrefStore),
131 sdch_owner_(&sdch_manager_, &url_request_context_) { 257 sdch_owner_(&sdch_manager_, &url_request_context_) {
132 // Any jobs created on this context will immediately error, 258 // Any jobs created on this context will immediately error,
133 // which leaves the test in control of signals to SdchOwner. 259 // which leaves the test in control of signals to SdchOwner.
134 url_request_context_.set_job_factory(&job_factory_); 260 url_request_context_.set_job_factory(&job_factory_);
135 261
136 // Reduce sizes to reduce time for string operations. 262 // Reduce sizes to reduce time for string operations.
137 sdch_owner_.SetMaxTotalDictionarySize(kMaxSizeForTesting); 263 sdch_owner_.SetMaxTotalDictionarySize(kMaxSizeForTesting);
138 sdch_owner_.SetMinSpaceForDictionaryFetch(kMinFetchSpaceForTesting); 264 sdch_owner_.SetMinSpaceForDictionaryFetch(kMinFetchSpaceForTesting);
139 } 265 }
140 266
141 SdchManager& sdch_manager() { return sdch_manager_; } 267 SdchManager& sdch_manager() { return sdch_manager_; }
142 SdchOwner& sdch_owner() { return sdch_owner_; } 268 SdchOwner& sdch_owner() { return sdch_owner_; }
143 BoundNetLog& bound_net_log() { return net_log_; } 269 BoundNetLog& bound_net_log() { return net_log_; }
270 TestingPrefStore& pref_store() { return *(pref_store_.get()); }
144 271
145 int JobsRecentlyCreated() { 272 int JobsRecentlyCreated() {
146 int result = error_jobs_created - last_jobs_created_; 273 int result = error_jobs_created - last_jobs_created_;
147 last_jobs_created_ = error_jobs_created; 274 last_jobs_created_ = error_jobs_created;
148 return result; 275 return result;
149 } 276 }
150 277
151 bool DictionaryPresentInManager(const std::string& server_hash) { 278 bool DictionaryPresentInManager(const std::string& server_hash) {
152 // Presumes all tests use generic url. 279 // Presumes all tests use generic url.
153 SdchProblemCode tmp; 280 SdchProblemCode tmp;
154 scoped_ptr<SdchManager::DictionarySet> set( 281 scoped_ptr<SdchManager::DictionarySet> set(
155 sdch_manager_.GetDictionarySetByHash(GURL(generic_url), server_hash, 282 sdch_manager_.GetDictionarySetByHash(GURL(generic_url), server_hash,
156 &tmp)); 283 &tmp));
157 return !!set.get(); 284 return !!set.get();
158 } 285 }
159 286
160 void SignalGetDictionaryAndClearJobs(GURL request_url, GURL dictionary_url) { 287 void WaitForNoJobs() {
161 sdch_owner().OnGetDictionary(&sdch_manager_, request_url, dictionary_url);
162 if (outstanding_url_request_error_counting_jobs == 0) 288 if (outstanding_url_request_error_counting_jobs == 0)
163 return; 289 return;
290
164 base::RunLoop run_loop; 291 base::RunLoop run_loop;
165 base::Closure quit_closure(run_loop.QuitClosure()); 292 base::Closure quit_closure(run_loop.QuitClosure());
166 empty_url_request_jobs_callback = &quit_closure; 293 empty_url_request_jobs_callback = &quit_closure;
167 run_loop.Run(); 294 run_loop.Run();
168 empty_url_request_jobs_callback = NULL; 295 empty_url_request_jobs_callback = NULL;
169 } 296 }
170 297
298 void SignalGetDictionaryAndClearJobs(GURL request_url, GURL dictionary_url) {
299 sdch_owner().OnGetDictionary(&sdch_manager_, request_url, dictionary_url);
300 WaitForNoJobs();
301 }
302
171 // Create a unique (by hash) dictionary of the given size, 303 // Create a unique (by hash) dictionary of the given size,
172 // associate it with a unique URL, add it to the manager through 304 // associate it with a unique URL, add it to the manager through
173 // SdchOwner::OnDictionaryFetched(), and return whether that 305 // SdchOwner::OnDictionaryFetched(), and return whether that
174 // addition was successful or not. 306 // addition was successful or not.
175 bool CreateAndAddDictionary(size_t size, std::string* server_hash_p) { 307 bool CreateAndAddDictionary(size_t size,
308 std::string* server_hash_p,
309 base::Time last_used_time) {
176 GURL dictionary_url( 310 GURL dictionary_url(
177 base::StringPrintf("%s/d%d", generic_url, dictionary_creation_index_)); 311 base::StringPrintf("%s/d%d", generic_url, dictionary_creation_index_));
178 std::string dictionary_text(NewSdchDictionary(size - 4)); 312 std::string dictionary_text(NewSdchDictionary(size - 4));
179 dictionary_text += base::StringPrintf("%04d", dictionary_creation_index_); 313 dictionary_text += base::StringPrintf("%04d", dictionary_creation_index_);
180 ++dictionary_creation_index_; 314 ++dictionary_creation_index_;
181 std::string client_hash; 315 std::string client_hash;
182 std::string server_hash; 316 std::string server_hash;
183 SdchManager::GenerateHash(dictionary_text, &client_hash, &server_hash); 317 SdchManager::GenerateHash(dictionary_text, &client_hash, &server_hash);
184 318
185 if (DictionaryPresentInManager(server_hash)) 319 if (DictionaryPresentInManager(server_hash))
186 return false; 320 return false;
187 sdch_owner().OnDictionaryFetched(dictionary_text, dictionary_url, net_log_); 321 sdch_owner().OnDictionaryFetched(last_used_time, 0, dictionary_text,
322 dictionary_url, net_log_);
188 if (server_hash_p) 323 if (server_hash_p)
189 *server_hash_p = server_hash; 324 *server_hash_p = server_hash;
190 return DictionaryPresentInManager(server_hash); 325 return DictionaryPresentInManager(server_hash);
191 } 326 }
192 327
193 private: 328 private:
194 int last_jobs_created_; 329 int last_jobs_created_;
195 BoundNetLog net_log_; 330 BoundNetLog net_log_;
196 int dictionary_creation_index_; 331 int dictionary_creation_index_;
197 332
198 // The dependencies of these objects (sdch_owner_ -> {sdch_manager_, 333 // The dependencies of these objects (sdch_owner_ -> {sdch_manager_,
199 // url_request_context_}, url_request_context_->job_factory_) require 334 // url_request_context_}, url_request_context_->job_factory_) require
200 // this order for correct destruction semantics. 335 // this order for correct destruction semantics.
201 MockURLRequestJobFactory job_factory_; 336 MockURLRequestJobFactory job_factory_;
202 URLRequestContext url_request_context_; 337 URLRequestContext url_request_context_;
203 SdchManager sdch_manager_; 338 SdchManager sdch_manager_;
339 scoped_refptr<TestingPrefStore> pref_store_;
204 SdchOwner sdch_owner_; 340 SdchOwner sdch_owner_;
205 341
206 DISALLOW_COPY_AND_ASSIGN(SdchOwnerTest); 342 DISALLOW_COPY_AND_ASSIGN(SdchOwnerTest);
207 }; 343 };
208 344
209 // Does OnGetDictionary result in a fetch when there's enough space, and not 345 // Does OnGetDictionary result in a fetch when there's enough space, and not
210 // when there's not? 346 // when there's not?
211 TEST_F(SdchOwnerTest, OnGetDictionary_Fetching) { 347 TEST_F(SdchOwnerTest, OnGetDictionary_Fetching) {
212 GURL request_url(std::string(generic_url) + "/r1"); 348 GURL request_url(std::string(generic_url) + "/r1");
213 349
214 // Fetch generated when empty. 350 // Fetch generated when empty.
215 GURL dict_url1(std::string(generic_url) + "/d1"); 351 GURL dict_url1(std::string(generic_url) + "/d1");
216 EXPECT_EQ(0, JobsRecentlyCreated()); 352 EXPECT_EQ(0, JobsRecentlyCreated());
217 SignalGetDictionaryAndClearJobs(request_url, dict_url1); 353 SignalGetDictionaryAndClearJobs(request_url, dict_url1);
218 EXPECT_EQ(1, JobsRecentlyCreated()); 354 EXPECT_EQ(1, JobsRecentlyCreated());
219 355
220 // Fetch generated when half full. 356 // Fetch generated when half full.
221 GURL dict_url2(std::string(generic_url) + "/d2"); 357 GURL dict_url2(std::string(generic_url) + "/d2");
222 std::string dictionary1(NewSdchDictionary(kMaxSizeForTesting / 2)); 358 std::string dictionary1(NewSdchDictionary(kMaxSizeForTesting / 2));
223 sdch_owner().OnDictionaryFetched(dictionary1, dict_url1, bound_net_log()); 359 sdch_owner().OnDictionaryFetched(base::Time::Now(), 1, dictionary1, dict_url1,
360 bound_net_log());
224 EXPECT_EQ(0, JobsRecentlyCreated()); 361 EXPECT_EQ(0, JobsRecentlyCreated());
225 SignalGetDictionaryAndClearJobs(request_url, dict_url2); 362 SignalGetDictionaryAndClearJobs(request_url, dict_url2);
226 EXPECT_EQ(1, JobsRecentlyCreated()); 363 EXPECT_EQ(1, JobsRecentlyCreated());
227 364
228 // Fetch not generated when close to completely full. 365 // Fetch not generated when close to completely full.
229 GURL dict_url3(std::string(generic_url) + "/d3"); 366 GURL dict_url3(std::string(generic_url) + "/d3");
230 std::string dictionary2(NewSdchDictionary( 367 std::string dictionary2(NewSdchDictionary(
231 (kMaxSizeForTesting / 2 - kMinFetchSpaceForTesting / 2))); 368 (kMaxSizeForTesting / 2 - kMinFetchSpaceForTesting / 2)));
232 sdch_owner().OnDictionaryFetched(dictionary2, dict_url2, bound_net_log()); 369 sdch_owner().OnDictionaryFetched(base::Time::Now(), 1, dictionary2, dict_url2,
370 bound_net_log());
233 EXPECT_EQ(0, JobsRecentlyCreated()); 371 EXPECT_EQ(0, JobsRecentlyCreated());
234 SignalGetDictionaryAndClearJobs(request_url, dict_url3); 372 SignalGetDictionaryAndClearJobs(request_url, dict_url3);
235 EXPECT_EQ(0, JobsRecentlyCreated()); 373 EXPECT_EQ(0, JobsRecentlyCreated());
236 } 374 }
237 375
238 // Make sure attempts to add dictionaries do what they should. 376 // Make sure attempts to add dictionaries do what they should.
239 TEST_F(SdchOwnerTest, OnDictionaryFetched_Fetching) { 377 TEST_F(SdchOwnerTest, OnDictionaryFetched_Fetching) {
240 GURL request_url(std::string(generic_url) + "/r1"); 378 GURL request_url(std::string(generic_url) + "/r1");
241 std::string client_hash; 379 std::string client_hash;
242 std::string server_hash; 380 std::string server_hash;
243 381
382 // In the past, but still fresh for an unused dictionary.
383 base::Time dictionary_last_used_time(base::Time::Now() -
384 base::TimeDelta::FromMinutes(30));
385
244 // Add successful when empty. 386 // Add successful when empty.
245 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, nullptr)); 387 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, nullptr,
388 dictionary_last_used_time));
246 EXPECT_EQ(0, JobsRecentlyCreated()); 389 EXPECT_EQ(0, JobsRecentlyCreated());
247 390
248 // Add successful when half full. 391 // Add successful when half full.
249 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, nullptr)); 392 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, nullptr,
393 dictionary_last_used_time));
250 EXPECT_EQ(0, JobsRecentlyCreated()); 394 EXPECT_EQ(0, JobsRecentlyCreated());
251 395
252 // Add unsuccessful when full. 396 // Add unsuccessful when full.
253 EXPECT_FALSE(CreateAndAddDictionary(kMaxSizeForTesting / 2, nullptr)); 397 EXPECT_FALSE(CreateAndAddDictionary(kMaxSizeForTesting / 2, nullptr,
398 dictionary_last_used_time));
254 EXPECT_EQ(0, JobsRecentlyCreated()); 399 EXPECT_EQ(0, JobsRecentlyCreated());
255 } 400 }
256 401
257 // Confirm auto-eviction happens if space is needed. 402 // Confirm auto-eviction happens if space is needed.
258 TEST_F(SdchOwnerTest, ConfirmAutoEviction) { 403 TEST_F(SdchOwnerTest, ConfirmAutoEviction) {
259 std::string server_hash_d1; 404 std::string server_hash_d1;
260 std::string server_hash_d2; 405 std::string server_hash_d2;
261 std::string server_hash_d3; 406 std::string server_hash_d3;
262 407
263 // Add two dictionaries, one recent, one more than a day in the past. 408 // Add two dictionaries, one recent, one more than a day in the past.
264 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d1)); 409 base::Time fresh(base::Time::Now() - base::TimeDelta::FromHours(23));
410 base::Time stale(base::Time::Now() - base::TimeDelta::FromHours(25));
265 411
266 scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock); 412 EXPECT_TRUE(
267 clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(2)); 413 CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d1, fresh));
268 sdch_owner().SetClockForTesting(clock.Pass()); 414 EXPECT_TRUE(
269 415 CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d2, stale));
270 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d2));
271 416
272 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1)); 417 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
273 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2)); 418 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2));
274 419
275 // The addition of a new dictionary should succeed, evicting the old one. 420 EXPECT_TRUE(
276 clock.reset(new base::SimpleTestClock); 421 CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d3, fresh));
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)); 422 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
282 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2)); 423 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2));
283 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3)); 424 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3));
284 } 425 }
285 426
286 // Confirm auto-eviction happens if space is needed, with a more complicated 427 // Confirm auto-eviction happens if space is needed, with a more complicated
287 // situation 428 // situation
288 TEST_F(SdchOwnerTest, ConfirmAutoEviction_2) { 429 TEST_F(SdchOwnerTest, ConfirmAutoEviction_2) {
289 std::string server_hash_d1; 430 std::string server_hash_d1;
290 std::string server_hash_d2; 431 std::string server_hash_d2;
291 std::string server_hash_d3; 432 std::string server_hash_d3;
292 433
293 // Add dictionaries, one recent, two more than a day in the past that 434 // Add dictionaries, one recent, two more than a day in the past that
294 // between them add up to the space needed. 435 // between them add up to the space needed.
295 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d1)); 436 base::Time fresh(base::Time::Now() - base::TimeDelta::FromHours(23));
437 base::Time stale(base::Time::Now() - base::TimeDelta::FromHours(25));
438 EXPECT_TRUE(
439 CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d1, fresh));
296 440
297 scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock); 441 EXPECT_TRUE(
298 clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(2)); 442 CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d2, stale));
299 sdch_owner().SetClockForTesting(clock.Pass()); 443 EXPECT_TRUE(
300 444 CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d3, stale));
301 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d2));
302 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d3));
303 445
304 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1)); 446 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
305 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2)); 447 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2));
306 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3)); 448 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3));
307 449
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; 450 std::string server_hash_d4;
314 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d4)); 451 EXPECT_TRUE(
452 CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d4, fresh));
315 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1)); 453 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
316 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2)); 454 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2));
317 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d3)); 455 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d3));
318 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d4)); 456 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d4));
319 } 457 }
320 458
321 // Confirm if only one dictionary needs to be evicted it's the oldest. 459 // Confirm if only one dictionary needs to be evicted it's the oldest.
322 TEST_F(SdchOwnerTest, ConfirmAutoEviction_Oldest) { 460 TEST_F(SdchOwnerTest, ConfirmAutoEviction_Oldest) {
323 std::string server_hash_d1; 461 std::string server_hash_d1;
324 std::string server_hash_d2; 462 std::string server_hash_d2;
325 std::string server_hash_d3; 463 std::string server_hash_d3;
326 464
327 // Add dictionaries, one recent, one two days in the past, and one 465 // Add dictionaries, one recent, one two days in the past, and one
328 // four days in the past. 466 // four days in the past.
329 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d1)); 467 base::Time fresh(base::Time::Now() - base::TimeDelta::FromHours(23));
468 base::Time stale_newer(base::Time::Now() - base::TimeDelta::FromHours(47));
469 base::Time stale_older(base::Time::Now() - base::TimeDelta::FromHours(71));
330 470
331 scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock); 471 EXPECT_TRUE(
332 clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(2)); 472 CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d1, fresh));
333 sdch_owner().SetClockForTesting(clock.Pass());
334 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d2));
335 473
336 clock.reset(new base::SimpleTestClock); 474 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d2,
337 clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(4)); 475 stale_newer));
338 sdch_owner().SetClockForTesting(clock.Pass()); 476
339 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d3)); 477 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d3,
478 stale_older));
340 479
341 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1)); 480 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
342 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2)); 481 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2));
343 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3)); 482 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3));
344 483
345 // The addition of a new dictionary should succeed, evicting only the 484 // The addition of a new dictionary should succeed, evicting only the
346 // oldest one. 485 // oldest one.
347 clock.reset(new base::SimpleTestClock);
348 clock->SetNow(base::Time::Now());
349 sdch_owner().SetClockForTesting(clock.Pass());
350 486
351 std::string server_hash_d4; 487 std::string server_hash_d4;
352 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d4)); 488 EXPECT_TRUE(
489 CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d4, fresh));
353 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1)); 490 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
354 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2)); 491 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2));
355 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d3)); 492 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d3));
356 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d4)); 493 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d4));
357 } 494 }
358 495
359 // Confirm using a dictionary changes eviction behavior properly. 496 // Confirm using a dictionary changes eviction behavior properly.
360 TEST_F(SdchOwnerTest, UseChangesEviction) { 497 TEST_F(SdchOwnerTest, UseChangesEviction) {
361 std::string server_hash_d1; 498 std::string server_hash_d1;
362 std::string server_hash_d2; 499 std::string server_hash_d2;
363 std::string server_hash_d3; 500 std::string server_hash_d3;
364 501
365 // Add dictionaries, one recent, one two days in the past, and one 502 // Add dictionaries, one recent, one two days in the past, and one
366 // four days in the past. 503 // four days in the past.
367 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d1)); 504 base::Time fresh(base::Time::Now() - base::TimeDelta::FromHours(23));
505 base::Time stale_newer(base::Time::Now() - base::TimeDelta::FromHours(47));
506 base::Time stale_older(base::Time::Now() - base::TimeDelta::FromHours(71));
368 507
369 scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock); 508 EXPECT_TRUE(
370 clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(2)); 509 CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d1, fresh));
371 sdch_owner().SetClockForTesting(clock.Pass());
372 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d2));
373 510
374 clock.reset(new base::SimpleTestClock); 511 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d2,
375 clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(4)); 512 stale_newer));
376 sdch_owner().SetClockForTesting(clock.Pass()); 513
377 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d3)); 514 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d3,
515 stale_older));
378 516
379 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1)); 517 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
380 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2)); 518 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2));
381 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3)); 519 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3));
382 520
383 clock.reset(new base::SimpleTestClock);
384 clock->SetNow(base::Time::Now());
385 sdch_owner().SetClockForTesting(clock.Pass());
386
387 // Use the oldest dictionary. 521 // Use the oldest dictionary.
388 sdch_owner().OnDictionaryUsed(&sdch_manager(), server_hash_d3); 522 sdch_owner().OnDictionaryUsed(&sdch_manager(), server_hash_d3);
389 523
390 // The addition of a new dictionary should succeed, evicting only the 524 // The addition of a new dictionary should succeed, evicting only the
391 // newer stale one. 525 // newer stale one.
392 std::string server_hash_d4; 526 std::string server_hash_d4;
393 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d4)); 527 EXPECT_TRUE(
528 CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d4, fresh));
394 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1)); 529 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
395 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2)); 530 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2));
396 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3)); 531 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3));
397 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d4)); 532 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d4));
398 } 533 }
399 534
400 // Confirm using a dictionary can prevent the addition of a new dictionary. 535 // Confirm using a dictionary can prevent the addition of a new dictionary.
401 TEST_F(SdchOwnerTest, UsePreventsAddition) { 536 TEST_F(SdchOwnerTest, UsePreventsAddition) {
402 std::string server_hash_d1; 537 std::string server_hash_d1;
403 std::string server_hash_d2; 538 std::string server_hash_d2;
404 std::string server_hash_d3; 539 std::string server_hash_d3;
405 540
406 // Add dictionaries, one recent, one two days in the past, and one 541 // Add dictionaries, one recent, one two days in the past, and one
407 // four days in the past. 542 // four days in the past.
408 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d1)); 543 base::Time fresh(base::Time::Now() - base::TimeDelta::FromMinutes(30));
544 base::Time stale_newer(base::Time::Now() - base::TimeDelta::FromHours(47));
545 base::Time stale_older(base::Time::Now() - base::TimeDelta::FromHours(71));
409 546
410 scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock); 547 EXPECT_TRUE(
411 clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(2)); 548 CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d1, fresh));
412 sdch_owner().SetClockForTesting(clock.Pass());
413 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d2));
414 549
415 clock.reset(new base::SimpleTestClock); 550 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d2,
416 clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(4)); 551 stale_newer));
417 sdch_owner().SetClockForTesting(clock.Pass()); 552
418 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d3)); 553 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 4, &server_hash_d3,
554 stale_older));
419 555
420 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1)); 556 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
421 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2)); 557 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2));
422 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3)); 558 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3));
423 559
424 clock.reset(new base::SimpleTestClock);
425 clock->SetNow(base::Time::Now());
426 sdch_owner().SetClockForTesting(clock.Pass());
427
428 // Use the older dictionaries. 560 // Use the older dictionaries.
429 sdch_owner().OnDictionaryUsed(&sdch_manager(), server_hash_d2); 561 sdch_owner().OnDictionaryUsed(&sdch_manager(), server_hash_d2);
430 sdch_owner().OnDictionaryUsed(&sdch_manager(), server_hash_d3); 562 sdch_owner().OnDictionaryUsed(&sdch_manager(), server_hash_d3);
431 563
432 // The addition of a new dictionary should fail, not evicting anything. 564 // The addition of a new dictionary should fail, not evicting anything.
433 std::string server_hash_d4; 565 std::string server_hash_d4;
434 EXPECT_FALSE(CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d4)); 566 EXPECT_FALSE(
567 CreateAndAddDictionary(kMaxSizeForTesting / 2, &server_hash_d4, fresh));
435 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1)); 568 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
436 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2)); 569 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d2));
437 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3)); 570 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d3));
438 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d4)); 571 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d4));
439 } 572 }
440 573
441 // Confirm clear gets all the space back. 574 // Confirm clear gets all the space back.
442 TEST_F(SdchOwnerTest, ClearReturnsSpace) { 575 TEST_F(SdchOwnerTest, ClearReturnsSpace) {
443 std::string server_hash_d1; 576 std::string server_hash_d1;
444 std::string server_hash_d2; 577 std::string server_hash_d2;
445 578
446 // Take up all the space. 579 // Take up all the space.
447 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting, &server_hash_d1)); 580 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting, &server_hash_d1,
448 581 base::Time::Now()));
449 // Addition should fail. 582 // Addition should fail.
450 EXPECT_FALSE(CreateAndAddDictionary(kMaxSizeForTesting, &server_hash_d2)); 583 EXPECT_FALSE(CreateAndAddDictionary(kMaxSizeForTesting, &server_hash_d2,
451 584 base::Time::Now()));
452 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1)); 585 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
453 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2)); 586 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2));
454
455 sdch_manager().ClearData(); 587 sdch_manager().ClearData();
456 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d1)); 588 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d1));
457 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2)); 589 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2));
458 590
459 // Addition should now succeed. 591 // Addition should now succeed.
460 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting, nullptr)); 592 EXPECT_TRUE(
593 CreateAndAddDictionary(kMaxSizeForTesting, nullptr, base::Time::Now()));
461 } 594 }
462 595
463 // Confirm memory pressure gets all the space back. 596 // Confirm memory pressure gets all the space back.
464 // TODO(rmcilroy) Disabled while investigating http://crbug.com/447208 - 597 // TODO(rmcilroy) Disabled while investigating http://crbug.com/447208 -
465 // re-enable once fixed. 598 // re-enable once fixed.
466 TEST_F(SdchOwnerTest, DISABLED_MemoryPressureReturnsSpace) { 599 TEST_F(SdchOwnerTest, DISABLED_MemoryPressureReturnsSpace) {
467 std::string server_hash_d1; 600 std::string server_hash_d1;
468 std::string server_hash_d2; 601 std::string server_hash_d2;
469 602
470 // Take up all the space. 603 // Take up all the space.
471 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting, &server_hash_d1)); 604 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting, &server_hash_d1,
605 base::Time::Now()));
472 606
473 // Addition should fail. 607 // Addition should fail.
474 EXPECT_FALSE(CreateAndAddDictionary(kMaxSizeForTesting, &server_hash_d2)); 608 EXPECT_FALSE(CreateAndAddDictionary(kMaxSizeForTesting, &server_hash_d2,
609 base::Time::Now()));
475 610
476 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1)); 611 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
477 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2)); 612 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2));
478 613
479 base::MemoryPressureListener::NotifyMemoryPressure( 614 base::MemoryPressureListener::NotifyMemoryPressure(
480 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); 615 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
481 // The notification may have (implementation note: does :-}) use a PostTask, 616 // The notification may have (implementation note: does :-}) use a PostTask,
482 // so we drain the local message queue. This should be safe (i.e. not have 617 // so we drain the local message queue. This should be safe (i.e. not have
483 // an inifinite number of messages) in a unit test. 618 // an inifinite number of messages) in a unit test.
484 base::RunLoop().RunUntilIdle(); 619 base::RunLoop().RunUntilIdle();
485 620
486 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d1)); 621 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d1));
487 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2)); 622 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2));
488 623
489 // Addition should now succeed. 624 // Addition should now succeed.
490 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting, nullptr)); 625 EXPECT_TRUE(
626 CreateAndAddDictionary(kMaxSizeForTesting, nullptr, base::Time::Now()));
627 }
628
629 class SdchOwnerPersistenceTest : public ::testing::Test {
630 public:
631 SdchOwnerPersistenceTest() : pref_store_(new TestingPrefStore()) {
632 pref_store_->SetInitializationCompleted();
633 }
634 virtual ~SdchOwnerPersistenceTest() {}
635
636 void ClearOwner() {
637 owner_.reset(NULL);
638 }
639
640 void ResetOwner(bool delay) {
641 // This has to be done first, since SdchOwner may be observing SdchManager,
642 // and SdchManager can't be destroyed with a live observer.
643 owner_.reset(NULL);
644 manager_.reset(new SdchManager());
645 fetcher_ = new MockSdchDictionaryFetcher();
646 owner_.reset(new SdchOwner(manager_.get(),
647 &url_request_context_));
648 owner_->SetMaxTotalDictionarySize(SdchOwnerTest::kMaxSizeForTesting);
649 owner_->SetMinSpaceForDictionaryFetch(
650 SdchOwnerTest::kMinFetchSpaceForTesting);
651 owner_->SetFetcherForTesting(make_scoped_ptr(fetcher_));
652 if (!delay)
653 owner_->EnablePersistentStorage(pref_store_.get());
654 }
655
656 void InsertDictionaryForURL(const GURL& url, const std::string& nonce) {
657 owner_->OnDictionaryFetched(base::Time::Now(), 1,
658 CreateDictionary(url, nonce),
659 url, net_log_);
660 }
661
662 bool CompleteLoadFromURL(const GURL& url, const std::string& nonce) {
663 return fetcher_->CompletePendingRequest(url, CreateDictionary(url, nonce),
664 net_log_);
665 }
666
667 std::string CreateDictionary(const GURL& url, const std::string& nonce) {
668 std::string dict;
669 dict.append("Domain: ");
670 dict.append(url.host());
671 dict.append("\n\n");
672 dict.append(url.spec());
673 dict.append(nonce);
674 return dict;
675 }
676
677 protected:
678 BoundNetLog net_log_;
679 scoped_refptr<TestingPrefStore> pref_store_;
680 scoped_ptr<SdchManager> manager_;
681 MockSdchDictionaryFetcher* fetcher_;
682 scoped_ptr<SdchOwner> owner_;
683 TestURLRequestContext url_request_context_;
684 };
685
686 // Test an empty persistence store.
687 TEST_F(SdchOwnerPersistenceTest, Empty) {
688 ResetOwner(false);
689 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
690 }
691
692 // Test a persistence store with an empty dictionary.
693 TEST_F(SdchOwnerPersistenceTest, Persistent_EmptyDict) {
694 pref_store_->SetValue("SDCH", new base::DictionaryValue());
695 ResetOwner(false);
696 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
697 }
698
699 // Test a persistence store with a bad version number.
700 TEST_F(SdchOwnerPersistenceTest, Persistent_BadVersion) {
701 base::DictionaryValue* sdch_dict = new base::DictionaryValue();
702 sdch_dict->SetInteger("version", 2);
703 pref_store_->SetValue("SDCH", sdch_dict);
704
705 ResetOwner(false);
706 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
707 }
708
709 // Test a persistence store with an empty dictionaries map.
710 TEST_F(SdchOwnerPersistenceTest, Persistent_EmptyDictList) {
711 base::DictionaryValue* sdch_dict = new base::DictionaryValue();
712 scoped_ptr<base::DictionaryValue> dicts(new base::DictionaryValue());
713 sdch_dict->SetInteger("version", 1);
714 sdch_dict->Set("dictionaries", dicts.Pass());
715 pref_store_->SetValue("SDCH", sdch_dict);
716
717 ResetOwner(false);
718 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
719 }
720
721 TEST_F(SdchOwnerPersistenceTest, OneDict) {
722 const GURL url("http://www.example.com/dict");
723 ResetOwner(false);
724 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
725 InsertDictionaryForURL(url, "0");
726 EXPECT_EQ(1, owner_->GetDictionaryCountForTesting());
727
728 ResetOwner(false);
729 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
730 EXPECT_TRUE(CompleteLoadFromURL(url, "0"));
731 EXPECT_EQ(1, owner_->GetDictionaryCountForTesting());
732 }
733
734 TEST_F(SdchOwnerPersistenceTest, TwoDicts) {
735 const GURL url0("http://www.example.com/dict0");
736 const GURL url1("http://www.example.com/dict1");
737 ResetOwner(false);
738 InsertDictionaryForURL(url0, "0");
739 InsertDictionaryForURL(url1, "1");
740
741 ResetOwner(false);
742 EXPECT_TRUE(CompleteLoadFromURL(url0, "0"));
743 EXPECT_TRUE(CompleteLoadFromURL(url1, "1"));
744 EXPECT_EQ(2, owner_->GetDictionaryCountForTesting());
745 EXPECT_TRUE(owner_->HasDictionaryFromURLForTesting(url0));
746 EXPECT_TRUE(owner_->HasDictionaryFromURLForTesting(url1));
747 }
748
749 TEST_F(SdchOwnerPersistenceTest, OneGoodDictOneBadDict) {
750 const GURL url0("http://www.example.com/dict0");
751 const GURL url1("http://www.example.com/dict1");
752 ResetOwner(false);
753 InsertDictionaryForURL(url0, "0");
754 InsertDictionaryForURL(url1, "1");
755
756 // Mutate the pref store a bit now. Clear the owner first, to ensure that the
757 // SdchOwner doesn't observe these changes and object. The manual dictionary
758 // manipulation is a bit icky.
759 ClearOwner();
760 base::DictionaryValue* dict = nullptr;
761 ASSERT_TRUE(GetDictionaryForURL(pref_store_.get(), url1, nullptr, &dict));
762 dict->Remove("use_count", nullptr);
763
764 ResetOwner(false);
765 EXPECT_TRUE(CompleteLoadFromURL(url0, "0"));
766 EXPECT_FALSE(CompleteLoadFromURL(url1, "1"));
767 EXPECT_EQ(1, owner_->GetDictionaryCountForTesting());
768 EXPECT_TRUE(owner_->HasDictionaryFromURLForTesting(url0));
769 EXPECT_FALSE(owner_->HasDictionaryFromURLForTesting(url1));
770 }
771
772 TEST_F(SdchOwnerPersistenceTest, UsingDictionaryUpdatesUseCount) {
773 const GURL url("http://www.example.com/dict");
774 ResetOwner(false);
775 InsertDictionaryForURL(url, "0");
776
777 std::string hash;
778 int old_count;
779 {
780 ClearOwner();
781 base::DictionaryValue* dict = nullptr;
782 ASSERT_TRUE(GetDictionaryForURL(pref_store_.get(), url, &hash, &dict));
783 ASSERT_TRUE(dict->GetInteger("use_count", &old_count));
784 }
785
786 ResetOwner(false);
787 ASSERT_TRUE(CompleteLoadFromURL(url, "0"));
788 owner_->OnDictionaryUsed(manager_.get(), hash);
789
790 int new_count;
791 {
792 ClearOwner();
793 base::DictionaryValue* dict = nullptr;
794 ASSERT_TRUE(GetDictionaryForURL(pref_store_.get(), url, nullptr, &dict));
795 ASSERT_TRUE(dict->GetInteger("use_count", &new_count));
796 }
797
798 EXPECT_EQ(old_count + 1, new_count);
799 }
800
801 TEST_F(SdchOwnerPersistenceTest, LoadingDictionaryMerges) {
802 const GURL url0("http://www.example.com/dict0");
803 const GURL url1("http://www.example.com/dict1");
804
805 ResetOwner(false);
806 InsertDictionaryForURL(url1, "1");
807
808 ResetOwner(true);
809 InsertDictionaryForURL(url0, "0");
810 EXPECT_EQ(1, owner_->GetDictionaryCountForTesting());
811 owner_->EnablePersistentStorage(pref_store_.get());
812 ASSERT_TRUE(CompleteLoadFromURL(url1, "1"));
813 EXPECT_EQ(2, owner_->GetDictionaryCountForTesting());
491 } 814 }
492 815
493 } // namespace net 816 } // namespace net
OLDNEW
« no previous file with comments | « net/sdch/sdch_owner.cc ('k') | net/url_request/sdch_dictionary_fetcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698