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

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: Beef up SdchDictionaryFetcher tests 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,
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 TEST_F(SdchOwnerTest, MemoryPressureReturnsSpace) { 597 TEST_F(SdchOwnerTest, MemoryPressureReturnsSpace) {
465 std::string server_hash_d1; 598 std::string server_hash_d1;
466 std::string server_hash_d2; 599 std::string server_hash_d2;
467 600
468 // Take up all the space. 601 // Take up all the space.
469 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting, &server_hash_d1)); 602 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting, &server_hash_d1,
603 base::Time::Now()));
470 604
471 // Addition should fail. 605 // Addition should fail.
472 EXPECT_FALSE(CreateAndAddDictionary(kMaxSizeForTesting, &server_hash_d2)); 606 EXPECT_FALSE(CreateAndAddDictionary(kMaxSizeForTesting, &server_hash_d2,
607 base::Time::Now()));
473 608
474 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1)); 609 EXPECT_TRUE(DictionaryPresentInManager(server_hash_d1));
475 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2)); 610 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2));
476 611
477 base::MemoryPressureListener::NotifyMemoryPressure( 612 base::MemoryPressureListener::NotifyMemoryPressure(
478 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); 613 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
479 // The notification may have (implementation note: does :-}) use a PostTask, 614 // 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 615 // 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. 616 // an inifinite number of messages) in a unit test.
482 base::RunLoop().RunUntilIdle(); 617 base::RunLoop().RunUntilIdle();
483 618
484 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d1)); 619 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d1));
485 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2)); 620 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2));
486 621
487 // Addition should now succeed. 622 // Addition should now succeed.
488 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting, nullptr)); 623 EXPECT_TRUE(
624 CreateAndAddDictionary(kMaxSizeForTesting, nullptr, base::Time::Now()));
625 }
626
627 class SdchOwnerPersistenceTest : public ::testing::Test {
628 public:
629 SdchOwnerPersistenceTest() : pref_store_(new TestingPrefStore()) {
630 pref_store_->SetInitializationCompleted();
631 }
632 virtual ~SdchOwnerPersistenceTest() {}
633
634 void ClearOwner() {
635 owner_.reset(NULL);
636 }
637
638 void ResetOwner(bool delay) {
639 // This has to be done first, since SdchOwner may be observing SdchManager,
640 // and SdchManager can't be destroyed with a live observer.
641 owner_.reset(NULL);
642 manager_.reset(new SdchManager());
643 fetcher_ = new MockSdchDictionaryFetcher();
644 owner_.reset(new SdchOwner(manager_.get(),
645 &url_request_context_));
646 owner_->SetMaxTotalDictionarySize(SdchOwnerTest::kMaxSizeForTesting);
647 owner_->SetMinSpaceForDictionaryFetch(
648 SdchOwnerTest::kMinFetchSpaceForTesting);
649 owner_->SetFetcherForTesting(make_scoped_ptr(fetcher_));
650 if (!delay)
651 owner_->EnablePersistentStorage(pref_store_.get());
652 }
653
654 void InsertDictionaryForURL(const GURL& url, const std::string& nonce) {
655 owner_->OnDictionaryFetched(base::Time::Now(), 1,
656 CreateDictionary(url, nonce),
657 url, net_log_);
658 }
659
660 bool CompleteLoadFromURL(const GURL& url, const std::string& nonce) {
661 return fetcher_->CompletePendingRequest(url, CreateDictionary(url, nonce),
662 net_log_);
663 }
664
665 std::string CreateDictionary(const GURL& url, const std::string& nonce) {
666 std::string dict;
667 dict.append("Domain: ");
668 dict.append(url.host());
669 dict.append("\n\n");
670 dict.append(url.spec());
671 dict.append(nonce);
672 return dict;
673 }
674
675 protected:
676 BoundNetLog net_log_;
677 scoped_refptr<TestingPrefStore> pref_store_;
678 scoped_ptr<SdchManager> manager_;
679 MockSdchDictionaryFetcher* fetcher_;
680 scoped_ptr<SdchOwner> owner_;
681 TestURLRequestContext url_request_context_;
682 };
683
684 // Test an empty persistence store.
685 TEST_F(SdchOwnerPersistenceTest, Empty) {
686 ResetOwner(false);
687 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
688 }
689
690 // Test a persistence store with an empty dictionary.
691 TEST_F(SdchOwnerPersistenceTest, Persistent_EmptyDict) {
692 pref_store_->SetValue("SDCH", new base::DictionaryValue());
693 ResetOwner(false);
694 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
695 }
696
697 // Test a persistence store with a bad version number.
698 TEST_F(SdchOwnerPersistenceTest, Persistent_BadVersion) {
699 base::DictionaryValue* sdch_dict = new base::DictionaryValue();
700 sdch_dict->SetInteger("version", 2);
701 pref_store_->SetValue("SDCH", sdch_dict);
702
703 ResetOwner(false);
704 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
705 }
706
707 // Test a persistence store with an empty dictionaries map.
708 TEST_F(SdchOwnerPersistenceTest, Persistent_EmptyDictList) {
709 base::DictionaryValue* sdch_dict = new base::DictionaryValue();
710 scoped_ptr<base::DictionaryValue> dicts(new base::DictionaryValue());
711 sdch_dict->SetInteger("version", 1);
712 sdch_dict->Set("dictionaries", dicts.Pass());
713 pref_store_->SetValue("SDCH", sdch_dict);
714
715 ResetOwner(false);
716 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
717 }
718
719 TEST_F(SdchOwnerPersistenceTest, OneDict) {
720 const GURL url("http://www.example.com/dict");
721 ResetOwner(false);
722 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
723 InsertDictionaryForURL(url, "0");
724 EXPECT_EQ(1, owner_->GetDictionaryCountForTesting());
725
726 ResetOwner(false);
727 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
728 EXPECT_TRUE(CompleteLoadFromURL(url, "0"));
729 EXPECT_EQ(1, owner_->GetDictionaryCountForTesting());
730 }
731
732 TEST_F(SdchOwnerPersistenceTest, TwoDicts) {
733 const GURL url0("http://www.example.com/dict0");
734 const GURL url1("http://www.example.com/dict1");
735 ResetOwner(false);
736 InsertDictionaryForURL(url0, "0");
737 InsertDictionaryForURL(url1, "1");
738
739 ResetOwner(false);
740 EXPECT_TRUE(CompleteLoadFromURL(url0, "0"));
741 EXPECT_TRUE(CompleteLoadFromURL(url1, "1"));
742 EXPECT_EQ(2, owner_->GetDictionaryCountForTesting());
743 EXPECT_TRUE(owner_->HasDictionaryFromURLForTesting(url0));
744 EXPECT_TRUE(owner_->HasDictionaryFromURLForTesting(url1));
745 }
746
747 TEST_F(SdchOwnerPersistenceTest, OneGoodDictOneBadDict) {
748 const GURL url0("http://www.example.com/dict0");
749 const GURL url1("http://www.example.com/dict1");
750 ResetOwner(false);
751 InsertDictionaryForURL(url0, "0");
752 InsertDictionaryForURL(url1, "1");
753
754 // Mutate the pref store a bit now. Clear the owner first, to ensure that the
755 // SdchOwner doesn't observe these changes and object. The manual dictionary
756 // manipulation is a bit icky.
757 ClearOwner();
758 base::DictionaryValue* dict = nullptr;
759 ASSERT_TRUE(GetDictionaryForURL(pref_store_.get(), url1, nullptr, &dict));
760 dict->Remove("use_count", nullptr);
761
762 ResetOwner(false);
763 EXPECT_TRUE(CompleteLoadFromURL(url0, "0"));
764 EXPECT_FALSE(CompleteLoadFromURL(url1, "1"));
765 EXPECT_EQ(1, owner_->GetDictionaryCountForTesting());
766 EXPECT_TRUE(owner_->HasDictionaryFromURLForTesting(url0));
767 EXPECT_FALSE(owner_->HasDictionaryFromURLForTesting(url1));
768 }
769
770 TEST_F(SdchOwnerPersistenceTest, UsingDictionaryUpdatesUseCount) {
771 const GURL url("http://www.example.com/dict");
772 ResetOwner(false);
773 InsertDictionaryForURL(url, "0");
774
775 std::string hash;
776 int old_count;
777 {
778 ClearOwner();
779 base::DictionaryValue* dict = nullptr;
780 ASSERT_TRUE(GetDictionaryForURL(pref_store_.get(), url, &hash, &dict));
781 ASSERT_TRUE(dict->GetInteger("use_count", &old_count));
782 }
783
784 ResetOwner(false);
785 ASSERT_TRUE(CompleteLoadFromURL(url, "0"));
786 owner_->OnDictionaryUsed(manager_.get(), hash);
787
788 int new_count;
789 {
790 ClearOwner();
791 base::DictionaryValue* dict = nullptr;
792 ASSERT_TRUE(GetDictionaryForURL(pref_store_.get(), url, nullptr, &dict));
793 ASSERT_TRUE(dict->GetInteger("use_count", &new_count));
794 }
795
796 EXPECT_EQ(old_count + 1, new_count);
797 }
798
799 TEST_F(SdchOwnerPersistenceTest, LoadingDictionaryMerges) {
800 const GURL url0("http://www.example.com/dict0");
801 const GURL url1("http://www.example.com/dict1");
802
803 ResetOwner(false);
804 InsertDictionaryForURL(url1, "1");
805
806 ResetOwner(true);
807 InsertDictionaryForURL(url0, "0");
808 EXPECT_EQ(1, owner_->GetDictionaryCountForTesting());
809 owner_->EnablePersistentStorage(pref_store_.get());
810 ASSERT_TRUE(CompleteLoadFromURL(url1, "1"));
811 EXPECT_EQ(2, owner_->GetDictionaryCountForTesting());
489 } 812 }
490 813
491 } // namespace net 814 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698