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