Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_transaction_unittest.cc
blobcf35852fa1837af047e35051a65c20c14bb6966b
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_transaction.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "content/browser/indexed_db/indexed_db_fake_backing_store.h"
12 #include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 namespace content {
17 class IndexedDBTransactionTest : public testing::Test {
18 public:
19 IndexedDBTransactionTest() {
20 backing_store_ = new IndexedDBFakeBackingStore();
21 CreateDB();
24 void CreateDB() {
25 // DB is created here instead of the constructor to workaround a
26 // "peculiarity of C++". More info at
27 // https://code.google.com/p/googletest/wiki/FAQ#My_compiler_complains_that_a_constructor_(or_destructor)_cannot
28 IndexedDBFactory* factory = NULL;
29 leveldb::Status s;
30 db_ = IndexedDBDatabase::Create(base::ASCIIToUTF16("db"),
31 backing_store_,
32 factory,
33 IndexedDBDatabase::Identifier(),
34 &s);
35 ASSERT_TRUE(s.ok());
38 void RunPostedTasks() { message_loop_.RunUntilIdle(); }
39 void DummyOperation(IndexedDBTransaction* transaction) {}
41 protected:
42 scoped_refptr<IndexedDBFakeBackingStore> backing_store_;
43 scoped_refptr<IndexedDBDatabase> db_;
45 private:
46 base::MessageLoop message_loop_;
48 DISALLOW_COPY_AND_ASSIGN(IndexedDBTransactionTest);
51 class IndexedDBTransactionTestMode : public IndexedDBTransactionTest,
52 public testing::WithParamInterface<indexed_db::TransactionMode> {
53 public:
54 IndexedDBTransactionTestMode() {}
55 private:
56 DISALLOW_COPY_AND_ASSIGN(IndexedDBTransactionTestMode);
59 TEST_F(IndexedDBTransactionTest, Timeout) {
60 const int64 id = 0;
61 const std::set<int64> scope;
62 const bool commit_success = true;
63 scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction(
64 id,
65 new MockIndexedDBDatabaseCallbacks(),
66 scope,
67 indexed_db::TRANSACTION_READ_WRITE,
68 db_,
69 new IndexedDBFakeBackingStore::FakeTransaction(commit_success));
70 db_->TransactionCreated(transaction);
72 // No conflicting transactions, so coordinator will start it immediately:
73 EXPECT_EQ(IndexedDBTransaction::STARTED, transaction->state());
74 EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
75 EXPECT_EQ(0, transaction->diagnostics().tasks_scheduled);
76 EXPECT_EQ(0, transaction->diagnostics().tasks_completed);
78 // Schedule a task - timer won't be started until it's processed.
79 transaction->ScheduleTask(base::Bind(
80 &IndexedDBTransactionTest::DummyOperation, base::Unretained(this)));
81 EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
82 EXPECT_EQ(1, transaction->diagnostics().tasks_scheduled);
83 EXPECT_EQ(0, transaction->diagnostics().tasks_completed);
85 RunPostedTasks();
86 EXPECT_TRUE(transaction->IsTimeoutTimerRunning());
88 transaction->Timeout();
89 EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state());
90 EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
91 EXPECT_EQ(1, transaction->diagnostics().tasks_scheduled);
92 EXPECT_EQ(1, transaction->diagnostics().tasks_completed);
94 // This task will be ignored.
95 transaction->ScheduleTask(base::Bind(
96 &IndexedDBTransactionTest::DummyOperation, base::Unretained(this)));
97 EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state());
98 EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
99 EXPECT_EQ(1, transaction->diagnostics().tasks_scheduled);
100 EXPECT_EQ(1, transaction->diagnostics().tasks_completed);
103 TEST_F(IndexedDBTransactionTest, NoTimeoutReadOnly) {
104 const int64 id = 0;
105 const std::set<int64> scope;
106 const bool commit_success = true;
107 scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction(
109 new MockIndexedDBDatabaseCallbacks(),
110 scope,
111 indexed_db::TRANSACTION_READ_ONLY,
112 db_,
113 new IndexedDBFakeBackingStore::FakeTransaction(commit_success));
114 db_->TransactionCreated(transaction);
116 // No conflicting transactions, so coordinator will start it immediately:
117 EXPECT_EQ(IndexedDBTransaction::STARTED, transaction->state());
118 EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
120 // Schedule a task - timer won't be started until it's processed.
121 transaction->ScheduleTask(base::Bind(
122 &IndexedDBTransactionTest::DummyOperation, base::Unretained(this)));
123 EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
125 // Transaction is read-only, so no need to time it out.
126 RunPostedTasks();
127 EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
129 // Clean up to avoid leaks.
130 transaction->Abort();
131 EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state());
132 EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
135 class AbortObserver {
136 public:
137 AbortObserver() : abort_task_called_(false) {}
139 void AbortTask(IndexedDBTransaction* transaction) {
140 abort_task_called_ = true;
143 bool abort_task_called() const { return abort_task_called_; }
145 private:
146 bool abort_task_called_;
147 DISALLOW_COPY_AND_ASSIGN(AbortObserver);
150 TEST_P(IndexedDBTransactionTestMode, ScheduleNormalTask) {
151 const int64 id = 0;
152 const std::set<int64> scope;
153 const bool commit_failure = false;
154 scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction(
156 new MockIndexedDBDatabaseCallbacks(),
157 scope,
158 GetParam(),
159 db_,
160 new IndexedDBFakeBackingStore::FakeTransaction(commit_failure));
162 EXPECT_FALSE(transaction->HasPendingTasks());
163 EXPECT_TRUE(transaction->IsTaskQueueEmpty());
164 EXPECT_TRUE(transaction->task_queue_.empty());
165 EXPECT_TRUE(transaction->preemptive_task_queue_.empty());
166 EXPECT_EQ(0, transaction->diagnostics().tasks_scheduled);
167 EXPECT_EQ(0, transaction->diagnostics().tasks_completed);
169 db_->TransactionCreated(transaction);
171 EXPECT_FALSE(transaction->HasPendingTasks());
172 EXPECT_TRUE(transaction->IsTaskQueueEmpty());
173 EXPECT_TRUE(transaction->task_queue_.empty());
174 EXPECT_TRUE(transaction->preemptive_task_queue_.empty());
176 transaction->ScheduleTask(
177 IndexedDBDatabase::NORMAL_TASK,
178 base::Bind(&IndexedDBTransactionTest::DummyOperation,
179 base::Unretained(this)));
181 EXPECT_EQ(1, transaction->diagnostics().tasks_scheduled);
182 EXPECT_EQ(0, transaction->diagnostics().tasks_completed);
184 EXPECT_TRUE(transaction->HasPendingTasks());
185 EXPECT_FALSE(transaction->IsTaskQueueEmpty());
186 EXPECT_FALSE(transaction->task_queue_.empty());
187 EXPECT_TRUE(transaction->preemptive_task_queue_.empty());
189 // Pump the message loop so that the transaction completes all pending tasks,
190 // otherwise it will defer the commit.
191 base::MessageLoop::current()->RunUntilIdle();
192 EXPECT_FALSE(transaction->HasPendingTasks());
193 EXPECT_TRUE(transaction->IsTaskQueueEmpty());
194 EXPECT_TRUE(transaction->task_queue_.empty());
195 EXPECT_TRUE(transaction->preemptive_task_queue_.empty());
196 EXPECT_EQ(IndexedDBTransaction::STARTED, transaction->state());
197 EXPECT_EQ(1, transaction->diagnostics().tasks_scheduled);
198 EXPECT_EQ(1, transaction->diagnostics().tasks_completed);
200 transaction->Commit();
202 EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state());
203 EXPECT_FALSE(transaction->HasPendingTasks());
204 EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
205 EXPECT_TRUE(transaction->IsTaskQueueEmpty());
206 EXPECT_TRUE(transaction->task_queue_.empty());
207 EXPECT_TRUE(transaction->preemptive_task_queue_.empty());
208 EXPECT_EQ(1, transaction->diagnostics().tasks_scheduled);
209 EXPECT_EQ(1, transaction->diagnostics().tasks_completed);
212 TEST_F(IndexedDBTransactionTest, SchedulePreemptiveTask) {
213 const int64 id = 0;
214 const std::set<int64> scope;
215 const bool commit_failure = false;
216 scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction(
218 new MockIndexedDBDatabaseCallbacks(),
219 scope,
220 indexed_db::TRANSACTION_VERSION_CHANGE,
221 db_,
222 new IndexedDBFakeBackingStore::FakeTransaction(commit_failure));
224 EXPECT_FALSE(transaction->HasPendingTasks());
225 EXPECT_TRUE(transaction->IsTaskQueueEmpty());
226 EXPECT_TRUE(transaction->task_queue_.empty());
227 EXPECT_TRUE(transaction->preemptive_task_queue_.empty());
228 EXPECT_EQ(0, transaction->diagnostics().tasks_scheduled);
229 EXPECT_EQ(0, transaction->diagnostics().tasks_completed);
231 db_->TransactionCreated(transaction);
233 EXPECT_FALSE(transaction->HasPendingTasks());
234 EXPECT_TRUE(transaction->IsTaskQueueEmpty());
235 EXPECT_TRUE(transaction->task_queue_.empty());
236 EXPECT_TRUE(transaction->preemptive_task_queue_.empty());
238 transaction->ScheduleTask(
239 IndexedDBDatabase::PREEMPTIVE_TASK,
240 base::Bind(&IndexedDBTransactionTest::DummyOperation,
241 base::Unretained(this)));
242 transaction->AddPreemptiveEvent();
244 EXPECT_TRUE(transaction->HasPendingTasks());
245 EXPECT_FALSE(transaction->IsTaskQueueEmpty());
246 EXPECT_TRUE(transaction->task_queue_.empty());
247 EXPECT_FALSE(transaction->preemptive_task_queue_.empty());
249 // Pump the message loop so that the transaction completes all pending tasks,
250 // otherwise it will defer the commit.
251 base::MessageLoop::current()->RunUntilIdle();
252 EXPECT_TRUE(transaction->HasPendingTasks());
253 EXPECT_TRUE(transaction->IsTaskQueueEmpty());
254 EXPECT_TRUE(transaction->task_queue_.empty());
255 EXPECT_TRUE(transaction->preemptive_task_queue_.empty());
256 EXPECT_EQ(IndexedDBTransaction::STARTED, transaction->state());
257 EXPECT_EQ(0, transaction->diagnostics().tasks_scheduled);
258 EXPECT_EQ(0, transaction->diagnostics().tasks_completed);
260 transaction->DidCompletePreemptiveEvent();
261 transaction->Commit();
263 EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state());
264 EXPECT_FALSE(transaction->HasPendingTasks());
265 EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
266 EXPECT_TRUE(transaction->IsTaskQueueEmpty());
267 EXPECT_TRUE(transaction->task_queue_.empty());
268 EXPECT_TRUE(transaction->preemptive_task_queue_.empty());
269 EXPECT_EQ(0, transaction->diagnostics().tasks_scheduled);
270 EXPECT_EQ(0, transaction->diagnostics().tasks_completed);
273 TEST_P(IndexedDBTransactionTestMode, AbortTasks) {
274 const int64 id = 0;
275 const std::set<int64> scope;
276 const bool commit_failure = false;
277 scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction(
279 new MockIndexedDBDatabaseCallbacks(),
280 scope,
281 GetParam(),
282 db_,
283 new IndexedDBFakeBackingStore::FakeTransaction(commit_failure));
284 db_->TransactionCreated(transaction);
286 AbortObserver observer;
287 transaction->ScheduleTask(
288 base::Bind(&IndexedDBTransactionTest::DummyOperation,
289 base::Unretained(this)),
290 base::Bind(&AbortObserver::AbortTask, base::Unretained(&observer)));
292 // Pump the message loop so that the transaction completes all pending tasks,
293 // otherwise it will defer the commit.
294 base::MessageLoop::current()->RunUntilIdle();
296 EXPECT_FALSE(observer.abort_task_called());
297 transaction->Commit();
298 EXPECT_TRUE(observer.abort_task_called());
299 EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state());
300 EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
303 TEST_P(IndexedDBTransactionTestMode, AbortPreemptive) {
304 const int64 id = 0;
305 const std::set<int64> scope;
306 const bool commit_success = true;
307 scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction(
309 new MockIndexedDBDatabaseCallbacks(),
310 scope,
311 GetParam(),
312 db_,
313 new IndexedDBFakeBackingStore::FakeTransaction(commit_success));
314 db_->TransactionCreated(transaction);
316 // No conflicting transactions, so coordinator will start it immediately:
317 EXPECT_EQ(IndexedDBTransaction::STARTED, transaction->state());
318 EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
320 transaction->ScheduleTask(
321 IndexedDBDatabase::PREEMPTIVE_TASK,
322 base::Bind(&IndexedDBTransactionTest::DummyOperation,
323 base::Unretained(this)));
324 EXPECT_EQ(0, transaction->pending_preemptive_events_);
325 transaction->AddPreemptiveEvent();
326 EXPECT_EQ(1, transaction->pending_preemptive_events_);
328 RunPostedTasks();
330 transaction->Abort();
331 EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state());
332 EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
333 EXPECT_EQ(0, transaction->pending_preemptive_events_);
334 EXPECT_TRUE(transaction->preemptive_task_queue_.empty());
335 EXPECT_TRUE(transaction->task_queue_.empty());
336 EXPECT_FALSE(transaction->HasPendingTasks());
337 EXPECT_EQ(transaction->diagnostics().tasks_completed,
338 transaction->diagnostics().tasks_scheduled);
339 EXPECT_FALSE(transaction->should_process_queue_);
340 EXPECT_TRUE(transaction->backing_store_transaction_begun_);
341 EXPECT_TRUE(transaction->used_);
342 EXPECT_FALSE(transaction->commit_pending_);
344 // This task will be ignored.
345 transaction->ScheduleTask(base::Bind(
346 &IndexedDBTransactionTest::DummyOperation, base::Unretained(this)));
347 EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state());
348 EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
349 EXPECT_FALSE(transaction->HasPendingTasks());
350 EXPECT_EQ(transaction->diagnostics().tasks_completed,
351 transaction->diagnostics().tasks_scheduled);
354 static const indexed_db::TransactionMode kTestModes[] = {
355 indexed_db::TRANSACTION_READ_ONLY,
356 indexed_db::TRANSACTION_READ_WRITE,
357 indexed_db::TRANSACTION_VERSION_CHANGE
360 INSTANTIATE_TEST_CASE_P(IndexedDBTransactions,
361 IndexedDBTransactionTestMode,
362 ::testing::ValuesIn(kTestModes));
364 } // namespace content