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 3 // found in the LICENSE file. 4 5 #include "base/bind.h" 6 #include "base/file_util.h" 7 #include "base/files/scoped_temp_dir.h" 8 #include "base/logging.h" 9 #include "sql/connection.h" 10 #include "sql/meta_table.h" 11 #include "sql/statement.h" 12 #include "sql/test/error_callback_support.h" 13 #include "sql/test/scoped_error_ignorer.h" 14 #include "sql/test/test_helpers.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 #include "third_party/sqlite/sqlite3.h" 17 18 namespace { 19 20 // Helper to return the count of items in sqlite_master. Return -1 in 21 // case of error. 22 int SqliteMasterCount(sql::Connection* db) { 23 const char* kMasterCount = "SELECT COUNT(*) FROM sqlite_master"; 24 sql::Statement s(db->GetUniqueStatement(kMasterCount)); 25 return s.Step() ? s.ColumnInt(0) : -1; 26 } 27 28 // Track the number of valid references which share the same pointer. 29 // This is used to allow testing an implicitly use-after-free case by 30 // explicitly having the ref count live longer than the object. 31 class RefCounter { 32 public: 33 RefCounter(size_t* counter) 34 : counter_(counter) { 35 (*counter_)++; 36 } 37 RefCounter(const RefCounter& other) 38 : counter_(other.counter_) { 39 (*counter_)++; 40 } 41 ~RefCounter() { 42 (*counter_)--; 43 } 44 45 private: 46 size_t* counter_; 47 48 DISALLOW_ASSIGN(RefCounter); 49 }; 50 51 // Empty callback for implementation of ErrorCallbackSetHelper(). 52 void IgnoreErrorCallback(int error, sql::Statement* stmt) { 53 } 54 55 void ErrorCallbackSetHelper(sql::Connection* db, 56 size_t* counter, 57 const RefCounter& r, 58 int error, sql::Statement* stmt) { 59 // The ref count should not go to zero when changing the callback. 60 EXPECT_GT(*counter, 0u); 61 db->set_error_callback(base::Bind(&IgnoreErrorCallback)); 62 EXPECT_GT(*counter, 0u); 63 } 64 65 void ErrorCallbackResetHelper(sql::Connection* db, 66 size_t* counter, 67 const RefCounter& r, 68 int error, sql::Statement* stmt) { 69 // The ref count should not go to zero when clearing the callback. 70 EXPECT_GT(*counter, 0u); 71 db->reset_error_callback(); 72 EXPECT_GT(*counter, 0u); 73 } 74 75 #if defined(OS_POSIX) 76 // Set a umask and restore the old mask on destruction. Cribbed from 77 // shared_memory_unittest.cc. Used by POSIX-only UserPermission test. 78 class ScopedUmaskSetter { 79 public: 80 explicit ScopedUmaskSetter(mode_t target_mask) { 81 old_umask_ = umask(target_mask); 82 } 83 ~ScopedUmaskSetter() { umask(old_umask_); } 84 private: 85 mode_t old_umask_; 86 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter); 87 }; 88 #endif 89 90 class SQLConnectionTest : public testing::Test { 91 public: 92 virtual void SetUp() { 93 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 94 db_path_ = temp_dir_.path().AppendASCII("SQLConnectionTest.db"); 95 ASSERT_TRUE(db_.Open(db_path_)); 96 } 97 98 virtual void TearDown() { 99 db_.Close(); 100 } 101 102 sql::Connection& db() { return db_; } 103 const base::FilePath& db_path() { return db_path_; } 104 105 // Handle errors by blowing away the database. 106 void RazeErrorCallback(int expected_error, int error, sql::Statement* stmt) { 107 EXPECT_EQ(expected_error, error); 108 db_.RazeAndClose(); 109 } 110 111 private: 112 sql::Connection db_; 113 base::FilePath db_path_; 114 base::ScopedTempDir temp_dir_; 115 }; 116 117 TEST_F(SQLConnectionTest, Execute) { 118 // Valid statement should return true. 119 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); 120 EXPECT_EQ(SQLITE_OK, db().GetErrorCode()); 121 122 // Invalid statement should fail. 123 ASSERT_EQ(SQLITE_ERROR, 124 db().ExecuteAndReturnErrorCode("CREATE TAB foo (a, b")); 125 EXPECT_EQ(SQLITE_ERROR, db().GetErrorCode()); 126 } 127 128 TEST_F(SQLConnectionTest, ExecuteWithErrorCode) { 129 ASSERT_EQ(SQLITE_OK, 130 db().ExecuteAndReturnErrorCode("CREATE TABLE foo (a, b)")); 131 ASSERT_EQ(SQLITE_ERROR, 132 db().ExecuteAndReturnErrorCode("CREATE TABLE TABLE")); 133 ASSERT_EQ(SQLITE_ERROR, 134 db().ExecuteAndReturnErrorCode( 135 "INSERT INTO foo(a, b) VALUES (1, 2, 3, 4)")); 136 } 137 138 TEST_F(SQLConnectionTest, CachedStatement) { 139 sql::StatementID id1("foo", 12); 140 141 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); 142 ASSERT_TRUE(db().Execute("INSERT INTO foo(a, b) VALUES (12, 13)")); 143 144 // Create a new cached statement. 145 { 146 sql::Statement s(db().GetCachedStatement(id1, "SELECT a FROM foo")); 147 ASSERT_TRUE(s.is_valid()); 148 149 ASSERT_TRUE(s.Step()); 150 EXPECT_EQ(12, s.ColumnInt(0)); 151 } 152 153 // The statement should be cached still. 154 EXPECT_TRUE(db().HasCachedStatement(id1)); 155 156 { 157 // Get the same statement using different SQL. This should ignore our 158 // SQL and use the cached one (so it will be valid). 159 sql::Statement s(db().GetCachedStatement(id1, "something invalid(")); 160 ASSERT_TRUE(s.is_valid()); 161 162 ASSERT_TRUE(s.Step()); 163 EXPECT_EQ(12, s.ColumnInt(0)); 164 } 165 166 // Make sure other statements aren't marked as cached. 167 EXPECT_FALSE(db().HasCachedStatement(SQL_FROM_HERE)); 168 } 169 170 TEST_F(SQLConnectionTest, IsSQLValidTest) { 171 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); 172 ASSERT_TRUE(db().IsSQLValid("SELECT a FROM foo")); 173 ASSERT_FALSE(db().IsSQLValid("SELECT no_exist FROM foo")); 174 } 175 176 TEST_F(SQLConnectionTest, DoesStuffExist) { 177 // Test DoesTableExist. 178 EXPECT_FALSE(db().DoesTableExist("foo")); 179 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); 180 EXPECT_TRUE(db().DoesTableExist("foo")); 181 182 // Should be case sensitive. 183 EXPECT_FALSE(db().DoesTableExist("FOO")); 184 185 // Test DoesColumnExist. 186 EXPECT_FALSE(db().DoesColumnExist("foo", "bar")); 187 EXPECT_TRUE(db().DoesColumnExist("foo", "a")); 188 189 // Testing for a column on a nonexistent table. 190 EXPECT_FALSE(db().DoesColumnExist("bar", "b")); 191 } 192 193 TEST_F(SQLConnectionTest, GetLastInsertRowId) { 194 ASSERT_TRUE(db().Execute("CREATE TABLE foo (id INTEGER PRIMARY KEY, value)")); 195 196 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)")); 197 198 // Last insert row ID should be valid. 199 int64 row = db().GetLastInsertRowId(); 200 EXPECT_LT(0, row); 201 202 // It should be the primary key of the row we just inserted. 203 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo WHERE id=?")); 204 s.BindInt64(0, row); 205 ASSERT_TRUE(s.Step()); 206 EXPECT_EQ(12, s.ColumnInt(0)); 207 } 208 209 TEST_F(SQLConnectionTest, Rollback) { 210 ASSERT_TRUE(db().BeginTransaction()); 211 ASSERT_TRUE(db().BeginTransaction()); 212 EXPECT_EQ(2, db().transaction_nesting()); 213 db().RollbackTransaction(); 214 EXPECT_FALSE(db().CommitTransaction()); 215 EXPECT_TRUE(db().BeginTransaction()); 216 } 217 218 // Test the scoped error ignorer by attempting to insert a duplicate 219 // value into an index. 220 TEST_F(SQLConnectionTest, ScopedIgnoreError) { 221 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)"; 222 ASSERT_TRUE(db().Execute(kCreateSql)); 223 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)")); 224 225 sql::ScopedErrorIgnorer ignore_errors; 226 ignore_errors.IgnoreError(SQLITE_CONSTRAINT); 227 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); 228 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 229 } 230 231 TEST_F(SQLConnectionTest, ErrorCallback) { 232 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)"; 233 ASSERT_TRUE(db().Execute(kCreateSql)); 234 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)")); 235 236 int error = SQLITE_OK; 237 { 238 sql::ScopedErrorCallback sec( 239 &db(), base::Bind(&sql::CaptureErrorCallback, &error)); 240 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); 241 EXPECT_EQ(SQLITE_CONSTRAINT, error); 242 } 243 244 // Callback is no longer in force due to reset. 245 { 246 error = SQLITE_OK; 247 sql::ScopedErrorIgnorer ignore_errors; 248 ignore_errors.IgnoreError(SQLITE_CONSTRAINT); 249 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); 250 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 251 EXPECT_EQ(SQLITE_OK, error); 252 } 253 254 // base::Bind() can curry arguments to be passed by const reference 255 // to the callback function. If the callback function calls 256 // re/set_error_callback(), the storage for those arguments can be 257 // deleted while the callback function is still executing. 258 // 259 // RefCounter() counts how many objects are live using an external 260 // count. The same counter is passed to the callback, so that it 261 // can check directly even if the RefCounter object is no longer 262 // live. 263 { 264 size_t count = 0; 265 sql::ScopedErrorCallback sec( 266 &db(), base::Bind(&ErrorCallbackSetHelper, 267 &db(), &count, RefCounter(&count))); 268 269 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); 270 } 271 272 // Same test, but reset_error_callback() case. 273 { 274 size_t count = 0; 275 sql::ScopedErrorCallback sec( 276 &db(), base::Bind(&ErrorCallbackResetHelper, 277 &db(), &count, RefCounter(&count))); 278 279 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); 280 } 281 } 282 283 // Test that sql::Connection::Raze() results in a database without the 284 // tables from the original database. 285 TEST_F(SQLConnectionTest, Raze) { 286 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 287 ASSERT_TRUE(db().Execute(kCreateSql)); 288 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)")); 289 290 int pragma_auto_vacuum = 0; 291 { 292 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum")); 293 ASSERT_TRUE(s.Step()); 294 pragma_auto_vacuum = s.ColumnInt(0); 295 ASSERT_TRUE(pragma_auto_vacuum == 0 || pragma_auto_vacuum == 1); 296 } 297 298 // If auto_vacuum is set, there's an extra page to maintain a freelist. 299 const int kExpectedPageCount = 2 + pragma_auto_vacuum; 300 301 { 302 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count")); 303 ASSERT_TRUE(s.Step()); 304 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(0)); 305 } 306 307 { 308 sql::Statement s(db().GetUniqueStatement("SELECT * FROM sqlite_master")); 309 ASSERT_TRUE(s.Step()); 310 EXPECT_EQ("table", s.ColumnString(0)); 311 EXPECT_EQ("foo", s.ColumnString(1)); 312 EXPECT_EQ("foo", s.ColumnString(2)); 313 // Table "foo" is stored in the last page of the file. 314 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(3)); 315 EXPECT_EQ(kCreateSql, s.ColumnString(4)); 316 } 317 318 ASSERT_TRUE(db().Raze()); 319 320 { 321 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count")); 322 ASSERT_TRUE(s.Step()); 323 EXPECT_EQ(1, s.ColumnInt(0)); 324 } 325 326 ASSERT_EQ(0, SqliteMasterCount(&db())); 327 328 { 329 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum")); 330 ASSERT_TRUE(s.Step()); 331 // The new database has the same auto_vacuum as a fresh database. 332 EXPECT_EQ(pragma_auto_vacuum, s.ColumnInt(0)); 333 } 334 } 335 336 // Test that Raze() maintains page_size. 337 TEST_F(SQLConnectionTest, RazePageSize) { 338 // Fetch the default page size and double it for use in this test. 339 // Scoped to release statement before Close(). 340 int default_page_size = 0; 341 { 342 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size")); 343 ASSERT_TRUE(s.Step()); 344 default_page_size = s.ColumnInt(0); 345 } 346 ASSERT_GT(default_page_size, 0); 347 const int kPageSize = 2 * default_page_size; 348 349 // Re-open the database to allow setting the page size. 350 db().Close(); 351 db().set_page_size(kPageSize); 352 ASSERT_TRUE(db().Open(db_path())); 353 354 // page_size should match the indicated value. 355 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size")); 356 ASSERT_TRUE(s.Step()); 357 ASSERT_EQ(kPageSize, s.ColumnInt(0)); 358 359 // After raze, page_size should still match the indicated value. 360 ASSERT_TRUE(db().Raze()); 361 s.Reset(true); 362 ASSERT_TRUE(s.Step()); 363 ASSERT_EQ(kPageSize, s.ColumnInt(0)); 364 } 365 366 // Test that Raze() results are seen in other connections. 367 TEST_F(SQLConnectionTest, RazeMultiple) { 368 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 369 ASSERT_TRUE(db().Execute(kCreateSql)); 370 371 sql::Connection other_db; 372 ASSERT_TRUE(other_db.Open(db_path())); 373 374 // Check that the second connection sees the table. 375 ASSERT_EQ(1, SqliteMasterCount(&other_db)); 376 377 ASSERT_TRUE(db().Raze()); 378 379 // The second connection sees the updated database. 380 ASSERT_EQ(0, SqliteMasterCount(&other_db)); 381 } 382 383 TEST_F(SQLConnectionTest, RazeLocked) { 384 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 385 ASSERT_TRUE(db().Execute(kCreateSql)); 386 387 // Open a transaction and write some data in a second connection. 388 // This will acquire a PENDING or EXCLUSIVE transaction, which will 389 // cause the raze to fail. 390 sql::Connection other_db; 391 ASSERT_TRUE(other_db.Open(db_path())); 392 ASSERT_TRUE(other_db.BeginTransaction()); 393 const char* kInsertSql = "INSERT INTO foo VALUES (1, 'data')"; 394 ASSERT_TRUE(other_db.Execute(kInsertSql)); 395 396 ASSERT_FALSE(db().Raze()); 397 398 // Works after COMMIT. 399 ASSERT_TRUE(other_db.CommitTransaction()); 400 ASSERT_TRUE(db().Raze()); 401 402 // Re-create the database. 403 ASSERT_TRUE(db().Execute(kCreateSql)); 404 ASSERT_TRUE(db().Execute(kInsertSql)); 405 406 // An unfinished read transaction in the other connection also 407 // blocks raze. 408 const char *kQuery = "SELECT COUNT(*) FROM foo"; 409 sql::Statement s(other_db.GetUniqueStatement(kQuery)); 410 ASSERT_TRUE(s.Step()); 411 ASSERT_FALSE(db().Raze()); 412 413 // Complete the statement unlocks the database. 414 ASSERT_FALSE(s.Step()); 415 ASSERT_TRUE(db().Raze()); 416 } 417 418 // Verify that Raze() can handle an empty file. SQLite should treat 419 // this as an empty database. 420 TEST_F(SQLConnectionTest, RazeEmptyDB) { 421 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 422 ASSERT_TRUE(db().Execute(kCreateSql)); 423 db().Close(); 424 425 { 426 file_util::ScopedFILE file(base::OpenFile(db_path(), "rb+")); 427 ASSERT_TRUE(file.get() != NULL); 428 ASSERT_EQ(0, fseek(file.get(), 0, SEEK_SET)); 429 ASSERT_TRUE(base::TruncateFile(file.get())); 430 } 431 432 ASSERT_TRUE(db().Open(db_path())); 433 ASSERT_TRUE(db().Raze()); 434 EXPECT_EQ(0, SqliteMasterCount(&db())); 435 } 436 437 // Verify that Raze() can handle a file of junk. 438 TEST_F(SQLConnectionTest, RazeNOTADB) { 439 db().Close(); 440 sql::Connection::Delete(db_path()); 441 ASSERT_FALSE(base::PathExists(db_path())); 442 443 { 444 file_util::ScopedFILE file(base::OpenFile(db_path(), "wb")); 445 ASSERT_TRUE(file.get() != NULL); 446 447 const char* kJunk = "This is the hour of our discontent."; 448 fputs(kJunk, file.get()); 449 } 450 ASSERT_TRUE(base::PathExists(db_path())); 451 452 // SQLite will successfully open the handle, but will fail with 453 // SQLITE_IOERR_SHORT_READ on pragma statemenets which read the 454 // header. 455 { 456 sql::ScopedErrorIgnorer ignore_errors; 457 ignore_errors.IgnoreError(SQLITE_IOERR_SHORT_READ); 458 EXPECT_TRUE(db().Open(db_path())); 459 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 460 } 461 EXPECT_TRUE(db().Raze()); 462 db().Close(); 463 464 // Now empty, the open should open an empty database. 465 EXPECT_TRUE(db().Open(db_path())); 466 EXPECT_EQ(0, SqliteMasterCount(&db())); 467 } 468 469 // Verify that Raze() can handle a database overwritten with garbage. 470 TEST_F(SQLConnectionTest, RazeNOTADB2) { 471 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 472 ASSERT_TRUE(db().Execute(kCreateSql)); 473 ASSERT_EQ(1, SqliteMasterCount(&db())); 474 db().Close(); 475 476 { 477 file_util::ScopedFILE file(base::OpenFile(db_path(), "rb+")); 478 ASSERT_TRUE(file.get() != NULL); 479 ASSERT_EQ(0, fseek(file.get(), 0, SEEK_SET)); 480 481 const char* kJunk = "This is the hour of our discontent."; 482 fputs(kJunk, file.get()); 483 } 484 485 // SQLite will successfully open the handle, but will fail with 486 // SQLITE_NOTADB on pragma statemenets which attempt to read the 487 // corrupted header. 488 { 489 sql::ScopedErrorIgnorer ignore_errors; 490 ignore_errors.IgnoreError(SQLITE_NOTADB); 491 EXPECT_TRUE(db().Open(db_path())); 492 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 493 } 494 EXPECT_TRUE(db().Raze()); 495 db().Close(); 496 497 // Now empty, the open should succeed with an empty database. 498 EXPECT_TRUE(db().Open(db_path())); 499 EXPECT_EQ(0, SqliteMasterCount(&db())); 500 } 501 502 // Test that a callback from Open() can raze the database. This is 503 // essential for cases where the Open() can fail entirely, so the 504 // Raze() cannot happen later. Additionally test that when the 505 // callback does this during Open(), the open is retried and succeeds. 506 TEST_F(SQLConnectionTest, RazeCallbackReopen) { 507 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 508 ASSERT_TRUE(db().Execute(kCreateSql)); 509 ASSERT_EQ(1, SqliteMasterCount(&db())); 510 db().Close(); 511 512 // Corrupt the database so that nothing works, including PRAGMAs. 513 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path())); 514 515 // Open() will succeed, even though the PRAGMA calls within will 516 // fail with SQLITE_CORRUPT, as will this PRAGMA. 517 { 518 sql::ScopedErrorIgnorer ignore_errors; 519 ignore_errors.IgnoreError(SQLITE_CORRUPT); 520 ASSERT_TRUE(db().Open(db_path())); 521 ASSERT_FALSE(db().Execute("PRAGMA auto_vacuum")); 522 db().Close(); 523 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 524 } 525 526 db().set_error_callback(base::Bind(&SQLConnectionTest::RazeErrorCallback, 527 base::Unretained(this), 528 SQLITE_CORRUPT)); 529 530 // When the PRAGMA calls in Open() raise SQLITE_CORRUPT, the error 531 // callback will call RazeAndClose(). Open() will then fail and be 532 // retried. The second Open() on the empty database will succeed 533 // cleanly. 534 ASSERT_TRUE(db().Open(db_path())); 535 ASSERT_TRUE(db().Execute("PRAGMA auto_vacuum")); 536 EXPECT_EQ(0, SqliteMasterCount(&db())); 537 } 538 539 // Basic test of RazeAndClose() operation. 540 TEST_F(SQLConnectionTest, RazeAndClose) { 541 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 542 const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)"; 543 544 // Test that RazeAndClose() closes the database, and that the 545 // database is empty when re-opened. 546 ASSERT_TRUE(db().Execute(kCreateSql)); 547 ASSERT_TRUE(db().Execute(kPopulateSql)); 548 ASSERT_TRUE(db().RazeAndClose()); 549 ASSERT_FALSE(db().is_open()); 550 db().Close(); 551 ASSERT_TRUE(db().Open(db_path())); 552 ASSERT_EQ(0, SqliteMasterCount(&db())); 553 554 // Test that RazeAndClose() can break transactions. 555 ASSERT_TRUE(db().Execute(kCreateSql)); 556 ASSERT_TRUE(db().Execute(kPopulateSql)); 557 ASSERT_TRUE(db().BeginTransaction()); 558 ASSERT_TRUE(db().RazeAndClose()); 559 ASSERT_FALSE(db().is_open()); 560 ASSERT_FALSE(db().CommitTransaction()); 561 db().Close(); 562 ASSERT_TRUE(db().Open(db_path())); 563 ASSERT_EQ(0, SqliteMasterCount(&db())); 564 } 565 566 // Test that various operations fail without crashing after 567 // RazeAndClose(). 568 TEST_F(SQLConnectionTest, RazeAndCloseDiagnostics) { 569 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 570 const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)"; 571 const char* kSimpleSql = "SELECT 1"; 572 573 ASSERT_TRUE(db().Execute(kCreateSql)); 574 ASSERT_TRUE(db().Execute(kPopulateSql)); 575 576 // Test baseline expectations. 577 db().Preload(); 578 ASSERT_TRUE(db().DoesTableExist("foo")); 579 ASSERT_TRUE(db().IsSQLValid(kSimpleSql)); 580 ASSERT_EQ(SQLITE_OK, db().ExecuteAndReturnErrorCode(kSimpleSql)); 581 ASSERT_TRUE(db().Execute(kSimpleSql)); 582 ASSERT_TRUE(db().is_open()); 583 { 584 sql::Statement s(db().GetUniqueStatement(kSimpleSql)); 585 ASSERT_TRUE(s.Step()); 586 } 587 { 588 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql)); 589 ASSERT_TRUE(s.Step()); 590 } 591 ASSERT_TRUE(db().BeginTransaction()); 592 ASSERT_TRUE(db().CommitTransaction()); 593 ASSERT_TRUE(db().BeginTransaction()); 594 db().RollbackTransaction(); 595 596 ASSERT_TRUE(db().RazeAndClose()); 597 598 // At this point, they should all fail, but not crash. 599 db().Preload(); 600 ASSERT_FALSE(db().DoesTableExist("foo")); 601 ASSERT_FALSE(db().IsSQLValid(kSimpleSql)); 602 ASSERT_EQ(SQLITE_ERROR, db().ExecuteAndReturnErrorCode(kSimpleSql)); 603 ASSERT_FALSE(db().Execute(kSimpleSql)); 604 ASSERT_FALSE(db().is_open()); 605 { 606 sql::Statement s(db().GetUniqueStatement(kSimpleSql)); 607 ASSERT_FALSE(s.Step()); 608 } 609 { 610 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql)); 611 ASSERT_FALSE(s.Step()); 612 } 613 ASSERT_FALSE(db().BeginTransaction()); 614 ASSERT_FALSE(db().CommitTransaction()); 615 ASSERT_FALSE(db().BeginTransaction()); 616 db().RollbackTransaction(); 617 618 // Close normally to reset the poisoned flag. 619 db().Close(); 620 621 // DEATH tests not supported on Android or iOS. 622 #if !defined(OS_ANDROID) && !defined(OS_IOS) 623 // Once the real Close() has been called, various calls enforce API 624 // usage by becoming fatal in debug mode. Since DEATH tests are 625 // expensive, just test one of them. 626 if (DLOG_IS_ON(FATAL)) { 627 ASSERT_DEATH({ 628 db().IsSQLValid(kSimpleSql); 629 }, "Illegal use of connection without a db"); 630 } 631 #endif 632 } 633 634 // TODO(shess): Spin up a background thread to hold other_db, to more 635 // closely match real life. That would also allow testing 636 // RazeWithTimeout(). 637 638 #if defined(OS_ANDROID) 639 TEST_F(SQLConnectionTest, SetTempDirForSQL) { 640 641 sql::MetaTable meta_table; 642 // Below call needs a temporary directory in sqlite3 643 // On Android, it can pass only when the temporary directory is set. 644 // Otherwise, sqlite3 doesn't find the correct directory to store 645 // temporary files and will report the error 'unable to open 646 // database file'. 647 ASSERT_TRUE(meta_table.Init(&db(), 4, 4)); 648 } 649 #endif 650 651 TEST_F(SQLConnectionTest, Delete) { 652 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)")); 653 db().Close(); 654 655 // Should have both a main database file and a journal file because 656 // of journal_mode PERSIST. 657 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal")); 658 ASSERT_TRUE(base::PathExists(db_path())); 659 ASSERT_TRUE(base::PathExists(journal)); 660 661 sql::Connection::Delete(db_path()); 662 EXPECT_FALSE(base::PathExists(db_path())); 663 EXPECT_FALSE(base::PathExists(journal)); 664 } 665 666 #if defined(OS_POSIX) 667 // Test that set_restrict_to_user() trims database permissions so that 668 // only the owner (and root) can read. 669 TEST_F(SQLConnectionTest, UserPermission) { 670 // If the bots all had a restrictive umask setting such that 671 // databases are always created with only the owner able to read 672 // them, then the code could break without breaking the tests. 673 // Temporarily provide a more permissive umask. 674 db().Close(); 675 sql::Connection::Delete(db_path()); 676 ASSERT_FALSE(base::PathExists(db_path())); 677 ScopedUmaskSetter permissive_umask(S_IWGRP | S_IWOTH); 678 ASSERT_TRUE(db().Open(db_path())); 679 680 // Cause the journal file to be created. If the default 681 // journal_mode is changed back to DELETE, then parts of this test 682 // will need to be updated. 683 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)")); 684 685 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal")); 686 int mode; 687 688 // Given a permissive umask, the database is created with permissive 689 // read access for the database and journal. 690 ASSERT_TRUE(base::PathExists(db_path())); 691 ASSERT_TRUE(base::PathExists(journal)); 692 mode = base::FILE_PERMISSION_MASK; 693 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode)); 694 ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode); 695 mode = base::FILE_PERMISSION_MASK; 696 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode)); 697 ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode); 698 699 // Re-open with restricted permissions and verify that the modes 700 // changed for both the main database and the journal. 701 db().Close(); 702 db().set_restrict_to_user(); 703 ASSERT_TRUE(db().Open(db_path())); 704 ASSERT_TRUE(base::PathExists(db_path())); 705 ASSERT_TRUE(base::PathExists(journal)); 706 mode = base::FILE_PERMISSION_MASK; 707 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode)); 708 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode); 709 mode = base::FILE_PERMISSION_MASK; 710 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode)); 711 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode); 712 713 // Delete and re-create the database, the restriction should still apply. 714 db().Close(); 715 sql::Connection::Delete(db_path()); 716 ASSERT_TRUE(db().Open(db_path())); 717 ASSERT_TRUE(base::PathExists(db_path())); 718 ASSERT_FALSE(base::PathExists(journal)); 719 mode = base::FILE_PERMISSION_MASK; 720 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode)); 721 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode); 722 723 // Verify that journal creation inherits the restriction. 724 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)")); 725 ASSERT_TRUE(base::PathExists(journal)); 726 mode = base::FILE_PERMISSION_MASK; 727 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode)); 728 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode); 729 } 730 #endif // defined(OS_POSIX) 731 732 // Test that errors start happening once Poison() is called. 733 TEST_F(SQLConnectionTest, Poison) { 734 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)")); 735 736 // Before the Poison() call, things generally work. 737 EXPECT_TRUE(db().IsSQLValid("INSERT INTO x VALUES ('x')")); 738 EXPECT_TRUE(db().Execute("INSERT INTO x VALUES ('x')")); 739 { 740 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x")); 741 ASSERT_TRUE(s.is_valid()); 742 ASSERT_TRUE(s.Step()); 743 } 744 745 // Get a statement which is valid before and will exist across Poison(). 746 sql::Statement valid_statement( 747 db().GetUniqueStatement("SELECT COUNT(*) FROM sqlite_master")); 748 ASSERT_TRUE(valid_statement.is_valid()); 749 ASSERT_TRUE(valid_statement.Step()); 750 valid_statement.Reset(true); 751 752 db().Poison(); 753 754 // After the Poison() call, things fail. 755 EXPECT_FALSE(db().IsSQLValid("INSERT INTO x VALUES ('x')")); 756 EXPECT_FALSE(db().Execute("INSERT INTO x VALUES ('x')")); 757 { 758 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x")); 759 ASSERT_FALSE(s.is_valid()); 760 ASSERT_FALSE(s.Step()); 761 } 762 763 // The existing statement has become invalid. 764 ASSERT_FALSE(valid_statement.is_valid()); 765 ASSERT_FALSE(valid_statement.Step()); 766 } 767 768 // Test attaching and detaching databases from the connection. 769 TEST_F(SQLConnectionTest, Attach) { 770 EXPECT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); 771 772 // Create a database to attach to. 773 base::FilePath attach_path = 774 db_path().DirName().AppendASCII("SQLConnectionAttach.db"); 775 const char kAttachmentPoint[] = "other"; 776 { 777 sql::Connection other_db; 778 ASSERT_TRUE(other_db.Open(attach_path)); 779 EXPECT_TRUE(other_db.Execute("CREATE TABLE bar (a, b)")); 780 EXPECT_TRUE(other_db.Execute("INSERT INTO bar VALUES ('hello', 'world')")); 781 } 782 783 // Cannot see the attached database, yet. 784 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar")); 785 786 // Attach fails in a transaction. 787 EXPECT_TRUE(db().BeginTransaction()); 788 { 789 sql::ScopedErrorIgnorer ignore_errors; 790 ignore_errors.IgnoreError(SQLITE_ERROR); 791 EXPECT_FALSE(db().AttachDatabase(attach_path, kAttachmentPoint)); 792 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 793 } 794 795 // Attach succeeds when the transaction is closed. 796 db().RollbackTransaction(); 797 EXPECT_TRUE(db().AttachDatabase(attach_path, kAttachmentPoint)); 798 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar")); 799 800 // Queries can touch both databases. 801 EXPECT_TRUE(db().Execute("INSERT INTO foo SELECT a, b FROM other.bar")); 802 { 803 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM foo")); 804 ASSERT_TRUE(s.Step()); 805 EXPECT_EQ(1, s.ColumnInt(0)); 806 } 807 808 // Detach also fails in a transaction. 809 EXPECT_TRUE(db().BeginTransaction()); 810 { 811 sql::ScopedErrorIgnorer ignore_errors; 812 ignore_errors.IgnoreError(SQLITE_ERROR); 813 EXPECT_FALSE(db().DetachDatabase(kAttachmentPoint)); 814 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar")); 815 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 816 } 817 818 // Detach succeeds outside of a transaction. 819 db().RollbackTransaction(); 820 EXPECT_TRUE(db().DetachDatabase(kAttachmentPoint)); 821 822 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar")); 823 } 824 825 TEST_F(SQLConnectionTest, Basic_QuickIntegrityCheck) { 826 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 827 ASSERT_TRUE(db().Execute(kCreateSql)); 828 EXPECT_TRUE(db().QuickIntegrityCheck()); 829 db().Close(); 830 831 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path())); 832 833 { 834 sql::ScopedErrorIgnorer ignore_errors; 835 ignore_errors.IgnoreError(SQLITE_CORRUPT); 836 ASSERT_TRUE(db().Open(db_path())); 837 EXPECT_FALSE(db().QuickIntegrityCheck()); 838 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 839 } 840 } 841 842 TEST_F(SQLConnectionTest, Basic_FullIntegrityCheck) { 843 const std::string kOk("ok"); 844 std::vector<std::string> messages; 845 846 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 847 ASSERT_TRUE(db().Execute(kCreateSql)); 848 EXPECT_TRUE(db().FullIntegrityCheck(&messages)); 849 EXPECT_EQ(1u, messages.size()); 850 EXPECT_EQ(kOk, messages[0]); 851 db().Close(); 852 853 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path())); 854 855 { 856 sql::ScopedErrorIgnorer ignore_errors; 857 ignore_errors.IgnoreError(SQLITE_CORRUPT); 858 ASSERT_TRUE(db().Open(db_path())); 859 EXPECT_TRUE(db().FullIntegrityCheck(&messages)); 860 EXPECT_LT(1u, messages.size()); 861 EXPECT_NE(kOk, messages[0]); 862 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 863 } 864 865 // TODO(shess): CorruptTableOrIndex could be used to produce a 866 // file that would pass the quick check and fail the full check. 867 } 868 869 } // namespace 870