Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_database_unittest.cc
blobeb5df982118a0ef584decf21a80f3a20c4ea80fa
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_class_factory.h"
18 #include "content/browser/indexed_db/indexed_db_connection.h"
19 #include "content/browser/indexed_db/indexed_db_cursor.h"
20 #include "content/browser/indexed_db/indexed_db_fake_backing_store.h"
21 #include "content/browser/indexed_db/indexed_db_transaction.h"
22 #include "content/browser/indexed_db/indexed_db_value.h"
23 #include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
24 #include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
25 #include "content/browser/indexed_db/mock_indexed_db_factory.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 using base::ASCIIToUTF16;
30 namespace {
31 const int kFakeChildProcessId = 0;
34 namespace content {
36 TEST(IndexedDBDatabaseTest, BackingStoreRetention) {
37 scoped_refptr<IndexedDBFakeBackingStore> backing_store =
38 new IndexedDBFakeBackingStore();
39 EXPECT_TRUE(backing_store->HasOneRef());
41 scoped_refptr<MockIndexedDBFactory> factory = new MockIndexedDBFactory();
42 leveldb::Status s;
43 scoped_refptr<IndexedDBDatabase> db =
44 IndexedDBDatabase::Create(ASCIIToUTF16("db"),
45 backing_store.get(),
46 factory.get(),
47 IndexedDBDatabase::Identifier(),
48 &s);
49 ASSERT_TRUE(s.ok());
50 EXPECT_FALSE(backing_store->HasOneRef()); // local and db
51 db = NULL;
52 EXPECT_TRUE(backing_store->HasOneRef()); // local
55 TEST(IndexedDBDatabaseTest, ConnectionLifecycle) {
56 scoped_refptr<IndexedDBFakeBackingStore> backing_store =
57 new IndexedDBFakeBackingStore();
58 EXPECT_TRUE(backing_store->HasOneRef()); // local
60 scoped_refptr<MockIndexedDBFactory> factory = new MockIndexedDBFactory();
61 leveldb::Status s;
62 scoped_refptr<IndexedDBDatabase> db =
63 IndexedDBDatabase::Create(ASCIIToUTF16("db"),
64 backing_store.get(),
65 factory.get(),
66 IndexedDBDatabase::Identifier(),
67 &s);
68 ASSERT_TRUE(s.ok());
69 EXPECT_FALSE(backing_store->HasOneRef()); // local and db
71 scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks());
72 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1(
73 new MockIndexedDBDatabaseCallbacks());
74 const int64 transaction_id1 = 1;
75 IndexedDBPendingConnection connection1(
76 request1,
77 callbacks1,
78 kFakeChildProcessId,
79 transaction_id1,
80 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
81 db->OpenConnection(connection1);
83 EXPECT_FALSE(backing_store->HasOneRef()); // db, connection count > 0
85 scoped_refptr<MockIndexedDBCallbacks> request2(new MockIndexedDBCallbacks());
86 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks2(
87 new MockIndexedDBDatabaseCallbacks());
88 const int64 transaction_id2 = 2;
89 IndexedDBPendingConnection connection2(
90 request2,
91 callbacks2,
92 kFakeChildProcessId,
93 transaction_id2,
94 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
95 db->OpenConnection(connection2);
97 EXPECT_FALSE(backing_store->HasOneRef()); // local and connection
99 request1->connection()->ForceClose();
100 EXPECT_FALSE(request1->connection()->IsConnected());
102 EXPECT_FALSE(backing_store->HasOneRef()); // local and connection
104 request2->connection()->ForceClose();
105 EXPECT_FALSE(request2->connection()->IsConnected());
107 EXPECT_TRUE(backing_store->HasOneRef());
108 EXPECT_FALSE(db->backing_store());
110 db = NULL;
113 TEST(IndexedDBDatabaseTest, ForcedClose) {
114 scoped_refptr<IndexedDBFakeBackingStore> backing_store =
115 new IndexedDBFakeBackingStore();
116 EXPECT_TRUE(backing_store->HasOneRef());
118 scoped_refptr<MockIndexedDBFactory> factory = new MockIndexedDBFactory();
119 leveldb::Status s;
120 scoped_refptr<IndexedDBDatabase> database =
121 IndexedDBDatabase::Create(ASCIIToUTF16("db"),
122 backing_store.get(),
123 factory.get(),
124 IndexedDBDatabase::Identifier(),
125 &s);
126 ASSERT_TRUE(s.ok());
127 EXPECT_FALSE(backing_store->HasOneRef()); // local and db
129 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks(
130 new MockIndexedDBDatabaseCallbacks());
131 scoped_refptr<MockIndexedDBCallbacks> request(new MockIndexedDBCallbacks());
132 const int64 upgrade_transaction_id = 3;
133 IndexedDBPendingConnection connection(
134 request,
135 callbacks,
136 kFakeChildProcessId,
137 upgrade_transaction_id,
138 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
139 database->OpenConnection(connection);
140 EXPECT_EQ(database.get(), request->connection()->database());
142 const int64 transaction_id = 123;
143 const std::vector<int64> scope;
144 database->CreateTransaction(transaction_id,
145 request->connection(),
146 scope,
147 blink::WebIDBTransactionModeReadOnly);
149 request->connection()->ForceClose();
151 EXPECT_TRUE(backing_store->HasOneRef()); // local
152 EXPECT_TRUE(callbacks->abort_called());
155 class MockDeleteCallbacks : public IndexedDBCallbacks {
156 public:
157 MockDeleteCallbacks()
158 : IndexedDBCallbacks(NULL, 0, 0),
159 blocked_called_(false),
160 success_called_(false) {}
162 void OnBlocked(int64 existing_version) override { blocked_called_ = true; }
163 void OnSuccess(int64 result) override { success_called_ = true; }
165 bool blocked_called() const { return blocked_called_; }
166 bool success_called() const { return success_called_; }
168 private:
169 ~MockDeleteCallbacks() override {}
171 bool blocked_called_;
172 bool success_called_;
174 DISALLOW_COPY_AND_ASSIGN(MockDeleteCallbacks);
177 TEST(IndexedDBDatabaseTest, PendingDelete) {
178 scoped_refptr<IndexedDBFakeBackingStore> backing_store =
179 new IndexedDBFakeBackingStore();
180 EXPECT_TRUE(backing_store->HasOneRef()); // local
182 scoped_refptr<MockIndexedDBFactory> factory = new MockIndexedDBFactory();
183 leveldb::Status s;
184 scoped_refptr<IndexedDBDatabase> db =
185 IndexedDBDatabase::Create(ASCIIToUTF16("db"),
186 backing_store.get(),
187 factory.get(),
188 IndexedDBDatabase::Identifier(),
189 &s);
190 ASSERT_TRUE(s.ok());
191 EXPECT_FALSE(backing_store->HasOneRef()); // local and db
193 scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks());
194 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1(
195 new MockIndexedDBDatabaseCallbacks());
196 const int64 transaction_id1 = 1;
197 IndexedDBPendingConnection connection(
198 request1,
199 callbacks1,
200 kFakeChildProcessId,
201 transaction_id1,
202 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
203 db->OpenConnection(connection);
205 EXPECT_FALSE(backing_store->HasOneRef()); // local and db
207 scoped_refptr<MockDeleteCallbacks> request2(new MockDeleteCallbacks());
208 db->DeleteDatabase(request2);
210 EXPECT_FALSE(request2->blocked_called());
211 db->VersionChangeIgnored();
212 EXPECT_TRUE(request2->blocked_called());
214 EXPECT_FALSE(backing_store->HasOneRef()); // local and db
216 db->Close(request1->connection(), true /* forced */);
218 EXPECT_FALSE(db->backing_store());
219 EXPECT_TRUE(backing_store->HasOneRef()); // local
220 EXPECT_TRUE(request2->success_called());
223 void DummyOperation(IndexedDBTransaction* transaction) {
226 class IndexedDBDatabaseOperationTest : public testing::Test {
227 public:
228 IndexedDBDatabaseOperationTest()
229 : commit_success_(leveldb::Status::OK()),
230 factory_(new MockIndexedDBFactory()) {}
232 void SetUp() override {
233 backing_store_ = new IndexedDBFakeBackingStore();
234 leveldb::Status s;
235 db_ = IndexedDBDatabase::Create(ASCIIToUTF16("db"),
236 backing_store_.get(),
237 factory_.get(),
238 IndexedDBDatabase::Identifier(),
239 &s);
240 ASSERT_TRUE(s.ok());
242 request_ = new MockIndexedDBCallbacks();
243 callbacks_ = new MockIndexedDBDatabaseCallbacks();
244 const int64 transaction_id = 1;
245 db_->OpenConnection(IndexedDBPendingConnection(
246 request_,
247 callbacks_,
248 kFakeChildProcessId,
249 transaction_id,
250 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION));
251 EXPECT_EQ(IndexedDBDatabaseMetadata::NO_INT_VERSION,
252 db_->metadata().int_version);
254 transaction_ = IndexedDBClassFactory::Get()->CreateIndexedDBTransaction(
255 transaction_id, callbacks_, std::set<int64>() /*scope*/,
256 blink::WebIDBTransactionModeVersionChange, db_.get(),
257 new IndexedDBFakeBackingStore::FakeTransaction(commit_success_));
258 db_->TransactionCreated(transaction_.get());
260 // Add a dummy task which takes the place of the VersionChangeOperation
261 // which kicks off the upgrade. This ensures that the transaction has
262 // processed at least one task before the CreateObjectStore call.
263 transaction_->ScheduleTask(base::Bind(&DummyOperation));
266 void RunPostedTasks() { base::RunLoop().RunUntilIdle(); }
268 protected:
269 scoped_refptr<IndexedDBFakeBackingStore> backing_store_;
270 scoped_refptr<IndexedDBDatabase> db_;
271 scoped_refptr<MockIndexedDBCallbacks> request_;
272 scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks_;
273 scoped_refptr<IndexedDBTransaction> transaction_;
275 leveldb::Status commit_success_;
277 private:
278 base::MessageLoop message_loop_;
279 scoped_refptr<MockIndexedDBFactory> factory_;
281 DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseOperationTest);
284 TEST_F(IndexedDBDatabaseOperationTest, CreateObjectStore) {
285 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
286 const int64 store_id = 1001;
287 db_->CreateObjectStore(transaction_->id(),
288 store_id,
289 ASCIIToUTF16("store"),
290 IndexedDBKeyPath(),
291 false /*auto_increment*/);
292 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
293 RunPostedTasks();
294 transaction_->Commit();
295 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
298 TEST_F(IndexedDBDatabaseOperationTest, CreateIndex) {
299 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
300 const int64 store_id = 1001;
301 db_->CreateObjectStore(transaction_->id(),
302 store_id,
303 ASCIIToUTF16("store"),
304 IndexedDBKeyPath(),
305 false /*auto_increment*/);
306 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
307 const int64 index_id = 2002;
308 db_->CreateIndex(transaction_->id(),
309 store_id,
310 index_id,
311 ASCIIToUTF16("index"),
312 IndexedDBKeyPath(),
313 false /*unique*/,
314 false /*multi_entry*/);
315 EXPECT_EQ(
316 1ULL,
317 db_->metadata().object_stores.find(store_id)->second.indexes.size());
318 RunPostedTasks();
319 transaction_->Commit();
320 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
321 EXPECT_EQ(
322 1ULL,
323 db_->metadata().object_stores.find(store_id)->second.indexes.size());
326 class IndexedDBDatabaseOperationAbortTest
327 : public IndexedDBDatabaseOperationTest {
328 public:
329 IndexedDBDatabaseOperationAbortTest() {
330 commit_success_ = leveldb::Status::NotFound("Bummer.");
333 private:
334 DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseOperationAbortTest);
337 TEST_F(IndexedDBDatabaseOperationAbortTest, CreateObjectStore) {
338 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
339 const int64 store_id = 1001;
340 db_->CreateObjectStore(transaction_->id(),
341 store_id,
342 ASCIIToUTF16("store"),
343 IndexedDBKeyPath(),
344 false /*auto_increment*/);
345 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
346 RunPostedTasks();
347 transaction_->Commit();
348 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
351 TEST_F(IndexedDBDatabaseOperationAbortTest, CreateIndex) {
352 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
353 const int64 store_id = 1001;
354 db_->CreateObjectStore(transaction_->id(),
355 store_id,
356 ASCIIToUTF16("store"),
357 IndexedDBKeyPath(),
358 false /*auto_increment*/);
359 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
360 const int64 index_id = 2002;
361 db_->CreateIndex(transaction_->id(),
362 store_id,
363 index_id,
364 ASCIIToUTF16("index"),
365 IndexedDBKeyPath(),
366 false /*unique*/,
367 false /*multi_entry*/);
368 EXPECT_EQ(
369 1ULL,
370 db_->metadata().object_stores.find(store_id)->second.indexes.size());
371 RunPostedTasks();
372 transaction_->Commit();
373 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
376 TEST_F(IndexedDBDatabaseOperationTest, CreatePutDelete) {
377 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
378 const int64 store_id = 1001;
380 // Creation is synchronous.
381 db_->CreateObjectStore(transaction_->id(),
382 store_id,
383 ASCIIToUTF16("store"),
384 IndexedDBKeyPath(),
385 false /*auto_increment*/);
386 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
389 // Put is asynchronous
390 IndexedDBValue value("value1", std::vector<IndexedDBBlobInfo>());
391 ScopedVector<storage::BlobDataHandle> handles;
392 scoped_ptr<IndexedDBKey> key(new IndexedDBKey("key"));
393 std::vector<IndexedDBDatabase::IndexKeys> index_keys;
394 scoped_refptr<MockIndexedDBCallbacks> request(
395 new MockIndexedDBCallbacks(false));
396 db_->Put(transaction_->id(),
397 store_id,
398 &value,
399 &handles,
400 key.Pass(),
401 blink::WebIDBPutModeAddOnly,
402 request,
403 index_keys);
405 // Deletion is asynchronous.
406 db_->DeleteObjectStore(transaction_->id(),
407 store_id);
408 EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
410 // This will execute the Put then Delete.
411 RunPostedTasks();
412 EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
414 transaction_->Commit(); // Cleans up the object hierarchy.
417 } // namespace content