Index: content/browser/indexed_db/indexed_db_active_blob_registry_unittest.cc |
diff --git a/content/browser/indexed_db/indexed_db_active_blob_registry_unittest.cc b/content/browser/indexed_db/indexed_db_active_blob_registry_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e3d741e9221c9b7168571c45a4407db1decc0e76 |
--- /dev/null |
+++ b/content/browser/indexed_db/indexed_db_active_blob_registry_unittest.cc |
@@ -0,0 +1,270 @@ |
+// Copyright (c) 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 <set> |
+ |
+#include "base/test/test_simple_task_runner.h" |
+#include "content/browser/indexed_db/indexed_db_active_blob_registry.h" |
+#include "content/browser/indexed_db/indexed_db_backing_store.h" |
+#include "content/browser/indexed_db/indexed_db_factory.h" |
+#include "content/browser/indexed_db/indexed_db_fake_backing_store.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace content { |
+ |
+namespace { |
+ |
+class MockIDBFactory : public IndexedDBFactory { |
+ public: |
+ MockIDBFactory() : IndexedDBFactory(NULL), duplicate_calls_(false) {} |
+ |
+ virtual void ReportOutstandingBlobs(const GURL& origin_url, |
+ bool blobs_outstanding) OVERRIDE { |
+ if (blobs_outstanding) { |
+ if (origins_.count(origin_url)) { |
+ duplicate_calls_ = true; |
+ } else { |
+ origins_.insert(origin_url); |
+ } |
+ } else { |
+ if (!origins_.count(origin_url)) { |
+ duplicate_calls_ = true; |
+ } else { |
+ origins_.erase(origin_url); |
+ } |
+ } |
+ } |
+ |
+ bool CheckNoOriginsInUse() const { |
+ return !duplicate_calls_ && !origins_.size(); |
+ } |
+ bool CheckSingleOriginInUse(const GURL& origin) const { |
+ return !duplicate_calls_ && origins_.size() == 1 && origins_.count(origin); |
+ } |
+ |
+ protected: |
+ virtual ~MockIDBFactory() {} |
+ |
+ private: |
+ std::set<GURL> origins_; |
+ bool duplicate_calls_; |
+}; |
+ |
+class MockIDBBackingStore : public IndexedDBFakeBackingStore { |
+ public: |
+ MockIDBBackingStore(IndexedDBFactory* factory, base::TaskRunner* task_runner) |
+ : IndexedDBFakeBackingStore(factory, task_runner), |
+ duplicate_calls_(false) {} |
+ |
+ virtual void ReportBlobUnused(int64 database_id, int64 blob_key) OVERRIDE { |
+ unused_blobs_.insert(std::make_pair(database_id, blob_key)); |
+ } |
+ |
+ typedef std::pair<int64, int64> KeyPair; |
+ typedef std::set<KeyPair> KeyPairSet; |
+ bool CheckUnusedBlobsEmpty() const { |
+ return !duplicate_calls_ && !unused_blobs_.size(); |
+ } |
+ bool CheckSingleUnusedBlob(int64 database_id, int64 blob_key) const { |
+ return !duplicate_calls_ && unused_blobs_.size() == 1 && |
+ unused_blobs_.count(std::make_pair(database_id, blob_key)); |
+ } |
+ |
+ const KeyPairSet& unused_blobs() const { return unused_blobs_; } |
+ |
+ protected: |
+ virtual ~MockIDBBackingStore() {} |
+ |
+ private: |
+ KeyPairSet unused_blobs_; |
+ bool duplicate_calls_; |
+}; |
+ |
+// Base class for our test fixtures. |
+class IndexedDBActiveBlobRegistryTest : public testing::Test { |
+ public: |
+ IndexedDBActiveBlobRegistryTest() |
+ : task_runner_(new base::TestSimpleTaskRunner), |
+ factory_(new MockIDBFactory), |
+ backing_store_(new MockIDBBackingStore(factory_, task_runner_)), |
+ registry_(new IndexedDBActiveBlobRegistry(backing_store_.get())) {} |
+ |
+ void RunUntilIdle() { task_runner_->RunUntilIdle(); } |
+ MockIDBFactory* factory() const { return factory_.get(); } |
+ MockIDBBackingStore* backing_store() const { return backing_store_.get(); } |
+ IndexedDBActiveBlobRegistry* registry() const { return registry_.get(); } |
+ |
+ static const int64 kDatabaseId0 = 7; |
+ static const int64 kDatabaseId1 = 12; |
+ static const int64 kBlobKey0 = 77; |
+ static const int64 kBlobKey1 = 14; |
+ |
+ typedef webkit_blob::ShareableFileReference::FinalReleaseCallback |
+ ReleaseCallback; |
+ |
+ private: |
+ scoped_refptr<base::TestSimpleTaskRunner> task_runner_; |
+ scoped_refptr<MockIDBFactory> factory_; |
+ scoped_refptr<MockIDBBackingStore> backing_store_; |
+ scoped_ptr<IndexedDBActiveBlobRegistry> registry_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(IndexedDBActiveBlobRegistryTest); |
+}; |
+ |
+TEST_F(IndexedDBActiveBlobRegistryTest, DeleteUnused) { |
+ EXPECT_TRUE(factory()->CheckNoOriginsInUse()); |
+ EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty()); |
+ |
+ EXPECT_FALSE(registry()->MarkDeletedCheckIfUsed(kDatabaseId0, kBlobKey0)); |
+ RunUntilIdle(); |
+ |
+ EXPECT_TRUE(factory()->CheckNoOriginsInUse()); |
+ EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty()); |
+} |
+ |
+TEST_F(IndexedDBActiveBlobRegistryTest, SimpleUse) { |
+ EXPECT_TRUE(factory()->CheckNoOriginsInUse()); |
+ EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty()); |
+ |
+ base::Closure add_ref = |
+ registry()->GetAddBlobRefCallback(kDatabaseId0, kBlobKey0); |
+ ReleaseCallback release = |
+ registry()->GetFinalReleaseCallback(kDatabaseId0, kBlobKey0); |
+ add_ref.Run(); |
+ RunUntilIdle(); |
+ |
+ EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url())); |
+ EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty()); |
+ |
+ release.Run(base::FilePath()); |
+ RunUntilIdle(); |
+ |
+ EXPECT_TRUE(factory()->CheckNoOriginsInUse()); |
+ EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty()); |
+} |
+ |
+TEST_F(IndexedDBActiveBlobRegistryTest, DeleteWhileInUse) { |
+ EXPECT_TRUE(factory()->CheckNoOriginsInUse()); |
+ EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty()); |
+ |
+ base::Closure add_ref = |
+ registry()->GetAddBlobRefCallback(kDatabaseId0, kBlobKey0); |
+ ReleaseCallback release = |
+ registry()->GetFinalReleaseCallback(kDatabaseId0, kBlobKey0); |
+ |
+ add_ref.Run(); |
+ RunUntilIdle(); |
+ |
+ EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url())); |
+ EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty()); |
+ |
+ EXPECT_TRUE(registry()->MarkDeletedCheckIfUsed(kDatabaseId0, kBlobKey0)); |
+ RunUntilIdle(); |
+ |
+ EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url())); |
+ EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty()); |
+ |
+ release.Run(base::FilePath()); |
+ RunUntilIdle(); |
+ |
+ EXPECT_TRUE(factory()->CheckNoOriginsInUse()); |
+ EXPECT_TRUE(backing_store()->CheckSingleUnusedBlob(kDatabaseId0, kBlobKey0)); |
+} |
+ |
+TEST_F(IndexedDBActiveBlobRegistryTest, MultipleBlobs) { |
+ EXPECT_TRUE(factory()->CheckNoOriginsInUse()); |
+ EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty()); |
+ |
+ base::Closure add_ref_00 = |
+ registry()->GetAddBlobRefCallback(kDatabaseId0, kBlobKey0); |
+ ReleaseCallback release_00 = |
+ registry()->GetFinalReleaseCallback(kDatabaseId0, kBlobKey0); |
+ base::Closure add_ref_01 = |
+ registry()->GetAddBlobRefCallback(kDatabaseId0, kBlobKey1); |
+ ReleaseCallback release_01 = |
+ registry()->GetFinalReleaseCallback(kDatabaseId0, kBlobKey1); |
+ base::Closure add_ref_10 = |
+ registry()->GetAddBlobRefCallback(kDatabaseId1, kBlobKey0); |
+ ReleaseCallback release_10 = |
+ registry()->GetFinalReleaseCallback(kDatabaseId1, kBlobKey0); |
+ base::Closure add_ref_11 = |
+ registry()->GetAddBlobRefCallback(kDatabaseId1, kBlobKey1); |
+ ReleaseCallback release_11 = |
+ registry()->GetFinalReleaseCallback(kDatabaseId1, kBlobKey1); |
+ |
+ add_ref_00.Run(); |
+ add_ref_01.Run(); |
+ RunUntilIdle(); |
+ |
+ EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url())); |
+ EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty()); |
+ |
+ release_00.Run(base::FilePath()); |
+ add_ref_10.Run(); |
+ add_ref_11.Run(); |
+ RunUntilIdle(); |
+ |
+ EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url())); |
+ EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty()); |
+ |
+ EXPECT_TRUE(registry()->MarkDeletedCheckIfUsed(kDatabaseId0, kBlobKey1)); |
+ RunUntilIdle(); |
+ |
+ EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url())); |
+ EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty()); |
+ |
+ release_01.Run(base::FilePath()); |
+ release_11.Run(base::FilePath()); |
+ RunUntilIdle(); |
+ |
+ EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url())); |
+ EXPECT_TRUE(backing_store()->CheckSingleUnusedBlob(kDatabaseId0, kBlobKey1)); |
+ |
+ release_10.Run(base::FilePath()); |
+ RunUntilIdle(); |
+ |
+ EXPECT_TRUE(factory()->CheckNoOriginsInUse()); |
+ EXPECT_TRUE(backing_store()->CheckSingleUnusedBlob(kDatabaseId0, kBlobKey1)); |
+} |
+ |
+TEST_F(IndexedDBActiveBlobRegistryTest, ForceShutdown) { |
+ EXPECT_TRUE(factory()->CheckNoOriginsInUse()); |
+ EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty()); |
+ |
+ base::Closure add_ref_0 = |
+ registry()->GetAddBlobRefCallback(kDatabaseId0, kBlobKey0); |
+ ReleaseCallback release_0 = |
+ registry()->GetFinalReleaseCallback(kDatabaseId0, kBlobKey0); |
+ base::Closure add_ref_1 = |
+ registry()->GetAddBlobRefCallback(kDatabaseId0, kBlobKey1); |
+ ReleaseCallback release_1 = |
+ registry()->GetFinalReleaseCallback(kDatabaseId0, kBlobKey1); |
+ |
+ add_ref_0.Run(); |
+ RunUntilIdle(); |
+ |
+ EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url())); |
+ EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty()); |
+ |
+ registry()->ForceShutdown(); |
+ |
+ add_ref_1.Run(); |
+ RunUntilIdle(); |
+ |
+ // Nothing changes. |
+ EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url())); |
+ EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty()); |
+ |
+ release_0.Run(base::FilePath()); |
+ release_1.Run(base::FilePath()); |
+ RunUntilIdle(); |
+ |
+ // Nothing changes. |
+ EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url())); |
+ EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty()); |
+} |
+ |
+} // namespace |
+ |
+} // namespace content |