transaction_unittest.cc 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // Copyright (c) 2011 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.
  4. #include "sql/transaction.h"
  5. #include "base/files/file_util.h"
  6. #include "base/files/scoped_temp_dir.h"
  7. #include "sql/database.h"
  8. #include "sql/statement.h"
  9. #include "testing/gtest/include/gtest/gtest.h"
  10. #include "third_party/sqlite/sqlite3.h"
  11. namespace sql {
  12. namespace {
  13. class SQLTransactionTest : public testing::Test {
  14. public:
  15. ~SQLTransactionTest() override = default;
  16. void SetUp() override {
  17. ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
  18. ASSERT_TRUE(
  19. db_.Open(temp_dir_.GetPath().AppendASCII("transaction_test.sqlite")));
  20. ASSERT_TRUE(db_.Execute("CREATE TABLE foo (a, b)"));
  21. }
  22. // Returns the number of rows in table "foo".
  23. int CountFoo() {
  24. Statement count(db_.GetUniqueStatement("SELECT count(*) FROM foo"));
  25. count.Step();
  26. return count.ColumnInt(0);
  27. }
  28. protected:
  29. base::ScopedTempDir temp_dir_;
  30. Database db_;
  31. };
  32. TEST_F(SQLTransactionTest, Commit) {
  33. {
  34. Transaction transaction(&db_);
  35. EXPECT_FALSE(db_.HasActiveTransactions());
  36. EXPECT_FALSE(transaction.IsActiveForTesting());
  37. ASSERT_TRUE(transaction.Begin());
  38. EXPECT_TRUE(db_.HasActiveTransactions());
  39. EXPECT_TRUE(transaction.IsActiveForTesting());
  40. ASSERT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (1, 2)"));
  41. ASSERT_EQ(1, CountFoo()) << "INSERT did not work as intended";
  42. transaction.Commit();
  43. EXPECT_FALSE(db_.HasActiveTransactions());
  44. EXPECT_FALSE(transaction.IsActiveForTesting());
  45. }
  46. EXPECT_FALSE(db_.HasActiveTransactions());
  47. EXPECT_EQ(1, CountFoo()) << "Transaction changes not committed";
  48. }
  49. TEST_F(SQLTransactionTest, RollbackOnDestruction) {
  50. EXPECT_FALSE(db_.HasActiveTransactions());
  51. {
  52. Transaction transaction(&db_);
  53. EXPECT_FALSE(db_.HasActiveTransactions());
  54. EXPECT_FALSE(transaction.IsActiveForTesting());
  55. ASSERT_TRUE(transaction.Begin());
  56. EXPECT_TRUE(db_.HasActiveTransactions());
  57. EXPECT_TRUE(transaction.IsActiveForTesting());
  58. ASSERT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (1, 2)"));
  59. ASSERT_EQ(1, CountFoo()) << "INSERT did not work as intended";
  60. }
  61. EXPECT_FALSE(db_.HasActiveTransactions());
  62. EXPECT_EQ(0, CountFoo()) << "Transaction changes not rolled back";
  63. }
  64. TEST_F(SQLTransactionTest, ExplicitRollback) {
  65. EXPECT_FALSE(db_.HasActiveTransactions());
  66. {
  67. Transaction transaction(&db_);
  68. EXPECT_FALSE(db_.HasActiveTransactions());
  69. EXPECT_FALSE(transaction.IsActiveForTesting());
  70. ASSERT_TRUE(transaction.Begin());
  71. EXPECT_TRUE(db_.HasActiveTransactions());
  72. EXPECT_TRUE(transaction.IsActiveForTesting());
  73. ASSERT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (1, 2)"));
  74. ASSERT_EQ(1, CountFoo()) << "INSERT did not work as intended";
  75. transaction.Rollback();
  76. EXPECT_FALSE(db_.HasActiveTransactions());
  77. EXPECT_FALSE(transaction.IsActiveForTesting());
  78. EXPECT_EQ(0, CountFoo()) << "Transaction changes not rolled back";
  79. }
  80. EXPECT_FALSE(db_.HasActiveTransactions());
  81. EXPECT_EQ(0, CountFoo()) << "Transaction changes not rolled back";
  82. }
  83. // Rolling back any part of a transaction should roll back all of them.
  84. TEST_F(SQLTransactionTest, NestedRollback) {
  85. EXPECT_FALSE(db_.HasActiveTransactions());
  86. EXPECT_EQ(0, db_.transaction_nesting());
  87. // Outermost transaction.
  88. {
  89. Transaction outer_txn(&db_);
  90. EXPECT_FALSE(db_.HasActiveTransactions());
  91. EXPECT_EQ(0, db_.transaction_nesting());
  92. ASSERT_TRUE(outer_txn.Begin());
  93. EXPECT_TRUE(db_.HasActiveTransactions());
  94. EXPECT_EQ(1, db_.transaction_nesting());
  95. // First inner transaction is committed.
  96. {
  97. Transaction committed_inner_txn(&db_);
  98. EXPECT_TRUE(db_.HasActiveTransactions());
  99. EXPECT_EQ(1, db_.transaction_nesting());
  100. ASSERT_TRUE(committed_inner_txn.Begin());
  101. EXPECT_TRUE(db_.HasActiveTransactions());
  102. EXPECT_EQ(2, db_.transaction_nesting());
  103. ASSERT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (1, 2)"));
  104. ASSERT_EQ(1, CountFoo()) << "INSERT did not work as intended";
  105. committed_inner_txn.Commit();
  106. EXPECT_TRUE(db_.HasActiveTransactions());
  107. EXPECT_EQ(1, db_.transaction_nesting());
  108. }
  109. EXPECT_TRUE(db_.HasActiveTransactions());
  110. EXPECT_EQ(1, db_.transaction_nesting());
  111. EXPECT_EQ(1, CountFoo()) << "First inner transaction did not commit";
  112. // Second inner transaction is rolled back.
  113. {
  114. Transaction rolled_back_inner_txn(&db_);
  115. EXPECT_TRUE(db_.HasActiveTransactions());
  116. EXPECT_EQ(1, db_.transaction_nesting());
  117. ASSERT_TRUE(rolled_back_inner_txn.Begin());
  118. EXPECT_TRUE(db_.HasActiveTransactions());
  119. EXPECT_EQ(2, db_.transaction_nesting());
  120. ASSERT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (2, 3)"));
  121. ASSERT_EQ(2, CountFoo()) << "INSERT did not work as intended";
  122. rolled_back_inner_txn.Rollback();
  123. EXPECT_TRUE(db_.HasActiveTransactions());
  124. EXPECT_EQ(1, db_.transaction_nesting());
  125. EXPECT_EQ(2, CountFoo())
  126. << "Nested transaction rollback deferred to top-level transaction";
  127. }
  128. EXPECT_TRUE(db_.HasActiveTransactions());
  129. EXPECT_EQ(1, db_.transaction_nesting());
  130. EXPECT_EQ(2, CountFoo())
  131. << "Nested transaction rollback deferred to top-level transaction";
  132. // Third inner transaction fails in Begin(), because a nested transaction
  133. // has already been rolled back.
  134. {
  135. Transaction failed_inner_txn(&db_);
  136. EXPECT_TRUE(db_.HasActiveTransactions());
  137. EXPECT_EQ(1, db_.transaction_nesting());
  138. EXPECT_FALSE(failed_inner_txn.Begin());
  139. EXPECT_TRUE(db_.HasActiveTransactions());
  140. EXPECT_EQ(1, db_.transaction_nesting());
  141. }
  142. }
  143. EXPECT_FALSE(db_.HasActiveTransactions());
  144. EXPECT_EQ(0, db_.transaction_nesting());
  145. EXPECT_EQ(0, CountFoo());
  146. }
  147. } // namespace
  148. } // namespace sql