Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 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_database.h" | 5 #include "content/browser/indexed_db/indexed_db_database.h" |
| 6 | 6 |
| 7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/strings/string16.h" | 9 #include "base/strings/string16.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| 11 #include "content/browser/indexed_db/indexed_db.h" | 11 #include "content/browser/indexed_db/indexed_db.h" |
| 12 #include "content/browser/indexed_db/indexed_db_backing_store.h" | 12 #include "content/browser/indexed_db/indexed_db_backing_store.h" |
| 13 #include "content/browser/indexed_db/indexed_db_callbacks.h" | 13 #include "content/browser/indexed_db/indexed_db_callbacks.h" |
| 14 #include "content/browser/indexed_db/indexed_db_connection.h" | 14 #include "content/browser/indexed_db/indexed_db_connection.h" |
| 15 #include "content/browser/indexed_db/indexed_db_cursor.h" | 15 #include "content/browser/indexed_db/indexed_db_cursor.h" |
| 16 #include "content/browser/indexed_db/indexed_db_database.h" | 16 #include "content/browser/indexed_db/indexed_db_database.h" |
| 17 #include "content/browser/indexed_db/indexed_db_factory.h" | 17 #include "content/browser/indexed_db/indexed_db_factory.h" |
| 18 #include "content/browser/indexed_db/indexed_db_fake_backing_store.h" | 18 #include "content/browser/indexed_db/indexed_db_fake_backing_store.h" |
| 19 #include "content/browser/indexed_db/indexed_db_transaction.h" | 19 #include "content/browser/indexed_db/indexed_db_transaction.h" |
| 20 #include "content/browser/indexed_db/mock_indexed_db_callbacks.h" | 20 #include "content/browser/indexed_db/mock_indexed_db_callbacks.h" |
| 21 #include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h" | 21 #include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h" |
| 22 #include "testing/gtest/include/gtest/gtest.h" | 22 #include "testing/gtest/include/gtest/gtest.h" |
| 23 | 23 |
| 24 using base::ASCIIToUTF16; | 24 using base::ASCIIToUTF16; |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 const int FAKE_CHILD_PROCESS_ID = 0; | 27 const int kFakeChildProcessId = 0; |
| 28 } | 28 } |
| 29 | 29 |
| 30 namespace content { | 30 namespace content { |
| 31 | 31 |
| 32 TEST(IndexedDBDatabaseTest, BackingStoreRetention) { | 32 TEST(IndexedDBDatabaseTest, BackingStoreRetention) { |
| 33 scoped_refptr<IndexedDBFakeBackingStore> backing_store = | 33 scoped_refptr<IndexedDBFakeBackingStore> backing_store = |
| 34 new IndexedDBFakeBackingStore(); | 34 new IndexedDBFakeBackingStore(); |
| 35 EXPECT_TRUE(backing_store->HasOneRef()); | 35 EXPECT_TRUE(backing_store->HasOneRef()); |
| 36 | 36 |
| 37 IndexedDBFactory* factory = 0; | 37 IndexedDBFactory* factory = 0; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 64 ASSERT_TRUE(s.ok()); | 64 ASSERT_TRUE(s.ok()); |
| 65 EXPECT_FALSE(backing_store->HasOneRef()); // local and db | 65 EXPECT_FALSE(backing_store->HasOneRef()); // local and db |
| 66 | 66 |
| 67 scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks()); | 67 scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks()); |
| 68 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1( | 68 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1( |
| 69 new MockIndexedDBDatabaseCallbacks()); | 69 new MockIndexedDBDatabaseCallbacks()); |
| 70 const int64 transaction_id1 = 1; | 70 const int64 transaction_id1 = 1; |
| 71 IndexedDBPendingConnection connection1( | 71 IndexedDBPendingConnection connection1( |
| 72 request1, | 72 request1, |
| 73 callbacks1, | 73 callbacks1, |
| 74 FAKE_CHILD_PROCESS_ID, | 74 kFakeChildProcessId, |
| 75 transaction_id1, | 75 transaction_id1, |
| 76 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); | 76 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); |
| 77 db->OpenConnection(connection1); | 77 db->OpenConnection(connection1); |
| 78 | 78 |
| 79 EXPECT_FALSE(backing_store->HasOneRef()); // db, connection count > 0 | 79 EXPECT_FALSE(backing_store->HasOneRef()); // db, connection count > 0 |
| 80 | 80 |
| 81 scoped_refptr<MockIndexedDBCallbacks> request2(new MockIndexedDBCallbacks()); | 81 scoped_refptr<MockIndexedDBCallbacks> request2(new MockIndexedDBCallbacks()); |
| 82 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks2( | 82 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks2( |
| 83 new MockIndexedDBDatabaseCallbacks()); | 83 new MockIndexedDBDatabaseCallbacks()); |
| 84 const int64 transaction_id2 = 2; | 84 const int64 transaction_id2 = 2; |
| 85 IndexedDBPendingConnection connection2( | 85 IndexedDBPendingConnection connection2( |
| 86 request2, | 86 request2, |
| 87 callbacks2, | 87 callbacks2, |
| 88 FAKE_CHILD_PROCESS_ID, | 88 kFakeChildProcessId, |
| 89 transaction_id2, | 89 transaction_id2, |
| 90 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); | 90 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); |
| 91 db->OpenConnection(connection2); | 91 db->OpenConnection(connection2); |
| 92 | 92 |
| 93 EXPECT_FALSE(backing_store->HasOneRef()); // local and connection | 93 EXPECT_FALSE(backing_store->HasOneRef()); // local and connection |
| 94 | 94 |
| 95 request1->connection()->ForceClose(); | 95 request1->connection()->ForceClose(); |
| 96 EXPECT_FALSE(request1->connection()->IsConnected()); | 96 EXPECT_FALSE(request1->connection()->IsConnected()); |
| 97 | 97 |
| 98 EXPECT_FALSE(backing_store->HasOneRef()); // local and connection | 98 EXPECT_FALSE(backing_store->HasOneRef()); // local and connection |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 122 ASSERT_TRUE(s.ok()); | 122 ASSERT_TRUE(s.ok()); |
| 123 EXPECT_FALSE(backing_store->HasOneRef()); // local and db | 123 EXPECT_FALSE(backing_store->HasOneRef()); // local and db |
| 124 | 124 |
| 125 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks( | 125 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks( |
| 126 new MockIndexedDBDatabaseCallbacks()); | 126 new MockIndexedDBDatabaseCallbacks()); |
| 127 scoped_refptr<MockIndexedDBCallbacks> request(new MockIndexedDBCallbacks()); | 127 scoped_refptr<MockIndexedDBCallbacks> request(new MockIndexedDBCallbacks()); |
| 128 const int64 upgrade_transaction_id = 3; | 128 const int64 upgrade_transaction_id = 3; |
| 129 IndexedDBPendingConnection connection( | 129 IndexedDBPendingConnection connection( |
| 130 request, | 130 request, |
| 131 callbacks, | 131 callbacks, |
| 132 FAKE_CHILD_PROCESS_ID, | 132 kFakeChildProcessId, |
| 133 upgrade_transaction_id, | 133 upgrade_transaction_id, |
| 134 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); | 134 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); |
| 135 database->OpenConnection(connection); | 135 database->OpenConnection(connection); |
| 136 EXPECT_EQ(database, request->connection()->database()); | 136 EXPECT_EQ(database, request->connection()->database()); |
| 137 | 137 |
| 138 const int64 transaction_id = 123; | 138 const int64 transaction_id = 123; |
| 139 const std::vector<int64> scope; | 139 const std::vector<int64> scope; |
| 140 database->CreateTransaction(transaction_id, | 140 database->CreateTransaction(transaction_id, |
| 141 request->connection(), | 141 request->connection(), |
| 142 scope, | 142 scope, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 186 ASSERT_TRUE(s.ok()); | 186 ASSERT_TRUE(s.ok()); |
| 187 EXPECT_FALSE(backing_store->HasOneRef()); // local and db | 187 EXPECT_FALSE(backing_store->HasOneRef()); // local and db |
| 188 | 188 |
| 189 scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks()); | 189 scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks()); |
| 190 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1( | 190 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1( |
| 191 new MockIndexedDBDatabaseCallbacks()); | 191 new MockIndexedDBDatabaseCallbacks()); |
| 192 const int64 transaction_id1 = 1; | 192 const int64 transaction_id1 = 1; |
| 193 IndexedDBPendingConnection connection( | 193 IndexedDBPendingConnection connection( |
| 194 request1, | 194 request1, |
| 195 callbacks1, | 195 callbacks1, |
| 196 FAKE_CHILD_PROCESS_ID, | 196 kFakeChildProcessId, |
| 197 transaction_id1, | 197 transaction_id1, |
| 198 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); | 198 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); |
| 199 db->OpenConnection(connection); | 199 db->OpenConnection(connection); |
| 200 | 200 |
| 201 EXPECT_FALSE(backing_store->HasOneRef()); // local and db | 201 EXPECT_FALSE(backing_store->HasOneRef()); // local and db |
| 202 | 202 |
| 203 scoped_refptr<MockDeleteCallbacks> request2(new MockDeleteCallbacks()); | 203 scoped_refptr<MockDeleteCallbacks> request2(new MockDeleteCallbacks()); |
| 204 db->DeleteDatabase(request2); | 204 db->DeleteDatabase(request2); |
| 205 | 205 |
| 206 EXPECT_TRUE(request2->blocked_called()); | 206 EXPECT_TRUE(request2->blocked_called()); |
| 207 EXPECT_FALSE(backing_store->HasOneRef()); // local and db | 207 EXPECT_FALSE(backing_store->HasOneRef()); // local and db |
| 208 | 208 |
| 209 db->Close(request1->connection(), true /* forced */); | 209 db->Close(request1->connection(), true /* forced */); |
| 210 | 210 |
| 211 EXPECT_FALSE(db->backing_store()); | 211 EXPECT_FALSE(db->backing_store()); |
| 212 EXPECT_TRUE(backing_store->HasOneRef()); // local | 212 EXPECT_TRUE(backing_store->HasOneRef()); // local |
| 213 EXPECT_TRUE(request2->success_called()); | 213 EXPECT_TRUE(request2->success_called()); |
| 214 } | 214 } |
| 215 | 215 |
| 216 void DummyOperation(IndexedDBTransaction* transaction) { | |
| 217 } | |
| 218 | |
| 219 class IndexedDBDatabaseOperationTest : public testing::Test { | |
| 220 public: | |
| 221 IndexedDBDatabaseOperationTest() : commit_success_(true) {} | |
| 222 | |
| 223 virtual void SetUp() { | |
| 224 backing_store_ = new IndexedDBFakeBackingStore(); | |
| 225 leveldb::Status s; | |
| 226 db_ = IndexedDBDatabase::Create(ASCIIToUTF16("db"), | |
| 227 backing_store_, | |
| 228 NULL /*factory*/, | |
| 229 IndexedDBDatabase::Identifier(), | |
| 230 &s); | |
| 231 ASSERT_TRUE(s.ok()); | |
| 232 | |
| 233 request_ = new MockIndexedDBCallbacks(); | |
| 234 callbacks_ = new MockIndexedDBDatabaseCallbacks(); | |
| 235 const int64 transaction_id = 1; | |
| 236 db_->OpenConnection(IndexedDBPendingConnection( | |
| 237 request_, | |
| 238 callbacks_, | |
| 239 kFakeChildProcessId, | |
| 240 transaction_id, | |
| 241 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION)); | |
| 242 EXPECT_EQ(IndexedDBDatabaseMetadata::NO_INT_VERSION, | |
| 243 db_->metadata().int_version); | |
| 244 | |
| 245 transaction_ = new IndexedDBTransaction( | |
| 246 transaction_id, | |
| 247 callbacks_, | |
| 248 std::set<int64>() /*scope*/, | |
| 249 indexed_db::TRANSACTION_VERSION_CHANGE, | |
| 250 db_, | |
| 251 new IndexedDBFakeBackingStore::FakeTransaction(commit_success_)); | |
| 252 db_->TransactionCreated(transaction_); | |
| 253 | |
| 254 // Add a dummy task which takes the place of the VersionChangeOperation | |
| 255 // which kicks off the upgrade. This ensures that the transaction has | |
| 256 // processed at least one task before the CreateObjectStore call. | |
|
ericu
2014/05/14 01:08:00
Why is that desirable?
jsbell
2014/05/14 11:05:52
The previous formulation of abort tasks was WEIRD.
| |
| 257 transaction_->ScheduleTask(base::Bind(&DummyOperation)); | |
| 258 } | |
| 259 | |
| 260 void RunPostedTasks() { message_loop_.RunUntilIdle(); } | |
|
ericu
2014/05/14 01:08:00
MessageLoop::RunUntilIdle is deprecated.
All the c
jsbell
2014/05/14 11:05:52
Will fix, thanks.
| |
| 261 | |
| 262 protected: | |
| 263 scoped_refptr<IndexedDBFakeBackingStore> backing_store_; | |
| 264 scoped_refptr<IndexedDBDatabase> db_; | |
| 265 scoped_refptr<MockIndexedDBCallbacks> request_; | |
| 266 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks_; | |
| 267 scoped_refptr<IndexedDBTransaction> transaction_; | |
| 268 | |
| 269 bool commit_success_; | |
| 270 | |
| 271 private: | |
| 272 base::MessageLoop message_loop_; | |
| 273 | |
| 274 DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseOperationTest); | |
| 275 }; | |
| 276 | |
| 277 TEST_F(IndexedDBDatabaseOperationTest, CreateObjectStore) { | |
| 278 EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); | |
| 279 const int64 store_id = 1001; | |
| 280 db_->CreateObjectStore(transaction_->id(), | |
| 281 store_id, | |
| 282 ASCIIToUTF16("store"), | |
| 283 IndexedDBKeyPath(), | |
| 284 false /*auto_increment*/); | |
| 285 EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); | |
| 286 RunPostedTasks(); | |
| 287 transaction_->Commit(); | |
| 288 EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); | |
| 289 } | |
| 290 | |
|
ericu
2014/05/14 01:08:00
How about a test that captures the create-put-dele
jsbell
2014/05/14 11:05:52
Will add one. (I have a blink layout test, but can
| |
| 291 TEST_F(IndexedDBDatabaseOperationTest, CreateIndex) { | |
| 292 EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); | |
| 293 const int64 store_id = 1001; | |
| 294 db_->CreateObjectStore(transaction_->id(), | |
| 295 store_id, | |
| 296 ASCIIToUTF16("store"), | |
| 297 IndexedDBKeyPath(), | |
| 298 false /*auto_increment*/); | |
| 299 EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); | |
| 300 const int64 index_id = 2002; | |
| 301 db_->CreateIndex(transaction_->id(), | |
| 302 store_id, | |
| 303 index_id, | |
| 304 ASCIIToUTF16("index"), | |
| 305 IndexedDBKeyPath(), | |
| 306 false /*unique*/, | |
| 307 false /*multi_entry*/); | |
| 308 EXPECT_EQ( | |
| 309 1ULL, | |
| 310 db_->metadata().object_stores.find(store_id)->second.indexes.size()); | |
| 311 RunPostedTasks(); | |
| 312 transaction_->Commit(); | |
| 313 EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); | |
| 314 EXPECT_EQ( | |
| 315 1ULL, | |
| 316 db_->metadata().object_stores.find(store_id)->second.indexes.size()); | |
| 317 } | |
| 318 | |
| 319 class IndexedDBDatabaseOperationAbortTest | |
| 320 : public IndexedDBDatabaseOperationTest { | |
| 321 public: | |
| 322 IndexedDBDatabaseOperationAbortTest() { commit_success_ = false; } | |
| 323 }; | |
| 324 | |
| 325 TEST_F(IndexedDBDatabaseOperationAbortTest, CreateObjectStore) { | |
| 326 EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); | |
| 327 const int64 store_id = 1001; | |
| 328 db_->CreateObjectStore(transaction_->id(), | |
| 329 store_id, | |
| 330 ASCIIToUTF16("store"), | |
| 331 IndexedDBKeyPath(), | |
| 332 false /*auto_increment*/); | |
| 333 EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); | |
| 334 RunPostedTasks(); | |
| 335 transaction_->Commit(); | |
| 336 EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); | |
| 337 } | |
| 338 | |
| 339 TEST_F(IndexedDBDatabaseOperationAbortTest, CreateIndex) { | |
| 340 EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); | |
| 341 const int64 store_id = 1001; | |
| 342 db_->CreateObjectStore(transaction_->id(), | |
| 343 store_id, | |
| 344 ASCIIToUTF16("store"), | |
| 345 IndexedDBKeyPath(), | |
| 346 false /*auto_increment*/); | |
| 347 EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); | |
| 348 const int64 index_id = 2002; | |
| 349 db_->CreateIndex(transaction_->id(), | |
| 350 store_id, | |
| 351 index_id, | |
| 352 ASCIIToUTF16("index"), | |
| 353 IndexedDBKeyPath(), | |
| 354 false /*unique*/, | |
| 355 false /*multi_entry*/); | |
| 356 EXPECT_EQ( | |
| 357 1ULL, | |
| 358 db_->metadata().object_stores.find(store_id)->second.indexes.size()); | |
| 359 RunPostedTasks(); | |
| 360 transaction_->Commit(); | |
| 361 EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); | |
| 362 } | |
| 363 | |
| 216 } // namespace content | 364 } // namespace content |
| OLD | NEW |