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