Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: content/browser/indexed_db/indexed_db_backing_store_unittest.cc

Issue 18023022: Blob support for IDB [Chromium] (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More small build fixes. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/indexed_db/indexed_db_backing_store.h" 5 #include "content/browser/indexed_db/indexed_db_backing_store.h"
6 6
7 #include "base/callback.h"
8 #include "base/file_util.h"
9 #include "base/files/scoped_temp_dir.h"
7 #include "base/logging.h" 10 #include "base/logging.h"
8 #include "base/strings/string16.h" 11 #include "base/strings/string16.h"
9 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
13 #include "base/task_runner.h"
14 #include "base/test/test_simple_task_runner.h"
15 #include "content/browser/indexed_db/indexed_db_context_impl.h"
10 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" 16 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
11 #include "content/browser/indexed_db/indexed_db_value.h" 17 #include "content/browser/indexed_db/indexed_db_value.h"
18 #include "content/public/test/mock_special_storage_policy.h"
19 #include "net/url_request/url_request_test_util.h"
12 #include "testing/gtest/include/gtest/gtest.h" 20 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/WebKit/public/platform/WebIDBTypes.h" 21 #include "third_party/WebKit/public/platform/WebIDBTypes.h"
22 #include "webkit/browser/blob/blob_data_handle.h"
23 #include "webkit/browser/quota/special_storage_policy.h"
14 24
15 using base::ASCIIToUTF16; 25 using base::ASCIIToUTF16;
16 26
17 namespace content { 27 namespace content {
18 28
19 namespace { 29 namespace {
20 30
31 class Comparator : public LevelDBComparator {
32 public:
33 virtual int Compare(const base::StringPiece& a,
34 const base::StringPiece& b) const OVERRIDE {
35 return content::Compare(a, b, false /*index_keys*/);
36 }
37 virtual const char* Name() const OVERRIDE { return "idb_cmp1"; }
38 };
39
40 class DefaultLevelDBFactory : public LevelDBFactory {
41 public:
42 virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
43 const LevelDBComparator* comparator,
44 scoped_ptr<LevelDBDatabase>* db,
45 bool* is_disk_full) OVERRIDE {
46 return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full);
47 }
48 virtual leveldb::Status DestroyLevelDB(
49 const base::FilePath& file_name) OVERRIDE {
50 return LevelDBDatabase::Destroy(file_name);
51 }
52 };
53
54 class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
55 public:
56 static scoped_refptr<TestableIndexedDBBackingStore> Open(
57 IndexedDBFactory* indexed_db_factory,
58 const GURL& origin_url,
59 const base::FilePath& path_base,
60 net::URLRequestContext* request_context,
61 LevelDBFactory* leveldb_factory,
62 base::TaskRunner* task_runner) {
63 DCHECK(!path_base.empty());
64
65 scoped_ptr<LevelDBComparator> comparator(new Comparator());
66
67 if (!base::CreateDirectory(path_base))
68 return scoped_refptr<TestableIndexedDBBackingStore>();
69
70 const base::FilePath file_path = path_base.AppendASCII("test_db_path");
71 const base::FilePath blob_path = path_base.AppendASCII("test_blob_path");
72
73 scoped_ptr<LevelDBDatabase> db;
74 bool is_disk_full = false;
75 leveldb::Status status = leveldb_factory->OpenLevelDB(
76 file_path, comparator.get(), &db, &is_disk_full);
77
78 if (!db || !status.ok())
79 return scoped_refptr<TestableIndexedDBBackingStore>();
80
81 scoped_refptr<TestableIndexedDBBackingStore> backing_store(
82 new TestableIndexedDBBackingStore(indexed_db_factory,
83 origin_url,
84 blob_path,
85 request_context,
86 db.Pass(),
87 comparator.Pass(),
88 task_runner));
89
90 if (!backing_store->SetUpMetadata())
91 return scoped_refptr<TestableIndexedDBBackingStore>();
92
93 return backing_store;
94 }
95
96 const std::vector<IndexedDBBackingStore::Transaction::WriteDescriptor>&
97 writes() const {
98 return writes_;
99 }
100 void ClearWrites() { writes_.clear(); }
101 const std::vector<int64>& removals() const { return removals_; }
102 void ClearRemovals() { removals_.clear(); }
103
104 protected:
105 virtual ~TestableIndexedDBBackingStore() {}
106
107 virtual bool WriteBlobFile(
108 int64 database_id,
109 const Transaction::WriteDescriptor& descriptor,
110 Transaction::ChainedBlobWriter* chained_blob_writer) OVERRIDE {
111 if (KeyPrefix::IsValidDatabaseId(database_id_)) {
112 if (database_id_ != database_id) {
113 return false;
114 }
115 } else {
116 database_id_ = database_id;
117 }
118 writes_.push_back(descriptor);
119 task_runner()->PostTask(
120 FROM_HERE,
121 base::Bind(&Transaction::ChainedBlobWriter::ReportWriteCompletion,
122 chained_blob_writer,
123 true,
124 1));
125 return true;
126 }
127
128 virtual bool RemoveBlobFile(int64 database_id, int64 key) OVERRIDE {
129 if (database_id_ != database_id ||
130 !KeyPrefix::IsValidDatabaseId(database_id)) {
131 return false;
132 }
133 removals_.push_back(key);
134 return true;
135 }
136
137 // Timers don't play nicely with unit tests.
138 virtual void StartJournalCleaningTimer() OVERRIDE {
139 CleanPrimaryJournalIgnoreReturn();
140 }
141
142 private:
143 TestableIndexedDBBackingStore(IndexedDBFactory* indexed_db_factory,
144 const GURL& origin_url,
145 const base::FilePath& blob_path,
146 net::URLRequestContext* request_context,
147 scoped_ptr<LevelDBDatabase> db,
148 scoped_ptr<LevelDBComparator> comparator,
149 base::TaskRunner* task_runner)
150 : IndexedDBBackingStore(indexed_db_factory,
151 origin_url,
152 blob_path,
153 request_context,
154 db.Pass(),
155 comparator.Pass(),
156 task_runner),
157 database_id_(0) {}
158
159 int64 database_id_;
160 std::vector<Transaction::WriteDescriptor> writes_;
161 std::vector<int64> removals_;
162 };
163
164 class TestIDBFactory : public IndexedDBFactory {
165 public:
166 TestIDBFactory(IndexedDBContextImpl* idb_context)
167 : IndexedDBFactory(idb_context) {}
168
169 scoped_refptr<TestableIndexedDBBackingStore> OpenBackingStoreForTest(
170 const GURL& origin,
171 net::URLRequestContext* url_request_context) {
172 blink::WebIDBDataLoss data_loss;
173 std::string data_loss_reason;
174 bool disk_full;
175 scoped_refptr<IndexedDBBackingStore> backing_store =
176 OpenBackingStore(origin,
177 context()->data_path(),
178 url_request_context,
179 &data_loss,
180 &data_loss_reason,
181 &disk_full);
182 scoped_refptr<TestableIndexedDBBackingStore> testable_store =
183 static_cast<TestableIndexedDBBackingStore*>(backing_store.get());
184 return testable_store;
185 }
186
187 protected:
188 virtual ~TestIDBFactory() {}
189
190 virtual scoped_refptr<IndexedDBBackingStore> OpenBackingStoreHelper(
191 const GURL& origin_url,
192 const base::FilePath& data_directory,
193 net::URLRequestContext* request_context,
194 blink::WebIDBDataLoss* data_loss,
195 std::string* data_loss_message,
196 bool* disk_full,
197 bool first_time) OVERRIDE {
198 DefaultLevelDBFactory leveldb_factory;
199 return TestableIndexedDBBackingStore::Open(this,
200 origin_url,
201 data_directory,
202 request_context,
203 &leveldb_factory,
204 context()->TaskRunner());
205 }
206 };
207
21 class IndexedDBBackingStoreTest : public testing::Test { 208 class IndexedDBBackingStoreTest : public testing::Test {
22 public: 209 public:
23 IndexedDBBackingStoreTest() {} 210 IndexedDBBackingStoreTest() {}
24 virtual void SetUp() { 211 virtual void SetUp() {
25 const GURL origin("http://localhost:81"); 212 const GURL origin("http://localhost:81");
213 task_runner_ = new base::TestSimpleTaskRunner();
214 special_storage_policy_ = new MockSpecialStoragePolicy();
215 special_storage_policy_->SetAllUnlimited(true);
216 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
217 idb_context_ = new IndexedDBContextImpl(
218 temp_dir_.path(), special_storage_policy_, NULL, task_runner_);
219 idb_factory_ = new TestIDBFactory(idb_context_);
26 backing_store_ = 220 backing_store_ =
27 IndexedDBBackingStore::OpenInMemory(origin, NULL /* task_runner */); 221 idb_factory_->OpenBackingStoreForTest(origin, &url_request_context_);
28 222
29 // useful keys and values during tests 223 // useful keys and values during tests
30 m_value1 = IndexedDBValue("value1", std::vector<IndexedDBBlobInfo>()); 224 m_value1 = IndexedDBValue("value1", std::vector<IndexedDBBlobInfo>());
31 m_value2 = IndexedDBValue("value2", std::vector<IndexedDBBlobInfo>()); 225 m_value2 = IndexedDBValue("value2", std::vector<IndexedDBBlobInfo>());
32 226
227 m_blob_info.push_back(
228 IndexedDBBlobInfo("uuid 3", base::UTF8ToUTF16("blob type"), 1));
229 m_blob_info.push_back(
230 IndexedDBBlobInfo("uuid 4",
231 base::FilePath(FILE_PATH_LITERAL("path/to/file")),
232 base::UTF8ToUTF16("file name"),
233 base::UTF8ToUTF16("file type")));
234 m_value3 = IndexedDBValue("value3", m_blob_info);
235
33 m_key1 = IndexedDBKey(99, blink::WebIDBKeyTypeNumber); 236 m_key1 = IndexedDBKey(99, blink::WebIDBKeyTypeNumber);
34 m_key2 = IndexedDBKey(ASCIIToUTF16("key2")); 237 m_key2 = IndexedDBKey(ASCIIToUTF16("key2"));
238 m_key3 = IndexedDBKey(ASCIIToUTF16("key3"));
239 }
240
241 // This just checks the data that survive getting stored and recalled, e.g.
242 // the file path and UUID will change and thus aren't verified.
243 bool CheckBlobInfoMatches(const std::vector<IndexedDBBlobInfo>& reads) const {
244 if (m_blob_info.size() != reads.size())
245 return false;
246 for (size_t i = 0; i < m_blob_info.size(); ++i) {
247 const IndexedDBBlobInfo& a = m_blob_info[i];
248 const IndexedDBBlobInfo& b = reads[i];
249 if (a.is_file() != b.is_file())
jsbell 2014/05/28 21:29:15 Maybe add IndexedDBBlobInfo::Compare ?
ericu 2014/05/28 22:50:42 It's not clear to me that there's a general-purpos
jsbell 2014/05/28 23:35:18 I'm fine with leaving this inline, since some fiel
250 return false;
251 if (a.type() != b.type())
252 return false;
253 if (a.is_file()) {
254 if (a.file_name() != b.file_name())
cmumford 2014/05/28 20:34:54 Do you also need to check last_modified?
ericu 2014/05/28 22:50:42 That can change too, for files, since we may not k
255 return false;
256 } else {
257 if (a.size() != b.size())
258 return false;
259 }
260 }
261 return true;
262 }
263
264 bool CheckBlobReadsMatchWrites(
265 const std::vector<IndexedDBBlobInfo>& reads) const {
266 if (backing_store_->writes().size() != reads.size())
267 return false;
268 std::set<int64> ids;
269 for (size_t i = 0; i < backing_store_->writes().size(); ++i)
270 ids.insert(backing_store_->writes()[i].key());
271 if (ids.size() != backing_store_->writes().size())
272 return false;
273 for (size_t i = 0; i < reads.size(); ++i) {
274 if (ids.count(reads[i].key()) != 1)
275 return false;
276 }
277 return true;
278 }
279
280 bool CheckBlobWrites() const {
281 if (backing_store_->writes().size() != m_blob_info.size())
282 return false;
283 for (size_t i = 0; i < backing_store_->writes().size(); ++i) {
284 const IndexedDBBackingStore::Transaction::WriteDescriptor& desc =
285 backing_store_->writes()[i];
286 const IndexedDBBlobInfo& info = m_blob_info[i];
287 if (desc.is_file() != info.is_file())
288 return false;
289 if (desc.is_file()) {
290 if (desc.file_path() != info.file_path())
291 return false;
292 } else {
293 if (desc.url() != GURL("blob:uuid/" + info.uuid()))
294 return false;
295 }
296 }
297 return true;
298 }
299
300 bool CheckBlobRemovals() const {
301 if (backing_store_->removals().size() != backing_store_->writes().size())
302 return false;
303 for (size_t i = 0; i < backing_store_->writes().size(); ++i)
jsbell 2014/05/28 21:29:15 Nit: Needs {}
ericu 2014/05/28 22:50:42 Done.
304 if (backing_store_->writes()[i].key() != backing_store_->removals()[i])
305 return false;
306 return true;
35 } 307 }
36 308
37 protected: 309 protected:
38 scoped_refptr<IndexedDBBackingStore> backing_store_; 310 base::ScopedTempDir temp_dir_;
311 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
312 scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
313 scoped_refptr<IndexedDBContextImpl> idb_context_;
314 scoped_refptr<TestIDBFactory> idb_factory_;
315 net::TestURLRequestContext url_request_context_;
316
317 scoped_refptr<TestableIndexedDBBackingStore> backing_store_;
39 318
40 // Sample keys and values that are consistent. 319 // Sample keys and values that are consistent.
41 IndexedDBKey m_key1; 320 IndexedDBKey m_key1;
42 IndexedDBKey m_key2; 321 IndexedDBKey m_key2;
322 IndexedDBKey m_key3;
43 IndexedDBValue m_value1; 323 IndexedDBValue m_value1;
44 IndexedDBValue m_value2; 324 IndexedDBValue m_value2;
325 IndexedDBValue m_value3;
326 std::vector<IndexedDBBlobInfo> m_blob_info;
45 327
46 private: 328 private:
47 DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest); 329 DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest);
48 }; 330 };
49 331
332 class TestCallback : public IndexedDBBackingStore::BlobWriteCallback {
333 public:
334 TestCallback() : called(false), succeeded(false) {}
335 virtual void Run(bool succeeded_in) OVERRIDE {
336 called = true;
337 succeeded = succeeded_in;
338 }
339 bool called;
340 bool succeeded;
341
342 protected:
343 virtual ~TestCallback() {}
344 };
345
50 TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) { 346 TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
51 { 347 {
52 IndexedDBBackingStore::Transaction transaction1(backing_store_); 348 IndexedDBBackingStore::Transaction transaction1(backing_store_);
53 transaction1.Begin(); 349 transaction1.Begin();
54 ScopedVector<webkit_blob::BlobDataHandle> handles; 350 ScopedVector<webkit_blob::BlobDataHandle> handles;
55 IndexedDBBackingStore::RecordIdentifier record; 351 IndexedDBBackingStore::RecordIdentifier record;
56 leveldb::Status s = backing_store_->PutRecord( 352 leveldb::Status s = backing_store_->PutRecord(
57 &transaction1, 1, 1, m_key1, m_value1, &handles, &record); 353 &transaction1, 1, 1, m_key1, m_value1, &handles, &record);
58 EXPECT_TRUE(s.ok()); 354 EXPECT_TRUE(s.ok());
59 transaction1.Commit(); 355 scoped_refptr<TestCallback> callback(new TestCallback());
356 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
357 EXPECT_TRUE(callback->called);
358 EXPECT_TRUE(callback->succeeded);
359 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
60 } 360 }
61 361
62 { 362 {
63 IndexedDBBackingStore::Transaction transaction2(backing_store_); 363 IndexedDBBackingStore::Transaction transaction2(backing_store_);
64 transaction2.Begin(); 364 transaction2.Begin();
65 IndexedDBValue result_value; 365 IndexedDBValue result_value;
66 leveldb::Status s = 366 EXPECT_TRUE(
67 backing_store_->GetRecord(&transaction2, 1, 1, m_key1, &result_value); 367 backing_store_->GetRecord(&transaction2, 1, 1, m_key1, &result_value)
68 transaction2.Commit(); 368 .ok());
69 EXPECT_TRUE(s.ok()); 369 scoped_refptr<TestCallback> callback(new TestCallback());
370 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
371 EXPECT_TRUE(callback->called);
372 EXPECT_TRUE(callback->succeeded);
373 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
70 EXPECT_EQ(m_value1.bits, result_value.bits); 374 EXPECT_EQ(m_value1.bits, result_value.bits);
71 } 375 }
72 } 376 }
73 377
378 TEST_F(IndexedDBBackingStoreTest, PutGetConsistencyWithBlobs) {
379 {
380 IndexedDBBackingStore::Transaction transaction1(backing_store_);
381 transaction1.Begin();
382 ScopedVector<webkit_blob::BlobDataHandle> handles;
383 IndexedDBBackingStore::RecordIdentifier record;
384 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
385 1,
386 1,
387 m_key3,
388 m_value3,
389 &handles,
390 &record).ok());
391 scoped_refptr<TestCallback> callback(new TestCallback());
392 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
393 task_runner_->RunUntilIdle();
394 EXPECT_TRUE(CheckBlobWrites());
395 EXPECT_TRUE(callback->called);
396 EXPECT_TRUE(callback->succeeded);
397 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
398 }
399
400 {
401 IndexedDBBackingStore::Transaction transaction2(backing_store_);
402 transaction2.Begin();
403 IndexedDBValue result_value;
404 EXPECT_TRUE(
405 backing_store_->GetRecord(&transaction2, 1, 1, m_key3, &result_value)
406 .ok());
407 scoped_refptr<TestCallback> callback(new TestCallback());
408 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
409 EXPECT_TRUE(callback->called);
410 EXPECT_TRUE(callback->succeeded);
411 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
412 EXPECT_EQ(m_value3.bits, result_value.bits);
413 EXPECT_TRUE(CheckBlobInfoMatches(result_value.blob_info));
414 EXPECT_TRUE(CheckBlobReadsMatchWrites(result_value.blob_info));
415 }
416
417 {
418 IndexedDBBackingStore::Transaction transaction3(backing_store_);
419 transaction3.Begin();
420 IndexedDBValue result_value;
421 EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
422 1,
423 1,
424 IndexedDBKeyRange(m_key3)).ok());
425 scoped_refptr<TestCallback> callback(new TestCallback());
426 EXPECT_TRUE(transaction3.CommitPhaseOne(callback).ok());
427 task_runner_->RunUntilIdle();
428 EXPECT_TRUE(callback->called);
429 EXPECT_TRUE(callback->succeeded);
430 EXPECT_TRUE(transaction3.CommitPhaseTwo().ok());
431 EXPECT_TRUE(CheckBlobRemovals());
432 }
433 }
434
435 TEST_F(IndexedDBBackingStoreTest, DeleteRange) {
436 IndexedDBKey key0 = IndexedDBKey(ASCIIToUTF16("key0"));
437 IndexedDBKey key1 = IndexedDBKey(ASCIIToUTF16("key1"));
438 IndexedDBKey key2 = IndexedDBKey(ASCIIToUTF16("key2"));
439 IndexedDBKey key3 = IndexedDBKey(ASCIIToUTF16("key3"));
440 IndexedDBBlobInfo blob0("uuid 0", base::UTF8ToUTF16("type 0"), 1);
441 IndexedDBBlobInfo blob1("uuid 1", base::UTF8ToUTF16("type 1"), 1);
442 IndexedDBBlobInfo blob2("uuid 2", base::UTF8ToUTF16("type 2"), 1);
443 IndexedDBBlobInfo blob3("uuid 3", base::UTF8ToUTF16("type 3"), 1);
444 IndexedDBKeyRange ranges[] = {IndexedDBKeyRange(key1, key2, false, false),
445 IndexedDBKeyRange(key1, key2, false, false),
446 IndexedDBKeyRange(key0, key2, true, false),
447 IndexedDBKeyRange(key1, key3, false, true),
448 IndexedDBKeyRange(key0, key3, true, true)};
449
450 for (unsigned i = 0; i < sizeof(ranges) / sizeof(IndexedDBKeyRange); ++i) {
451 backing_store_->ClearWrites();
452 backing_store_->ClearRemovals();
453
454 {
455 std::vector<IndexedDBBlobInfo> blob_info0, blob_info1, blob_info2,
456 blob_info3;
457 blob_info0.push_back(blob0);
458 blob_info1.push_back(blob1);
459 blob_info2.push_back(blob2);
460 blob_info3.push_back(blob3);
461 IndexedDBValue value0 = IndexedDBValue("value0", blob_info0);
462 IndexedDBValue value1 = IndexedDBValue("value1", blob_info1);
463 IndexedDBValue value2 = IndexedDBValue("value2", blob_info2);
464 IndexedDBValue value3 = IndexedDBValue("value3", blob_info3);
465 IndexedDBBackingStore::Transaction transaction1(backing_store_);
466 transaction1.Begin();
467 ScopedVector<webkit_blob::BlobDataHandle> handles;
468 IndexedDBBackingStore::RecordIdentifier record;
469 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
470 1,
471 i + 1,
472 key0,
473 value0,
474 &handles,
475 &record).ok());
476 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
477 1,
478 i + 1,
479 key1,
480 value1,
481 &handles,
482 &record).ok());
483 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
484 1,
485 i + 1,
486 key2,
487 value2,
488 &handles,
489 &record).ok());
490 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
491 1,
492 i + 1,
493 key3,
494 value3,
495 &handles,
496 &record).ok());
497 scoped_refptr<TestCallback> callback(new TestCallback());
498 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
499 task_runner_->RunUntilIdle();
500 EXPECT_TRUE(callback->called);
501 EXPECT_TRUE(callback->succeeded);
502 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
503 }
504
505 {
506 IndexedDBBackingStore::Transaction transaction2(backing_store_);
507 transaction2.Begin();
508 IndexedDBValue result_value;
509 EXPECT_TRUE(
510 backing_store_->DeleteRange(&transaction2, 1, i + 1, ranges[i]).ok());
511 scoped_refptr<TestCallback> callback(new TestCallback());
512 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
513 task_runner_->RunUntilIdle();
514 EXPECT_TRUE(callback->called);
515 EXPECT_TRUE(callback->succeeded);
516 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
517 EXPECT_EQ(2UL, backing_store_->removals().size());
518 EXPECT_EQ(backing_store_->writes()[1].key(),
519 backing_store_->removals()[0]);
520 EXPECT_EQ(backing_store_->writes()[2].key(),
521 backing_store_->removals()[1]);
522 }
523 }
524 }
525
526 TEST_F(IndexedDBBackingStoreTest, DeleteRangeEmptyRange) {
527 IndexedDBKey key0 = IndexedDBKey(ASCIIToUTF16("key0"));
528 IndexedDBKey key1 = IndexedDBKey(ASCIIToUTF16("key1"));
529 IndexedDBKey key2 = IndexedDBKey(ASCIIToUTF16("key2"));
530 IndexedDBKey key3 = IndexedDBKey(ASCIIToUTF16("key3"));
531 IndexedDBKey key4 = IndexedDBKey(ASCIIToUTF16("key4"));
532 IndexedDBBlobInfo blob0("uuid 0", base::UTF8ToUTF16("type 0"), 1);
533 IndexedDBBlobInfo blob1("uuid 1", base::UTF8ToUTF16("type 1"), 1);
534 IndexedDBBlobInfo blob2("uuid 2", base::UTF8ToUTF16("type 2"), 1);
535 IndexedDBBlobInfo blob3("uuid 3", base::UTF8ToUTF16("type 3"), 1);
536 IndexedDBKeyRange ranges[] = {IndexedDBKeyRange(key3, key4, true, false),
537 IndexedDBKeyRange(key2, key1, false, false),
538 IndexedDBKeyRange(key2, key1, true, true)};
539
540 for (unsigned i = 0; i < sizeof(ranges) / sizeof(IndexedDBKeyRange); ++i) {
cmumford 2014/05/28 20:34:54 Nit: Why not just use "arraysize(ranges)"?
ericu 2014/05/28 22:50:42 Done. Thanks; I'd forgotten we had that.
541 backing_store_->ClearWrites();
542 backing_store_->ClearRemovals();
543
544 {
545 std::vector<IndexedDBBlobInfo> blob_info0, blob_info1, blob_info2,
546 blob_info3;
547 blob_info0.push_back(blob0);
548 blob_info1.push_back(blob1);
549 blob_info2.push_back(blob2);
550 blob_info3.push_back(blob3);
551 IndexedDBValue value0 = IndexedDBValue("value0", blob_info0);
552 IndexedDBValue value1 = IndexedDBValue("value1", blob_info1);
553 IndexedDBValue value2 = IndexedDBValue("value2", blob_info2);
554 IndexedDBValue value3 = IndexedDBValue("value3", blob_info3);
555 IndexedDBBackingStore::Transaction transaction1(backing_store_);
556 transaction1.Begin();
557 ScopedVector<webkit_blob::BlobDataHandle> handles;
558 IndexedDBBackingStore::RecordIdentifier record;
559 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
560 1,
561 i + 1,
562 key0,
563 value0,
564 &handles,
565 &record).ok());
566 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
567 1,
568 i + 1,
569 key1,
570 value1,
571 &handles,
572 &record).ok());
573 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
574 1,
575 i + 1,
576 key2,
577 value2,
578 &handles,
579 &record).ok());
580 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
581 1,
582 i + 1,
583 key3,
584 value3,
585 &handles,
586 &record).ok());
587 scoped_refptr<TestCallback> callback(new TestCallback());
588 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
589 task_runner_->RunUntilIdle();
590 EXPECT_TRUE(callback->called);
591 EXPECT_TRUE(callback->succeeded);
592 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
593 }
594
595 {
596 IndexedDBBackingStore::Transaction transaction2(backing_store_);
597 transaction2.Begin();
598 IndexedDBValue result_value;
599 EXPECT_TRUE(
600 backing_store_->DeleteRange(&transaction2, 1, i + 1, ranges[i]).ok());
601 scoped_refptr<TestCallback> callback(new TestCallback());
602 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
603 task_runner_->RunUntilIdle();
604 EXPECT_TRUE(callback->called);
605 EXPECT_TRUE(callback->succeeded);
606 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
607 EXPECT_EQ(0UL, backing_store_->removals().size());
608 }
609 }
610 }
611
612 TEST_F(IndexedDBBackingStoreTest, LiveBlobJournal) {
613 {
614 IndexedDBBackingStore::Transaction transaction1(backing_store_);
615 transaction1.Begin();
616 ScopedVector<webkit_blob::BlobDataHandle> handles;
617 IndexedDBBackingStore::RecordIdentifier record;
618 EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
619 1,
620 1,
621 m_key3,
622 m_value3,
623 &handles,
624 &record).ok());
625 scoped_refptr<TestCallback> callback(new TestCallback());
626 EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
627 task_runner_->RunUntilIdle();
628 EXPECT_TRUE(CheckBlobWrites());
629 EXPECT_TRUE(callback->called);
630 EXPECT_TRUE(callback->succeeded);
631 EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
632 }
633
634 IndexedDBValue read_result_value;
635 {
636 IndexedDBBackingStore::Transaction transaction2(backing_store_);
637 transaction2.Begin();
638 EXPECT_TRUE(
639 backing_store_->GetRecord(
640 &transaction2, 1, 1, m_key3, &read_result_value)
641 .ok());
642 scoped_refptr<TestCallback> callback(new TestCallback());
643 EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
644 EXPECT_TRUE(callback->called);
645 EXPECT_TRUE(callback->succeeded);
646 EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
647 EXPECT_EQ(m_value3.bits, read_result_value.bits);
648 EXPECT_TRUE(CheckBlobInfoMatches(read_result_value.blob_info));
649 EXPECT_TRUE(CheckBlobReadsMatchWrites(read_result_value.blob_info));
650 for (size_t i = 0; i < read_result_value.blob_info.size(); ++i) {
651 read_result_value.blob_info[i].mark_used_callback().Run();
652 }
653 }
654
655 {
656 IndexedDBBackingStore::Transaction transaction3(backing_store_);
657 transaction3.Begin();
658 EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
659 1,
660 1,
661 IndexedDBKeyRange(m_key3)).ok());
662 scoped_refptr<TestCallback> callback(new TestCallback());
663 EXPECT_TRUE(transaction3.CommitPhaseOne(callback).ok());
664 task_runner_->RunUntilIdle();
665 EXPECT_TRUE(callback->called);
666 EXPECT_TRUE(callback->succeeded);
667 EXPECT_TRUE(transaction3.CommitPhaseTwo().ok());
668 EXPECT_EQ(0U, backing_store_->removals().size());
669 for (size_t i = 0; i < read_result_value.blob_info.size(); ++i) {
670 read_result_value.blob_info[i].release_callback().Run(
671 read_result_value.blob_info[i].file_path());
672 }
673 task_runner_->RunUntilIdle();
674 EXPECT_NE(0U, backing_store_->removals().size());
675 EXPECT_TRUE(CheckBlobRemovals());
676 }
677 }
678
74 // Make sure that using very high ( more than 32 bit ) values for database_id 679 // Make sure that using very high ( more than 32 bit ) values for database_id
75 // and object_store_id still work. 680 // and object_store_id still work.
76 TEST_F(IndexedDBBackingStoreTest, HighIds) { 681 TEST_F(IndexedDBBackingStoreTest, HighIds) {
77 const int64 high_database_id = 1ULL << 35; 682 const int64 high_database_id = 1ULL << 35;
78 const int64 high_object_store_id = 1ULL << 39; 683 const int64 high_object_store_id = 1ULL << 39;
79 // index_ids are capped at 32 bits for storage purposes. 684 // index_ids are capped at 32 bits for storage purposes.
80 const int64 high_index_id = 1ULL << 29; 685 const int64 high_index_id = 1ULL << 29;
81 686
82 const int64 invalid_high_index_id = 1ULL << 37; 687 const int64 invalid_high_index_id = 1ULL << 37;
83 688
(...skipping 23 matching lines...) Expand all
107 EXPECT_FALSE(s.ok()); 712 EXPECT_FALSE(s.ok());
108 713
109 s = backing_store_->PutIndexDataForRecord(&transaction1, 714 s = backing_store_->PutIndexDataForRecord(&transaction1,
110 high_database_id, 715 high_database_id,
111 high_object_store_id, 716 high_object_store_id,
112 high_index_id, 717 high_index_id,
113 index_key, 718 index_key,
114 record); 719 record);
115 EXPECT_TRUE(s.ok()); 720 EXPECT_TRUE(s.ok());
116 721
117 s = transaction1.Commit(); 722 scoped_refptr<TestCallback> callback(new TestCallback());
723 s = transaction1.CommitPhaseOne(callback);
724 EXPECT_TRUE(s.ok());
725 EXPECT_TRUE(callback->called);
726 EXPECT_TRUE(callback->succeeded);
727 s = transaction1.CommitPhaseTwo();
118 EXPECT_TRUE(s.ok()); 728 EXPECT_TRUE(s.ok());
119 } 729 }
120 730
121 { 731 {
122 IndexedDBBackingStore::Transaction transaction2(backing_store_); 732 IndexedDBBackingStore::Transaction transaction2(backing_store_);
123 transaction2.Begin(); 733 transaction2.Begin();
124 IndexedDBValue result_value; 734 IndexedDBValue result_value;
125 leveldb::Status s = backing_store_->GetRecord(&transaction2, 735 leveldb::Status s = backing_store_->GetRecord(&transaction2,
126 high_database_id, 736 high_database_id,
127 high_object_store_id, 737 high_object_store_id,
(...skipping 13 matching lines...) Expand all
141 751
142 s = backing_store_->GetPrimaryKeyViaIndex(&transaction2, 752 s = backing_store_->GetPrimaryKeyViaIndex(&transaction2,
143 high_database_id, 753 high_database_id,
144 high_object_store_id, 754 high_object_store_id,
145 high_index_id, 755 high_index_id,
146 index_key, 756 index_key,
147 &new_primary_key); 757 &new_primary_key);
148 EXPECT_TRUE(s.ok()); 758 EXPECT_TRUE(s.ok());
149 EXPECT_TRUE(new_primary_key->Equals(m_key1)); 759 EXPECT_TRUE(new_primary_key->Equals(m_key1));
150 760
151 s = transaction2.Commit(); 761 scoped_refptr<TestCallback> callback(new TestCallback());
762 s = transaction2.CommitPhaseOne(callback);
763 EXPECT_TRUE(s.ok());
764 EXPECT_TRUE(callback->called);
765 EXPECT_TRUE(callback->succeeded);
766 s = transaction2.CommitPhaseTwo();
152 EXPECT_TRUE(s.ok()); 767 EXPECT_TRUE(s.ok());
153 } 768 }
154 } 769 }
155 770
156 // Make sure that other invalid ids do not crash. 771 // Make sure that other invalid ids do not crash.
157 TEST_F(IndexedDBBackingStoreTest, InvalidIds) { 772 TEST_F(IndexedDBBackingStoreTest, InvalidIds) {
158 // valid ids for use when testing invalid ids 773 // valid ids for use when testing invalid ids
159 const int64 database_id = 1; 774 const int64 database_id = 1;
160 const int64 object_store_id = 1; 775 const int64 object_store_id = 1;
161 const int64 index_id = kMinimumIndexId; 776 const int64 index_id = kMinimumIndexId;
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 s = backing_store_->CreateIndex(&transaction, 895 s = backing_store_->CreateIndex(&transaction,
281 database_id, 896 database_id,
282 object_store_id, 897 object_store_id,
283 index_id, 898 index_id,
284 index_name, 899 index_name,
285 index_key_path, 900 index_key_path,
286 unique, 901 unique,
287 multi_entry); 902 multi_entry);
288 EXPECT_TRUE(s.ok()); 903 EXPECT_TRUE(s.ok());
289 904
290 s = transaction.Commit(); 905 scoped_refptr<TestCallback> callback(new TestCallback());
906 s = transaction.CommitPhaseOne(callback);
907 EXPECT_TRUE(s.ok());
908 EXPECT_TRUE(callback->called);
909 EXPECT_TRUE(callback->succeeded);
910 s = transaction.CommitPhaseTwo();
291 EXPECT_TRUE(s.ok()); 911 EXPECT_TRUE(s.ok());
292 } 912 }
293 913
294 { 914 {
295 IndexedDBDatabaseMetadata database; 915 IndexedDBDatabaseMetadata database;
296 bool found; 916 bool found;
297 leveldb::Status s = backing_store_->GetIDBDatabaseMetaData( 917 leveldb::Status s = backing_store_->GetIDBDatabaseMetaData(
298 database_name, &database, &found); 918 database_name, &database, &found);
299 EXPECT_TRUE(s.ok()); 919 EXPECT_TRUE(s.ok());
300 EXPECT_TRUE(found); 920 EXPECT_TRUE(found);
(...skipping 18 matching lines...) Expand all
319 EXPECT_EQ(index_name, index.name); 939 EXPECT_EQ(index_name, index.name);
320 EXPECT_EQ(index_key_path, index.key_path); 940 EXPECT_EQ(index_key_path, index.key_path);
321 EXPECT_EQ(unique, index.unique); 941 EXPECT_EQ(unique, index.unique);
322 EXPECT_EQ(multi_entry, index.multi_entry); 942 EXPECT_EQ(multi_entry, index.multi_entry);
323 } 943 }
324 } 944 }
325 945
326 } // namespace 946 } // namespace
327 947
328 } // namespace content 948 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698