Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / browser / indexed_db / indexed_db_backing_store_unittest.cc
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.
4
5 #include "content/browser/indexed_db/indexed_db_backing_store.h"
6
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"
28
29 using base::ASCIIToUTF16;
30
31 namespace content {
32
33 namespace {
34
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*/);
40   }
41   virtual const char* Name() const OVERRIDE { return "idb_cmp1"; }
42 };
43
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);
52   }
53   virtual leveldb::Status DestroyLevelDB(
54       const base::FilePath& file_name) OVERRIDE {
55     return LevelDBDatabase::Destroy(file_name);
56   }
57
58  private:
59   DISALLOW_COPY_AND_ASSIGN(DefaultLevelDBFactory);
60 };
61
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());
73
74     scoped_ptr<LevelDBComparator> comparator(new Comparator());
75
76     if (!base::CreateDirectory(path_base)) {
77       *status = leveldb::Status::IOError("Unable to create base dir");
78       return scoped_refptr<TestableIndexedDBBackingStore>();
79     }
80
81     const base::FilePath file_path = path_base.AppendASCII("test_db_path");
82     const base::FilePath blob_path = path_base.AppendASCII("test_blob_path");
83
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);
88
89     if (!db || !status->ok())
90       return scoped_refptr<TestableIndexedDBBackingStore>();
91
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));
100
101     *status = backing_store->SetUpMetadata();
102     if (!status->ok())
103       return scoped_refptr<TestableIndexedDBBackingStore>();
104
105     return backing_store;
106   }
107
108   const std::vector<IndexedDBBackingStore::Transaction::WriteDescriptor>&
109   writes() const {
110     return writes_;
111   }
112   void ClearWrites() { writes_.clear(); }
113   const std::vector<int64>& removals() const { return removals_; }
114   void ClearRemovals() { removals_.clear(); }
115
116  protected:
117   virtual ~TestableIndexedDBBackingStore() {}
118
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;
126       }
127     } else {
128       database_id_ = database_id;
129     }
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;
138   }
139
140   virtual bool RemoveBlobFile(int64 database_id, int64 key) OVERRIDE {
141     if (database_id_ != database_id ||
142         !KeyPrefix::IsValidDatabaseId(database_id)) {
143       return false;
144     }
145     removals_.push_back(key);
146     return true;
147   }
148
149   // Timers don't play nicely with unit tests.
150   virtual void StartJournalCleaningTimer() OVERRIDE {
151     CleanPrimaryJournalIgnoreReturn();
152   }
153
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) {}
170
171   int64 database_id_;
172   std::vector<Transaction::WriteDescriptor> writes_;
173   std::vector<int64> removals_;
174
175   DISALLOW_COPY_AND_ASSIGN(TestableIndexedDBBackingStore);
176 };
177
178 class TestIDBFactory : public IndexedDBFactoryImpl {
179  public:
180   explicit TestIDBFactory(IndexedDBContextImpl* idb_context)
181       : IndexedDBFactoryImpl(idb_context) {}
182
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;
201   }
202
203  protected:
204   virtual ~TestIDBFactory() {}
205
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);
223   }
224
225  private:
226   DISALLOW_COPY_AND_ASSIGN(TestIDBFactory);
227 };
228
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_);
245
246     // useful keys and values during tests
247     m_value1 = IndexedDBValue("value1", std::vector<IndexedDBBlobInfo>());
248     m_value2 = IndexedDBValue("value2", std::vector<IndexedDBBlobInfo>());
249
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);
258
259     m_key1 = IndexedDBKey(99, blink::WebIDBKeyTypeNumber);
260     m_key2 = IndexedDBKey(ASCIIToUTF16("key2"));
261     m_key3 = IndexedDBKey(ASCIIToUTF16("key3"));
262   }
263
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;
282       }
283     }
284     return true;
285   }
286
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;
299     }
300     return true;
301   }
302
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;
318       }
319     }
320     return true;
321   }
322
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;
329     }
330     return true;
331   }
332
333  protected:
334   // Must be initialized before url_request_context_
335   content::TestBrowserThreadBundle thread_bundle_;
336
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_;
343
344   scoped_refptr<TestableIndexedDBBackingStore> backing_store_;
345
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;
354
355  private:
356   DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest);
357 };
358
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;
365   }
366   bool called;
367   bool succeeded;
368
369  protected:
370   virtual ~TestCallback() {}
371
372  private:
373   DISALLOW_COPY_AND_ASSIGN(TestCallback);
374 };
375
376 TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
377   {
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());
390   }
391
392   {
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);
405   }
406 }
407
408 TEST_F(IndexedDBBackingStoreTest, PutGetConsistencyWithBlobs) {
409   {
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,
415                                           1,
416                                           1,
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());
428   }
429
430   {
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));
445   }
446
447   {
448     IndexedDBBackingStore::Transaction transaction3(backing_store_.get());
449     transaction3.Begin();
450     IndexedDBValue result_value;
451     EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
452                                             1,
453                                             1,
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());
462   }
463 }
464
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)};
479
480   for (unsigned i = 0; i < sizeof(ranges) / sizeof(IndexedDBKeyRange); ++i) {
481     backing_store_->ClearWrites();
482     backing_store_->ClearRemovals();
483
484     {
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,
500                                             1,
501                                             i + 1,
502                                             key0,
503                                             &value0,
504                                             &handles,
505                                             &record).ok());
506       EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
507                                             1,
508                                             i + 1,
509                                             key1,
510                                             &value1,
511                                             &handles,
512                                             &record).ok());
513       EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
514                                             1,
515                                             i + 1,
516                                             key2,
517                                             &value2,
518                                             &handles,
519                                             &record).ok());
520       EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
521                                             1,
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());
533     }
534
535     {
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]);
552     }
553   }
554 }
555
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)};
569
570   for (unsigned i = 0; i < arraysize(ranges); ++i) {
571     backing_store_->ClearWrites();
572     backing_store_->ClearRemovals();
573
574     {
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,
590                                             1,
591                                             i + 1,
592                                             key0,
593                                             &value0,
594                                             &handles,
595                                             &record).ok());
596       EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
597                                             1,
598                                             i + 1,
599                                             key1,
600                                             &value1,
601                                             &handles,
602                                             &record).ok());
603       EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
604                                             1,
605                                             i + 1,
606                                             key2,
607                                             &value2,
608                                             &handles,
609                                             &record).ok());
610       EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
611                                             1,
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());
623     }
624
625     {
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());
638     }
639   }
640 }
641
642 TEST_F(IndexedDBBackingStoreTest, LiveBlobJournal) {
643   {
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,
649                                           1,
650                                           1,
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());
662   }
663
664   IndexedDBValue read_result_value;
665   {
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();
682     }
683   }
684
685   {
686     IndexedDBBackingStore::Transaction transaction3(backing_store_.get());
687     transaction3.Begin();
688     EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
689                                             1,
690                                             1,
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());
702     }
703     task_runner_->RunUntilIdle();
704     EXPECT_NE(0U, backing_store_->removals().size());
705     EXPECT_TRUE(CheckBlobRemovals());
706   }
707 }
708
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;
716
717   const int64 invalid_high_index_id = 1ULL << 37;
718
719   const IndexedDBKey& index_key = m_key2;
720   std::string index_key_raw;
721   EncodeIDBKey(index_key, &index_key_raw);
722   {
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());
735
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());
743
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());
751
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());
759   }
760
761   {
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);
772
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());
781
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));
790
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());
798   }
799 }
800
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
808
809   IndexedDBValue result_value;
810
811   IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
812   transaction1.Begin();
813
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());
838
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());
854
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());
873
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());
888 }
889
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;
895
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"));
901
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"));
907
908   {
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);
913
914     IndexedDBBackingStore::Transaction transaction(backing_store_.get());
915     transaction.Begin();
916
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());
924
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());
934
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());
942   }
943
944   {
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);
951
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);
956
957     s = backing_store_->GetObjectStores(database.id, &database.object_stores);
958     EXPECT_TRUE(s.ok());
959
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);
966
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);
973   }
974 }
975
976 TEST_F(IndexedDBBackingStoreTest, GetDatabaseNames) {
977   const base::string16 string_version(ASCIIToUTF16("string_version"));
978
979   const base::string16 db1_name(ASCIIToUTF16("db1"));
980   const int64 db1_version = 1LL;
981   int64 db1_id;
982
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;
988
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);
993
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);
998
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);
1003 }
1004
1005 }  // namespace
1006
1007 }  // namespace content