// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stddef.h>
#include <stdint.h>

#include <utility>

#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#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/common/service_worker/service_worker_utils.h"
#include "content/public/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/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "net/test/url_request/url_request_failed_job.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job_factory_impl.h"
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace content {

namespace {

const char kHeaders[] =
    "HTTP/1.1 200 OK\n"
    "Content-Type: text/javascript\n"
    "Expires: Thu, 1 Jan 2100 20:00:00 GMT\n"
    "\n";
const char kScriptCode[] = "// no script code\n";

void EmptyCallback() {
}

// The blocksize that ServiceWorkerWriteToCacheJob reads/writes at a time.
const int kBlockSize = 16 * 1024;
const int kNumBlocks = 8;
const int kMiddleBlock = 5;

std::string GenerateLongResponse() {
  return std::string(kNumBlocks * kBlockSize, 'a');
}

net::URLRequestJob* CreateNormalURLRequestJob(
    net::URLRequest* request,
    net::NetworkDelegate* network_delegate) {
  return new net::URLRequestTestJob(request,
                                    network_delegate,
                                    std::string(kHeaders, arraysize(kHeaders)),
                                    kScriptCode,
                                    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* CreateFailedURLRequestJob(
    net::URLRequest* request,
    net::NetworkDelegate* network_delegate) {
  return new net::URLRequestFailedJob(request, network_delegate,
                                      net::URLRequestFailedJob::START,
                                      net::ERR_FAILED);
}

net::URLRequestJob* CreateInvalidMimeTypeJob(
    net::URLRequest* request,
    net::NetworkDelegate* network_delegate) {
  const char kPlainTextHeaders[] =
      "HTTP/1.1 200 OK\n"
      "Content-Type: text/plain\n"
      "Expires: Thu, 1 Jan 2100 20:00:00 GMT\n"
      "\n";
  return new net::URLRequestTestJob(
      request,
      network_delegate,
      std::string(kPlainTextHeaders, arraysize(kPlainTextHeaders)),
      kScriptCode,
      true);
}

class SSLCertificateErrorJob : public net::URLRequestTestJob {
 public:
  SSLCertificateErrorJob(net::URLRequest* request,
                         net::NetworkDelegate* network_delegate,
                         const std::string& response_headers,
                         const std::string& response_data,
                         bool auto_advance)
      : net::URLRequestTestJob(request,
                               network_delegate,
                               response_headers,
                               response_data,
                               auto_advance),
        weak_factory_(this) {}
  void Start() override {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::Bind(&SSLCertificateErrorJob::NotifyError,
                              weak_factory_.GetWeakPtr()));
  }
  void NotifyError() {
    net::SSLInfo info;
    info.cert_status = net::CERT_STATUS_DATE_INVALID;
    NotifySSLCertificateError(info, true);
  }
  void ContinueDespiteLastError() override {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::Bind(&SSLCertificateErrorJob::StartAsync,
                              weak_factory_.GetWeakPtr()));
  }

 protected:
  ~SSLCertificateErrorJob() override {}
  base::WeakPtrFactory<SSLCertificateErrorJob> weak_factory_;
};

net::URLRequestJob* CreateSSLCertificateErrorJob(
    net::URLRequest* request,
    net::NetworkDelegate* network_delegate) {
  return new SSLCertificateErrorJob(request,
                                    network_delegate,
                                    std::string(kHeaders, arraysize(kHeaders)),
                                    kScriptCode,
                                    true);
}

class CertStatusErrorJob : public net::URLRequestTestJob {
 public:
  CertStatusErrorJob(net::URLRequest* request,
                     net::NetworkDelegate* network_delegate,
                     const std::string& response_headers,
                     const std::string& response_data,
                     bool auto_advance)
      : net::URLRequestTestJob(request,
                               network_delegate,
                               response_headers,
                               response_data,
                               auto_advance) {}
  void GetResponseInfo(net::HttpResponseInfo* info) override {
    URLRequestTestJob::GetResponseInfo(info);
    info->ssl_info.cert_status = net::CERT_STATUS_DATE_INVALID;
  }

 protected:
  ~CertStatusErrorJob() override {}
};

net::URLRequestJob* CreateCertStatusErrorJob(
    net::URLRequest* request,
    net::NetworkDelegate* network_delegate) {
  return new CertStatusErrorJob(request,
                                network_delegate,
                                std::string(kHeaders, arraysize(kHeaders)),
                                kScriptCode,
                                true);
}

class MockHttpProtocolHandler
    : public net::URLRequestJobFactory::ProtocolHandler {
 public:
  typedef base::Callback<
      net::URLRequestJob*(net::URLRequest*, net::NetworkDelegate*)> JobCallback;

  explicit MockHttpProtocolHandler(ResourceContext* resource_context)
      : resource_context_(resource_context) {}
  ~MockHttpProtocolHandler() override {}

  net::URLRequestJob* MaybeCreateJob(
      net::URLRequest* request,
      net::NetworkDelegate* network_delegate) const override {
    ServiceWorkerRequestHandler* handler =
        ServiceWorkerRequestHandler::GetHandler(request);
    if (handler) {
      return handler->MaybeCreateJob(
          request, network_delegate, resource_context_);
    }
    return create_job_callback_.Run(request, network_delegate);
  }
  void SetCreateJobCallback(const JobCallback& callback) {
    create_job_callback_ = callback;
  }

 private:
  ResourceContext* resource_context_;
  JobCallback create_job_callback_;
};

class ResponseVerifier : public base::RefCounted<ResponseVerifier> {
 public:
  ResponseVerifier(std::unique_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(kBlockSize);
    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(), kBlockSize,
                      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() {}

  std::unique_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:
  ServiceWorkerWriteToCacheJobTest()
      : ServiceWorkerWriteToCacheJobTest("https://host/scope/",
                                         "https://host/script.js") {}
  ServiceWorkerWriteToCacheJobTest(const std::string& scope,
                                   const std::string& script_url)
      : scope_(scope),
        script_url_(script_url),
        browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
        mock_protocol_handler_(nullptr) {}
  ~ServiceWorkerWriteToCacheJobTest() override {}

  base::WeakPtr<ServiceWorkerProviderHost> CreateHostForVersion(
      int process_id,
      int provider_id,
      const scoped_refptr<ServiceWorkerVersion>& version) {
    std::unique_ptr<ServiceWorkerProviderHost> host =
        CreateProviderHostForServiceWorkerContext(
            process_id, provider_id, true /* is_parent_frame_secure */,
            context()->AsWeakPtr(), &remote_endpoint_);
    base::WeakPtr<ServiceWorkerProviderHost> provider_host = host->AsWeakPtr();
    context()->AddProviderHost(std::move(host));
    provider_host->running_hosted_version_ = version;
    return provider_host;
  }

  void SetUpScriptRequest(int process_id, int provider_id) {
    request_.reset();
    url_request_context_.reset();
    url_request_job_factory_.reset();
    mock_protocol_handler_ = nullptr;
    // URLRequestJobs may post clean-up tasks on destruction.
    base::RunLoop().RunUntilIdle();

    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", base::WrapUnique(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_,
        TRAFFIC_ANNOTATION_FOR_TESTS);
    ServiceWorkerRequestHandler::InitializeHandler(
        request_.get(), context_wrapper(), &blob_storage_context_, process_id,
        provider_id, false, FETCH_REQUEST_MODE_NO_CORS,
        FETCH_CREDENTIALS_MODE_OMIT, FetchRedirectMode::FOLLOW_MODE,
        RESOURCE_TYPE_SERVICE_WORKER, REQUEST_CONTEXT_TYPE_SERVICE_WORKER,
        REQUEST_CONTEXT_FRAME_TYPE_NONE, scoped_refptr<ResourceRequestBody>());
  }

  int NextProviderId() { return next_provider_id_++; }
  int NextVersionId() { return next_version_id_++; }

  void SetUp() override {
    int provider_id = NextProviderId();
    helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));

    // A new unstored registration/version.
    registration_ = new ServiceWorkerRegistration(
        ServiceWorkerRegistrationOptions(scope_), 1L, context()->AsWeakPtr());
    version_ =
        new ServiceWorkerVersion(registration_.get(), script_url_,
                                 NextVersionId(), context()->AsWeakPtr());
    base::WeakPtr<ServiceWorkerProviderHost> host = CreateHostForVersion(
        helper_->mock_render_process_id(), provider_id, version_);
    ASSERT_TRUE(host);
    SetUpScriptRequest(helper_->mock_render_process_id(), host->provider_id());

    context()->storage()->LazyInitialize(base::Bind(&EmptyCallback));
    base::RunLoop().RunUntilIdle();
  }

  void TearDown() override {
    request_.reset();
    url_request_context_.reset();
    url_request_job_factory_.reset();
    mock_protocol_handler_ = nullptr;
    version_ = nullptr;
    registration_ = nullptr;
    helper_.reset();
    // URLRequestJobs may post clean-up tasks on destruction.
    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(kInvalidServiceWorkerResourceId, 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 GetResourceId(ServiceWorkerVersion* version) {
    return version->script_cache_map()->LookupResourceId(script_url_);
  }

  // Performs the net request for an update of |registration_|'s incumbent
  // to the script |response|. Returns the new version.
  scoped_refptr<ServiceWorkerVersion> UpdateScript(
      const std::string& response) {
    int provider_id = NextProviderId();
    scoped_refptr<ServiceWorkerVersion> new_version =
        new ServiceWorkerVersion(registration_.get(), script_url_,
                                 NextVersionId(), context()->AsWeakPtr());
    new_version->set_pause_after_download(true);
    base::WeakPtr<ServiceWorkerProviderHost> host = CreateHostForVersion(
        helper_->mock_render_process_id(), provider_id, new_version);

    SetUpScriptRequest(helper_->mock_render_process_id(), host->provider_id());
    mock_protocol_handler_->SetCreateJobCallback(
        base::Bind(&CreateResponseJob, response));
    request_->Start();
    base::RunLoop().RunUntilIdle();
    return new_version;
  }

  void VerifyResource(int id, const std::string& expected) {
    ASSERT_NE(kInvalidServiceWorkerResourceId, id);
    bool is_equal = false;
    std::unique_ptr<ServiceWorkerResponseReader> reader =
        context()->storage()->CreateResponseReader(id);
    scoped_refptr<ResponseVerifier> verifier = new ResponseVerifier(
        std::move(reader), 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();
  }

  // Disables the cache to simulate cache errors.
  void DisableCache() { context()->storage()->disk_cache()->Disable(); }

 protected:
  const GURL scope_;
  const GURL script_url_;

  TestBrowserThreadBundle browser_thread_bundle_;
  std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
  scoped_refptr<ServiceWorkerRegistration> registration_;
  scoped_refptr<ServiceWorkerVersion> version_;
  base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
  std::unique_ptr<net::URLRequestContext> url_request_context_;
  std::unique_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
  std::unique_ptr<net::URLRequest> request_;
  MockHttpProtocolHandler* mock_protocol_handler_;

  storage::BlobStorageContext blob_storage_context_;
  content::MockResourceContext resource_context_;
  ServiceWorkerRemoteProviderEndpoint remote_endpoint_;

  net::TestDelegate url_request_delegate_;
  int next_provider_id_ = 1;
  int64_t next_version_id_ = 1L;
};

TEST_F(ServiceWorkerWriteToCacheJobTest, Normal) {
  mock_protocol_handler_->SetCreateJobCallback(
      base::Bind(&CreateNormalURLRequestJob));
  request_->Start();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(net::URLRequestStatus::SUCCESS, request_->status().status());
  EXPECT_NE(kInvalidServiceWorkerResourceId,
            version_->script_cache_map()->LookupResourceId(script_url_));
}

TEST_F(ServiceWorkerWriteToCacheJobTest, InvalidMimeType) {
  mock_protocol_handler_->SetCreateJobCallback(
      base::Bind(&CreateInvalidMimeTypeJob));
  request_->Start();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(net::URLRequestStatus::FAILED, request_->status().status());
  EXPECT_EQ(net::ERR_INSECURE_RESPONSE, request_->status().error());
  EXPECT_EQ(kInvalidServiceWorkerResourceId,
            version_->script_cache_map()->LookupResourceId(script_url_));
}

TEST_F(ServiceWorkerWriteToCacheJobTest, SSLCertificateError) {
  mock_protocol_handler_->SetCreateJobCallback(
      base::Bind(&CreateSSLCertificateErrorJob));
  request_->Start();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(net::URLRequestStatus::FAILED, request_->status().status());
  EXPECT_EQ(net::ERR_INSECURE_RESPONSE, request_->status().error());
  EXPECT_EQ(kInvalidServiceWorkerResourceId,
            version_->script_cache_map()->LookupResourceId(script_url_));
}

class ServiceWorkerWriteToCacheLocalhostTest
    : public ServiceWorkerWriteToCacheJobTest {
 public:
  ServiceWorkerWriteToCacheLocalhostTest()
      : ServiceWorkerWriteToCacheJobTest("https://localhost/scope/",
                                         "https://localhost/script.js") {}
  ~ServiceWorkerWriteToCacheLocalhostTest() override {}
};

TEST_F(ServiceWorkerWriteToCacheLocalhostTest,
       SSLCertificateError_AllowInsecureLocalhost) {
  base::CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kAllowInsecureLocalhost);

  mock_protocol_handler_->SetCreateJobCallback(
      base::Bind(&CreateSSLCertificateErrorJob));
  request_->Start();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(net::URLRequestStatus::SUCCESS, request_->status().status());
  EXPECT_EQ(net::OK, request_->status().error());
  EXPECT_NE(kInvalidServiceWorkerResourceId,
            version_->script_cache_map()->LookupResourceId(script_url_));
}

TEST_F(ServiceWorkerWriteToCacheLocalhostTest, SSLCertificateError) {
  mock_protocol_handler_->SetCreateJobCallback(
      base::Bind(&CreateSSLCertificateErrorJob));
  request_->Start();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(net::URLRequestStatus::FAILED, request_->status().status());
  EXPECT_EQ(net::ERR_INSECURE_RESPONSE, request_->status().error());
  EXPECT_EQ(kInvalidServiceWorkerResourceId,
            version_->script_cache_map()->LookupResourceId(script_url_));
}

TEST_F(ServiceWorkerWriteToCacheLocalhostTest,
       CertStatusError_AllowInsecureLocalhost) {
  base::CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kAllowInsecureLocalhost);

  mock_protocol_handler_->SetCreateJobCallback(
      base::Bind(&CreateCertStatusErrorJob));
  request_->Start();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(net::URLRequestStatus::SUCCESS, request_->status().status());
  EXPECT_EQ(net::OK, request_->status().error());
  EXPECT_NE(kInvalidServiceWorkerResourceId,
            version_->script_cache_map()->LookupResourceId(script_url_));
}

TEST_F(ServiceWorkerWriteToCacheLocalhostTest, CertStatusError) {
  mock_protocol_handler_->SetCreateJobCallback(
      base::Bind(&CreateCertStatusErrorJob));
  request_->Start();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(net::URLRequestStatus::FAILED, request_->status().status());
  EXPECT_EQ(net::ERR_INSECURE_RESPONSE, request_->status().error());
  EXPECT_EQ(kInvalidServiceWorkerResourceId,
            version_->script_cache_map()->LookupResourceId(script_url_));
}

TEST_F(ServiceWorkerWriteToCacheJobTest, CertStatusError) {
  mock_protocol_handler_->SetCreateJobCallback(
      base::Bind(&CreateCertStatusErrorJob));
  request_->Start();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(net::URLRequestStatus::FAILED, request_->status().status());
  EXPECT_EQ(net::ERR_INSECURE_RESPONSE, request_->status().error());
  EXPECT_EQ(kInvalidServiceWorkerResourceId,
            version_->script_cache_map()->LookupResourceId(script_url_));
}

TEST_F(ServiceWorkerWriteToCacheJobTest, Update_SameScript) {
  std::string response = GenerateLongResponse();
  CreateIncumbent(response);
  scoped_refptr<ServiceWorkerVersion> version = UpdateScript(response);
  EXPECT_EQ(kInvalidServiceWorkerResourceId, GetResourceId(version.get()));
}

TEST_F(ServiceWorkerWriteToCacheJobTest, Update_SameSizeScript) {
  std::string response = GenerateLongResponse();
  CreateIncumbent(response);

  // Change the first byte.
  response[0] = 'x';
  scoped_refptr<ServiceWorkerVersion> version = UpdateScript(response);
  VerifyResource(GetResourceId(version.get()), response);
  registration_->SetWaitingVersion(version);

  // Change something within the first block.
  response[5555] = 'x';
  version = UpdateScript(response);
  VerifyResource(GetResourceId(version.get()), response);
  registration_->SetWaitingVersion(version);

  // Change something in a middle block.
  response[kMiddleBlock * kBlockSize + 111] = 'x';
  version = UpdateScript(response);
  VerifyResource(GetResourceId(version.get()), response);
  registration_->SetWaitingVersion(version);

  // Change something within the last block.
  response[(kNumBlocks - 1) * kBlockSize] = 'x';
  version = UpdateScript(response);
  VerifyResource(GetResourceId(version.get()), response);
  registration_->SetWaitingVersion(version);

  // Change the last byte.
  response[(kNumBlocks * kBlockSize) - 1] = 'x';
  version = UpdateScript(response);
  VerifyResource(GetResourceId(version.get()), response);
  registration_->SetWaitingVersion(version);
}

TEST_F(ServiceWorkerWriteToCacheJobTest, Update_TruncatedScript) {
  std::string response = GenerateLongResponse();
  CreateIncumbent(response);

  // Truncate a single byte.
  response.resize(response.size() - 1);
  scoped_refptr<ServiceWorkerVersion> version = UpdateScript(response);
  VerifyResource(GetResourceId(version.get()), response);
  registration_->SetWaitingVersion(version);

  // Truncate to a middle block.
  response.resize((kMiddleBlock + 1) * kBlockSize + 111);
  version = UpdateScript(response);
  VerifyResource(GetResourceId(version.get()), response);
  registration_->SetWaitingVersion(version);

  // Truncate to a block boundary.
  response.resize((kMiddleBlock - 1) * kBlockSize);
  version = UpdateScript(response);
  VerifyResource(GetResourceId(version.get()), response);
  registration_->SetWaitingVersion(version);

  // Truncate to a single byte.
  response.resize(1);
  version = UpdateScript(response);
  VerifyResource(GetResourceId(version.get()), response);
  registration_->SetWaitingVersion(version);
}

TEST_F(ServiceWorkerWriteToCacheJobTest, Update_ElongatedScript) {
  std::string original_response = GenerateLongResponse();
  CreateIncumbent(original_response);

  // Extend a single byte.
  std::string new_response = original_response + 'a';
  scoped_refptr<ServiceWorkerVersion> version = UpdateScript(new_response);
  VerifyResource(GetResourceId(version.get()), new_response);
  registration_->SetWaitingVersion(version);

  // Extend multiple blocks.
  new_response = original_response + std::string(3 * kBlockSize, 'a');
  version = UpdateScript(new_response);
  VerifyResource(GetResourceId(version.get()), new_response);
  registration_->SetWaitingVersion(version);

  // Extend multiple blocks and bytes.
  new_response = original_response + std::string(7 * kBlockSize + 777, 'a');
  version = UpdateScript(new_response);
  VerifyResource(GetResourceId(version.get()), new_response);
  registration_->SetWaitingVersion(version);
}

TEST_F(ServiceWorkerWriteToCacheJobTest, Update_EmptyScript) {
  // Create empty incumbent.
  CreateIncumbent(std::string());

  // Update from empty to non-empty.
  std::string response = GenerateLongResponse();
  scoped_refptr<ServiceWorkerVersion> version = UpdateScript(response);
  VerifyResource(GetResourceId(version.get()), response);
  registration_->SetWaitingVersion(version);

  // Update from non-empty to empty.
  version = UpdateScript(std::string());
  VerifyResource(GetResourceId(version.get()), std::string());
  registration_->SetWaitingVersion(version);

  // Update from empty to empty.
  version = UpdateScript(std::string());
  EXPECT_EQ(kInvalidServiceWorkerResourceId, GetResourceId(version.get()));
}

TEST_F(ServiceWorkerWriteToCacheJobTest, Error) {
  mock_protocol_handler_->SetCreateJobCallback(
      base::Bind(&CreateFailedURLRequestJob));
  request_->Start();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(net::URLRequestStatus::FAILED, request_->status().status());
  EXPECT_EQ(net::ERR_FAILED, request_->status().error());
  EXPECT_EQ(kInvalidServiceWorkerResourceId,
            version_->script_cache_map()->LookupResourceId(script_url_));
}

TEST_F(ServiceWorkerWriteToCacheJobTest, FailedWriteHeadersToCache) {
  mock_protocol_handler_->SetCreateJobCallback(
      base::Bind(&CreateNormalURLRequestJob));
  DisableCache();
  request_->Start();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(net::URLRequestStatus::FAILED, request_->status().status());
  EXPECT_EQ(net::ERR_FAILED, request_->status().error());
}

}  // namespace content
