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