1 // Copyright 2011 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "sql/transaction.h"
7 #include "base/files/file_util.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "sql/database.h"
10 #include "sql/statement.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "third_party/sqlite/sqlite3.h"
18 class SQLTransactionTest : public testing::Test {
20 ~SQLTransactionTest() override = default;
22 void SetUp() override {
23 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
25 db_.Open(temp_dir_.GetPath().AppendASCII("transaction_test.sqlite")));
27 ASSERT_TRUE(db_.Execute("CREATE TABLE foo (a, b)"));
30 // Returns the number of rows in table "foo".
32 Statement count(db_.GetUniqueStatement("SELECT count(*) FROM foo"));
34 return count.ColumnInt(0);
38 base::ScopedTempDir temp_dir_;
42 TEST_F(SQLTransactionTest, Commit) {
44 Transaction transaction(&db_);
45 EXPECT_FALSE(db_.HasActiveTransactions());
46 EXPECT_FALSE(transaction.IsActiveForTesting());
48 ASSERT_TRUE(transaction.Begin());
49 EXPECT_TRUE(db_.HasActiveTransactions());
50 EXPECT_TRUE(transaction.IsActiveForTesting());
52 ASSERT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (1, 2)"));
53 ASSERT_EQ(1, CountFoo()) << "INSERT did not work as intended";
56 EXPECT_FALSE(db_.HasActiveTransactions());
57 EXPECT_FALSE(transaction.IsActiveForTesting());
60 EXPECT_FALSE(db_.HasActiveTransactions());
61 EXPECT_EQ(1, CountFoo()) << "Transaction changes not committed";
64 TEST_F(SQLTransactionTest, RollbackOnDestruction) {
65 EXPECT_FALSE(db_.HasActiveTransactions());
68 Transaction transaction(&db_);
69 EXPECT_FALSE(db_.HasActiveTransactions());
70 EXPECT_FALSE(transaction.IsActiveForTesting());
72 ASSERT_TRUE(transaction.Begin());
73 EXPECT_TRUE(db_.HasActiveTransactions());
74 EXPECT_TRUE(transaction.IsActiveForTesting());
76 ASSERT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (1, 2)"));
77 ASSERT_EQ(1, CountFoo()) << "INSERT did not work as intended";
80 EXPECT_FALSE(db_.HasActiveTransactions());
81 EXPECT_EQ(0, CountFoo()) << "Transaction changes not rolled back";
84 TEST_F(SQLTransactionTest, ExplicitRollback) {
85 EXPECT_FALSE(db_.HasActiveTransactions());
88 Transaction transaction(&db_);
89 EXPECT_FALSE(db_.HasActiveTransactions());
90 EXPECT_FALSE(transaction.IsActiveForTesting());
92 ASSERT_TRUE(transaction.Begin());
93 EXPECT_TRUE(db_.HasActiveTransactions());
94 EXPECT_TRUE(transaction.IsActiveForTesting());
96 ASSERT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (1, 2)"));
97 ASSERT_EQ(1, CountFoo()) << "INSERT did not work as intended";
99 transaction.Rollback();
100 EXPECT_FALSE(db_.HasActiveTransactions());
101 EXPECT_FALSE(transaction.IsActiveForTesting());
102 EXPECT_EQ(0, CountFoo()) << "Transaction changes not rolled back";
105 EXPECT_FALSE(db_.HasActiveTransactions());
106 EXPECT_EQ(0, CountFoo()) << "Transaction changes not rolled back";
109 // Rolling back any part of a transaction should roll back all of them.
110 TEST_F(SQLTransactionTest, NestedRollback) {
111 EXPECT_FALSE(db_.HasActiveTransactions());
112 EXPECT_EQ(0, db_.transaction_nesting());
114 // Outermost transaction.
116 Transaction outer_txn(&db_);
117 EXPECT_FALSE(db_.HasActiveTransactions());
118 EXPECT_EQ(0, db_.transaction_nesting());
120 ASSERT_TRUE(outer_txn.Begin());
121 EXPECT_TRUE(db_.HasActiveTransactions());
122 EXPECT_EQ(1, db_.transaction_nesting());
124 // First inner transaction is committed.
126 Transaction committed_inner_txn(&db_);
127 EXPECT_TRUE(db_.HasActiveTransactions());
128 EXPECT_EQ(1, db_.transaction_nesting());
130 ASSERT_TRUE(committed_inner_txn.Begin());
131 EXPECT_TRUE(db_.HasActiveTransactions());
132 EXPECT_EQ(2, db_.transaction_nesting());
134 ASSERT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (1, 2)"));
135 ASSERT_EQ(1, CountFoo()) << "INSERT did not work as intended";
137 committed_inner_txn.Commit();
138 EXPECT_TRUE(db_.HasActiveTransactions());
139 EXPECT_EQ(1, db_.transaction_nesting());
142 EXPECT_TRUE(db_.HasActiveTransactions());
143 EXPECT_EQ(1, db_.transaction_nesting());
144 EXPECT_EQ(1, CountFoo()) << "First inner transaction did not commit";
146 // Second inner transaction is rolled back.
148 Transaction rolled_back_inner_txn(&db_);
149 EXPECT_TRUE(db_.HasActiveTransactions());
150 EXPECT_EQ(1, db_.transaction_nesting());
152 ASSERT_TRUE(rolled_back_inner_txn.Begin());
153 EXPECT_TRUE(db_.HasActiveTransactions());
154 EXPECT_EQ(2, db_.transaction_nesting());
156 ASSERT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (2, 3)"));
157 ASSERT_EQ(2, CountFoo()) << "INSERT did not work as intended";
159 rolled_back_inner_txn.Rollback();
160 EXPECT_TRUE(db_.HasActiveTransactions());
161 EXPECT_EQ(1, db_.transaction_nesting());
162 EXPECT_EQ(2, CountFoo())
163 << "Nested transaction rollback deferred to top-level transaction";
166 EXPECT_TRUE(db_.HasActiveTransactions());
167 EXPECT_EQ(1, db_.transaction_nesting());
168 EXPECT_EQ(2, CountFoo())
169 << "Nested transaction rollback deferred to top-level transaction";
171 // Third inner transaction fails in Begin(), because a nested transaction
172 // has already been rolled back.
174 Transaction failed_inner_txn(&db_);
175 EXPECT_TRUE(db_.HasActiveTransactions());
176 EXPECT_EQ(1, db_.transaction_nesting());
178 EXPECT_FALSE(failed_inner_txn.Begin());
179 EXPECT_TRUE(db_.HasActiveTransactions());
180 EXPECT_EQ(1, db_.transaction_nesting());
184 EXPECT_FALSE(db_.HasActiveTransactions());
185 EXPECT_EQ(0, db_.transaction_nesting());
186 EXPECT_EQ(0, CountFoo());