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.
6 #include "base/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"
21 // Helper to return the count of items in sqlite_master. Return -1 in
23 int 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;
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.
34 RefCounter(size_t* counter
)
38 RefCounter(const RefCounter
& other
)
39 : counter_(other
.counter_
) {
49 DISALLOW_ASSIGN(RefCounter
);
52 // Empty callback for implementation of ErrorCallbackSetHelper().
53 void IgnoreErrorCallback(int error
, sql::Statement
* stmt
) {
56 void ErrorCallbackSetHelper(sql::Connection
* db
,
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);
66 void ErrorCallbackResetHelper(sql::Connection
* db
,
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);
77 // Set a umask and restore the old mask on destruction. Cribbed from
78 // shared_memory_unittest.cc. Used by POSIX-only UserPermission test.
79 class ScopedUmaskSetter
{
81 explicit ScopedUmaskSetter(mode_t target_mask
) {
82 old_umask_
= umask(target_mask
);
84 ~ScopedUmaskSetter() { umask(old_umask_
); }
87 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter
);
91 class SQLConnectionTest
: public testing::Test
{
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_
));
99 virtual void TearDown() {
103 sql::Connection
& db() { return db_
; }
104 const base::FilePath
& db_path() { return db_path_
; }
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
);
114 base::FilePath db_path_
;
115 base::ScopedTempDir temp_dir_
;
118 TEST_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());
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());
129 TEST_F(SQLConnectionTest
, ExecuteWithErrorCode
) {
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)"));
139 TEST_F(SQLConnectionTest
, CachedStatement
) {
140 sql::StatementID
id1("foo", 12);
142 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
143 ASSERT_TRUE(db().Execute("INSERT INTO foo(a, b) VALUES (12, 13)"));
145 // Create a new cached statement.
147 sql::Statement
s(db().GetCachedStatement(id1
, "SELECT a FROM foo"));
148 ASSERT_TRUE(s
.is_valid());
150 ASSERT_TRUE(s
.Step());
151 EXPECT_EQ(12, s
.ColumnInt(0));
154 // The statement should be cached still.
155 EXPECT_TRUE(db().HasCachedStatement(id1
));
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());
163 ASSERT_TRUE(s
.Step());
164 EXPECT_EQ(12, s
.ColumnInt(0));
167 // Make sure other statements aren't marked as cached.
168 EXPECT_FALSE(db().HasCachedStatement(SQL_FROM_HERE
));
171 TEST_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"));
177 TEST_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"));
183 // Should be case sensitive.
184 EXPECT_FALSE(db().DoesTableExist("FOO"));
186 // Test DoesColumnExist.
187 EXPECT_FALSE(db().DoesColumnExist("foo", "bar"));
188 EXPECT_TRUE(db().DoesColumnExist("foo", "a"));
190 // Testing for a column on a nonexistent table.
191 EXPECT_FALSE(db().DoesColumnExist("bar", "b"));
194 TEST_F(SQLConnectionTest
, GetLastInsertRowId
) {
195 ASSERT_TRUE(db().Execute("CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"));
197 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)"));
199 // Last insert row ID should be valid.
200 int64 row
= db().GetLastInsertRowId();
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=?"));
206 ASSERT_TRUE(s
.Step());
207 EXPECT_EQ(12, s
.ColumnInt(0));
210 TEST_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());
219 // Test the scoped error ignorer by attempting to insert a duplicate
220 // value into an index.
221 TEST_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)"));
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());
232 TEST_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)"));
237 int error
= SQLITE_OK
;
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
);
245 // Callback is no longer in force due to reset.
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
);
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.
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
266 sql::ScopedErrorCallback
sec(
267 &db(), base::Bind(&ErrorCallbackSetHelper
,
268 &db(), &count
, RefCounter(&count
)));
270 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
273 // Same test, but reset_error_callback() case.
276 sql::ScopedErrorCallback
sec(
277 &db(), base::Bind(&ErrorCallbackResetHelper
,
278 &db(), &count
, RefCounter(&count
)));
280 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
284 // Test that sql::Connection::Raze() results in a database without the
285 // tables from the original database.
286 TEST_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)"));
291 int pragma_auto_vacuum
= 0;
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);
299 // If auto_vacuum is set, there's an extra page to maintain a freelist.
300 const int kExpectedPageCount
= 2 + pragma_auto_vacuum
;
303 sql::Statement
s(db().GetUniqueStatement("PRAGMA page_count"));
304 ASSERT_TRUE(s
.Step());
305 EXPECT_EQ(kExpectedPageCount
, s
.ColumnInt(0));
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));
319 ASSERT_TRUE(db().Raze());
322 sql::Statement
s(db().GetUniqueStatement("PRAGMA page_count"));
323 ASSERT_TRUE(s
.Step());
324 EXPECT_EQ(1, s
.ColumnInt(0));
327 ASSERT_EQ(0, SqliteMasterCount(&db()));
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));
337 // Test that Raze() maintains page_size.
338 TEST_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;
343 sql::Statement
s(db().GetUniqueStatement("PRAGMA page_size"));
344 ASSERT_TRUE(s
.Step());
345 default_page_size
= s
.ColumnInt(0);
347 ASSERT_GT(default_page_size
, 0);
348 const int kPageSize
= 2 * default_page_size
;
350 // Re-open the database to allow setting the page size.
352 db().set_page_size(kPageSize
);
353 ASSERT_TRUE(db().Open(db_path()));
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));
360 // After raze, page_size should still match the indicated value.
361 ASSERT_TRUE(db().Raze());
363 ASSERT_TRUE(s
.Step());
364 ASSERT_EQ(kPageSize
, s
.ColumnInt(0));
367 // Test that Raze() results are seen in other connections.
368 TEST_F(SQLConnectionTest
, RazeMultiple
) {
369 const char* kCreateSql
= "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
370 ASSERT_TRUE(db().Execute(kCreateSql
));
372 sql::Connection other_db
;
373 ASSERT_TRUE(other_db
.Open(db_path()));
375 // Check that the second connection sees the table.
376 ASSERT_EQ(1, SqliteMasterCount(&other_db
));
378 ASSERT_TRUE(db().Raze());
380 // The second connection sees the updated database.
381 ASSERT_EQ(0, SqliteMasterCount(&other_db
));
384 TEST_F(SQLConnectionTest
, RazeLocked
) {
385 const char* kCreateSql
= "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
386 ASSERT_TRUE(db().Execute(kCreateSql
));
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
));
397 ASSERT_FALSE(db().Raze());
399 // Works after COMMIT.
400 ASSERT_TRUE(other_db
.CommitTransaction());
401 ASSERT_TRUE(db().Raze());
403 // Re-create the database.
404 ASSERT_TRUE(db().Execute(kCreateSql
));
405 ASSERT_TRUE(db().Execute(kInsertSql
));
407 // An unfinished read transaction in the other connection also
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());
414 // Complete the statement unlocks the database.
415 ASSERT_FALSE(s
.Step());
416 ASSERT_TRUE(db().Raze());
419 // Verify that Raze() can handle an empty file. SQLite should treat
420 // this as an empty database.
421 TEST_F(SQLConnectionTest
, RazeEmptyDB
) {
422 const char* kCreateSql
= "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
423 ASSERT_TRUE(db().Execute(kCreateSql
));
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()));
433 ASSERT_TRUE(db().Open(db_path()));
434 ASSERT_TRUE(db().Raze());
435 EXPECT_EQ(0, SqliteMasterCount(&db()));
438 // Verify that Raze() can handle a file of junk.
439 TEST_F(SQLConnectionTest
, RazeNOTADB
) {
441 sql::Connection::Delete(db_path());
442 ASSERT_FALSE(base::PathExists(db_path()));
445 base::ScopedFILE
file(base::OpenFile(db_path(), "wb"));
446 ASSERT_TRUE(file
.get() != NULL
);
448 const char* kJunk
= "This is the hour of our discontent.";
449 fputs(kJunk
, file
.get());
451 ASSERT_TRUE(base::PathExists(db_path()));
453 // SQLite will successfully open the handle, but will fail with
454 // SQLITE_IOERR_SHORT_READ on pragma statemenets which read the
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());
462 EXPECT_TRUE(db().Raze());
465 // Now empty, the open should open an empty database.
466 EXPECT_TRUE(db().Open(db_path()));
467 EXPECT_EQ(0, SqliteMasterCount(&db()));
470 // Verify that Raze() can handle a database overwritten with garbage.
471 TEST_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()));
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
));
482 const char* kJunk
= "This is the hour of our discontent.";
483 fputs(kJunk
, file
.get());
486 // SQLite will successfully open the handle, but will fail with
487 // SQLITE_NOTADB on pragma statemenets which attempt to read the
490 sql::ScopedErrorIgnorer ignore_errors
;
491 ignore_errors
.IgnoreError(SQLITE_NOTADB
);
492 EXPECT_TRUE(db().Open(db_path()));
493 ASSERT_TRUE(ignore_errors
.CheckIgnoredErrors());
495 EXPECT_TRUE(db().Raze());
498 // Now empty, the open should succeed with an empty database.
499 EXPECT_TRUE(db().Open(db_path()));
500 EXPECT_EQ(0, SqliteMasterCount(&db()));
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.
507 TEST_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()));
513 // Corrupt the database so that nothing works, including PRAGMAs.
514 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path()));
516 // Open() will succeed, even though the PRAGMA calls within will
517 // fail with SQLITE_CORRUPT, as will this PRAGMA.
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"));
524 ASSERT_TRUE(ignore_errors
.CheckIgnoredErrors());
527 db().set_error_callback(base::Bind(&SQLConnectionTest::RazeErrorCallback
,
528 base::Unretained(this),
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
535 ASSERT_TRUE(db().Open(db_path()));
536 ASSERT_TRUE(db().Execute("PRAGMA auto_vacuum"));
537 EXPECT_EQ(0, SqliteMasterCount(&db()));
540 // Basic test of RazeAndClose() operation.
541 TEST_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)";
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());
552 ASSERT_TRUE(db().Open(db_path()));
553 ASSERT_EQ(0, SqliteMasterCount(&db()));
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());
563 ASSERT_TRUE(db().Open(db_path()));
564 ASSERT_EQ(0, SqliteMasterCount(&db()));
567 // Test that various operations fail without crashing after
569 TEST_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";
574 ASSERT_TRUE(db().Execute(kCreateSql
));
575 ASSERT_TRUE(db().Execute(kPopulateSql
));
577 // Test baseline expectations.
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());
585 sql::Statement
s(db().GetUniqueStatement(kSimpleSql
));
586 ASSERT_TRUE(s
.Step());
589 sql::Statement
s(db().GetCachedStatement(SQL_FROM_HERE
, kSimpleSql
));
590 ASSERT_TRUE(s
.Step());
592 ASSERT_TRUE(db().BeginTransaction());
593 ASSERT_TRUE(db().CommitTransaction());
594 ASSERT_TRUE(db().BeginTransaction());
595 db().RollbackTransaction();
597 ASSERT_TRUE(db().RazeAndClose());
599 // At this point, they should all fail, but not crash.
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());
607 sql::Statement
s(db().GetUniqueStatement(kSimpleSql
));
608 ASSERT_FALSE(s
.Step());
611 sql::Statement
s(db().GetCachedStatement(SQL_FROM_HERE
, kSimpleSql
));
612 ASSERT_FALSE(s
.Step());
614 ASSERT_FALSE(db().BeginTransaction());
615 ASSERT_FALSE(db().CommitTransaction());
616 ASSERT_FALSE(db().BeginTransaction());
617 db().RollbackTransaction();
619 // Close normally to reset the poisoned flag.
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
)) {
629 db().IsSQLValid(kSimpleSql
);
630 }, "Illegal use of connection without a db");
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().
639 #if defined(OS_ANDROID)
640 TEST_F(SQLConnectionTest
, SetTempDirForSQL
) {
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
648 ASSERT_TRUE(meta_table
.Init(&db(), 4, 4));
652 TEST_F(SQLConnectionTest
, Delete
) {
653 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
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
));
662 sql::Connection::Delete(db_path());
663 EXPECT_FALSE(base::PathExists(db_path()));
664 EXPECT_FALSE(base::PathExists(journal
));
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.
670 TEST_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.
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()));
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)"));
686 base::FilePath
journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
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
);
700 // Re-open with restricted permissions and verify that the modes
701 // changed for both the main database and the journal.
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
);
714 // Delete and re-create the database, the restriction should still apply.
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
);
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
);
731 #endif // defined(OS_POSIX)
733 // Test that errors start happening once Poison() is called.
734 TEST_F(SQLConnectionTest
, Poison
) {
735 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
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')"));
741 sql::Statement
s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
742 ASSERT_TRUE(s
.is_valid());
743 ASSERT_TRUE(s
.Step());
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);
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')"));
759 sql::Statement
s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
760 ASSERT_FALSE(s
.is_valid());
761 ASSERT_FALSE(s
.Step());
764 // The existing statement has become invalid.
765 ASSERT_FALSE(valid_statement
.is_valid());
766 ASSERT_FALSE(valid_statement
.Step());
769 // Test attaching and detaching databases from the connection.
770 TEST_F(SQLConnectionTest
, Attach
) {
771 EXPECT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
773 // Create a database to attach to.
774 base::FilePath attach_path
=
775 db_path().DirName().AppendASCII("SQLConnectionAttach.db");
776 const char kAttachmentPoint
[] = "other";
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')"));
784 // Cannot see the attached database, yet.
785 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
787 // Attach fails in a transaction.
788 EXPECT_TRUE(db().BeginTransaction());
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());
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"));
801 // Queries can touch both databases.
802 EXPECT_TRUE(db().Execute("INSERT INTO foo SELECT a, b FROM other.bar"));
804 sql::Statement
s(db().GetUniqueStatement("SELECT COUNT(*) FROM foo"));
805 ASSERT_TRUE(s
.Step());
806 EXPECT_EQ(1, s
.ColumnInt(0));
809 // Detach also fails in a transaction.
810 EXPECT_TRUE(db().BeginTransaction());
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());
819 // Detach succeeds outside of a transaction.
820 db().RollbackTransaction();
821 EXPECT_TRUE(db().DetachDatabase(kAttachmentPoint
));
823 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
826 TEST_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());
832 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path()));
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());
843 TEST_F(SQLConnectionTest
, Basic_FullIntegrityCheck
) {
844 const std::string
kOk("ok");
845 std::vector
<std::string
> messages
;
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]);
854 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path()));
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());
866 // TODO(shess): CorruptTableOrIndex could be used to produce a
867 // file that would pass the quick check and fail the full check.