Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(407)

Unified Diff: content/browser/indexed_db/indexed_db_database_unittest.cc

Issue 277583002: IndexedDB: Prevent store/index deletion from racing ahead of use (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: base::Closure copies const-refs, so this is better Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/indexed_db/indexed_db_database_unittest.cc
diff --git a/content/browser/indexed_db/indexed_db_database_unittest.cc b/content/browser/indexed_db/indexed_db_database_unittest.cc
index 7feed8201d7ac179ded65f9390f22d8b21885a45..c5f3a13aaceec2b316d3f8a43395e335bae33070 100644
--- a/content/browser/indexed_db/indexed_db_database_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -6,6 +6,7 @@
#include "base/auto_reset.h"
#include "base/logging.h"
+#include "base/run_loop.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/indexed_db/indexed_db.h"
@@ -17,6 +18,7 @@
#include "content/browser/indexed_db/indexed_db_factory.h"
#include "content/browser/indexed_db/indexed_db_fake_backing_store.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
+#include "content/browser/indexed_db/indexed_db_value.h"
#include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -24,7 +26,7 @@
using base::ASCIIToUTF16;
namespace {
-const int FAKE_CHILD_PROCESS_ID = 0;
+const int kFakeChildProcessId = 0;
}
namespace content {
@@ -71,7 +73,7 @@ TEST(IndexedDBDatabaseTest, ConnectionLifecycle) {
IndexedDBPendingConnection connection1(
request1,
callbacks1,
- FAKE_CHILD_PROCESS_ID,
+ kFakeChildProcessId,
transaction_id1,
IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
db->OpenConnection(connection1);
@@ -85,7 +87,7 @@ TEST(IndexedDBDatabaseTest, ConnectionLifecycle) {
IndexedDBPendingConnection connection2(
request2,
callbacks2,
- FAKE_CHILD_PROCESS_ID,
+ kFakeChildProcessId,
transaction_id2,
IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
db->OpenConnection(connection2);
@@ -129,7 +131,7 @@ TEST(IndexedDBDatabaseTest, ForcedClose) {
IndexedDBPendingConnection connection(
request,
callbacks,
- FAKE_CHILD_PROCESS_ID,
+ kFakeChildProcessId,
upgrade_transaction_id,
IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
database->OpenConnection(connection);
@@ -193,7 +195,7 @@ TEST(IndexedDBDatabaseTest, PendingDelete) {
IndexedDBPendingConnection connection(
request1,
callbacks1,
- FAKE_CHILD_PROCESS_ID,
+ kFakeChildProcessId,
transaction_id1,
IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
db->OpenConnection(connection);
@@ -213,4 +215,191 @@ TEST(IndexedDBDatabaseTest, PendingDelete) {
EXPECT_TRUE(request2->success_called());
}
+void DummyOperation(IndexedDBTransaction* transaction) {
+}
+
+class IndexedDBDatabaseOperationTest : public testing::Test {
+ public:
+ IndexedDBDatabaseOperationTest() : commit_success_(true) {}
+
+ virtual void SetUp() {
+ backing_store_ = new IndexedDBFakeBackingStore();
+ leveldb::Status s;
+ db_ = IndexedDBDatabase::Create(ASCIIToUTF16("db"),
+ backing_store_,
+ NULL /*factory*/,
+ IndexedDBDatabase::Identifier(),
+ &s);
+ ASSERT_TRUE(s.ok());
+
+ request_ = new MockIndexedDBCallbacks();
+ callbacks_ = new MockIndexedDBDatabaseCallbacks();
+ const int64 transaction_id = 1;
+ db_->OpenConnection(IndexedDBPendingConnection(
+ request_,
+ callbacks_,
+ kFakeChildProcessId,
+ transaction_id,
+ IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION));
+ EXPECT_EQ(IndexedDBDatabaseMetadata::NO_INT_VERSION,
+ db_->metadata().int_version);
+
+ transaction_ = new IndexedDBTransaction(
+ transaction_id,
+ callbacks_,
+ std::set<int64>() /*scope*/,
+ indexed_db::TRANSACTION_VERSION_CHANGE,
+ db_,
+ new IndexedDBFakeBackingStore::FakeTransaction(commit_success_));
+ db_->TransactionCreated(transaction_);
+
+ // Add a dummy task which takes the place of the VersionChangeOperation
+ // which kicks off the upgrade. This ensures that the transaction has
+ // processed at least one task before the CreateObjectStore call.
+ transaction_->ScheduleTask(base::Bind(&DummyOperation));
+ }
+
+ void RunPostedTasks() { base::RunLoop().RunUntilIdle(); }
+
+ protected:
+ scoped_refptr<IndexedDBFakeBackingStore> backing_store_;
+ scoped_refptr<IndexedDBDatabase> db_;
+ scoped_refptr<MockIndexedDBCallbacks> request_;
+ scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks_;
+ scoped_refptr<IndexedDBTransaction> transaction_;
+
+ bool commit_success_;
+
+ private:
+ base::MessageLoop message_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseOperationTest);
+};
+
+TEST_F(IndexedDBDatabaseOperationTest, CreateObjectStore) {
+ EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
+ const int64 store_id = 1001;
+ db_->CreateObjectStore(transaction_->id(),
+ store_id,
+ ASCIIToUTF16("store"),
+ IndexedDBKeyPath(),
+ false /*auto_increment*/);
+ EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
+ RunPostedTasks();
+ transaction_->Commit();
+ EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
+}
+
+TEST_F(IndexedDBDatabaseOperationTest, CreateIndex) {
+ EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
+ const int64 store_id = 1001;
+ db_->CreateObjectStore(transaction_->id(),
+ store_id,
+ ASCIIToUTF16("store"),
+ IndexedDBKeyPath(),
+ false /*auto_increment*/);
+ EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
+ const int64 index_id = 2002;
+ db_->CreateIndex(transaction_->id(),
+ store_id,
+ index_id,
+ ASCIIToUTF16("index"),
+ IndexedDBKeyPath(),
+ false /*unique*/,
+ false /*multi_entry*/);
+ EXPECT_EQ(
+ 1ULL,
+ db_->metadata().object_stores.find(store_id)->second.indexes.size());
+ RunPostedTasks();
+ transaction_->Commit();
+ EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
+ EXPECT_EQ(
+ 1ULL,
+ db_->metadata().object_stores.find(store_id)->second.indexes.size());
+}
+
+class IndexedDBDatabaseOperationAbortTest
+ : public IndexedDBDatabaseOperationTest {
+ public:
+ IndexedDBDatabaseOperationAbortTest() { commit_success_ = false; }
+};
+
+TEST_F(IndexedDBDatabaseOperationAbortTest, CreateObjectStore) {
+ EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
+ const int64 store_id = 1001;
+ db_->CreateObjectStore(transaction_->id(),
+ store_id,
+ ASCIIToUTF16("store"),
+ IndexedDBKeyPath(),
+ false /*auto_increment*/);
+ EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
+ RunPostedTasks();
+ transaction_->Commit();
+ EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
+}
+
+TEST_F(IndexedDBDatabaseOperationAbortTest, CreateIndex) {
+ EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
+ const int64 store_id = 1001;
+ db_->CreateObjectStore(transaction_->id(),
+ store_id,
+ ASCIIToUTF16("store"),
+ IndexedDBKeyPath(),
+ false /*auto_increment*/);
+ EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
+ const int64 index_id = 2002;
+ db_->CreateIndex(transaction_->id(),
+ store_id,
+ index_id,
+ ASCIIToUTF16("index"),
+ IndexedDBKeyPath(),
+ false /*unique*/,
+ false /*multi_entry*/);
+ EXPECT_EQ(
+ 1ULL,
+ db_->metadata().object_stores.find(store_id)->second.indexes.size());
+ RunPostedTasks();
+ transaction_->Commit();
+ EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
+}
+
+TEST_F(IndexedDBDatabaseOperationTest, CreatePutDelete) {
+ EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
+ const int64 store_id = 1001;
+
+ // Creation is synchronous.
+ db_->CreateObjectStore(transaction_->id(),
+ store_id,
+ ASCIIToUTF16("store"),
+ IndexedDBKeyPath(),
+ false /*auto_increment*/);
+ EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
+
+
+ // Put is asynchronous
+ IndexedDBValue value("value1", std::vector<IndexedDBBlobInfo>());
+ ScopedVector<webkit_blob::BlobDataHandle> handles;
+ scoped_ptr<IndexedDBKey> key(new IndexedDBKey("key"));
+ std::vector<IndexedDBDatabase::IndexKeys> index_keys;
+ scoped_refptr<MockIndexedDBCallbacks> request(
+ new MockIndexedDBCallbacks(false));
+ db_->Put(transaction_->id(),
+ store_id,
+ &value,
+ &handles,
+ key.Pass(),
+ IndexedDBDatabase::ADD_ONLY,
+ request,
+ index_keys);
+
+ // Deletion is asynchronous.
+ db_->DeleteObjectStore(transaction_->id(),
+ store_id);
+ EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
+
+ // This will execute the Put then Delete.
+ RunPostedTasks();
+ EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698