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

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

Issue 18023022: Blob support for IDB [Chromium] (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merged out--bot failed due to staleness. 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_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 8d7307744a4db821ada95e4cade89899fbd45914..bdbf077b573bbb799f857d069413a8e7947cdfa5 100644
--- a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
@@ -4,13 +4,24 @@
#include "content/browser/indexed_db/indexed_db_backing_store.h"
+#include "base/callback.h"
+#include "base/file_util.h"
+#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
+#include "base/macros.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task_runner.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_leveldb_coding.h"
#include "content/browser/indexed_db/indexed_db_value.h"
+#include "content/public/test/mock_special_storage_policy.h"
+#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebIDBTypes.h"
+#include "webkit/browser/blob/blob_data_handle.h"
+#include "webkit/browser/quota/special_storage_policy.h"
using base::ASCIIToUTF16;
@@ -18,35 +29,322 @@ namespace content {
namespace {
+class Comparator : public LevelDBComparator {
+ public:
+ virtual int Compare(const base::StringPiece& a,
+ const base::StringPiece& b) const OVERRIDE {
+ return content::Compare(a, b, false /*index_keys*/);
+ }
+ virtual const char* Name() const OVERRIDE { return "idb_cmp1"; }
+};
+
+class DefaultLevelDBFactory : public LevelDBFactory {
+ public:
+ virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
+ const LevelDBComparator* comparator,
+ scoped_ptr<LevelDBDatabase>* db,
+ bool* is_disk_full) OVERRIDE {
+ return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full);
+ }
+ virtual leveldb::Status DestroyLevelDB(
+ const base::FilePath& file_name) OVERRIDE {
+ return LevelDBDatabase::Destroy(file_name);
+ }
+};
+
+class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
+ public:
+ static scoped_refptr<TestableIndexedDBBackingStore> Open(
+ IndexedDBFactory* indexed_db_factory,
+ const GURL& origin_url,
+ const base::FilePath& path_base,
+ net::URLRequestContext* request_context,
+ LevelDBFactory* leveldb_factory,
+ base::TaskRunner* task_runner) {
+ DCHECK(!path_base.empty());
+
+ scoped_ptr<LevelDBComparator> comparator(new Comparator());
+
+ if (!base::CreateDirectory(path_base))
+ return scoped_refptr<TestableIndexedDBBackingStore>();
+
+ const base::FilePath file_path = path_base.AppendASCII("test_db_path");
+ const base::FilePath blob_path = path_base.AppendASCII("test_blob_path");
+
+ scoped_ptr<LevelDBDatabase> db;
+ bool is_disk_full = false;
+ leveldb::Status status = leveldb_factory->OpenLevelDB(
+ file_path, comparator.get(), &db, &is_disk_full);
+
+ if (!db || !status.ok())
+ return scoped_refptr<TestableIndexedDBBackingStore>();
+
+ scoped_refptr<TestableIndexedDBBackingStore> backing_store(
+ new TestableIndexedDBBackingStore(indexed_db_factory,
+ origin_url,
+ blob_path,
+ request_context,
+ db.Pass(),
+ comparator.Pass(),
+ task_runner));
+
+ if (!backing_store->SetUpMetadata())
+ return scoped_refptr<TestableIndexedDBBackingStore>();
+
+ return backing_store;
+ }
+
+ const std::vector<IndexedDBBackingStore::Transaction::WriteDescriptor>&
+ writes() const {
+ return writes_;
+ }
+ void ClearWrites() { writes_.clear(); }
+ const std::vector<int64>& removals() const { return removals_; }
+ void ClearRemovals() { removals_.clear(); }
+
+ protected:
+ virtual ~TestableIndexedDBBackingStore() {}
+
+ virtual bool WriteBlobFile(
+ int64 database_id,
+ const Transaction::WriteDescriptor& descriptor,
+ Transaction::ChainedBlobWriter* chained_blob_writer) OVERRIDE {
+ if (KeyPrefix::IsValidDatabaseId(database_id_)) {
+ if (database_id_ != database_id) {
+ return false;
+ }
+ } else {
+ database_id_ = database_id;
+ }
+ writes_.push_back(descriptor);
+ task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&Transaction::ChainedBlobWriter::ReportWriteCompletion,
+ chained_blob_writer,
+ true,
+ 1));
+ return true;
+ }
+
+ virtual bool RemoveBlobFile(int64 database_id, int64 key) OVERRIDE {
+ if (database_id_ != database_id ||
+ !KeyPrefix::IsValidDatabaseId(database_id)) {
+ return false;
+ }
+ removals_.push_back(key);
+ return true;
+ }
+
+ // Timers don't play nicely with unit tests.
+ virtual void StartJournalCleaningTimer() OVERRIDE {
+ CleanPrimaryJournalIgnoreReturn();
+ }
+
+ private:
+ TestableIndexedDBBackingStore(IndexedDBFactory* indexed_db_factory,
+ const GURL& origin_url,
+ const base::FilePath& blob_path,
+ net::URLRequestContext* request_context,
+ scoped_ptr<LevelDBDatabase> db,
+ scoped_ptr<LevelDBComparator> comparator,
+ base::TaskRunner* task_runner)
+ : IndexedDBBackingStore(indexed_db_factory,
+ origin_url,
+ blob_path,
+ request_context,
+ db.Pass(),
+ comparator.Pass(),
+ task_runner),
+ database_id_(0) {}
+
+ int64 database_id_;
+ std::vector<Transaction::WriteDescriptor> writes_;
+ std::vector<int64> removals_;
+};
+
+class TestIDBFactory : public IndexedDBFactory {
+ public:
+ TestIDBFactory(IndexedDBContextImpl* idb_context)
+ : IndexedDBFactory(idb_context) {}
+
+ scoped_refptr<TestableIndexedDBBackingStore> OpenBackingStoreForTest(
+ const GURL& origin,
+ net::URLRequestContext* url_request_context) {
+ blink::WebIDBDataLoss data_loss;
+ std::string data_loss_reason;
+ bool disk_full;
+ scoped_refptr<IndexedDBBackingStore> backing_store =
+ OpenBackingStore(origin,
+ context()->data_path(),
+ url_request_context,
+ &data_loss,
+ &data_loss_reason,
+ &disk_full);
+ scoped_refptr<TestableIndexedDBBackingStore> testable_store =
+ static_cast<TestableIndexedDBBackingStore*>(backing_store.get());
+ return testable_store;
+ }
+
+ protected:
+ virtual ~TestIDBFactory() {}
+
+ virtual scoped_refptr<IndexedDBBackingStore> OpenBackingStoreHelper(
+ const GURL& origin_url,
+ const base::FilePath& data_directory,
+ net::URLRequestContext* request_context,
+ blink::WebIDBDataLoss* data_loss,
+ std::string* data_loss_message,
+ bool* disk_full,
+ bool first_time) OVERRIDE {
+ DefaultLevelDBFactory leveldb_factory;
+ return TestableIndexedDBBackingStore::Open(this,
+ origin_url,
+ data_directory,
+ request_context,
+ &leveldb_factory,
+ context()->TaskRunner());
+ }
+};
+
class IndexedDBBackingStoreTest : public testing::Test {
public:
IndexedDBBackingStoreTest() {}
virtual void SetUp() {
const GURL origin("http://localhost:81");
+ task_runner_ = new base::TestSimpleTaskRunner();
+ special_storage_policy_ = new MockSpecialStoragePolicy();
+ special_storage_policy_->SetAllUnlimited(true);
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ idb_context_ = new IndexedDBContextImpl(
+ temp_dir_.path(), special_storage_policy_, NULL, task_runner_);
+ idb_factory_ = new TestIDBFactory(idb_context_);
backing_store_ =
- IndexedDBBackingStore::OpenInMemory(origin, NULL /* task_runner */);
+ idb_factory_->OpenBackingStoreForTest(origin, &url_request_context_);
// useful keys and values during tests
m_value1 = IndexedDBValue("value1", std::vector<IndexedDBBlobInfo>());
m_value2 = IndexedDBValue("value2", std::vector<IndexedDBBlobInfo>());
+ m_blob_info.push_back(
+ IndexedDBBlobInfo("uuid 3", base::UTF8ToUTF16("blob type"), 1));
+ m_blob_info.push_back(
+ IndexedDBBlobInfo("uuid 4",
+ base::FilePath(FILE_PATH_LITERAL("path/to/file")),
+ base::UTF8ToUTF16("file name"),
+ base::UTF8ToUTF16("file type")));
+ m_value3 = IndexedDBValue("value3", m_blob_info);
+
m_key1 = IndexedDBKey(99, blink::WebIDBKeyTypeNumber);
m_key2 = IndexedDBKey(ASCIIToUTF16("key2"));
+ m_key3 = IndexedDBKey(ASCIIToUTF16("key3"));
+ }
+
+ // 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 {
+ if (m_blob_info.size() != reads.size())
+ return false;
+ for (size_t i = 0; i < m_blob_info.size(); ++i) {
+ const IndexedDBBlobInfo& a = m_blob_info[i];
+ const IndexedDBBlobInfo& b = reads[i];
+ if (a.is_file() != b.is_file())
+ return false;
+ if (a.type() != b.type())
+ return false;
+ if (a.is_file()) {
+ if (a.file_name() != b.file_name())
+ return false;
+ } else {
+ if (a.size() != b.size())
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool CheckBlobReadsMatchWrites(
+ const std::vector<IndexedDBBlobInfo>& reads) const {
+ if (backing_store_->writes().size() != reads.size())
+ return false;
+ std::set<int64> ids;
+ for (size_t i = 0; i < backing_store_->writes().size(); ++i)
+ ids.insert(backing_store_->writes()[i].key());
+ if (ids.size() != backing_store_->writes().size())
+ return false;
+ for (size_t i = 0; i < reads.size(); ++i) {
+ if (ids.count(reads[i].key()) != 1)
+ return false;
+ }
+ return true;
+ }
+
+ bool CheckBlobWrites() const {
+ if (backing_store_->writes().size() != m_blob_info.size())
+ return false;
+ for (size_t i = 0; i < backing_store_->writes().size(); ++i) {
+ const IndexedDBBackingStore::Transaction::WriteDescriptor& desc =
+ backing_store_->writes()[i];
+ const IndexedDBBlobInfo& info = m_blob_info[i];
+ if (desc.is_file() != info.is_file())
+ return false;
+ if (desc.is_file()) {
+ if (desc.file_path() != info.file_path())
+ return false;
+ } else {
+ if (desc.url() != GURL("blob:uuid/" + info.uuid()))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool CheckBlobRemovals() const {
+ if (backing_store_->removals().size() != backing_store_->writes().size())
+ return false;
+ for (size_t i = 0; i < backing_store_->writes().size(); ++i) {
+ if (backing_store_->writes()[i].key() != backing_store_->removals()[i])
+ return false;
+ }
+ return true;
}
protected:
- scoped_refptr<IndexedDBBackingStore> backing_store_;
+ base::ScopedTempDir temp_dir_;
+ scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
+ scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
+ scoped_refptr<IndexedDBContextImpl> idb_context_;
+ scoped_refptr<TestIDBFactory> idb_factory_;
+ net::TestURLRequestContext url_request_context_;
+
+ scoped_refptr<TestableIndexedDBBackingStore> backing_store_;
// Sample keys and values that are consistent.
IndexedDBKey m_key1;
IndexedDBKey m_key2;
+ IndexedDBKey m_key3;
IndexedDBValue m_value1;
IndexedDBValue m_value2;
+ IndexedDBValue m_value3;
+ std::vector<IndexedDBBlobInfo> m_blob_info;
private:
DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest);
};
+class TestCallback : public IndexedDBBackingStore::BlobWriteCallback {
+ public:
+ TestCallback() : called(false), succeeded(false) {}
+ virtual void Run(bool succeeded_in) OVERRIDE {
+ called = true;
+ succeeded = succeeded_in;
+ }
+ bool called;
+ bool succeeded;
+
+ protected:
+ virtual ~TestCallback() {}
+};
+
TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
{
IndexedDBBackingStore::Transaction transaction1(backing_store_);
@@ -56,21 +354,330 @@ TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
leveldb::Status s = backing_store_->PutRecord(
&transaction1, 1, 1, m_key1, m_value1, &handles, &record);
EXPECT_TRUE(s.ok());
- transaction1.Commit();
+ 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_);
transaction2.Begin();
IndexedDBValue result_value;
- leveldb::Status s =
- backing_store_->GetRecord(&transaction2, 1, 1, m_key1, &result_value);
- transaction2.Commit();
- EXPECT_TRUE(s.ok());
+ EXPECT_TRUE(
+ backing_store_->GetRecord(&transaction2, 1, 1, m_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(m_value1.bits, result_value.bits);
}
}
+TEST_F(IndexedDBBackingStoreTest, PutGetConsistencyWithBlobs) {
+ {
+ IndexedDBBackingStore::Transaction transaction1(backing_store_);
+ transaction1.Begin();
+ ScopedVector<webkit_blob::BlobDataHandle> handles;
+ IndexedDBBackingStore::RecordIdentifier record;
+ EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
+ 1,
+ 1,
+ m_key3,
+ m_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_);
+ transaction2.Begin();
+ IndexedDBValue result_value;
+ EXPECT_TRUE(
+ backing_store_->GetRecord(&transaction2, 1, 1, m_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(m_value3.bits, result_value.bits);
+ EXPECT_TRUE(CheckBlobInfoMatches(result_value.blob_info));
+ EXPECT_TRUE(CheckBlobReadsMatchWrites(result_value.blob_info));
+ }
+
+ {
+ IndexedDBBackingStore::Transaction transaction3(backing_store_);
+ transaction3.Begin();
+ IndexedDBValue result_value;
+ EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
+ 1,
+ 1,
+ IndexedDBKeyRange(m_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_TRUE(CheckBlobRemovals());
+ }
+}
+
+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_);
+ transaction1.Begin();
+ ScopedVector<webkit_blob::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_);
+ 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(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]);
+ }
+ }
+}
+
+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_);
+ transaction1.Begin();
+ ScopedVector<webkit_blob::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_);
+ 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());
+ }
+ }
+}
+
+TEST_F(IndexedDBBackingStoreTest, LiveBlobJournal) {
+ {
+ IndexedDBBackingStore::Transaction transaction1(backing_store_);
+ transaction1.Begin();
+ ScopedVector<webkit_blob::BlobDataHandle> handles;
+ IndexedDBBackingStore::RecordIdentifier record;
+ EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
+ 1,
+ 1,
+ m_key3,
+ m_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_);
+ transaction2.Begin();
+ EXPECT_TRUE(
+ backing_store_->GetRecord(
+ &transaction2, 1, 1, m_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(m_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_);
+ transaction3.Begin();
+ EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
+ 1,
+ 1,
+ IndexedDBKeyRange(m_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());
+ }
+}
+
// Make sure that using very high ( more than 32 bit ) values for database_id
// and object_store_id still work.
TEST_F(IndexedDBBackingStoreTest, HighIds) {
@@ -114,7 +721,12 @@ TEST_F(IndexedDBBackingStoreTest, HighIds) {
record);
EXPECT_TRUE(s.ok());
- s = transaction1.Commit();
+ 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());
}
@@ -148,7 +760,12 @@ TEST_F(IndexedDBBackingStoreTest, HighIds) {
EXPECT_TRUE(s.ok());
EXPECT_TRUE(new_primary_key->Equals(m_key1));
- s = transaction2.Commit();
+ 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());
}
}
@@ -287,7 +904,12 @@ TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
multi_entry);
EXPECT_TRUE(s.ok());
- s = transaction.Commit();
+ 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());
}
« no previous file with comments | « content/browser/indexed_db/indexed_db_backing_store.cc ('k') | content/browser/indexed_db/indexed_db_context_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698