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/bind.h" |
6 #include "base/file_util.h" | 6 #include "base/file_util.h" |
7 #include "base/files/scoped_temp_dir.h" | 7 #include "base/files/scoped_temp_dir.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "sql/connection.h" | 9 #include "sql/connection.h" |
10 #include "sql/meta_table.h" | 10 #include "sql/meta_table.h" |
11 #include "sql/statement.h" | 11 #include "sql/statement.h" |
| 12 #include "sql/test/error_callback_support.h" |
12 #include "sql/test/scoped_error_ignorer.h" | 13 #include "sql/test/scoped_error_ignorer.h" |
13 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
14 #include "third_party/sqlite/sqlite3.h" | 15 #include "third_party/sqlite/sqlite3.h" |
15 | 16 |
16 namespace { | 17 namespace { |
17 | 18 |
18 // Helper to return the count of items in sqlite_master. Return -1 in | 19 // Helper to return the count of items in sqlite_master. Return -1 in |
19 // case of error. | 20 // case of error. |
20 int SqliteMasterCount(sql::Connection* db) { | 21 int SqliteMasterCount(sql::Connection* db) { |
21 const char* kMasterCount = "SELECT COUNT(*) FROM sqlite_master"; | 22 const char* kMasterCount = "SELECT COUNT(*) FROM sqlite_master"; |
22 sql::Statement s(db->GetUniqueStatement(kMasterCount)); | 23 sql::Statement s(db->GetUniqueStatement(kMasterCount)); |
23 return s.Step() ? s.ColumnInt(0) : -1; | 24 return s.Step() ? s.ColumnInt(0) : -1; |
24 } | 25 } |
25 | 26 |
| 27 // Track the number of valid references which share the same pointer. |
| 28 // This is used to allow testing an implicitly use-after-free case by |
| 29 // explicitly having the ref count live longer than the object. |
| 30 class RefCounter { |
| 31 public: |
| 32 RefCounter(size_t* counter) |
| 33 : counter_(counter) { |
| 34 (*counter_)++; |
| 35 } |
| 36 RefCounter(const RefCounter& other) |
| 37 : counter_(other.counter_) { |
| 38 (*counter_)++; |
| 39 } |
| 40 ~RefCounter() { |
| 41 (*counter_)--; |
| 42 } |
| 43 |
| 44 private: |
| 45 size_t* counter_; |
| 46 |
| 47 DISALLOW_ASSIGN(RefCounter); |
| 48 }; |
| 49 |
| 50 // Empty callback for implementation of ErrorCallbackSetHelper(). |
| 51 void IgnoreErrorCallback(int error, sql::Statement* stmt) { |
| 52 } |
| 53 |
| 54 void ErrorCallbackSetHelper(sql::Connection* db, |
| 55 size_t* counter, |
| 56 const RefCounter& r, |
| 57 int error, sql::Statement* stmt) { |
| 58 // The ref count should not go to zero when changing the callback. |
| 59 EXPECT_GT(*counter, 0u); |
| 60 db->set_error_callback(base::Bind(&IgnoreErrorCallback)); |
| 61 EXPECT_GT(*counter, 0u); |
| 62 } |
| 63 |
| 64 void ErrorCallbackResetHelper(sql::Connection* db, |
| 65 size_t* counter, |
| 66 const RefCounter& r, |
| 67 int error, sql::Statement* stmt) { |
| 68 // The ref count should not go to zero when clearing the callback. |
| 69 EXPECT_GT(*counter, 0u); |
| 70 db->reset_error_callback(); |
| 71 EXPECT_GT(*counter, 0u); |
| 72 } |
| 73 |
26 class SQLConnectionTest : public testing::Test { | 74 class SQLConnectionTest : public testing::Test { |
27 public: | 75 public: |
28 SQLConnectionTest() {} | 76 SQLConnectionTest() {} |
29 | 77 |
30 virtual void SetUp() { | 78 virtual void SetUp() { |
31 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 79 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
32 ASSERT_TRUE(db_.Open(db_path())); | 80 ASSERT_TRUE(db_.Open(db_path())); |
33 } | 81 } |
34 | 82 |
35 virtual void TearDown() { | 83 virtual void TearDown() { |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)"; | 208 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)"; |
161 ASSERT_TRUE(db().Execute(kCreateSql)); | 209 ASSERT_TRUE(db().Execute(kCreateSql)); |
162 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)")); | 210 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)")); |
163 | 211 |
164 sql::ScopedErrorIgnorer ignore_errors; | 212 sql::ScopedErrorIgnorer ignore_errors; |
165 ignore_errors.IgnoreError(SQLITE_CONSTRAINT); | 213 ignore_errors.IgnoreError(SQLITE_CONSTRAINT); |
166 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); | 214 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); |
167 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); | 215 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); |
168 } | 216 } |
169 | 217 |
| 218 TEST_F(SQLConnectionTest, ErrorCallback) { |
| 219 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)"; |
| 220 ASSERT_TRUE(db().Execute(kCreateSql)); |
| 221 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)")); |
| 222 |
| 223 int error = SQLITE_OK; |
| 224 { |
| 225 sql::ScopedErrorCallback sec( |
| 226 &db(), base::Bind(&sql::CaptureErrorCallback, &error)); |
| 227 |
| 228 // Inserting something other than a number into the primary key |
| 229 // should result in the callback seeing SQLITE_MISMATCH. |
| 230 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); |
| 231 EXPECT_EQ(SQLITE_CONSTRAINT, error); |
| 232 } |
| 233 |
| 234 // Callback is no longer in force due to reset. |
| 235 { |
| 236 error = SQLITE_OK; |
| 237 sql::ScopedErrorIgnorer ignore_errors; |
| 238 ignore_errors.IgnoreError(SQLITE_CONSTRAINT); |
| 239 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); |
| 240 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); |
| 241 EXPECT_EQ(SQLITE_OK, error); |
| 242 } |
| 243 |
| 244 // base::Bind() can curry arguments to be passed by const reference |
| 245 // to the callback function. If the callback function causes |
| 246 // re/set_error_callback() to be called, the storage for those |
| 247 // arguments can be deleted. |
| 248 // |
| 249 // RefCounter() counts how many objects are live using an external |
| 250 // count. The same counter is passed to the callback, so that it |
| 251 // can check directly even if the RefCounter object is no longer |
| 252 // live. |
| 253 { |
| 254 size_t count = 0; |
| 255 sql::ScopedErrorCallback sec( |
| 256 &db(), base::Bind(&ErrorCallbackSetHelper, |
| 257 &db(), &count, RefCounter(&count))); |
| 258 |
| 259 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); |
| 260 } |
| 261 |
| 262 // Same test, but reset_error_callback() case. |
| 263 { |
| 264 size_t count = 0; |
| 265 sql::ScopedErrorCallback sec( |
| 266 &db(), base::Bind(&ErrorCallbackResetHelper, |
| 267 &db(), &count, RefCounter(&count))); |
| 268 |
| 269 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); |
| 270 } |
| 271 } |
| 272 |
170 // Test that sql::Connection::Raze() results in a database without the | 273 // Test that sql::Connection::Raze() results in a database without the |
171 // tables from the original database. | 274 // tables from the original database. |
172 TEST_F(SQLConnectionTest, Raze) { | 275 TEST_F(SQLConnectionTest, Raze) { |
173 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; | 276 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; |
174 ASSERT_TRUE(db().Execute(kCreateSql)); | 277 ASSERT_TRUE(db().Execute(kCreateSql)); |
175 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)")); | 278 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)")); |
176 | 279 |
177 int pragma_auto_vacuum = 0; | 280 int pragma_auto_vacuum = 0; |
178 { | 281 { |
179 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum")); | 282 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum")); |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
553 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal")); | 656 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal")); |
554 ASSERT_TRUE(file_util::PathExists(db_path())); | 657 ASSERT_TRUE(file_util::PathExists(db_path())); |
555 ASSERT_TRUE(file_util::PathExists(journal)); | 658 ASSERT_TRUE(file_util::PathExists(journal)); |
556 | 659 |
557 sql::Connection::Delete(db_path()); | 660 sql::Connection::Delete(db_path()); |
558 EXPECT_FALSE(file_util::PathExists(db_path())); | 661 EXPECT_FALSE(file_util::PathExists(db_path())); |
559 EXPECT_FALSE(file_util::PathExists(journal)); | 662 EXPECT_FALSE(file_util::PathExists(journal)); |
560 } | 663 } |
561 | 664 |
562 } // namespace | 665 } // namespace |
OLD | NEW |