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/run_loop.h" |
9 #include "base/strings/string16.h" | 10 #include "base/strings/string16.h" |
10 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
11 #include "content/browser/indexed_db/indexed_db.h" | 12 #include "content/browser/indexed_db/indexed_db.h" |
12 #include "content/browser/indexed_db/indexed_db_backing_store.h" | 13 #include "content/browser/indexed_db/indexed_db_backing_store.h" |
13 #include "content/browser/indexed_db/indexed_db_callbacks.h" | 14 #include "content/browser/indexed_db/indexed_db_callbacks.h" |
14 #include "content/browser/indexed_db/indexed_db_connection.h" | 15 #include "content/browser/indexed_db/indexed_db_connection.h" |
15 #include "content/browser/indexed_db/indexed_db_cursor.h" | 16 #include "content/browser/indexed_db/indexed_db_cursor.h" |
16 #include "content/browser/indexed_db/indexed_db_database.h" | 17 #include "content/browser/indexed_db/indexed_db_database.h" |
17 #include "content/browser/indexed_db/indexed_db_factory.h" | 18 #include "content/browser/indexed_db/indexed_db_factory.h" |
18 #include "content/browser/indexed_db/indexed_db_fake_backing_store.h" | 19 #include "content/browser/indexed_db/indexed_db_fake_backing_store.h" |
19 #include "content/browser/indexed_db/indexed_db_transaction.h" | 20 #include "content/browser/indexed_db/indexed_db_transaction.h" |
| 21 #include "content/browser/indexed_db/indexed_db_value.h" |
20 #include "content/browser/indexed_db/mock_indexed_db_callbacks.h" | 22 #include "content/browser/indexed_db/mock_indexed_db_callbacks.h" |
21 #include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h" | 23 #include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h" |
22 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
23 | 25 |
24 using base::ASCIIToUTF16; | 26 using base::ASCIIToUTF16; |
25 | 27 |
26 namespace { | 28 namespace { |
27 const int FAKE_CHILD_PROCESS_ID = 0; | 29 const int kFakeChildProcessId = 0; |
28 } | 30 } |
29 | 31 |
30 namespace content { | 32 namespace content { |
31 | 33 |
32 TEST(IndexedDBDatabaseTest, BackingStoreRetention) { | 34 TEST(IndexedDBDatabaseTest, BackingStoreRetention) { |
33 scoped_refptr<IndexedDBFakeBackingStore> backing_store = | 35 scoped_refptr<IndexedDBFakeBackingStore> backing_store = |
34 new IndexedDBFakeBackingStore(); | 36 new IndexedDBFakeBackingStore(); |
35 EXPECT_TRUE(backing_store->HasOneRef()); | 37 EXPECT_TRUE(backing_store->HasOneRef()); |
36 | 38 |
37 IndexedDBFactory* factory = 0; | 39 IndexedDBFactory* factory = 0; |
(...skipping 26 matching lines...) Expand all Loading... |
64 ASSERT_TRUE(s.ok()); | 66 ASSERT_TRUE(s.ok()); |
65 EXPECT_FALSE(backing_store->HasOneRef()); // local and db | 67 EXPECT_FALSE(backing_store->HasOneRef()); // local and db |
66 | 68 |
67 scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks()); | 69 scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks()); |
68 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1( | 70 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1( |
69 new MockIndexedDBDatabaseCallbacks()); | 71 new MockIndexedDBDatabaseCallbacks()); |
70 const int64 transaction_id1 = 1; | 72 const int64 transaction_id1 = 1; |
71 IndexedDBPendingConnection connection1( | 73 IndexedDBPendingConnection connection1( |
72 request1, | 74 request1, |
73 callbacks1, | 75 callbacks1, |
74 FAKE_CHILD_PROCESS_ID, | 76 kFakeChildProcessId, |
75 transaction_id1, | 77 transaction_id1, |
76 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); | 78 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); |
77 db->OpenConnection(connection1); | 79 db->OpenConnection(connection1); |
78 | 80 |
79 EXPECT_FALSE(backing_store->HasOneRef()); // db, connection count > 0 | 81 EXPECT_FALSE(backing_store->HasOneRef()); // db, connection count > 0 |
80 | 82 |
81 scoped_refptr<MockIndexedDBCallbacks> request2(new MockIndexedDBCallbacks()); | 83 scoped_refptr<MockIndexedDBCallbacks> request2(new MockIndexedDBCallbacks()); |
82 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks2( | 84 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks2( |
83 new MockIndexedDBDatabaseCallbacks()); | 85 new MockIndexedDBDatabaseCallbacks()); |
84 const int64 transaction_id2 = 2; | 86 const int64 transaction_id2 = 2; |
85 IndexedDBPendingConnection connection2( | 87 IndexedDBPendingConnection connection2( |
86 request2, | 88 request2, |
87 callbacks2, | 89 callbacks2, |
88 FAKE_CHILD_PROCESS_ID, | 90 kFakeChildProcessId, |
89 transaction_id2, | 91 transaction_id2, |
90 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); | 92 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); |
91 db->OpenConnection(connection2); | 93 db->OpenConnection(connection2); |
92 | 94 |
93 EXPECT_FALSE(backing_store->HasOneRef()); // local and connection | 95 EXPECT_FALSE(backing_store->HasOneRef()); // local and connection |
94 | 96 |
95 request1->connection()->ForceClose(); | 97 request1->connection()->ForceClose(); |
96 EXPECT_FALSE(request1->connection()->IsConnected()); | 98 EXPECT_FALSE(request1->connection()->IsConnected()); |
97 | 99 |
98 EXPECT_FALSE(backing_store->HasOneRef()); // local and connection | 100 EXPECT_FALSE(backing_store->HasOneRef()); // local and connection |
(...skipping 23 matching lines...) Expand all Loading... |
122 ASSERT_TRUE(s.ok()); | 124 ASSERT_TRUE(s.ok()); |
123 EXPECT_FALSE(backing_store->HasOneRef()); // local and db | 125 EXPECT_FALSE(backing_store->HasOneRef()); // local and db |
124 | 126 |
125 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks( | 127 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks( |
126 new MockIndexedDBDatabaseCallbacks()); | 128 new MockIndexedDBDatabaseCallbacks()); |
127 scoped_refptr<MockIndexedDBCallbacks> request(new MockIndexedDBCallbacks()); | 129 scoped_refptr<MockIndexedDBCallbacks> request(new MockIndexedDBCallbacks()); |
128 const int64 upgrade_transaction_id = 3; | 130 const int64 upgrade_transaction_id = 3; |
129 IndexedDBPendingConnection connection( | 131 IndexedDBPendingConnection connection( |
130 request, | 132 request, |
131 callbacks, | 133 callbacks, |
132 FAKE_CHILD_PROCESS_ID, | 134 kFakeChildProcessId, |
133 upgrade_transaction_id, | 135 upgrade_transaction_id, |
134 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); | 136 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); |
135 database->OpenConnection(connection); | 137 database->OpenConnection(connection); |
136 EXPECT_EQ(database, request->connection()->database()); | 138 EXPECT_EQ(database, request->connection()->database()); |
137 | 139 |
138 const int64 transaction_id = 123; | 140 const int64 transaction_id = 123; |
139 const std::vector<int64> scope; | 141 const std::vector<int64> scope; |
140 database->CreateTransaction(transaction_id, | 142 database->CreateTransaction(transaction_id, |
141 request->connection(), | 143 request->connection(), |
142 scope, | 144 scope, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 ASSERT_TRUE(s.ok()); | 188 ASSERT_TRUE(s.ok()); |
187 EXPECT_FALSE(backing_store->HasOneRef()); // local and db | 189 EXPECT_FALSE(backing_store->HasOneRef()); // local and db |
188 | 190 |
189 scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks()); | 191 scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks()); |
190 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1( | 192 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1( |
191 new MockIndexedDBDatabaseCallbacks()); | 193 new MockIndexedDBDatabaseCallbacks()); |
192 const int64 transaction_id1 = 1; | 194 const int64 transaction_id1 = 1; |
193 IndexedDBPendingConnection connection( | 195 IndexedDBPendingConnection connection( |
194 request1, | 196 request1, |
195 callbacks1, | 197 callbacks1, |
196 FAKE_CHILD_PROCESS_ID, | 198 kFakeChildProcessId, |
197 transaction_id1, | 199 transaction_id1, |
198 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); | 200 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); |
199 db->OpenConnection(connection); | 201 db->OpenConnection(connection); |
200 | 202 |
201 EXPECT_FALSE(backing_store->HasOneRef()); // local and db | 203 EXPECT_FALSE(backing_store->HasOneRef()); // local and db |
202 | 204 |
203 scoped_refptr<MockDeleteCallbacks> request2(new MockDeleteCallbacks()); | 205 scoped_refptr<MockDeleteCallbacks> request2(new MockDeleteCallbacks()); |
204 db->DeleteDatabase(request2); | 206 db->DeleteDatabase(request2); |
205 | 207 |
206 EXPECT_TRUE(request2->blocked_called()); | 208 EXPECT_TRUE(request2->blocked_called()); |
207 EXPECT_FALSE(backing_store->HasOneRef()); // local and db | 209 EXPECT_FALSE(backing_store->HasOneRef()); // local and db |
208 | 210 |
209 db->Close(request1->connection(), true /* forced */); | 211 db->Close(request1->connection(), true /* forced */); |
210 | 212 |
211 EXPECT_FALSE(db->backing_store()); | 213 EXPECT_FALSE(db->backing_store()); |
212 EXPECT_TRUE(backing_store->HasOneRef()); // local | 214 EXPECT_TRUE(backing_store->HasOneRef()); // local |
213 EXPECT_TRUE(request2->success_called()); | 215 EXPECT_TRUE(request2->success_called()); |
214 } | 216 } |
215 | 217 |
| 218 void DummyOperation(IndexedDBTransaction* transaction) { |
| 219 } |
| 220 |
| 221 class IndexedDBDatabaseOperationTest : public testing::Test { |
| 222 public: |
| 223 IndexedDBDatabaseOperationTest() : commit_success_(true) {} |
| 224 |
| 225 virtual void SetUp() { |
| 226 backing_store_ = new IndexedDBFakeBackingStore(); |
| 227 leveldb::Status s; |
| 228 db_ = IndexedDBDatabase::Create(ASCIIToUTF16("db"), |
| 229 backing_store_, |
| 230 NULL /*factory*/, |
| 231 IndexedDBDatabase::Identifier(), |
| 232 &s); |
| 233 ASSERT_TRUE(s.ok()); |
| 234 |
| 235 request_ = new MockIndexedDBCallbacks(); |
| 236 callbacks_ = new MockIndexedDBDatabaseCallbacks(); |
| 237 const int64 transaction_id = 1; |
| 238 db_->OpenConnection(IndexedDBPendingConnection( |
| 239 request_, |
| 240 callbacks_, |
| 241 kFakeChildProcessId, |
| 242 transaction_id, |
| 243 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION)); |
| 244 EXPECT_EQ(IndexedDBDatabaseMetadata::NO_INT_VERSION, |
| 245 db_->metadata().int_version); |
| 246 |
| 247 transaction_ = new IndexedDBTransaction( |
| 248 transaction_id, |
| 249 callbacks_, |
| 250 std::set<int64>() /*scope*/, |
| 251 indexed_db::TRANSACTION_VERSION_CHANGE, |
| 252 db_, |
| 253 new IndexedDBFakeBackingStore::FakeTransaction(commit_success_)); |
| 254 db_->TransactionCreated(transaction_); |
| 255 |
| 256 // Add a dummy task which takes the place of the VersionChangeOperation |
| 257 // which kicks off the upgrade. This ensures that the transaction has |
| 258 // processed at least one task before the CreateObjectStore call. |
| 259 transaction_->ScheduleTask(base::Bind(&DummyOperation)); |
| 260 } |
| 261 |
| 262 void RunPostedTasks() { base::RunLoop().RunUntilIdle(); } |
| 263 |
| 264 protected: |
| 265 scoped_refptr<IndexedDBFakeBackingStore> backing_store_; |
| 266 scoped_refptr<IndexedDBDatabase> db_; |
| 267 scoped_refptr<MockIndexedDBCallbacks> request_; |
| 268 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks_; |
| 269 scoped_refptr<IndexedDBTransaction> transaction_; |
| 270 |
| 271 bool commit_success_; |
| 272 |
| 273 private: |
| 274 base::MessageLoop message_loop_; |
| 275 |
| 276 DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseOperationTest); |
| 277 }; |
| 278 |
| 279 TEST_F(IndexedDBDatabaseOperationTest, CreateObjectStore) { |
| 280 EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); |
| 281 const int64 store_id = 1001; |
| 282 db_->CreateObjectStore(transaction_->id(), |
| 283 store_id, |
| 284 ASCIIToUTF16("store"), |
| 285 IndexedDBKeyPath(), |
| 286 false /*auto_increment*/); |
| 287 EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); |
| 288 RunPostedTasks(); |
| 289 transaction_->Commit(); |
| 290 EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); |
| 291 } |
| 292 |
| 293 TEST_F(IndexedDBDatabaseOperationTest, CreateIndex) { |
| 294 EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); |
| 295 const int64 store_id = 1001; |
| 296 db_->CreateObjectStore(transaction_->id(), |
| 297 store_id, |
| 298 ASCIIToUTF16("store"), |
| 299 IndexedDBKeyPath(), |
| 300 false /*auto_increment*/); |
| 301 EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); |
| 302 const int64 index_id = 2002; |
| 303 db_->CreateIndex(transaction_->id(), |
| 304 store_id, |
| 305 index_id, |
| 306 ASCIIToUTF16("index"), |
| 307 IndexedDBKeyPath(), |
| 308 false /*unique*/, |
| 309 false /*multi_entry*/); |
| 310 EXPECT_EQ( |
| 311 1ULL, |
| 312 db_->metadata().object_stores.find(store_id)->second.indexes.size()); |
| 313 RunPostedTasks(); |
| 314 transaction_->Commit(); |
| 315 EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); |
| 316 EXPECT_EQ( |
| 317 1ULL, |
| 318 db_->metadata().object_stores.find(store_id)->second.indexes.size()); |
| 319 } |
| 320 |
| 321 class IndexedDBDatabaseOperationAbortTest |
| 322 : public IndexedDBDatabaseOperationTest { |
| 323 public: |
| 324 IndexedDBDatabaseOperationAbortTest() { commit_success_ = false; } |
| 325 }; |
| 326 |
| 327 TEST_F(IndexedDBDatabaseOperationAbortTest, CreateObjectStore) { |
| 328 EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); |
| 329 const int64 store_id = 1001; |
| 330 db_->CreateObjectStore(transaction_->id(), |
| 331 store_id, |
| 332 ASCIIToUTF16("store"), |
| 333 IndexedDBKeyPath(), |
| 334 false /*auto_increment*/); |
| 335 EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); |
| 336 RunPostedTasks(); |
| 337 transaction_->Commit(); |
| 338 EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); |
| 339 } |
| 340 |
| 341 TEST_F(IndexedDBDatabaseOperationAbortTest, CreateIndex) { |
| 342 EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); |
| 343 const int64 store_id = 1001; |
| 344 db_->CreateObjectStore(transaction_->id(), |
| 345 store_id, |
| 346 ASCIIToUTF16("store"), |
| 347 IndexedDBKeyPath(), |
| 348 false /*auto_increment*/); |
| 349 EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); |
| 350 const int64 index_id = 2002; |
| 351 db_->CreateIndex(transaction_->id(), |
| 352 store_id, |
| 353 index_id, |
| 354 ASCIIToUTF16("index"), |
| 355 IndexedDBKeyPath(), |
| 356 false /*unique*/, |
| 357 false /*multi_entry*/); |
| 358 EXPECT_EQ( |
| 359 1ULL, |
| 360 db_->metadata().object_stores.find(store_id)->second.indexes.size()); |
| 361 RunPostedTasks(); |
| 362 transaction_->Commit(); |
| 363 EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); |
| 364 } |
| 365 |
| 366 TEST_F(IndexedDBDatabaseOperationTest, CreatePutDelete) { |
| 367 EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); |
| 368 const int64 store_id = 1001; |
| 369 |
| 370 // Creation is synchronous. |
| 371 db_->CreateObjectStore(transaction_->id(), |
| 372 store_id, |
| 373 ASCIIToUTF16("store"), |
| 374 IndexedDBKeyPath(), |
| 375 false /*auto_increment*/); |
| 376 EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); |
| 377 |
| 378 |
| 379 // Put is asynchronous |
| 380 IndexedDBValue value("value1", std::vector<IndexedDBBlobInfo>()); |
| 381 ScopedVector<webkit_blob::BlobDataHandle> handles; |
| 382 scoped_ptr<IndexedDBKey> key(new IndexedDBKey("key")); |
| 383 std::vector<IndexedDBDatabase::IndexKeys> index_keys; |
| 384 scoped_refptr<MockIndexedDBCallbacks> request( |
| 385 new MockIndexedDBCallbacks(false)); |
| 386 db_->Put(transaction_->id(), |
| 387 store_id, |
| 388 &value, |
| 389 &handles, |
| 390 key.Pass(), |
| 391 IndexedDBDatabase::ADD_ONLY, |
| 392 request, |
| 393 index_keys); |
| 394 |
| 395 // Deletion is asynchronous. |
| 396 db_->DeleteObjectStore(transaction_->id(), |
| 397 store_id); |
| 398 EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); |
| 399 |
| 400 // This will execute the Put then Delete. |
| 401 RunPostedTasks(); |
| 402 EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); |
| 403 } |
| 404 |
216 } // namespace content | 405 } // namespace content |
OLD | NEW |