blob: 07c9fa7c732c0714e4eb07a5799f0946ed7a1076 [file] [log] [blame]
[email protected]44ad7d902012-03-23 00:09:051// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]e5ffd0e42009-09-11 21:30:562// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]7bae5742013-07-10 20:46:165#include "base/bind.h"
thestig22dfc4012014-09-05 08:29:446#include "base/files/file_util.h"
[email protected]b9b4a572014-03-17 23:11:127#include "base/files/scoped_file.h"
[email protected]ea1a3f62012-11-16 20:34:238#include "base/files/scoped_temp_dir.h"
[email protected]41a97c812013-02-07 02:35:389#include "base/logging.h"
[email protected]f0a54b22011-07-19 18:40:2110#include "sql/connection.h"
[email protected]1348765a2012-07-24 08:25:5311#include "sql/meta_table.h"
[email protected]ea1a3f62012-11-16 20:34:2312#include "sql/statement.h"
[email protected]98cf3002013-07-12 01:38:5613#include "sql/test/error_callback_support.h"
[email protected]4350e322013-06-18 22:18:1014#include "sql/test/scoped_error_ignorer.h"
[email protected]a8848a72013-11-18 04:18:4715#include "sql/test/test_helpers.h"
[email protected]e5ffd0e42009-09-11 21:30:5616#include "testing/gtest/include/gtest/gtest.h"
[email protected]e33cba42010-08-18 23:37:0317#include "third_party/sqlite/sqlite3.h"
[email protected]e5ffd0e42009-09-11 21:30:5618
[email protected]7bae5742013-07-10 20:46:1619namespace {
20
21// Helper to return the count of items in sqlite_master. Return -1 in
22// case of error.
23int 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
[email protected]98cf3002013-07-12 01:38:5629// 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.
32class RefCounter {
33 public:
34 RefCounter(size_t* counter)
35 : counter_(counter) {
36 (*counter_)++;
37 }
38 RefCounter(const RefCounter& other)
39 : counter_(other.counter_) {
40 (*counter_)++;
41 }
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().
53void IgnoreErrorCallback(int error, sql::Statement* stmt) {
54}
55
56void 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
66void 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
[email protected]81a2a602013-07-17 19:10:3676#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.
79class ScopedUmaskSetter {
80 public:
81 explicit ScopedUmaskSetter(mode_t target_mask) {
82 old_umask_ = umask(target_mask);
83 }
84 ~ScopedUmaskSetter() { umask(old_umask_); }
85 private:
86 mode_t old_umask_;
87 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter);
88};
89#endif
90
[email protected]e5ffd0e42009-09-11 21:30:5691class SQLConnectionTest : public testing::Test {
92 public:
dcheng1b3b125e2014-12-22 23:00:2493 void SetUp() override {
[email protected]3a305db2011-04-12 13:40:5394 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]6ed6d14f2013-09-07 15:48:3695 db_path_ = temp_dir_.path().AppendASCII("SQLConnectionTest.db");
96 ASSERT_TRUE(db_.Open(db_path_));
[email protected]e5ffd0e42009-09-11 21:30:5697 }
98
dcheng1b3b125e2014-12-22 23:00:2499 void TearDown() override { db_.Close(); }
[email protected]e5ffd0e42009-09-11 21:30:56100
101 sql::Connection& db() { return db_; }
[email protected]6ed6d14f2013-09-07 15:48:36102 const base::FilePath& db_path() { return db_path_; }
[email protected]8e0c01282012-04-06 19:36:49103
[email protected]7bae5742013-07-10 20:46:16104 // Handle errors by blowing away the database.
105 void RazeErrorCallback(int expected_error, int error, sql::Statement* stmt) {
106 EXPECT_EQ(expected_error, error);
107 db_.RazeAndClose();
108 }
109
[email protected]e5ffd0e42009-09-11 21:30:56110 private:
[email protected]e5ffd0e42009-09-11 21:30:56111 sql::Connection db_;
[email protected]6ed6d14f2013-09-07 15:48:36112 base::FilePath db_path_;
113 base::ScopedTempDir temp_dir_;
[email protected]e5ffd0e42009-09-11 21:30:56114};
115
116TEST_F(SQLConnectionTest, Execute) {
117 // Valid statement should return true.
118 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
119 EXPECT_EQ(SQLITE_OK, db().GetErrorCode());
120
121 // Invalid statement should fail.
[email protected]eff1fa522011-12-12 23:50:59122 ASSERT_EQ(SQLITE_ERROR,
123 db().ExecuteAndReturnErrorCode("CREATE TAB foo (a, b"));
[email protected]e5ffd0e42009-09-11 21:30:56124 EXPECT_EQ(SQLITE_ERROR, db().GetErrorCode());
125}
126
[email protected]eff1fa522011-12-12 23:50:59127TEST_F(SQLConnectionTest, ExecuteWithErrorCode) {
128 ASSERT_EQ(SQLITE_OK,
129 db().ExecuteAndReturnErrorCode("CREATE TABLE foo (a, b)"));
130 ASSERT_EQ(SQLITE_ERROR,
131 db().ExecuteAndReturnErrorCode("CREATE TABLE TABLE"));
132 ASSERT_EQ(SQLITE_ERROR,
133 db().ExecuteAndReturnErrorCode(
134 "INSERT INTO foo(a, b) VALUES (1, 2, 3, 4)"));
135}
136
[email protected]e5ffd0e42009-09-11 21:30:56137TEST_F(SQLConnectionTest, CachedStatement) {
138 sql::StatementID id1("foo", 12);
139
140 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
141 ASSERT_TRUE(db().Execute("INSERT INTO foo(a, b) VALUES (12, 13)"));
142
143 // Create a new cached statement.
144 {
145 sql::Statement s(db().GetCachedStatement(id1, "SELECT a FROM foo"));
[email protected]eff1fa522011-12-12 23:50:59146 ASSERT_TRUE(s.is_valid());
[email protected]e5ffd0e42009-09-11 21:30:56147
148 ASSERT_TRUE(s.Step());
149 EXPECT_EQ(12, s.ColumnInt(0));
150 }
151
152 // The statement should be cached still.
153 EXPECT_TRUE(db().HasCachedStatement(id1));
154
155 {
156 // Get the same statement using different SQL. This should ignore our
157 // SQL and use the cached one (so it will be valid).
158 sql::Statement s(db().GetCachedStatement(id1, "something invalid("));
[email protected]eff1fa522011-12-12 23:50:59159 ASSERT_TRUE(s.is_valid());
[email protected]e5ffd0e42009-09-11 21:30:56160
161 ASSERT_TRUE(s.Step());
162 EXPECT_EQ(12, s.ColumnInt(0));
163 }
164
165 // Make sure other statements aren't marked as cached.
166 EXPECT_FALSE(db().HasCachedStatement(SQL_FROM_HERE));
167}
168
[email protected]eff1fa522011-12-12 23:50:59169TEST_F(SQLConnectionTest, IsSQLValidTest) {
170 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
171 ASSERT_TRUE(db().IsSQLValid("SELECT a FROM foo"));
172 ASSERT_FALSE(db().IsSQLValid("SELECT no_exist FROM foo"));
173}
174
[email protected]e5ffd0e42009-09-11 21:30:56175TEST_F(SQLConnectionTest, DoesStuffExist) {
176 // Test DoesTableExist.
177 EXPECT_FALSE(db().DoesTableExist("foo"));
178 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
179 EXPECT_TRUE(db().DoesTableExist("foo"));
180
181 // Should be case sensitive.
182 EXPECT_FALSE(db().DoesTableExist("FOO"));
183
184 // Test DoesColumnExist.
185 EXPECT_FALSE(db().DoesColumnExist("foo", "bar"));
186 EXPECT_TRUE(db().DoesColumnExist("foo", "a"));
187
[email protected]e7afe2452010-08-22 16:19:13188 // Testing for a column on a nonexistent table.
[email protected]e5ffd0e42009-09-11 21:30:56189 EXPECT_FALSE(db().DoesColumnExist("bar", "b"));
190}
191
192TEST_F(SQLConnectionTest, GetLastInsertRowId) {
193 ASSERT_TRUE(db().Execute("CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"));
194
195 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)"));
196
197 // Last insert row ID should be valid.
198 int64 row = db().GetLastInsertRowId();
199 EXPECT_LT(0, row);
200
201 // It should be the primary key of the row we just inserted.
202 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo WHERE id=?"));
203 s.BindInt64(0, row);
204 ASSERT_TRUE(s.Step());
205 EXPECT_EQ(12, s.ColumnInt(0));
206}
[email protected]44ad7d902012-03-23 00:09:05207
208TEST_F(SQLConnectionTest, Rollback) {
209 ASSERT_TRUE(db().BeginTransaction());
210 ASSERT_TRUE(db().BeginTransaction());
211 EXPECT_EQ(2, db().transaction_nesting());
212 db().RollbackTransaction();
213 EXPECT_FALSE(db().CommitTransaction());
214 EXPECT_TRUE(db().BeginTransaction());
215}
[email protected]8e0c01282012-04-06 19:36:49216
[email protected]4350e322013-06-18 22:18:10217// Test the scoped error ignorer by attempting to insert a duplicate
218// value into an index.
219TEST_F(SQLConnectionTest, ScopedIgnoreError) {
220 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
221 ASSERT_TRUE(db().Execute(kCreateSql));
222 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
223
224 sql::ScopedErrorIgnorer ignore_errors;
225 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
226 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
227 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
228}
229
[email protected]98cf3002013-07-12 01:38:56230TEST_F(SQLConnectionTest, ErrorCallback) {
231 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
232 ASSERT_TRUE(db().Execute(kCreateSql));
233 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
234
235 int error = SQLITE_OK;
236 {
237 sql::ScopedErrorCallback sec(
238 &db(), base::Bind(&sql::CaptureErrorCallback, &error));
[email protected]98cf3002013-07-12 01:38:56239 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
Scott Hessdcf120482015-02-10 21:33:29240
241 // Later versions of SQLite throw SQLITE_CONSTRAINT_UNIQUE. The specific
242 // sub-error isn't really important.
243 EXPECT_EQ(SQLITE_CONSTRAINT, (error&0xff));
[email protected]98cf3002013-07-12 01:38:56244 }
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
[email protected]81a2a602013-07-17 19:10:36257 // 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.
[email protected]98cf3002013-07-12 01:38:56260 //
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
[email protected]8e0c01282012-04-06 19:36:49285// 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
[email protected]69c58452012-08-06 19:22:42292 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
[email protected]8e0c01282012-04-06 19:36:49303 {
304 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count"));
305 ASSERT_TRUE(s.Step());
[email protected]69c58452012-08-06 19:22:42306 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(0));
[email protected]8e0c01282012-04-06 19:36:49307 }
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));
[email protected]69c58452012-08-06 19:22:42315 // Table "foo" is stored in the last page of the file.
316 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(3));
[email protected]8e0c01282012-04-06 19:36:49317 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
[email protected]7bae5742013-07-10 20:46:16328 ASSERT_EQ(0, SqliteMasterCount(&db()));
[email protected]69c58452012-08-06 19:22:42329
330 {
331 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum"));
332 ASSERT_TRUE(s.Step());
[email protected]6d42f152012-11-10 00:38:24333 // The new database has the same auto_vacuum as a fresh database.
[email protected]69c58452012-08-06 19:22:42334 EXPECT_EQ(pragma_auto_vacuum, s.ColumnInt(0));
335 }
[email protected]8e0c01282012-04-06 19:36:49336}
337
338// Test that Raze() maintains page_size.
339TEST_F(SQLConnectionTest, RazePageSize) {
[email protected]e73e89222012-07-13 18:55:22340 // Fetch the default page size and double it for use in this test.
[email protected]8e0c01282012-04-06 19:36:49341 // Scoped to release statement before Close().
[email protected]e73e89222012-07-13 18:55:22342 int default_page_size = 0;
[email protected]8e0c01282012-04-06 19:36:49343 {
344 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size"));
345 ASSERT_TRUE(s.Step());
[email protected]e73e89222012-07-13 18:55:22346 default_page_size = s.ColumnInt(0);
[email protected]8e0c01282012-04-06 19:36:49347 }
[email protected]e73e89222012-07-13 18:55:22348 ASSERT_GT(default_page_size, 0);
349 const int kPageSize = 2 * default_page_size;
[email protected]8e0c01282012-04-06 19:36:49350
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());
[email protected]389e0a42012-04-25 21:36:41363 s.Reset(true);
[email protected]8e0c01282012-04-06 19:36:49364 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.
[email protected]7bae5742013-07-10 20:46:16377 ASSERT_EQ(1, SqliteMasterCount(&other_db));
[email protected]8e0c01282012-04-06 19:36:49378
379 ASSERT_TRUE(db().Raze());
380
381 // The second connection sees the updated database.
[email protected]7bae5742013-07-10 20:46:16382 ASSERT_EQ(0, SqliteMasterCount(&other_db));
[email protected]8e0c01282012-04-06 19:36:49383}
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
[email protected]7bae5742013-07-10 20:46:16420// 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 {
[email protected]b9b4a572014-03-17 23:11:12428 base::ScopedFILE file(base::OpenFile(db_path(), "rb+"));
[email protected]7bae5742013-07-10 20:46:16429 ASSERT_TRUE(file.get() != NULL);
430 ASSERT_EQ(0, fseek(file.get(), 0, SEEK_SET));
[email protected]7600d0b2013-12-08 21:43:30431 ASSERT_TRUE(base::TruncateFile(file.get()));
[email protected]7bae5742013-07-10 20:46:16432 }
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());
[email protected]7567484142013-07-11 17:36:07443 ASSERT_FALSE(base::PathExists(db_path()));
[email protected]7bae5742013-07-10 20:46:16444
445 {
[email protected]b9b4a572014-03-17 23:11:12446 base::ScopedFILE file(base::OpenFile(db_path(), "wb"));
[email protected]7bae5742013-07-10 20:46:16447 ASSERT_TRUE(file.get() != NULL);
448
449 const char* kJunk = "This is the hour of our discontent.";
450 fputs(kJunk, file.get());
451 }
[email protected]7567484142013-07-11 17:36:07452 ASSERT_TRUE(base::PathExists(db_path()));
[email protected]7bae5742013-07-10 20:46:16453
Scott Hessdcf120482015-02-10 21:33:29454 // SQLite will successfully open the handle, but fail when running PRAGMA
455 // statements that access the database.
[email protected]7bae5742013-07-10 20:46:16456 {
457 sql::ScopedErrorIgnorer ignore_errors;
Scott Hessdcf120482015-02-10 21:33:29458
459 // Earlier versions of Chromium compiled against SQLite 3.6.7.3, which
460 // returned SQLITE_IOERR_SHORT_READ in this case. Some platforms may still
461 // compile against an earlier SQLite via USE_SYSTEM_SQLITE.
462 if (ignore_errors.SQLiteLibVersionNumber() < 3008007) {
463 ignore_errors.IgnoreError(SQLITE_IOERR_SHORT_READ);
464 } else {
465 ignore_errors.IgnoreError(SQLITE_NOTADB);
466 }
467
[email protected]7bae5742013-07-10 20:46:16468 EXPECT_TRUE(db().Open(db_path()));
469 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
470 }
471 EXPECT_TRUE(db().Raze());
472 db().Close();
473
474 // Now empty, the open should open an empty database.
475 EXPECT_TRUE(db().Open(db_path()));
476 EXPECT_EQ(0, SqliteMasterCount(&db()));
477}
478
479// Verify that Raze() can handle a database overwritten with garbage.
480TEST_F(SQLConnectionTest, RazeNOTADB2) {
481 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
482 ASSERT_TRUE(db().Execute(kCreateSql));
483 ASSERT_EQ(1, SqliteMasterCount(&db()));
484 db().Close();
485
486 {
[email protected]b9b4a572014-03-17 23:11:12487 base::ScopedFILE file(base::OpenFile(db_path(), "rb+"));
[email protected]7bae5742013-07-10 20:46:16488 ASSERT_TRUE(file.get() != NULL);
489 ASSERT_EQ(0, fseek(file.get(), 0, SEEK_SET));
490
491 const char* kJunk = "This is the hour of our discontent.";
492 fputs(kJunk, file.get());
493 }
494
495 // SQLite will successfully open the handle, but will fail with
496 // SQLITE_NOTADB on pragma statemenets which attempt to read the
497 // corrupted header.
498 {
499 sql::ScopedErrorIgnorer ignore_errors;
500 ignore_errors.IgnoreError(SQLITE_NOTADB);
501 EXPECT_TRUE(db().Open(db_path()));
502 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
503 }
504 EXPECT_TRUE(db().Raze());
505 db().Close();
506
507 // Now empty, the open should succeed with an empty database.
508 EXPECT_TRUE(db().Open(db_path()));
509 EXPECT_EQ(0, SqliteMasterCount(&db()));
510}
511
512// Test that a callback from Open() can raze the database. This is
513// essential for cases where the Open() can fail entirely, so the
[email protected]fed734a2013-07-17 04:45:13514// Raze() cannot happen later. Additionally test that when the
515// callback does this during Open(), the open is retried and succeeds.
[email protected]fed734a2013-07-17 04:45:13516TEST_F(SQLConnectionTest, RazeCallbackReopen) {
[email protected]7bae5742013-07-10 20:46:16517 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
518 ASSERT_TRUE(db().Execute(kCreateSql));
519 ASSERT_EQ(1, SqliteMasterCount(&db()));
[email protected]7bae5742013-07-10 20:46:16520 db().Close();
521
[email protected]a8848a72013-11-18 04:18:47522 // Corrupt the database so that nothing works, including PRAGMAs.
523 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path()));
[email protected]7bae5742013-07-10 20:46:16524
[email protected]fed734a2013-07-17 04:45:13525 // Open() will succeed, even though the PRAGMA calls within will
526 // fail with SQLITE_CORRUPT, as will this PRAGMA.
527 {
528 sql::ScopedErrorIgnorer ignore_errors;
529 ignore_errors.IgnoreError(SQLITE_CORRUPT);
530 ASSERT_TRUE(db().Open(db_path()));
531 ASSERT_FALSE(db().Execute("PRAGMA auto_vacuum"));
532 db().Close();
533 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
534 }
535
[email protected]7bae5742013-07-10 20:46:16536 db().set_error_callback(base::Bind(&SQLConnectionTest::RazeErrorCallback,
537 base::Unretained(this),
538 SQLITE_CORRUPT));
539
[email protected]fed734a2013-07-17 04:45:13540 // When the PRAGMA calls in Open() raise SQLITE_CORRUPT, the error
541 // callback will call RazeAndClose(). Open() will then fail and be
542 // retried. The second Open() on the empty database will succeed
543 // cleanly.
544 ASSERT_TRUE(db().Open(db_path()));
545 ASSERT_TRUE(db().Execute("PRAGMA auto_vacuum"));
[email protected]7bae5742013-07-10 20:46:16546 EXPECT_EQ(0, SqliteMasterCount(&db()));
547}
548
[email protected]41a97c812013-02-07 02:35:38549// Basic test of RazeAndClose() operation.
550TEST_F(SQLConnectionTest, RazeAndClose) {
551 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
552 const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)";
553
554 // Test that RazeAndClose() closes the database, and that the
555 // database is empty when re-opened.
556 ASSERT_TRUE(db().Execute(kCreateSql));
557 ASSERT_TRUE(db().Execute(kPopulateSql));
558 ASSERT_TRUE(db().RazeAndClose());
559 ASSERT_FALSE(db().is_open());
560 db().Close();
561 ASSERT_TRUE(db().Open(db_path()));
[email protected]7bae5742013-07-10 20:46:16562 ASSERT_EQ(0, SqliteMasterCount(&db()));
[email protected]41a97c812013-02-07 02:35:38563
564 // Test that RazeAndClose() can break transactions.
565 ASSERT_TRUE(db().Execute(kCreateSql));
566 ASSERT_TRUE(db().Execute(kPopulateSql));
567 ASSERT_TRUE(db().BeginTransaction());
568 ASSERT_TRUE(db().RazeAndClose());
569 ASSERT_FALSE(db().is_open());
570 ASSERT_FALSE(db().CommitTransaction());
571 db().Close();
572 ASSERT_TRUE(db().Open(db_path()));
[email protected]7bae5742013-07-10 20:46:16573 ASSERT_EQ(0, SqliteMasterCount(&db()));
[email protected]41a97c812013-02-07 02:35:38574}
575
576// Test that various operations fail without crashing after
577// RazeAndClose().
578TEST_F(SQLConnectionTest, RazeAndCloseDiagnostics) {
579 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
580 const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)";
581 const char* kSimpleSql = "SELECT 1";
582
583 ASSERT_TRUE(db().Execute(kCreateSql));
584 ASSERT_TRUE(db().Execute(kPopulateSql));
585
586 // Test baseline expectations.
587 db().Preload();
588 ASSERT_TRUE(db().DoesTableExist("foo"));
589 ASSERT_TRUE(db().IsSQLValid(kSimpleSql));
590 ASSERT_EQ(SQLITE_OK, db().ExecuteAndReturnErrorCode(kSimpleSql));
591 ASSERT_TRUE(db().Execute(kSimpleSql));
592 ASSERT_TRUE(db().is_open());
593 {
594 sql::Statement s(db().GetUniqueStatement(kSimpleSql));
595 ASSERT_TRUE(s.Step());
596 }
597 {
598 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
599 ASSERT_TRUE(s.Step());
600 }
601 ASSERT_TRUE(db().BeginTransaction());
602 ASSERT_TRUE(db().CommitTransaction());
603 ASSERT_TRUE(db().BeginTransaction());
604 db().RollbackTransaction();
605
606 ASSERT_TRUE(db().RazeAndClose());
607
608 // At this point, they should all fail, but not crash.
609 db().Preload();
610 ASSERT_FALSE(db().DoesTableExist("foo"));
611 ASSERT_FALSE(db().IsSQLValid(kSimpleSql));
612 ASSERT_EQ(SQLITE_ERROR, db().ExecuteAndReturnErrorCode(kSimpleSql));
613 ASSERT_FALSE(db().Execute(kSimpleSql));
614 ASSERT_FALSE(db().is_open());
615 {
616 sql::Statement s(db().GetUniqueStatement(kSimpleSql));
617 ASSERT_FALSE(s.Step());
618 }
619 {
620 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
621 ASSERT_FALSE(s.Step());
622 }
623 ASSERT_FALSE(db().BeginTransaction());
624 ASSERT_FALSE(db().CommitTransaction());
625 ASSERT_FALSE(db().BeginTransaction());
626 db().RollbackTransaction();
627
628 // Close normally to reset the poisoned flag.
629 db().Close();
630
631 // DEATH tests not supported on Android or iOS.
632#if !defined(OS_ANDROID) && !defined(OS_IOS)
633 // Once the real Close() has been called, various calls enforce API
634 // usage by becoming fatal in debug mode. Since DEATH tests are
635 // expensive, just test one of them.
636 if (DLOG_IS_ON(FATAL)) {
637 ASSERT_DEATH({
638 db().IsSQLValid(kSimpleSql);
639 }, "Illegal use of connection without a db");
640 }
641#endif
642}
643
644// TODO(shess): Spin up a background thread to hold other_db, to more
645// closely match real life. That would also allow testing
646// RazeWithTimeout().
647
[email protected]1348765a2012-07-24 08:25:53648#if defined(OS_ANDROID)
649TEST_F(SQLConnectionTest, SetTempDirForSQL) {
650
651 sql::MetaTable meta_table;
652 // Below call needs a temporary directory in sqlite3
653 // On Android, it can pass only when the temporary directory is set.
654 // Otherwise, sqlite3 doesn't find the correct directory to store
655 // temporary files and will report the error 'unable to open
656 // database file'.
657 ASSERT_TRUE(meta_table.Init(&db(), 4, 4));
658}
659#endif
[email protected]8d2e39e2013-06-24 05:55:08660
661TEST_F(SQLConnectionTest, Delete) {
662 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
663 db().Close();
664
665 // Should have both a main database file and a journal file because
666 // of journal_mode PERSIST.
667 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
[email protected]7567484142013-07-11 17:36:07668 ASSERT_TRUE(base::PathExists(db_path()));
669 ASSERT_TRUE(base::PathExists(journal));
[email protected]8d2e39e2013-06-24 05:55:08670
671 sql::Connection::Delete(db_path());
[email protected]7567484142013-07-11 17:36:07672 EXPECT_FALSE(base::PathExists(db_path()));
673 EXPECT_FALSE(base::PathExists(journal));
[email protected]8d2e39e2013-06-24 05:55:08674}
[email protected]7bae5742013-07-10 20:46:16675
[email protected]81a2a602013-07-17 19:10:36676#if defined(OS_POSIX)
677// Test that set_restrict_to_user() trims database permissions so that
678// only the owner (and root) can read.
679TEST_F(SQLConnectionTest, UserPermission) {
680 // If the bots all had a restrictive umask setting such that
681 // databases are always created with only the owner able to read
682 // them, then the code could break without breaking the tests.
683 // Temporarily provide a more permissive umask.
684 db().Close();
685 sql::Connection::Delete(db_path());
686 ASSERT_FALSE(base::PathExists(db_path()));
687 ScopedUmaskSetter permissive_umask(S_IWGRP | S_IWOTH);
688 ASSERT_TRUE(db().Open(db_path()));
689
690 // Cause the journal file to be created. If the default
691 // journal_mode is changed back to DELETE, then parts of this test
692 // will need to be updated.
693 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
694
695 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
696 int mode;
697
698 // Given a permissive umask, the database is created with permissive
699 // read access for the database and journal.
700 ASSERT_TRUE(base::PathExists(db_path()));
701 ASSERT_TRUE(base::PathExists(journal));
[email protected]b264eab2013-11-27 23:22:08702 mode = base::FILE_PERMISSION_MASK;
703 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
704 ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode);
705 mode = base::FILE_PERMISSION_MASK;
706 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
707 ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36708
709 // Re-open with restricted permissions and verify that the modes
710 // changed for both the main database and the journal.
711 db().Close();
712 db().set_restrict_to_user();
713 ASSERT_TRUE(db().Open(db_path()));
714 ASSERT_TRUE(base::PathExists(db_path()));
715 ASSERT_TRUE(base::PathExists(journal));
[email protected]b264eab2013-11-27 23:22:08716 mode = base::FILE_PERMISSION_MASK;
717 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
718 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
719 mode = base::FILE_PERMISSION_MASK;
720 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
721 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36722
723 // Delete and re-create the database, the restriction should still apply.
724 db().Close();
725 sql::Connection::Delete(db_path());
726 ASSERT_TRUE(db().Open(db_path()));
727 ASSERT_TRUE(base::PathExists(db_path()));
728 ASSERT_FALSE(base::PathExists(journal));
[email protected]b264eab2013-11-27 23:22:08729 mode = base::FILE_PERMISSION_MASK;
730 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
731 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36732
733 // Verify that journal creation inherits the restriction.
734 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
735 ASSERT_TRUE(base::PathExists(journal));
[email protected]b264eab2013-11-27 23:22:08736 mode = base::FILE_PERMISSION_MASK;
737 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
738 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36739}
740#endif // defined(OS_POSIX)
741
[email protected]8d409412013-07-19 18:25:30742// Test that errors start happening once Poison() is called.
743TEST_F(SQLConnectionTest, Poison) {
744 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
745
746 // Before the Poison() call, things generally work.
747 EXPECT_TRUE(db().IsSQLValid("INSERT INTO x VALUES ('x')"));
748 EXPECT_TRUE(db().Execute("INSERT INTO x VALUES ('x')"));
749 {
750 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
751 ASSERT_TRUE(s.is_valid());
752 ASSERT_TRUE(s.Step());
753 }
754
755 // Get a statement which is valid before and will exist across Poison().
756 sql::Statement valid_statement(
757 db().GetUniqueStatement("SELECT COUNT(*) FROM sqlite_master"));
758 ASSERT_TRUE(valid_statement.is_valid());
759 ASSERT_TRUE(valid_statement.Step());
760 valid_statement.Reset(true);
761
762 db().Poison();
763
764 // After the Poison() call, things fail.
765 EXPECT_FALSE(db().IsSQLValid("INSERT INTO x VALUES ('x')"));
766 EXPECT_FALSE(db().Execute("INSERT INTO x VALUES ('x')"));
767 {
768 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
769 ASSERT_FALSE(s.is_valid());
770 ASSERT_FALSE(s.Step());
771 }
772
773 // The existing statement has become invalid.
774 ASSERT_FALSE(valid_statement.is_valid());
775 ASSERT_FALSE(valid_statement.Step());
776}
777
778// Test attaching and detaching databases from the connection.
779TEST_F(SQLConnectionTest, Attach) {
780 EXPECT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
781
782 // Create a database to attach to.
783 base::FilePath attach_path =
784 db_path().DirName().AppendASCII("SQLConnectionAttach.db");
785 const char kAttachmentPoint[] = "other";
786 {
787 sql::Connection other_db;
788 ASSERT_TRUE(other_db.Open(attach_path));
789 EXPECT_TRUE(other_db.Execute("CREATE TABLE bar (a, b)"));
790 EXPECT_TRUE(other_db.Execute("INSERT INTO bar VALUES ('hello', 'world')"));
791 }
792
793 // Cannot see the attached database, yet.
794 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
795
796 // Attach fails in a transaction.
797 EXPECT_TRUE(db().BeginTransaction());
798 {
799 sql::ScopedErrorIgnorer ignore_errors;
800 ignore_errors.IgnoreError(SQLITE_ERROR);
801 EXPECT_FALSE(db().AttachDatabase(attach_path, kAttachmentPoint));
802 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
803 }
804
805 // Attach succeeds when the transaction is closed.
806 db().RollbackTransaction();
807 EXPECT_TRUE(db().AttachDatabase(attach_path, kAttachmentPoint));
808 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
809
810 // Queries can touch both databases.
811 EXPECT_TRUE(db().Execute("INSERT INTO foo SELECT a, b FROM other.bar"));
812 {
813 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM foo"));
814 ASSERT_TRUE(s.Step());
815 EXPECT_EQ(1, s.ColumnInt(0));
816 }
817
818 // Detach also fails in a transaction.
819 EXPECT_TRUE(db().BeginTransaction());
820 {
821 sql::ScopedErrorIgnorer ignore_errors;
822 ignore_errors.IgnoreError(SQLITE_ERROR);
823 EXPECT_FALSE(db().DetachDatabase(kAttachmentPoint));
824 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
825 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
826 }
827
828 // Detach succeeds outside of a transaction.
829 db().RollbackTransaction();
830 EXPECT_TRUE(db().DetachDatabase(kAttachmentPoint));
831
832 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
833}
834
[email protected]579446c2013-12-16 18:36:52835TEST_F(SQLConnectionTest, Basic_QuickIntegrityCheck) {
836 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
837 ASSERT_TRUE(db().Execute(kCreateSql));
838 EXPECT_TRUE(db().QuickIntegrityCheck());
839 db().Close();
840
841 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path()));
842
843 {
844 sql::ScopedErrorIgnorer ignore_errors;
845 ignore_errors.IgnoreError(SQLITE_CORRUPT);
846 ASSERT_TRUE(db().Open(db_path()));
847 EXPECT_FALSE(db().QuickIntegrityCheck());
848 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
849 }
850}
851
852TEST_F(SQLConnectionTest, Basic_FullIntegrityCheck) {
853 const std::string kOk("ok");
854 std::vector<std::string> messages;
855
856 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
857 ASSERT_TRUE(db().Execute(kCreateSql));
858 EXPECT_TRUE(db().FullIntegrityCheck(&messages));
859 EXPECT_EQ(1u, messages.size());
860 EXPECT_EQ(kOk, messages[0]);
861 db().Close();
862
863 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path()));
864
865 {
866 sql::ScopedErrorIgnorer ignore_errors;
867 ignore_errors.IgnoreError(SQLITE_CORRUPT);
868 ASSERT_TRUE(db().Open(db_path()));
869 EXPECT_TRUE(db().FullIntegrityCheck(&messages));
870 EXPECT_LT(1u, messages.size());
871 EXPECT_NE(kOk, messages[0]);
872 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
873 }
874
875 // TODO(shess): CorruptTableOrIndex could be used to produce a
876 // file that would pass the quick check and fail the full check.
877}
878
[email protected]7bae5742013-07-10 20:46:16879} // namespace