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, |
| 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 Loading... |
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 |
OLD | NEW |