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