Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(237)

Side by Side Diff: content/browser/indexed_db/indexed_db_database_unittest.cc

Issue 277583002: IndexedDB: Prevent store/index deletion from racing ahead of use (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added tests Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698