Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_backing_store_unittest.cc
blob43724c1e5caeeb33d982373e204722daa9c023b7
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/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 "testing/gtest/include/gtest/gtest.h"
25 #include "third_party/WebKit/public/platform/WebIDBTypes.h"
26 #include "webkit/browser/blob/blob_data_handle.h"
27 #include "webkit/browser/quota/special_storage_policy.h"
29 using base::ASCIIToUTF16;
31 namespace content {
33 namespace {
35 class Comparator : public LevelDBComparator {
36 public:
37 virtual int Compare(const base::StringPiece& a,
38 const base::StringPiece& b) const OVERRIDE {
39 return content::Compare(a, b, false /*index_keys*/);
41 virtual const char* Name() const OVERRIDE { return "idb_cmp1"; }
44 class DefaultLevelDBFactory : public LevelDBFactory {
45 public:
46 DefaultLevelDBFactory() {}
47 virtual 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 virtual leveldb::Status DestroyLevelDB(
54 const base::FilePath& file_name) OVERRIDE {
55 return LevelDBDatabase::Destroy(file_name);
58 private:
59 DISALLOW_COPY_AND_ASSIGN(DefaultLevelDBFactory);
62 class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
63 public:
64 static scoped_refptr<TestableIndexedDBBackingStore> Open(
65 IndexedDBFactory* indexed_db_factory,
66 const GURL& origin_url,
67 const base::FilePath& path_base,
68 net::URLRequestContext* request_context,
69 LevelDBFactory* leveldb_factory,
70 base::SequencedTaskRunner* task_runner,
71 leveldb::Status* status) {
72 DCHECK(!path_base.empty());
74 scoped_ptr<LevelDBComparator> comparator(new Comparator());
76 if (!base::CreateDirectory(path_base)) {
77 *status = leveldb::Status::IOError("Unable to create base dir");
78 return scoped_refptr<TestableIndexedDBBackingStore>();
81 const base::FilePath file_path = path_base.AppendASCII("test_db_path");
82 const base::FilePath blob_path = path_base.AppendASCII("test_blob_path");
84 scoped_ptr<LevelDBDatabase> db;
85 bool is_disk_full = false;
86 *status = leveldb_factory->OpenLevelDB(
87 file_path, comparator.get(), &db, &is_disk_full);
89 if (!db || !status->ok())
90 return scoped_refptr<TestableIndexedDBBackingStore>();
92 scoped_refptr<TestableIndexedDBBackingStore> backing_store(
93 new TestableIndexedDBBackingStore(indexed_db_factory,
94 origin_url,
95 blob_path,
96 request_context,
97 db.Pass(),
98 comparator.Pass(),
99 task_runner));
101 *status = backing_store->SetUpMetadata();
102 if (!status->ok())
103 return scoped_refptr<TestableIndexedDBBackingStore>();
105 return backing_store;
108 const std::vector<IndexedDBBackingStore::Transaction::WriteDescriptor>&
109 writes() const {
110 return writes_;
112 void ClearWrites() { writes_.clear(); }
113 const std::vector<int64>& removals() const { return removals_; }
114 void ClearRemovals() { removals_.clear(); }
116 protected:
117 virtual ~TestableIndexedDBBackingStore() {}
119 virtual bool WriteBlobFile(
120 int64 database_id,
121 const Transaction::WriteDescriptor& descriptor,
122 Transaction::ChainedBlobWriter* chained_blob_writer) OVERRIDE {
123 if (KeyPrefix::IsValidDatabaseId(database_id_)) {
124 if (database_id_ != database_id) {
125 return false;
127 } else {
128 database_id_ = database_id;
130 writes_.push_back(descriptor);
131 task_runner()->PostTask(
132 FROM_HERE,
133 base::Bind(&Transaction::ChainedBlobWriter::ReportWriteCompletion,
134 chained_blob_writer,
135 true,
136 1));
137 return true;
140 virtual bool RemoveBlobFile(int64 database_id, int64 key) OVERRIDE {
141 if (database_id_ != database_id ||
142 !KeyPrefix::IsValidDatabaseId(database_id)) {
143 return false;
145 removals_.push_back(key);
146 return true;
149 // Timers don't play nicely with unit tests.
150 virtual void StartJournalCleaningTimer() OVERRIDE {
151 CleanPrimaryJournalIgnoreReturn();
154 private:
155 TestableIndexedDBBackingStore(IndexedDBFactory* indexed_db_factory,
156 const GURL& origin_url,
157 const base::FilePath& blob_path,
158 net::URLRequestContext* request_context,
159 scoped_ptr<LevelDBDatabase> db,
160 scoped_ptr<LevelDBComparator> comparator,
161 base::SequencedTaskRunner* task_runner)
162 : IndexedDBBackingStore(indexed_db_factory,
163 origin_url,
164 blob_path,
165 request_context,
166 db.Pass(),
167 comparator.Pass(),
168 task_runner),
169 database_id_(0) {}
171 int64 database_id_;
172 std::vector<Transaction::WriteDescriptor> writes_;
173 std::vector<int64> removals_;
175 DISALLOW_COPY_AND_ASSIGN(TestableIndexedDBBackingStore);
178 class TestIDBFactory : public IndexedDBFactoryImpl {
179 public:
180 explicit TestIDBFactory(IndexedDBContextImpl* idb_context)
181 : IndexedDBFactoryImpl(idb_context) {}
183 scoped_refptr<TestableIndexedDBBackingStore> OpenBackingStoreForTest(
184 const GURL& origin,
185 net::URLRequestContext* url_request_context) {
186 blink::WebIDBDataLoss data_loss;
187 std::string data_loss_reason;
188 bool disk_full;
189 leveldb::Status status;
190 scoped_refptr<IndexedDBBackingStore> backing_store =
191 OpenBackingStore(origin,
192 context()->data_path(),
193 url_request_context,
194 &data_loss,
195 &data_loss_reason,
196 &disk_full,
197 &status);
198 scoped_refptr<TestableIndexedDBBackingStore> testable_store =
199 static_cast<TestableIndexedDBBackingStore*>(backing_store.get());
200 return testable_store;
203 protected:
204 virtual ~TestIDBFactory() {}
206 virtual scoped_refptr<IndexedDBBackingStore> OpenBackingStoreHelper(
207 const GURL& origin_url,
208 const base::FilePath& data_directory,
209 net::URLRequestContext* request_context,
210 blink::WebIDBDataLoss* data_loss,
211 std::string* data_loss_message,
212 bool* disk_full,
213 bool first_time,
214 leveldb::Status* status) OVERRIDE {
215 DefaultLevelDBFactory leveldb_factory;
216 return TestableIndexedDBBackingStore::Open(this,
217 origin_url,
218 data_directory,
219 request_context,
220 &leveldb_factory,
221 context()->TaskRunner(),
222 status);
225 private:
226 DISALLOW_COPY_AND_ASSIGN(TestIDBFactory);
229 class IndexedDBBackingStoreTest : public testing::Test {
230 public:
231 IndexedDBBackingStoreTest() {}
232 virtual void SetUp() {
233 const GURL origin("http://localhost:81");
234 task_runner_ = new base::TestSimpleTaskRunner();
235 special_storage_policy_ = new MockSpecialStoragePolicy();
236 special_storage_policy_->SetAllUnlimited(true);
237 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
238 idb_context_ = new IndexedDBContextImpl(temp_dir_.path(),
239 special_storage_policy_.get(),
240 NULL,
241 task_runner_.get());
242 idb_factory_ = new TestIDBFactory(idb_context_.get());
243 backing_store_ =
244 idb_factory_->OpenBackingStoreForTest(origin, &url_request_context_);
246 // useful keys and values during tests
247 m_value1 = IndexedDBValue("value1", std::vector<IndexedDBBlobInfo>());
248 m_value2 = IndexedDBValue("value2", std::vector<IndexedDBBlobInfo>());
250 m_blob_info.push_back(
251 IndexedDBBlobInfo("uuid 3", base::UTF8ToUTF16("blob type"), 1));
252 m_blob_info.push_back(
253 IndexedDBBlobInfo("uuid 4",
254 base::FilePath(FILE_PATH_LITERAL("path/to/file")),
255 base::UTF8ToUTF16("file name"),
256 base::UTF8ToUTF16("file type")));
257 m_value3 = IndexedDBValue("value3", m_blob_info);
259 m_key1 = IndexedDBKey(99, blink::WebIDBKeyTypeNumber);
260 m_key2 = IndexedDBKey(ASCIIToUTF16("key2"));
261 m_key3 = IndexedDBKey(ASCIIToUTF16("key3"));
264 // This just checks the data that survive getting stored and recalled, e.g.
265 // the file path and UUID will change and thus aren't verified.
266 bool CheckBlobInfoMatches(const std::vector<IndexedDBBlobInfo>& reads) const {
267 if (m_blob_info.size() != reads.size())
268 return false;
269 for (size_t i = 0; i < m_blob_info.size(); ++i) {
270 const IndexedDBBlobInfo& a = m_blob_info[i];
271 const IndexedDBBlobInfo& b = reads[i];
272 if (a.is_file() != b.is_file())
273 return false;
274 if (a.type() != b.type())
275 return false;
276 if (a.is_file()) {
277 if (a.file_name() != b.file_name())
278 return false;
279 } else {
280 if (a.size() != b.size())
281 return false;
284 return true;
287 bool CheckBlobReadsMatchWrites(
288 const std::vector<IndexedDBBlobInfo>& reads) const {
289 if (backing_store_->writes().size() != reads.size())
290 return false;
291 std::set<int64> ids;
292 for (size_t i = 0; i < backing_store_->writes().size(); ++i)
293 ids.insert(backing_store_->writes()[i].key());
294 if (ids.size() != backing_store_->writes().size())
295 return false;
296 for (size_t i = 0; i < reads.size(); ++i) {
297 if (ids.count(reads[i].key()) != 1)
298 return false;
300 return true;
303 bool CheckBlobWrites() const {
304 if (backing_store_->writes().size() != m_blob_info.size())
305 return false;
306 for (size_t i = 0; i < backing_store_->writes().size(); ++i) {
307 const IndexedDBBackingStore::Transaction::WriteDescriptor& desc =
308 backing_store_->writes()[i];
309 const IndexedDBBlobInfo& info = m_blob_info[i];
310 if (desc.is_file() != info.is_file())
311 return false;
312 if (desc.is_file()) {
313 if (desc.file_path() != info.file_path())
314 return false;
315 } else {
316 if (desc.url() != GURL("blob:uuid/" + info.uuid()))
317 return false;
320 return true;
323 bool CheckBlobRemovals() const {
324 if (backing_store_->removals().size() != backing_store_->writes().size())
325 return false;
326 for (size_t i = 0; i < backing_store_->writes().size(); ++i) {
327 if (backing_store_->writes()[i].key() != backing_store_->removals()[i])
328 return false;
330 return true;
333 protected:
334 // Must be initialized before url_request_context_
335 content::TestBrowserThreadBundle thread_bundle_;
337 base::ScopedTempDir temp_dir_;
338 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
339 scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
340 scoped_refptr<IndexedDBContextImpl> idb_context_;
341 scoped_refptr<TestIDBFactory> idb_factory_;
342 net::TestURLRequestContext url_request_context_;
344 scoped_refptr<TestableIndexedDBBackingStore> backing_store_;
346 // Sample keys and values that are consistent.
347 IndexedDBKey m_key1;
348 IndexedDBKey m_key2;
349 IndexedDBKey m_key3;
350 IndexedDBValue m_value1;
351 IndexedDBValue m_value2;
352 IndexedDBValue m_value3;
353 std::vector<IndexedDBBlobInfo> m_blob_info;
355 private:
356 DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest);
359 class TestCallback : public IndexedDBBackingStore::BlobWriteCallback {
360 public:
361 TestCallback() : called(false), succeeded(false) {}
362 virtual void Run(bool succeeded_in) OVERRIDE {
363 called = true;
364 succeeded = succeeded_in;
366 bool called;
367 bool succeeded;
369 protected:
370 virtual ~TestCallback() {}
372 private:
373 DISALLOW_COPY_AND_ASSIGN(TestCallback);
376 TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
378 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
379 transaction1.Begin();
380 ScopedVector<storage::BlobDataHandle> handles;
381 IndexedDBBackingStore::RecordIdentifier record;
382 leveldb::Status s = backing_store_->PutRecord(
383 &transaction1, 1, 1, m_key1, &m_value1, &handles, &record);
384 EXPECT_TRUE(s.ok());
385 scoped_refptr<TestCallback> callback(new TestCallback());
386 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
387 EXPECT_TRUE(callback->called);
388 EXPECT_TRUE(callback->succeeded);
389 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
393 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
394 transaction2.Begin();
395 IndexedDBValue result_value;
396 EXPECT_TRUE(
397 backing_store_->GetRecord(&transaction2, 1, 1, m_key1, &result_value)
398 .ok());
399 scoped_refptr<TestCallback> callback(new TestCallback());
400 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
401 EXPECT_TRUE(callback->called);
402 EXPECT_TRUE(callback->succeeded);
403 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
404 EXPECT_EQ(m_value1.bits, result_value.bits);
408 TEST_F(IndexedDBBackingStoreTest, PutGetConsistencyWithBlobs) {
410 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
411 transaction1.Begin();
412 ScopedVector<storage::BlobDataHandle> handles;
413 IndexedDBBackingStore::RecordIdentifier record;
414 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
417 m_key3,
418 &m_value3,
419 &handles,
420 &record).ok());
421 scoped_refptr<TestCallback> callback(new TestCallback());
422 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
423 task_runner_->RunUntilIdle();
424 EXPECT_TRUE(CheckBlobWrites());
425 EXPECT_TRUE(callback->called);
426 EXPECT_TRUE(callback->succeeded);
427 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
431 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
432 transaction2.Begin();
433 IndexedDBValue result_value;
434 EXPECT_TRUE(
435 backing_store_->GetRecord(&transaction2, 1, 1, m_key3, &result_value)
436 .ok());
437 scoped_refptr<TestCallback> callback(new TestCallback());
438 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
439 EXPECT_TRUE(callback->called);
440 EXPECT_TRUE(callback->succeeded);
441 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
442 EXPECT_EQ(m_value3.bits, result_value.bits);
443 EXPECT_TRUE(CheckBlobInfoMatches(result_value.blob_info));
444 EXPECT_TRUE(CheckBlobReadsMatchWrites(result_value.blob_info));
448 IndexedDBBackingStore::Transaction transaction3(backing_store_.get());
449 transaction3.Begin();
450 IndexedDBValue result_value;
451 EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
454 IndexedDBKeyRange(m_key3)).ok());
455 scoped_refptr<TestCallback> callback(new TestCallback());
456 EXPECT_TRUE(transaction3.CommitPhaseOne(callback).ok());
457 task_runner_->RunUntilIdle();
458 EXPECT_TRUE(callback->called);
459 EXPECT_TRUE(callback->succeeded);
460 EXPECT_TRUE(transaction3.CommitPhaseTwo().ok());
461 EXPECT_TRUE(CheckBlobRemovals());
465 TEST_F(IndexedDBBackingStoreTest, DeleteRange) {
466 IndexedDBKey key0 = IndexedDBKey(ASCIIToUTF16("key0"));
467 IndexedDBKey key1 = IndexedDBKey(ASCIIToUTF16("key1"));
468 IndexedDBKey key2 = IndexedDBKey(ASCIIToUTF16("key2"));
469 IndexedDBKey key3 = IndexedDBKey(ASCIIToUTF16("key3"));
470 IndexedDBBlobInfo blob0("uuid 0", base::UTF8ToUTF16("type 0"), 1);
471 IndexedDBBlobInfo blob1("uuid 1", base::UTF8ToUTF16("type 1"), 1);
472 IndexedDBBlobInfo blob2("uuid 2", base::UTF8ToUTF16("type 2"), 1);
473 IndexedDBBlobInfo blob3("uuid 3", base::UTF8ToUTF16("type 3"), 1);
474 IndexedDBKeyRange ranges[] = {IndexedDBKeyRange(key1, key2, false, false),
475 IndexedDBKeyRange(key1, key2, false, false),
476 IndexedDBKeyRange(key0, key2, true, false),
477 IndexedDBKeyRange(key1, key3, false, true),
478 IndexedDBKeyRange(key0, key3, true, true)};
480 for (unsigned i = 0; i < sizeof(ranges) / sizeof(IndexedDBKeyRange); ++i) {
481 backing_store_->ClearWrites();
482 backing_store_->ClearRemovals();
485 std::vector<IndexedDBBlobInfo> blob_info0, blob_info1, blob_info2,
486 blob_info3;
487 blob_info0.push_back(blob0);
488 blob_info1.push_back(blob1);
489 blob_info2.push_back(blob2);
490 blob_info3.push_back(blob3);
491 IndexedDBValue value0 = IndexedDBValue("value0", blob_info0);
492 IndexedDBValue value1 = IndexedDBValue("value1", blob_info1);
493 IndexedDBValue value2 = IndexedDBValue("value2", blob_info2);
494 IndexedDBValue value3 = IndexedDBValue("value3", blob_info3);
495 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
496 transaction1.Begin();
497 ScopedVector<storage::BlobDataHandle> handles;
498 IndexedDBBackingStore::RecordIdentifier record;
499 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
501 i + 1,
502 key0,
503 &value0,
504 &handles,
505 &record).ok());
506 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
508 i + 1,
509 key1,
510 &value1,
511 &handles,
512 &record).ok());
513 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
515 i + 1,
516 key2,
517 &value2,
518 &handles,
519 &record).ok());
520 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
522 i + 1,
523 key3,
524 &value3,
525 &handles,
526 &record).ok());
527 scoped_refptr<TestCallback> callback(new TestCallback());
528 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
529 task_runner_->RunUntilIdle();
530 EXPECT_TRUE(callback->called);
531 EXPECT_TRUE(callback->succeeded);
532 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
536 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
537 transaction2.Begin();
538 IndexedDBValue result_value;
539 EXPECT_TRUE(
540 backing_store_->DeleteRange(&transaction2, 1, i + 1, ranges[i]).ok());
541 scoped_refptr<TestCallback> callback(new TestCallback());
542 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
543 task_runner_->RunUntilIdle();
544 EXPECT_TRUE(callback->called);
545 EXPECT_TRUE(callback->succeeded);
546 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
547 EXPECT_EQ(2UL, backing_store_->removals().size());
548 EXPECT_EQ(backing_store_->writes()[1].key(),
549 backing_store_->removals()[0]);
550 EXPECT_EQ(backing_store_->writes()[2].key(),
551 backing_store_->removals()[1]);
556 TEST_F(IndexedDBBackingStoreTest, DeleteRangeEmptyRange) {
557 IndexedDBKey key0 = IndexedDBKey(ASCIIToUTF16("key0"));
558 IndexedDBKey key1 = IndexedDBKey(ASCIIToUTF16("key1"));
559 IndexedDBKey key2 = IndexedDBKey(ASCIIToUTF16("key2"));
560 IndexedDBKey key3 = IndexedDBKey(ASCIIToUTF16("key3"));
561 IndexedDBKey key4 = IndexedDBKey(ASCIIToUTF16("key4"));
562 IndexedDBBlobInfo blob0("uuid 0", base::UTF8ToUTF16("type 0"), 1);
563 IndexedDBBlobInfo blob1("uuid 1", base::UTF8ToUTF16("type 1"), 1);
564 IndexedDBBlobInfo blob2("uuid 2", base::UTF8ToUTF16("type 2"), 1);
565 IndexedDBBlobInfo blob3("uuid 3", base::UTF8ToUTF16("type 3"), 1);
566 IndexedDBKeyRange ranges[] = {IndexedDBKeyRange(key3, key4, true, false),
567 IndexedDBKeyRange(key2, key1, false, false),
568 IndexedDBKeyRange(key2, key1, true, true)};
570 for (unsigned i = 0; i < arraysize(ranges); ++i) {
571 backing_store_->ClearWrites();
572 backing_store_->ClearRemovals();
575 std::vector<IndexedDBBlobInfo> blob_info0, blob_info1, blob_info2,
576 blob_info3;
577 blob_info0.push_back(blob0);
578 blob_info1.push_back(blob1);
579 blob_info2.push_back(blob2);
580 blob_info3.push_back(blob3);
581 IndexedDBValue value0 = IndexedDBValue("value0", blob_info0);
582 IndexedDBValue value1 = IndexedDBValue("value1", blob_info1);
583 IndexedDBValue value2 = IndexedDBValue("value2", blob_info2);
584 IndexedDBValue value3 = IndexedDBValue("value3", blob_info3);
585 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
586 transaction1.Begin();
587 ScopedVector<storage::BlobDataHandle> handles;
588 IndexedDBBackingStore::RecordIdentifier record;
589 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
591 i + 1,
592 key0,
593 &value0,
594 &handles,
595 &record).ok());
596 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
598 i + 1,
599 key1,
600 &value1,
601 &handles,
602 &record).ok());
603 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
605 i + 1,
606 key2,
607 &value2,
608 &handles,
609 &record).ok());
610 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
612 i + 1,
613 key3,
614 &value3,
615 &handles,
616 &record).ok());
617 scoped_refptr<TestCallback> callback(new TestCallback());
618 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
619 task_runner_->RunUntilIdle();
620 EXPECT_TRUE(callback->called);
621 EXPECT_TRUE(callback->succeeded);
622 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
626 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
627 transaction2.Begin();
628 IndexedDBValue result_value;
629 EXPECT_TRUE(
630 backing_store_->DeleteRange(&transaction2, 1, i + 1, ranges[i]).ok());
631 scoped_refptr<TestCallback> callback(new TestCallback());
632 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
633 task_runner_->RunUntilIdle();
634 EXPECT_TRUE(callback->called);
635 EXPECT_TRUE(callback->succeeded);
636 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
637 EXPECT_EQ(0UL, backing_store_->removals().size());
642 TEST_F(IndexedDBBackingStoreTest, LiveBlobJournal) {
644 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
645 transaction1.Begin();
646 ScopedVector<storage::BlobDataHandle> handles;
647 IndexedDBBackingStore::RecordIdentifier record;
648 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
651 m_key3,
652 &m_value3,
653 &handles,
654 &record).ok());
655 scoped_refptr<TestCallback> callback(new TestCallback());
656 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
657 task_runner_->RunUntilIdle();
658 EXPECT_TRUE(CheckBlobWrites());
659 EXPECT_TRUE(callback->called);
660 EXPECT_TRUE(callback->succeeded);
661 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
664 IndexedDBValue read_result_value;
666 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
667 transaction2.Begin();
668 EXPECT_TRUE(
669 backing_store_->GetRecord(
670 &transaction2, 1, 1, m_key3, &read_result_value)
671 .ok());
672 scoped_refptr<TestCallback> callback(new TestCallback());
673 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
674 EXPECT_TRUE(callback->called);
675 EXPECT_TRUE(callback->succeeded);
676 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
677 EXPECT_EQ(m_value3.bits, read_result_value.bits);
678 EXPECT_TRUE(CheckBlobInfoMatches(read_result_value.blob_info));
679 EXPECT_TRUE(CheckBlobReadsMatchWrites(read_result_value.blob_info));
680 for (size_t i = 0; i < read_result_value.blob_info.size(); ++i) {
681 read_result_value.blob_info[i].mark_used_callback().Run();
686 IndexedDBBackingStore::Transaction transaction3(backing_store_.get());
687 transaction3.Begin();
688 EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
691 IndexedDBKeyRange(m_key3)).ok());
692 scoped_refptr<TestCallback> callback(new TestCallback());
693 EXPECT_TRUE(transaction3.CommitPhaseOne(callback).ok());
694 task_runner_->RunUntilIdle();
695 EXPECT_TRUE(callback->called);
696 EXPECT_TRUE(callback->succeeded);
697 EXPECT_TRUE(transaction3.CommitPhaseTwo().ok());
698 EXPECT_EQ(0U, backing_store_->removals().size());
699 for (size_t i = 0; i < read_result_value.blob_info.size(); ++i) {
700 read_result_value.blob_info[i].release_callback().Run(
701 read_result_value.blob_info[i].file_path());
703 task_runner_->RunUntilIdle();
704 EXPECT_NE(0U, backing_store_->removals().size());
705 EXPECT_TRUE(CheckBlobRemovals());
709 // Make sure that using very high ( more than 32 bit ) values for database_id
710 // and object_store_id still work.
711 TEST_F(IndexedDBBackingStoreTest, HighIds) {
712 const int64 high_database_id = 1ULL << 35;
713 const int64 high_object_store_id = 1ULL << 39;
714 // index_ids are capped at 32 bits for storage purposes.
715 const int64 high_index_id = 1ULL << 29;
717 const int64 invalid_high_index_id = 1ULL << 37;
719 const IndexedDBKey& index_key = m_key2;
720 std::string index_key_raw;
721 EncodeIDBKey(index_key, &index_key_raw);
723 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
724 transaction1.Begin();
725 ScopedVector<storage::BlobDataHandle> handles;
726 IndexedDBBackingStore::RecordIdentifier record;
727 leveldb::Status s = backing_store_->PutRecord(&transaction1,
728 high_database_id,
729 high_object_store_id,
730 m_key1,
731 &m_value1,
732 &handles,
733 &record);
734 EXPECT_TRUE(s.ok());
736 s = backing_store_->PutIndexDataForRecord(&transaction1,
737 high_database_id,
738 high_object_store_id,
739 invalid_high_index_id,
740 index_key,
741 record);
742 EXPECT_FALSE(s.ok());
744 s = backing_store_->PutIndexDataForRecord(&transaction1,
745 high_database_id,
746 high_object_store_id,
747 high_index_id,
748 index_key,
749 record);
750 EXPECT_TRUE(s.ok());
752 scoped_refptr<TestCallback> callback(new TestCallback());
753 s = transaction1.CommitPhaseOne(callback);
754 EXPECT_TRUE(s.ok());
755 EXPECT_TRUE(callback->called);
756 EXPECT_TRUE(callback->succeeded);
757 s = transaction1.CommitPhaseTwo();
758 EXPECT_TRUE(s.ok());
762 IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
763 transaction2.Begin();
764 IndexedDBValue result_value;
765 leveldb::Status s = backing_store_->GetRecord(&transaction2,
766 high_database_id,
767 high_object_store_id,
768 m_key1,
769 &result_value);
770 EXPECT_TRUE(s.ok());
771 EXPECT_EQ(m_value1.bits, result_value.bits);
773 scoped_ptr<IndexedDBKey> new_primary_key;
774 s = backing_store_->GetPrimaryKeyViaIndex(&transaction2,
775 high_database_id,
776 high_object_store_id,
777 invalid_high_index_id,
778 index_key,
779 &new_primary_key);
780 EXPECT_FALSE(s.ok());
782 s = backing_store_->GetPrimaryKeyViaIndex(&transaction2,
783 high_database_id,
784 high_object_store_id,
785 high_index_id,
786 index_key,
787 &new_primary_key);
788 EXPECT_TRUE(s.ok());
789 EXPECT_TRUE(new_primary_key->Equals(m_key1));
791 scoped_refptr<TestCallback> callback(new TestCallback());
792 s = transaction2.CommitPhaseOne(callback);
793 EXPECT_TRUE(s.ok());
794 EXPECT_TRUE(callback->called);
795 EXPECT_TRUE(callback->succeeded);
796 s = transaction2.CommitPhaseTwo();
797 EXPECT_TRUE(s.ok());
801 // Make sure that other invalid ids do not crash.
802 TEST_F(IndexedDBBackingStoreTest, InvalidIds) {
803 // valid ids for use when testing invalid ids
804 const int64 database_id = 1;
805 const int64 object_store_id = 1;
806 const int64 index_id = kMinimumIndexId;
807 const int64 invalid_low_index_id = 19; // index_ids must be > kMinimumIndexId
809 IndexedDBValue result_value;
811 IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
812 transaction1.Begin();
814 ScopedVector<storage::BlobDataHandle> handles;
815 IndexedDBBackingStore::RecordIdentifier record;
816 leveldb::Status s = backing_store_->PutRecord(&transaction1,
817 database_id,
818 KeyPrefix::kInvalidId,
819 m_key1,
820 &m_value1,
821 &handles,
822 &record);
823 EXPECT_FALSE(s.ok());
824 s = backing_store_->PutRecord(
825 &transaction1, database_id, 0, m_key1, &m_value1, &handles, &record);
826 EXPECT_FALSE(s.ok());
827 s = backing_store_->PutRecord(&transaction1,
828 KeyPrefix::kInvalidId,
829 object_store_id,
830 m_key1,
831 &m_value1,
832 &handles,
833 &record);
834 EXPECT_FALSE(s.ok());
835 s = backing_store_->PutRecord(
836 &transaction1, 0, object_store_id, m_key1, &m_value1, &handles, &record);
837 EXPECT_FALSE(s.ok());
839 s = backing_store_->GetRecord(
840 &transaction1, database_id, KeyPrefix::kInvalidId, m_key1, &result_value);
841 EXPECT_FALSE(s.ok());
842 s = backing_store_->GetRecord(
843 &transaction1, database_id, 0, m_key1, &result_value);
844 EXPECT_FALSE(s.ok());
845 s = backing_store_->GetRecord(&transaction1,
846 KeyPrefix::kInvalidId,
847 object_store_id,
848 m_key1,
849 &result_value);
850 EXPECT_FALSE(s.ok());
851 s = backing_store_->GetRecord(
852 &transaction1, 0, object_store_id, m_key1, &result_value);
853 EXPECT_FALSE(s.ok());
855 scoped_ptr<IndexedDBKey> new_primary_key;
856 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
857 database_id,
858 object_store_id,
859 KeyPrefix::kInvalidId,
860 m_key1,
861 &new_primary_key);
862 EXPECT_FALSE(s.ok());
863 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
864 database_id,
865 object_store_id,
866 invalid_low_index_id,
867 m_key1,
868 &new_primary_key);
869 EXPECT_FALSE(s.ok());
870 s = backing_store_->GetPrimaryKeyViaIndex(
871 &transaction1, database_id, object_store_id, 0, m_key1, &new_primary_key);
872 EXPECT_FALSE(s.ok());
874 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
875 KeyPrefix::kInvalidId,
876 object_store_id,
877 index_id,
878 m_key1,
879 &new_primary_key);
880 EXPECT_FALSE(s.ok());
881 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
882 database_id,
883 KeyPrefix::kInvalidId,
884 index_id,
885 m_key1,
886 &new_primary_key);
887 EXPECT_FALSE(s.ok());
890 TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
891 const base::string16 database_name(ASCIIToUTF16("db1"));
892 int64 database_id;
893 const base::string16 version(ASCIIToUTF16("old_string_version"));
894 const int64 int_version = 9;
896 const int64 object_store_id = 99;
897 const base::string16 object_store_name(ASCIIToUTF16("object_store1"));
898 const bool auto_increment = true;
899 const IndexedDBKeyPath object_store_key_path(
900 ASCIIToUTF16("object_store_key"));
902 const int64 index_id = 999;
903 const base::string16 index_name(ASCIIToUTF16("index1"));
904 const bool unique = true;
905 const bool multi_entry = true;
906 const IndexedDBKeyPath index_key_path(ASCIIToUTF16("index_key"));
909 leveldb::Status s = backing_store_->CreateIDBDatabaseMetaData(
910 database_name, version, int_version, &database_id);
911 EXPECT_TRUE(s.ok());
912 EXPECT_GT(database_id, 0);
914 IndexedDBBackingStore::Transaction transaction(backing_store_.get());
915 transaction.Begin();
917 s = backing_store_->CreateObjectStore(&transaction,
918 database_id,
919 object_store_id,
920 object_store_name,
921 object_store_key_path,
922 auto_increment);
923 EXPECT_TRUE(s.ok());
925 s = backing_store_->CreateIndex(&transaction,
926 database_id,
927 object_store_id,
928 index_id,
929 index_name,
930 index_key_path,
931 unique,
932 multi_entry);
933 EXPECT_TRUE(s.ok());
935 scoped_refptr<TestCallback> callback(new TestCallback());
936 s = transaction.CommitPhaseOne(callback);
937 EXPECT_TRUE(s.ok());
938 EXPECT_TRUE(callback->called);
939 EXPECT_TRUE(callback->succeeded);
940 s = transaction.CommitPhaseTwo();
941 EXPECT_TRUE(s.ok());
945 IndexedDBDatabaseMetadata database;
946 bool found;
947 leveldb::Status s = backing_store_->GetIDBDatabaseMetaData(
948 database_name, &database, &found);
949 EXPECT_TRUE(s.ok());
950 EXPECT_TRUE(found);
952 // database.name is not filled in by the implementation.
953 EXPECT_EQ(version, database.version);
954 EXPECT_EQ(int_version, database.int_version);
955 EXPECT_EQ(database_id, database.id);
957 s = backing_store_->GetObjectStores(database.id, &database.object_stores);
958 EXPECT_TRUE(s.ok());
960 EXPECT_EQ(1UL, database.object_stores.size());
961 IndexedDBObjectStoreMetadata object_store =
962 database.object_stores[object_store_id];
963 EXPECT_EQ(object_store_name, object_store.name);
964 EXPECT_EQ(object_store_key_path, object_store.key_path);
965 EXPECT_EQ(auto_increment, object_store.auto_increment);
967 EXPECT_EQ(1UL, object_store.indexes.size());
968 IndexedDBIndexMetadata index = object_store.indexes[index_id];
969 EXPECT_EQ(index_name, index.name);
970 EXPECT_EQ(index_key_path, index.key_path);
971 EXPECT_EQ(unique, index.unique);
972 EXPECT_EQ(multi_entry, index.multi_entry);
976 TEST_F(IndexedDBBackingStoreTest, GetDatabaseNames) {
977 const base::string16 string_version(ASCIIToUTF16("string_version"));
979 const base::string16 db1_name(ASCIIToUTF16("db1"));
980 const int64 db1_version = 1LL;
981 int64 db1_id;
983 // Database records with DEFAULT_INT_VERSION represent stale data,
984 // and should not be enumerated.
985 const base::string16 db2_name(ASCIIToUTF16("db2"));
986 const int64 db2_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
987 int64 db2_id;
989 leveldb::Status s = backing_store_->CreateIDBDatabaseMetaData(
990 db1_name, string_version, db1_version, &db1_id);
991 EXPECT_TRUE(s.ok());
992 EXPECT_GT(db1_id, 0LL);
994 s = backing_store_->CreateIDBDatabaseMetaData(
995 db2_name, string_version, db2_version, &db2_id);
996 EXPECT_TRUE(s.ok());
997 EXPECT_GT(db2_id, db1_id);
999 std::vector<base::string16> names = backing_store_->GetDatabaseNames(&s);
1000 EXPECT_TRUE(s.ok());
1001 EXPECT_EQ(names.size(), 1ULL);
1002 EXPECT_EQ(names[0], db1_name);
1005 } // namespace
1007 } // namespace content