Blink roll 25b6bd3a7a131ffe68d809546ad1a20707915cdc:3a503f41ae42e5b79cfcd2ff10e65afde...
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_backing_store_unittest.cc
blobda9bcda9386711528934a8a15eaeacafcdcb8051
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/indexed_db/indexed_db_backing_store.h"
7 #include "base/callback.h"
8 #include "base/files/file_util.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/logging.h"
11 #include "base/macros.h"
12 #include "base/sequenced_task_runner.h"
13 #include "base/strings/string16.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/test/test_simple_task_runner.h"
16 #include "content/browser/indexed_db/indexed_db_context_impl.h"
17 #include "content/browser/indexed_db/indexed_db_factory_impl.h"
18 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
19 #include "content/browser/indexed_db/indexed_db_value.h"
20 #include "content/browser/indexed_db/leveldb/leveldb_factory.h"
21 #include "content/public/test/mock_special_storage_policy.h"
22 #include "content/public/test/test_browser_thread_bundle.h"
23 #include "net/url_request/url_request_test_util.h"
24 #include "storage/browser/blob/blob_data_handle.h"
25 #include "storage/browser/quota/special_storage_policy.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "third_party/WebKit/public/platform/WebIDBTypes.h"
29 using base::ASCIIToUTF16;
31 namespace content {
33 namespace {
35 class Comparator : public LevelDBComparator {
36 public:
37 int Compare(const base::StringPiece& a,
38 const base::StringPiece& b) const override {
39 return content::Compare(a, b, false /*index_keys*/);
41 const char* Name() const override { return "idb_cmp1"; }
44 class DefaultLevelDBFactory : public LevelDBFactory {
45 public:
46 DefaultLevelDBFactory() {}
47 leveldb::Status OpenLevelDB(const base::FilePath& file_name,
48 const LevelDBComparator* comparator,
49 scoped_ptr<LevelDBDatabase>* db,
50 bool* is_disk_full) override {
51 return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full);
53 leveldb::Status DestroyLevelDB(const base::FilePath& file_name) override {
54 return LevelDBDatabase::Destroy(file_name);
57 private:
58 DISALLOW_COPY_AND_ASSIGN(DefaultLevelDBFactory);
61 class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
62 public:
63 static scoped_refptr<TestableIndexedDBBackingStore> Open(
64 IndexedDBFactory* indexed_db_factory,
65 const GURL& origin_url,
66 const base::FilePath& path_base,
67 net::URLRequestContext* request_context,
68 LevelDBFactory* leveldb_factory,
69 base::SequencedTaskRunner* task_runner,
70 leveldb::Status* status) {
71 DCHECK(!path_base.empty());
73 scoped_ptr<LevelDBComparator> comparator(new Comparator());
75 if (!base::CreateDirectory(path_base)) {
76 *status = leveldb::Status::IOError("Unable to create base dir");
77 return scoped_refptr<TestableIndexedDBBackingStore>();
80 const base::FilePath file_path = path_base.AppendASCII("test_db_path");
81 const base::FilePath blob_path = path_base.AppendASCII("test_blob_path");
83 scoped_ptr<LevelDBDatabase> db;
84 bool is_disk_full = false;
85 *status = leveldb_factory->OpenLevelDB(
86 file_path, comparator.get(), &db, &is_disk_full);
88 if (!db || !status->ok())
89 return scoped_refptr<TestableIndexedDBBackingStore>();
91 scoped_refptr<TestableIndexedDBBackingStore> backing_store(
92 new TestableIndexedDBBackingStore(indexed_db_factory,
93 origin_url,
94 blob_path,
95 request_context,
96 db.Pass(),
97 comparator.Pass(),
98 task_runner));
100 *status = backing_store->SetUpMetadata();
101 if (!status->ok())
102 return scoped_refptr<TestableIndexedDBBackingStore>();
104 return backing_store;
107 const std::vector<IndexedDBBackingStore::Transaction::WriteDescriptor>&
108 writes() const {
109 return writes_;
111 void ClearWrites() { writes_.clear(); }
112 const std::vector<int64>& removals() const { return removals_; }
113 void ClearRemovals() { removals_.clear(); }
115 protected:
116 ~TestableIndexedDBBackingStore() override {}
118 bool WriteBlobFile(
119 int64 database_id,
120 const Transaction::WriteDescriptor& descriptor,
121 Transaction::ChainedBlobWriter* chained_blob_writer) override {
122 if (KeyPrefix::IsValidDatabaseId(database_id_)) {
123 if (database_id_ != database_id) {
124 return false;
126 } else {
127 database_id_ = database_id;
129 writes_.push_back(descriptor);
130 task_runner()->PostTask(
131 FROM_HERE,
132 base::Bind(&Transaction::ChainedBlobWriter::ReportWriteCompletion,
133 chained_blob_writer,
134 true,
135 1));
136 return true;
139 bool RemoveBlobFile(int64 database_id, int64 key) override {
140 if (database_id_ != database_id ||
141 !KeyPrefix::IsValidDatabaseId(database_id)) {
142 return false;
144 removals_.push_back(key);
145 return true;
148 // Timers don't play nicely with unit tests.
149 void StartJournalCleaningTimer() override {
150 CleanPrimaryJournalIgnoreReturn();
153 private:
154 TestableIndexedDBBackingStore(IndexedDBFactory* indexed_db_factory,
155 const GURL& origin_url,
156 const base::FilePath& blob_path,
157 net::URLRequestContext* request_context,
158 scoped_ptr<LevelDBDatabase> db,
159 scoped_ptr<LevelDBComparator> comparator,
160 base::SequencedTaskRunner* task_runner)
161 : IndexedDBBackingStore(indexed_db_factory,
162 origin_url,
163 blob_path,
164 request_context,
165 db.Pass(),
166 comparator.Pass(),
167 task_runner),
168 database_id_(0) {}
170 int64 database_id_;
171 std::vector<Transaction::WriteDescriptor> writes_;
172 std::vector<int64> removals_;
174 DISALLOW_COPY_AND_ASSIGN(TestableIndexedDBBackingStore);
177 class TestIDBFactory : public IndexedDBFactoryImpl {
178 public:
179 explicit TestIDBFactory(IndexedDBContextImpl* idb_context)
180 : IndexedDBFactoryImpl(idb_context) {}
182 scoped_refptr<TestableIndexedDBBackingStore> OpenBackingStoreForTest(
183 const GURL& origin,
184 net::URLRequestContext* url_request_context) {
185 blink::WebIDBDataLoss data_loss;
186 std::string data_loss_reason;
187 bool disk_full;
188 leveldb::Status status;
189 scoped_refptr<IndexedDBBackingStore> backing_store =
190 OpenBackingStore(origin,
191 context()->data_path(),
192 url_request_context,
193 &data_loss,
194 &data_loss_reason,
195 &disk_full,
196 &status);
197 scoped_refptr<TestableIndexedDBBackingStore> testable_store =
198 static_cast<TestableIndexedDBBackingStore*>(backing_store.get());
199 return testable_store;
202 protected:
203 ~TestIDBFactory() override {}
205 scoped_refptr<IndexedDBBackingStore> OpenBackingStoreHelper(
206 const GURL& origin_url,
207 const base::FilePath& data_directory,
208 net::URLRequestContext* request_context,
209 blink::WebIDBDataLoss* data_loss,
210 std::string* data_loss_message,
211 bool* disk_full,
212 bool first_time,
213 leveldb::Status* status) override {
214 DefaultLevelDBFactory leveldb_factory;
215 return TestableIndexedDBBackingStore::Open(this,
216 origin_url,
217 data_directory,
218 request_context,
219 &leveldb_factory,
220 context()->TaskRunner(),
221 status);
224 private:
225 DISALLOW_COPY_AND_ASSIGN(TestIDBFactory);
228 class IndexedDBBackingStoreTest : public testing::Test {
229 public:
230 IndexedDBBackingStoreTest() {}
231 void SetUp() override {
232 const GURL origin("http://localhost:81");
233 task_runner_ = new base::TestSimpleTaskRunner();
234 special_storage_policy_ = new MockSpecialStoragePolicy();
235 special_storage_policy_->SetAllUnlimited(true);
236 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
237 idb_context_ = new IndexedDBContextImpl(temp_dir_.path(),
238 special_storage_policy_.get(),
239 NULL,
240 task_runner_.get());
241 idb_factory_ = new TestIDBFactory(idb_context_.get());
242 backing_store_ =
243 idb_factory_->OpenBackingStoreForTest(origin, &url_request_context_);
245 // useful keys and values during tests
246 m_value1 = IndexedDBValue("value1", std::vector<IndexedDBBlobInfo>());
247 m_value2 = IndexedDBValue("value2", std::vector<IndexedDBBlobInfo>());
249 m_blob_info.push_back(
250 IndexedDBBlobInfo("uuid 3", base::UTF8ToUTF16("blob type"), 1));
251 m_blob_info.push_back(
252 IndexedDBBlobInfo("uuid 4",
253 base::FilePath(FILE_PATH_LITERAL("path/to/file")),
254 base::UTF8ToUTF16("file name"),
255 base::UTF8ToUTF16("file type")));
256 m_value3 = IndexedDBValue("value3", m_blob_info);
258 m_key1 = IndexedDBKey(99, blink::WebIDBKeyTypeNumber);
259 m_key2 = IndexedDBKey(ASCIIToUTF16("key2"));
260 m_key3 = IndexedDBKey(ASCIIToUTF16("key3"));
263 // This just checks the data that survive getting stored and recalled, e.g.
264 // the file path and UUID will change and thus aren't verified.
265 bool CheckBlobInfoMatches(const std::vector<IndexedDBBlobInfo>& reads) const {
266 if (m_blob_info.size() != reads.size())
267 return false;
268 for (size_t i = 0; i < m_blob_info.size(); ++i) {
269 const IndexedDBBlobInfo& a = m_blob_info[i];
270 const IndexedDBBlobInfo& b = reads[i];
271 if (a.is_file() != b.is_file())
272 return false;
273 if (a.type() != b.type())
274 return false;
275 if (a.is_file()) {
276 if (a.file_name() != b.file_name())
277 return false;
278 } else {
279 if (a.size() != b.size())
280 return false;
283 return true;
286 bool CheckBlobReadsMatchWrites(
287 const std::vector<IndexedDBBlobInfo>& reads) const {
288 if (backing_store_->writes().size() != reads.size())
289 return false;
290 std::set<int64> ids;
291 for (size_t i = 0; i < backing_store_->writes().size(); ++i)
292 ids.insert(backing_store_->writes()[i].key());
293 if (ids.size() != backing_store_->writes().size())
294 return false;
295 for (size_t i = 0; i < reads.size(); ++i) {
296 if (ids.count(reads[i].key()) != 1)
297 return false;
299 return true;
302 bool CheckBlobWrites() const {
303 if (backing_store_->writes().size() != m_blob_info.size())
304 return false;
305 for (size_t i = 0; i < backing_store_->writes().size(); ++i) {
306 const IndexedDBBackingStore::Transaction::WriteDescriptor& desc =
307 backing_store_->writes()[i];
308 const IndexedDBBlobInfo& info = m_blob_info[i];
309 if (desc.is_file() != info.is_file())
310 return false;
311 if (desc.is_file()) {
312 if (desc.file_path() != info.file_path())
313 return false;
314 } else {
315 if (desc.url() != GURL("blob:uuid/" + info.uuid()))
316 return false;
319 return true;
322 bool CheckBlobRemovals() const {
323 if (backing_store_->removals().size() != backing_store_->writes().size())
324 return false;
325 for (size_t i = 0; i < backing_store_->writes().size(); ++i) {
326 if (backing_store_->writes()[i].key() != backing_store_->removals()[i])
327 return false;
329 return true;
332 protected:
333 // Must be initialized before url_request_context_
334 content::TestBrowserThreadBundle thread_bundle_;
336 base::ScopedTempDir temp_dir_;
337 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
338 scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
339 scoped_refptr<IndexedDBContextImpl> idb_context_;
340 scoped_refptr<TestIDBFactory> idb_factory_;
341 net::TestURLRequestContext url_request_context_;
343 scoped_refptr<TestableIndexedDBBackingStore> backing_store_;
345 // Sample keys and values that are consistent.
346 IndexedDBKey m_key1;
347 IndexedDBKey m_key2;
348 IndexedDBKey m_key3;
349 IndexedDBValue m_value1;
350 IndexedDBValue m_value2;
351 IndexedDBValue m_value3;
352 std::vector<IndexedDBBlobInfo> m_blob_info;
354 private:
355 DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest);
358 class TestCallback : public IndexedDBBackingStore::BlobWriteCallback {
359 public:
360 TestCallback() : called(false), succeeded(false) {}
361 void Run(bool succeeded_in) override {
362 called = true;
363 succeeded = succeeded_in;
365 bool called;
366 bool succeeded;
368 protected:
369 ~TestCallback() override {}
371 private:
372 DISALLOW_COPY_AND_ASSIGN(TestCallback);
375 TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
377 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
378 transaction1.Begin();
379 ScopedVector<storage::BlobDataHandle> handles;
380 IndexedDBBackingStore::RecordIdentifier record;
381 leveldb::Status s = backing_store_->PutRecord(
382 &transaction1, 1, 1, m_key1, &m_value1, &handles, &record);
383 EXPECT_TRUE(s.ok());
384 scoped_refptr<TestCallback> callback(new TestCallback());
385 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
386 EXPECT_TRUE(callback->called);
387 EXPECT_TRUE(callback->succeeded);
388 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
392 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
393 transaction2.Begin();
394 IndexedDBValue result_value;
395 EXPECT_TRUE(
396 backing_store_->GetRecord(&transaction2, 1, 1, m_key1, &result_value)
397 .ok());
398 scoped_refptr<TestCallback> callback(new TestCallback());
399 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
400 EXPECT_TRUE(callback->called);
401 EXPECT_TRUE(callback->succeeded);
402 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
403 EXPECT_EQ(m_value1.bits, result_value.bits);
407 TEST_F(IndexedDBBackingStoreTest, PutGetConsistencyWithBlobs) {
409 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
410 transaction1.Begin();
411 ScopedVector<storage::BlobDataHandle> handles;
412 IndexedDBBackingStore::RecordIdentifier record;
413 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
416 m_key3,
417 &m_value3,
418 &handles,
419 &record).ok());
420 scoped_refptr<TestCallback> callback(new TestCallback());
421 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
422 task_runner_->RunUntilIdle();
423 EXPECT_TRUE(CheckBlobWrites());
424 EXPECT_TRUE(callback->called);
425 EXPECT_TRUE(callback->succeeded);
426 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
430 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
431 transaction2.Begin();
432 IndexedDBValue result_value;
433 EXPECT_TRUE(
434 backing_store_->GetRecord(&transaction2, 1, 1, m_key3, &result_value)
435 .ok());
436 scoped_refptr<TestCallback> callback(new TestCallback());
437 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
438 EXPECT_TRUE(callback->called);
439 EXPECT_TRUE(callback->succeeded);
440 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
441 EXPECT_EQ(m_value3.bits, result_value.bits);
442 EXPECT_TRUE(CheckBlobInfoMatches(result_value.blob_info));
443 EXPECT_TRUE(CheckBlobReadsMatchWrites(result_value.blob_info));
447 IndexedDBBackingStore::Transaction transaction3(backing_store_.get());
448 transaction3.Begin();
449 IndexedDBValue result_value;
450 EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
453 IndexedDBKeyRange(m_key3)).ok());
454 scoped_refptr<TestCallback> callback(new TestCallback());
455 EXPECT_TRUE(transaction3.CommitPhaseOne(callback).ok());
456 task_runner_->RunUntilIdle();
457 EXPECT_TRUE(callback->called);
458 EXPECT_TRUE(callback->succeeded);
459 EXPECT_TRUE(transaction3.CommitPhaseTwo().ok());
460 EXPECT_TRUE(CheckBlobRemovals());
464 TEST_F(IndexedDBBackingStoreTest, DeleteRange) {
465 IndexedDBKey key0 = IndexedDBKey(ASCIIToUTF16("key0"));
466 IndexedDBKey key1 = IndexedDBKey(ASCIIToUTF16("key1"));
467 IndexedDBKey key2 = IndexedDBKey(ASCIIToUTF16("key2"));
468 IndexedDBKey key3 = IndexedDBKey(ASCIIToUTF16("key3"));
469 IndexedDBBlobInfo blob0("uuid 0", base::UTF8ToUTF16("type 0"), 1);
470 IndexedDBBlobInfo blob1("uuid 1", base::UTF8ToUTF16("type 1"), 1);
471 IndexedDBBlobInfo blob2("uuid 2", base::UTF8ToUTF16("type 2"), 1);
472 IndexedDBBlobInfo blob3("uuid 3", base::UTF8ToUTF16("type 3"), 1);
473 IndexedDBKeyRange ranges[] = {IndexedDBKeyRange(key1, key2, false, false),
474 IndexedDBKeyRange(key1, key2, false, false),
475 IndexedDBKeyRange(key0, key2, true, false),
476 IndexedDBKeyRange(key1, key3, false, true),
477 IndexedDBKeyRange(key0, key3, true, true)};
479 for (unsigned i = 0; i < sizeof(ranges) / sizeof(IndexedDBKeyRange); ++i) {
480 backing_store_->ClearWrites();
481 backing_store_->ClearRemovals();
484 std::vector<IndexedDBBlobInfo> blob_info0, blob_info1, blob_info2,
485 blob_info3;
486 blob_info0.push_back(blob0);
487 blob_info1.push_back(blob1);
488 blob_info2.push_back(blob2);
489 blob_info3.push_back(blob3);
490 IndexedDBValue value0 = IndexedDBValue("value0", blob_info0);
491 IndexedDBValue value1 = IndexedDBValue("value1", blob_info1);
492 IndexedDBValue value2 = IndexedDBValue("value2", blob_info2);
493 IndexedDBValue value3 = IndexedDBValue("value3", blob_info3);
494 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
495 transaction1.Begin();
496 ScopedVector<storage::BlobDataHandle> handles;
497 IndexedDBBackingStore::RecordIdentifier record;
498 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
500 i + 1,
501 key0,
502 &value0,
503 &handles,
504 &record).ok());
505 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
507 i + 1,
508 key1,
509 &value1,
510 &handles,
511 &record).ok());
512 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
514 i + 1,
515 key2,
516 &value2,
517 &handles,
518 &record).ok());
519 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
521 i + 1,
522 key3,
523 &value3,
524 &handles,
525 &record).ok());
526 scoped_refptr<TestCallback> callback(new TestCallback());
527 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
528 task_runner_->RunUntilIdle();
529 EXPECT_TRUE(callback->called);
530 EXPECT_TRUE(callback->succeeded);
531 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
535 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
536 transaction2.Begin();
537 IndexedDBValue result_value;
538 EXPECT_TRUE(
539 backing_store_->DeleteRange(&transaction2, 1, i + 1, ranges[i]).ok());
540 scoped_refptr<TestCallback> callback(new TestCallback());
541 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
542 task_runner_->RunUntilIdle();
543 EXPECT_TRUE(callback->called);
544 EXPECT_TRUE(callback->succeeded);
545 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
546 EXPECT_EQ(2UL, backing_store_->removals().size());
547 EXPECT_EQ(backing_store_->writes()[1].key(),
548 backing_store_->removals()[0]);
549 EXPECT_EQ(backing_store_->writes()[2].key(),
550 backing_store_->removals()[1]);
555 TEST_F(IndexedDBBackingStoreTest, DeleteRangeEmptyRange) {
556 IndexedDBKey key0 = IndexedDBKey(ASCIIToUTF16("key0"));
557 IndexedDBKey key1 = IndexedDBKey(ASCIIToUTF16("key1"));
558 IndexedDBKey key2 = IndexedDBKey(ASCIIToUTF16("key2"));
559 IndexedDBKey key3 = IndexedDBKey(ASCIIToUTF16("key3"));
560 IndexedDBKey key4 = IndexedDBKey(ASCIIToUTF16("key4"));
561 IndexedDBBlobInfo blob0("uuid 0", base::UTF8ToUTF16("type 0"), 1);
562 IndexedDBBlobInfo blob1("uuid 1", base::UTF8ToUTF16("type 1"), 1);
563 IndexedDBBlobInfo blob2("uuid 2", base::UTF8ToUTF16("type 2"), 1);
564 IndexedDBBlobInfo blob3("uuid 3", base::UTF8ToUTF16("type 3"), 1);
565 IndexedDBKeyRange ranges[] = {IndexedDBKeyRange(key3, key4, true, false),
566 IndexedDBKeyRange(key2, key1, false, false),
567 IndexedDBKeyRange(key2, key1, true, true)};
569 for (unsigned i = 0; i < arraysize(ranges); ++i) {
570 backing_store_->ClearWrites();
571 backing_store_->ClearRemovals();
574 std::vector<IndexedDBBlobInfo> blob_info0, blob_info1, blob_info2,
575 blob_info3;
576 blob_info0.push_back(blob0);
577 blob_info1.push_back(blob1);
578 blob_info2.push_back(blob2);
579 blob_info3.push_back(blob3);
580 IndexedDBValue value0 = IndexedDBValue("value0", blob_info0);
581 IndexedDBValue value1 = IndexedDBValue("value1", blob_info1);
582 IndexedDBValue value2 = IndexedDBValue("value2", blob_info2);
583 IndexedDBValue value3 = IndexedDBValue("value3", blob_info3);
584 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
585 transaction1.Begin();
586 ScopedVector<storage::BlobDataHandle> handles;
587 IndexedDBBackingStore::RecordIdentifier record;
588 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
590 i + 1,
591 key0,
592 &value0,
593 &handles,
594 &record).ok());
595 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
597 i + 1,
598 key1,
599 &value1,
600 &handles,
601 &record).ok());
602 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
604 i + 1,
605 key2,
606 &value2,
607 &handles,
608 &record).ok());
609 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
611 i + 1,
612 key3,
613 &value3,
614 &handles,
615 &record).ok());
616 scoped_refptr<TestCallback> callback(new TestCallback());
617 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
618 task_runner_->RunUntilIdle();
619 EXPECT_TRUE(callback->called);
620 EXPECT_TRUE(callback->succeeded);
621 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
625 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
626 transaction2.Begin();
627 IndexedDBValue result_value;
628 EXPECT_TRUE(
629 backing_store_->DeleteRange(&transaction2, 1, i + 1, ranges[i]).ok());
630 scoped_refptr<TestCallback> callback(new TestCallback());
631 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
632 task_runner_->RunUntilIdle();
633 EXPECT_TRUE(callback->called);
634 EXPECT_TRUE(callback->succeeded);
635 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
636 EXPECT_EQ(0UL, backing_store_->removals().size());
641 TEST_F(IndexedDBBackingStoreTest, LiveBlobJournal) {
643 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
644 transaction1.Begin();
645 ScopedVector<storage::BlobDataHandle> handles;
646 IndexedDBBackingStore::RecordIdentifier record;
647 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
650 m_key3,
651 &m_value3,
652 &handles,
653 &record).ok());
654 scoped_refptr<TestCallback> callback(new TestCallback());
655 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
656 task_runner_->RunUntilIdle();
657 EXPECT_TRUE(CheckBlobWrites());
658 EXPECT_TRUE(callback->called);
659 EXPECT_TRUE(callback->succeeded);
660 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
663 IndexedDBValue read_result_value;
665 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
666 transaction2.Begin();
667 EXPECT_TRUE(
668 backing_store_->GetRecord(
669 &transaction2, 1, 1, m_key3, &read_result_value)
670 .ok());
671 scoped_refptr<TestCallback> callback(new TestCallback());
672 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
673 EXPECT_TRUE(callback->called);
674 EXPECT_TRUE(callback->succeeded);
675 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
676 EXPECT_EQ(m_value3.bits, read_result_value.bits);
677 EXPECT_TRUE(CheckBlobInfoMatches(read_result_value.blob_info));
678 EXPECT_TRUE(CheckBlobReadsMatchWrites(read_result_value.blob_info));
679 for (size_t i = 0; i < read_result_value.blob_info.size(); ++i) {
680 read_result_value.blob_info[i].mark_used_callback().Run();
685 IndexedDBBackingStore::Transaction transaction3(backing_store_.get());
686 transaction3.Begin();
687 EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
690 IndexedDBKeyRange(m_key3)).ok());
691 scoped_refptr<TestCallback> callback(new TestCallback());
692 EXPECT_TRUE(transaction3.CommitPhaseOne(callback).ok());
693 task_runner_->RunUntilIdle();
694 EXPECT_TRUE(callback->called);
695 EXPECT_TRUE(callback->succeeded);
696 EXPECT_TRUE(transaction3.CommitPhaseTwo().ok());
697 EXPECT_EQ(0U, backing_store_->removals().size());
698 for (size_t i = 0; i < read_result_value.blob_info.size(); ++i) {
699 read_result_value.blob_info[i].release_callback().Run(
700 read_result_value.blob_info[i].file_path());
702 task_runner_->RunUntilIdle();
703 EXPECT_NE(0U, backing_store_->removals().size());
704 EXPECT_TRUE(CheckBlobRemovals());
708 // Make sure that using very high ( more than 32 bit ) values for database_id
709 // and object_store_id still work.
710 TEST_F(IndexedDBBackingStoreTest, HighIds) {
711 const int64 high_database_id = 1ULL << 35;
712 const int64 high_object_store_id = 1ULL << 39;
713 // index_ids are capped at 32 bits for storage purposes.
714 const int64 high_index_id = 1ULL << 29;
716 const int64 invalid_high_index_id = 1ULL << 37;
718 const IndexedDBKey& index_key = m_key2;
719 std::string index_key_raw;
720 EncodeIDBKey(index_key, &index_key_raw);
722 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
723 transaction1.Begin();
724 ScopedVector<storage::BlobDataHandle> handles;
725 IndexedDBBackingStore::RecordIdentifier record;
726 leveldb::Status s = backing_store_->PutRecord(&transaction1,
727 high_database_id,
728 high_object_store_id,
729 m_key1,
730 &m_value1,
731 &handles,
732 &record);
733 EXPECT_TRUE(s.ok());
735 s = backing_store_->PutIndexDataForRecord(&transaction1,
736 high_database_id,
737 high_object_store_id,
738 invalid_high_index_id,
739 index_key,
740 record);
741 EXPECT_FALSE(s.ok());
743 s = backing_store_->PutIndexDataForRecord(&transaction1,
744 high_database_id,
745 high_object_store_id,
746 high_index_id,
747 index_key,
748 record);
749 EXPECT_TRUE(s.ok());
751 scoped_refptr<TestCallback> callback(new TestCallback());
752 s = transaction1.CommitPhaseOne(callback);
753 EXPECT_TRUE(s.ok());
754 EXPECT_TRUE(callback->called);
755 EXPECT_TRUE(callback->succeeded);
756 s = transaction1.CommitPhaseTwo();
757 EXPECT_TRUE(s.ok());
761 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
762 transaction2.Begin();
763 IndexedDBValue result_value;
764 leveldb::Status s = backing_store_->GetRecord(&transaction2,
765 high_database_id,
766 high_object_store_id,
767 m_key1,
768 &result_value);
769 EXPECT_TRUE(s.ok());
770 EXPECT_EQ(m_value1.bits, result_value.bits);
772 scoped_ptr<IndexedDBKey> new_primary_key;
773 s = backing_store_->GetPrimaryKeyViaIndex(&transaction2,
774 high_database_id,
775 high_object_store_id,
776 invalid_high_index_id,
777 index_key,
778 &new_primary_key);
779 EXPECT_FALSE(s.ok());
781 s = backing_store_->GetPrimaryKeyViaIndex(&transaction2,
782 high_database_id,
783 high_object_store_id,
784 high_index_id,
785 index_key,
786 &new_primary_key);
787 EXPECT_TRUE(s.ok());
788 EXPECT_TRUE(new_primary_key->Equals(m_key1));
790 scoped_refptr<TestCallback> callback(new TestCallback());
791 s = transaction2.CommitPhaseOne(callback);
792 EXPECT_TRUE(s.ok());
793 EXPECT_TRUE(callback->called);
794 EXPECT_TRUE(callback->succeeded);
795 s = transaction2.CommitPhaseTwo();
796 EXPECT_TRUE(s.ok());
800 // Make sure that other invalid ids do not crash.
801 TEST_F(IndexedDBBackingStoreTest, InvalidIds) {
802 // valid ids for use when testing invalid ids
803 const int64 database_id = 1;
804 const int64 object_store_id = 1;
805 const int64 index_id = kMinimumIndexId;
806 const int64 invalid_low_index_id = 19; // index_ids must be > kMinimumIndexId
808 IndexedDBValue result_value;
810 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
811 transaction1.Begin();
813 ScopedVector<storage::BlobDataHandle> handles;
814 IndexedDBBackingStore::RecordIdentifier record;
815 leveldb::Status s = backing_store_->PutRecord(&transaction1,
816 database_id,
817 KeyPrefix::kInvalidId,
818 m_key1,
819 &m_value1,
820 &handles,
821 &record);
822 EXPECT_FALSE(s.ok());
823 s = backing_store_->PutRecord(
824 &transaction1, database_id, 0, m_key1, &m_value1, &handles, &record);
825 EXPECT_FALSE(s.ok());
826 s = backing_store_->PutRecord(&transaction1,
827 KeyPrefix::kInvalidId,
828 object_store_id,
829 m_key1,
830 &m_value1,
831 &handles,
832 &record);
833 EXPECT_FALSE(s.ok());
834 s = backing_store_->PutRecord(
835 &transaction1, 0, object_store_id, m_key1, &m_value1, &handles, &record);
836 EXPECT_FALSE(s.ok());
838 s = backing_store_->GetRecord(
839 &transaction1, database_id, KeyPrefix::kInvalidId, m_key1, &result_value);
840 EXPECT_FALSE(s.ok());
841 s = backing_store_->GetRecord(
842 &transaction1, database_id, 0, m_key1, &result_value);
843 EXPECT_FALSE(s.ok());
844 s = backing_store_->GetRecord(&transaction1,
845 KeyPrefix::kInvalidId,
846 object_store_id,
847 m_key1,
848 &result_value);
849 EXPECT_FALSE(s.ok());
850 s = backing_store_->GetRecord(
851 &transaction1, 0, object_store_id, m_key1, &result_value);
852 EXPECT_FALSE(s.ok());
854 scoped_ptr<IndexedDBKey> new_primary_key;
855 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
856 database_id,
857 object_store_id,
858 KeyPrefix::kInvalidId,
859 m_key1,
860 &new_primary_key);
861 EXPECT_FALSE(s.ok());
862 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
863 database_id,
864 object_store_id,
865 invalid_low_index_id,
866 m_key1,
867 &new_primary_key);
868 EXPECT_FALSE(s.ok());
869 s = backing_store_->GetPrimaryKeyViaIndex(
870 &transaction1, database_id, object_store_id, 0, m_key1, &new_primary_key);
871 EXPECT_FALSE(s.ok());
873 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
874 KeyPrefix::kInvalidId,
875 object_store_id,
876 index_id,
877 m_key1,
878 &new_primary_key);
879 EXPECT_FALSE(s.ok());
880 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
881 database_id,
882 KeyPrefix::kInvalidId,
883 index_id,
884 m_key1,
885 &new_primary_key);
886 EXPECT_FALSE(s.ok());
889 TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
890 const base::string16 database_name(ASCIIToUTF16("db1"));
891 int64 database_id;
892 const base::string16 version(ASCIIToUTF16("old_string_version"));
893 const int64 int_version = 9;
895 const int64 object_store_id = 99;
896 const base::string16 object_store_name(ASCIIToUTF16("object_store1"));
897 const bool auto_increment = true;
898 const IndexedDBKeyPath object_store_key_path(
899 ASCIIToUTF16("object_store_key"));
901 const int64 index_id = 999;
902 const base::string16 index_name(ASCIIToUTF16("index1"));
903 const bool unique = true;
904 const bool multi_entry = true;
905 const IndexedDBKeyPath index_key_path(ASCIIToUTF16("index_key"));
908 leveldb::Status s = backing_store_->CreateIDBDatabaseMetaData(
909 database_name, version, int_version, &database_id);
910 EXPECT_TRUE(s.ok());
911 EXPECT_GT(database_id, 0);
913 IndexedDBBackingStore::Transaction transaction(backing_store_.get());
914 transaction.Begin();
916 s = backing_store_->CreateObjectStore(&transaction,
917 database_id,
918 object_store_id,
919 object_store_name,
920 object_store_key_path,
921 auto_increment);
922 EXPECT_TRUE(s.ok());
924 s = backing_store_->CreateIndex(&transaction,
925 database_id,
926 object_store_id,
927 index_id,
928 index_name,
929 index_key_path,
930 unique,
931 multi_entry);
932 EXPECT_TRUE(s.ok());
934 scoped_refptr<TestCallback> callback(new TestCallback());
935 s = transaction.CommitPhaseOne(callback);
936 EXPECT_TRUE(s.ok());
937 EXPECT_TRUE(callback->called);
938 EXPECT_TRUE(callback->succeeded);
939 s = transaction.CommitPhaseTwo();
940 EXPECT_TRUE(s.ok());
944 IndexedDBDatabaseMetadata database;
945 bool found;
946 leveldb::Status s = backing_store_->GetIDBDatabaseMetaData(
947 database_name, &database, &found);
948 EXPECT_TRUE(s.ok());
949 EXPECT_TRUE(found);
951 // database.name is not filled in by the implementation.
952 EXPECT_EQ(version, database.version);
953 EXPECT_EQ(int_version, database.int_version);
954 EXPECT_EQ(database_id, database.id);
956 s = backing_store_->GetObjectStores(database.id, &database.object_stores);
957 EXPECT_TRUE(s.ok());
959 EXPECT_EQ(1UL, database.object_stores.size());
960 IndexedDBObjectStoreMetadata object_store =
961 database.object_stores[object_store_id];
962 EXPECT_EQ(object_store_name, object_store.name);
963 EXPECT_EQ(object_store_key_path, object_store.key_path);
964 EXPECT_EQ(auto_increment, object_store.auto_increment);
966 EXPECT_EQ(1UL, object_store.indexes.size());
967 IndexedDBIndexMetadata index = object_store.indexes[index_id];
968 EXPECT_EQ(index_name, index.name);
969 EXPECT_EQ(index_key_path, index.key_path);
970 EXPECT_EQ(unique, index.unique);
971 EXPECT_EQ(multi_entry, index.multi_entry);
975 TEST_F(IndexedDBBackingStoreTest, GetDatabaseNames) {
976 const base::string16 string_version(ASCIIToUTF16("string_version"));
978 const base::string16 db1_name(ASCIIToUTF16("db1"));
979 const int64 db1_version = 1LL;
980 int64 db1_id;
982 // Database records with DEFAULT_INT_VERSION represent stale data,
983 // and should not be enumerated.
984 const base::string16 db2_name(ASCIIToUTF16("db2"));
985 const int64 db2_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
986 int64 db2_id;
988 leveldb::Status s = backing_store_->CreateIDBDatabaseMetaData(
989 db1_name, string_version, db1_version, &db1_id);
990 EXPECT_TRUE(s.ok());
991 EXPECT_GT(db1_id, 0LL);
993 s = backing_store_->CreateIDBDatabaseMetaData(
994 db2_name, string_version, db2_version, &db2_id);
995 EXPECT_TRUE(s.ok());
996 EXPECT_GT(db2_id, db1_id);
998 std::vector<base::string16> names = backing_store_->GetDatabaseNames(&s);
999 EXPECT_TRUE(s.ok());
1000 EXPECT_EQ(names.size(), 1ULL);
1001 EXPECT_EQ(names[0], db1_name);
1004 } // namespace
1006 } // namespace content