OLD | NEW |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |