| Index: content/browser/service_worker/service_worker_cache_unittest.cc
|
| diff --git a/content/browser/service_worker/service_worker_cache_unittest.cc b/content/browser/service_worker/service_worker_cache_unittest.cc
|
| index 0d1c8fad3a5fdbc987da3ade8c243806eae0ce71..3e68aafccc593191084811b9f666272972a3c2a7 100644
|
| --- a/content/browser/service_worker/service_worker_cache_unittest.cc
|
| +++ b/content/browser/service_worker/service_worker_cache_unittest.cc
|
| @@ -40,9 +40,88 @@ storage::BlobProtocolHandler* CreateMockBlobProtocolHandler(
|
| blob_storage_context, NULL, base::MessageLoopProxy::current().get());
|
| }
|
|
|
| +// A disk_cache::Backend wrapper that can delay operations.
|
| +class DelayableBackend : public disk_cache::Backend {
|
| + public:
|
| + DelayableBackend(scoped_ptr<disk_cache::Backend> backend)
|
| + : backend_(backend.Pass()), delay_open_(false) {}
|
| +
|
| + // disk_cache::Backend overrides
|
| + virtual net::CacheType GetCacheType() const override {
|
| + return backend_->GetCacheType();
|
| + }
|
| + virtual int32 GetEntryCount() const override {
|
| + return backend_->GetEntryCount();
|
| + }
|
| + virtual int OpenEntry(const std::string& key,
|
| + disk_cache::Entry** entry,
|
| + const CompletionCallback& callback) override {
|
| + if (delay_open_) {
|
| + open_entry_callback_ =
|
| + base::Bind(&DelayableBackend::OpenEntryDelayedImpl,
|
| + base::Unretained(this), key, entry, callback);
|
| + return net::ERR_IO_PENDING;
|
| + }
|
| +
|
| + return backend_->OpenEntry(key, entry, callback);
|
| + }
|
| + virtual int CreateEntry(const std::string& key,
|
| + disk_cache::Entry** entry,
|
| + const CompletionCallback& callback) override {
|
| + return backend_->CreateEntry(key, entry, callback);
|
| + }
|
| + virtual int DoomEntry(const std::string& key,
|
| + const CompletionCallback& callback) override {
|
| + return backend_->DoomEntry(key, callback);
|
| + }
|
| + virtual int DoomAllEntries(const CompletionCallback& callback) override {
|
| + return backend_->DoomAllEntries(callback);
|
| + }
|
| + virtual int DoomEntriesBetween(base::Time initial_time,
|
| + base::Time end_time,
|
| + const CompletionCallback& callback) override {
|
| + return backend_->DoomEntriesBetween(initial_time, end_time, callback);
|
| + }
|
| + virtual int DoomEntriesSince(base::Time initial_time,
|
| + const CompletionCallback& callback) override {
|
| + return backend_->DoomEntriesSince(initial_time, callback);
|
| + }
|
| + virtual scoped_ptr<Iterator> CreateIterator() override {
|
| + return backend_->CreateIterator();
|
| + }
|
| + virtual void GetStats(
|
| + std::vector<std::pair<std::string, std::string>>* stats) override {
|
| + return backend_->GetStats(stats);
|
| + }
|
| + virtual void OnExternalCacheHit(const std::string& key) override {
|
| + return backend_->OnExternalCacheHit(key);
|
| + }
|
| +
|
| + // Call to continue a delayed open.
|
| + void OpenEntryContinue() {
|
| + EXPECT_FALSE(open_entry_callback_.is_null());
|
| + open_entry_callback_.Run();
|
| + }
|
| +
|
| + void set_delay_open(bool value) { delay_open_ = value; }
|
| +
|
| + private:
|
| + void OpenEntryDelayedImpl(const std::string& key,
|
| + disk_cache::Entry** entry,
|
| + const CompletionCallback& callback) {
|
| + int rv = backend_->OpenEntry(key, entry, callback);
|
| + if (rv != net::ERR_IO_PENDING)
|
| + callback.Run(rv);
|
| + }
|
| +
|
| + scoped_ptr<disk_cache::Backend> backend_;
|
| + bool delay_open_;
|
| + base::Closure open_entry_callback_;
|
| +};
|
| +
|
| } // namespace
|
|
|
| -// A ServiceWorkerCache that can optionally pause during backend creation.
|
| +// A ServiceWorkerCache that can optionally delay during backend creation.
|
| class TestServiceWorkerCache : public ServiceWorkerCache {
|
| public:
|
| TestServiceWorkerCache(
|
| @@ -56,11 +135,11 @@ class TestServiceWorkerCache : public ServiceWorkerCache {
|
| request_context,
|
| quota_manager_proxy,
|
| blob_context),
|
| - pause_backend_creation_(false) {}
|
| + delay_backend_creation_(false) {}
|
|
|
| virtual void CreateBackend(const ErrorCallback& callback) override {
|
| backend_creation_callback_ = callback;
|
| - if (pause_backend_creation_)
|
| + if (delay_backend_creation_)
|
| return;
|
| ContinueCreateBackend();
|
| }
|
| @@ -69,14 +148,23 @@ class TestServiceWorkerCache : public ServiceWorkerCache {
|
| ServiceWorkerCache::CreateBackend(backend_creation_callback_);
|
| }
|
|
|
| - void set_pause_backend_creation(bool pause) {
|
| - pause_backend_creation_ = pause;
|
| + void set_delay_backend_creation(bool delay) {
|
| + delay_backend_creation_ = delay;
|
| + }
|
| +
|
| + // Swap the existing backend with a delayable one. The backend must have been
|
| + // created before calling this.
|
| + DelayableBackend* UseDelayableBackend() {
|
| + EXPECT_TRUE(backend_);
|
| + DelayableBackend* delayable_backend = new DelayableBackend(backend_.Pass());
|
| + backend_.reset(delayable_backend);
|
| + return delayable_backend;
|
| }
|
|
|
| private:
|
| virtual ~TestServiceWorkerCache() override {}
|
|
|
| - bool pause_backend_creation_;
|
| + bool delay_backend_creation_;
|
| ErrorCallback backend_creation_callback_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(TestServiceWorkerCache);
|
| @@ -683,7 +771,7 @@ TEST_F(ServiceWorkerCacheTest, MemoryBackedSizePersistent) {
|
| }
|
|
|
| TEST_P(ServiceWorkerCacheTestP, OpsFailOnClosedBackendNeverCreated) {
|
| - cache_->set_pause_backend_creation(
|
| + cache_->set_delay_backend_creation(
|
| true); // Will hang the test if a backend is created.
|
| EXPECT_TRUE(Close());
|
| VerifyAllOpsFail();
|
| @@ -696,10 +784,10 @@ TEST_P(ServiceWorkerCacheTestP, OpsFailOnClosedBackend) {
|
| VerifyAllOpsFail();
|
| }
|
|
|
| -TEST_F(ServiceWorkerCacheTest, ClosedDuringPut) {
|
| +TEST_P(ServiceWorkerCacheTestP, ClosedDuringPutInitBackend) {
|
| // Even though Close is called in the middle of a Put operation (during
|
| - // backend creation), the put operation should still finish.
|
| - cache_->set_pause_backend_creation(true);
|
| + // backend creation), the put operation should exit early.
|
| + cache_->set_delay_backend_creation(true);
|
| scoped_ptr<base::RunLoop> close_loop(new base::RunLoop());
|
| cache_->Put(CopyFetchRequest(body_request_),
|
| CopyFetchResponse(body_response_),
|
| @@ -708,22 +796,22 @@ TEST_F(ServiceWorkerCacheTest, ClosedDuringPut) {
|
| cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback,
|
| base::Unretained(this), close_loop.get()));
|
| base::RunLoop().RunUntilIdle();
|
| - EXPECT_FALSE(callback_response_);
|
| + EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_);
|
| EXPECT_FALSE(callback_closed_);
|
|
|
| cache_->ContinueCreateBackend();
|
|
|
| close_loop->Run();
|
| - EXPECT_TRUE(callback_response_);
|
| + EXPECT_EQ(ServiceWorkerCache::ErrorTypeStorage, callback_error_);
|
| EXPECT_TRUE(callback_closed_);
|
|
|
| VerifyAllOpsFail();
|
| }
|
|
|
| -TEST_F(ServiceWorkerCacheTest, ClosedDuringMatch) {
|
| +TEST_P(ServiceWorkerCacheTestP, ClosedDuringMatchInitBackend) {
|
| // Even though Close is called in the middle of a Match operation (during
|
| - // backend creation), the match operation should still finish.
|
| - cache_->set_pause_backend_creation(true);
|
| + // backend creation), the match operation should exit early.
|
| + cache_->set_delay_backend_creation(true);
|
| scoped_ptr<base::RunLoop> close_loop(new base::RunLoop());
|
| cache_->Match(CopyFetchRequest(body_request_),
|
| base::Bind(&ServiceWorkerCacheTest::ResponseAndErrorCallback,
|
| @@ -737,16 +825,16 @@ TEST_F(ServiceWorkerCacheTest, ClosedDuringMatch) {
|
| cache_->ContinueCreateBackend();
|
|
|
| close_loop->Run();
|
| - EXPECT_EQ(ServiceWorkerCache::ErrorTypeNotFound, callback_error_);
|
| + EXPECT_EQ(ServiceWorkerCache::ErrorTypeStorage, callback_error_);
|
| EXPECT_TRUE(callback_closed_);
|
|
|
| VerifyAllOpsFail();
|
| }
|
|
|
| -TEST_F(ServiceWorkerCacheTest, ClosedDuringDelete) {
|
| +TEST_P(ServiceWorkerCacheTestP, ClosedDuringDeleteInitBackend) {
|
| // Even though Close is called in the middle of a Delete operation (during
|
| - // backend creation), the delete operation should still finish.
|
| - cache_->set_pause_backend_creation(true);
|
| + // backend creation), the delete operation should exit early.
|
| + cache_->set_delay_backend_creation(true);
|
| scoped_ptr<base::RunLoop> close_loop(new base::RunLoop());
|
| cache_->Delete(CopyFetchRequest(body_request_),
|
| base::Bind(&ServiceWorkerCacheTest::ErrorTypeCallback,
|
| @@ -760,30 +848,59 @@ TEST_F(ServiceWorkerCacheTest, ClosedDuringDelete) {
|
| cache_->ContinueCreateBackend();
|
|
|
| close_loop->Run();
|
| - EXPECT_EQ(ServiceWorkerCache::ErrorTypeNotFound, callback_error_);
|
| + EXPECT_EQ(ServiceWorkerCache::ErrorTypeStorage, callback_error_);
|
| EXPECT_TRUE(callback_closed_);
|
|
|
| VerifyAllOpsFail();
|
| }
|
|
|
| -TEST_F(ServiceWorkerCacheTest, ClosedDuringKeys) {
|
| +TEST_P(ServiceWorkerCacheTestP, ClosedDuringKeysInitBackend) {
|
| // Even though Close is called in the middle of a Keys operation (during
|
| - // backend creation), the keys operation should still finish.
|
| - cache_->set_pause_backend_creation(true);
|
| + // backend creation), the keys operation should exit early.
|
| + cache_->set_delay_backend_creation(true);
|
| scoped_ptr<base::RunLoop> close_loop(new base::RunLoop());
|
| - callback_error_ = ServiceWorkerCache::ErrorTypeNotFound;
|
| cache_->Keys(base::Bind(&ServiceWorkerCacheTest::RequestsCallback,
|
| base::Unretained(this), nullptr));
|
| cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback,
|
| base::Unretained(this), close_loop.get()));
|
| base::RunLoop().RunUntilIdle();
|
| - EXPECT_EQ(ServiceWorkerCache::ErrorTypeNotFound, callback_error_);
|
| + EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_);
|
| EXPECT_FALSE(callback_closed_);
|
|
|
| cache_->ContinueCreateBackend();
|
|
|
| close_loop->Run();
|
| + EXPECT_EQ(ServiceWorkerCache::ErrorTypeStorage, callback_error_);
|
| + EXPECT_TRUE(callback_closed_);
|
| +
|
| + VerifyAllOpsFail();
|
| +}
|
| +
|
| +TEST_P(ServiceWorkerCacheTestP, ClosedDuringPutOpenEntry) {
|
| + EXPECT_TRUE(Keys()); // Opens the backend.
|
| + DelayableBackend* delayable_backend = cache_->UseDelayableBackend();
|
| + delayable_backend->set_delay_open(true);
|
| +
|
| + // Run Put and Close. Put will delay on OpenEntry, Close will wait for Put to
|
| + // finish.
|
| + scoped_ptr<base::RunLoop> close_loop(new base::RunLoop());
|
| + cache_->Put(CopyFetchRequest(body_request_),
|
| + CopyFetchResponse(body_response_),
|
| + base::Bind(&ServiceWorkerCacheTest::ResponseAndErrorCallback,
|
| + base::Unretained(this), nullptr));
|
| + cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback,
|
| + base::Unretained(this), close_loop.get()));
|
| +
|
| + base::RunLoop().RunUntilIdle();
|
| + // Verify that neither operation has finished.
|
| EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_);
|
| + EXPECT_FALSE(callback_closed_);
|
| +
|
| + delayable_backend->OpenEntryContinue();
|
| +
|
| + close_loop->Run();
|
| + // Put failed because the backend was closed while it was running.
|
| + EXPECT_EQ(ServiceWorkerCache::ErrorTypeStorage, callback_error_);
|
| EXPECT_TRUE(callback_closed_);
|
|
|
| VerifyAllOpsFail();
|
|
|