Chromium Code Reviews| Index: content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc |
| diff --git a/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc b/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc |
| index cd90d45f731150edf3217673b3d97d4d506b0dac..4d27dd50d994e70ed41b31197cf3b736e4484955 100644 |
| --- a/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc |
| +++ b/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc |
| @@ -7,12 +7,15 @@ |
| #include "content/browser/service_worker/embedded_worker_test_helper.h" |
| #include "content/browser/service_worker/service_worker_context_core.h" |
| #include "content/browser/service_worker/service_worker_context_request_handler.h" |
| +#include "content/browser/service_worker/service_worker_disk_cache.h" |
| #include "content/browser/service_worker/service_worker_provider_host.h" |
| #include "content/browser/service_worker/service_worker_registration.h" |
| +#include "content/browser/service_worker/service_worker_test_utils.h" |
| #include "content/browser/service_worker/service_worker_utils.h" |
| #include "content/common/resource_request_body.h" |
| #include "content/public/test/mock_resource_context.h" |
| #include "content/public/test/test_browser_thread_bundle.h" |
| +#include "net/base/io_buffer.h" |
| #include "net/base/load_flags.h" |
| #include "net/http/http_response_headers.h" |
| #include "net/url_request/url_request_context.h" |
| @@ -28,6 +31,9 @@ namespace { |
| int kMockRenderProcessId = 1224; |
| int kMockProviderId = 1; |
| +int kMockRenderProcessId2 = 1225; |
| +int kMockProviderId2 = 2; |
| + |
| const char kHeaders[] = |
| "HTTP/1.1 200 OK\0" |
| "Content-Type: text/javascript\0" |
| @@ -38,6 +44,9 @@ const char kScriptCode[] = "// no script code\n"; |
| void EmptyCallback() { |
| } |
| +std::string GenerateLongResponse() { |
| + return std::string(32 * 1024, 'a'); |
| +} |
| net::URLRequestJob* CreateNormalURLRequestJob( |
| net::URLRequest* request, |
| net::NetworkDelegate* network_delegate) { |
| @@ -48,6 +57,14 @@ net::URLRequestJob* CreateNormalURLRequestJob( |
| true); |
| } |
| +net::URLRequestJob* CreateResponseJob(const std::string& response_data, |
| + net::URLRequest* request, |
| + net::NetworkDelegate* network_delegate) { |
| + return new net::URLRequestTestJob(request, network_delegate, |
| + std::string(kHeaders, arraysize(kHeaders)), |
| + response_data, true); |
| +} |
| + |
| net::URLRequestJob* CreateInvalidMimeTypeJob( |
| net::URLRequest* request, |
| net::NetworkDelegate* network_delegate) { |
| @@ -141,7 +158,7 @@ class MockHttpProtocolHandler |
| typedef base::Callback< |
| net::URLRequestJob*(net::URLRequest*, net::NetworkDelegate*)> JobCallback; |
| - MockHttpProtocolHandler(ResourceContext* resource_context) |
| + explicit MockHttpProtocolHandler(ResourceContext* resource_context) |
| : resource_context_(resource_context) {} |
| ~MockHttpProtocolHandler() override {} |
| @@ -164,7 +181,74 @@ class MockHttpProtocolHandler |
| ResourceContext* resource_context_; |
| JobCallback create_job_callback_; |
| }; |
| -} |
| + |
| +const int kBufferSize = 16 * 1024; |
| + |
| +class ResponseVerifier : public base::RefCounted<ResponseVerifier> { |
| + public: |
| + ResponseVerifier(scoped_ptr<ServiceWorkerResponseReader> reader, |
| + const std::string& expected, |
| + const base::Callback<void(bool)> callback) |
| + : reader_(reader.release()), expected_(expected), callback_(callback) {} |
| + |
| + void Start() { |
| + info_buffer_ = new HttpResponseInfoIOBuffer(); |
| + io_buffer_ = new net::IOBuffer(kBufferSize); |
| + reader_->ReadInfo(info_buffer_.get(), |
| + base::Bind(&ResponseVerifier::OnReadInfoComplete, this)); |
| + bytes_read_ = 0; |
| + } |
| + |
| + void OnReadInfoComplete(int result) { |
| + if (result < 0) { |
| + callback_.Run(false); |
| + return; |
| + } |
| + if (info_buffer_->response_data_size != |
| + static_cast<int>(expected_.size())) { |
| + callback_.Run(false); |
| + return; |
| + } |
| + ReadSomeData(); |
| + } |
| + |
| + void ReadSomeData() { |
| + reader_->ReadData(io_buffer_.get(), kBufferSize, |
| + base::Bind(&ResponseVerifier::OnReadDataComplete, this)); |
| + } |
| + |
| + void OnReadDataComplete(int result) { |
| + if (result < 0) { |
| + callback_.Run(false); |
| + return; |
| + } |
| + if (result == 0) { |
| + callback_.Run(true); |
| + return; |
| + } |
| + std::string str(io_buffer_->data(), result); |
| + std::string expect = expected_.substr(bytes_read_, result); |
| + if (str != expect) { |
| + callback_.Run(false); |
| + return; |
| + } |
| + bytes_read_ += result; |
| + ReadSomeData(); |
| + } |
| + |
| + private: |
| + friend class base::RefCounted<ResponseVerifier>; |
| + ~ResponseVerifier() {} |
| + |
| + scoped_ptr<ServiceWorkerResponseReader> reader_; |
| + const std::string expected_; |
| + base::Callback<void(bool)> callback_; |
| + scoped_refptr<HttpResponseInfoIOBuffer> info_buffer_; |
| + scoped_refptr<net::IOBuffer> io_buffer_; |
| + size_t bytes_read_; |
| +}; |
| + |
| +} // namespace |
| class ServiceWorkerWriteToCacheJobTest : public testing::Test { |
| public: |
| @@ -188,7 +272,7 @@ class ServiceWorkerWriteToCacheJobTest : public testing::Test { |
| // An empty host. |
| scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost( |
| kMockRenderProcessId, MSG_ROUTING_NONE, kMockProviderId, |
| - SERVICE_WORKER_PROVIDER_FOR_WINDOW, context()->AsWeakPtr(), nullptr)); |
| + SERVICE_WORKER_PROVIDER_FOR_WORKER, context()->AsWeakPtr(), nullptr)); |
|
nhiroki
2015/06/03 05:36:14
Why did you change the provider type?
falken
2015/06/03 09:07:41
I think the original was wrong. This provider host
|
| provider_host_ = host->AsWeakPtr(); |
| context()->AddProviderHost(host.Pass()); |
| provider_host_->running_hosted_version_ = version_; |
| @@ -232,6 +316,71 @@ class ServiceWorkerWriteToCacheJobTest : public testing::Test { |
| base::RunLoop().RunUntilIdle(); |
| } |
| + int CreateIncumbent(const std::string& response) { |
| + mock_protocol_handler_->SetCreateJobCallback( |
| + base::Bind(&CreateResponseJob, response)); |
| + request_->Start(); |
| + base::RunLoop().RunUntilIdle(); |
| + EXPECT_EQ(net::URLRequestStatus::SUCCESS, request_->status().status()); |
| + int incumbent_resource_id = |
| + version_->script_cache_map()->LookupResourceId(script_url_); |
| + EXPECT_NE(kInvalidServiceWorkerResponseId, incumbent_resource_id); |
| + |
| + registration_->SetActiveVersion(version_); |
| + |
| + // Teardown the request. |
| + request_.reset(); |
| + url_request_context_.reset(); |
| + url_request_job_factory_.reset(); |
| + mock_protocol_handler_ = nullptr; |
| + base::RunLoop().RunUntilIdle(); |
| + |
| + return incumbent_resource_id; |
| + } |
| + |
| + int UpdateScript(const std::string& response) { |
| + scoped_refptr<ServiceWorkerVersion> new_version = new ServiceWorkerVersion( |
| + registration_.get(), script_url_, 2L, context()->AsWeakPtr()); |
| + scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost( |
| + kMockRenderProcessId2, MSG_ROUTING_NONE, kMockProviderId2, |
| + SERVICE_WORKER_PROVIDER_FOR_WORKER, context()->AsWeakPtr(), nullptr)); |
| + provider_host_ = host->AsWeakPtr(); |
| + context()->AddProviderHost(host.Pass()); |
| + provider_host_->running_hosted_version_ = new_version; |
| + |
| + url_request_context_.reset(new net::URLRequestContext); |
| + mock_protocol_handler_ = new MockHttpProtocolHandler(&resource_context_); |
| + url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl); |
| + url_request_job_factory_->SetProtocolHandler("https", |
| + mock_protocol_handler_); |
| + url_request_context_->set_job_factory(url_request_job_factory_.get()); |
| + |
| + request_ = url_request_context_->CreateRequest( |
| + script_url_, net::DEFAULT_PRIORITY, &url_request_delegate_); |
| + ServiceWorkerRequestHandler::InitializeHandler( |
| + request_.get(), context_wrapper(), &blob_storage_context_, |
| + kMockRenderProcessId2, kMockProviderId2, false, |
| + FETCH_REQUEST_MODE_NO_CORS, FETCH_CREDENTIALS_MODE_OMIT, |
| + RESOURCE_TYPE_SERVICE_WORKER, REQUEST_CONTEXT_TYPE_SERVICE_WORKER, |
| + REQUEST_CONTEXT_FRAME_TYPE_NONE, scoped_refptr<ResourceRequestBody>()); |
| + mock_protocol_handler_->SetCreateJobCallback( |
| + base::Bind(&CreateResponseJob, response)); |
| + request_->Start(); |
| + base::RunLoop().RunUntilIdle(); |
| + return new_version->script_cache_map()->LookupResourceId(script_url_); |
| + } |
| + |
| + void VerifyResource(int id, const std::string& expected) { |
| + bool is_equal = false; |
| + scoped_ptr<ServiceWorkerResponseReader> reader = |
| + context()->storage()->CreateResponseReader(id); |
| + scoped_refptr<ResponseVerifier> verifier = new ResponseVerifier( |
| + reader.Pass(), expected, CreateReceiverOnCurrentThread(&is_equal)); |
| + verifier->Start(); |
| + base::RunLoop().RunUntilIdle(); |
| + EXPECT_TRUE(is_equal); |
| + } |
| + |
| ServiceWorkerContextCore* context() const { return helper_->context(); } |
| ServiceWorkerContextWrapper* context_wrapper() const { |
| return helper_->context_wrapper(); |
| @@ -299,4 +448,46 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, CertStatusError) { |
| version_->script_cache_map()->LookupResourceId(script_url_)); |
| } |
| +TEST_F(ServiceWorkerWriteToCacheJobTest, Update_SameScript) { |
| + std::string response = GenerateLongResponse(); |
| + CreateIncumbent(response); |
| + int new_resource_id = UpdateScript(response); |
| + EXPECT_EQ(kInvalidServiceWorkerResponseId, new_resource_id); |
| +} |
| + |
| +TEST_F(ServiceWorkerWriteToCacheJobTest, Update_SameSizeScript) { |
| + std::string response = GenerateLongResponse(); |
| + CreateIncumbent(response); |
| + response[7 * 1024 + 42] = 'x'; |
| + int new_resource_id = UpdateScript(response); |
| + ASSERT_NE(kInvalidServiceWorkerResponseId, new_resource_id); |
| + VerifyResource(new_resource_id, response); |
| +} |
| + |
| +TEST_F(ServiceWorkerWriteToCacheJobTest, Update_TruncatedScript) { |
| + std::string response = GenerateLongResponse(); |
| + CreateIncumbent(response); |
| + response.resize(response.size() - 1); |
| + int new_resource_id = UpdateScript(response); |
| + ASSERT_NE(kInvalidServiceWorkerResponseId, new_resource_id); |
| + VerifyResource(new_resource_id, response); |
| +} |
| + |
| +TEST_F(ServiceWorkerWriteToCacheJobTest, Update_ElongatedScript) { |
| + std::string response = GenerateLongResponse(); |
| + CreateIncumbent(response); |
| + response += 'a'; |
| + int new_resource_id = UpdateScript(response); |
| + ASSERT_NE(kInvalidServiceWorkerResponseId, new_resource_id); |
| + VerifyResource(new_resource_id, response); |
| +} |
| + |
| +TEST_F(ServiceWorkerWriteToCacheJobTest, Update_EmptyScript) { |
| + std::string response = GenerateLongResponse(); |
| + CreateIncumbent(response); |
| + int new_resource_id = UpdateScript(std::string()); |
| + ASSERT_NE(kInvalidServiceWorkerResponseId, new_resource_id); |
| + VerifyResource(new_resource_id, std::string()); |
| +} |
| + |
| } // namespace content |