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