Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_database_unittest.cc
blob865086a9b27a6011220ed6d383d855083d1a9041
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
3 // found in the LICENSE file.
5 #include "content/browser/indexed_db/indexed_db_database.h"
7 #include <set>
9 #include "base/auto_reset.h"
10 #include "base/logging.h"
11 #include "base/run_loop.h"
12 #include "base/strings/string16.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "content/browser/indexed_db/indexed_db.h"
15 #include "content/browser/indexed_db/indexed_db_backing_store.h"
16 #include "content/browser/indexed_db/indexed_db_callbacks.h"
17 #include "content/browser/indexed_db/indexed_db_connection.h"
18 #include "content/browser/indexed_db/indexed_db_cursor.h"
19 #include "content/browser/indexed_db/indexed_db_fake_backing_store.h"
20 #include "content/browser/indexed_db/indexed_db_transaction.h"
21 #include "content/browser/indexed_db/indexed_db_value.h"
22 #include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
23 #include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
24 #include "content/browser/indexed_db/mock_indexed_db_factory.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 using base::ASCIIToUTF16;
29 namespace {
30 const int kFakeChildProcessId = 0;
33 namespace content {
35 TEST(IndexedDBDatabaseTest, BackingStoreRetention) {
36 scoped_refptr<IndexedDBFakeBackingStore> backing_store =
37 new IndexedDBFakeBackingStore();
38 EXPECT_TRUE(backing_store->HasOneRef());
40 scoped_refptr<MockIndexedDBFactory> factory = new MockIndexedDBFactory();
41 leveldb::Status s;
42 scoped_refptr<IndexedDBDatabase> db =
43 IndexedDBDatabase::Create(ASCIIToUTF16("db"),
44 backing_store.get(),
45 factory.get(),
46 IndexedDBDatabase::Identifier(),
47 &s);
48 ASSERT_TRUE(s.ok());
49 EXPECT_FALSE(backing_store->HasOneRef()); // local and db
50 db = NULL;
51 EXPECT_TRUE(backing_store->HasOneRef()); // local
54 TEST(IndexedDBDatabaseTest, ConnectionLifecycle) {
55 scoped_refptr<IndexedDBFakeBackingStore> backing_store =
56 new IndexedDBFakeBackingStore();
57 EXPECT_TRUE(backing_store->HasOneRef()); // local
59 scoped_refptr<MockIndexedDBFactory> factory = new MockIndexedDBFactory();
60 leveldb::Status s;
61 scoped_refptr<IndexedDBDatabase> db =
62 IndexedDBDatabase::Create(ASCIIToUTF16("db"),
63 backing_store.get(),
64 factory.get(),
65 IndexedDBDatabase::Identifier(),
66 &s);
67 ASSERT_TRUE(s.ok());
68 EXPECT_FALSE(backing_store->HasOneRef()); // local and db
70 scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks());
71 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1(
72 new MockIndexedDBDatabaseCallbacks());
73 const int64 transaction_id1 = 1;
74 IndexedDBPendingConnection connection1(
75 request1,
76 callbacks1,
77 kFakeChildProcessId,
78 transaction_id1,
79 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
80 db->OpenConnection(connection1);
82 EXPECT_FALSE(backing_store->HasOneRef()); // db, connection count > 0
84 scoped_refptr<MockIndexedDBCallbacks> request2(new MockIndexedDBCallbacks());
85 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks2(
86 new MockIndexedDBDatabaseCallbacks());
87 const int64 transaction_id2 = 2;
88 IndexedDBPendingConnection connection2(
89 request2,
90 callbacks2,
91 kFakeChildProcessId,
92 transaction_id2,
93 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
94 db->OpenConnection(connection2);
96 EXPECT_FALSE(backing_store->HasOneRef()); // local and connection
98 request1->connection()->ForceClose();
99 EXPECT_FALSE(request1->connection()->IsConnected());
101 EXPECT_FALSE(backing_store->HasOneRef()); // local and connection
103 request2->connection()->ForceClose();
104 EXPECT_FALSE(request2->connection()->IsConnected());
106 EXPECT_TRUE(backing_store->HasOneRef());
107 EXPECT_FALSE(db->backing_store());
109 db = NULL;
112 TEST(IndexedDBDatabaseTest, ForcedClose) {
113 scoped_refptr<IndexedDBFakeBackingStore> backing_store =
114 new IndexedDBFakeBackingStore();
115 EXPECT_TRUE(backing_store->HasOneRef());
117 scoped_refptr<MockIndexedDBFactory> factory = new MockIndexedDBFactory();
118 leveldb::Status s;
119 scoped_refptr<IndexedDBDatabase> database =
120 IndexedDBDatabase::Create(ASCIIToUTF16("db"),
121 backing_store.get(),
122 factory.get(),
123 IndexedDBDatabase::Identifier(),
124 &s);
125 ASSERT_TRUE(s.ok());
126 EXPECT_FALSE(backing_store->HasOneRef()); // local and db
128 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks(
129 new MockIndexedDBDatabaseCallbacks());
130 scoped_refptr<MockIndexedDBCallbacks> request(new MockIndexedDBCallbacks());
131 const int64 upgrade_transaction_id = 3;
132 IndexedDBPendingConnection connection(
133 request,
134 callbacks,
135 kFakeChildProcessId,
136 upgrade_transaction_id,
137 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
138 database->OpenConnection(connection);
139 EXPECT_EQ(database.get(), request->connection()->database());
141 const int64 transaction_id = 123;
142 const std::vector<int64> scope;
143 database->CreateTransaction(transaction_id,
144 request->connection(),
145 scope,
146 blink::WebIDBTransactionModeReadOnly);
148 request->connection()->ForceClose();
150 EXPECT_TRUE(backing_store->HasOneRef()); // local
151 EXPECT_TRUE(callbacks->abort_called());
154 class MockDeleteCallbacks : public IndexedDBCallbacks {
155 public:
156 MockDeleteCallbacks()
157 : IndexedDBCallbacks(NULL, 0, 0),
158 blocked_called_(false),
159 success_called_(false) {}
161 void OnBlocked(int64 existing_version) override { blocked_called_ = true; }
162 void OnSuccess(int64 result) override { success_called_ = true; }
164 bool blocked_called() const { return blocked_called_; }
165 bool success_called() const { return success_called_; }
167 private:
168 ~MockDeleteCallbacks() override {}
170 bool blocked_called_;
171 bool success_called_;
173 DISALLOW_COPY_AND_ASSIGN(MockDeleteCallbacks);
176 TEST(IndexedDBDatabaseTest, PendingDelete) {
177 scoped_refptr<IndexedDBFakeBackingStore> backing_store =
178 new IndexedDBFakeBackingStore();
179 EXPECT_TRUE(backing_store->HasOneRef()); // local
181 scoped_refptr<MockIndexedDBFactory> factory = new MockIndexedDBFactory();
182 leveldb::Status s;
183 scoped_refptr<IndexedDBDatabase> db =
184 IndexedDBDatabase::Create(ASCIIToUTF16("db"),
185 backing_store.get(),
186 factory.get(),
187 IndexedDBDatabase::Identifier(),
188 &s);
189 ASSERT_TRUE(s.ok());
190 EXPECT_FALSE(backing_store->HasOneRef()); // local and db
192 scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks());
193 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1(
194 new MockIndexedDBDatabaseCallbacks());
195 const int64 transaction_id1 = 1;
196 IndexedDBPendingConnection connection(
197 request1,
198 callbacks1,
199 kFakeChildProcessId,
200 transaction_id1,
201 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
202 db->OpenConnection(connection);
204 EXPECT_FALSE(backing_store->HasOneRef()); // local and db
206 scoped_refptr<MockDeleteCallbacks> request2(new MockDeleteCallbacks());
207 db->DeleteDatabase(request2);
209 EXPECT_FALSE(request2->blocked_called());
210 db->VersionChangeIgnored();
211 EXPECT_TRUE(request2->blocked_called());
213 EXPECT_FALSE(backing_store->HasOneRef()); // local and db
215 db->Close(request1->connection(), true /* forced */);
217 EXPECT_FALSE(db->backing_store());
218 EXPECT_TRUE(backing_store->HasOneRef()); // local
219 EXPECT_TRUE(request2->success_called());
222 void DummyOperation(IndexedDBTransaction* transaction) {
225 class IndexedDBDatabaseOperationTest : public testing::Test {
226 public:
227 IndexedDBDatabaseOperationTest()
228 : commit_success_(leveldb::Status::OK()),
229 factory_(new MockIndexedDBFactory()) {}
231 void SetUp() override {
232 backing_store_ = new IndexedDBFakeBackingStore();
233 leveldb::Status s;
234 db_ = IndexedDBDatabase::Create(ASCIIToUTF16("db"),
235 backing_store_.get(),
236 factory_.get(),
237 IndexedDBDatabase::Identifier(),
238 &s);
239 ASSERT_TRUE(s.ok());
241 request_ = new MockIndexedDBCallbacks();
242 callbacks_ = new MockIndexedDBDatabaseCallbacks();
243 const int64 transaction_id = 1;
244 db_->OpenConnection(IndexedDBPendingConnection(
245 request_,
246 callbacks_,
247 kFakeChildProcessId,
248 transaction_id,
249 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION));
250 EXPECT_EQ(IndexedDBDatabaseMetadata::NO_INT_VERSION,
251 db_->metadata().int_version);
253 transaction_ = new IndexedDBTransaction(
254 transaction_id,
255 callbacks_,
256 std::set<int64>() /*scope*/,
257 blink::WebIDBTransactionModeVersionChange,
258 db_.get(),
259 new IndexedDBFakeBackingStore::FakeTransaction(commit_success_));
260 db_->TransactionCreated(transaction_.get());
262 // Add a dummy task which takes the place of the VersionChangeOperation
263 // which kicks off the upgrade. This ensures that the transaction has
264 // processed at least one task before the CreateObjectStore call.
265 transaction_->ScheduleTask(base::Bind(&DummyOperation));
268 void RunPostedTasks() { base::RunLoop().RunUntilIdle(); }
270 protected:
271 scoped_refptr<IndexedDBFakeBackingStore> backing_store_;
272 scoped_refptr<IndexedDBDatabase> db_;
273 scoped_refptr<MockIndexedDBCallbacks> request_;
274 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks_;
275 scoped_refptr<IndexedDBTransaction> transaction_;
277 leveldb::Status commit_success_;
279 private:
280 base::MessageLoop message_loop_;
281 scoped_refptr<MockIndexedDBFactory> factory_;
283 DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseOperationTest);
286 TEST_F(IndexedDBDatabaseOperationTest, CreateObjectStore) {
287 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
288 const int64 store_id = 1001;
289 db_->CreateObjectStore(transaction_->id(),
290 store_id,
291 ASCIIToUTF16("store"),
292 IndexedDBKeyPath(),
293 false /*auto_increment*/);
294 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
295 RunPostedTasks();
296 transaction_->Commit();
297 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
300 TEST_F(IndexedDBDatabaseOperationTest, CreateIndex) {
301 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
302 const int64 store_id = 1001;
303 db_->CreateObjectStore(transaction_->id(),
304 store_id,
305 ASCIIToUTF16("store"),
306 IndexedDBKeyPath(),
307 false /*auto_increment*/);
308 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
309 const int64 index_id = 2002;
310 db_->CreateIndex(transaction_->id(),
311 store_id,
312 index_id,
313 ASCIIToUTF16("index"),
314 IndexedDBKeyPath(),
315 false /*unique*/,
316 false /*multi_entry*/);
317 EXPECT_EQ(
318 1ULL,
319 db_->metadata().object_stores.find(store_id)->second.indexes.size());
320 RunPostedTasks();
321 transaction_->Commit();
322 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
323 EXPECT_EQ(
324 1ULL,
325 db_->metadata().object_stores.find(store_id)->second.indexes.size());
328 class IndexedDBDatabaseOperationAbortTest
329 : public IndexedDBDatabaseOperationTest {
330 public:
331 IndexedDBDatabaseOperationAbortTest() {
332 commit_success_ = leveldb::Status::NotFound("Bummer.");
335 private:
336 DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseOperationAbortTest);
339 TEST_F(IndexedDBDatabaseOperationAbortTest, CreateObjectStore) {
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 RunPostedTasks();
349 transaction_->Commit();
350 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
353 TEST_F(IndexedDBDatabaseOperationAbortTest, CreateIndex) {
354 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
355 const int64 store_id = 1001;
356 db_->CreateObjectStore(transaction_->id(),
357 store_id,
358 ASCIIToUTF16("store"),
359 IndexedDBKeyPath(),
360 false /*auto_increment*/);
361 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
362 const int64 index_id = 2002;
363 db_->CreateIndex(transaction_->id(),
364 store_id,
365 index_id,
366 ASCIIToUTF16("index"),
367 IndexedDBKeyPath(),
368 false /*unique*/,
369 false /*multi_entry*/);
370 EXPECT_EQ(
371 1ULL,
372 db_->metadata().object_stores.find(store_id)->second.indexes.size());
373 RunPostedTasks();
374 transaction_->Commit();
375 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
378 TEST_F(IndexedDBDatabaseOperationTest, CreatePutDelete) {
379 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
380 const int64 store_id = 1001;
382 // Creation is synchronous.
383 db_->CreateObjectStore(transaction_->id(),
384 store_id,
385 ASCIIToUTF16("store"),
386 IndexedDBKeyPath(),
387 false /*auto_increment*/);
388 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
391 // Put is asynchronous
392 IndexedDBValue value("value1", std::vector<IndexedDBBlobInfo>());
393 ScopedVector<storage::BlobDataHandle> handles;
394 scoped_ptr<IndexedDBKey> key(new IndexedDBKey("key"));
395 std::vector<IndexedDBDatabase::IndexKeys> index_keys;
396 scoped_refptr<MockIndexedDBCallbacks> request(
397 new MockIndexedDBCallbacks(false));
398 db_->Put(transaction_->id(),
399 store_id,
400 &value,
401 &handles,
402 key.Pass(),
403 blink::WebIDBPutModeAddOnly,
404 request,
405 index_keys);
407 // Deletion is asynchronous.
408 db_->DeleteObjectStore(transaction_->id(),
409 store_id);
410 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
412 // This will execute the Put then Delete.
413 RunPostedTasks();
414 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
416 transaction_->Commit(); // Cleans up the object hierarchy.
419 } // namespace content