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/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"
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 void SetUp() override
{
94 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
95 db_path_
= temp_dir_
.path().AppendASCII("SQLConnectionTest.db");
96 ASSERT_TRUE(db_
.Open(db_path_
));
99 void TearDown() override
{ db_
.Close(); }
101 sql::Connection
& db() { return db_
; }
102 const base::FilePath
& db_path() { return db_path_
; }
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
);
112 base::FilePath db_path_
;
113 base::ScopedTempDir temp_dir_
;
116 TEST_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());
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());
127 TEST_F(SQLConnectionTest
, ExecuteWithErrorCode
) {
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)"));
137 TEST_F(SQLConnectionTest
, CachedStatement
) {
138 sql::StatementID
id1("foo", 12);
140 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
141 ASSERT_TRUE(db().Execute("INSERT INTO foo(a, b) VALUES (12, 13)"));
143 // Create a new cached statement.
145 sql::Statement
s(db().GetCachedStatement(id1
, "SELECT a FROM foo"));
146 ASSERT_TRUE(s
.is_valid());
148 ASSERT_TRUE(s
.Step());
149 EXPECT_EQ(12, s
.ColumnInt(0));
152 // The statement should be cached still.
153 EXPECT_TRUE(db().HasCachedStatement(id1
));
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());
161 ASSERT_TRUE(s
.Step());
162 EXPECT_EQ(12, s
.ColumnInt(0));
165 // Make sure other statements aren't marked as cached.
166 EXPECT_FALSE(db().HasCachedStatement(SQL_FROM_HERE
));
169 TEST_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"));
175 TEST_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"));
181 // Should be case sensitive.
182 EXPECT_FALSE(db().DoesTableExist("FOO"));
184 // Test DoesColumnExist.
185 EXPECT_FALSE(db().DoesColumnExist("foo", "bar"));
186 EXPECT_TRUE(db().DoesColumnExist("foo", "a"));
188 // Testing for a column on a nonexistent table.
189 EXPECT_FALSE(db().DoesColumnExist("bar", "b"));
192 TEST_F(SQLConnectionTest
, GetLastInsertRowId
) {
193 ASSERT_TRUE(db().Execute("CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"));
195 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)"));
197 // Last insert row ID should be valid.
198 int64 row
= db().GetLastInsertRowId();
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=?"));
204 ASSERT_TRUE(s
.Step());
205 EXPECT_EQ(12, s
.ColumnInt(0));
208 TEST_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());
217 // Test the scoped error ignorer by attempting to insert a duplicate
218 // value into an index.
219 TEST_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)"));
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());
230 TEST_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)"));
235 int error
= SQLITE_OK
;
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
);
243 // Callback is no longer in force due to reset.
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
);
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.
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
264 sql::ScopedErrorCallback
sec(
265 &db(), base::Bind(&ErrorCallbackSetHelper
,
266 &db(), &count
, RefCounter(&count
)));
268 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
271 // Same test, but reset_error_callback() case.
274 sql::ScopedErrorCallback
sec(
275 &db(), base::Bind(&ErrorCallbackResetHelper
,
276 &db(), &count
, RefCounter(&count
)));
278 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
282 // Test that sql::Connection::Raze() results in a database without the
283 // tables from the original database.
284 TEST_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)"));
289 int pragma_auto_vacuum
= 0;
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);
297 // If auto_vacuum is set, there's an extra page to maintain a freelist.
298 const int kExpectedPageCount
= 2 + pragma_auto_vacuum
;
301 sql::Statement
s(db().GetUniqueStatement("PRAGMA page_count"));
302 ASSERT_TRUE(s
.Step());
303 EXPECT_EQ(kExpectedPageCount
, s
.ColumnInt(0));
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));
317 ASSERT_TRUE(db().Raze());
320 sql::Statement
s(db().GetUniqueStatement("PRAGMA page_count"));
321 ASSERT_TRUE(s
.Step());
322 EXPECT_EQ(1, s
.ColumnInt(0));
325 ASSERT_EQ(0, SqliteMasterCount(&db()));
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));
335 // Test that Raze() maintains page_size.
336 TEST_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;
341 sql::Statement
s(db().GetUniqueStatement("PRAGMA page_size"));
342 ASSERT_TRUE(s
.Step());
343 default_page_size
= s
.ColumnInt(0);
345 ASSERT_GT(default_page_size
, 0);
346 const int kPageSize
= 2 * default_page_size
;
348 // Re-open the database to allow setting the page size.
350 db().set_page_size(kPageSize
);
351 ASSERT_TRUE(db().Open(db_path()));
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));
358 // After raze, page_size should still match the indicated value.
359 ASSERT_TRUE(db().Raze());
361 ASSERT_TRUE(s
.Step());
362 ASSERT_EQ(kPageSize
, s
.ColumnInt(0));
365 // Test that Raze() results are seen in other connections.
366 TEST_F(SQLConnectionTest
, RazeMultiple
) {
367 const char* kCreateSql
= "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
368 ASSERT_TRUE(db().Execute(kCreateSql
));
370 sql::Connection other_db
;
371 ASSERT_TRUE(other_db
.Open(db_path()));
373 // Check that the second connection sees the table.
374 ASSERT_EQ(1, SqliteMasterCount(&other_db
));
376 ASSERT_TRUE(db().Raze());
378 // The second connection sees the updated database.
379 ASSERT_EQ(0, SqliteMasterCount(&other_db
));
382 TEST_F(SQLConnectionTest
, RazeLocked
) {
383 const char* kCreateSql
= "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
384 ASSERT_TRUE(db().Execute(kCreateSql
));
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
));
395 ASSERT_FALSE(db().Raze());
397 // Works after COMMIT.
398 ASSERT_TRUE(other_db
.CommitTransaction());
399 ASSERT_TRUE(db().Raze());
401 // Re-create the database.
402 ASSERT_TRUE(db().Execute(kCreateSql
));
403 ASSERT_TRUE(db().Execute(kInsertSql
));
405 // An unfinished read transaction in the other connection also
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());
412 // Complete the statement unlocks the database.
413 ASSERT_FALSE(s
.Step());
414 ASSERT_TRUE(db().Raze());
417 // Verify that Raze() can handle an empty file. SQLite should treat
418 // this as an empty database.
419 TEST_F(SQLConnectionTest
, RazeEmptyDB
) {
420 const char* kCreateSql
= "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
421 ASSERT_TRUE(db().Execute(kCreateSql
));
425 base::ScopedFILE
file(base::OpenFile(db_path(), "rb+"));
426 ASSERT_TRUE(file
.get() != NULL
);
427 ASSERT_EQ(0, fseek(file
.get(), 0, SEEK_SET
));
428 ASSERT_TRUE(base::TruncateFile(file
.get()));
431 ASSERT_TRUE(db().Open(db_path()));
432 ASSERT_TRUE(db().Raze());
433 EXPECT_EQ(0, SqliteMasterCount(&db()));
436 // Verify that Raze() can handle a file of junk.
437 TEST_F(SQLConnectionTest
, RazeNOTADB
) {
439 sql::Connection::Delete(db_path());
440 ASSERT_FALSE(base::PathExists(db_path()));
443 base::ScopedFILE
file(base::OpenFile(db_path(), "wb"));
444 ASSERT_TRUE(file
.get() != NULL
);
446 const char* kJunk
= "This is the hour of our discontent.";
447 fputs(kJunk
, file
.get());
449 ASSERT_TRUE(base::PathExists(db_path()));
451 // SQLite will successfully open the handle, but will fail with
452 // SQLITE_IOERR_SHORT_READ on pragma statemenets which read the
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());
460 EXPECT_TRUE(db().Raze());
463 // Now empty, the open should open an empty database.
464 EXPECT_TRUE(db().Open(db_path()));
465 EXPECT_EQ(0, SqliteMasterCount(&db()));
468 // Verify that Raze() can handle a database overwritten with garbage.
469 TEST_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()));
476 base::ScopedFILE
file(base::OpenFile(db_path(), "rb+"));
477 ASSERT_TRUE(file
.get() != NULL
);
478 ASSERT_EQ(0, fseek(file
.get(), 0, SEEK_SET
));
480 const char* kJunk
= "This is the hour of our discontent.";
481 fputs(kJunk
, file
.get());
484 // SQLite will successfully open the handle, but will fail with
485 // SQLITE_NOTADB on pragma statemenets which attempt to read the
488 sql::ScopedErrorIgnorer ignore_errors
;
489 ignore_errors
.IgnoreError(SQLITE_NOTADB
);
490 EXPECT_TRUE(db().Open(db_path()));
491 ASSERT_TRUE(ignore_errors
.CheckIgnoredErrors());
493 EXPECT_TRUE(db().Raze());
496 // Now empty, the open should succeed with an empty database.
497 EXPECT_TRUE(db().Open(db_path()));
498 EXPECT_EQ(0, SqliteMasterCount(&db()));
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 TEST_F(SQLConnectionTest
, RazeCallbackReopen
) {
506 const char* kCreateSql
= "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
507 ASSERT_TRUE(db().Execute(kCreateSql
));
508 ASSERT_EQ(1, SqliteMasterCount(&db()));
511 // Corrupt the database so that nothing works, including PRAGMAs.
512 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path()));
514 // Open() will succeed, even though the PRAGMA calls within will
515 // fail with SQLITE_CORRUPT, as will this PRAGMA.
517 sql::ScopedErrorIgnorer ignore_errors
;
518 ignore_errors
.IgnoreError(SQLITE_CORRUPT
);
519 ASSERT_TRUE(db().Open(db_path()));
520 ASSERT_FALSE(db().Execute("PRAGMA auto_vacuum"));
522 ASSERT_TRUE(ignore_errors
.CheckIgnoredErrors());
525 db().set_error_callback(base::Bind(&SQLConnectionTest::RazeErrorCallback
,
526 base::Unretained(this),
529 // When the PRAGMA calls in Open() raise SQLITE_CORRUPT, the error
530 // callback will call RazeAndClose(). Open() will then fail and be
531 // retried. The second Open() on the empty database will succeed
533 ASSERT_TRUE(db().Open(db_path()));
534 ASSERT_TRUE(db().Execute("PRAGMA auto_vacuum"));
535 EXPECT_EQ(0, SqliteMasterCount(&db()));
538 // Basic test of RazeAndClose() operation.
539 TEST_F(SQLConnectionTest
, RazeAndClose
) {
540 const char* kCreateSql
= "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
541 const char* kPopulateSql
= "INSERT INTO foo (value) VALUES (12)";
543 // Test that RazeAndClose() closes the database, and that the
544 // database is empty when re-opened.
545 ASSERT_TRUE(db().Execute(kCreateSql
));
546 ASSERT_TRUE(db().Execute(kPopulateSql
));
547 ASSERT_TRUE(db().RazeAndClose());
548 ASSERT_FALSE(db().is_open());
550 ASSERT_TRUE(db().Open(db_path()));
551 ASSERT_EQ(0, SqliteMasterCount(&db()));
553 // Test that RazeAndClose() can break transactions.
554 ASSERT_TRUE(db().Execute(kCreateSql
));
555 ASSERT_TRUE(db().Execute(kPopulateSql
));
556 ASSERT_TRUE(db().BeginTransaction());
557 ASSERT_TRUE(db().RazeAndClose());
558 ASSERT_FALSE(db().is_open());
559 ASSERT_FALSE(db().CommitTransaction());
561 ASSERT_TRUE(db().Open(db_path()));
562 ASSERT_EQ(0, SqliteMasterCount(&db()));
565 // Test that various operations fail without crashing after
567 TEST_F(SQLConnectionTest
, RazeAndCloseDiagnostics
) {
568 const char* kCreateSql
= "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
569 const char* kPopulateSql
= "INSERT INTO foo (value) VALUES (12)";
570 const char* kSimpleSql
= "SELECT 1";
572 ASSERT_TRUE(db().Execute(kCreateSql
));
573 ASSERT_TRUE(db().Execute(kPopulateSql
));
575 // Test baseline expectations.
577 ASSERT_TRUE(db().DoesTableExist("foo"));
578 ASSERT_TRUE(db().IsSQLValid(kSimpleSql
));
579 ASSERT_EQ(SQLITE_OK
, db().ExecuteAndReturnErrorCode(kSimpleSql
));
580 ASSERT_TRUE(db().Execute(kSimpleSql
));
581 ASSERT_TRUE(db().is_open());
583 sql::Statement
s(db().GetUniqueStatement(kSimpleSql
));
584 ASSERT_TRUE(s
.Step());
587 sql::Statement
s(db().GetCachedStatement(SQL_FROM_HERE
, kSimpleSql
));
588 ASSERT_TRUE(s
.Step());
590 ASSERT_TRUE(db().BeginTransaction());
591 ASSERT_TRUE(db().CommitTransaction());
592 ASSERT_TRUE(db().BeginTransaction());
593 db().RollbackTransaction();
595 ASSERT_TRUE(db().RazeAndClose());
597 // At this point, they should all fail, but not crash.
599 ASSERT_FALSE(db().DoesTableExist("foo"));
600 ASSERT_FALSE(db().IsSQLValid(kSimpleSql
));
601 ASSERT_EQ(SQLITE_ERROR
, db().ExecuteAndReturnErrorCode(kSimpleSql
));
602 ASSERT_FALSE(db().Execute(kSimpleSql
));
603 ASSERT_FALSE(db().is_open());
605 sql::Statement
s(db().GetUniqueStatement(kSimpleSql
));
606 ASSERT_FALSE(s
.Step());
609 sql::Statement
s(db().GetCachedStatement(SQL_FROM_HERE
, kSimpleSql
));
610 ASSERT_FALSE(s
.Step());
612 ASSERT_FALSE(db().BeginTransaction());
613 ASSERT_FALSE(db().CommitTransaction());
614 ASSERT_FALSE(db().BeginTransaction());
615 db().RollbackTransaction();
617 // Close normally to reset the poisoned flag.
620 // DEATH tests not supported on Android or iOS.
621 #if !defined(OS_ANDROID) && !defined(OS_IOS)
622 // Once the real Close() has been called, various calls enforce API
623 // usage by becoming fatal in debug mode. Since DEATH tests are
624 // expensive, just test one of them.
625 if (DLOG_IS_ON(FATAL
)) {
627 db().IsSQLValid(kSimpleSql
);
628 }, "Illegal use of connection without a db");
633 // TODO(shess): Spin up a background thread to hold other_db, to more
634 // closely match real life. That would also allow testing
635 // RazeWithTimeout().
637 #if defined(OS_ANDROID)
638 TEST_F(SQLConnectionTest
, SetTempDirForSQL
) {
640 sql::MetaTable meta_table
;
641 // Below call needs a temporary directory in sqlite3
642 // On Android, it can pass only when the temporary directory is set.
643 // Otherwise, sqlite3 doesn't find the correct directory to store
644 // temporary files and will report the error 'unable to open
646 ASSERT_TRUE(meta_table
.Init(&db(), 4, 4));
650 TEST_F(SQLConnectionTest
, Delete
) {
651 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
654 // Should have both a main database file and a journal file because
655 // of journal_mode PERSIST.
656 base::FilePath
journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
657 ASSERT_TRUE(base::PathExists(db_path()));
658 ASSERT_TRUE(base::PathExists(journal
));
660 sql::Connection::Delete(db_path());
661 EXPECT_FALSE(base::PathExists(db_path()));
662 EXPECT_FALSE(base::PathExists(journal
));
665 #if defined(OS_POSIX)
666 // Test that set_restrict_to_user() trims database permissions so that
667 // only the owner (and root) can read.
668 TEST_F(SQLConnectionTest
, UserPermission
) {
669 // If the bots all had a restrictive umask setting such that
670 // databases are always created with only the owner able to read
671 // them, then the code could break without breaking the tests.
672 // Temporarily provide a more permissive umask.
674 sql::Connection::Delete(db_path());
675 ASSERT_FALSE(base::PathExists(db_path()));
676 ScopedUmaskSetter
permissive_umask(S_IWGRP
| S_IWOTH
);
677 ASSERT_TRUE(db().Open(db_path()));
679 // Cause the journal file to be created. If the default
680 // journal_mode is changed back to DELETE, then parts of this test
681 // will need to be updated.
682 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
684 base::FilePath
journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
687 // Given a permissive umask, the database is created with permissive
688 // read access for the database and journal.
689 ASSERT_TRUE(base::PathExists(db_path()));
690 ASSERT_TRUE(base::PathExists(journal
));
691 mode
= base::FILE_PERMISSION_MASK
;
692 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode
));
693 ASSERT_NE((mode
& base::FILE_PERMISSION_USER_MASK
), mode
);
694 mode
= base::FILE_PERMISSION_MASK
;
695 EXPECT_TRUE(base::GetPosixFilePermissions(journal
, &mode
));
696 ASSERT_NE((mode
& base::FILE_PERMISSION_USER_MASK
), mode
);
698 // Re-open with restricted permissions and verify that the modes
699 // changed for both the main database and the journal.
701 db().set_restrict_to_user();
702 ASSERT_TRUE(db().Open(db_path()));
703 ASSERT_TRUE(base::PathExists(db_path()));
704 ASSERT_TRUE(base::PathExists(journal
));
705 mode
= base::FILE_PERMISSION_MASK
;
706 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode
));
707 ASSERT_EQ((mode
& base::FILE_PERMISSION_USER_MASK
), mode
);
708 mode
= base::FILE_PERMISSION_MASK
;
709 EXPECT_TRUE(base::GetPosixFilePermissions(journal
, &mode
));
710 ASSERT_EQ((mode
& base::FILE_PERMISSION_USER_MASK
), mode
);
712 // Delete and re-create the database, the restriction should still apply.
714 sql::Connection::Delete(db_path());
715 ASSERT_TRUE(db().Open(db_path()));
716 ASSERT_TRUE(base::PathExists(db_path()));
717 ASSERT_FALSE(base::PathExists(journal
));
718 mode
= base::FILE_PERMISSION_MASK
;
719 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode
));
720 ASSERT_EQ((mode
& base::FILE_PERMISSION_USER_MASK
), mode
);
722 // Verify that journal creation inherits the restriction.
723 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
724 ASSERT_TRUE(base::PathExists(journal
));
725 mode
= base::FILE_PERMISSION_MASK
;
726 EXPECT_TRUE(base::GetPosixFilePermissions(journal
, &mode
));
727 ASSERT_EQ((mode
& base::FILE_PERMISSION_USER_MASK
), mode
);
729 #endif // defined(OS_POSIX)
731 // Test that errors start happening once Poison() is called.
732 TEST_F(SQLConnectionTest
, Poison
) {
733 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
735 // Before the Poison() call, things generally work.
736 EXPECT_TRUE(db().IsSQLValid("INSERT INTO x VALUES ('x')"));
737 EXPECT_TRUE(db().Execute("INSERT INTO x VALUES ('x')"));
739 sql::Statement
s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
740 ASSERT_TRUE(s
.is_valid());
741 ASSERT_TRUE(s
.Step());
744 // Get a statement which is valid before and will exist across Poison().
745 sql::Statement
valid_statement(
746 db().GetUniqueStatement("SELECT COUNT(*) FROM sqlite_master"));
747 ASSERT_TRUE(valid_statement
.is_valid());
748 ASSERT_TRUE(valid_statement
.Step());
749 valid_statement
.Reset(true);
753 // After the Poison() call, things fail.
754 EXPECT_FALSE(db().IsSQLValid("INSERT INTO x VALUES ('x')"));
755 EXPECT_FALSE(db().Execute("INSERT INTO x VALUES ('x')"));
757 sql::Statement
s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
758 ASSERT_FALSE(s
.is_valid());
759 ASSERT_FALSE(s
.Step());
762 // The existing statement has become invalid.
763 ASSERT_FALSE(valid_statement
.is_valid());
764 ASSERT_FALSE(valid_statement
.Step());
767 // Test attaching and detaching databases from the connection.
768 TEST_F(SQLConnectionTest
, Attach
) {
769 EXPECT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
771 // Create a database to attach to.
772 base::FilePath attach_path
=
773 db_path().DirName().AppendASCII("SQLConnectionAttach.db");
774 const char kAttachmentPoint
[] = "other";
776 sql::Connection other_db
;
777 ASSERT_TRUE(other_db
.Open(attach_path
));
778 EXPECT_TRUE(other_db
.Execute("CREATE TABLE bar (a, b)"));
779 EXPECT_TRUE(other_db
.Execute("INSERT INTO bar VALUES ('hello', 'world')"));
782 // Cannot see the attached database, yet.
783 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
785 // Attach fails in a transaction.
786 EXPECT_TRUE(db().BeginTransaction());
788 sql::ScopedErrorIgnorer ignore_errors
;
789 ignore_errors
.IgnoreError(SQLITE_ERROR
);
790 EXPECT_FALSE(db().AttachDatabase(attach_path
, kAttachmentPoint
));
791 ASSERT_TRUE(ignore_errors
.CheckIgnoredErrors());
794 // Attach succeeds when the transaction is closed.
795 db().RollbackTransaction();
796 EXPECT_TRUE(db().AttachDatabase(attach_path
, kAttachmentPoint
));
797 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
799 // Queries can touch both databases.
800 EXPECT_TRUE(db().Execute("INSERT INTO foo SELECT a, b FROM other.bar"));
802 sql::Statement
s(db().GetUniqueStatement("SELECT COUNT(*) FROM foo"));
803 ASSERT_TRUE(s
.Step());
804 EXPECT_EQ(1, s
.ColumnInt(0));
807 // Detach also fails in a transaction.
808 EXPECT_TRUE(db().BeginTransaction());
810 sql::ScopedErrorIgnorer ignore_errors
;
811 ignore_errors
.IgnoreError(SQLITE_ERROR
);
812 EXPECT_FALSE(db().DetachDatabase(kAttachmentPoint
));
813 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
814 ASSERT_TRUE(ignore_errors
.CheckIgnoredErrors());
817 // Detach succeeds outside of a transaction.
818 db().RollbackTransaction();
819 EXPECT_TRUE(db().DetachDatabase(kAttachmentPoint
));
821 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
824 TEST_F(SQLConnectionTest
, Basic_QuickIntegrityCheck
) {
825 const char* kCreateSql
= "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
826 ASSERT_TRUE(db().Execute(kCreateSql
));
827 EXPECT_TRUE(db().QuickIntegrityCheck());
830 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path()));
833 sql::ScopedErrorIgnorer ignore_errors
;
834 ignore_errors
.IgnoreError(SQLITE_CORRUPT
);
835 ASSERT_TRUE(db().Open(db_path()));
836 EXPECT_FALSE(db().QuickIntegrityCheck());
837 ASSERT_TRUE(ignore_errors
.CheckIgnoredErrors());
841 TEST_F(SQLConnectionTest
, Basic_FullIntegrityCheck
) {
842 const std::string
kOk("ok");
843 std::vector
<std::string
> messages
;
845 const char* kCreateSql
= "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
846 ASSERT_TRUE(db().Execute(kCreateSql
));
847 EXPECT_TRUE(db().FullIntegrityCheck(&messages
));
848 EXPECT_EQ(1u, messages
.size());
849 EXPECT_EQ(kOk
, messages
[0]);
852 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path()));
855 sql::ScopedErrorIgnorer ignore_errors
;
856 ignore_errors
.IgnoreError(SQLITE_CORRUPT
);
857 ASSERT_TRUE(db().Open(db_path()));
858 EXPECT_TRUE(db().FullIntegrityCheck(&messages
));
859 EXPECT_LT(1u, messages
.size());
860 EXPECT_NE(kOk
, messages
[0]);
861 ASSERT_TRUE(ignore_errors
.CheckIgnoredErrors());
864 // TODO(shess): CorruptTableOrIndex could be used to produce a
865 // file that would pass the quick check and fail the full check.