| 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 396189e51955a6c5797e269eab41a35ab77809d8..da3d399a6b1a83e37c24c64d889949b685e6e653 100644
|
| --- a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
|
| +++ b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
|
| @@ -4,68 +4,481 @@
|
|
|
| #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/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 "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/mock_special_storage_policy.h"
|
| +#include "webkit/browser/quota/special_storage_policy.h"
|
|
|
| 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 bool 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 (!file_util::CreateDirectory(path_base))
|
| + return scoped_refptr<TestableIndexedDBBackingStore>();
|
| +
|
| + const base::FilePath file_path = path_base.Append("test_db_path");
|
| + const base::FilePath blob_path = path_base.Append("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_;
|
| + }
|
| + const std::vector<int64> removals() const { return removals_; }
|
| +
|
| + protected:
|
| + 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;
|
| + }
|
| +
|
| + 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.
|
| + 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,
|
| + base::TaskRunner* task_runner) {
|
| + 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,
|
| + task_runner);
|
| + scoped_refptr<TestableIndexedDBBackingStore> testable_store =
|
| + static_cast<TestableIndexedDBBackingStore*>(backing_store.get());
|
| + return testable_store;
|
| + }
|
| +
|
| + protected:
|
| + 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,
|
| + base::TaskRunner* task_runner,
|
| + bool first_time) {
|
| + DefaultLevelDBFactory leveldb_factory;
|
| + return TestableIndexedDBBackingStore::Open(this,
|
| + origin_url,
|
| + data_directory,
|
| + request_context,
|
| + &leveldb_factory,
|
| + task_runner);
|
| + }
|
| +};
|
| +
|
| class IndexedDBBackingStoreTest : public testing::Test {
|
| public:
|
| IndexedDBBackingStoreTest() {}
|
| virtual void SetUp() {
|
| const GURL origin("http://localhost:81");
|
| - backing_store_ = IndexedDBBackingStore::OpenInMemory(origin);
|
| + task_runner_ = new base::TestSimpleTaskRunner();
|
| + special_storage_policy_ = new quota::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_ = idb_factory_->OpenBackingStoreForTest(
|
| + origin, &url_request_context_, task_runner_.get());
|
|
|
| // useful keys and values during tests
|
| - m_value1 = "value1";
|
| - m_value2 = "value2";
|
| - m_value3 = "value3";
|
| + m_value1 = IndexedDBValue("value1", std::vector<IndexedDBBlobInfo>());
|
| + m_value2 = IndexedDBValue("value2", std::vector<IndexedDBBlobInfo>());
|
| +
|
| + m_blobInfo.push_back(
|
| + IndexedDBBlobInfo("uuid 3", UTF8ToUTF16("blob type"), 1));
|
| + m_blobInfo.push_back(
|
| + IndexedDBBlobInfo(base::FilePath(FILE_PATH_LITERAL("path/to/file")),
|
| + UTF8ToUTF16("file name"),
|
| + UTF8ToUTF16("file type")));
|
| + m_value3 = IndexedDBValue("value3", m_blobInfo);
|
| +
|
| 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_blobInfo.size() != reads.size())
|
| + return false;
|
| + for (size_t i = 0; i < m_blobInfo.size(); ++i) {
|
| + const IndexedDBBlobInfo& a = m_blobInfo[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_blobInfo.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_blobInfo[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<quota::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;
|
| - std::string m_value1;
|
| - std::string m_value2;
|
| - std::string m_value3;
|
| + IndexedDBValue m_value1;
|
| + IndexedDBValue m_value2;
|
| + IndexedDBValue m_value3;
|
| + std::vector<IndexedDBBlobInfo> m_blobInfo;
|
|
|
| private:
|
| DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest);
|
| };
|
|
|
| +class TestCallback : public IndexedDBBackingStore::BlobWriteCallback {
|
| + public:
|
| + TestCallback() : called(false), succeeded(false) {}
|
| + virtual ~TestCallback() {}
|
| + virtual void didSucceed() {
|
| + called = true;
|
| + succeeded = true;
|
| + }
|
| + virtual void didFail() {
|
| + called = true;
|
| + succeeded = false;
|
| + }
|
| + bool called;
|
| + bool succeeded;
|
| +};
|
| +
|
| TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
|
| {
|
| IndexedDBBackingStore::Transaction transaction1(backing_store_);
|
| transaction1.Begin();
|
| + ScopedVector<webkit_blob::BlobDataHandle> handles;
|
| IndexedDBBackingStore::RecordIdentifier record;
|
| bool ok = backing_store_->PutRecord(
|
| - &transaction1, 1, 1, m_key1, m_value1, &record);
|
| + &transaction1, 1, 1, m_key1, m_value1, &handles, &record);
|
| EXPECT_TRUE(ok);
|
| - transaction1.Commit();
|
| + scoped_refptr<TestCallback> callback(new TestCallback());
|
| + EXPECT_TRUE(transaction1.CommitPhaseOne(callback));
|
| + EXPECT_TRUE(callback->called);
|
| + EXPECT_TRUE(callback->succeeded);
|
| + EXPECT_TRUE(transaction1.CommitPhaseTwo());
|
| }
|
|
|
| {
|
| IndexedDBBackingStore::Transaction transaction2(backing_store_);
|
| transaction2.Begin();
|
| - std::string result_value;
|
| + IndexedDBValue result_value;
|
| bool ok =
|
| backing_store_->GetRecord(&transaction2, 1, 1, m_key1, &result_value);
|
| - transaction2.Commit();
|
| + scoped_refptr<TestCallback> callback(new TestCallback());
|
| + EXPECT_TRUE(transaction2.CommitPhaseOne(callback));
|
| + EXPECT_TRUE(ok);
|
| + EXPECT_TRUE(callback->called);
|
| + EXPECT_TRUE(callback->succeeded);
|
| + EXPECT_TRUE(transaction2.CommitPhaseTwo());
|
| + 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;
|
| + bool ok = backing_store_->PutRecord(
|
| + &transaction1, 1, 1, m_key3, m_value3, &handles, &record);
|
| + EXPECT_TRUE(ok);
|
| + scoped_refptr<TestCallback> callback(new TestCallback());
|
| + EXPECT_TRUE(transaction1.CommitPhaseOne(callback));
|
| + task_runner_->RunUntilIdle();
|
| + EXPECT_TRUE(CheckBlobWrites());
|
| + EXPECT_TRUE(callback->called);
|
| + EXPECT_TRUE(callback->succeeded);
|
| + EXPECT_TRUE(transaction1.CommitPhaseTwo());
|
| + }
|
| +
|
| + {
|
| + IndexedDBBackingStore::Transaction transaction2(backing_store_);
|
| + transaction2.Begin();
|
| + IndexedDBValue result_value;
|
| + bool ok =
|
| + backing_store_->GetRecord(&transaction2, 1, 1, m_key3, &result_value);
|
| + EXPECT_TRUE(ok);
|
| + scoped_refptr<TestCallback> callback(new TestCallback());
|
| + EXPECT_TRUE(transaction2.CommitPhaseOne(callback));
|
| + EXPECT_TRUE(callback->called);
|
| + EXPECT_TRUE(callback->succeeded);
|
| + EXPECT_TRUE(transaction2.CommitPhaseTwo());
|
| + 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;
|
| + bool ok = backing_store_->DeleteRange(
|
| + &transaction3, 1, 1, IndexedDBKeyRange(m_key3));
|
| + EXPECT_TRUE(ok);
|
| + scoped_refptr<TestCallback> callback(new TestCallback());
|
| + EXPECT_TRUE(transaction3.CommitPhaseOne(callback));
|
| + task_runner_->RunUntilIdle();
|
| + EXPECT_TRUE(callback->called);
|
| + EXPECT_TRUE(callback->succeeded);
|
| + EXPECT_TRUE(transaction3.CommitPhaseTwo());
|
| + EXPECT_TRUE(CheckBlobRemovals());
|
| + }
|
| +}
|
| +
|
| +TEST_F(IndexedDBBackingStoreTest, LiveBlobJournal) {
|
| + {
|
| + IndexedDBBackingStore::Transaction transaction1(backing_store_);
|
| + transaction1.Begin();
|
| + ScopedVector<webkit_blob::BlobDataHandle> handles;
|
| + IndexedDBBackingStore::RecordIdentifier record;
|
| + bool ok = backing_store_->PutRecord(
|
| + &transaction1, 1, 1, m_key3, m_value3, &handles, &record);
|
| + EXPECT_TRUE(ok);
|
| + scoped_refptr<TestCallback> callback(new TestCallback());
|
| + EXPECT_TRUE(transaction1.CommitPhaseOne(callback));
|
| + task_runner_->RunUntilIdle();
|
| + EXPECT_TRUE(CheckBlobWrites());
|
| + EXPECT_TRUE(callback->called);
|
| + EXPECT_TRUE(callback->succeeded);
|
| + EXPECT_TRUE(transaction1.CommitPhaseTwo());
|
| + }
|
| +
|
| + IndexedDBValue read_result_value;
|
| + {
|
| + IndexedDBBackingStore::Transaction transaction2(backing_store_);
|
| + transaction2.Begin();
|
| + bool ok = backing_store_->GetRecord(
|
| + &transaction2, 1, 1, m_key3, &read_result_value);
|
| + EXPECT_TRUE(ok);
|
| + scoped_refptr<TestCallback> callback(new TestCallback());
|
| + EXPECT_TRUE(transaction2.CommitPhaseOne(callback));
|
| + EXPECT_TRUE(callback->called);
|
| + EXPECT_TRUE(callback->succeeded);
|
| + EXPECT_TRUE(transaction2.CommitPhaseTwo());
|
| + 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();
|
| + bool ok = backing_store_->DeleteRange(
|
| + &transaction3, 1, 1, IndexedDBKeyRange(m_key3));
|
| EXPECT_TRUE(ok);
|
| - EXPECT_EQ(m_value1, result_value);
|
| + scoped_refptr<TestCallback> callback(new TestCallback());
|
| + EXPECT_TRUE(transaction3.CommitPhaseOne(callback));
|
| + task_runner_->RunUntilIdle();
|
| + EXPECT_TRUE(callback->called);
|
| + EXPECT_TRUE(callback->succeeded);
|
| + EXPECT_TRUE(transaction3.CommitPhaseTwo());
|
| + 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());
|
| }
|
| }
|
|
|
| @@ -85,12 +498,14 @@ TEST_F(IndexedDBBackingStoreTest, HighIds) {
|
| {
|
| IndexedDBBackingStore::Transaction transaction1(backing_store_);
|
| transaction1.Begin();
|
| + ScopedVector<webkit_blob::BlobDataHandle> handles;
|
| IndexedDBBackingStore::RecordIdentifier record;
|
| bool ok = backing_store_->PutRecord(&transaction1,
|
| high_database_id,
|
| high_object_store_id,
|
| m_key1,
|
| m_value1,
|
| + &handles,
|
| &record);
|
| EXPECT_TRUE(ok);
|
|
|
| @@ -110,21 +525,25 @@ TEST_F(IndexedDBBackingStoreTest, HighIds) {
|
| record);
|
| EXPECT_TRUE(ok);
|
|
|
| - ok = transaction1.Commit();
|
| + scoped_refptr<TestCallback> callback(new TestCallback());
|
| + ok = transaction1.CommitPhaseOne(callback);
|
| EXPECT_TRUE(ok);
|
| + EXPECT_TRUE(callback->called);
|
| + EXPECT_TRUE(callback->succeeded);
|
| + EXPECT_TRUE(transaction1.CommitPhaseTwo());
|
| }
|
|
|
| {
|
| IndexedDBBackingStore::Transaction transaction2(backing_store_);
|
| transaction2.Begin();
|
| - std::string result_value;
|
| + IndexedDBValue result_value;
|
| bool ok = backing_store_->GetRecord(&transaction2,
|
| high_database_id,
|
| high_object_store_id,
|
| m_key1,
|
| &result_value);
|
| EXPECT_TRUE(ok);
|
| - EXPECT_EQ(m_value1, result_value);
|
| + EXPECT_EQ(m_value1.bits, result_value.bits);
|
|
|
| scoped_ptr<IndexedDBKey> new_primary_key;
|
| ok = backing_store_->GetPrimaryKeyViaIndex(&transaction2,
|
| @@ -144,8 +563,12 @@ TEST_F(IndexedDBBackingStoreTest, HighIds) {
|
| EXPECT_TRUE(ok);
|
| EXPECT_TRUE(new_primary_key->IsEqual(m_key1));
|
|
|
| - ok = transaction2.Commit();
|
| + scoped_refptr<TestCallback> callback(new TestCallback());
|
| + ok = transaction2.CommitPhaseOne(callback);
|
| EXPECT_TRUE(ok);
|
| + EXPECT_TRUE(callback->called);
|
| + EXPECT_TRUE(callback->succeeded);
|
| + EXPECT_TRUE(transaction2.CommitPhaseTwo());
|
| }
|
| }
|
|
|
| @@ -157,31 +580,34 @@ TEST_F(IndexedDBBackingStoreTest, InvalidIds) {
|
| const int64 index_id = kMinimumIndexId;
|
| const int64 invalid_low_index_id = 19; // index_ids must be > kMinimumIndexId
|
|
|
| - std::string result_value;
|
| + IndexedDBValue result_value;
|
|
|
| IndexedDBBackingStore::Transaction transaction1(backing_store_);
|
| transaction1.Begin();
|
|
|
| + ScopedVector<webkit_blob::BlobDataHandle> handles;
|
| IndexedDBBackingStore::RecordIdentifier record;
|
| bool ok = backing_store_->PutRecord(&transaction1,
|
| database_id,
|
| KeyPrefix::kInvalidId,
|
| m_key1,
|
| m_value1,
|
| + &handles,
|
| &record);
|
| EXPECT_FALSE(ok);
|
| ok = backing_store_->PutRecord(
|
| - &transaction1, database_id, 0, m_key1, m_value1, &record);
|
| + &transaction1, database_id, 0, m_key1, m_value1, &handles, &record);
|
| EXPECT_FALSE(ok);
|
| ok = backing_store_->PutRecord(&transaction1,
|
| KeyPrefix::kInvalidId,
|
| object_store_id,
|
| m_key1,
|
| m_value1,
|
| + &handles,
|
| &record);
|
| EXPECT_FALSE(ok);
|
| ok = backing_store_->PutRecord(
|
| - &transaction1, 0, object_store_id, m_key1, m_value1, &record);
|
| + &transaction1, 0, object_store_id, m_key1, m_value1, &handles, &record);
|
| EXPECT_FALSE(ok);
|
|
|
| ok = backing_store_->GetRecord(
|
| @@ -280,8 +706,12 @@ TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
|
| multi_entry);
|
| EXPECT_TRUE(ok);
|
|
|
| - ok = transaction.Commit();
|
| + scoped_refptr<TestCallback> callback(new TestCallback());
|
| + ok = transaction.CommitPhaseOne(callback);
|
| EXPECT_TRUE(ok);
|
| + EXPECT_TRUE(callback->called);
|
| + EXPECT_TRUE(callback->succeeded);
|
| + EXPECT_TRUE(transaction.CommitPhaseTwo());
|
| }
|
|
|
| {
|
|
|