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

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

Powered by Google App Engine
This is Rietveld 408576698