OLD | NEW |
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" |
| 17 #include "content/browser/indexed_db/indexed_db_value.h" |
| 18 #include "net/url_request/url_request_test_util.h" |
11 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
12 #include "third_party/WebKit/public/platform/WebIDBTypes.h" | 20 #include "third_party/WebKit/public/platform/WebIDBTypes.h" |
| 21 #include "webkit/browser/blob/blob_data_handle.h" |
| 22 #include "webkit/browser/quota/mock_special_storage_policy.h" |
| 23 #include "webkit/browser/quota/special_storage_policy.h" |
13 | 24 |
14 namespace content { | 25 namespace content { |
15 | 26 |
16 namespace { | 27 namespace { |
17 | 28 |
| 29 class Comparator : public LevelDBComparator { |
| 30 public: |
| 31 virtual int Compare(const base::StringPiece& a, |
| 32 const base::StringPiece& b) const OVERRIDE { |
| 33 return content::Compare(a, b, false /*index_keys*/); |
| 34 } |
| 35 virtual const char* Name() const OVERRIDE { return "idb_cmp1"; } |
| 36 }; |
| 37 |
| 38 class DefaultLevelDBFactory : public LevelDBFactory { |
| 39 public: |
| 40 virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name, |
| 41 const LevelDBComparator* comparator, |
| 42 scoped_ptr<LevelDBDatabase>* db, |
| 43 bool* is_disk_full) OVERRIDE { |
| 44 return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full); |
| 45 } |
| 46 virtual bool DestroyLevelDB(const base::FilePath& file_name) OVERRIDE { |
| 47 return LevelDBDatabase::Destroy(file_name); |
| 48 } |
| 49 }; |
| 50 |
| 51 class TestableIndexedDBBackingStore : public IndexedDBBackingStore { |
| 52 public: |
| 53 static scoped_refptr<TestableIndexedDBBackingStore> Open( |
| 54 IndexedDBFactory* indexed_db_factory, |
| 55 const GURL& origin_url, |
| 56 const base::FilePath& path_base, |
| 57 net::URLRequestContext* request_context, |
| 58 LevelDBFactory* leveldb_factory, |
| 59 base::TaskRunner* task_runner) { |
| 60 DCHECK(!path_base.empty()); |
| 61 |
| 62 scoped_ptr<LevelDBComparator> comparator(new Comparator()); |
| 63 |
| 64 if (!file_util::CreateDirectory(path_base)) |
| 65 return scoped_refptr<TestableIndexedDBBackingStore>(); |
| 66 |
| 67 const base::FilePath file_path = path_base.Append("test_db_path"); |
| 68 const base::FilePath blob_path = path_base.Append("test_blob_path"); |
| 69 |
| 70 scoped_ptr<LevelDBDatabase> db; |
| 71 bool is_disk_full = false; |
| 72 leveldb::Status status = leveldb_factory->OpenLevelDB( |
| 73 file_path, comparator.get(), &db, &is_disk_full); |
| 74 |
| 75 if (!db || !status.ok()) |
| 76 return scoped_refptr<TestableIndexedDBBackingStore>(); |
| 77 |
| 78 scoped_refptr<TestableIndexedDBBackingStore> backing_store( |
| 79 new TestableIndexedDBBackingStore(indexed_db_factory, |
| 80 origin_url, |
| 81 blob_path, |
| 82 request_context, |
| 83 db.Pass(), |
| 84 comparator.Pass(), |
| 85 task_runner)); |
| 86 |
| 87 if (!backing_store->SetUpMetadata()) |
| 88 return scoped_refptr<TestableIndexedDBBackingStore>(); |
| 89 |
| 90 return backing_store; |
| 91 } |
| 92 |
| 93 const std::vector<IndexedDBBackingStore::Transaction::WriteDescriptor>& |
| 94 writes() const { |
| 95 return writes_; |
| 96 } |
| 97 const std::vector<int64> removals() const { return removals_; } |
| 98 |
| 99 protected: |
| 100 bool WriteBlobFile(int64 database_id, |
| 101 const Transaction::WriteDescriptor& descriptor, |
| 102 Transaction::ChainedBlobWriter* chained_blob_writer) |
| 103 OVERRIDE { |
| 104 if (KeyPrefix::IsValidDatabaseId(database_id_)) { |
| 105 if (database_id_ != database_id) { |
| 106 return false; |
| 107 } |
| 108 } else { |
| 109 database_id_ = database_id; |
| 110 } |
| 111 writes_.push_back(descriptor); |
| 112 task_runner()->PostTask( |
| 113 FROM_HERE, |
| 114 base::Bind(&Transaction::ChainedBlobWriter::ReportWriteCompletion, |
| 115 chained_blob_writer, |
| 116 true, |
| 117 1)); |
| 118 return true; |
| 119 } |
| 120 |
| 121 bool RemoveBlobFile(int64 database_id, int64 key) OVERRIDE { |
| 122 if (database_id_ != database_id || |
| 123 !KeyPrefix::IsValidDatabaseId(database_id)) { |
| 124 return false; |
| 125 } |
| 126 removals_.push_back(key); |
| 127 return true; |
| 128 } |
| 129 |
| 130 // Timers don't play nicely with unit tests. |
| 131 void StartJournalCleaningTimer() OVERRIDE { |
| 132 CleanPrimaryJournalIgnoreReturn(); |
| 133 } |
| 134 |
| 135 private: |
| 136 TestableIndexedDBBackingStore(IndexedDBFactory* indexed_db_factory, |
| 137 const GURL& origin_url, |
| 138 const base::FilePath& blob_path, |
| 139 net::URLRequestContext* request_context, |
| 140 scoped_ptr<LevelDBDatabase> db, |
| 141 scoped_ptr<LevelDBComparator> comparator, |
| 142 base::TaskRunner* task_runner) |
| 143 : IndexedDBBackingStore(indexed_db_factory, |
| 144 origin_url, |
| 145 blob_path, |
| 146 request_context, |
| 147 db.Pass(), |
| 148 comparator.Pass(), |
| 149 task_runner), |
| 150 database_id_(0) {} |
| 151 |
| 152 int64 database_id_; |
| 153 std::vector<Transaction::WriteDescriptor> writes_; |
| 154 std::vector<int64> removals_; |
| 155 }; |
| 156 |
| 157 class TestIDBFactory : public IndexedDBFactory { |
| 158 public: |
| 159 TestIDBFactory(IndexedDBContextImpl* idb_context) |
| 160 : IndexedDBFactory(idb_context) {} |
| 161 |
| 162 scoped_refptr<TestableIndexedDBBackingStore> OpenBackingStoreForTest( |
| 163 const GURL& origin, |
| 164 net::URLRequestContext* url_request_context, |
| 165 base::TaskRunner* task_runner) { |
| 166 blink::WebIDBDataLoss data_loss; |
| 167 std::string data_loss_reason; |
| 168 bool disk_full; |
| 169 scoped_refptr<IndexedDBBackingStore> backing_store = |
| 170 OpenBackingStore(origin, |
| 171 context()->data_path(), |
| 172 url_request_context, |
| 173 &data_loss, |
| 174 &data_loss_reason, |
| 175 &disk_full, |
| 176 task_runner); |
| 177 scoped_refptr<TestableIndexedDBBackingStore> testable_store = |
| 178 static_cast<TestableIndexedDBBackingStore*>(backing_store.get()); |
| 179 return testable_store; |
| 180 } |
| 181 |
| 182 protected: |
| 183 scoped_refptr<IndexedDBBackingStore> OpenBackingStoreHelper( |
| 184 const GURL& origin_url, |
| 185 const base::FilePath& data_directory, |
| 186 net::URLRequestContext* request_context, |
| 187 blink::WebIDBDataLoss* data_loss, |
| 188 std::string* data_loss_message, |
| 189 bool* disk_full, |
| 190 base::TaskRunner* task_runner, |
| 191 bool first_time) { |
| 192 DefaultLevelDBFactory leveldb_factory; |
| 193 return TestableIndexedDBBackingStore::Open(this, |
| 194 origin_url, |
| 195 data_directory, |
| 196 request_context, |
| 197 &leveldb_factory, |
| 198 task_runner); |
| 199 } |
| 200 }; |
| 201 |
18 class IndexedDBBackingStoreTest : public testing::Test { | 202 class IndexedDBBackingStoreTest : public testing::Test { |
19 public: | 203 public: |
20 IndexedDBBackingStoreTest() {} | 204 IndexedDBBackingStoreTest() {} |
21 virtual void SetUp() { | 205 virtual void SetUp() { |
22 const GURL origin("http://localhost:81"); | 206 const GURL origin("http://localhost:81"); |
23 backing_store_ = IndexedDBBackingStore::OpenInMemory(origin); | 207 task_runner_ = new base::TestSimpleTaskRunner(); |
| 208 special_storage_policy_ = new quota::MockSpecialStoragePolicy(); |
| 209 special_storage_policy_->SetAllUnlimited(true); |
| 210 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 211 idb_context_ = new IndexedDBContextImpl( |
| 212 temp_dir_.path(), special_storage_policy_, NULL, task_runner_); |
| 213 idb_factory_ = new TestIDBFactory(idb_context_); |
| 214 backing_store_ = idb_factory_->OpenBackingStoreForTest( |
| 215 origin, &url_request_context_, task_runner_.get()); |
24 | 216 |
25 // useful keys and values during tests | 217 // useful keys and values during tests |
26 m_value1 = "value1"; | 218 m_value1 = IndexedDBValue("value1", std::vector<IndexedDBBlobInfo>()); |
27 m_value2 = "value2"; | 219 m_value2 = IndexedDBValue("value2", std::vector<IndexedDBBlobInfo>()); |
28 m_value3 = "value3"; | 220 |
| 221 m_blobInfo.push_back( |
| 222 IndexedDBBlobInfo("uuid 3", UTF8ToUTF16("blob type"), 1)); |
| 223 m_blobInfo.push_back( |
| 224 IndexedDBBlobInfo(base::FilePath(FILE_PATH_LITERAL("path/to/file")), |
| 225 UTF8ToUTF16("file name"), |
| 226 UTF8ToUTF16("file type"))); |
| 227 m_value3 = IndexedDBValue("value3", m_blobInfo); |
| 228 |
29 m_key1 = IndexedDBKey(99, blink::WebIDBKeyTypeNumber); | 229 m_key1 = IndexedDBKey(99, blink::WebIDBKeyTypeNumber); |
30 m_key2 = IndexedDBKey(ASCIIToUTF16("key2")); | 230 m_key2 = IndexedDBKey(ASCIIToUTF16("key2")); |
31 m_key3 = IndexedDBKey(ASCIIToUTF16("key3")); | 231 m_key3 = IndexedDBKey(ASCIIToUTF16("key3")); |
32 } | 232 } |
33 | 233 |
| 234 // This just checks the data that survive getting stored and recalled, e.g. |
| 235 // the file path and UUID will change and thus aren't verified. |
| 236 bool CheckBlobInfoMatches(const std::vector<IndexedDBBlobInfo>& reads) const { |
| 237 if (m_blobInfo.size() != reads.size()) |
| 238 return false; |
| 239 for (size_t i = 0; i < m_blobInfo.size(); ++i) { |
| 240 const IndexedDBBlobInfo& a = m_blobInfo[i]; |
| 241 const IndexedDBBlobInfo& b = reads[i]; |
| 242 if (a.is_file() != b.is_file()) |
| 243 return false; |
| 244 if (a.type() != b.type()) |
| 245 return false; |
| 246 if (a.is_file()) { |
| 247 if (a.file_name() != b.file_name()) |
| 248 return false; |
| 249 } else { |
| 250 if (a.size() != b.size()) |
| 251 return false; |
| 252 } |
| 253 } |
| 254 return true; |
| 255 } |
| 256 |
| 257 bool CheckBlobReadsMatchWrites(const std::vector<IndexedDBBlobInfo>& reads) |
| 258 const { |
| 259 if (backing_store_->writes().size() != reads.size()) |
| 260 return false; |
| 261 std::set<int64> ids; |
| 262 for (size_t i = 0; i < backing_store_->writes().size(); ++i) |
| 263 ids.insert(backing_store_->writes()[i].key()); |
| 264 if (ids.size() != backing_store_->writes().size()) |
| 265 return false; |
| 266 for (size_t i = 0; i < reads.size(); ++i) |
| 267 if (ids.count(reads[i].key()) != 1) |
| 268 return false; |
| 269 return true; |
| 270 } |
| 271 |
| 272 bool CheckBlobWrites() const { |
| 273 if (backing_store_->writes().size() != m_blobInfo.size()) |
| 274 return false; |
| 275 for (size_t i = 0; i < backing_store_->writes().size(); ++i) { |
| 276 const IndexedDBBackingStore::Transaction::WriteDescriptor& desc = |
| 277 backing_store_->writes()[i]; |
| 278 const IndexedDBBlobInfo& info = m_blobInfo[i]; |
| 279 if (desc.is_file() != info.is_file()) |
| 280 return false; |
| 281 if (desc.is_file()) { |
| 282 if (desc.file_path() != info.file_path()) |
| 283 return false; |
| 284 } else { |
| 285 if (desc.url() != GURL("blob:uuid/" + info.uuid())) |
| 286 return false; |
| 287 } |
| 288 } |
| 289 return true; |
| 290 } |
| 291 |
| 292 bool CheckBlobRemovals() const { |
| 293 if (backing_store_->removals().size() != backing_store_->writes().size()) |
| 294 return false; |
| 295 for (size_t i = 0; i < backing_store_->writes().size(); ++i) |
| 296 if (backing_store_->writes()[i].key() != backing_store_->removals()[i]) |
| 297 return false; |
| 298 return true; |
| 299 } |
| 300 |
34 protected: | 301 protected: |
35 scoped_refptr<IndexedDBBackingStore> backing_store_; | 302 base::ScopedTempDir temp_dir_; |
| 303 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; |
| 304 scoped_refptr<quota::MockSpecialStoragePolicy> special_storage_policy_; |
| 305 scoped_refptr<IndexedDBContextImpl> idb_context_; |
| 306 scoped_refptr<TestIDBFactory> idb_factory_; |
| 307 net::TestURLRequestContext url_request_context_; |
| 308 |
| 309 scoped_refptr<TestableIndexedDBBackingStore> backing_store_; |
36 | 310 |
37 // Sample keys and values that are consistent. | 311 // Sample keys and values that are consistent. |
38 IndexedDBKey m_key1; | 312 IndexedDBKey m_key1; |
39 IndexedDBKey m_key2; | 313 IndexedDBKey m_key2; |
40 IndexedDBKey m_key3; | 314 IndexedDBKey m_key3; |
41 std::string m_value1; | 315 IndexedDBValue m_value1; |
42 std::string m_value2; | 316 IndexedDBValue m_value2; |
43 std::string m_value3; | 317 IndexedDBValue m_value3; |
| 318 std::vector<IndexedDBBlobInfo> m_blobInfo; |
44 | 319 |
45 private: | 320 private: |
46 DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest); | 321 DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest); |
47 }; | 322 }; |
48 | 323 |
| 324 class TestCallback : public IndexedDBBackingStore::BlobWriteCallback { |
| 325 public: |
| 326 TestCallback() : called(false), succeeded(false) {} |
| 327 virtual ~TestCallback() {} |
| 328 virtual void didSucceed() { |
| 329 called = true; |
| 330 succeeded = true; |
| 331 } |
| 332 virtual void didFail() { |
| 333 called = true; |
| 334 succeeded = false; |
| 335 } |
| 336 bool called; |
| 337 bool succeeded; |
| 338 }; |
| 339 |
49 TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) { | 340 TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) { |
50 { | 341 { |
51 IndexedDBBackingStore::Transaction transaction1(backing_store_); | 342 IndexedDBBackingStore::Transaction transaction1(backing_store_); |
52 transaction1.Begin(); | 343 transaction1.Begin(); |
| 344 ScopedVector<webkit_blob::BlobDataHandle> handles; |
53 IndexedDBBackingStore::RecordIdentifier record; | 345 IndexedDBBackingStore::RecordIdentifier record; |
54 bool ok = backing_store_->PutRecord( | 346 bool ok = backing_store_->PutRecord( |
55 &transaction1, 1, 1, m_key1, m_value1, &record); | 347 &transaction1, 1, 1, m_key1, m_value1, &handles, &record); |
56 EXPECT_TRUE(ok); | 348 EXPECT_TRUE(ok); |
57 transaction1.Commit(); | 349 scoped_refptr<TestCallback> callback(new TestCallback()); |
| 350 EXPECT_TRUE(transaction1.CommitPhaseOne(callback)); |
| 351 EXPECT_TRUE(callback->called); |
| 352 EXPECT_TRUE(callback->succeeded); |
| 353 EXPECT_TRUE(transaction1.CommitPhaseTwo()); |
58 } | 354 } |
59 | 355 |
60 { | 356 { |
61 IndexedDBBackingStore::Transaction transaction2(backing_store_); | 357 IndexedDBBackingStore::Transaction transaction2(backing_store_); |
62 transaction2.Begin(); | 358 transaction2.Begin(); |
63 std::string result_value; | 359 IndexedDBValue result_value; |
64 bool ok = | 360 bool ok = |
65 backing_store_->GetRecord(&transaction2, 1, 1, m_key1, &result_value); | 361 backing_store_->GetRecord(&transaction2, 1, 1, m_key1, &result_value); |
66 transaction2.Commit(); | 362 scoped_refptr<TestCallback> callback(new TestCallback()); |
67 EXPECT_TRUE(ok); | 363 EXPECT_TRUE(transaction2.CommitPhaseOne(callback)); |
68 EXPECT_EQ(m_value1, result_value); | 364 EXPECT_TRUE(ok); |
| 365 EXPECT_TRUE(callback->called); |
| 366 EXPECT_TRUE(callback->succeeded); |
| 367 EXPECT_TRUE(transaction2.CommitPhaseTwo()); |
| 368 EXPECT_EQ(m_value1.bits, result_value.bits); |
69 } | 369 } |
70 } | 370 } |
71 | 371 |
| 372 TEST_F(IndexedDBBackingStoreTest, PutGetConsistencyWithBlobs) { |
| 373 { |
| 374 IndexedDBBackingStore::Transaction transaction1(backing_store_); |
| 375 transaction1.Begin(); |
| 376 ScopedVector<webkit_blob::BlobDataHandle> handles; |
| 377 IndexedDBBackingStore::RecordIdentifier record; |
| 378 bool ok = backing_store_->PutRecord( |
| 379 &transaction1, 1, 1, m_key3, m_value3, &handles, &record); |
| 380 EXPECT_TRUE(ok); |
| 381 scoped_refptr<TestCallback> callback(new TestCallback()); |
| 382 EXPECT_TRUE(transaction1.CommitPhaseOne(callback)); |
| 383 task_runner_->RunUntilIdle(); |
| 384 EXPECT_TRUE(CheckBlobWrites()); |
| 385 EXPECT_TRUE(callback->called); |
| 386 EXPECT_TRUE(callback->succeeded); |
| 387 EXPECT_TRUE(transaction1.CommitPhaseTwo()); |
| 388 } |
| 389 |
| 390 { |
| 391 IndexedDBBackingStore::Transaction transaction2(backing_store_); |
| 392 transaction2.Begin(); |
| 393 IndexedDBValue result_value; |
| 394 bool ok = |
| 395 backing_store_->GetRecord(&transaction2, 1, 1, m_key3, &result_value); |
| 396 EXPECT_TRUE(ok); |
| 397 scoped_refptr<TestCallback> callback(new TestCallback()); |
| 398 EXPECT_TRUE(transaction2.CommitPhaseOne(callback)); |
| 399 EXPECT_TRUE(callback->called); |
| 400 EXPECT_TRUE(callback->succeeded); |
| 401 EXPECT_TRUE(transaction2.CommitPhaseTwo()); |
| 402 EXPECT_EQ(m_value3.bits, result_value.bits); |
| 403 EXPECT_TRUE(CheckBlobInfoMatches(result_value.blob_info)); |
| 404 EXPECT_TRUE(CheckBlobReadsMatchWrites(result_value.blob_info)); |
| 405 } |
| 406 |
| 407 { |
| 408 IndexedDBBackingStore::Transaction transaction3(backing_store_); |
| 409 transaction3.Begin(); |
| 410 IndexedDBValue result_value; |
| 411 bool ok = backing_store_->DeleteRange( |
| 412 &transaction3, 1, 1, IndexedDBKeyRange(m_key3)); |
| 413 EXPECT_TRUE(ok); |
| 414 scoped_refptr<TestCallback> callback(new TestCallback()); |
| 415 EXPECT_TRUE(transaction3.CommitPhaseOne(callback)); |
| 416 task_runner_->RunUntilIdle(); |
| 417 EXPECT_TRUE(callback->called); |
| 418 EXPECT_TRUE(callback->succeeded); |
| 419 EXPECT_TRUE(transaction3.CommitPhaseTwo()); |
| 420 EXPECT_TRUE(CheckBlobRemovals()); |
| 421 } |
| 422 } |
| 423 |
| 424 TEST_F(IndexedDBBackingStoreTest, LiveBlobJournal) { |
| 425 { |
| 426 IndexedDBBackingStore::Transaction transaction1(backing_store_); |
| 427 transaction1.Begin(); |
| 428 ScopedVector<webkit_blob::BlobDataHandle> handles; |
| 429 IndexedDBBackingStore::RecordIdentifier record; |
| 430 bool ok = backing_store_->PutRecord( |
| 431 &transaction1, 1, 1, m_key3, m_value3, &handles, &record); |
| 432 EXPECT_TRUE(ok); |
| 433 scoped_refptr<TestCallback> callback(new TestCallback()); |
| 434 EXPECT_TRUE(transaction1.CommitPhaseOne(callback)); |
| 435 task_runner_->RunUntilIdle(); |
| 436 EXPECT_TRUE(CheckBlobWrites()); |
| 437 EXPECT_TRUE(callback->called); |
| 438 EXPECT_TRUE(callback->succeeded); |
| 439 EXPECT_TRUE(transaction1.CommitPhaseTwo()); |
| 440 } |
| 441 |
| 442 IndexedDBValue read_result_value; |
| 443 { |
| 444 IndexedDBBackingStore::Transaction transaction2(backing_store_); |
| 445 transaction2.Begin(); |
| 446 bool ok = backing_store_->GetRecord( |
| 447 &transaction2, 1, 1, m_key3, &read_result_value); |
| 448 EXPECT_TRUE(ok); |
| 449 scoped_refptr<TestCallback> callback(new TestCallback()); |
| 450 EXPECT_TRUE(transaction2.CommitPhaseOne(callback)); |
| 451 EXPECT_TRUE(callback->called); |
| 452 EXPECT_TRUE(callback->succeeded); |
| 453 EXPECT_TRUE(transaction2.CommitPhaseTwo()); |
| 454 EXPECT_EQ(m_value3.bits, read_result_value.bits); |
| 455 EXPECT_TRUE(CheckBlobInfoMatches(read_result_value.blob_info)); |
| 456 EXPECT_TRUE(CheckBlobReadsMatchWrites(read_result_value.blob_info)); |
| 457 for (size_t i = 0; i < read_result_value.blob_info.size(); ++i) { |
| 458 read_result_value.blob_info[i].mark_used_callback().Run(); |
| 459 } |
| 460 } |
| 461 |
| 462 { |
| 463 IndexedDBBackingStore::Transaction transaction3(backing_store_); |
| 464 transaction3.Begin(); |
| 465 bool ok = backing_store_->DeleteRange( |
| 466 &transaction3, 1, 1, IndexedDBKeyRange(m_key3)); |
| 467 EXPECT_TRUE(ok); |
| 468 scoped_refptr<TestCallback> callback(new TestCallback()); |
| 469 EXPECT_TRUE(transaction3.CommitPhaseOne(callback)); |
| 470 task_runner_->RunUntilIdle(); |
| 471 EXPECT_TRUE(callback->called); |
| 472 EXPECT_TRUE(callback->succeeded); |
| 473 EXPECT_TRUE(transaction3.CommitPhaseTwo()); |
| 474 EXPECT_EQ(0U, backing_store_->removals().size()); |
| 475 for (size_t i = 0; i < read_result_value.blob_info.size(); ++i) { |
| 476 read_result_value.blob_info[i].release_callback().Run( |
| 477 read_result_value.blob_info[i].file_path()); |
| 478 } |
| 479 task_runner_->RunUntilIdle(); |
| 480 EXPECT_NE(0U, backing_store_->removals().size()); |
| 481 EXPECT_TRUE(CheckBlobRemovals()); |
| 482 } |
| 483 } |
| 484 |
72 // Make sure that using very high ( more than 32 bit ) values for database_id | 485 // Make sure that using very high ( more than 32 bit ) values for database_id |
73 // and object_store_id still work. | 486 // and object_store_id still work. |
74 TEST_F(IndexedDBBackingStoreTest, HighIds) { | 487 TEST_F(IndexedDBBackingStoreTest, HighIds) { |
75 const int64 high_database_id = 1ULL << 35; | 488 const int64 high_database_id = 1ULL << 35; |
76 const int64 high_object_store_id = 1ULL << 39; | 489 const int64 high_object_store_id = 1ULL << 39; |
77 // index_ids are capped at 32 bits for storage purposes. | 490 // index_ids are capped at 32 bits for storage purposes. |
78 const int64 high_index_id = 1ULL << 29; | 491 const int64 high_index_id = 1ULL << 29; |
79 | 492 |
80 const int64 invalid_high_index_id = 1ULL << 37; | 493 const int64 invalid_high_index_id = 1ULL << 37; |
81 | 494 |
82 const IndexedDBKey& index_key = m_key2; | 495 const IndexedDBKey& index_key = m_key2; |
83 std::string index_key_raw; | 496 std::string index_key_raw; |
84 EncodeIDBKey(index_key, &index_key_raw); | 497 EncodeIDBKey(index_key, &index_key_raw); |
85 { | 498 { |
86 IndexedDBBackingStore::Transaction transaction1(backing_store_); | 499 IndexedDBBackingStore::Transaction transaction1(backing_store_); |
87 transaction1.Begin(); | 500 transaction1.Begin(); |
| 501 ScopedVector<webkit_blob::BlobDataHandle> handles; |
88 IndexedDBBackingStore::RecordIdentifier record; | 502 IndexedDBBackingStore::RecordIdentifier record; |
89 bool ok = backing_store_->PutRecord(&transaction1, | 503 bool ok = backing_store_->PutRecord(&transaction1, |
90 high_database_id, | 504 high_database_id, |
91 high_object_store_id, | 505 high_object_store_id, |
92 m_key1, | 506 m_key1, |
93 m_value1, | 507 m_value1, |
| 508 &handles, |
94 &record); | 509 &record); |
95 EXPECT_TRUE(ok); | 510 EXPECT_TRUE(ok); |
96 | 511 |
97 ok = backing_store_->PutIndexDataForRecord(&transaction1, | 512 ok = backing_store_->PutIndexDataForRecord(&transaction1, |
98 high_database_id, | 513 high_database_id, |
99 high_object_store_id, | 514 high_object_store_id, |
100 invalid_high_index_id, | 515 invalid_high_index_id, |
101 index_key, | 516 index_key, |
102 record); | 517 record); |
103 EXPECT_FALSE(ok); | 518 EXPECT_FALSE(ok); |
104 | 519 |
105 ok = backing_store_->PutIndexDataForRecord(&transaction1, | 520 ok = backing_store_->PutIndexDataForRecord(&transaction1, |
106 high_database_id, | 521 high_database_id, |
107 high_object_store_id, | 522 high_object_store_id, |
108 high_index_id, | 523 high_index_id, |
109 index_key, | 524 index_key, |
110 record); | 525 record); |
111 EXPECT_TRUE(ok); | 526 EXPECT_TRUE(ok); |
112 | 527 |
113 ok = transaction1.Commit(); | 528 scoped_refptr<TestCallback> callback(new TestCallback()); |
| 529 ok = transaction1.CommitPhaseOne(callback); |
114 EXPECT_TRUE(ok); | 530 EXPECT_TRUE(ok); |
| 531 EXPECT_TRUE(callback->called); |
| 532 EXPECT_TRUE(callback->succeeded); |
| 533 EXPECT_TRUE(transaction1.CommitPhaseTwo()); |
115 } | 534 } |
116 | 535 |
117 { | 536 { |
118 IndexedDBBackingStore::Transaction transaction2(backing_store_); | 537 IndexedDBBackingStore::Transaction transaction2(backing_store_); |
119 transaction2.Begin(); | 538 transaction2.Begin(); |
120 std::string result_value; | 539 IndexedDBValue result_value; |
121 bool ok = backing_store_->GetRecord(&transaction2, | 540 bool ok = backing_store_->GetRecord(&transaction2, |
122 high_database_id, | 541 high_database_id, |
123 high_object_store_id, | 542 high_object_store_id, |
124 m_key1, | 543 m_key1, |
125 &result_value); | 544 &result_value); |
126 EXPECT_TRUE(ok); | 545 EXPECT_TRUE(ok); |
127 EXPECT_EQ(m_value1, result_value); | 546 EXPECT_EQ(m_value1.bits, result_value.bits); |
128 | 547 |
129 scoped_ptr<IndexedDBKey> new_primary_key; | 548 scoped_ptr<IndexedDBKey> new_primary_key; |
130 ok = backing_store_->GetPrimaryKeyViaIndex(&transaction2, | 549 ok = backing_store_->GetPrimaryKeyViaIndex(&transaction2, |
131 high_database_id, | 550 high_database_id, |
132 high_object_store_id, | 551 high_object_store_id, |
133 invalid_high_index_id, | 552 invalid_high_index_id, |
134 index_key, | 553 index_key, |
135 &new_primary_key); | 554 &new_primary_key); |
136 EXPECT_FALSE(ok); | 555 EXPECT_FALSE(ok); |
137 | 556 |
138 ok = backing_store_->GetPrimaryKeyViaIndex(&transaction2, | 557 ok = backing_store_->GetPrimaryKeyViaIndex(&transaction2, |
139 high_database_id, | 558 high_database_id, |
140 high_object_store_id, | 559 high_object_store_id, |
141 high_index_id, | 560 high_index_id, |
142 index_key, | 561 index_key, |
143 &new_primary_key); | 562 &new_primary_key); |
144 EXPECT_TRUE(ok); | 563 EXPECT_TRUE(ok); |
145 EXPECT_TRUE(new_primary_key->IsEqual(m_key1)); | 564 EXPECT_TRUE(new_primary_key->IsEqual(m_key1)); |
146 | 565 |
147 ok = transaction2.Commit(); | 566 scoped_refptr<TestCallback> callback(new TestCallback()); |
| 567 ok = transaction2.CommitPhaseOne(callback); |
148 EXPECT_TRUE(ok); | 568 EXPECT_TRUE(ok); |
| 569 EXPECT_TRUE(callback->called); |
| 570 EXPECT_TRUE(callback->succeeded); |
| 571 EXPECT_TRUE(transaction2.CommitPhaseTwo()); |
149 } | 572 } |
150 } | 573 } |
151 | 574 |
152 // Make sure that other invalid ids do not crash. | 575 // Make sure that other invalid ids do not crash. |
153 TEST_F(IndexedDBBackingStoreTest, InvalidIds) { | 576 TEST_F(IndexedDBBackingStoreTest, InvalidIds) { |
154 // valid ids for use when testing invalid ids | 577 // valid ids for use when testing invalid ids |
155 const int64 database_id = 1; | 578 const int64 database_id = 1; |
156 const int64 object_store_id = 1; | 579 const int64 object_store_id = 1; |
157 const int64 index_id = kMinimumIndexId; | 580 const int64 index_id = kMinimumIndexId; |
158 const int64 invalid_low_index_id = 19; // index_ids must be > kMinimumIndexId | 581 const int64 invalid_low_index_id = 19; // index_ids must be > kMinimumIndexId |
159 | 582 |
160 std::string result_value; | 583 IndexedDBValue result_value; |
161 | 584 |
162 IndexedDBBackingStore::Transaction transaction1(backing_store_); | 585 IndexedDBBackingStore::Transaction transaction1(backing_store_); |
163 transaction1.Begin(); | 586 transaction1.Begin(); |
164 | 587 |
| 588 ScopedVector<webkit_blob::BlobDataHandle> handles; |
165 IndexedDBBackingStore::RecordIdentifier record; | 589 IndexedDBBackingStore::RecordIdentifier record; |
166 bool ok = backing_store_->PutRecord(&transaction1, | 590 bool ok = backing_store_->PutRecord(&transaction1, |
167 database_id, | 591 database_id, |
168 KeyPrefix::kInvalidId, | 592 KeyPrefix::kInvalidId, |
169 m_key1, | 593 m_key1, |
170 m_value1, | 594 m_value1, |
| 595 &handles, |
171 &record); | 596 &record); |
172 EXPECT_FALSE(ok); | 597 EXPECT_FALSE(ok); |
173 ok = backing_store_->PutRecord( | 598 ok = backing_store_->PutRecord( |
174 &transaction1, database_id, 0, m_key1, m_value1, &record); | 599 &transaction1, database_id, 0, m_key1, m_value1, &handles, &record); |
175 EXPECT_FALSE(ok); | 600 EXPECT_FALSE(ok); |
176 ok = backing_store_->PutRecord(&transaction1, | 601 ok = backing_store_->PutRecord(&transaction1, |
177 KeyPrefix::kInvalidId, | 602 KeyPrefix::kInvalidId, |
178 object_store_id, | 603 object_store_id, |
179 m_key1, | 604 m_key1, |
180 m_value1, | 605 m_value1, |
| 606 &handles, |
181 &record); | 607 &record); |
182 EXPECT_FALSE(ok); | 608 EXPECT_FALSE(ok); |
183 ok = backing_store_->PutRecord( | 609 ok = backing_store_->PutRecord( |
184 &transaction1, 0, object_store_id, m_key1, m_value1, &record); | 610 &transaction1, 0, object_store_id, m_key1, m_value1, &handles, &record); |
185 EXPECT_FALSE(ok); | 611 EXPECT_FALSE(ok); |
186 | 612 |
187 ok = backing_store_->GetRecord( | 613 ok = backing_store_->GetRecord( |
188 &transaction1, database_id, KeyPrefix::kInvalidId, m_key1, &result_value); | 614 &transaction1, database_id, KeyPrefix::kInvalidId, m_key1, &result_value); |
189 EXPECT_FALSE(ok); | 615 EXPECT_FALSE(ok); |
190 ok = backing_store_->GetRecord( | 616 ok = backing_store_->GetRecord( |
191 &transaction1, database_id, 0, m_key1, &result_value); | 617 &transaction1, database_id, 0, m_key1, &result_value); |
192 EXPECT_FALSE(ok); | 618 EXPECT_FALSE(ok); |
193 ok = backing_store_->GetRecord(&transaction1, | 619 ok = backing_store_->GetRecord(&transaction1, |
194 KeyPrefix::kInvalidId, | 620 KeyPrefix::kInvalidId, |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 ok = backing_store_->CreateIndex(&transaction, | 699 ok = backing_store_->CreateIndex(&transaction, |
274 database_id, | 700 database_id, |
275 object_store_id, | 701 object_store_id, |
276 index_id, | 702 index_id, |
277 index_name, | 703 index_name, |
278 index_key_path, | 704 index_key_path, |
279 unique, | 705 unique, |
280 multi_entry); | 706 multi_entry); |
281 EXPECT_TRUE(ok); | 707 EXPECT_TRUE(ok); |
282 | 708 |
283 ok = transaction.Commit(); | 709 scoped_refptr<TestCallback> callback(new TestCallback()); |
| 710 ok = transaction.CommitPhaseOne(callback); |
284 EXPECT_TRUE(ok); | 711 EXPECT_TRUE(ok); |
| 712 EXPECT_TRUE(callback->called); |
| 713 EXPECT_TRUE(callback->succeeded); |
| 714 EXPECT_TRUE(transaction.CommitPhaseTwo()); |
285 } | 715 } |
286 | 716 |
287 { | 717 { |
288 IndexedDBDatabaseMetadata database; | 718 IndexedDBDatabaseMetadata database; |
289 bool found; | 719 bool found; |
290 bool ok = backing_store_->GetIDBDatabaseMetaData( | 720 bool ok = backing_store_->GetIDBDatabaseMetaData( |
291 database_name, &database, &found); | 721 database_name, &database, &found); |
292 EXPECT_TRUE(ok); | 722 EXPECT_TRUE(ok); |
293 EXPECT_TRUE(found); | 723 EXPECT_TRUE(found); |
294 | 724 |
(...skipping 17 matching lines...) Expand all Loading... |
312 EXPECT_EQ(index_name, index.name); | 742 EXPECT_EQ(index_name, index.name); |
313 EXPECT_EQ(index_key_path, index.key_path); | 743 EXPECT_EQ(index_key_path, index.key_path); |
314 EXPECT_EQ(unique, index.unique); | 744 EXPECT_EQ(unique, index.unique); |
315 EXPECT_EQ(multi_entry, index.multi_entry); | 745 EXPECT_EQ(multi_entry, index.multi_entry); |
316 } | 746 } |
317 } | 747 } |
318 | 748 |
319 } // namespace | 749 } // namespace |
320 | 750 |
321 } // namespace content | 751 } // namespace content |
OLD | NEW |