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