OLD | NEW |
---|---|
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, | |
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 Loading... | |
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 }; | |
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 /* SdchOwnerTest */ { | |
Randy Smith (Not in Mondays)
2015/02/16 01:10:05
nit: I find this comment syntax confusing. Should
Elly Fong-Jones
2015/02/17 20:35:29
The comment was saying that it notionally was, but
| |
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 |
OLD | NEW |