Android media: VideoFrame should not store so many sync points.
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_backing_store_unittest.cc
blobde685b8014e1f4613796c4767d39595550d24958
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/strings/string16.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/task_runner.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 "net/url_request/url_request_test_util.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "third_party/WebKit/public/platform/WebIDBTypes.h"
25 #include "webkit/browser/blob/blob_data_handle.h"
26 #include "webkit/browser/quota/special_storage_policy.h"
28 using base::ASCIIToUTF16;
30 namespace content {
32 namespace {
34 class Comparator : public LevelDBComparator {
35 public:
36 virtual int Compare(const base::StringPiece& a,
37 const base::StringPiece& b) const OVERRIDE {
38 return content::Compare(a, b, false /*index_keys*/);
40 virtual const char* Name() const OVERRIDE { return "idb_cmp1"; }
43 class DefaultLevelDBFactory : public LevelDBFactory {
44 public:
45 DefaultLevelDBFactory() {}
46 virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
47 const LevelDBComparator* comparator,
48 scoped_ptr<LevelDBDatabase>* db,
49 bool* is_disk_full) OVERRIDE {
50 return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full);
52 virtual leveldb::Status DestroyLevelDB(
53 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::TaskRunner* 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 virtual ~TestableIndexedDBBackingStore() {}
118 virtual 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 virtual 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 virtual 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::TaskRunner* 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 virtual ~TestIDBFactory() {}
205 virtual 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 virtual void SetUp() {
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(
238 temp_dir_.path(), special_storage_policy_, NULL, task_runner_);
239 idb_factory_ = new TestIDBFactory(idb_context_);
240 backing_store_ =
241 idb_factory_->OpenBackingStoreForTest(origin, &url_request_context_);
243 // useful keys and values during tests
244 m_value1 = IndexedDBValue("value1", std::vector<IndexedDBBlobInfo>());
245 m_value2 = IndexedDBValue("value2", std::vector<IndexedDBBlobInfo>());
247 m_blob_info.push_back(
248 IndexedDBBlobInfo("uuid 3", base::UTF8ToUTF16("blob type"), 1));
249 m_blob_info.push_back(
250 IndexedDBBlobInfo("uuid 4",
251 base::FilePath(FILE_PATH_LITERAL("path/to/file")),
252 base::UTF8ToUTF16("file name"),
253 base::UTF8ToUTF16("file type")));
254 m_value3 = IndexedDBValue("value3", m_blob_info);
256 m_key1 = IndexedDBKey(99, blink::WebIDBKeyTypeNumber);
257 m_key2 = IndexedDBKey(ASCIIToUTF16("key2"));
258 m_key3 = IndexedDBKey(ASCIIToUTF16("key3"));
261 // This just checks the data that survive getting stored and recalled, e.g.
262 // the file path and UUID will change and thus aren't verified.
263 bool CheckBlobInfoMatches(const std::vector<IndexedDBBlobInfo>& reads) const {
264 if (m_blob_info.size() != reads.size())
265 return false;
266 for (size_t i = 0; i < m_blob_info.size(); ++i) {
267 const IndexedDBBlobInfo& a = m_blob_info[i];
268 const IndexedDBBlobInfo& b = reads[i];
269 if (a.is_file() != b.is_file())
270 return false;
271 if (a.type() != b.type())
272 return false;
273 if (a.is_file()) {
274 if (a.file_name() != b.file_name())
275 return false;
276 } else {
277 if (a.size() != b.size())
278 return false;
281 return true;
284 bool CheckBlobReadsMatchWrites(
285 const std::vector<IndexedDBBlobInfo>& reads) const {
286 if (backing_store_->writes().size() != reads.size())
287 return false;
288 std::set<int64> ids;
289 for (size_t i = 0; i < backing_store_->writes().size(); ++i)
290 ids.insert(backing_store_->writes()[i].key());
291 if (ids.size() != backing_store_->writes().size())
292 return false;
293 for (size_t i = 0; i < reads.size(); ++i) {
294 if (ids.count(reads[i].key()) != 1)
295 return false;
297 return true;
300 bool CheckBlobWrites() const {
301 if (backing_store_->writes().size() != m_blob_info.size())
302 return false;
303 for (size_t i = 0; i < backing_store_->writes().size(); ++i) {
304 const IndexedDBBackingStore::Transaction::WriteDescriptor& desc =
305 backing_store_->writes()[i];
306 const IndexedDBBlobInfo& info = m_blob_info[i];
307 if (desc.is_file() != info.is_file())
308 return false;
309 if (desc.is_file()) {
310 if (desc.file_path() != info.file_path())
311 return false;
312 } else {
313 if (desc.url() != GURL("blob:uuid/" + info.uuid()))
314 return false;
317 return true;
320 bool CheckBlobRemovals() const {
321 if (backing_store_->removals().size() != backing_store_->writes().size())
322 return false;
323 for (size_t i = 0; i < backing_store_->writes().size(); ++i) {
324 if (backing_store_->writes()[i].key() != backing_store_->removals()[i])
325 return false;
327 return true;
330 protected:
331 base::ScopedTempDir temp_dir_;
332 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
333 scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
334 scoped_refptr<IndexedDBContextImpl> idb_context_;
335 scoped_refptr<TestIDBFactory> idb_factory_;
336 net::TestURLRequestContext url_request_context_;
338 scoped_refptr<TestableIndexedDBBackingStore> backing_store_;
340 // Sample keys and values that are consistent.
341 IndexedDBKey m_key1;
342 IndexedDBKey m_key2;
343 IndexedDBKey m_key3;
344 IndexedDBValue m_value1;
345 IndexedDBValue m_value2;
346 IndexedDBValue m_value3;
347 std::vector<IndexedDBBlobInfo> m_blob_info;
349 private:
350 DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest);
353 class TestCallback : public IndexedDBBackingStore::BlobWriteCallback {
354 public:
355 TestCallback() : called(false), succeeded(false) {}
356 virtual void Run(bool succeeded_in) OVERRIDE {
357 called = true;
358 succeeded = succeeded_in;
360 bool called;
361 bool succeeded;
363 protected:
364 virtual ~TestCallback() {}
366 private:
367 DISALLOW_COPY_AND_ASSIGN(TestCallback);
370 TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
372 IndexedDBBackingStore::Transaction transaction1(backing_store_);
373 transaction1.Begin();
374 ScopedVector<webkit_blob::BlobDataHandle> handles;
375 IndexedDBBackingStore::RecordIdentifier record;
376 leveldb::Status s = backing_store_->PutRecord(
377 &transaction1, 1, 1, m_key1, &m_value1, &handles, &record);
378 EXPECT_TRUE(s.ok());
379 scoped_refptr<TestCallback> callback(new TestCallback());
380 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
381 EXPECT_TRUE(callback->called);
382 EXPECT_TRUE(callback->succeeded);
383 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
387 IndexedDBBackingStore::Transaction transaction2(backing_store_);
388 transaction2.Begin();
389 IndexedDBValue result_value;
390 EXPECT_TRUE(
391 backing_store_->GetRecord(&transaction2, 1, 1, m_key1, &result_value)
392 .ok());
393 scoped_refptr<TestCallback> callback(new TestCallback());
394 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
395 EXPECT_TRUE(callback->called);
396 EXPECT_TRUE(callback->succeeded);
397 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
398 EXPECT_EQ(m_value1.bits, result_value.bits);
402 TEST_F(IndexedDBBackingStoreTest, PutGetConsistencyWithBlobs) {
404 IndexedDBBackingStore::Transaction transaction1(backing_store_);
405 transaction1.Begin();
406 ScopedVector<webkit_blob::BlobDataHandle> handles;
407 IndexedDBBackingStore::RecordIdentifier record;
408 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
411 m_key3,
412 &m_value3,
413 &handles,
414 &record).ok());
415 scoped_refptr<TestCallback> callback(new TestCallback());
416 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
417 task_runner_->RunUntilIdle();
418 EXPECT_TRUE(CheckBlobWrites());
419 EXPECT_TRUE(callback->called);
420 EXPECT_TRUE(callback->succeeded);
421 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
425 IndexedDBBackingStore::Transaction transaction2(backing_store_);
426 transaction2.Begin();
427 IndexedDBValue result_value;
428 EXPECT_TRUE(
429 backing_store_->GetRecord(&transaction2, 1, 1, m_key3, &result_value)
430 .ok());
431 scoped_refptr<TestCallback> callback(new TestCallback());
432 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
433 EXPECT_TRUE(callback->called);
434 EXPECT_TRUE(callback->succeeded);
435 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
436 EXPECT_EQ(m_value3.bits, result_value.bits);
437 EXPECT_TRUE(CheckBlobInfoMatches(result_value.blob_info));
438 EXPECT_TRUE(CheckBlobReadsMatchWrites(result_value.blob_info));
442 IndexedDBBackingStore::Transaction transaction3(backing_store_);
443 transaction3.Begin();
444 IndexedDBValue result_value;
445 EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
448 IndexedDBKeyRange(m_key3)).ok());
449 scoped_refptr<TestCallback> callback(new TestCallback());
450 EXPECT_TRUE(transaction3.CommitPhaseOne(callback).ok());
451 task_runner_->RunUntilIdle();
452 EXPECT_TRUE(callback->called);
453 EXPECT_TRUE(callback->succeeded);
454 EXPECT_TRUE(transaction3.CommitPhaseTwo().ok());
455 EXPECT_TRUE(CheckBlobRemovals());
459 TEST_F(IndexedDBBackingStoreTest, DeleteRange) {
460 IndexedDBKey key0 = IndexedDBKey(ASCIIToUTF16("key0"));
461 IndexedDBKey key1 = IndexedDBKey(ASCIIToUTF16("key1"));
462 IndexedDBKey key2 = IndexedDBKey(ASCIIToUTF16("key2"));
463 IndexedDBKey key3 = IndexedDBKey(ASCIIToUTF16("key3"));
464 IndexedDBBlobInfo blob0("uuid 0", base::UTF8ToUTF16("type 0"), 1);
465 IndexedDBBlobInfo blob1("uuid 1", base::UTF8ToUTF16("type 1"), 1);
466 IndexedDBBlobInfo blob2("uuid 2", base::UTF8ToUTF16("type 2"), 1);
467 IndexedDBBlobInfo blob3("uuid 3", base::UTF8ToUTF16("type 3"), 1);
468 IndexedDBKeyRange ranges[] = {IndexedDBKeyRange(key1, key2, false, false),
469 IndexedDBKeyRange(key1, key2, false, false),
470 IndexedDBKeyRange(key0, key2, true, false),
471 IndexedDBKeyRange(key1, key3, false, true),
472 IndexedDBKeyRange(key0, key3, true, true)};
474 for (unsigned i = 0; i < sizeof(ranges) / sizeof(IndexedDBKeyRange); ++i) {
475 backing_store_->ClearWrites();
476 backing_store_->ClearRemovals();
479 std::vector<IndexedDBBlobInfo> blob_info0, blob_info1, blob_info2,
480 blob_info3;
481 blob_info0.push_back(blob0);
482 blob_info1.push_back(blob1);
483 blob_info2.push_back(blob2);
484 blob_info3.push_back(blob3);
485 IndexedDBValue value0 = IndexedDBValue("value0", blob_info0);
486 IndexedDBValue value1 = IndexedDBValue("value1", blob_info1);
487 IndexedDBValue value2 = IndexedDBValue("value2", blob_info2);
488 IndexedDBValue value3 = IndexedDBValue("value3", blob_info3);
489 IndexedDBBackingStore::Transaction transaction1(backing_store_);
490 transaction1.Begin();
491 ScopedVector<webkit_blob::BlobDataHandle> handles;
492 IndexedDBBackingStore::RecordIdentifier record;
493 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
495 i + 1,
496 key0,
497 &value0,
498 &handles,
499 &record).ok());
500 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
502 i + 1,
503 key1,
504 &value1,
505 &handles,
506 &record).ok());
507 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
509 i + 1,
510 key2,
511 &value2,
512 &handles,
513 &record).ok());
514 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
516 i + 1,
517 key3,
518 &value3,
519 &handles,
520 &record).ok());
521 scoped_refptr<TestCallback> callback(new TestCallback());
522 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
523 task_runner_->RunUntilIdle();
524 EXPECT_TRUE(callback->called);
525 EXPECT_TRUE(callback->succeeded);
526 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
530 IndexedDBBackingStore::Transaction transaction2(backing_store_);
531 transaction2.Begin();
532 IndexedDBValue result_value;
533 EXPECT_TRUE(
534 backing_store_->DeleteRange(&transaction2, 1, i + 1, ranges[i]).ok());
535 scoped_refptr<TestCallback> callback(new TestCallback());
536 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
537 task_runner_->RunUntilIdle();
538 EXPECT_TRUE(callback->called);
539 EXPECT_TRUE(callback->succeeded);
540 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
541 EXPECT_EQ(2UL, backing_store_->removals().size());
542 EXPECT_EQ(backing_store_->writes()[1].key(),
543 backing_store_->removals()[0]);
544 EXPECT_EQ(backing_store_->writes()[2].key(),
545 backing_store_->removals()[1]);
550 TEST_F(IndexedDBBackingStoreTest, DeleteRangeEmptyRange) {
551 IndexedDBKey key0 = IndexedDBKey(ASCIIToUTF16("key0"));
552 IndexedDBKey key1 = IndexedDBKey(ASCIIToUTF16("key1"));
553 IndexedDBKey key2 = IndexedDBKey(ASCIIToUTF16("key2"));
554 IndexedDBKey key3 = IndexedDBKey(ASCIIToUTF16("key3"));
555 IndexedDBKey key4 = IndexedDBKey(ASCIIToUTF16("key4"));
556 IndexedDBBlobInfo blob0("uuid 0", base::UTF8ToUTF16("type 0"), 1);
557 IndexedDBBlobInfo blob1("uuid 1", base::UTF8ToUTF16("type 1"), 1);
558 IndexedDBBlobInfo blob2("uuid 2", base::UTF8ToUTF16("type 2"), 1);
559 IndexedDBBlobInfo blob3("uuid 3", base::UTF8ToUTF16("type 3"), 1);
560 IndexedDBKeyRange ranges[] = {IndexedDBKeyRange(key3, key4, true, false),
561 IndexedDBKeyRange(key2, key1, false, false),
562 IndexedDBKeyRange(key2, key1, true, true)};
564 for (unsigned i = 0; i < arraysize(ranges); ++i) {
565 backing_store_->ClearWrites();
566 backing_store_->ClearRemovals();
569 std::vector<IndexedDBBlobInfo> blob_info0, blob_info1, blob_info2,
570 blob_info3;
571 blob_info0.push_back(blob0);
572 blob_info1.push_back(blob1);
573 blob_info2.push_back(blob2);
574 blob_info3.push_back(blob3);
575 IndexedDBValue value0 = IndexedDBValue("value0", blob_info0);
576 IndexedDBValue value1 = IndexedDBValue("value1", blob_info1);
577 IndexedDBValue value2 = IndexedDBValue("value2", blob_info2);
578 IndexedDBValue value3 = IndexedDBValue("value3", blob_info3);
579 IndexedDBBackingStore::Transaction transaction1(backing_store_);
580 transaction1.Begin();
581 ScopedVector<webkit_blob::BlobDataHandle> handles;
582 IndexedDBBackingStore::RecordIdentifier record;
583 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
585 i + 1,
586 key0,
587 &value0,
588 &handles,
589 &record).ok());
590 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
592 i + 1,
593 key1,
594 &value1,
595 &handles,
596 &record).ok());
597 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
599 i + 1,
600 key2,
601 &value2,
602 &handles,
603 &record).ok());
604 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
606 i + 1,
607 key3,
608 &value3,
609 &handles,
610 &record).ok());
611 scoped_refptr<TestCallback> callback(new TestCallback());
612 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
613 task_runner_->RunUntilIdle();
614 EXPECT_TRUE(callback->called);
615 EXPECT_TRUE(callback->succeeded);
616 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
620 IndexedDBBackingStore::Transaction transaction2(backing_store_);
621 transaction2.Begin();
622 IndexedDBValue result_value;
623 EXPECT_TRUE(
624 backing_store_->DeleteRange(&transaction2, 1, i + 1, ranges[i]).ok());
625 scoped_refptr<TestCallback> callback(new TestCallback());
626 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
627 task_runner_->RunUntilIdle();
628 EXPECT_TRUE(callback->called);
629 EXPECT_TRUE(callback->succeeded);
630 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
631 EXPECT_EQ(0UL, backing_store_->removals().size());
636 TEST_F(IndexedDBBackingStoreTest, LiveBlobJournal) {
638 IndexedDBBackingStore::Transaction transaction1(backing_store_);
639 transaction1.Begin();
640 ScopedVector<webkit_blob::BlobDataHandle> handles;
641 IndexedDBBackingStore::RecordIdentifier record;
642 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
645 m_key3,
646 &m_value3,
647 &handles,
648 &record).ok());
649 scoped_refptr<TestCallback> callback(new TestCallback());
650 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
651 task_runner_->RunUntilIdle();
652 EXPECT_TRUE(CheckBlobWrites());
653 EXPECT_TRUE(callback->called);
654 EXPECT_TRUE(callback->succeeded);
655 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
658 IndexedDBValue read_result_value;
660 IndexedDBBackingStore::Transaction transaction2(backing_store_);
661 transaction2.Begin();
662 EXPECT_TRUE(
663 backing_store_->GetRecord(
664 &transaction2, 1, 1, m_key3, &read_result_value)
665 .ok());
666 scoped_refptr<TestCallback> callback(new TestCallback());
667 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
668 EXPECT_TRUE(callback->called);
669 EXPECT_TRUE(callback->succeeded);
670 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
671 EXPECT_EQ(m_value3.bits, read_result_value.bits);
672 EXPECT_TRUE(CheckBlobInfoMatches(read_result_value.blob_info));
673 EXPECT_TRUE(CheckBlobReadsMatchWrites(read_result_value.blob_info));
674 for (size_t i = 0; i < read_result_value.blob_info.size(); ++i) {
675 read_result_value.blob_info[i].mark_used_callback().Run();
680 IndexedDBBackingStore::Transaction transaction3(backing_store_);
681 transaction3.Begin();
682 EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
685 IndexedDBKeyRange(m_key3)).ok());
686 scoped_refptr<TestCallback> callback(new TestCallback());
687 EXPECT_TRUE(transaction3.CommitPhaseOne(callback).ok());
688 task_runner_->RunUntilIdle();
689 EXPECT_TRUE(callback->called);
690 EXPECT_TRUE(callback->succeeded);
691 EXPECT_TRUE(transaction3.CommitPhaseTwo().ok());
692 EXPECT_EQ(0U, backing_store_->removals().size());
693 for (size_t i = 0; i < read_result_value.blob_info.size(); ++i) {
694 read_result_value.blob_info[i].release_callback().Run(
695 read_result_value.blob_info[i].file_path());
697 task_runner_->RunUntilIdle();
698 EXPECT_NE(0U, backing_store_->removals().size());
699 EXPECT_TRUE(CheckBlobRemovals());
703 // Make sure that using very high ( more than 32 bit ) values for database_id
704 // and object_store_id still work.
705 TEST_F(IndexedDBBackingStoreTest, HighIds) {
706 const int64 high_database_id = 1ULL << 35;
707 const int64 high_object_store_id = 1ULL << 39;
708 // index_ids are capped at 32 bits for storage purposes.
709 const int64 high_index_id = 1ULL << 29;
711 const int64 invalid_high_index_id = 1ULL << 37;
713 const IndexedDBKey& index_key = m_key2;
714 std::string index_key_raw;
715 EncodeIDBKey(index_key, &index_key_raw);
717 IndexedDBBackingStore::Transaction transaction1(backing_store_);
718 transaction1.Begin();
719 ScopedVector<webkit_blob::BlobDataHandle> handles;
720 IndexedDBBackingStore::RecordIdentifier record;
721 leveldb::Status s = backing_store_->PutRecord(&transaction1,
722 high_database_id,
723 high_object_store_id,
724 m_key1,
725 &m_value1,
726 &handles,
727 &record);
728 EXPECT_TRUE(s.ok());
730 s = backing_store_->PutIndexDataForRecord(&transaction1,
731 high_database_id,
732 high_object_store_id,
733 invalid_high_index_id,
734 index_key,
735 record);
736 EXPECT_FALSE(s.ok());
738 s = backing_store_->PutIndexDataForRecord(&transaction1,
739 high_database_id,
740 high_object_store_id,
741 high_index_id,
742 index_key,
743 record);
744 EXPECT_TRUE(s.ok());
746 scoped_refptr<TestCallback> callback(new TestCallback());
747 s = transaction1.CommitPhaseOne(callback);
748 EXPECT_TRUE(s.ok());
749 EXPECT_TRUE(callback->called);
750 EXPECT_TRUE(callback->succeeded);
751 s = transaction1.CommitPhaseTwo();
752 EXPECT_TRUE(s.ok());
756 IndexedDBBackingStore::Transaction transaction2(backing_store_);
757 transaction2.Begin();
758 IndexedDBValue result_value;
759 leveldb::Status s = backing_store_->GetRecord(&transaction2,
760 high_database_id,
761 high_object_store_id,
762 m_key1,
763 &result_value);
764 EXPECT_TRUE(s.ok());
765 EXPECT_EQ(m_value1.bits, result_value.bits);
767 scoped_ptr<IndexedDBKey> new_primary_key;
768 s = backing_store_->GetPrimaryKeyViaIndex(&transaction2,
769 high_database_id,
770 high_object_store_id,
771 invalid_high_index_id,
772 index_key,
773 &new_primary_key);
774 EXPECT_FALSE(s.ok());
776 s = backing_store_->GetPrimaryKeyViaIndex(&transaction2,
777 high_database_id,
778 high_object_store_id,
779 high_index_id,
780 index_key,
781 &new_primary_key);
782 EXPECT_TRUE(s.ok());
783 EXPECT_TRUE(new_primary_key->Equals(m_key1));
785 scoped_refptr<TestCallback> callback(new TestCallback());
786 s = transaction2.CommitPhaseOne(callback);
787 EXPECT_TRUE(s.ok());
788 EXPECT_TRUE(callback->called);
789 EXPECT_TRUE(callback->succeeded);
790 s = transaction2.CommitPhaseTwo();
791 EXPECT_TRUE(s.ok());
795 // Make sure that other invalid ids do not crash.
796 TEST_F(IndexedDBBackingStoreTest, InvalidIds) {
797 // valid ids for use when testing invalid ids
798 const int64 database_id = 1;
799 const int64 object_store_id = 1;
800 const int64 index_id = kMinimumIndexId;
801 const int64 invalid_low_index_id = 19; // index_ids must be > kMinimumIndexId
803 IndexedDBValue result_value;
805 IndexedDBBackingStore::Transaction transaction1(backing_store_);
806 transaction1.Begin();
808 ScopedVector<webkit_blob::BlobDataHandle> handles;
809 IndexedDBBackingStore::RecordIdentifier record;
810 leveldb::Status s = backing_store_->PutRecord(&transaction1,
811 database_id,
812 KeyPrefix::kInvalidId,
813 m_key1,
814 &m_value1,
815 &handles,
816 &record);
817 EXPECT_FALSE(s.ok());
818 s = backing_store_->PutRecord(
819 &transaction1, database_id, 0, m_key1, &m_value1, &handles, &record);
820 EXPECT_FALSE(s.ok());
821 s = backing_store_->PutRecord(&transaction1,
822 KeyPrefix::kInvalidId,
823 object_store_id,
824 m_key1,
825 &m_value1,
826 &handles,
827 &record);
828 EXPECT_FALSE(s.ok());
829 s = backing_store_->PutRecord(
830 &transaction1, 0, object_store_id, m_key1, &m_value1, &handles, &record);
831 EXPECT_FALSE(s.ok());
833 s = backing_store_->GetRecord(
834 &transaction1, database_id, KeyPrefix::kInvalidId, m_key1, &result_value);
835 EXPECT_FALSE(s.ok());
836 s = backing_store_->GetRecord(
837 &transaction1, database_id, 0, m_key1, &result_value);
838 EXPECT_FALSE(s.ok());
839 s = backing_store_->GetRecord(&transaction1,
840 KeyPrefix::kInvalidId,
841 object_store_id,
842 m_key1,
843 &result_value);
844 EXPECT_FALSE(s.ok());
845 s = backing_store_->GetRecord(
846 &transaction1, 0, object_store_id, m_key1, &result_value);
847 EXPECT_FALSE(s.ok());
849 scoped_ptr<IndexedDBKey> new_primary_key;
850 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
851 database_id,
852 object_store_id,
853 KeyPrefix::kInvalidId,
854 m_key1,
855 &new_primary_key);
856 EXPECT_FALSE(s.ok());
857 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
858 database_id,
859 object_store_id,
860 invalid_low_index_id,
861 m_key1,
862 &new_primary_key);
863 EXPECT_FALSE(s.ok());
864 s = backing_store_->GetPrimaryKeyViaIndex(
865 &transaction1, database_id, object_store_id, 0, m_key1, &new_primary_key);
866 EXPECT_FALSE(s.ok());
868 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
869 KeyPrefix::kInvalidId,
870 object_store_id,
871 index_id,
872 m_key1,
873 &new_primary_key);
874 EXPECT_FALSE(s.ok());
875 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
876 database_id,
877 KeyPrefix::kInvalidId,
878 index_id,
879 m_key1,
880 &new_primary_key);
881 EXPECT_FALSE(s.ok());
884 TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
885 const base::string16 database_name(ASCIIToUTF16("db1"));
886 int64 database_id;
887 const base::string16 version(ASCIIToUTF16("old_string_version"));
888 const int64 int_version = 9;
890 const int64 object_store_id = 99;
891 const base::string16 object_store_name(ASCIIToUTF16("object_store1"));
892 const bool auto_increment = true;
893 const IndexedDBKeyPath object_store_key_path(
894 ASCIIToUTF16("object_store_key"));
896 const int64 index_id = 999;
897 const base::string16 index_name(ASCIIToUTF16("index1"));
898 const bool unique = true;
899 const bool multi_entry = true;
900 const IndexedDBKeyPath index_key_path(ASCIIToUTF16("index_key"));
903 leveldb::Status s = backing_store_->CreateIDBDatabaseMetaData(
904 database_name, version, int_version, &database_id);
905 EXPECT_TRUE(s.ok());
906 EXPECT_GT(database_id, 0);
908 IndexedDBBackingStore::Transaction transaction(backing_store_);
909 transaction.Begin();
911 s = backing_store_->CreateObjectStore(&transaction,
912 database_id,
913 object_store_id,
914 object_store_name,
915 object_store_key_path,
916 auto_increment);
917 EXPECT_TRUE(s.ok());
919 s = backing_store_->CreateIndex(&transaction,
920 database_id,
921 object_store_id,
922 index_id,
923 index_name,
924 index_key_path,
925 unique,
926 multi_entry);
927 EXPECT_TRUE(s.ok());
929 scoped_refptr<TestCallback> callback(new TestCallback());
930 s = transaction.CommitPhaseOne(callback);
931 EXPECT_TRUE(s.ok());
932 EXPECT_TRUE(callback->called);
933 EXPECT_TRUE(callback->succeeded);
934 s = transaction.CommitPhaseTwo();
935 EXPECT_TRUE(s.ok());
939 IndexedDBDatabaseMetadata database;
940 bool found;
941 leveldb::Status s = backing_store_->GetIDBDatabaseMetaData(
942 database_name, &database, &found);
943 EXPECT_TRUE(s.ok());
944 EXPECT_TRUE(found);
946 // database.name is not filled in by the implementation.
947 EXPECT_EQ(version, database.version);
948 EXPECT_EQ(int_version, database.int_version);
949 EXPECT_EQ(database_id, database.id);
951 s = backing_store_->GetObjectStores(database.id, &database.object_stores);
952 EXPECT_TRUE(s.ok());
954 EXPECT_EQ(1UL, database.object_stores.size());
955 IndexedDBObjectStoreMetadata object_store =
956 database.object_stores[object_store_id];
957 EXPECT_EQ(object_store_name, object_store.name);
958 EXPECT_EQ(object_store_key_path, object_store.key_path);
959 EXPECT_EQ(auto_increment, object_store.auto_increment);
961 EXPECT_EQ(1UL, object_store.indexes.size());
962 IndexedDBIndexMetadata index = object_store.indexes[index_id];
963 EXPECT_EQ(index_name, index.name);
964 EXPECT_EQ(index_key_path, index.key_path);
965 EXPECT_EQ(unique, index.unique);
966 EXPECT_EQ(multi_entry, index.multi_entry);
970 } // namespace
972 } // namespace content