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