Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <stack> | 5 #include <stack> |
| 6 #include <string> | 6 #include <string> |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/threading/thread.h" | 10 #include "base/threading/thread.h" |
| 11 #include "base/synchronization/waitable_event.h" | 11 #include "base/synchronization/waitable_event.h" |
| 12 #include "net/base/net_errors.h" | 12 #include "net/base/net_errors.h" |
| 13 #include "net/http/http_response_headers.h" | |
| 13 #include "net/url_request/url_request.h" | 14 #include "net/url_request/url_request.h" |
| 14 #include "net/url_request/url_request_error_job.h" | 15 #include "net/url_request/url_request_error_job.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 16 #include "webkit/appcache/appcache.h" | 17 #include "webkit/appcache/appcache.h" |
| 17 #include "webkit/appcache/appcache_backend_impl.h" | 18 #include "webkit/appcache/appcache_backend_impl.h" |
| 18 #include "webkit/appcache/appcache_request_handler.h" | 19 #include "webkit/appcache/appcache_request_handler.h" |
| 19 #include "webkit/appcache/appcache_url_request_job.h" | 20 #include "webkit/appcache/appcache_url_request_job.h" |
| 20 #include "webkit/appcache/mock_appcache_service.h" | 21 #include "webkit/appcache/mock_appcache_service.h" |
| 21 | 22 |
| 22 namespace appcache { | 23 namespace appcache { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 61 virtual void Run() { | 62 virtual void Run() { |
| 62 test_->SetUpTest(); | 63 test_->SetUpTest(); |
| 63 (test_->*method_)(); | 64 (test_->*method_)(); |
| 64 } | 65 } |
| 65 | 66 |
| 66 private: | 67 private: |
| 67 AppCacheRequestHandlerTest* test_; | 68 AppCacheRequestHandlerTest* test_; |
| 68 Method method_; | 69 Method method_; |
| 69 }; | 70 }; |
| 70 | 71 |
| 71 // Subclasses to simulate particular response codes so test cases can | 72 // Subclasses to simulate particular responses so test cases can |
| 72 // exercise fallback code paths. | 73 // exercise fallback code paths. |
| 73 | 74 |
| 75 class MockURLRequestDelegate : public net::URLRequest::Delegate { | |
| 76 virtual void OnResponseStarted(net::URLRequest* request) {} | |
| 77 virtual void OnReadCompleted(net::URLRequest* request, int bytes_read) {} | |
| 78 }; | |
| 79 | |
| 74 class MockURLRequestJob : public net::URLRequestJob { | 80 class MockURLRequestJob : public net::URLRequestJob { |
| 75 public: | 81 public: |
| 76 MockURLRequestJob(net::URLRequest* request, int response_code) | 82 MockURLRequestJob( |
| 77 : net::URLRequestJob(request), response_code_(response_code) {} | 83 net::URLRequest* request, int response_code) |
| 78 virtual void Start() {} | 84 : net::URLRequestJob(request), |
| 79 virtual int GetResponseCode() const { return response_code_; } | 85 response_code_(response_code), |
| 86 has_response_info_(false) {} | |
| 87 MockURLRequestJob( | |
| 88 net::URLRequest* request, const net::HttpResponseInfo& info) | |
| 89 : net::URLRequestJob(request), | |
| 90 response_code_(0), | |
| 91 has_response_info_(true), | |
| 92 response_info_(info) {} | |
| 93 virtual void Start() { | |
| 94 NotifyHeadersComplete(); | |
| 95 } | |
| 96 virtual int GetResponseCode() const { | |
| 97 if (!has_response_info_) | |
|
jennb
2011/05/10 00:13:53
You could initialize response_code_ to info.header
michaeln
2011/05/10 00:41:58
Done.
| |
| 98 return response_code_; | |
| 99 return response_info_.headers->response_code(); | |
| 100 } | |
| 101 virtual void GetResponseInfo(net::HttpResponseInfo* info) { | |
| 102 if (!has_response_info_) | |
| 103 return; | |
| 104 *info = response_info_; | |
| 105 } | |
| 80 int response_code_; | 106 int response_code_; |
| 107 bool has_response_info_; | |
| 108 net::HttpResponseInfo response_info_; | |
| 81 }; | 109 }; |
| 82 | 110 |
| 83 class MockURLRequest : public net::URLRequest { | 111 class MockURLRequest : public net::URLRequest { |
| 84 public: | 112 public: |
| 85 explicit MockURLRequest(const GURL& url) : net::URLRequest(url, NULL) {} | 113 explicit MockURLRequest(const GURL& url) : net::URLRequest(url, NULL) {} |
| 86 | 114 |
| 87 void SimulateResponseCode(int http_response_code) { | 115 void SimulateResponseCode(int http_response_code) { |
| 88 mock_factory_job_ = new MockURLRequestJob(this, http_response_code); | 116 mock_factory_job_ = new MockURLRequestJob(this, http_response_code); |
| 89 Start(); | 117 Start(); |
| 90 DCHECK(!mock_factory_job_); | 118 DCHECK(!mock_factory_job_); |
| 91 // All our simulation need to do satisfy are the following two DCHECKs | 119 // All our simulation needs to satisfy are the following two DCHECKs |
| 92 DCHECK(status().is_success()); | 120 DCHECK(status().is_success()); |
| 93 DCHECK_EQ(http_response_code, GetResponseCode()); | 121 DCHECK_EQ(http_response_code, GetResponseCode()); |
| 94 } | 122 } |
| 123 | |
| 124 void SimulateResponseInfo(const net::HttpResponseInfo& info) { | |
| 125 mock_factory_job_ = new MockURLRequestJob(this, info); | |
| 126 set_delegate(&delegate_); // needed to get the info back out | |
| 127 Start(); | |
| 128 DCHECK(!mock_factory_job_); | |
| 129 } | |
| 130 | |
| 131 MockURLRequestDelegate delegate_; | |
| 95 }; | 132 }; |
| 96 | 133 |
| 97 static net::URLRequestJob* MockHttpJobFactory(net::URLRequest* request, | 134 static net::URLRequestJob* MockHttpJobFactory(net::URLRequest* request, |
| 98 const std::string& scheme) { | 135 const std::string& scheme) { |
| 99 if (mock_factory_job_) { | 136 if (mock_factory_job_) { |
| 100 net::URLRequestJob* temp = mock_factory_job_; | 137 net::URLRequestJob* temp = mock_factory_job_; |
| 101 mock_factory_job_ = NULL; | 138 mock_factory_job_ = NULL; |
| 102 return temp; | 139 return temp; |
| 103 } else { | 140 } else { |
| 104 // Some of these tests trigger UpdateJobs which start URLRequests. | 141 // Some of these tests trigger UpdateJobs which start URLRequests. |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 321 EXPECT_EQ(GURL("http://blah/manifest/"), manifest_url); | 358 EXPECT_EQ(GURL("http://blah/manifest/"), manifest_url); |
| 322 EXPECT_TRUE(host_->main_resource_was_fallback_); | 359 EXPECT_TRUE(host_->main_resource_was_fallback_); |
| 323 EXPECT_EQ(GURL("http://blah/fallbackurl"), host_->fallback_url_); | 360 EXPECT_EQ(GURL("http://blah/fallbackurl"), host_->fallback_url_); |
| 324 | 361 |
| 325 EXPECT_EQ(GURL("http://blah/manifest/"), | 362 EXPECT_EQ(GURL("http://blah/manifest/"), |
| 326 host_->preferred_manifest_url()); | 363 host_->preferred_manifest_url()); |
| 327 | 364 |
| 328 TestFinished(); | 365 TestFinished(); |
| 329 } | 366 } |
| 330 | 367 |
| 368 // MainResource_FallbackOverride -------------------------------------------- | |
| 369 | |
| 370 void MainResource_FallbackOverride() { | |
| 371 PushNextTask(NewRunnableMethod( | |
| 372 this, | |
| 373 &AppCacheRequestHandlerTest::Verify_MainResource_FallbackOverride)); | |
| 374 | |
| 375 request_.reset(new MockURLRequest(GURL("http://blah/fallback-override"))); | |
| 376 handler_.reset(host_->CreateRequestHandler(request_.get(), | |
| 377 ResourceType::MAIN_FRAME)); | |
| 378 EXPECT_TRUE(handler_.get()); | |
| 379 | |
| 380 mock_storage()->SimulateFindMainResource( | |
| 381 AppCacheEntry(), | |
| 382 GURL("http://blah/fallbackurl"), | |
| 383 AppCacheEntry(AppCacheEntry::EXPLICIT, 1), | |
| 384 1, GURL("http://blah/manifest/")); | |
| 385 | |
| 386 job_ = handler_->MaybeLoadResource(request_.get()); | |
| 387 EXPECT_TRUE(job_.get()); | |
| 388 EXPECT_TRUE(job_->is_waiting()); | |
| 389 | |
| 390 // We have to wait for completion of storage->FindResponseForMainRequest. | |
| 391 ScheduleNextTask(); | |
| 392 } | |
| 393 | |
| 394 void Verify_MainResource_FallbackOverride() { | |
| 395 EXPECT_FALSE(job_->is_waiting()); | |
| 396 EXPECT_TRUE(job_->is_delivering_network_response()); | |
| 397 | |
| 398 // When the request is restarted, the existing job is dropped so a | |
| 399 // real network job gets created. We expect NULL here which will cause | |
| 400 // the net library to create a real job. | |
| 401 job_ = handler_->MaybeLoadResource(request_.get()); | |
| 402 EXPECT_FALSE(job_); | |
| 403 | |
| 404 // Simulate an http error of the real network job, but with custom | |
| 405 // headers that override the fallback behavior. | |
| 406 const char kOverrideHeaders[] = | |
| 407 "HTTP/1.1 404 BOO HOO\0" | |
| 408 "x-chromium-appcache-fallback-override: disallow-fallback\0" | |
| 409 "\0"; | |
| 410 net::HttpResponseInfo info; | |
| 411 info.headers = new net::HttpResponseHeaders( | |
| 412 std::string(kOverrideHeaders, arraysize(kOverrideHeaders))); | |
| 413 request_->SimulateResponseInfo(info); | |
| 414 | |
| 415 job_ = handler_->MaybeLoadFallbackForResponse(request_.get()); | |
| 416 EXPECT_FALSE(job_); | |
| 417 | |
| 418 int64 cache_id = kNoCacheId; | |
|
jennb
2011/05/10 00:13:53
These checks seem unnecessary as we've already ass
michaeln
2011/05/10 00:41:58
removed
| |
| 419 GURL manifest_url; | |
| 420 handler_->GetExtraResponseInfo(&cache_id, &manifest_url); | |
| 421 EXPECT_EQ(kNoCacheId, cache_id); | |
| 422 EXPECT_TRUE(manifest_url.is_empty()); | |
| 423 | |
| 424 TestFinished(); | |
| 425 } | |
| 426 | |
| 331 // SubResource_Miss_WithNoCacheSelected ---------------------------------- | 427 // SubResource_Miss_WithNoCacheSelected ---------------------------------- |
| 332 | 428 |
| 333 void SubResource_Miss_WithNoCacheSelected() { | 429 void SubResource_Miss_WithNoCacheSelected() { |
| 334 request_.reset(new MockURLRequest(GURL("http://blah/"))); | 430 request_.reset(new MockURLRequest(GURL("http://blah/"))); |
| 335 handler_.reset(host_->CreateRequestHandler(request_.get(), | 431 handler_.reset(host_->CreateRequestHandler(request_.get(), |
| 336 ResourceType::SUB_RESOURCE)); | 432 ResourceType::SUB_RESOURCE)); |
| 337 | 433 |
| 338 // We avoid creating handler when possible, sub-resource requests are not | 434 // We avoid creating handler when possible, sub-resource requests are not |
| 339 // subject to retrieval from an appcache when there's no associated cache. | 435 // subject to retrieval from an appcache when there's no associated cache. |
| 340 EXPECT_FALSE(handler_.get()); | 436 EXPECT_FALSE(handler_.get()); |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 690 } | 786 } |
| 691 | 787 |
| 692 TEST_F(AppCacheRequestHandlerTest, MainResource_Hit) { | 788 TEST_F(AppCacheRequestHandlerTest, MainResource_Hit) { |
| 693 RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Hit); | 789 RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Hit); |
| 694 } | 790 } |
| 695 | 791 |
| 696 TEST_F(AppCacheRequestHandlerTest, MainResource_Fallback) { | 792 TEST_F(AppCacheRequestHandlerTest, MainResource_Fallback) { |
| 697 RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Fallback); | 793 RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Fallback); |
| 698 } | 794 } |
| 699 | 795 |
| 796 TEST_F(AppCacheRequestHandlerTest, MainResource_FallbackOverride) { | |
| 797 RunTestOnIOThread( | |
| 798 &AppCacheRequestHandlerTest::MainResource_FallbackOverride); | |
| 799 } | |
| 800 | |
| 700 TEST_F(AppCacheRequestHandlerTest, SubResource_Miss_WithNoCacheSelected) { | 801 TEST_F(AppCacheRequestHandlerTest, SubResource_Miss_WithNoCacheSelected) { |
| 701 RunTestOnIOThread( | 802 RunTestOnIOThread( |
| 702 &AppCacheRequestHandlerTest::SubResource_Miss_WithNoCacheSelected); | 803 &AppCacheRequestHandlerTest::SubResource_Miss_WithNoCacheSelected); |
| 703 } | 804 } |
| 704 | 805 |
| 705 TEST_F(AppCacheRequestHandlerTest, SubResource_Miss_WithCacheSelected) { | 806 TEST_F(AppCacheRequestHandlerTest, SubResource_Miss_WithCacheSelected) { |
| 706 RunTestOnIOThread( | 807 RunTestOnIOThread( |
| 707 &AppCacheRequestHandlerTest::SubResource_Miss_WithCacheSelected); | 808 &AppCacheRequestHandlerTest::SubResource_Miss_WithCacheSelected); |
| 708 } | 809 } |
| 709 | 810 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 748 | 849 |
| 749 TEST_F(AppCacheRequestHandlerTest, WorkerRequest) { | 850 TEST_F(AppCacheRequestHandlerTest, WorkerRequest) { |
| 750 RunTestOnIOThread(&AppCacheRequestHandlerTest::WorkerRequest); | 851 RunTestOnIOThread(&AppCacheRequestHandlerTest::WorkerRequest); |
| 751 } | 852 } |
| 752 | 853 |
| 753 } // namespace appcache | 854 } // namespace appcache |
| 754 | 855 |
| 755 // AppCacheRequestHandlerTest is expected to always live longer than the | 856 // AppCacheRequestHandlerTest is expected to always live longer than the |
| 756 // runnable methods. This lets us call NewRunnableMethod on its instances. | 857 // runnable methods. This lets us call NewRunnableMethod on its instances. |
| 757 DISABLE_RUNNABLE_METHOD_REFCOUNT(appcache::AppCacheRequestHandlerTest); | 858 DISABLE_RUNNABLE_METHOD_REFCOUNT(appcache::AppCacheRequestHandlerTest); |
| OLD | NEW |