Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: sql/connection_unittest.cc

Issue 17726002: [sql] Callback and scoped-ignore tests for sql::Statement. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add test for whether curried values stay live. Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/bind.h"
5 #include "base/file_util.h" 6 #include "base/file_util.h"
6 #include "base/files/scoped_temp_dir.h" 7 #include "base/files/scoped_temp_dir.h"
7 #include "base/logging.h" 8 #include "base/logging.h"
8 #include "sql/connection.h" 9 #include "sql/connection.h"
9 #include "sql/meta_table.h" 10 #include "sql/meta_table.h"
10 #include "sql/statement.h" 11 #include "sql/statement.h"
12 #include "sql/test/error_callback_support.h"
11 #include "sql/test/scoped_error_ignorer.h" 13 #include "sql/test/scoped_error_ignorer.h"
12 #include "testing/gtest/include/gtest/gtest.h" 14 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/sqlite/sqlite3.h" 15 #include "third_party/sqlite/sqlite3.h"
14 16
17 namespace {
18
19 // Track the number of valid references which share the same pointer.
20 // This is used to allow testing an implicitly use-after-free case by
21 // explicitly having the ref count live longer than the object.
22 class RefCounter {
23 public:
24 RefCounter(size_t* counter)
25 : counter_(counter) {
26 (*counter_)++;
27 }
28 RefCounter(const RefCounter& other)
29 : counter_(other.counter_) {
30 (*counter_)++;
31 }
32 ~RefCounter() {
33 (*counter_)--;
34 }
35
36 private:
37 size_t* counter_;
38
39 DISALLOW_ASSIGN(RefCounter);
40 };
41
42 // Empty callback for implementation of ErrorCallbackSetHelper().
43 void IgnoreErrorCallback(int error, sql::Statement* stmt) {
44 }
45
46 void ErrorCallbackSetHelper(sql::Connection* db,
47 size_t* counter,
48 const RefCounter& r,
49 int error, sql::Statement* stmt) {
50 // The ref count should not go to zero when changing the callback.
51 EXPECT_GT(*counter, 0u);
52 db->set_error_callback(base::Bind(&IgnoreErrorCallback));
53 EXPECT_GT(*counter, 0u);
54 }
55
56 void ErrorCallbackResetHelper(sql::Connection* db,
57 size_t* counter,
58 const RefCounter& r,
59 int error, sql::Statement* stmt) {
60 // The ref count should not go to zero when clearing the callback.
61 EXPECT_GT(*counter, 0u);
62 db->reset_error_callback();
63 EXPECT_GT(*counter, 0u);
64 }
65
15 class SQLConnectionTest : public testing::Test { 66 class SQLConnectionTest : public testing::Test {
16 public: 67 public:
17 SQLConnectionTest() {} 68 SQLConnectionTest() {}
18 69
19 virtual void SetUp() { 70 virtual void SetUp() {
20 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 71 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
21 ASSERT_TRUE(db_.Open(db_path())); 72 ASSERT_TRUE(db_.Open(db_path()));
22 } 73 }
23 74
24 virtual void TearDown() { 75 virtual void TearDown() {
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)"; 194 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
144 ASSERT_TRUE(db().Execute(kCreateSql)); 195 ASSERT_TRUE(db().Execute(kCreateSql));
145 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)")); 196 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
146 197
147 sql::ScopedErrorIgnorer ignore_errors; 198 sql::ScopedErrorIgnorer ignore_errors;
148 ignore_errors.IgnoreError(SQLITE_CONSTRAINT); 199 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
149 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); 200 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
150 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 201 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
151 } 202 }
152 203
204 TEST_F(SQLConnectionTest, ErrorCallback) {
205 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
206 ASSERT_TRUE(db().Execute(kCreateSql));
207 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
208
209 int error = SQLITE_OK;
210 {
211 sql::ScopedErrorCallback sec(
212 &db(), base::Bind(&sql::CaptureErrorCallback, &error));
213
214 // Inserting something other than a number into the primary key
215 // should result in the callback seeing SQLITE_MISMATCH.
216 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
217 EXPECT_EQ(SQLITE_CONSTRAINT, error);
218 }
219
220 // Callback is no longer in force due to reset.
221 {
222 error = SQLITE_OK;
223 sql::ScopedErrorIgnorer ignore_errors;
224 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
225 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
226 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
227 EXPECT_EQ(SQLITE_OK, error);
228 }
229
230 // base::Bind() can curry arguments to be passed by const reference
231 // to the callback function. If the callback function causes
232 // re/set_error_callback() to be called, the storage for those
233 // arguments can be deleted.
234 //
235 // RefCounter() counts how many objects are live using an external
236 // count. The same counter is passed to the callback, so that it
237 // can check directly even if the RefCounter object is no longer
238 // live.
239 {
240 size_t count = 0;
241 sql::ScopedErrorCallback sec(
242 &db(), base::Bind(&ErrorCallbackSetHelper,
243 &db(), &count, RefCounter(&count)));
244
245 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
246 }
247
248 // Same test, but reset_error_callback() case.
249 {
250 size_t count = 0;
251 sql::ScopedErrorCallback sec(
252 &db(), base::Bind(&ErrorCallbackResetHelper,
253 &db(), &count, RefCounter(&count)));
254
255 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
256 }
257 }
258
153 // Test that sql::Connection::Raze() results in a database without the 259 // Test that sql::Connection::Raze() results in a database without the
154 // tables from the original database. 260 // tables from the original database.
155 TEST_F(SQLConnectionTest, Raze) { 261 TEST_F(SQLConnectionTest, Raze) {
156 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 262 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
157 ASSERT_TRUE(db().Execute(kCreateSql)); 263 ASSERT_TRUE(db().Execute(kCreateSql));
158 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)")); 264 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)"));
159 265
160 int pragma_auto_vacuum = 0; 266 int pragma_auto_vacuum = 0;
161 { 267 {
162 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum")); 268 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum"));
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 // Should have both a main database file and a journal file because 525 // Should have both a main database file and a journal file because
420 // of journal_mode PERSIST. 526 // of journal_mode PERSIST.
421 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal")); 527 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
422 ASSERT_TRUE(file_util::PathExists(db_path())); 528 ASSERT_TRUE(file_util::PathExists(db_path()));
423 ASSERT_TRUE(file_util::PathExists(journal)); 529 ASSERT_TRUE(file_util::PathExists(journal));
424 530
425 sql::Connection::Delete(db_path()); 531 sql::Connection::Delete(db_path());
426 EXPECT_FALSE(file_util::PathExists(db_path())); 532 EXPECT_FALSE(file_util::PathExists(db_path()));
427 EXPECT_FALSE(file_util::PathExists(journal)); 533 EXPECT_FALSE(file_util::PathExists(journal));
428 } 534 }
535
536 } // namespace
OLDNEW
« sql/connection.cc ('K') | « sql/connection.cc ('k') | sql/sql.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698