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 <string>
      6 
      7 #include "app/sql/connection.h"
      8 #include "app/sql/statement.h"
      9 #include "base/file_util.h"
     10 #include "base/memory/scoped_temp_dir.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 #include "third_party/sqlite/sqlite3.h"
     13 
     14 class StatementErrorHandler : public sql::ErrorDelegate {
     15  public:
     16   StatementErrorHandler() : error_(SQLITE_OK) {}
     17 
     18   virtual int OnError(int error, sql::Connection* connection,
     19                       sql::Statement* stmt) {
     20     error_ = error;
     21     const char* sql_txt = stmt ? stmt->GetSQLStatement() : NULL;
     22     sql_text_ = sql_txt ? sql_txt : "no statement available";
     23     return error;
     24   }
     25 
     26   int error() const { return error_; }
     27 
     28   void reset_error() {
     29     sql_text_.clear();
     30     error_ = SQLITE_OK;
     31   }
     32 
     33   const char* sql_statement() const { return sql_text_.c_str(); }
     34 
     35  private:
     36   int error_;
     37   std::string sql_text_;
     38 };
     39 
     40 class SQLStatementTest : public testing::Test {
     41  public:
     42   SQLStatementTest() : error_handler_(new StatementErrorHandler) {}
     43 
     44   void SetUp() {
     45     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     46     ASSERT_TRUE(db_.Open(temp_dir_.path().AppendASCII("SQLStatementTest.db")));
     47 
     48     // The |error_handler_| will be called if any sqlite statement operation
     49     // returns an error code.
     50     db_.set_error_delegate(error_handler_);
     51   }
     52 
     53   void TearDown() {
     54     // If any error happened the original sql statement can be found in
     55     // error_handler_->sql_statement().
     56     EXPECT_EQ(SQLITE_OK, error_handler_->error());
     57     db_.Close();
     58   }
     59 
     60   sql::Connection& db() { return db_; }
     61 
     62   int sqlite_error() const { return error_handler_->error(); }
     63   void reset_error() const { error_handler_->reset_error(); }
     64 
     65  private:
     66   ScopedTempDir temp_dir_;
     67   sql::Connection db_;
     68   scoped_refptr<StatementErrorHandler> error_handler_;
     69 };
     70 
     71 TEST_F(SQLStatementTest, Assign) {
     72   sql::Statement s;
     73   EXPECT_FALSE(s);  // bool conversion operator.
     74   EXPECT_TRUE(!s);  // ! operator.
     75   EXPECT_FALSE(s.is_valid());
     76 
     77   s.Assign(db().GetUniqueStatement("CREATE TABLE foo (a, b)"));
     78   EXPECT_TRUE(s);
     79   EXPECT_FALSE(!s);
     80   EXPECT_TRUE(s.is_valid());
     81 }
     82 
     83 TEST_F(SQLStatementTest, Run) {
     84   ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
     85   ASSERT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (3, 12)"));
     86 
     87   sql::Statement s(db().GetUniqueStatement("SELECT b FROM foo WHERE a=?"));
     88   EXPECT_FALSE(s.Succeeded());
     89 
     90   // Stepping it won't work since we haven't bound the value.
     91   EXPECT_FALSE(s.Step());
     92 
     93   // Run should fail since this produces output, and we should use Step(). This
     94   // gets a bit wonky since sqlite says this is OK so succeeded is set.
     95   s.Reset();
     96   s.BindInt(0, 3);
     97   EXPECT_FALSE(s.Run());
     98   EXPECT_EQ(SQLITE_ROW, db().GetErrorCode());
     99   EXPECT_TRUE(s.Succeeded());
    100 
    101   // Resetting it should put it back to the previous state (not runnable).
    102   s.Reset();
    103   EXPECT_FALSE(s.Succeeded());
    104 
    105   // Binding and stepping should produce one row.
    106   s.BindInt(0, 3);
    107   EXPECT_TRUE(s.Step());
    108   EXPECT_TRUE(s.Succeeded());
    109   EXPECT_EQ(12, s.ColumnInt(0));
    110   EXPECT_FALSE(s.Step());
    111   EXPECT_TRUE(s.Succeeded());
    112 }
    113 
    114 TEST_F(SQLStatementTest, BasicErrorCallback) {
    115   ASSERT_TRUE(db().Execute("CREATE TABLE foo (a INTEGER PRIMARY KEY, b)"));
    116   EXPECT_EQ(SQLITE_OK, sqlite_error());
    117   // Insert in the foo table the primary key. It is an error to insert
    118   // something other than an number. This error causes the error callback
    119   // handler to be called with SQLITE_MISMATCH as error code.
    120   sql::Statement s(db().GetUniqueStatement("INSERT INTO foo (a) VALUES (?)"));
    121   EXPECT_TRUE(s.is_valid());
    122   s.BindCString(0, "bad bad");
    123   EXPECT_FALSE(s.Run());
    124   EXPECT_EQ(SQLITE_MISMATCH, sqlite_error());
    125   reset_error();
    126 }
    127