Chromium Code Reviews| Index: content/browser/indexed_db/leveldb/leveldb_transaction_unittest.cc |
| diff --git a/content/browser/indexed_db/leveldb/leveldb_transaction_unittest.cc b/content/browser/indexed_db/leveldb/leveldb_transaction_unittest.cc |
| index 2052d1ab9b4388b9c6ee9b322975b779db053507..60f0b732d65ea2566860c69f4e63a62e569a307d 100644 |
| --- a/content/browser/indexed_db/leveldb/leveldb_transaction_unittest.cc |
| +++ b/content/browser/indexed_db/leveldb/leveldb_transaction_unittest.cc |
| @@ -24,6 +24,7 @@ |
| namespace content { |
| namespace { |
| +static const size_t kTestingMaxOpenCursors = 3; |
| class SimpleComparator : public LevelDBComparator { |
| public: |
| @@ -35,12 +36,17 @@ class SimpleComparator : public LevelDBComparator { |
| const char* Name() const override { return "temp_comparator"; } |
| }; |
| +} // namespace |
| + |
| class LevelDBTransactionTest : public testing::Test { |
| public: |
| LevelDBTransactionTest() {} |
| void SetUp() override { |
| ASSERT_TRUE(temp_directory_.CreateUniqueTempDir()); |
| - LevelDBDatabase::Open(temp_directory_.GetPath(), &comparator_, &leveldb_); |
| + leveldb::Status s = |
| + LevelDBDatabase::Open(temp_directory_.GetPath(), &comparator_, |
| + &leveldb_, kTestingMaxOpenCursors); |
| + ASSERT_TRUE(s.ok()); |
| ASSERT_TRUE(leveldb_); |
| } |
| void TearDown() override {} |
| @@ -96,6 +102,10 @@ class LevelDBTransactionTest : public testing::Test { |
| LevelDBDatabase* db() { return leveldb_.get(); } |
| + scoped_refptr<LevelDBTransaction> CreateTransaction() { |
| + return new LevelDBTransaction(db()); |
| + } |
| + |
| private: |
| base::ScopedTempDir temp_directory_; |
| SimpleComparator comparator_; |
| @@ -104,8 +114,6 @@ class LevelDBTransactionTest : public testing::Test { |
| DISALLOW_COPY_AND_ASSIGN(LevelDBTransactionTest); |
| }; |
| -} // namespace |
| - |
| TEST_F(LevelDBTransactionTest, GetAndPut) { |
| leveldb::Status status; |
| @@ -210,6 +218,72 @@ TEST_F(LevelDBTransactionTest, Commit) { |
| EXPECT_EQ(value3, got_value); |
| } |
| +TEST_F(LevelDBTransactionTest, IterationWithEvictedCursors) { |
| + leveldb::Status status; |
| + |
| + const std::string key1("key1"); |
|
pwnall
2017/03/24 09:16:03
You don't seem to reuse these strings (which is pe
dmurph
2017/03/24 23:33:39
Done.
|
| + const std::string key2("key2"); |
| + const std::string key3("key3"); |
| + const std::string value1("value1"); |
| + const std::string value2("value2"); |
| + const std::string value3("value3"); |
| + |
| + Put(key1, value1); |
| + Put(key2, value2); |
| + Put(key3, value3); |
| + |
| + scoped_refptr<LevelDBTransaction> transaction = CreateTransaction(); |
| + |
| + std::unique_ptr<LevelDBIterator> evicted_normal_location = |
| + transaction->CreateIterator(); |
| + |
| + std::unique_ptr<LevelDBIterator> evicted_before_start = |
| + transaction->CreateIterator(); |
| + |
| + std::unique_ptr<LevelDBIterator> evicted_after_end = |
| + transaction->CreateIterator(); |
| + |
| + std::unique_ptr<LevelDBIterator> it1 = transaction->CreateIterator(); |
| + std::unique_ptr<LevelDBIterator> it2 = transaction->CreateIterator(); |
| + std::unique_ptr<LevelDBIterator> it3 = transaction->CreateIterator(); |
| + |
| + evicted_normal_location->Seek("key1"); |
| + evicted_before_start->Seek("key1"); |
| + evicted_before_start->Prev(); |
| + evicted_after_end->SeekToLast(); |
| + evicted_after_end->Next(); |
| + |
| + // Nothing is purged, as we just have 3 iterators used. |
| + EXPECT_FALSE(evicted_normal_location->IsEvicted()); |
| + EXPECT_FALSE(evicted_before_start->IsEvicted()); |
| + EXPECT_FALSE(evicted_after_end->IsEvicted()); |
| + EXPECT_FALSE(evicted_before_start->IsValid()); |
| + EXPECT_FALSE(evicted_after_end->IsValid()); |
| + |
| + // Should purge all of our earlier iterators. |
| + it1->Seek("key1"); |
| + it2->Seek("key2"); |
| + it3->Seek("key3"); |
| + |
| + EXPECT_TRUE(evicted_normal_location->IsEvicted()); |
| + EXPECT_TRUE(evicted_before_start->IsEvicted()); |
| + EXPECT_TRUE(evicted_after_end->IsEvicted()); |
| + |
| + // Check we don't need to reload for just the key. |
| + EXPECT_EQ(key1, evicted_normal_location->Key()); |
| + EXPECT_TRUE(evicted_normal_location->IsEvicted()); |
| + |
| + // Make sure iterators are reloaded correctly. |
| + EXPECT_TRUE(evicted_normal_location->IsValid()); |
| + EXPECT_EQ(value1, evicted_normal_location->Value()); |
| + EXPECT_FALSE(evicted_normal_location->IsEvicted()); |
| + EXPECT_FALSE(evicted_before_start->IsValid()); |
| + EXPECT_FALSE(evicted_after_end->IsValid()); |
| + |
| + // And our |Value()| call purged the earlier iterator. |
| + EXPECT_TRUE(it1->IsEvicted()); |
| +} |
| + |
| namespace { |
| enum RangePrepareMode { |
| DataInMemory, |