OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "base/run_loop.h" |
| 6 #include "base/threading/platform_thread.h" |
| 7 #include "chrome/browser/profiles/profile.h" |
| 8 #include "chrome/browser/ui/browser.h" |
| 9 #include "chrome/test/base/in_process_browser_test.h" |
| 10 #include "components/browsing_data/storage_partition_http_cache_data_remover.h" |
| 11 #include "content/public/browser/browser_context.h" |
| 12 #include "content/public/browser/browser_thread.h" |
| 13 #include "content/public/browser/storage_partition.h" |
| 14 #include "net/disk_cache/disk_cache.h" |
| 15 #include "net/http/http_cache.h" |
| 16 #include "net/url_request/url_request_context.h" |
| 17 #include "net/url_request/url_request_context_getter.h" |
| 18 |
| 19 using browsing_data::StoragePartitionHttpCacheDataRemover; |
| 20 using content::BrowserThread; |
| 21 |
| 22 class StoragePartitionHttpCacheDataRemoverBrowserTest |
| 23 : public InProcessBrowserTest { |
| 24 public: |
| 25 // Initialization ------------------------------------------------------------ |
| 26 |
| 27 void SetUpOnMainThread() override { |
| 28 result_callback_ = base::Bind( |
| 29 &StoragePartitionHttpCacheDataRemoverBrowserTest::ResultCallback, |
| 30 base::Unretained(this)); |
| 31 removal_callback_ = base::Bind( |
| 32 &StoragePartitionHttpCacheDataRemoverBrowserTest::RemovalCallback, |
| 33 base::Unretained(this)); |
| 34 done_callback_ = base::Bind( |
| 35 &StoragePartitionHttpCacheDataRemoverBrowserTest::DoneCallback, |
| 36 base::Unretained(this)); |
| 37 remaining_tasks_ = 0; |
| 38 next_key_ = 0; |
| 39 |
| 40 partition_ = content::BrowserContext::GetDefaultStoragePartition( |
| 41 browser()->profile()); |
| 42 |
| 43 // Get the cache backends. |
| 44 BrowserThread::PostTask( |
| 45 BrowserThread::IO, FROM_HERE, |
| 46 base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest:: |
| 47 InitializeCountingTest, |
| 48 base::Unretained(this))); |
| 49 WaitForTasksOnIOThread(); |
| 50 DCHECK(main_backend_); |
| 51 DCHECK(media_backend_); |
| 52 } |
| 53 |
| 54 void InitializeCountingTest() { |
| 55 net::URLRequestContextGetter* main_context; |
| 56 net::URLRequestContextGetter* media_context; |
| 57 |
| 58 main_context = partition_->GetURLRequestContext(); |
| 59 media_context = partition_->GetMediaURLRequestContext(); |
| 60 |
| 61 net::HttpCache* main_cache = main_context->GetURLRequestContext()-> |
| 62 http_transaction_factory()->GetCache(); |
| 63 net::HttpCache* media_cache = media_context->GetURLRequestContext()-> |
| 64 http_transaction_factory()->GetCache(); |
| 65 |
| 66 SetNumberOfWaitedTasks(2); |
| 67 WaitForCompletion(main_cache->GetBackend(&main_backend_, done_callback_)); |
| 68 WaitForCompletion(media_cache->GetBackend(&media_backend_, done_callback_)); |
| 69 } |
| 70 |
| 71 // Get a new remover instance. |
| 72 StoragePartitionHttpCacheDataRemover* GetNewRemover() { |
| 73 return GetNewRemoverForRange(base::Time(), base::Time::Max()); |
| 74 } |
| 75 |
| 76 StoragePartitionHttpCacheDataRemover* GetNewRemoverForRange( |
| 77 base::Time begin, base::Time end) { |
| 78 return StoragePartitionHttpCacheDataRemover::CreateForRange( |
| 79 partition_, begin, end); |
| 80 } |
| 81 |
| 82 // Waiting for the calculation and retrieving results on the UI thread, |
| 83 // or cache cleaning. -------------------------------------------------------- |
| 84 |
| 85 void WaitForResultOrRemoval() { |
| 86 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 87 loop_.reset(new base::RunLoop()); |
| 88 loop_->Run(); |
| 89 } |
| 90 |
| 91 void ResultCallback(int64 result) { |
| 92 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 93 if (loop_) |
| 94 loop_->Quit(); |
| 95 result_ = result; |
| 96 } |
| 97 |
| 98 void RemovalCallback() { |
| 99 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 100 if (loop_) |
| 101 loop_->Quit(); |
| 102 } |
| 103 |
| 104 net::Int64CompletionCallback GetResultCallback() { |
| 105 return result_callback_; |
| 106 } |
| 107 |
| 108 base::Closure GetRemovalCallback() { |
| 109 return removal_callback_; |
| 110 } |
| 111 |
| 112 int64 GetResult() { |
| 113 return result_; |
| 114 } |
| 115 |
| 116 // Waiting for tasks to be done on IO thread. -------------------------------- |
| 117 |
| 118 void WaitForTasksOnIOThread() { |
| 119 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 120 io_thread_loop_.reset(new base::RunLoop()); |
| 121 io_thread_loop_->Run(); |
| 122 } |
| 123 |
| 124 void SetNumberOfWaitedTasks(int count) { |
| 125 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 126 remaining_tasks_ = count; |
| 127 } |
| 128 |
| 129 void WaitForCompletion(int value) { |
| 130 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 131 if (value >= 0) { |
| 132 // We got the result immediately. |
| 133 DoneCallback(value); |
| 134 } else if (value == net::ERR_IO_PENDING) { |
| 135 // We need to wait for the callback. |
| 136 } else { |
| 137 // An error has occurred. |
| 138 NOTREACHED(); |
| 139 } |
| 140 } |
| 141 |
| 142 void DoneCallback(int value) { |
| 143 DCHECK_GE(value, 0); // Negative values represent error codes. |
| 144 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 145 if (--remaining_tasks_ > 0) |
| 146 return; |
| 147 |
| 148 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 149 BrowserThread::PostTask( |
| 150 BrowserThread::UI, FROM_HERE, |
| 151 base::Bind(&base::RunLoop::Quit, |
| 152 base::Unretained(io_thread_loop_.get()))); |
| 153 } |
| 154 |
| 155 // Helpers. ------------------------------------------------------------------ |
| 156 |
| 157 void CreateCacheEntries(size_t main_count, size_t media_count) { |
| 158 entries_.resize(main_count + media_count); |
| 159 |
| 160 SetNumberOfWaitedTasks(main_count + media_count); |
| 161 for (size_t i = 0; i < main_count; ++i) { |
| 162 WaitForCompletion(main_backend_->CreateEntry( |
| 163 GetUniqueEntryKey(), &entries_[i], done_callback_)); |
| 164 } |
| 165 for (size_t i = main_count; i < main_count + media_count; ++i) { |
| 166 WaitForCompletion(media_backend_->CreateEntry( |
| 167 GetUniqueEntryKey(), &entries_[i], done_callback_)); |
| 168 } |
| 169 } |
| 170 |
| 171 void WriteDataToEntries(const std::vector<int>& sizes) { |
| 172 DCHECK_EQ(entries_.size(), sizes.size()); |
| 173 std::string data(*std::max_element(sizes.begin(), sizes.end()), ' '); |
| 174 scoped_refptr<net::StringIOBuffer> buffer = new net::StringIOBuffer(data); |
| 175 |
| 176 SetNumberOfWaitedTasks(entries_.size()); |
| 177 for (size_t i = 0; i < entries_.size(); ++i) { |
| 178 // Alternate between writing to the first and second stream to test that |
| 179 // we're taking all streams into account. |
| 180 WaitForCompletion(entries_[i]->WriteData( |
| 181 i % 2, 0, buffer.get(), sizes[i], done_callback_, true)); |
| 182 } |
| 183 } |
| 184 |
| 185 private: |
| 186 // Generates a unique key for a new cache entry. |
| 187 std::string GetUniqueEntryKey() { |
| 188 return std::to_string(next_key_++); |
| 189 } |
| 190 |
| 191 int next_key_; |
| 192 |
| 193 content::StoragePartition* partition_; |
| 194 disk_cache::Backend* main_backend_ = nullptr; |
| 195 disk_cache::Backend* media_backend_ = nullptr; |
| 196 |
| 197 // Shorthands for callback binding. |
| 198 base::Callback<void(int)> done_callback_; |
| 199 base::Closure removal_callback_; |
| 200 net::Int64CompletionCallback result_callback_; |
| 201 |
| 202 int64 result_; |
| 203 scoped_ptr<base::RunLoop> loop_; |
| 204 scoped_ptr<base::RunLoop> io_thread_loop_; |
| 205 |
| 206 std::vector<disk_cache::Entry*> entries_; |
| 207 int remaining_tasks_; |
| 208 }; |
| 209 |
| 210 // Test that the size of empty cache is computed as 0. |
| 211 IN_PROC_BROWSER_TEST_F( |
| 212 StoragePartitionHttpCacheDataRemoverBrowserTest, Empty) { |
| 213 // Calculate the size of the empty caches. The result should be 0. |
| 214 GetNewRemover()->Count(GetResultCallback()); |
| 215 WaitForResultOrRemoval(); |
| 216 EXPECT_TRUE(GetResult() == 0 || GetResult() == net::ERR_NOT_IMPLEMENTED); |
| 217 } |
| 218 |
| 219 // Test that StoragePartitionHttpCacheDataRemover correctly counts the total |
| 220 // size of items in the main and media cache. |
| 221 IN_PROC_BROWSER_TEST_F( |
| 222 StoragePartitionHttpCacheDataRemoverBrowserTest, Counting) { |
| 223 // Create 5 entries and write 23 bytes of data, distributed to both caches, |
| 224 // different entries, and different streams within them. |
| 225 BrowserThread::PostTask( |
| 226 BrowserThread::IO, FROM_HERE, |
| 227 base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest:: |
| 228 CreateCacheEntries, |
| 229 base::Unretained(this), |
| 230 3, 2)); |
| 231 WaitForTasksOnIOThread(); |
| 232 |
| 233 std::vector<int> data; |
| 234 data.push_back(10); |
| 235 data.push_back(3); |
| 236 data.push_back(4); |
| 237 data.push_back(1); |
| 238 data.push_back(5); |
| 239 BrowserThread::PostTask( |
| 240 BrowserThread::IO, FROM_HERE, |
| 241 base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest:: |
| 242 WriteDataToEntries, |
| 243 base::Unretained(this), |
| 244 data)); |
| 245 WaitForTasksOnIOThread(); |
| 246 |
| 247 // Calculate the size of the caches now. The result should be 23. |
| 248 // TODO(msramek): Change the test to "EXPECT_EQ(23, GetResult());" as soon as |
| 249 // the size calculation is implemented for memory and simple cache backends. |
| 250 GetNewRemover()->Count(GetResultCallback()); |
| 251 WaitForResultOrRemoval(); |
| 252 EXPECT_TRUE(GetResult() == 23 || GetResult() == net::ERR_NOT_IMPLEMENTED); |
| 253 } |
| 254 |
| 255 // Test that StoragePartitionHttpCacheDataRemover correctly recognizes the cache |
| 256 // to be empty when it was populated and cleared again. |
| 257 IN_PROC_BROWSER_TEST_F( |
| 258 StoragePartitionHttpCacheDataRemoverBrowserTest, PopulatedAndCleared) { |
| 259 // Write data to both caches. |
| 260 BrowserThread::PostTask( |
| 261 BrowserThread::IO, FROM_HERE, |
| 262 base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest:: |
| 263 CreateCacheEntries, |
| 264 base::Unretained(this), |
| 265 1, 2)); |
| 266 WaitForTasksOnIOThread(); |
| 267 |
| 268 std::vector<int> data; |
| 269 data.push_back(10000); |
| 270 data.push_back(12345); |
| 271 data.push_back(20000); |
| 272 BrowserThread::PostTask( |
| 273 BrowserThread::IO, FROM_HERE, |
| 274 base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest:: |
| 275 WriteDataToEntries, |
| 276 base::Unretained(this), |
| 277 data)); |
| 278 WaitForTasksOnIOThread(); |
| 279 |
| 280 // Clear both caches. |
| 281 GetNewRemover()->Remove(GetRemovalCallback()); |
| 282 WaitForResultOrRemoval(); |
| 283 |
| 284 // Calculate the size of the caches. The result should be 0. |
| 285 // TODO(msramek): Change the test to "EXPECT_EQ(0, GetResult());" as soon as |
| 286 // the size calculation is implemented for memory and simple cache backends. |
| 287 GetNewRemover()->Count(GetResultCallback()); |
| 288 WaitForResultOrRemoval(); |
| 289 EXPECT_TRUE(GetResult() == 0 || GetResult() == net::ERR_NOT_IMPLEMENTED); |
| 290 } |
| 291 |
| 292 // Test that StoragePartitionHttpCacheDataRemover correctly counts the cache |
| 293 // size when data are incrementally added. |
| 294 IN_PROC_BROWSER_TEST_F( |
| 295 StoragePartitionHttpCacheDataRemoverBrowserTest, Incremental) { |
| 296 // Write data to both caches. |
| 297 BrowserThread::PostTask( |
| 298 BrowserThread::IO, FROM_HERE, |
| 299 base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest:: |
| 300 CreateCacheEntries, |
| 301 base::Unretained(this), |
| 302 1, 2)); |
| 303 WaitForTasksOnIOThread(); |
| 304 |
| 305 std::vector<int> data; |
| 306 data.push_back(5); |
| 307 data.push_back(7); |
| 308 data.push_back(9); |
| 309 BrowserThread::PostTask( |
| 310 BrowserThread::IO, FROM_HERE, |
| 311 base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest:: |
| 312 WriteDataToEntries, |
| 313 base::Unretained(this), |
| 314 data)); |
| 315 WaitForTasksOnIOThread(); |
| 316 |
| 317 // The size should be 21. |
| 318 // TODO(msramek): Change the test to "EXPECT_EQ(21, GetResult());" as soon as |
| 319 // the size calculation is implemented for memory and simple cache backends. |
| 320 GetNewRemover()->Count(GetResultCallback()); |
| 321 WaitForResultOrRemoval(); |
| 322 EXPECT_TRUE(GetResult() == 21 || GetResult() == net::ERR_NOT_IMPLEMENTED); |
| 323 |
| 324 // Create a new batch of entries and write more data. |
| 325 BrowserThread::PostTask( |
| 326 BrowserThread::IO, FROM_HERE, |
| 327 base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest:: |
| 328 CreateCacheEntries, |
| 329 base::Unretained(this), |
| 330 4, 3)); |
| 331 WaitForTasksOnIOThread(); |
| 332 |
| 333 data.clear(); |
| 334 data.push_back(0); |
| 335 data.push_back(1); |
| 336 data.push_back(1); |
| 337 data.push_back(8); |
| 338 data.push_back(9); |
| 339 data.push_back(9); |
| 340 data.push_back(9); |
| 341 BrowserThread::PostTask( |
| 342 BrowserThread::IO, FROM_HERE, |
| 343 base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest:: |
| 344 WriteDataToEntries, |
| 345 base::Unretained(this), |
| 346 data)); |
| 347 WaitForTasksOnIOThread(); |
| 348 |
| 349 // The size should be 58. |
| 350 // TODO(msramek): Change the test to "EXPECT_EQ(58, GetResult());" as soon as |
| 351 // the size calculation is implemented for memory and simple cache backends. |
| 352 GetNewRemover()->Count(GetResultCallback()); |
| 353 WaitForResultOrRemoval(); |
| 354 EXPECT_TRUE(GetResult() == 58 || GetResult() == net::ERR_NOT_IMPLEMENTED); |
| 355 |
| 356 // Update the entries from the last batch with new values. |
| 357 data.clear(); |
| 358 data.push_back(1); |
| 359 data.push_back(2); |
| 360 data.push_back(3); |
| 361 data.push_back(4); |
| 362 data.push_back(5); |
| 363 data.push_back(6); |
| 364 data.push_back(7); |
| 365 BrowserThread::PostTask( |
| 366 BrowserThread::IO, FROM_HERE, |
| 367 base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest:: |
| 368 WriteDataToEntries, |
| 369 base::Unretained(this), |
| 370 data)); |
| 371 WaitForTasksOnIOThread(); |
| 372 |
| 373 // The size should now be 49. |
| 374 // TODO(msramek): Change the test to "EXPECT_EQ(49, GetResult());" as soon as |
| 375 // the size calculation is implemented for memory and simple cache backends. |
| 376 GetNewRemover()->Count(GetResultCallback()); |
| 377 WaitForResultOrRemoval(); |
| 378 EXPECT_TRUE(GetResult() == 49 || GetResult() == net::ERR_NOT_IMPLEMENTED); |
| 379 } |
| 380 |
| 381 IN_PROC_BROWSER_TEST_F( |
| 382 StoragePartitionHttpCacheDataRemoverBrowserTest, TimePeriod) { |
| 383 // Write a batch of entries. |
| 384 BrowserThread::PostTask( |
| 385 BrowserThread::IO, FROM_HERE, |
| 386 base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest:: |
| 387 CreateCacheEntries, |
| 388 base::Unretained(this), |
| 389 2, 2)); |
| 390 WaitForTasksOnIOThread(); |
| 391 |
| 392 std::vector<int> data; |
| 393 data.push_back(7); |
| 394 data.push_back(2); |
| 395 data.push_back(5); |
| 396 data.push_back(3); |
| 397 BrowserThread::PostTask( |
| 398 BrowserThread::IO, FROM_HERE, |
| 399 base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest:: |
| 400 WriteDataToEntries, |
| 401 base::Unretained(this), |
| 402 data)); |
| 403 WaitForTasksOnIOThread(); |
| 404 |
| 405 // Skip at least a millisecond. Since time ranges are half-closed intervals, |
| 406 // |threshold| must be strictly greater than timestamps of any previous entry. |
| 407 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); |
| 408 base::Time threshold = base::Time::Now(); |
| 409 |
| 410 // Write another batch of entries. |
| 411 BrowserThread::PostTask( |
| 412 BrowserThread::IO, FROM_HERE, |
| 413 base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest:: |
| 414 CreateCacheEntries, |
| 415 base::Unretained(this), |
| 416 1, 2)); |
| 417 WaitForTasksOnIOThread(); |
| 418 |
| 419 data.clear(); |
| 420 data.push_back(1); |
| 421 data.push_back(6); |
| 422 data.push_back(4); |
| 423 BrowserThread::PostTask( |
| 424 BrowserThread::IO, FROM_HERE, |
| 425 base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest:: |
| 426 WriteDataToEntries, |
| 427 base::Unretained(this), |
| 428 data)); |
| 429 WaitForTasksOnIOThread(); |
| 430 |
| 431 // Count the entries added before the threshold. The result should be 17. |
| 432 // TODO(msramek): Change the test to "EXPECT_EQ(17, GetResult());" as soon as |
| 433 // the size calculation is implemented for memory and simple cache backends. |
| 434 GetNewRemoverForRange(base::Time(), threshold)->Count(GetResultCallback()); |
| 435 WaitForResultOrRemoval(); |
| 436 EXPECT_TRUE(GetResult() == 17 || GetResult() == net::ERR_NOT_IMPLEMENTED); |
| 437 |
| 438 // Count the entries added after the threshold. The result should be 11. |
| 439 // TODO(msramek): Change the test to "EXPECT_EQ(11, GetResult());" as soon as |
| 440 // the size calculation is implemented for memory and simple cache backends. |
| 441 GetNewRemoverForRange( |
| 442 threshold, base::Time::Now())->Count(GetResultCallback()); |
| 443 WaitForResultOrRemoval(); |
| 444 EXPECT_TRUE(GetResult() == 11 || GetResult() == net::ERR_NOT_IMPLEMENTED); |
| 445 } |
OLD | NEW |