blob: c5217aa6c9935ee742522d1b9421983a29cca5b9 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// Copyright (c) 2012 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
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01007#include "base/bind.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008#include "base/file_util.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009#include "base/files/scoped_temp_dir.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010#include "sql/connection.h"
11#include "sql/statement.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010012#include "sql/test/error_callback_support.h"
13#include "sql/test/scoped_error_ignorer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000014#include "testing/gtest/include/gtest/gtest.h"
15#include "third_party/sqlite/sqlite3.h"
16
17namespace {
18
Torne (Richard Coles)58218062012-11-14 11:43:16 +000019class SQLStatementTest : public testing::Test {
20 public:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000021 virtual void SetUp() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000022 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
23 ASSERT_TRUE(db_.Open(temp_dir_.path().AppendASCII("SQLStatementTest.db")));
Torne (Richard Coles)58218062012-11-14 11:43:16 +000024 }
25
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000026 virtual void TearDown() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000027 db_.Close();
28 }
29
30 sql::Connection& db() { return db_; }
31
Torne (Richard Coles)58218062012-11-14 11:43:16 +000032 private:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000033 base::ScopedTempDir temp_dir_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +000034 sql::Connection db_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +000035};
36
37} // namespace
38
39TEST_F(SQLStatementTest, Assign) {
40 sql::Statement s;
41 EXPECT_FALSE(s.is_valid());
42
43 s.Assign(db().GetUniqueStatement("CREATE TABLE foo (a, b)"));
44 EXPECT_TRUE(s.is_valid());
45}
46
47TEST_F(SQLStatementTest, Run) {
48 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
49 ASSERT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (3, 12)"));
50
51 sql::Statement s(db().GetUniqueStatement("SELECT b FROM foo WHERE a=?"));
52 EXPECT_FALSE(s.Succeeded());
53
54 // Stepping it won't work since we haven't bound the value.
55 EXPECT_FALSE(s.Step());
56
57 // Run should fail since this produces output, and we should use Step(). This
58 // gets a bit wonky since sqlite says this is OK so succeeded is set.
59 s.Reset(true);
60 s.BindInt(0, 3);
61 EXPECT_FALSE(s.Run());
62 EXPECT_EQ(SQLITE_ROW, db().GetErrorCode());
63 EXPECT_TRUE(s.Succeeded());
64
65 // Resetting it should put it back to the previous state (not runnable).
66 s.Reset(true);
67 EXPECT_FALSE(s.Succeeded());
68
69 // Binding and stepping should produce one row.
70 s.BindInt(0, 3);
71 EXPECT_TRUE(s.Step());
72 EXPECT_TRUE(s.Succeeded());
73 EXPECT_EQ(12, s.ColumnInt(0));
74 EXPECT_FALSE(s.Step());
75 EXPECT_TRUE(s.Succeeded());
76}
77
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010078// Error callback called for error running a statement.
79TEST_F(SQLStatementTest, ErrorCallback) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000080 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a INTEGER PRIMARY KEY, b)"));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010081
82 int error = SQLITE_OK;
83 sql::ScopedErrorCallback sec(
84 &db(), base::Bind(&sql::CaptureErrorCallback, &error));
85
Torne (Richard Coles)58218062012-11-14 11:43:16 +000086 // Insert in the foo table the primary key. It is an error to insert
87 // something other than an number. This error causes the error callback
88 // handler to be called with SQLITE_MISMATCH as error code.
89 sql::Statement s(db().GetUniqueStatement("INSERT INTO foo (a) VALUES (?)"));
90 EXPECT_TRUE(s.is_valid());
91 s.BindCString(0, "bad bad");
92 EXPECT_FALSE(s.Run());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010093 EXPECT_EQ(SQLITE_MISMATCH, error);
94}
95
96// Error ignorer works for error running a statement.
97TEST_F(SQLStatementTest, ScopedIgnoreError) {
98 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a INTEGER PRIMARY KEY, b)"));
99
100 sql::Statement s(db().GetUniqueStatement("INSERT INTO foo (a) VALUES (?)"));
101 EXPECT_TRUE(s.is_valid());
102
103 sql::ScopedErrorIgnorer ignore_errors;
104 ignore_errors.IgnoreError(SQLITE_MISMATCH);
105 s.BindCString(0, "bad bad");
106 ASSERT_FALSE(s.Run());
107 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000108}
109
110TEST_F(SQLStatementTest, Reset) {
111 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
112 ASSERT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (3, 12)"));
113 ASSERT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (4, 13)"));
114
115 sql::Statement s(db().GetUniqueStatement(
116 "SELECT b FROM foo WHERE a = ? "));
117 s.BindInt(0, 3);
118 ASSERT_TRUE(s.Step());
119 EXPECT_EQ(12, s.ColumnInt(0));
120 ASSERT_FALSE(s.Step());
121
122 s.Reset(false);
123 // Verify that we can get all rows again.
124 ASSERT_TRUE(s.Step());
125 EXPECT_EQ(12, s.ColumnInt(0));
126 EXPECT_FALSE(s.Step());
127
128 s.Reset(true);
129 ASSERT_FALSE(s.Step());
130}