Home | History | Annotate | Download | only in sql
      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 
      5 #include "base/file_util.h"
      6 #include "base/files/scoped_temp_dir.h"
      7 #include "sql/connection.h"
      8 #include "sql/statement.h"
      9 #include "sql/transaction.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 #include "third_party/sqlite/sqlite3.h"
     12 
     13 class SQLTransactionTest : public testing::Test {
     14  public:
     15   SQLTransactionTest() {}
     16 
     17   virtual void SetUp() {
     18     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     19     ASSERT_TRUE(db_.Open(
     20         temp_dir_.path().AppendASCII("SQLTransactionTest.db")));
     21 
     22     ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
     23   }
     24 
     25   virtual void TearDown() {
     26     db_.Close();
     27   }
     28 
     29   sql::Connection& db() { return db_; }
     30 
     31   // Returns the number of rows in table "foo".
     32   int CountFoo() {
     33     sql::Statement count(db().GetUniqueStatement("SELECT count(*) FROM foo"));
     34     count.Step();
     35     return count.ColumnInt(0);
     36   }
     37 
     38  private:
     39   base::ScopedTempDir temp_dir_;
     40   sql::Connection db_;
     41 };
     42 
     43 TEST_F(SQLTransactionTest, Commit) {
     44   {
     45     sql::Transaction t(&db());
     46     EXPECT_FALSE(t.is_open());
     47     EXPECT_TRUE(t.Begin());
     48     EXPECT_TRUE(t.is_open());
     49 
     50     EXPECT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (1, 2)"));
     51 
     52     t.Commit();
     53     EXPECT_FALSE(t.is_open());
     54   }
     55 
     56   EXPECT_EQ(1, CountFoo());
     57 }
     58 
     59 TEST_F(SQLTransactionTest, Rollback) {
     60   // Test some basic initialization, and that rollback runs when you exit the
     61   // scope.
     62   {
     63     sql::Transaction t(&db());
     64     EXPECT_FALSE(t.is_open());
     65     EXPECT_TRUE(t.Begin());
     66     EXPECT_TRUE(t.is_open());
     67 
     68     EXPECT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (1, 2)"));
     69   }
     70 
     71   // Nothing should have been committed since it was implicitly rolled back.
     72   EXPECT_EQ(0, CountFoo());
     73 
     74   // Test explicit rollback.
     75   sql::Transaction t2(&db());
     76   EXPECT_FALSE(t2.is_open());
     77   EXPECT_TRUE(t2.Begin());
     78 
     79   EXPECT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (1, 2)"));
     80   t2.Rollback();
     81   EXPECT_FALSE(t2.is_open());
     82 
     83   // Nothing should have been committed since it was explicitly rolled back.
     84   EXPECT_EQ(0, CountFoo());
     85 }
     86 
     87 // Rolling back any part of a transaction should roll back all of them.
     88 TEST_F(SQLTransactionTest, NestedRollback) {
     89   EXPECT_EQ(0, db().transaction_nesting());
     90 
     91   // Outermost transaction.
     92   {
     93     sql::Transaction outer(&db());
     94     EXPECT_TRUE(outer.Begin());
     95     EXPECT_EQ(1, db().transaction_nesting());
     96 
     97     // The first inner one gets committed.
     98     {
     99       sql::Transaction inner1(&db());
    100       EXPECT_TRUE(inner1.Begin());
    101       EXPECT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (1, 2)"));
    102       EXPECT_EQ(2, db().transaction_nesting());
    103 
    104       inner1.Commit();
    105       EXPECT_EQ(1, db().transaction_nesting());
    106     }
    107 
    108     // One row should have gotten inserted.
    109     EXPECT_EQ(1, CountFoo());
    110 
    111     // The second inner one gets rolled back.
    112     {
    113       sql::Transaction inner2(&db());
    114       EXPECT_TRUE(inner2.Begin());
    115       EXPECT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (1, 2)"));
    116       EXPECT_EQ(2, db().transaction_nesting());
    117 
    118       inner2.Rollback();
    119       EXPECT_EQ(1, db().transaction_nesting());
    120     }
    121 
    122     // A third inner one will fail in Begin since one has already been rolled
    123     // back.
    124     EXPECT_EQ(1, db().transaction_nesting());
    125     {
    126       sql::Transaction inner3(&db());
    127       EXPECT_FALSE(inner3.Begin());
    128       EXPECT_EQ(1, db().transaction_nesting());
    129     }
    130   }
    131   EXPECT_EQ(0, db().transaction_nesting());
    132   EXPECT_EQ(0, CountFoo());
    133 }
    134