Rename isSystemLocationEnabled to isLocationEnabled, as per internal review (185995).
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_backing_store_unittest.cc
blob0b8ecef0e27c2e9dd1792a37e3b7760b5be42296
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_blob_info.push_back(
257 IndexedDBBlobInfo("uuid 5",
258 base::FilePath(),
259 base::UTF8ToUTF16("file name"),
260 base::UTF8ToUTF16("file type")));
261 m_value3 = IndexedDBValue("value3", m_blob_info);
263 m_key1 = IndexedDBKey(99, blink::WebIDBKeyTypeNumber);
264 m_key2 = IndexedDBKey(ASCIIToUTF16("key2"));
265 m_key3 = IndexedDBKey(ASCIIToUTF16("key3"));
268 // This just checks the data that survive getting stored and recalled, e.g.
269 // the file path and UUID will change and thus aren't verified.
270 bool CheckBlobInfoMatches(const std::vector<IndexedDBBlobInfo>& reads) const {
271 if (m_blob_info.size() != reads.size())
272 return false;
273 for (size_t i = 0; i < m_blob_info.size(); ++i) {
274 const IndexedDBBlobInfo& a = m_blob_info[i];
275 const IndexedDBBlobInfo& b = reads[i];
276 if (a.is_file() != b.is_file())
277 return false;
278 if (a.type() != b.type())
279 return false;
280 if (a.is_file()) {
281 if (a.file_name() != b.file_name())
282 return false;
283 } else {
284 if (a.size() != b.size())
285 return false;
288 return true;
291 bool CheckBlobReadsMatchWrites(
292 const std::vector<IndexedDBBlobInfo>& reads) const {
293 if (backing_store_->writes().size() != reads.size())
294 return false;
295 std::set<int64> ids;
296 for (size_t i = 0; i < backing_store_->writes().size(); ++i)
297 ids.insert(backing_store_->writes()[i].key());
298 if (ids.size() != backing_store_->writes().size())
299 return false;
300 for (size_t i = 0; i < reads.size(); ++i) {
301 if (ids.count(reads[i].key()) != 1)
302 return false;
304 return true;
307 bool CheckBlobWrites() const {
308 if (backing_store_->writes().size() != m_blob_info.size())
309 return false;
310 for (size_t i = 0; i < backing_store_->writes().size(); ++i) {
311 const IndexedDBBackingStore::Transaction::WriteDescriptor& desc =
312 backing_store_->writes()[i];
313 const IndexedDBBlobInfo& info = m_blob_info[i];
314 if (desc.is_file() != info.is_file()) {
315 if (!info.is_file() || !info.file_path().empty())
316 return false;
317 } else if (desc.is_file()) {
318 if (desc.file_path() != info.file_path())
319 return false;
320 } else {
321 if (desc.url() != GURL("blob:uuid/" + info.uuid()))
322 return false;
325 return true;
328 bool CheckBlobRemovals() const {
329 if (backing_store_->removals().size() != backing_store_->writes().size())
330 return false;
331 for (size_t i = 0; i < backing_store_->writes().size(); ++i) {
332 if (backing_store_->writes()[i].key() != backing_store_->removals()[i])
333 return false;
335 return true;
338 protected:
339 // Must be initialized before url_request_context_
340 content::TestBrowserThreadBundle thread_bundle_;
342 base::ScopedTempDir temp_dir_;
343 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
344 scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
345 scoped_refptr<IndexedDBContextImpl> idb_context_;
346 scoped_refptr<TestIDBFactory> idb_factory_;
347 net::TestURLRequestContext url_request_context_;
349 scoped_refptr<TestableIndexedDBBackingStore> backing_store_;
351 // Sample keys and values that are consistent.
352 IndexedDBKey m_key1;
353 IndexedDBKey m_key2;
354 IndexedDBKey m_key3;
355 IndexedDBValue m_value1;
356 IndexedDBValue m_value2;
357 IndexedDBValue m_value3;
358 std::vector<IndexedDBBlobInfo> m_blob_info;
360 private:
361 DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest);
364 class TestCallback : public IndexedDBBackingStore::BlobWriteCallback {
365 public:
366 TestCallback() : called(false), succeeded(false) {}
367 void Run(bool succeeded_in) override {
368 called = true;
369 succeeded = succeeded_in;
371 bool called;
372 bool succeeded;
374 protected:
375 ~TestCallback() override {}
377 private:
378 DISALLOW_COPY_AND_ASSIGN(TestCallback);
381 TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
383 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
384 transaction1.Begin();
385 ScopedVector<storage::BlobDataHandle> handles;
386 IndexedDBBackingStore::RecordIdentifier record;
387 leveldb::Status s = backing_store_->PutRecord(
388 &transaction1, 1, 1, m_key1, &m_value1, &handles, &record);
389 EXPECT_TRUE(s.ok());
390 scoped_refptr<TestCallback> callback(new TestCallback());
391 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
392 EXPECT_TRUE(callback->called);
393 EXPECT_TRUE(callback->succeeded);
394 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
398 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
399 transaction2.Begin();
400 IndexedDBValue result_value;
401 EXPECT_TRUE(
402 backing_store_->GetRecord(&transaction2, 1, 1, m_key1, &result_value)
403 .ok());
404 scoped_refptr<TestCallback> callback(new TestCallback());
405 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
406 EXPECT_TRUE(callback->called);
407 EXPECT_TRUE(callback->succeeded);
408 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
409 EXPECT_EQ(m_value1.bits, result_value.bits);
413 TEST_F(IndexedDBBackingStoreTest, PutGetConsistencyWithBlobs) {
415 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
416 transaction1.Begin();
417 ScopedVector<storage::BlobDataHandle> handles;
418 IndexedDBBackingStore::RecordIdentifier record;
419 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
422 m_key3,
423 &m_value3,
424 &handles,
425 &record).ok());
426 scoped_refptr<TestCallback> callback(new TestCallback());
427 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
428 task_runner_->RunUntilIdle();
429 EXPECT_TRUE(CheckBlobWrites());
430 EXPECT_TRUE(callback->called);
431 EXPECT_TRUE(callback->succeeded);
432 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
436 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
437 transaction2.Begin();
438 IndexedDBValue result_value;
439 EXPECT_TRUE(
440 backing_store_->GetRecord(&transaction2, 1, 1, m_key3, &result_value)
441 .ok());
442 scoped_refptr<TestCallback> callback(new TestCallback());
443 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
444 EXPECT_TRUE(callback->called);
445 EXPECT_TRUE(callback->succeeded);
446 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
447 EXPECT_EQ(m_value3.bits, result_value.bits);
448 EXPECT_TRUE(CheckBlobInfoMatches(result_value.blob_info));
449 EXPECT_TRUE(CheckBlobReadsMatchWrites(result_value.blob_info));
453 IndexedDBBackingStore::Transaction transaction3(backing_store_.get());
454 transaction3.Begin();
455 IndexedDBValue result_value;
456 EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
459 IndexedDBKeyRange(m_key3)).ok());
460 scoped_refptr<TestCallback> callback(new TestCallback());
461 EXPECT_TRUE(transaction3.CommitPhaseOne(callback).ok());
462 task_runner_->RunUntilIdle();
463 EXPECT_TRUE(callback->called);
464 EXPECT_TRUE(callback->succeeded);
465 EXPECT_TRUE(transaction3.CommitPhaseTwo().ok());
466 EXPECT_TRUE(CheckBlobRemovals());
470 TEST_F(IndexedDBBackingStoreTest, DeleteRange) {
471 IndexedDBKey key0 = IndexedDBKey(ASCIIToUTF16("key0"));
472 IndexedDBKey key1 = IndexedDBKey(ASCIIToUTF16("key1"));
473 IndexedDBKey key2 = IndexedDBKey(ASCIIToUTF16("key2"));
474 IndexedDBKey key3 = IndexedDBKey(ASCIIToUTF16("key3"));
475 IndexedDBBlobInfo blob0("uuid 0", base::UTF8ToUTF16("type 0"), 1);
476 IndexedDBBlobInfo blob1("uuid 1", base::UTF8ToUTF16("type 1"), 1);
477 IndexedDBBlobInfo blob2("uuid 2", base::UTF8ToUTF16("type 2"), 1);
478 IndexedDBBlobInfo blob3("uuid 3", base::UTF8ToUTF16("type 3"), 1);
479 IndexedDBKeyRange ranges[] = {IndexedDBKeyRange(key1, key2, false, false),
480 IndexedDBKeyRange(key1, key2, false, false),
481 IndexedDBKeyRange(key0, key2, true, false),
482 IndexedDBKeyRange(key1, key3, false, true),
483 IndexedDBKeyRange(key0, key3, true, true)};
485 for (unsigned i = 0; i < sizeof(ranges) / sizeof(IndexedDBKeyRange); ++i) {
486 backing_store_->ClearWrites();
487 backing_store_->ClearRemovals();
490 std::vector<IndexedDBBlobInfo> blob_info0, blob_info1, blob_info2,
491 blob_info3;
492 blob_info0.push_back(blob0);
493 blob_info1.push_back(blob1);
494 blob_info2.push_back(blob2);
495 blob_info3.push_back(blob3);
496 IndexedDBValue value0 = IndexedDBValue("value0", blob_info0);
497 IndexedDBValue value1 = IndexedDBValue("value1", blob_info1);
498 IndexedDBValue value2 = IndexedDBValue("value2", blob_info2);
499 IndexedDBValue value3 = IndexedDBValue("value3", blob_info3);
500 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
501 transaction1.Begin();
502 ScopedVector<storage::BlobDataHandle> handles;
503 IndexedDBBackingStore::RecordIdentifier record;
504 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
506 i + 1,
507 key0,
508 &value0,
509 &handles,
510 &record).ok());
511 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
513 i + 1,
514 key1,
515 &value1,
516 &handles,
517 &record).ok());
518 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
520 i + 1,
521 key2,
522 &value2,
523 &handles,
524 &record).ok());
525 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
527 i + 1,
528 key3,
529 &value3,
530 &handles,
531 &record).ok());
532 scoped_refptr<TestCallback> callback(new TestCallback());
533 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
534 task_runner_->RunUntilIdle();
535 EXPECT_TRUE(callback->called);
536 EXPECT_TRUE(callback->succeeded);
537 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
541 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
542 transaction2.Begin();
543 IndexedDBValue result_value;
544 EXPECT_TRUE(
545 backing_store_->DeleteRange(&transaction2, 1, i + 1, ranges[i]).ok());
546 scoped_refptr<TestCallback> callback(new TestCallback());
547 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
548 task_runner_->RunUntilIdle();
549 EXPECT_TRUE(callback->called);
550 EXPECT_TRUE(callback->succeeded);
551 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
552 EXPECT_EQ(2UL, backing_store_->removals().size());
553 EXPECT_EQ(backing_store_->writes()[1].key(),
554 backing_store_->removals()[0]);
555 EXPECT_EQ(backing_store_->writes()[2].key(),
556 backing_store_->removals()[1]);
561 TEST_F(IndexedDBBackingStoreTest, DeleteRangeEmptyRange) {
562 IndexedDBKey key0 = IndexedDBKey(ASCIIToUTF16("key0"));
563 IndexedDBKey key1 = IndexedDBKey(ASCIIToUTF16("key1"));
564 IndexedDBKey key2 = IndexedDBKey(ASCIIToUTF16("key2"));
565 IndexedDBKey key3 = IndexedDBKey(ASCIIToUTF16("key3"));
566 IndexedDBKey key4 = IndexedDBKey(ASCIIToUTF16("key4"));
567 IndexedDBBlobInfo blob0("uuid 0", base::UTF8ToUTF16("type 0"), 1);
568 IndexedDBBlobInfo blob1("uuid 1", base::UTF8ToUTF16("type 1"), 1);
569 IndexedDBBlobInfo blob2("uuid 2", base::UTF8ToUTF16("type 2"), 1);
570 IndexedDBBlobInfo blob3("uuid 3", base::UTF8ToUTF16("type 3"), 1);
571 IndexedDBKeyRange ranges[] = {IndexedDBKeyRange(key3, key4, true, false),
572 IndexedDBKeyRange(key2, key1, false, false),
573 IndexedDBKeyRange(key2, key1, true, true)};
575 for (unsigned i = 0; i < arraysize(ranges); ++i) {
576 backing_store_->ClearWrites();
577 backing_store_->ClearRemovals();
580 std::vector<IndexedDBBlobInfo> blob_info0, blob_info1, blob_info2,
581 blob_info3;
582 blob_info0.push_back(blob0);
583 blob_info1.push_back(blob1);
584 blob_info2.push_back(blob2);
585 blob_info3.push_back(blob3);
586 IndexedDBValue value0 = IndexedDBValue("value0", blob_info0);
587 IndexedDBValue value1 = IndexedDBValue("value1", blob_info1);
588 IndexedDBValue value2 = IndexedDBValue("value2", blob_info2);
589 IndexedDBValue value3 = IndexedDBValue("value3", blob_info3);
590 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
591 transaction1.Begin();
592 ScopedVector<storage::BlobDataHandle> handles;
593 IndexedDBBackingStore::RecordIdentifier record;
594 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
596 i + 1,
597 key0,
598 &value0,
599 &handles,
600 &record).ok());
601 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
603 i + 1,
604 key1,
605 &value1,
606 &handles,
607 &record).ok());
608 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
610 i + 1,
611 key2,
612 &value2,
613 &handles,
614 &record).ok());
615 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
617 i + 1,
618 key3,
619 &value3,
620 &handles,
621 &record).ok());
622 scoped_refptr<TestCallback> callback(new TestCallback());
623 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
624 task_runner_->RunUntilIdle();
625 EXPECT_TRUE(callback->called);
626 EXPECT_TRUE(callback->succeeded);
627 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
631 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
632 transaction2.Begin();
633 IndexedDBValue result_value;
634 EXPECT_TRUE(
635 backing_store_->DeleteRange(&transaction2, 1, i + 1, ranges[i]).ok());
636 scoped_refptr<TestCallback> callback(new TestCallback());
637 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
638 task_runner_->RunUntilIdle();
639 EXPECT_TRUE(callback->called);
640 EXPECT_TRUE(callback->succeeded);
641 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
642 EXPECT_EQ(0UL, backing_store_->removals().size());
647 TEST_F(IndexedDBBackingStoreTest, LiveBlobJournal) {
649 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
650 transaction1.Begin();
651 ScopedVector<storage::BlobDataHandle> handles;
652 IndexedDBBackingStore::RecordIdentifier record;
653 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
656 m_key3,
657 &m_value3,
658 &handles,
659 &record).ok());
660 scoped_refptr<TestCallback> callback(new TestCallback());
661 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
662 task_runner_->RunUntilIdle();
663 EXPECT_TRUE(CheckBlobWrites());
664 EXPECT_TRUE(callback->called);
665 EXPECT_TRUE(callback->succeeded);
666 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
669 IndexedDBValue read_result_value;
671 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
672 transaction2.Begin();
673 EXPECT_TRUE(
674 backing_store_->GetRecord(
675 &transaction2, 1, 1, m_key3, &read_result_value)
676 .ok());
677 scoped_refptr<TestCallback> callback(new TestCallback());
678 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
679 EXPECT_TRUE(callback->called);
680 EXPECT_TRUE(callback->succeeded);
681 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
682 EXPECT_EQ(m_value3.bits, read_result_value.bits);
683 EXPECT_TRUE(CheckBlobInfoMatches(read_result_value.blob_info));
684 EXPECT_TRUE(CheckBlobReadsMatchWrites(read_result_value.blob_info));
685 for (size_t i = 0; i < read_result_value.blob_info.size(); ++i) {
686 read_result_value.blob_info[i].mark_used_callback().Run();
691 IndexedDBBackingStore::Transaction transaction3(backing_store_.get());
692 transaction3.Begin();
693 EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
696 IndexedDBKeyRange(m_key3)).ok());
697 scoped_refptr<TestCallback> callback(new TestCallback());
698 EXPECT_TRUE(transaction3.CommitPhaseOne(callback).ok());
699 task_runner_->RunUntilIdle();
700 EXPECT_TRUE(callback->called);
701 EXPECT_TRUE(callback->succeeded);
702 EXPECT_TRUE(transaction3.CommitPhaseTwo().ok());
703 EXPECT_EQ(0U, backing_store_->removals().size());
704 for (size_t i = 0; i < read_result_value.blob_info.size(); ++i) {
705 read_result_value.blob_info[i].release_callback().Run(
706 read_result_value.blob_info[i].file_path());
708 task_runner_->RunUntilIdle();
709 EXPECT_NE(0U, backing_store_->removals().size());
710 EXPECT_TRUE(CheckBlobRemovals());
714 // Make sure that using very high ( more than 32 bit ) values for database_id
715 // and object_store_id still work.
716 TEST_F(IndexedDBBackingStoreTest, HighIds) {
717 const int64 high_database_id = 1ULL << 35;
718 const int64 high_object_store_id = 1ULL << 39;
719 // index_ids are capped at 32 bits for storage purposes.
720 const int64 high_index_id = 1ULL << 29;
722 const int64 invalid_high_index_id = 1ULL << 37;
724 const IndexedDBKey& index_key = m_key2;
725 std::string index_key_raw;
726 EncodeIDBKey(index_key, &index_key_raw);
728 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
729 transaction1.Begin();
730 ScopedVector<storage::BlobDataHandle> handles;
731 IndexedDBBackingStore::RecordIdentifier record;
732 leveldb::Status s = backing_store_->PutRecord(&transaction1,
733 high_database_id,
734 high_object_store_id,
735 m_key1,
736 &m_value1,
737 &handles,
738 &record);
739 EXPECT_TRUE(s.ok());
741 s = backing_store_->PutIndexDataForRecord(&transaction1,
742 high_database_id,
743 high_object_store_id,
744 invalid_high_index_id,
745 index_key,
746 record);
747 EXPECT_FALSE(s.ok());
749 s = backing_store_->PutIndexDataForRecord(&transaction1,
750 high_database_id,
751 high_object_store_id,
752 high_index_id,
753 index_key,
754 record);
755 EXPECT_TRUE(s.ok());
757 scoped_refptr<TestCallback> callback(new TestCallback());
758 s = transaction1.CommitPhaseOne(callback);
759 EXPECT_TRUE(s.ok());
760 EXPECT_TRUE(callback->called);
761 EXPECT_TRUE(callback->succeeded);
762 s = transaction1.CommitPhaseTwo();
763 EXPECT_TRUE(s.ok());
767 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
768 transaction2.Begin();
769 IndexedDBValue result_value;
770 leveldb::Status s = backing_store_->GetRecord(&transaction2,
771 high_database_id,
772 high_object_store_id,
773 m_key1,
774 &result_value);
775 EXPECT_TRUE(s.ok());
776 EXPECT_EQ(m_value1.bits, result_value.bits);
778 scoped_ptr<IndexedDBKey> new_primary_key;
779 s = backing_store_->GetPrimaryKeyViaIndex(&transaction2,
780 high_database_id,
781 high_object_store_id,
782 invalid_high_index_id,
783 index_key,
784 &new_primary_key);
785 EXPECT_FALSE(s.ok());
787 s = backing_store_->GetPrimaryKeyViaIndex(&transaction2,
788 high_database_id,
789 high_object_store_id,
790 high_index_id,
791 index_key,
792 &new_primary_key);
793 EXPECT_TRUE(s.ok());
794 EXPECT_TRUE(new_primary_key->Equals(m_key1));
796 scoped_refptr<TestCallback> callback(new TestCallback());
797 s = transaction2.CommitPhaseOne(callback);
798 EXPECT_TRUE(s.ok());
799 EXPECT_TRUE(callback->called);
800 EXPECT_TRUE(callback->succeeded);
801 s = transaction2.CommitPhaseTwo();
802 EXPECT_TRUE(s.ok());
806 // Make sure that other invalid ids do not crash.
807 TEST_F(IndexedDBBackingStoreTest, InvalidIds) {
808 // valid ids for use when testing invalid ids
809 const int64 database_id = 1;
810 const int64 object_store_id = 1;
811 const int64 index_id = kMinimumIndexId;
812 const int64 invalid_low_index_id = 19; // index_ids must be > kMinimumIndexId
814 IndexedDBValue result_value;
816 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
817 transaction1.Begin();
819 ScopedVector<storage::BlobDataHandle> handles;
820 IndexedDBBackingStore::RecordIdentifier record;
821 leveldb::Status s = backing_store_->PutRecord(&transaction1,
822 database_id,
823 KeyPrefix::kInvalidId,
824 m_key1,
825 &m_value1,
826 &handles,
827 &record);
828 EXPECT_FALSE(s.ok());
829 s = backing_store_->PutRecord(
830 &transaction1, database_id, 0, m_key1, &m_value1, &handles, &record);
831 EXPECT_FALSE(s.ok());
832 s = backing_store_->PutRecord(&transaction1,
833 KeyPrefix::kInvalidId,
834 object_store_id,
835 m_key1,
836 &m_value1,
837 &handles,
838 &record);
839 EXPECT_FALSE(s.ok());
840 s = backing_store_->PutRecord(
841 &transaction1, 0, object_store_id, m_key1, &m_value1, &handles, &record);
842 EXPECT_FALSE(s.ok());
844 s = backing_store_->GetRecord(
845 &transaction1, database_id, KeyPrefix::kInvalidId, m_key1, &result_value);
846 EXPECT_FALSE(s.ok());
847 s = backing_store_->GetRecord(
848 &transaction1, database_id, 0, m_key1, &result_value);
849 EXPECT_FALSE(s.ok());
850 s = backing_store_->GetRecord(&transaction1,
851 KeyPrefix::kInvalidId,
852 object_store_id,
853 m_key1,
854 &result_value);
855 EXPECT_FALSE(s.ok());
856 s = backing_store_->GetRecord(
857 &transaction1, 0, object_store_id, m_key1, &result_value);
858 EXPECT_FALSE(s.ok());
860 scoped_ptr<IndexedDBKey> new_primary_key;
861 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
862 database_id,
863 object_store_id,
864 KeyPrefix::kInvalidId,
865 m_key1,
866 &new_primary_key);
867 EXPECT_FALSE(s.ok());
868 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
869 database_id,
870 object_store_id,
871 invalid_low_index_id,
872 m_key1,
873 &new_primary_key);
874 EXPECT_FALSE(s.ok());
875 s = backing_store_->GetPrimaryKeyViaIndex(
876 &transaction1, database_id, object_store_id, 0, m_key1, &new_primary_key);
877 EXPECT_FALSE(s.ok());
879 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
880 KeyPrefix::kInvalidId,
881 object_store_id,
882 index_id,
883 m_key1,
884 &new_primary_key);
885 EXPECT_FALSE(s.ok());
886 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
887 database_id,
888 KeyPrefix::kInvalidId,
889 index_id,
890 m_key1,
891 &new_primary_key);
892 EXPECT_FALSE(s.ok());
895 TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
896 const base::string16 database_name(ASCIIToUTF16("db1"));
897 int64 database_id;
898 const base::string16 version(ASCIIToUTF16("old_string_version"));
899 const int64 int_version = 9;
901 const int64 object_store_id = 99;
902 const base::string16 object_store_name(ASCIIToUTF16("object_store1"));
903 const bool auto_increment = true;
904 const IndexedDBKeyPath object_store_key_path(
905 ASCIIToUTF16("object_store_key"));
907 const int64 index_id = 999;
908 const base::string16 index_name(ASCIIToUTF16("index1"));
909 const bool unique = true;
910 const bool multi_entry = true;
911 const IndexedDBKeyPath index_key_path(ASCIIToUTF16("index_key"));
914 leveldb::Status s = backing_store_->CreateIDBDatabaseMetaData(
915 database_name, version, int_version, &database_id);
916 EXPECT_TRUE(s.ok());
917 EXPECT_GT(database_id, 0);
919 IndexedDBBackingStore::Transaction transaction(backing_store_.get());
920 transaction.Begin();
922 s = backing_store_->CreateObjectStore(&transaction,
923 database_id,
924 object_store_id,
925 object_store_name,
926 object_store_key_path,
927 auto_increment);
928 EXPECT_TRUE(s.ok());
930 s = backing_store_->CreateIndex(&transaction,
931 database_id,
932 object_store_id,
933 index_id,
934 index_name,
935 index_key_path,
936 unique,
937 multi_entry);
938 EXPECT_TRUE(s.ok());
940 scoped_refptr<TestCallback> callback(new TestCallback());
941 s = transaction.CommitPhaseOne(callback);
942 EXPECT_TRUE(s.ok());
943 EXPECT_TRUE(callback->called);
944 EXPECT_TRUE(callback->succeeded);
945 s = transaction.CommitPhaseTwo();
946 EXPECT_TRUE(s.ok());
950 IndexedDBDatabaseMetadata database;
951 bool found;
952 leveldb::Status s = backing_store_->GetIDBDatabaseMetaData(
953 database_name, &database, &found);
954 EXPECT_TRUE(s.ok());
955 EXPECT_TRUE(found);
957 // database.name is not filled in by the implementation.
958 EXPECT_EQ(version, database.version);
959 EXPECT_EQ(int_version, database.int_version);
960 EXPECT_EQ(database_id, database.id);
962 s = backing_store_->GetObjectStores(database.id, &database.object_stores);
963 EXPECT_TRUE(s.ok());
965 EXPECT_EQ(1UL, database.object_stores.size());
966 IndexedDBObjectStoreMetadata object_store =
967 database.object_stores[object_store_id];
968 EXPECT_EQ(object_store_name, object_store.name);
969 EXPECT_EQ(object_store_key_path, object_store.key_path);
970 EXPECT_EQ(auto_increment, object_store.auto_increment);
972 EXPECT_EQ(1UL, object_store.indexes.size());
973 IndexedDBIndexMetadata index = object_store.indexes[index_id];
974 EXPECT_EQ(index_name, index.name);
975 EXPECT_EQ(index_key_path, index.key_path);
976 EXPECT_EQ(unique, index.unique);
977 EXPECT_EQ(multi_entry, index.multi_entry);
981 TEST_F(IndexedDBBackingStoreTest, GetDatabaseNames) {
982 const base::string16 string_version(ASCIIToUTF16("string_version"));
984 const base::string16 db1_name(ASCIIToUTF16("db1"));
985 const int64 db1_version = 1LL;
986 int64 db1_id;
988 // Database records with DEFAULT_INT_VERSION represent stale data,
989 // and should not be enumerated.
990 const base::string16 db2_name(ASCIIToUTF16("db2"));
991 const int64 db2_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
992 int64 db2_id;
994 leveldb::Status s = backing_store_->CreateIDBDatabaseMetaData(
995 db1_name, string_version, db1_version, &db1_id);
996 EXPECT_TRUE(s.ok());
997 EXPECT_GT(db1_id, 0LL);
999 s = backing_store_->CreateIDBDatabaseMetaData(
1000 db2_name, string_version, db2_version, &db2_id);
1001 EXPECT_TRUE(s.ok());
1002 EXPECT_GT(db2_id, db1_id);
1004 std::vector<base::string16> names = backing_store_->GetDatabaseNames(&s);
1005 EXPECT_TRUE(s.ok());
1006 EXPECT_EQ(names.size(), 1ULL);
1007 EXPECT_EQ(names[0], db1_name);
1010 } // namespace
1012 } // namespace content