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