Chromium Code Reviews| Index: content/browser/indexed_db/indexed_db_backing_store_unittest.cc |
| diff --git a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc |
| index 99f1dff55e3482f685b56a6e9fa51fe37ecad20f..d5dc6681ffebc463a35d470546fc49ef43eb0bbb 100644 |
| --- a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc |
| +++ b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc |
| @@ -17,13 +17,13 @@ |
| #include "base/sequenced_task_runner.h" |
| #include "base/strings/string16.h" |
| #include "base/strings/utf_string_conversions.h" |
| -#include "base/test/test_simple_task_runner.h" |
| #include "content/browser/indexed_db/indexed_db_context_impl.h" |
| #include "content/browser/indexed_db/indexed_db_factory_impl.h" |
| #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" |
| #include "content/browser/indexed_db/indexed_db_value.h" |
| #include "content/browser/indexed_db/leveldb/leveldb_factory.h" |
| #include "content/public/test/test_browser_thread_bundle.h" |
| +#include "content/public/test/test_utils.h" |
| #include "net/url_request/url_request_test_util.h" |
| #include "storage/browser/blob/blob_data_handle.h" |
| #include "storage/browser/quota/special_storage_policy.h" |
| @@ -232,27 +232,94 @@ class TestIDBFactory : public IndexedDBFactoryImpl { |
| class IndexedDBBackingStoreTest : public testing::Test { |
| public: |
| - IndexedDBBackingStoreTest() {} |
| + IndexedDBBackingStoreTest() |
| + : url_request_context_getter_( |
| + base::MakeRefCounted<net::TestURLRequestContextGetter>( |
| + BrowserThread::GetTaskRunnerForThread(BrowserThread::UI))), |
| + special_storage_policy_( |
| + base::MakeRefCounted<MockSpecialStoragePolicy>()), |
| + quota_manager_proxy_( |
| + base::MakeRefCounted<MockQuotaManagerProxy>(nullptr, nullptr)) {} |
| + |
| void SetUp() override { |
| - const Origin origin(GURL("http://localhost:81")); |
| - task_runner_ = new base::TestSimpleTaskRunner(); |
| - url_request_context_getter_ = |
| - new net::TestURLRequestContextGetter(task_runner_); |
| - special_storage_policy_ = new MockSpecialStoragePolicy(); |
| - quota_manager_proxy_ = new MockQuotaManagerProxy(nullptr, nullptr); |
| special_storage_policy_->SetAllUnlimited(true); |
| ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| - idb_context_ = new IndexedDBContextImpl( |
| - temp_dir_.GetPath(), special_storage_policy_.get(), |
| - quota_manager_proxy_.get(), task_runner_.get()); |
| - idb_factory_ = new TestIDBFactory(idb_context_.get()); |
| - backing_store_ = idb_factory_->OpenBackingStoreForTest( |
| - origin, url_request_context_getter_); |
| + idb_context_ = base::MakeRefCounted<IndexedDBContextImpl>( |
| + temp_dir_.GetPath(), special_storage_policy_, quota_manager_proxy_); |
| + |
| + // Factory and backing store must be created on IDB task runner. |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, base::BindOnce( |
| + [](IndexedDBBackingStoreTest* test) { |
| + const Origin origin(GURL("http://localhost:81")); |
| + test->idb_factory_ = |
| + base::MakeRefCounted<TestIDBFactory>( |
| + test->idb_context_.get()); |
| + test->backing_store_ = |
| + test->idb_factory_->OpenBackingStoreForTest( |
| + origin, test->url_request_context_getter_); |
| + }, |
| + base::Unretained(this))); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| // useful keys and values during tests |
| value1_ = IndexedDBValue("value1", std::vector<IndexedDBBlobInfo>()); |
| value2_ = IndexedDBValue("value2", std::vector<IndexedDBBlobInfo>()); |
| + key1_ = IndexedDBKey(99, blink::kWebIDBKeyTypeNumber); |
| + key2_ = IndexedDBKey(ASCIIToUTF16("key2")); |
| + } |
| + |
| + void TearDown() override { |
| + // Factory and backing store must be destroyed on IDB task runner. |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, base::BindOnce( |
| + [](IndexedDBBackingStoreTest* test) { |
| + test->idb_factory_ = nullptr; |
| + test->backing_store_ = nullptr; |
| + }, |
| + base::Unretained(this))); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + quota_manager_proxy_->SimulateQuotaManagerDestroyed(); |
| + } |
| + |
| + TestableIndexedDBBackingStore* backing_store() const { |
| + return backing_store_.get(); |
| + } |
| + |
| + // Sample keys and values that are consistent. Public so that posted lambdas |
| + // passed |this| can access them. |
| + IndexedDBKey key1_; |
| + IndexedDBKey key2_; |
| + IndexedDBValue value1_; |
| + IndexedDBValue value2_; |
| + |
| + protected: |
| + // Must be initialized before url_request_context_getter_ |
| + TestBrowserThreadBundle thread_bundle_; |
| + |
| + base::ScopedTempDir temp_dir_; |
| + scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; |
| + scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_; |
| + scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_; |
| + scoped_refptr<IndexedDBContextImpl> idb_context_; |
| + scoped_refptr<TestIDBFactory> idb_factory_; |
| + |
| + scoped_refptr<TestableIndexedDBBackingStore> backing_store_; |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest); |
| +}; |
| + |
| +class IndexedDBBackingStoreTestWithBlobs : public IndexedDBBackingStoreTest { |
| + public: |
| + IndexedDBBackingStoreTestWithBlobs() {} |
| + |
| + void SetUp() override { |
| + IndexedDBBackingStoreTest::SetUp(); |
| + |
| + // useful keys and values during tests |
| blob_info_.push_back( |
| IndexedDBBlobInfo("uuid 3", base::UTF8ToUTF16("blob type"), 1)); |
| blob_info_.push_back(IndexedDBBlobInfo( |
| @@ -263,18 +330,14 @@ class IndexedDBBackingStoreTest : public testing::Test { |
| base::UTF8ToUTF16("file type"))); |
| value3_ = IndexedDBValue("value3", blob_info_); |
| - key1_ = IndexedDBKey(99, blink::kWebIDBKeyTypeNumber); |
| - key2_ = IndexedDBKey(ASCIIToUTF16("key2")); |
| key3_ = IndexedDBKey(ASCIIToUTF16("key3")); |
| } |
| - void TearDown() override { |
| - quota_manager_proxy_->SimulateQuotaManagerDestroyed(); |
| - } |
| - |
| // This just checks the data that survive getting stored and recalled, e.g. |
| // the file path and UUID will change and thus aren't verified. |
| bool CheckBlobInfoMatches(const std::vector<IndexedDBBlobInfo>& reads) const { |
| + DCHECK(idb_context_->TaskRunner()->RunsTasksInCurrentSequence()); |
| + |
| if (blob_info_.size() != reads.size()) |
| return false; |
| for (size_t i = 0; i < blob_info_.size(); ++i) { |
| @@ -297,6 +360,8 @@ class IndexedDBBackingStoreTest : public testing::Test { |
| bool CheckBlobReadsMatchWrites( |
| const std::vector<IndexedDBBlobInfo>& reads) const { |
| + DCHECK(idb_context_->TaskRunner()->RunsTasksInCurrentSequence()); |
| + |
| if (backing_store_->writes().size() != reads.size()) |
| return false; |
| std::set<int64_t> ids; |
| @@ -312,6 +377,8 @@ class IndexedDBBackingStoreTest : public testing::Test { |
| } |
| bool CheckBlobWrites() const { |
| + DCHECK(idb_context_->TaskRunner()->RunsTasksInCurrentSequence()); |
| + |
| if (backing_store_->writes().size() != blob_info_.size()) |
| return false; |
| for (size_t i = 0; i < backing_store_->writes().size(); ++i) { |
| @@ -333,6 +400,8 @@ class IndexedDBBackingStoreTest : public testing::Test { |
| } |
| bool CheckBlobRemovals() const { |
| + DCHECK(idb_context_->TaskRunner()->RunsTasksInCurrentSequence()); |
| + |
| if (backing_store_->removals().size() != backing_store_->writes().size()) |
| return false; |
| for (size_t i = 0; i < backing_store_->writes().size(); ++i) { |
| @@ -342,31 +411,17 @@ class IndexedDBBackingStoreTest : public testing::Test { |
| return true; |
| } |
| - protected: |
| - // Must be initialized before url_request_context_getter_ |
| - TestBrowserThreadBundle thread_bundle_; |
| - |
| - base::ScopedTempDir temp_dir_; |
| - scoped_refptr<base::TestSimpleTaskRunner> task_runner_; |
| - scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_; |
| - scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_; |
| - scoped_refptr<IndexedDBContextImpl> idb_context_; |
| - scoped_refptr<TestIDBFactory> idb_factory_; |
| - scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; |
| - |
| - scoped_refptr<TestableIndexedDBBackingStore> backing_store_; |
| - |
| - // Sample keys and values that are consistent. |
| - IndexedDBKey key1_; |
| - IndexedDBKey key2_; |
| + // Sample keys and values that are consistent. Public so that posted lambdas |
| + // passed |this| can access them. |
| IndexedDBKey key3_; |
| - IndexedDBValue value1_; |
| - IndexedDBValue value2_; |
| IndexedDBValue value3_; |
| - std::vector<IndexedDBBlobInfo> blob_info_; |
| private: |
| - DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest); |
| + // Blob details referenced by |value3_|. The various CheckBlob*() methods |
| + // can be used to verify the state as a test progresses. |
| + std::vector<IndexedDBBlobInfo> blob_info_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTestWithBlobs); |
| }; |
| class TestCallback : public IndexedDBBackingStore::BlobWriteCallback { |
| @@ -396,630 +451,847 @@ class TestCallback : public IndexedDBBackingStore::BlobWriteCallback { |
| }; |
| TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) { |
| - { |
| - IndexedDBBackingStore::Transaction transaction1(backing_store_.get()); |
| - transaction1.Begin(); |
| - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; |
| - IndexedDBBackingStore::RecordIdentifier record; |
| - leveldb::Status s = backing_store_->PutRecord(&transaction1, 1, 1, key1_, |
| - &value1_, &handles, &record); |
| - EXPECT_TRUE(s.ok()); |
| - scoped_refptr<TestCallback> callback(new TestCallback()); |
| - EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok()); |
| - EXPECT_TRUE(callback->called); |
| - EXPECT_TRUE(callback->succeeded); |
| - EXPECT_TRUE(transaction1.CommitPhaseTwo().ok()); |
| - } |
| - |
| - { |
| - IndexedDBBackingStore::Transaction transaction2(backing_store_.get()); |
| - transaction2.Begin(); |
| - IndexedDBValue result_value; |
| - EXPECT_TRUE( |
| - backing_store_->GetRecord(&transaction2, 1, 1, key1_, &result_value) |
| - .ok()); |
| - scoped_refptr<TestCallback> callback(new TestCallback()); |
| - EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok()); |
| - EXPECT_TRUE(callback->called); |
| - EXPECT_TRUE(callback->succeeded); |
| - EXPECT_TRUE(transaction2.CommitPhaseTwo().ok()); |
| - EXPECT_EQ(value1_.bits, result_value.bits); |
| - } |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](IndexedDBBackingStore* backing_store, IndexedDBKey key, |
| + IndexedDBValue value) { |
| + { |
| + IndexedDBBackingStore::Transaction transaction1(backing_store); |
| + transaction1.Begin(); |
| + std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; |
| + IndexedDBBackingStore::RecordIdentifier record; |
| + leveldb::Status s = backing_store->PutRecord( |
| + &transaction1, 1, 1, key, &value, &handles, &record); |
| + EXPECT_TRUE(s.ok()); |
| + scoped_refptr<TestCallback> callback( |
| + base::MakeRefCounted<TestCallback>()); |
| + EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok()); |
| + EXPECT_TRUE(callback->called); |
| + EXPECT_TRUE(callback->succeeded); |
| + EXPECT_TRUE(transaction1.CommitPhaseTwo().ok()); |
| + } |
| + |
| + { |
| + IndexedDBBackingStore::Transaction transaction2(backing_store); |
| + transaction2.Begin(); |
| + IndexedDBValue result_value; |
| + EXPECT_TRUE( |
| + backing_store |
| + ->GetRecord(&transaction2, 1, 1, key, &result_value) |
| + .ok()); |
| + scoped_refptr<TestCallback> callback( |
| + base::MakeRefCounted<TestCallback>()); |
| + EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok()); |
| + EXPECT_TRUE(callback->called); |
| + EXPECT_TRUE(callback->succeeded); |
| + EXPECT_TRUE(transaction2.CommitPhaseTwo().ok()); |
| + EXPECT_EQ(value.bits, result_value.bits); |
| + } |
| + }, |
| + base::Unretained(backing_store()), key1_, value1_)); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| } |
| -TEST_F(IndexedDBBackingStoreTest, PutGetConsistencyWithBlobs) { |
| - { |
| - IndexedDBBackingStore::Transaction transaction1(backing_store_.get()); |
| - transaction1.Begin(); |
| - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; |
| - IndexedDBBackingStore::RecordIdentifier record; |
| - EXPECT_TRUE( |
| - backing_store_ |
| - ->PutRecord(&transaction1, 1, 1, key3_, &value3_, &handles, &record) |
| - .ok()); |
| - scoped_refptr<TestCallback> callback(new TestCallback()); |
| - EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok()); |
| - task_runner_->RunUntilIdle(); |
| - EXPECT_TRUE(CheckBlobWrites()); |
| - EXPECT_TRUE(callback->called); |
| - EXPECT_TRUE(callback->succeeded); |
| - EXPECT_TRUE(transaction1.CommitPhaseTwo().ok()); |
| - } |
| - |
| - { |
| - IndexedDBBackingStore::Transaction transaction2(backing_store_.get()); |
| - transaction2.Begin(); |
| - IndexedDBValue result_value; |
| - EXPECT_TRUE( |
| - backing_store_->GetRecord(&transaction2, 1, 1, key3_, &result_value) |
| - .ok()); |
| - scoped_refptr<TestCallback> callback(new TestCallback()); |
| - EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok()); |
| - EXPECT_TRUE(callback->called); |
| - EXPECT_TRUE(callback->succeeded); |
| - EXPECT_TRUE(transaction2.CommitPhaseTwo().ok()); |
| - EXPECT_EQ(value3_.bits, result_value.bits); |
| - EXPECT_TRUE(CheckBlobInfoMatches(result_value.blob_info)); |
| - EXPECT_TRUE(CheckBlobReadsMatchWrites(result_value.blob_info)); |
| - } |
| - |
| - { |
| - IndexedDBBackingStore::Transaction transaction3(backing_store_.get()); |
| - transaction3.Begin(); |
| - IndexedDBValue result_value; |
| - EXPECT_TRUE(backing_store_ |
| - ->DeleteRange(&transaction3, 1, 1, IndexedDBKeyRange(key3_)) |
| +TEST_F(IndexedDBBackingStoreTestWithBlobs, PutGetConsistencyWithBlobs) { |
| + struct TestState { |
|
dmurph
2017/07/07 18:28:59
I like this approach.
|
| + std::unique_ptr<IndexedDBBackingStore::Transaction> transaction1; |
| + scoped_refptr<TestCallback> callback1; |
| + std::unique_ptr<IndexedDBBackingStore::Transaction> transaction3; |
| + scoped_refptr<TestCallback> callback3; |
| + } state; |
| + |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](IndexedDBBackingStoreTestWithBlobs* test, TestState* state) { |
| + // Initiate transaction1 - writing blobs. |
| + state->transaction1 = |
| + base::MakeUnique<IndexedDBBackingStore::Transaction>( |
| + test->backing_store()); |
| + state->transaction1->Begin(); |
| + std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; |
| + IndexedDBBackingStore::RecordIdentifier record; |
| + EXPECT_TRUE(test->backing_store() |
| + ->PutRecord(state->transaction1.get(), 1, 1, |
| + test->key3_, &test->value3_, &handles, |
| + &record) |
| + .ok()); |
| + state->callback1 = base::MakeRefCounted<TestCallback>(); |
| + EXPECT_TRUE( |
| + state->transaction1->CommitPhaseOne(state->callback1).ok()); |
| + }, |
| + base::Unretained(this), base::Unretained(&state))); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](IndexedDBBackingStoreTestWithBlobs* test, TestState* state) { |
| + // Finish up transaction1, verifying blob writes. |
| + EXPECT_TRUE(state->callback1->called); |
| + EXPECT_TRUE(state->callback1->succeeded); |
| + EXPECT_TRUE(test->CheckBlobWrites()); |
| + EXPECT_TRUE(state->transaction1->CommitPhaseTwo().ok()); |
| + |
| + // Initiate transaction2, reading blobs. |
| + IndexedDBBackingStore::Transaction transaction2( |
| + test->backing_store()); |
| + transaction2.Begin(); |
| + IndexedDBValue result_value; |
| + EXPECT_TRUE( |
| + test->backing_store() |
| + ->GetRecord(&transaction2, 1, 1, test->key3_, &result_value) |
| .ok()); |
| - scoped_refptr<TestCallback> callback(new TestCallback()); |
| - EXPECT_TRUE(transaction3.CommitPhaseOne(callback).ok()); |
| - task_runner_->RunUntilIdle(); |
| - EXPECT_TRUE(callback->called); |
| - EXPECT_TRUE(callback->succeeded); |
| - EXPECT_TRUE(transaction3.CommitPhaseTwo().ok()); |
| - EXPECT_TRUE(CheckBlobRemovals()); |
| - } |
| + |
| + // Finish up transaction2, verifying blob reads. |
| + scoped_refptr<TestCallback> callback( |
| + base::MakeRefCounted<TestCallback>()); |
| + EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok()); |
| + EXPECT_TRUE(callback->called); |
| + EXPECT_TRUE(callback->succeeded); |
| + EXPECT_TRUE(transaction2.CommitPhaseTwo().ok()); |
| + EXPECT_EQ(test->value3_.bits, result_value.bits); |
| + EXPECT_TRUE(test->CheckBlobInfoMatches(result_value.blob_info)); |
| + EXPECT_TRUE( |
| + test->CheckBlobReadsMatchWrites(result_value.blob_info)); |
| + |
| + // Initiate transaction3, deleting blobs. |
| + state->transaction3 = |
| + base::MakeUnique<IndexedDBBackingStore::Transaction>( |
| + test->backing_store()); |
| + state->transaction3->Begin(); |
| + EXPECT_TRUE(test->backing_store() |
| + ->DeleteRange(state->transaction3.get(), 1, 1, |
| + IndexedDBKeyRange(test->key3_)) |
| + .ok()); |
| + state->callback3 = base::MakeRefCounted<TestCallback>(); |
| + EXPECT_TRUE( |
| + state->transaction3->CommitPhaseOne(state->callback3).ok()); |
| + |
| + }, |
| + base::Unretained(this), base::Unretained(&state))); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](IndexedDBBackingStoreTestWithBlobs* test, TestState* state) { |
| + // Finish up transaction 3, verifying blob deletes. |
| + EXPECT_TRUE(state->transaction3->CommitPhaseTwo().ok()); |
| + EXPECT_TRUE(test->CheckBlobRemovals()); |
| + }, |
| + base::Unretained(this), base::Unretained(&state))); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| } |
| TEST_F(IndexedDBBackingStoreTest, DeleteRange) { |
| - IndexedDBKey key0 = IndexedDBKey(ASCIIToUTF16("key0")); |
| - IndexedDBKey key1 = IndexedDBKey(ASCIIToUTF16("key1")); |
| - IndexedDBKey key2 = IndexedDBKey(ASCIIToUTF16("key2")); |
| - IndexedDBKey key3 = IndexedDBKey(ASCIIToUTF16("key3")); |
| - IndexedDBBlobInfo blob0("uuid 0", base::UTF8ToUTF16("type 0"), 1); |
| - IndexedDBBlobInfo blob1("uuid 1", base::UTF8ToUTF16("type 1"), 1); |
| - IndexedDBBlobInfo blob2("uuid 2", base::UTF8ToUTF16("type 2"), 1); |
| - IndexedDBBlobInfo blob3("uuid 3", base::UTF8ToUTF16("type 3"), 1); |
| - IndexedDBKeyRange ranges[] = {IndexedDBKeyRange(key1, key2, false, false), |
| - IndexedDBKeyRange(key1, key2, false, false), |
| - IndexedDBKeyRange(key0, key2, true, false), |
| - IndexedDBKeyRange(key1, key3, false, true), |
| - IndexedDBKeyRange(key0, key3, true, true)}; |
| - |
| - for (unsigned i = 0; i < sizeof(ranges) / sizeof(IndexedDBKeyRange); ++i) { |
| - backing_store_->ClearWrites(); |
| - backing_store_->ClearRemovals(); |
| - |
| - { |
| - std::vector<IndexedDBBlobInfo> blob_info0, blob_info1, blob_info2, |
| - blob_info3; |
| - blob_info0.push_back(blob0); |
| - blob_info1.push_back(blob1); |
| - blob_info2.push_back(blob2); |
| - blob_info3.push_back(blob3); |
| - IndexedDBValue value0 = IndexedDBValue("value0", blob_info0); |
| - IndexedDBValue value1 = IndexedDBValue("value1", blob_info1); |
| - IndexedDBValue value2 = IndexedDBValue("value2", blob_info2); |
| - IndexedDBValue value3 = IndexedDBValue("value3", blob_info3); |
| - IndexedDBBackingStore::Transaction transaction1(backing_store_.get()); |
| - transaction1.Begin(); |
| - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; |
| - IndexedDBBackingStore::RecordIdentifier record; |
| - EXPECT_TRUE(backing_store_->PutRecord(&transaction1, |
| - 1, |
| - i + 1, |
| - key0, |
| - &value0, |
| - &handles, |
| - &record).ok()); |
| - EXPECT_TRUE(backing_store_->PutRecord(&transaction1, |
| - 1, |
| - i + 1, |
| - key1, |
| - &value1, |
| - &handles, |
| - &record).ok()); |
| - EXPECT_TRUE(backing_store_->PutRecord(&transaction1, |
| - 1, |
| - i + 1, |
| - key2, |
| - &value2, |
| - &handles, |
| - &record).ok()); |
| - EXPECT_TRUE(backing_store_->PutRecord(&transaction1, |
| - 1, |
| - i + 1, |
| - key3, |
| - &value3, |
| - &handles, |
| - &record).ok()); |
| - scoped_refptr<TestCallback> callback(new TestCallback()); |
| - EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok()); |
| - task_runner_->RunUntilIdle(); |
| - EXPECT_TRUE(callback->called); |
| - EXPECT_TRUE(callback->succeeded); |
| - EXPECT_TRUE(transaction1.CommitPhaseTwo().ok()); |
| - } |
| - |
| - { |
| - IndexedDBBackingStore::Transaction transaction2(backing_store_.get()); |
| - transaction2.Begin(); |
| - IndexedDBValue result_value; |
| - EXPECT_TRUE( |
| - backing_store_->DeleteRange(&transaction2, 1, i + 1, ranges[i]).ok()); |
| - scoped_refptr<TestCallback> callback(new TestCallback()); |
| - EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok()); |
| - task_runner_->RunUntilIdle(); |
| - EXPECT_TRUE(callback->called); |
| - EXPECT_TRUE(callback->succeeded); |
| - EXPECT_TRUE(transaction2.CommitPhaseTwo().ok()); |
| - ASSERT_EQ(2UL, backing_store_->removals().size()); |
| - EXPECT_EQ(backing_store_->writes()[1].key(), |
| - backing_store_->removals()[0]); |
| - EXPECT_EQ(backing_store_->writes()[2].key(), |
| - backing_store_->removals()[1]); |
| - } |
| + const std::vector<IndexedDBKey> keys = { |
| + IndexedDBKey(ASCIIToUTF16("key0")), IndexedDBKey(ASCIIToUTF16("key1")), |
| + IndexedDBKey(ASCIIToUTF16("key2")), IndexedDBKey(ASCIIToUTF16("key3"))}; |
| + const IndexedDBKeyRange ranges[] = { |
| + IndexedDBKeyRange(keys[1], keys[2], false, false), |
| + IndexedDBKeyRange(keys[1], keys[2], false, false), |
| + IndexedDBKeyRange(keys[0], keys[2], true, false), |
| + IndexedDBKeyRange(keys[1], keys[3], false, true), |
| + IndexedDBKeyRange(keys[0], keys[3], true, true)}; |
| + |
| + for (size_t i = 0; i < arraysize(ranges); ++i) { |
| + const int64_t database_id = 1; |
| + const int64_t object_store_id = i + 1; |
| + const IndexedDBKeyRange& range = ranges[i]; |
| + |
| + struct TestState { |
| + std::unique_ptr<IndexedDBBackingStore::Transaction> transaction1; |
| + scoped_refptr<TestCallback> callback1; |
| + std::unique_ptr<IndexedDBBackingStore::Transaction> transaction2; |
| + scoped_refptr<TestCallback> callback2; |
| + } state; |
| + |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](TestableIndexedDBBackingStore* backing_store, TestState* state, |
| + const std::vector<IndexedDBKey>& keys, int64_t database_id, |
| + int64_t object_store_id) { |
| + // Reset from previous iteration. |
| + backing_store->ClearWrites(); |
| + backing_store->ClearRemovals(); |
| + |
| + std::vector<IndexedDBValue> values = { |
| + IndexedDBValue( |
| + "value0", {IndexedDBBlobInfo( |
| + "uuid 0", base::UTF8ToUTF16("type 0"), 1)}), |
| + IndexedDBValue( |
| + "value1", {IndexedDBBlobInfo( |
| + "uuid 1", base::UTF8ToUTF16("type 1"), 1)}), |
| + IndexedDBValue( |
| + "value2", {IndexedDBBlobInfo( |
| + "uuid 2", base::UTF8ToUTF16("type 2"), 1)}), |
| + IndexedDBValue( |
| + "value3", |
| + {IndexedDBBlobInfo("uuid 3", base::UTF8ToUTF16("type 3"), |
| + 1)})}; |
| + ASSERT_GE(keys.size(), values.size()); |
| + |
| + // Initiate transaction1 - write records. |
| + state->transaction1 = |
| + base::MakeUnique<IndexedDBBackingStore::Transaction>( |
| + backing_store); |
| + state->transaction1->Begin(); |
| + std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; |
| + IndexedDBBackingStore::RecordIdentifier record; |
| + for (size_t i = 0; i < values.size(); ++i) { |
| + EXPECT_TRUE(backing_store |
| + ->PutRecord(state->transaction1.get(), |
| + database_id, object_store_id, |
| + keys[i], &values[i], &handles, |
| + &record) |
| + .ok()); |
| + } |
| + |
| + // Start committing transaction1. |
| + state->callback1 = base::MakeRefCounted<TestCallback>(); |
| + EXPECT_TRUE( |
| + state->transaction1->CommitPhaseOne(state->callback1).ok()); |
| + }, |
| + base::Unretained(backing_store()), base::Unretained(&state), |
| + base::ConstRef(keys), database_id, object_store_id)); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](TestableIndexedDBBackingStore* backing_store, TestState* state, |
| + IndexedDBKeyRange range, int64_t database_id, |
| + int64_t object_store_id) { |
| + // Finish committing transaction1. |
| + EXPECT_TRUE(state->callback1->called); |
| + EXPECT_TRUE(state->callback1->succeeded); |
| + EXPECT_TRUE(state->transaction1->CommitPhaseTwo().ok()); |
| + |
| + // Initiate transaction 2 - delete range. |
| + state->transaction2 = |
| + base::MakeUnique<IndexedDBBackingStore::Transaction>( |
| + backing_store); |
| + state->transaction2->Begin(); |
| + IndexedDBValue result_value; |
| + EXPECT_TRUE(backing_store |
| + ->DeleteRange(state->transaction2.get(), |
| + database_id, object_store_id, range) |
| + .ok()); |
| + |
| + // Start committing transaction2. |
| + state->callback2 = base::MakeRefCounted<TestCallback>(); |
| + EXPECT_TRUE( |
| + state->transaction2->CommitPhaseOne(state->callback2).ok()); |
| + }, |
| + base::Unretained(backing_store()), base::Unretained(&state), range, |
| + database_id, object_store_id)); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](TestableIndexedDBBackingStore* backing_store, TestState* state) { |
| + // Finish committing transaction2. |
| + EXPECT_TRUE(state->callback2->called); |
| + EXPECT_TRUE(state->callback2->succeeded); |
| + EXPECT_TRUE(state->transaction2->CommitPhaseTwo().ok()); |
| + |
| + // Verify blob removals. |
| + ASSERT_EQ(2UL, backing_store->removals().size()); |
| + EXPECT_EQ(backing_store->writes()[1].key(), |
| + backing_store->removals()[0]); |
| + EXPECT_EQ(backing_store->writes()[2].key(), |
| + backing_store->removals()[1]); |
| + }, |
| + base::Unretained(backing_store()), base::Unretained(&state))); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| } |
| } |
| TEST_F(IndexedDBBackingStoreTest, DeleteRangeEmptyRange) { |
| - IndexedDBKey key0 = IndexedDBKey(ASCIIToUTF16("key0")); |
| - IndexedDBKey key1 = IndexedDBKey(ASCIIToUTF16("key1")); |
| - IndexedDBKey key2 = IndexedDBKey(ASCIIToUTF16("key2")); |
| - IndexedDBKey key3 = IndexedDBKey(ASCIIToUTF16("key3")); |
| - IndexedDBKey key4 = IndexedDBKey(ASCIIToUTF16("key4")); |
| - IndexedDBBlobInfo blob0("uuid 0", base::UTF8ToUTF16("type 0"), 1); |
| - IndexedDBBlobInfo blob1("uuid 1", base::UTF8ToUTF16("type 1"), 1); |
| - IndexedDBBlobInfo blob2("uuid 2", base::UTF8ToUTF16("type 2"), 1); |
| - IndexedDBBlobInfo blob3("uuid 3", base::UTF8ToUTF16("type 3"), 1); |
| - IndexedDBKeyRange ranges[] = {IndexedDBKeyRange(key3, key4, true, false), |
| - IndexedDBKeyRange(key2, key1, false, false), |
| - IndexedDBKeyRange(key2, key1, true, true)}; |
| - |
| - for (unsigned i = 0; i < arraysize(ranges); ++i) { |
| - backing_store_->ClearWrites(); |
| - backing_store_->ClearRemovals(); |
| - |
| - { |
| - std::vector<IndexedDBBlobInfo> blob_info0, blob_info1, blob_info2, |
| - blob_info3; |
| - blob_info0.push_back(blob0); |
| - blob_info1.push_back(blob1); |
| - blob_info2.push_back(blob2); |
| - blob_info3.push_back(blob3); |
| - IndexedDBValue value0 = IndexedDBValue("value0", blob_info0); |
| - IndexedDBValue value1 = IndexedDBValue("value1", blob_info1); |
| - IndexedDBValue value2 = IndexedDBValue("value2", blob_info2); |
| - IndexedDBValue value3 = IndexedDBValue("value3", blob_info3); |
| - IndexedDBBackingStore::Transaction transaction1(backing_store_.get()); |
| - transaction1.Begin(); |
| - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; |
| - IndexedDBBackingStore::RecordIdentifier record; |
| - EXPECT_TRUE(backing_store_->PutRecord(&transaction1, |
| - 1, |
| - i + 1, |
| - key0, |
| - &value0, |
| - &handles, |
| - &record).ok()); |
| - EXPECT_TRUE(backing_store_->PutRecord(&transaction1, |
| - 1, |
| - i + 1, |
| - key1, |
| - &value1, |
| - &handles, |
| - &record).ok()); |
| - EXPECT_TRUE(backing_store_->PutRecord(&transaction1, |
| - 1, |
| - i + 1, |
| - key2, |
| - &value2, |
| - &handles, |
| - &record).ok()); |
| - EXPECT_TRUE(backing_store_->PutRecord(&transaction1, |
| - 1, |
| - i + 1, |
| - key3, |
| - &value3, |
| - &handles, |
| - &record).ok()); |
| - scoped_refptr<TestCallback> callback(new TestCallback()); |
| - EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok()); |
| - task_runner_->RunUntilIdle(); |
| - EXPECT_TRUE(callback->called); |
| - EXPECT_TRUE(callback->succeeded); |
| - EXPECT_TRUE(transaction1.CommitPhaseTwo().ok()); |
| - } |
| - |
| - { |
| - IndexedDBBackingStore::Transaction transaction2(backing_store_.get()); |
| - transaction2.Begin(); |
| - IndexedDBValue result_value; |
| - EXPECT_TRUE( |
| - backing_store_->DeleteRange(&transaction2, 1, i + 1, ranges[i]).ok()); |
| - scoped_refptr<TestCallback> callback(new TestCallback()); |
| - EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok()); |
| - task_runner_->RunUntilIdle(); |
| - EXPECT_TRUE(callback->called); |
| - EXPECT_TRUE(callback->succeeded); |
| - EXPECT_TRUE(transaction2.CommitPhaseTwo().ok()); |
| - EXPECT_EQ(0UL, backing_store_->removals().size()); |
| - } |
| + const std::vector<IndexedDBKey> keys = { |
| + IndexedDBKey(ASCIIToUTF16("key0")), IndexedDBKey(ASCIIToUTF16("key1")), |
| + IndexedDBKey(ASCIIToUTF16("key2")), IndexedDBKey(ASCIIToUTF16("key3")), |
| + IndexedDBKey(ASCIIToUTF16("key4"))}; |
| + const IndexedDBKeyRange ranges[] = { |
| + IndexedDBKeyRange(keys[3], keys[4], true, false), |
| + IndexedDBKeyRange(keys[2], keys[1], false, false), |
| + IndexedDBKeyRange(keys[2], keys[1], true, true)}; |
| + |
| + for (size_t i = 0; i < arraysize(ranges); ++i) { |
| + const int64_t database_id = 1; |
| + const int64_t object_store_id = i + 1; |
| + const IndexedDBKeyRange& range = ranges[i]; |
| + |
| + struct TestState { |
| + std::unique_ptr<IndexedDBBackingStore::Transaction> transaction1; |
| + scoped_refptr<TestCallback> callback1; |
| + std::unique_ptr<IndexedDBBackingStore::Transaction> transaction2; |
| + scoped_refptr<TestCallback> callback2; |
| + } state; |
| + |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](TestableIndexedDBBackingStore* backing_store, TestState* state, |
| + const std::vector<IndexedDBKey>& keys, int64_t database_id, |
| + int64_t object_store_id) { |
| + // Reset from previous iteration. |
| + backing_store->ClearWrites(); |
| + backing_store->ClearRemovals(); |
| + |
| + std::vector<IndexedDBValue> values = { |
| + IndexedDBValue( |
| + "value0", {IndexedDBBlobInfo( |
| + "uuid 0", base::UTF8ToUTF16("type 0"), 1)}), |
| + IndexedDBValue( |
| + "value1", {IndexedDBBlobInfo( |
| + "uuid 1", base::UTF8ToUTF16("type 1"), 1)}), |
| + IndexedDBValue( |
| + "value2", {IndexedDBBlobInfo( |
| + "uuid 2", base::UTF8ToUTF16("type 2"), 1)}), |
| + IndexedDBValue( |
| + "value3", |
| + {IndexedDBBlobInfo("uuid 3", base::UTF8ToUTF16("type 3"), |
| + 1)})}; |
| + ASSERT_GE(keys.size(), values.size()); |
| + |
| + // Initiate transaction1 - write records. |
| + state->transaction1 = |
| + base::MakeUnique<IndexedDBBackingStore::Transaction>( |
| + backing_store); |
| + state->transaction1->Begin(); |
| + |
| + std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; |
| + IndexedDBBackingStore::RecordIdentifier record; |
| + for (size_t i = 0; i < values.size(); ++i) { |
| + EXPECT_TRUE(backing_store |
| + ->PutRecord(state->transaction1.get(), |
| + database_id, object_store_id, |
| + keys[i], &values[i], &handles, |
| + &record) |
| + .ok()); |
| + } |
| + // Start committing transaction1. |
| + state->callback1 = base::MakeRefCounted<TestCallback>(); |
| + EXPECT_TRUE( |
| + state->transaction1->CommitPhaseOne(state->callback1).ok()); |
| + }, |
| + base::Unretained(backing_store()), base::Unretained(&state), |
| + base::ConstRef(keys), database_id, object_store_id)); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](TestableIndexedDBBackingStore* backing_store, TestState* state, |
| + IndexedDBKeyRange range, int64_t database_id, |
| + int64_t object_store_id) { |
| + // Finish committing transaction1. |
| + EXPECT_TRUE(state->callback1->called); |
| + EXPECT_TRUE(state->callback1->succeeded); |
| + EXPECT_TRUE(state->transaction1->CommitPhaseTwo().ok()); |
| + |
| + // Initiate transaction 2 - delete range. |
| + state->transaction2 = |
| + base::MakeUnique<IndexedDBBackingStore::Transaction>( |
| + backing_store); |
| + state->transaction2->Begin(); |
| + IndexedDBValue result_value; |
| + EXPECT_TRUE(backing_store |
| + ->DeleteRange(state->transaction2.get(), |
| + database_id, object_store_id, range) |
| + .ok()); |
| + |
| + // Start committing transaction2. |
| + state->callback2 = base::MakeRefCounted<TestCallback>(); |
| + EXPECT_TRUE( |
| + state->transaction2->CommitPhaseOne(state->callback2).ok()); |
| + }, |
| + base::Unretained(backing_store()), base::Unretained(&state), range, |
| + database_id, object_store_id)); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](TestableIndexedDBBackingStore* backing_store, TestState* state) { |
| + // Finish committing transaction2. |
| + EXPECT_TRUE(state->callback2->called); |
| + EXPECT_TRUE(state->callback2->succeeded); |
| + EXPECT_TRUE(state->transaction2->CommitPhaseTwo().ok()); |
| + |
| + // Verify blob removals. |
| + EXPECT_EQ(0UL, backing_store->removals().size()); |
| + }, |
| + base::Unretained(backing_store()), base::Unretained(&state))); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| } |
| } |
| -TEST_F(IndexedDBBackingStoreTest, BlobJournalInterleavedTransactions) { |
| - IndexedDBBackingStore::Transaction transaction1(backing_store_.get()); |
| - transaction1.Begin(); |
| - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles1; |
| - IndexedDBBackingStore::RecordIdentifier record1; |
| - EXPECT_TRUE( |
| - backing_store_ |
| - ->PutRecord(&transaction1, 1, 1, key3_, &value3_, &handles1, &record1) |
| - .ok()); |
| - scoped_refptr<TestCallback> callback1(new TestCallback()); |
| - EXPECT_TRUE(transaction1.CommitPhaseOne(callback1).ok()); |
| - task_runner_->RunUntilIdle(); |
| - EXPECT_TRUE(CheckBlobWrites()); |
| - EXPECT_TRUE(callback1->called); |
| - EXPECT_TRUE(callback1->succeeded); |
| - EXPECT_EQ(0U, backing_store_->removals().size()); |
| - |
| - IndexedDBBackingStore::Transaction transaction2(backing_store_.get()); |
| - transaction2.Begin(); |
| - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles2; |
| - IndexedDBBackingStore::RecordIdentifier record2; |
| - EXPECT_TRUE( |
| - backing_store_ |
| - ->PutRecord(&transaction2, 1, 1, key1_, &value1_, &handles2, &record2) |
| - .ok()); |
| - scoped_refptr<TestCallback> callback2(new TestCallback()); |
| - EXPECT_TRUE(transaction2.CommitPhaseOne(callback2).ok()); |
| - task_runner_->RunUntilIdle(); |
| - EXPECT_TRUE(CheckBlobWrites()); |
| - EXPECT_TRUE(callback2->called); |
| - EXPECT_TRUE(callback2->succeeded); |
| - EXPECT_EQ(0U, backing_store_->removals().size()); |
| - |
| - EXPECT_TRUE(transaction1.CommitPhaseTwo().ok()); |
| - EXPECT_EQ(0U, backing_store_->removals().size()); |
| - |
| - EXPECT_TRUE(transaction2.CommitPhaseTwo().ok()); |
| - EXPECT_EQ(0U, backing_store_->removals().size()); |
| +TEST_F(IndexedDBBackingStoreTestWithBlobs, BlobJournalInterleavedTransactions) { |
| + struct TestState { |
| + std::unique_ptr<IndexedDBBackingStore::Transaction> transaction1; |
| + scoped_refptr<TestCallback> callback1; |
| + std::unique_ptr<IndexedDBBackingStore::Transaction> transaction2; |
| + scoped_refptr<TestCallback> callback2; |
| + } state; |
| + |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](IndexedDBBackingStoreTestWithBlobs* test, TestState* state) { |
| + // Initiate transaction1. |
| + state->transaction1 = |
| + base::MakeUnique<IndexedDBBackingStore::Transaction>( |
| + test->backing_store()); |
| + state->transaction1->Begin(); |
| + std::vector<std::unique_ptr<storage::BlobDataHandle>> handles1; |
| + IndexedDBBackingStore::RecordIdentifier record1; |
| + EXPECT_TRUE(test->backing_store() |
| + ->PutRecord(state->transaction1.get(), 1, 1, |
| + test->key3_, &test->value3_, &handles1, |
| + &record1) |
| + .ok()); |
| + state->callback1 = base::MakeRefCounted<TestCallback>(); |
| + EXPECT_TRUE( |
| + state->transaction1->CommitPhaseOne(state->callback1).ok()); |
| + }, |
| + base::Unretained(this), base::Unretained(&state))); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](IndexedDBBackingStoreTestWithBlobs* test, TestState* state) { |
| + // Verify transaction1 phase one completed. |
| + EXPECT_TRUE(state->callback1->called); |
| + EXPECT_TRUE(state->callback1->succeeded); |
| + EXPECT_TRUE(test->CheckBlobWrites()); |
| + EXPECT_EQ(0U, test->backing_store()->removals().size()); |
| + |
| + // Initiate transaction2. |
| + state->transaction2 = |
| + base::MakeUnique<IndexedDBBackingStore::Transaction>( |
| + test->backing_store()); |
| + state->transaction2->Begin(); |
| + std::vector<std::unique_ptr<storage::BlobDataHandle>> handles2; |
| + IndexedDBBackingStore::RecordIdentifier record2; |
| + EXPECT_TRUE(test->backing_store() |
| + ->PutRecord(state->transaction2.get(), 1, 1, |
| + test->key1_, &test->value1_, &handles2, |
| + &record2) |
| + .ok()); |
| + state->callback2 = base::MakeRefCounted<TestCallback>(); |
| + EXPECT_TRUE( |
| + state->transaction2->CommitPhaseOne(state->callback2).ok()); |
| + }, |
| + base::Unretained(this), base::Unretained(&state))); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](IndexedDBBackingStoreTestWithBlobs* test, TestState* state) { |
| + // Verify transaction2 phase one completed. |
| + EXPECT_TRUE(state->callback2->called); |
| + EXPECT_TRUE(state->callback2->succeeded); |
| + EXPECT_TRUE(test->CheckBlobWrites()); |
| + EXPECT_EQ(0U, test->backing_store()->removals().size()); |
| + |
| + // Finalize both transactions. |
| + EXPECT_TRUE(state->transaction1->CommitPhaseTwo().ok()); |
| + EXPECT_EQ(0U, test->backing_store()->removals().size()); |
| + |
| + EXPECT_TRUE(state->transaction2->CommitPhaseTwo().ok()); |
| + EXPECT_EQ(0U, test->backing_store()->removals().size()); |
| + }, |
| + base::Unretained(this), base::Unretained(&state))); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| } |
| -TEST_F(IndexedDBBackingStoreTest, LiveBlobJournal) { |
| - { |
| - IndexedDBBackingStore::Transaction transaction1(backing_store_.get()); |
| - transaction1.Begin(); |
| - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; |
| - IndexedDBBackingStore::RecordIdentifier record; |
| - EXPECT_TRUE( |
| - backing_store_ |
| - ->PutRecord(&transaction1, 1, 1, key3_, &value3_, &handles, &record) |
| - .ok()); |
| - scoped_refptr<TestCallback> callback(new TestCallback()); |
| - EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok()); |
| - task_runner_->RunUntilIdle(); |
| - EXPECT_TRUE(CheckBlobWrites()); |
| - EXPECT_TRUE(callback->called); |
| - EXPECT_TRUE(callback->succeeded); |
| - EXPECT_TRUE(transaction1.CommitPhaseTwo().ok()); |
| - } |
| - |
| - IndexedDBValue read_result_value; |
| - { |
| - IndexedDBBackingStore::Transaction transaction2(backing_store_.get()); |
| - transaction2.Begin(); |
| - EXPECT_TRUE(backing_store_ |
| - ->GetRecord(&transaction2, 1, 1, key3_, &read_result_value) |
| - .ok()); |
| - scoped_refptr<TestCallback> callback(new TestCallback()); |
| - EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok()); |
| - EXPECT_TRUE(callback->called); |
| - EXPECT_TRUE(callback->succeeded); |
| - EXPECT_TRUE(transaction2.CommitPhaseTwo().ok()); |
| - EXPECT_EQ(value3_.bits, read_result_value.bits); |
| - EXPECT_TRUE(CheckBlobInfoMatches(read_result_value.blob_info)); |
| - EXPECT_TRUE(CheckBlobReadsMatchWrites(read_result_value.blob_info)); |
| - for (size_t i = 0; i < read_result_value.blob_info.size(); ++i) { |
| - read_result_value.blob_info[i].mark_used_callback().Run(); |
| - } |
| - } |
| - |
| - { |
| - IndexedDBBackingStore::Transaction transaction3(backing_store_.get()); |
| - transaction3.Begin(); |
| - EXPECT_TRUE(backing_store_ |
| - ->DeleteRange(&transaction3, 1, 1, IndexedDBKeyRange(key3_)) |
| - .ok()); |
| - scoped_refptr<TestCallback> callback(new TestCallback()); |
| - EXPECT_TRUE(transaction3.CommitPhaseOne(callback).ok()); |
| - task_runner_->RunUntilIdle(); |
| - EXPECT_TRUE(callback->called); |
| - EXPECT_TRUE(callback->succeeded); |
| - EXPECT_TRUE(transaction3.CommitPhaseTwo().ok()); |
| - EXPECT_EQ(0U, backing_store_->removals().size()); |
| - for (size_t i = 0; i < read_result_value.blob_info.size(); ++i) { |
| - read_result_value.blob_info[i].release_callback().Run( |
| - read_result_value.blob_info[i].file_path()); |
| - } |
| - task_runner_->RunUntilIdle(); |
| - EXPECT_NE(0U, backing_store_->removals().size()); |
| - EXPECT_TRUE(CheckBlobRemovals()); |
| - } |
| +TEST_F(IndexedDBBackingStoreTestWithBlobs, LiveBlobJournal) { |
| + struct TestState { |
| + std::unique_ptr<IndexedDBBackingStore::Transaction> transaction1; |
| + scoped_refptr<TestCallback> callback1; |
| + std::unique_ptr<IndexedDBBackingStore::Transaction> transaction3; |
| + scoped_refptr<TestCallback> callback3; |
| + IndexedDBValue read_result_value; |
| + } state; |
| + |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](IndexedDBBackingStoreTestWithBlobs* test, TestState* state) { |
| + state->transaction1 = |
| + base::MakeUnique<IndexedDBBackingStore::Transaction>( |
| + test->backing_store()); |
| + state->transaction1->Begin(); |
| + std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; |
| + IndexedDBBackingStore::RecordIdentifier record; |
| + EXPECT_TRUE(test->backing_store() |
| + ->PutRecord(state->transaction1.get(), 1, 1, |
| + test->key3_, &test->value3_, &handles, |
| + &record) |
| + .ok()); |
| + state->callback1 = base::MakeRefCounted<TestCallback>(); |
| + EXPECT_TRUE( |
| + state->transaction1->CommitPhaseOne(state->callback1).ok()); |
| + }, |
| + base::Unretained(this), base::Unretained(&state))); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](IndexedDBBackingStoreTestWithBlobs* test, TestState* state) { |
| + EXPECT_TRUE(state->callback1->called); |
| + EXPECT_TRUE(state->callback1->succeeded); |
| + EXPECT_TRUE(test->CheckBlobWrites()); |
| + EXPECT_TRUE(state->transaction1->CommitPhaseTwo().ok()); |
| + |
| + IndexedDBBackingStore::Transaction transaction2( |
| + test->backing_store()); |
| + transaction2.Begin(); |
| + EXPECT_TRUE(test->backing_store() |
| + ->GetRecord(&transaction2, 1, 1, test->key3_, |
| + &state->read_result_value) |
| + .ok()); |
| + scoped_refptr<TestCallback> callback( |
| + base::MakeRefCounted<TestCallback>()); |
| + EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok()); |
| + EXPECT_TRUE(callback->called); |
| + EXPECT_TRUE(callback->succeeded); |
| + EXPECT_TRUE(transaction2.CommitPhaseTwo().ok()); |
| + EXPECT_EQ(test->value3_.bits, state->read_result_value.bits); |
| + EXPECT_TRUE( |
| + test->CheckBlobInfoMatches(state->read_result_value.blob_info)); |
| + EXPECT_TRUE(test->CheckBlobReadsMatchWrites( |
| + state->read_result_value.blob_info)); |
| + for (size_t i = 0; i < state->read_result_value.blob_info.size(); |
| + ++i) { |
| + state->read_result_value.blob_info[i].mark_used_callback().Run(); |
| + } |
| + |
| + state->transaction3 = |
| + base::MakeUnique<IndexedDBBackingStore::Transaction>( |
| + test->backing_store()); |
| + state->transaction3->Begin(); |
| + EXPECT_TRUE(test->backing_store() |
| + ->DeleteRange(state->transaction3.get(), 1, 1, |
| + IndexedDBKeyRange(test->key3_)) |
| + .ok()); |
| + state->callback3 = base::MakeRefCounted<TestCallback>(); |
| + EXPECT_TRUE( |
| + state->transaction3->CommitPhaseOne(state->callback3).ok()); |
| + }, |
| + base::Unretained(this), base::Unretained(&state))); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](IndexedDBBackingStoreTestWithBlobs* test, TestState* state) { |
| + EXPECT_TRUE(state->callback3->called); |
| + EXPECT_TRUE(state->callback3->succeeded); |
| + EXPECT_TRUE(state->transaction3->CommitPhaseTwo().ok()); |
| + EXPECT_EQ(0U, test->backing_store()->removals().size()); |
| + for (size_t i = 0; i < state->read_result_value.blob_info.size(); |
| + ++i) { |
| + state->read_result_value.blob_info[i].release_callback().Run( |
| + state->read_result_value.blob_info[i].file_path()); |
| + } |
| + }, |
| + base::Unretained(this), base::Unretained(&state))); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, base::BindOnce( |
| + [](IndexedDBBackingStoreTestWithBlobs* test) { |
| + EXPECT_NE(0U, test->backing_store()->removals().size()); |
| + EXPECT_TRUE(test->CheckBlobRemovals()); |
| + }, |
| + base::Unretained(this))); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| } |
| // Make sure that using very high ( more than 32 bit ) values for database_id |
| // and object_store_id still work. |
| TEST_F(IndexedDBBackingStoreTest, HighIds) { |
| - const int64_t high_database_id = 1ULL << 35; |
| - const int64_t high_object_store_id = 1ULL << 39; |
| - // index_ids are capped at 32 bits for storage purposes. |
| - const int64_t high_index_id = 1ULL << 29; |
| - |
| - const int64_t invalid_high_index_id = 1ULL << 37; |
| - |
| - const IndexedDBKey& index_key = key2_; |
| - std::string index_key_raw; |
| - EncodeIDBKey(index_key, &index_key_raw); |
| - { |
| - IndexedDBBackingStore::Transaction transaction1(backing_store_.get()); |
| - transaction1.Begin(); |
| - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; |
| - IndexedDBBackingStore::RecordIdentifier record; |
| - leveldb::Status s = backing_store_->PutRecord( |
| - &transaction1, high_database_id, high_object_store_id, key1_, &value1_, |
| - &handles, &record); |
| - EXPECT_TRUE(s.ok()); |
| - |
| - s = backing_store_->PutIndexDataForRecord(&transaction1, |
| - high_database_id, |
| - high_object_store_id, |
| - invalid_high_index_id, |
| - index_key, |
| - record); |
| - EXPECT_FALSE(s.ok()); |
| - |
| - s = backing_store_->PutIndexDataForRecord(&transaction1, |
| - high_database_id, |
| - high_object_store_id, |
| - high_index_id, |
| - index_key, |
| - record); |
| - EXPECT_TRUE(s.ok()); |
| - |
| - scoped_refptr<TestCallback> callback(new TestCallback()); |
| - s = transaction1.CommitPhaseOne(callback); |
| - EXPECT_TRUE(s.ok()); |
| - EXPECT_TRUE(callback->called); |
| - EXPECT_TRUE(callback->succeeded); |
| - s = transaction1.CommitPhaseTwo(); |
| - EXPECT_TRUE(s.ok()); |
| - } |
| - |
| - { |
| - IndexedDBBackingStore::Transaction transaction2(backing_store_.get()); |
| - transaction2.Begin(); |
| - IndexedDBValue result_value; |
| - leveldb::Status s = |
| - backing_store_->GetRecord(&transaction2, high_database_id, |
| - high_object_store_id, key1_, &result_value); |
| - EXPECT_TRUE(s.ok()); |
| - EXPECT_EQ(value1_.bits, result_value.bits); |
| - |
| - std::unique_ptr<IndexedDBKey> new_primary_key; |
| - s = backing_store_->GetPrimaryKeyViaIndex(&transaction2, |
| - high_database_id, |
| - high_object_store_id, |
| - invalid_high_index_id, |
| - index_key, |
| - &new_primary_key); |
| - EXPECT_FALSE(s.ok()); |
| - |
| - s = backing_store_->GetPrimaryKeyViaIndex(&transaction2, |
| - high_database_id, |
| - high_object_store_id, |
| - high_index_id, |
| - index_key, |
| - &new_primary_key); |
| - EXPECT_TRUE(s.ok()); |
| - EXPECT_TRUE(new_primary_key->Equals(key1_)); |
| - |
| - scoped_refptr<TestCallback> callback(new TestCallback()); |
| - s = transaction2.CommitPhaseOne(callback); |
| - EXPECT_TRUE(s.ok()); |
| - EXPECT_TRUE(callback->called); |
| - EXPECT_TRUE(callback->succeeded); |
| - s = transaction2.CommitPhaseTwo(); |
| - EXPECT_TRUE(s.ok()); |
| - } |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](IndexedDBBackingStore* backing_store, IndexedDBKey key1, |
| + IndexedDBKey key2, IndexedDBValue value1) { |
| + const int64_t high_database_id = 1ULL << 35; |
| + const int64_t high_object_store_id = 1ULL << 39; |
| + // index_ids are capped at 32 bits for storage purposes. |
| + const int64_t high_index_id = 1ULL << 29; |
| + |
| + const int64_t invalid_high_index_id = 1ULL << 37; |
| + |
| + const IndexedDBKey& index_key = key2; |
| + std::string index_key_raw; |
| + EncodeIDBKey(index_key, &index_key_raw); |
| + { |
| + IndexedDBBackingStore::Transaction transaction1(backing_store); |
| + transaction1.Begin(); |
| + std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; |
| + IndexedDBBackingStore::RecordIdentifier record; |
| + leveldb::Status s = backing_store->PutRecord( |
| + &transaction1, high_database_id, high_object_store_id, key1, |
| + &value1, &handles, &record); |
| + EXPECT_TRUE(s.ok()); |
| + |
| + s = backing_store->PutIndexDataForRecord( |
| + &transaction1, high_database_id, high_object_store_id, |
| + invalid_high_index_id, index_key, record); |
| + EXPECT_FALSE(s.ok()); |
| + |
| + s = backing_store->PutIndexDataForRecord( |
| + &transaction1, high_database_id, high_object_store_id, |
| + high_index_id, index_key, record); |
| + EXPECT_TRUE(s.ok()); |
| + |
| + scoped_refptr<TestCallback> callback( |
| + base::MakeRefCounted<TestCallback>()); |
| + EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok()); |
| + EXPECT_TRUE(callback->called); |
| + EXPECT_TRUE(callback->succeeded); |
| + EXPECT_TRUE(transaction1.CommitPhaseTwo().ok()); |
| + } |
| + |
| + { |
| + IndexedDBBackingStore::Transaction transaction2(backing_store); |
| + transaction2.Begin(); |
| + IndexedDBValue result_value; |
| + leveldb::Status s = backing_store->GetRecord( |
| + &transaction2, high_database_id, high_object_store_id, key1, |
| + &result_value); |
| + EXPECT_TRUE(s.ok()); |
| + EXPECT_EQ(value1.bits, result_value.bits); |
| + |
| + std::unique_ptr<IndexedDBKey> new_primary_key; |
| + s = backing_store->GetPrimaryKeyViaIndex( |
| + &transaction2, high_database_id, high_object_store_id, |
| + invalid_high_index_id, index_key, &new_primary_key); |
| + EXPECT_FALSE(s.ok()); |
| + |
| + s = backing_store->GetPrimaryKeyViaIndex( |
| + &transaction2, high_database_id, high_object_store_id, |
| + high_index_id, index_key, &new_primary_key); |
| + EXPECT_TRUE(s.ok()); |
| + EXPECT_TRUE(new_primary_key->Equals(key1)); |
| + |
| + scoped_refptr<TestCallback> callback( |
| + base::MakeRefCounted<TestCallback>()); |
| + EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok()); |
| + EXPECT_TRUE(callback->called); |
| + EXPECT_TRUE(callback->succeeded); |
| + EXPECT_TRUE(transaction2.CommitPhaseTwo().ok()); |
| + } |
| + }, |
| + base::Unretained(backing_store()), key1_, key2_, value1_)); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| } |
| // Make sure that other invalid ids do not crash. |
| TEST_F(IndexedDBBackingStoreTest, InvalidIds) { |
| - // valid ids for use when testing invalid ids |
| - const int64_t database_id = 1; |
| - const int64_t object_store_id = 1; |
| - const int64_t index_id = kMinimumIndexId; |
| - const int64_t invalid_low_index_id = |
| - 19; // index_ids must be > kMinimumIndexId |
| - |
| - IndexedDBValue result_value; |
| - |
| - IndexedDBBackingStore::Transaction transaction1(backing_store_.get()); |
| - transaction1.Begin(); |
| - |
| - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; |
| - IndexedDBBackingStore::RecordIdentifier record; |
| - leveldb::Status s = backing_store_->PutRecord(&transaction1, database_id, |
| - KeyPrefix::kInvalidId, key1_, |
| - &value1_, &handles, &record); |
| - EXPECT_FALSE(s.ok()); |
| - s = backing_store_->PutRecord(&transaction1, database_id, 0, key1_, &value1_, |
| - &handles, &record); |
| - EXPECT_FALSE(s.ok()); |
| - s = backing_store_->PutRecord(&transaction1, KeyPrefix::kInvalidId, |
| - object_store_id, key1_, &value1_, &handles, |
| - &record); |
| - EXPECT_FALSE(s.ok()); |
| - s = backing_store_->PutRecord(&transaction1, 0, object_store_id, key1_, |
| - &value1_, &handles, &record); |
| - EXPECT_FALSE(s.ok()); |
| - |
| - s = backing_store_->GetRecord(&transaction1, database_id, |
| - KeyPrefix::kInvalidId, key1_, &result_value); |
| - EXPECT_FALSE(s.ok()); |
| - s = backing_store_->GetRecord(&transaction1, database_id, 0, key1_, |
| - &result_value); |
| - EXPECT_FALSE(s.ok()); |
| - s = backing_store_->GetRecord(&transaction1, KeyPrefix::kInvalidId, |
| - object_store_id, key1_, &result_value); |
| - EXPECT_FALSE(s.ok()); |
| - s = backing_store_->GetRecord(&transaction1, 0, object_store_id, key1_, |
| - &result_value); |
| - EXPECT_FALSE(s.ok()); |
| - |
| - std::unique_ptr<IndexedDBKey> new_primary_key; |
| - s = backing_store_->GetPrimaryKeyViaIndex( |
| - &transaction1, database_id, object_store_id, KeyPrefix::kInvalidId, key1_, |
| - &new_primary_key); |
| - EXPECT_FALSE(s.ok()); |
| - s = backing_store_->GetPrimaryKeyViaIndex( |
| - &transaction1, database_id, object_store_id, invalid_low_index_id, key1_, |
| - &new_primary_key); |
| - EXPECT_FALSE(s.ok()); |
| - s = backing_store_->GetPrimaryKeyViaIndex( |
| - &transaction1, database_id, object_store_id, 0, key1_, &new_primary_key); |
| - EXPECT_FALSE(s.ok()); |
| - |
| - s = backing_store_->GetPrimaryKeyViaIndex( |
| - &transaction1, KeyPrefix::kInvalidId, object_store_id, index_id, key1_, |
| - &new_primary_key); |
| - EXPECT_FALSE(s.ok()); |
| - s = backing_store_->GetPrimaryKeyViaIndex(&transaction1, database_id, |
| - KeyPrefix::kInvalidId, index_id, |
| - key1_, &new_primary_key); |
| - EXPECT_FALSE(s.ok()); |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](IndexedDBBackingStore* backing_store, IndexedDBKey key, |
| + IndexedDBValue value) { |
| + // valid ids for use when testing invalid ids |
| + const int64_t database_id = 1; |
| + const int64_t object_store_id = 1; |
| + const int64_t index_id = kMinimumIndexId; |
| + // index_ids must be > kMinimumIndexId |
| + const int64_t invalid_low_index_id = 19; |
| + IndexedDBValue result_value; |
| + |
| + IndexedDBBackingStore::Transaction transaction1(backing_store); |
| + transaction1.Begin(); |
| + |
| + std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; |
| + IndexedDBBackingStore::RecordIdentifier record; |
| + leveldb::Status s = backing_store->PutRecord( |
| + &transaction1, database_id, KeyPrefix::kInvalidId, key, &value, |
| + &handles, &record); |
| + EXPECT_FALSE(s.ok()); |
| + s = backing_store->PutRecord(&transaction1, database_id, 0, key, |
| + &value, &handles, &record); |
| + EXPECT_FALSE(s.ok()); |
| + s = backing_store->PutRecord(&transaction1, KeyPrefix::kInvalidId, |
| + object_store_id, key, &value, &handles, |
| + &record); |
| + EXPECT_FALSE(s.ok()); |
| + s = backing_store->PutRecord(&transaction1, 0, object_store_id, key, |
| + &value, &handles, &record); |
| + EXPECT_FALSE(s.ok()); |
| + |
| + s = backing_store->GetRecord(&transaction1, database_id, |
| + KeyPrefix::kInvalidId, key, |
| + &result_value); |
| + EXPECT_FALSE(s.ok()); |
| + s = backing_store->GetRecord(&transaction1, database_id, 0, key, |
| + &result_value); |
| + EXPECT_FALSE(s.ok()); |
| + s = backing_store->GetRecord(&transaction1, KeyPrefix::kInvalidId, |
| + object_store_id, key, &result_value); |
| + EXPECT_FALSE(s.ok()); |
| + s = backing_store->GetRecord(&transaction1, 0, object_store_id, key, |
| + &result_value); |
| + EXPECT_FALSE(s.ok()); |
| + |
| + std::unique_ptr<IndexedDBKey> new_primary_key; |
| + s = backing_store->GetPrimaryKeyViaIndex( |
| + &transaction1, database_id, object_store_id, |
| + KeyPrefix::kInvalidId, key, &new_primary_key); |
| + EXPECT_FALSE(s.ok()); |
| + s = backing_store->GetPrimaryKeyViaIndex( |
| + &transaction1, database_id, object_store_id, |
| + invalid_low_index_id, key, &new_primary_key); |
| + EXPECT_FALSE(s.ok()); |
| + s = backing_store->GetPrimaryKeyViaIndex(&transaction1, database_id, |
| + object_store_id, 0, key, |
| + &new_primary_key); |
| + EXPECT_FALSE(s.ok()); |
| + |
| + s = backing_store->GetPrimaryKeyViaIndex( |
| + &transaction1, KeyPrefix::kInvalidId, object_store_id, index_id, |
| + key, &new_primary_key); |
| + EXPECT_FALSE(s.ok()); |
| + s = backing_store->GetPrimaryKeyViaIndex( |
| + &transaction1, database_id, KeyPrefix::kInvalidId, index_id, |
| + key, &new_primary_key); |
| + EXPECT_FALSE(s.ok()); |
| + }, |
| + base::Unretained(backing_store()), key1_, value1_)); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| } |
| TEST_F(IndexedDBBackingStoreTest, CreateDatabase) { |
| - const base::string16 database_name(ASCIIToUTF16("db1")); |
| - int64_t database_id; |
| - const int64_t version = 9; |
| - |
| - const int64_t object_store_id = 99; |
| - const base::string16 object_store_name(ASCIIToUTF16("object_store1")); |
| - const bool auto_increment = true; |
| - const IndexedDBKeyPath object_store_key_path( |
| - ASCIIToUTF16("object_store_key")); |
| - |
| - const int64_t index_id = 999; |
| - const base::string16 index_name(ASCIIToUTF16("index1")); |
| - const bool unique = true; |
| - const bool multi_entry = true; |
| - const IndexedDBKeyPath index_key_path(ASCIIToUTF16("index_key")); |
| - |
| - { |
| - leveldb::Status s = backing_store_->CreateIDBDatabaseMetaData( |
| - database_name, version, &database_id); |
| - EXPECT_TRUE(s.ok()); |
| - EXPECT_GT(database_id, 0); |
| - |
| - IndexedDBBackingStore::Transaction transaction(backing_store_.get()); |
| - transaction.Begin(); |
| - |
| - s = backing_store_->CreateObjectStore(&transaction, |
| - database_id, |
| - object_store_id, |
| - object_store_name, |
| - object_store_key_path, |
| - auto_increment); |
| - EXPECT_TRUE(s.ok()); |
| - |
| - s = backing_store_->CreateIndex(&transaction, |
| - database_id, |
| - object_store_id, |
| - index_id, |
| - index_name, |
| - index_key_path, |
| - unique, |
| - multi_entry); |
| - EXPECT_TRUE(s.ok()); |
| - |
| - scoped_refptr<TestCallback> callback(new TestCallback()); |
| - s = transaction.CommitPhaseOne(callback); |
| - EXPECT_TRUE(s.ok()); |
| - EXPECT_TRUE(callback->called); |
| - EXPECT_TRUE(callback->succeeded); |
| - s = transaction.CommitPhaseTwo(); |
| - EXPECT_TRUE(s.ok()); |
| - } |
| - |
| - { |
| - IndexedDBDatabaseMetadata database; |
| - bool found; |
| - leveldb::Status s = backing_store_->GetIDBDatabaseMetaData( |
| - database_name, &database, &found); |
| - EXPECT_TRUE(s.ok()); |
| - EXPECT_TRUE(found); |
| - |
| - // database.name is not filled in by the implementation. |
| - EXPECT_EQ(version, database.version); |
| - EXPECT_EQ(database_id, database.id); |
| - |
| - s = backing_store_->GetObjectStores(database.id, &database.object_stores); |
| - EXPECT_TRUE(s.ok()); |
| - |
| - EXPECT_EQ(1UL, database.object_stores.size()); |
| - IndexedDBObjectStoreMetadata object_store = |
| - database.object_stores[object_store_id]; |
| - EXPECT_EQ(object_store_name, object_store.name); |
| - EXPECT_EQ(object_store_key_path, object_store.key_path); |
| - EXPECT_EQ(auto_increment, object_store.auto_increment); |
| - |
| - EXPECT_EQ(1UL, object_store.indexes.size()); |
| - IndexedDBIndexMetadata index = object_store.indexes[index_id]; |
| - EXPECT_EQ(index_name, index.name); |
| - EXPECT_EQ(index_key_path, index.key_path); |
| - EXPECT_EQ(unique, index.unique); |
| - EXPECT_EQ(multi_entry, index.multi_entry); |
| - } |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce( |
| + [](IndexedDBBackingStore* backing_store) { |
| + const base::string16 database_name(ASCIIToUTF16("db1")); |
| + int64_t database_id; |
| + const int64_t version = 9; |
| + |
| + const int64_t object_store_id = 99; |
| + const base::string16 object_store_name( |
| + ASCIIToUTF16("object_store1")); |
| + const bool auto_increment = true; |
| + const IndexedDBKeyPath object_store_key_path( |
| + ASCIIToUTF16("object_store_key")); |
| + |
| + const int64_t index_id = 999; |
| + const base::string16 index_name(ASCIIToUTF16("index1")); |
| + const bool unique = true; |
| + const bool multi_entry = true; |
| + const IndexedDBKeyPath index_key_path(ASCIIToUTF16("index_key")); |
| + |
| + { |
| + leveldb::Status s = backing_store->CreateIDBDatabaseMetaData( |
| + database_name, version, &database_id); |
| + EXPECT_TRUE(s.ok()); |
| + EXPECT_GT(database_id, 0); |
| + |
| + IndexedDBBackingStore::Transaction transaction(backing_store); |
| + transaction.Begin(); |
| + |
| + s = backing_store->CreateObjectStore( |
| + &transaction, database_id, object_store_id, object_store_name, |
| + object_store_key_path, auto_increment); |
| + EXPECT_TRUE(s.ok()); |
| + |
| + s = backing_store->CreateIndex( |
| + &transaction, database_id, object_store_id, index_id, |
| + index_name, index_key_path, unique, multi_entry); |
| + EXPECT_TRUE(s.ok()); |
| + |
| + scoped_refptr<TestCallback> callback( |
| + base::MakeRefCounted<TestCallback>()); |
| + EXPECT_TRUE(transaction.CommitPhaseOne(callback).ok()); |
| + EXPECT_TRUE(callback->called); |
| + EXPECT_TRUE(callback->succeeded); |
| + EXPECT_TRUE(transaction.CommitPhaseTwo().ok()); |
| + } |
| + |
| + { |
| + IndexedDBDatabaseMetadata database; |
| + bool found; |
| + leveldb::Status s = backing_store->GetIDBDatabaseMetaData( |
| + database_name, &database, &found); |
| + EXPECT_TRUE(s.ok()); |
| + EXPECT_TRUE(found); |
| + |
| + // database.name is not filled in by the implementation. |
| + EXPECT_EQ(version, database.version); |
| + EXPECT_EQ(database_id, database.id); |
| + |
| + s = backing_store->GetObjectStores(database.id, |
| + &database.object_stores); |
| + EXPECT_TRUE(s.ok()); |
| + |
| + EXPECT_EQ(1UL, database.object_stores.size()); |
| + IndexedDBObjectStoreMetadata object_store = |
| + database.object_stores[object_store_id]; |
| + EXPECT_EQ(object_store_name, object_store.name); |
| + EXPECT_EQ(object_store_key_path, object_store.key_path); |
| + EXPECT_EQ(auto_increment, object_store.auto_increment); |
| + |
| + EXPECT_EQ(1UL, object_store.indexes.size()); |
| + IndexedDBIndexMetadata index = object_store.indexes[index_id]; |
| + EXPECT_EQ(index_name, index.name); |
| + EXPECT_EQ(index_key_path, index.key_path); |
| + EXPECT_EQ(unique, index.unique); |
| + EXPECT_EQ(multi_entry, index.multi_entry); |
| + } |
| + }, |
| + base::Unretained(backing_store()))); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| } |
| TEST_F(IndexedDBBackingStoreTest, GetDatabaseNames) { |
| - const base::string16 db1_name(ASCIIToUTF16("db1")); |
| - const int64_t db1_version = 1LL; |
| - int64_t db1_id; |
| - |
| - // Database records with DEFAULT_VERSION represent stale data, |
| - // and should not be enumerated. |
| - const base::string16 db2_name(ASCIIToUTF16("db2")); |
| - const int64_t db2_version = IndexedDBDatabaseMetadata::DEFAULT_VERSION; |
| - int64_t db2_id; |
| - |
| - leveldb::Status s = |
| - backing_store_->CreateIDBDatabaseMetaData(db1_name, db1_version, &db1_id); |
| - EXPECT_TRUE(s.ok()); |
| - EXPECT_GT(db1_id, 0LL); |
| - |
| - s = backing_store_->CreateIDBDatabaseMetaData(db2_name, db2_version, &db2_id); |
| - EXPECT_TRUE(s.ok()); |
| - EXPECT_GT(db2_id, db1_id); |
| - |
| - std::vector<base::string16> names = backing_store_->GetDatabaseNames(&s); |
| - EXPECT_TRUE(s.ok()); |
| - ASSERT_EQ(1U, names.size()); |
| - EXPECT_EQ(db1_name, names[0]); |
| + idb_context_->TaskRunner()->PostTask( |
| + FROM_HERE, base::BindOnce( |
| + [](IndexedDBBackingStore* backing_store) { |
| + const base::string16 db1_name(ASCIIToUTF16("db1")); |
| + const int64_t db1_version = 1LL; |
| + int64_t db1_id; |
| + |
| + // Database records with DEFAULT_VERSION represent |
| + // stale data, and should not be enumerated. |
| + const base::string16 db2_name(ASCIIToUTF16("db2")); |
| + const int64_t db2_version = |
| + IndexedDBDatabaseMetadata::DEFAULT_VERSION; |
| + int64_t db2_id; |
| + |
| + leveldb::Status s = |
| + backing_store->CreateIDBDatabaseMetaData( |
| + db1_name, db1_version, &db1_id); |
| + EXPECT_TRUE(s.ok()); |
| + EXPECT_GT(db1_id, 0LL); |
| + |
| + s = backing_store->CreateIDBDatabaseMetaData( |
| + db2_name, db2_version, &db2_id); |
| + EXPECT_TRUE(s.ok()); |
| + EXPECT_GT(db2_id, db1_id); |
| + |
| + std::vector<base::string16> names = |
| + backing_store->GetDatabaseNames(&s); |
| + EXPECT_TRUE(s.ok()); |
| + ASSERT_EQ(1U, names.size()); |
| + EXPECT_EQ(db1_name, names[0]); |
| + }, |
| + base::Unretained(backing_store()))); |
| + RunAllBlockingPoolTasksUntilIdle(); |
| } |
| } // namespace |