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