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"
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"
19 class IndexedDBTransactionTest
: public testing::Test
{
21 IndexedDBTransactionTest() {
22 IndexedDBFactory
* factory
= NULL
;
23 backing_store_
= new IndexedDBFakeBackingStore();
24 db_
= IndexedDBDatabase::Create(base::ASCIIToUTF16("db"),
27 IndexedDBDatabase::Identifier());
30 void RunPostedTasks() { message_loop_
.RunUntilIdle(); }
31 void DummyOperation(IndexedDBTransaction
* transaction
) {}
34 scoped_refptr
<IndexedDBFakeBackingStore
> backing_store_
;
35 scoped_refptr
<IndexedDBDatabase
> db_
;
38 base::MessageLoop message_loop_
;
40 DISALLOW_COPY_AND_ASSIGN(IndexedDBTransactionTest
);
43 TEST_F(IndexedDBTransactionTest
, Timeout
) {
45 const std::set
<int64
> scope
;
46 const bool commit_success
= true;
47 scoped_refptr
<IndexedDBTransaction
> transaction
= new IndexedDBTransaction(
49 new MockIndexedDBDatabaseCallbacks(),
51 indexed_db::TRANSACTION_READ_WRITE
,
53 new IndexedDBFakeBackingStore::FakeTransaction(commit_success
));
54 db_
->TransactionCreated(transaction
);
56 // No conflicting transactions, so coordinator will start it immediately:
57 EXPECT_EQ(IndexedDBTransaction::STARTED
, transaction
->state());
58 EXPECT_FALSE(transaction
->IsTimeoutTimerRunning());
60 // Schedule a task - timer won't be started until it's processed.
61 transaction
->ScheduleTask(base::Bind(
62 &IndexedDBTransactionTest::DummyOperation
, base::Unretained(this)));
63 EXPECT_FALSE(transaction
->IsTimeoutTimerRunning());
66 EXPECT_TRUE(transaction
->IsTimeoutTimerRunning());
68 // Abort should cancel the timer.
70 EXPECT_EQ(IndexedDBTransaction::FINISHED
, transaction
->state());
71 EXPECT_FALSE(transaction
->IsTimeoutTimerRunning());
73 // This task will be ignored.
74 transaction
->ScheduleTask(base::Bind(
75 &IndexedDBTransactionTest::DummyOperation
, base::Unretained(this)));
76 EXPECT_EQ(IndexedDBTransaction::FINISHED
, transaction
->state());
77 EXPECT_FALSE(transaction
->IsTimeoutTimerRunning());
80 TEST_F(IndexedDBTransactionTest
, NoTimeoutReadOnly
) {
82 const std::set
<int64
> scope
;
83 const bool commit_success
= true;
84 scoped_refptr
<IndexedDBTransaction
> transaction
= new IndexedDBTransaction(
86 new MockIndexedDBDatabaseCallbacks(),
88 indexed_db::TRANSACTION_READ_ONLY
,
90 new IndexedDBFakeBackingStore::FakeTransaction(commit_success
));
91 db_
->TransactionCreated(transaction
);
93 // No conflicting transactions, so coordinator will start it immediately:
94 EXPECT_EQ(IndexedDBTransaction::STARTED
, transaction
->state());
95 EXPECT_FALSE(transaction
->IsTimeoutTimerRunning());
97 // Schedule a task - timer won't be started until it's processed.
98 transaction
->ScheduleTask(base::Bind(
99 &IndexedDBTransactionTest::DummyOperation
, base::Unretained(this)));
100 EXPECT_FALSE(transaction
->IsTimeoutTimerRunning());
102 // Transaction is read-only, so no need to time it out.
104 EXPECT_FALSE(transaction
->IsTimeoutTimerRunning());
106 // Clean up to avoid leaks.
107 transaction
->Abort();
108 EXPECT_EQ(IndexedDBTransaction::FINISHED
, transaction
->state());
109 EXPECT_FALSE(transaction
->IsTimeoutTimerRunning());
112 class AbortObserver
{
114 AbortObserver() : abort_task_called_(false) {}
116 void AbortTask(IndexedDBTransaction
* transaction
) {
117 abort_task_called_
= true;
120 bool abort_task_called() const { return abort_task_called_
; }
123 bool abort_task_called_
;
124 DISALLOW_COPY_AND_ASSIGN(AbortObserver
);
127 TEST_F(IndexedDBTransactionTest
, AbortTasks
) {
129 const std::set
<int64
> scope
;
130 const bool commit_failure
= false;
131 scoped_refptr
<IndexedDBTransaction
> transaction
= new IndexedDBTransaction(
133 new MockIndexedDBDatabaseCallbacks(),
135 indexed_db::TRANSACTION_READ_ONLY
,
137 new IndexedDBFakeBackingStore::FakeTransaction(commit_failure
));
138 db_
->TransactionCreated(transaction
);
140 AbortObserver observer
;
141 transaction
->ScheduleTask(
142 base::Bind(&IndexedDBTransactionTest::DummyOperation
,
143 base::Unretained(this)),
144 base::Bind(&AbortObserver::AbortTask
, base::Unretained(&observer
)));
146 // Pump the message loop so that the transaction completes all pending tasks,
147 // otherwise it will defer the commit.
148 base::MessageLoop::current()->RunUntilIdle();
150 EXPECT_FALSE(observer
.abort_task_called());
151 transaction
->Commit();
152 EXPECT_TRUE(observer
.abort_task_called());
157 } // namespace content