| 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 |