Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_database_unittest.cc
blob0f4134c96d8f702b44dd3eadadd6e1ae0c1bc113
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 virtual void OnBlocked(int64 existing_version) OVERRIDE {
162 blocked_called_ = true;
164 virtual void OnSuccess(int64 result) OVERRIDE { success_called_ = true; }
166 bool blocked_called() const { return blocked_called_; }
167 bool success_called() const { return success_called_; }
169 private:
170 virtual ~MockDeleteCallbacks() {}
172 bool blocked_called_;
173 bool success_called_;
175 DISALLOW_COPY_AND_ASSIGN(MockDeleteCallbacks);
178 TEST(IndexedDBDatabaseTest, PendingDelete) {
179 scoped_refptr<IndexedDBFakeBackingStore> backing_store =
180 new IndexedDBFakeBackingStore();
181 EXPECT_TRUE(backing_store->HasOneRef()); // local
183 scoped_refptr<MockIndexedDBFactory> factory = new MockIndexedDBFactory();
184 leveldb::Status s;
185 scoped_refptr<IndexedDBDatabase> db =
186 IndexedDBDatabase::Create(ASCIIToUTF16("db"),
187 backing_store.get(),
188 factory.get(),
189 IndexedDBDatabase::Identifier(),
190 &s);
191 ASSERT_TRUE(s.ok());
192 EXPECT_FALSE(backing_store->HasOneRef()); // local and db
194 scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks());
195 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1(
196 new MockIndexedDBDatabaseCallbacks());
197 const int64 transaction_id1 = 1;
198 IndexedDBPendingConnection connection(
199 request1,
200 callbacks1,
201 kFakeChildProcessId,
202 transaction_id1,
203 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
204 db->OpenConnection(connection);
206 EXPECT_FALSE(backing_store->HasOneRef()); // local and db
208 scoped_refptr<MockDeleteCallbacks> request2(new MockDeleteCallbacks());
209 db->DeleteDatabase(request2);
211 EXPECT_FALSE(request2->blocked_called());
212 db->VersionChangeIgnored();
213 EXPECT_TRUE(request2->blocked_called());
215 EXPECT_FALSE(backing_store->HasOneRef()); // local and db
217 db->Close(request1->connection(), true /* forced */);
219 EXPECT_FALSE(db->backing_store());
220 EXPECT_TRUE(backing_store->HasOneRef()); // local
221 EXPECT_TRUE(request2->success_called());
224 void DummyOperation(IndexedDBTransaction* transaction) {
227 class IndexedDBDatabaseOperationTest : public testing::Test {
228 public:
229 IndexedDBDatabaseOperationTest()
230 : commit_success_(leveldb::Status::OK()),
231 factory_(new MockIndexedDBFactory()) {}
233 virtual void SetUp() {
234 backing_store_ = new IndexedDBFakeBackingStore();
235 leveldb::Status s;
236 db_ = IndexedDBDatabase::Create(ASCIIToUTF16("db"),
237 backing_store_.get(),
238 factory_.get(),
239 IndexedDBDatabase::Identifier(),
240 &s);
241 ASSERT_TRUE(s.ok());
243 request_ = new MockIndexedDBCallbacks();
244 callbacks_ = new MockIndexedDBDatabaseCallbacks();
245 const int64 transaction_id = 1;
246 db_->OpenConnection(IndexedDBPendingConnection(
247 request_,
248 callbacks_,
249 kFakeChildProcessId,
250 transaction_id,
251 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION));
252 EXPECT_EQ(IndexedDBDatabaseMetadata::NO_INT_VERSION,
253 db_->metadata().int_version);
255 transaction_ = new IndexedDBTransaction(
256 transaction_id,
257 callbacks_,
258 std::set<int64>() /*scope*/,
259 blink::WebIDBTransactionModeVersionChange,
260 db_.get(),
261 new IndexedDBFakeBackingStore::FakeTransaction(commit_success_));
262 db_->TransactionCreated(transaction_.get());
264 // Add a dummy task which takes the place of the VersionChangeOperation
265 // which kicks off the upgrade. This ensures that the transaction has
266 // processed at least one task before the CreateObjectStore call.
267 transaction_->ScheduleTask(base::Bind(&DummyOperation));
270 void RunPostedTasks() { base::RunLoop().RunUntilIdle(); }
272 protected:
273 scoped_refptr<IndexedDBFakeBackingStore> backing_store_;
274 scoped_refptr<IndexedDBDatabase> db_;
275 scoped_refptr<MockIndexedDBCallbacks> request_;
276 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks_;
277 scoped_refptr<IndexedDBTransaction> transaction_;
279 leveldb::Status commit_success_;
281 private:
282 base::MessageLoop message_loop_;
283 scoped_refptr<MockIndexedDBFactory> factory_;
285 DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseOperationTest);
288 TEST_F(IndexedDBDatabaseOperationTest, CreateObjectStore) {
289 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
290 const int64 store_id = 1001;
291 db_->CreateObjectStore(transaction_->id(),
292 store_id,
293 ASCIIToUTF16("store"),
294 IndexedDBKeyPath(),
295 false /*auto_increment*/);
296 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
297 RunPostedTasks();
298 transaction_->Commit();
299 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
302 TEST_F(IndexedDBDatabaseOperationTest, CreateIndex) {
303 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
304 const int64 store_id = 1001;
305 db_->CreateObjectStore(transaction_->id(),
306 store_id,
307 ASCIIToUTF16("store"),
308 IndexedDBKeyPath(),
309 false /*auto_increment*/);
310 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
311 const int64 index_id = 2002;
312 db_->CreateIndex(transaction_->id(),
313 store_id,
314 index_id,
315 ASCIIToUTF16("index"),
316 IndexedDBKeyPath(),
317 false /*unique*/,
318 false /*multi_entry*/);
319 EXPECT_EQ(
320 1ULL,
321 db_->metadata().object_stores.find(store_id)->second.indexes.size());
322 RunPostedTasks();
323 transaction_->Commit();
324 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
325 EXPECT_EQ(
326 1ULL,
327 db_->metadata().object_stores.find(store_id)->second.indexes.size());
330 class IndexedDBDatabaseOperationAbortTest
331 : public IndexedDBDatabaseOperationTest {
332 public:
333 IndexedDBDatabaseOperationAbortTest() {
334 commit_success_ = leveldb::Status::NotFound("Bummer.");
337 private:
338 DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseOperationAbortTest);
341 TEST_F(IndexedDBDatabaseOperationAbortTest, CreateObjectStore) {
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 RunPostedTasks();
351 transaction_->Commit();
352 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
355 TEST_F(IndexedDBDatabaseOperationAbortTest, CreateIndex) {
356 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
357 const int64 store_id = 1001;
358 db_->CreateObjectStore(transaction_->id(),
359 store_id,
360 ASCIIToUTF16("store"),
361 IndexedDBKeyPath(),
362 false /*auto_increment*/);
363 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
364 const int64 index_id = 2002;
365 db_->CreateIndex(transaction_->id(),
366 store_id,
367 index_id,
368 ASCIIToUTF16("index"),
369 IndexedDBKeyPath(),
370 false /*unique*/,
371 false /*multi_entry*/);
372 EXPECT_EQ(
373 1ULL,
374 db_->metadata().object_stores.find(store_id)->second.indexes.size());
375 RunPostedTasks();
376 transaction_->Commit();
377 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
380 TEST_F(IndexedDBDatabaseOperationTest, CreatePutDelete) {
381 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
382 const int64 store_id = 1001;
384 // Creation is synchronous.
385 db_->CreateObjectStore(transaction_->id(),
386 store_id,
387 ASCIIToUTF16("store"),
388 IndexedDBKeyPath(),
389 false /*auto_increment*/);
390 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
393 // Put is asynchronous
394 IndexedDBValue value("value1", std::vector<IndexedDBBlobInfo>());
395 ScopedVector<storage::BlobDataHandle> handles;
396 scoped_ptr<IndexedDBKey> key(new IndexedDBKey("key"));
397 std::vector<IndexedDBDatabase::IndexKeys> index_keys;
398 scoped_refptr<MockIndexedDBCallbacks> request(
399 new MockIndexedDBCallbacks(false));
400 db_->Put(transaction_->id(),
401 store_id,
402 &value,
403 &handles,
404 key.Pass(),
405 blink::WebIDBPutModeAddOnly,
406 request,
407 index_keys);
409 // Deletion is asynchronous.
410 db_->DeleteObjectStore(transaction_->id(),
411 store_id);
412 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
414 // This will execute the Put then Delete.
415 RunPostedTasks();
416 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
418 transaction_->Commit(); // Cleans up the object hierarchy.
421 } // namespace content