Update linux build dependency script.
[chromium-blink-merge.git] / sql / connection_unittest.cc
blob445db3459bdfa972a6211bd51917a5202c3095f5
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.
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"
17 namespace {
19 // Helper to return the count of items in sqlite_master. Return -1 in
20 // case of error.
21 int 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;
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.
30 class RefCounter {
31 public:
32 RefCounter(size_t* counter)
33 : counter_(counter) {
34 (*counter_)++;
36 RefCounter(const RefCounter& other)
37 : counter_(other.counter_) {
38 (*counter_)++;
40 ~RefCounter() {
41 (*counter_)--;
44 private:
45 size_t* counter_;
47 DISALLOW_ASSIGN(RefCounter);
50 // Empty callback for implementation of ErrorCallbackSetHelper().
51 void IgnoreErrorCallback(int error, sql::Statement* stmt) {
54 void 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);
64 void 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);
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.
77 class ScopedUmaskSetter {
78 public:
79 explicit ScopedUmaskSetter(mode_t target_mask) {
80 old_umask_ = umask(target_mask);
82 ~ScopedUmaskSetter() { umask(old_umask_); }
83 private:
84 mode_t old_umask_;
85 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter);
87 #endif
89 class 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_));
97 virtual void TearDown() {
98 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);
107 db_.RazeAndClose();
110 private:
111 sql::Connection db_;
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) {
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)"));
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();
199 EXPECT_LT(0, row);
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));
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.
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);
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
261 // live.
263 size_t count = 0;
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.
273 size_t count = 0;
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.
349 db().Close();
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());
360 s.Reset(true);
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
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());
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));
422 db().Close();
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()));
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) {
438 db().Close();
439 sql::Connection::Delete(db_path());
440 ASSERT_FALSE(base::PathExists(db_path()));
443 file_util::ScopedFILE file(file_util::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
453 // header.
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());
461 db().Close();
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()));
473 db().Close();
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));
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
486 // corrupted header.
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());
494 db().Close();
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.
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.
512 TEST_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;
518 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size"));
519 ASSERT_TRUE(s.Step());
520 page_size = s.ColumnInt(0);
522 db().Close();
524 // Trim a single page from the end of the file.
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()));
532 // Open() will succeed, even though the PRAGMA calls within will
533 // fail with SQLITE_CORRUPT, as will this PRAGMA.
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());
543 db().set_error_callback(base::Bind(&SQLConnectionTest::RazeErrorCallback,
544 base::Unretained(this),
545 SQLITE_CORRUPT));
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()));
556 // Basic test of RazeAndClose() operation.
557 TEST_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)";
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()));
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()));
583 // Test that various operations fail without crashing after
584 // RazeAndClose().
585 TEST_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";
590 ASSERT_TRUE(db().Execute(kCreateSql));
591 ASSERT_TRUE(db().Execute(kPopulateSql));
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());
601 sql::Statement s(db().GetUniqueStatement(kSimpleSql));
602 ASSERT_TRUE(s.Step());
605 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
606 ASSERT_TRUE(s.Step());
608 ASSERT_TRUE(db().BeginTransaction());
609 ASSERT_TRUE(db().CommitTransaction());
610 ASSERT_TRUE(db().BeginTransaction());
611 db().RollbackTransaction();
613 ASSERT_TRUE(db().RazeAndClose());
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());
623 sql::Statement s(db().GetUniqueStatement(kSimpleSql));
624 ASSERT_FALSE(s.Step());
627 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
628 ASSERT_FALSE(s.Step());
630 ASSERT_FALSE(db().BeginTransaction());
631 ASSERT_FALSE(db().CommitTransaction());
632 ASSERT_FALSE(db().BeginTransaction());
633 db().RollbackTransaction();
635 // Close normally to reset the poisoned flag.
636 db().Close();
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");
648 #endif
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().
655 #if defined(OS_ANDROID)
656 TEST_F(SQLConnectionTest, SetTempDirForSQL) {
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));
666 #endif
668 TEST_F(SQLConnectionTest, Delete) {
669 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
670 db().Close();
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));
678 sql::Connection::Delete(db_path());
679 EXPECT_FALSE(base::PathExists(db_path()));
680 EXPECT_FALSE(base::PathExists(journal));
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.
686 TEST_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()));
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)"));
702 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
703 int mode;
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);
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);
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);
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);
747 #endif // defined(OS_POSIX)
749 // Test that errors start happening once Poison() is called.
750 TEST_F(SQLConnectionTest, Poison) {
751 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
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')"));
757 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
758 ASSERT_TRUE(s.is_valid());
759 ASSERT_TRUE(s.Step());
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);
769 db().Poison();
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')"));
775 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
776 ASSERT_FALSE(s.is_valid());
777 ASSERT_FALSE(s.Step());
780 // The existing statement has become invalid.
781 ASSERT_FALSE(valid_statement.is_valid());
782 ASSERT_FALSE(valid_statement.Step());
785 // Test attaching and detaching databases from the connection.
786 TEST_F(SQLConnectionTest, Attach) {
787 EXPECT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
789 // Create a database to attach to.
790 base::FilePath attach_path =
791 db_path().DirName().AppendASCII("SQLConnectionAttach.db");
792 const char kAttachmentPoint[] = "other";
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')"));
800 // Cannot see the attached database, yet.
801 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
803 // Attach fails in a transaction.
804 EXPECT_TRUE(db().BeginTransaction());
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());
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"));
817 // Queries can touch both databases.
818 EXPECT_TRUE(db().Execute("INSERT INTO foo SELECT a, b FROM other.bar"));
820 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM foo"));
821 ASSERT_TRUE(s.Step());
822 EXPECT_EQ(1, s.ColumnInt(0));
825 // Detach also fails in a transaction.
826 EXPECT_TRUE(db().BeginTransaction());
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());
835 // Detach succeeds outside of a transaction.
836 db().RollbackTransaction();
837 EXPECT_TRUE(db().DetachDatabase(kAttachmentPoint));
839 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
842 } // namespace