blob: c0a06410f19f8928e26638f864ac24e40425db79 [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"
[email protected]e5ffd0e42009-09-11 21:30:566#include "base/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:
[email protected]3dbbf7d2013-02-06 18:13:5393 virtual void SetUp() {
[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
[email protected]3dbbf7d2013-02-06 18:13:5399 virtual void TearDown() {
[email protected]e5ffd0e42009-09-11 21:30:56100 db_.Close();
[email protected]e5ffd0e42009-09-11 21:30:56101 }
102
103 sql::Connection& db() { return db_; }
[email protected]6ed6d14f2013-09-07 15:48:36104 const base::FilePath& db_path() { return db_path_; }
[email protected]8e0c01282012-04-06 19:36:49105
[email protected]7bae5742013-07-10 20:46:16106 // Handle errors by blowing away the database.
107 void RazeErrorCallback(int expected_error, int error, sql::Statement* stmt) {
108 EXPECT_EQ(expected_error, error);
109 db_.RazeAndClose();
110 }
111
[email protected]e5ffd0e42009-09-11 21:30:56112 private:
[email protected]e5ffd0e42009-09-11 21:30:56113 sql::Connection db_;
[email protected]6ed6d14f2013-09-07 15:48:36114 base::FilePath db_path_;
115 base::ScopedTempDir temp_dir_;
[email protected]e5ffd0e42009-09-11 21:30:56116};
117
118TEST_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.
[email protected]eff1fa522011-12-12 23:50:59124 ASSERT_EQ(SQLITE_ERROR,
125 db().ExecuteAndReturnErrorCode("CREATE TAB foo (a, b"));
[email protected]e5ffd0e42009-09-11 21:30:56126 EXPECT_EQ(SQLITE_ERROR, db().GetErrorCode());
127}
128
[email protected]eff1fa522011-12-12 23:50:59129TEST_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
[email protected]e5ffd0e42009-09-11 21:30:56139TEST_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"));
[email protected]eff1fa522011-12-12 23:50:59148 ASSERT_TRUE(s.is_valid());
[email protected]e5ffd0e42009-09-11 21:30:56149
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("));
[email protected]eff1fa522011-12-12 23:50:59161 ASSERT_TRUE(s.is_valid());
[email protected]e5ffd0e42009-09-11 21:30:56162
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
[email protected]eff1fa522011-12-12 23:50:59171TEST_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
[email protected]e5ffd0e42009-09-11 21:30:56177TEST_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
[email protected]e7afe2452010-08-22 16:19:13190 // Testing for a column on a nonexistent table.
[email protected]e5ffd0e42009-09-11 21:30:56191 EXPECT_FALSE(db().DoesColumnExist("bar", "b"));
192}
193
194TEST_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}
[email protected]44ad7d902012-03-23 00:09:05209
210TEST_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}
[email protected]8e0c01282012-04-06 19:36:49218
[email protected]4350e322013-06-18 22:18:10219// Test the scoped error ignorer by attempting to insert a duplicate
220// value into an index.
221TEST_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
[email protected]98cf3002013-07-12 01:38:56232TEST_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));
[email protected]98cf3002013-07-12 01:38:56241 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
[email protected]81a2a602013-07-17 19:10:36256 // 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.
[email protected]98cf3002013-07-12 01:38:56259 //
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
[email protected]8e0c01282012-04-06 19:36:49284// Test that sql::Connection::Raze() results in a database without the
285// tables from the original database.
286TEST_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
[email protected]69c58452012-08-06 19:22:42291 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
[email protected]8e0c01282012-04-06 19:36:49302 {
303 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count"));
304 ASSERT_TRUE(s.Step());
[email protected]69c58452012-08-06 19:22:42305 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(0));
[email protected]8e0c01282012-04-06 19:36:49306 }
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));
[email protected]69c58452012-08-06 19:22:42314 // Table "foo" is stored in the last page of the file.
315 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(3));
[email protected]8e0c01282012-04-06 19:36:49316 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
[email protected]7bae5742013-07-10 20:46:16327 ASSERT_EQ(0, SqliteMasterCount(&db()));
[email protected]69c58452012-08-06 19:22:42328
329 {
330 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum"));
331 ASSERT_TRUE(s.Step());
[email protected]6d42f152012-11-10 00:38:24332 // The new database has the same auto_vacuum as a fresh database.
[email protected]69c58452012-08-06 19:22:42333 EXPECT_EQ(pragma_auto_vacuum, s.ColumnInt(0));
334 }
[email protected]8e0c01282012-04-06 19:36:49335}
336
337// Test that Raze() maintains page_size.
338TEST_F(SQLConnectionTest, RazePageSize) {
[email protected]e73e89222012-07-13 18:55:22339 // Fetch the default page size and double it for use in this test.
[email protected]8e0c01282012-04-06 19:36:49340 // Scoped to release statement before Close().
[email protected]e73e89222012-07-13 18:55:22341 int default_page_size = 0;
[email protected]8e0c01282012-04-06 19:36:49342 {
343 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size"));
344 ASSERT_TRUE(s.Step());
[email protected]e73e89222012-07-13 18:55:22345 default_page_size = s.ColumnInt(0);
[email protected]8e0c01282012-04-06 19:36:49346 }
[email protected]e73e89222012-07-13 18:55:22347 ASSERT_GT(default_page_size, 0);
348 const int kPageSize = 2 * default_page_size;
[email protected]8e0c01282012-04-06 19:36:49349
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());
[email protected]389e0a42012-04-25 21:36:41362 s.Reset(true);
[email protected]8e0c01282012-04-06 19:36:49363 ASSERT_TRUE(s.Step());
364 ASSERT_EQ(kPageSize, s.ColumnInt(0));
365}
366
367// Test that Raze() results are seen in other connections.
368TEST_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.
[email protected]7bae5742013-07-10 20:46:16376 ASSERT_EQ(1, SqliteMasterCount(&other_db));
[email protected]8e0c01282012-04-06 19:36:49377
378 ASSERT_TRUE(db().Raze());
379
380 // The second connection sees the updated database.
[email protected]7bae5742013-07-10 20:46:16381 ASSERT_EQ(0, SqliteMasterCount(&other_db));
[email protected]8e0c01282012-04-06 19:36:49382}
383
384TEST_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
[email protected]7bae5742013-07-10 20:46:16419// Verify that Raze() can handle an empty file. SQLite should treat
420// this as an empty database.
421TEST_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 {
[email protected]b9b4a572014-03-17 23:11:12427 base::ScopedFILE file(base::OpenFile(db_path(), "rb+"));
[email protected]7bae5742013-07-10 20:46:16428 ASSERT_TRUE(file.get() != NULL);
429 ASSERT_EQ(0, fseek(file.get(), 0, SEEK_SET));
[email protected]7600d0b2013-12-08 21:43:30430 ASSERT_TRUE(base::TruncateFile(file.get()));
[email protected]7bae5742013-07-10 20:46:16431 }
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.
439TEST_F(SQLConnectionTest, RazeNOTADB) {
440 db().Close();
441 sql::Connection::Delete(db_path());
[email protected]7567484142013-07-11 17:36:07442 ASSERT_FALSE(base::PathExists(db_path()));
[email protected]7bae5742013-07-10 20:46:16443
444 {
[email protected]b9b4a572014-03-17 23:11:12445 base::ScopedFILE file(base::OpenFile(db_path(), "wb"));
[email protected]7bae5742013-07-10 20:46:16446 ASSERT_TRUE(file.get() != NULL);
447
448 const char* kJunk = "This is the hour of our discontent.";
449 fputs(kJunk, file.get());
450 }
[email protected]7567484142013-07-11 17:36:07451 ASSERT_TRUE(base::PathExists(db_path()));
[email protected]7bae5742013-07-10 20:46:16452
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.
471TEST_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 {
[email protected]b9b4a572014-03-17 23:11:12478 base::ScopedFILE file(base::OpenFile(db_path(), "rb+"));
[email protected]7bae5742013-07-10 20:46:16479 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
[email protected]fed734a2013-07-17 04:45:13505// Raze() cannot happen later. Additionally test that when the
506// callback does this during Open(), the open is retried and succeeds.
[email protected]fed734a2013-07-17 04:45:13507TEST_F(SQLConnectionTest, RazeCallbackReopen) {
[email protected]7bae5742013-07-10 20:46:16508 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
509 ASSERT_TRUE(db().Execute(kCreateSql));
510 ASSERT_EQ(1, SqliteMasterCount(&db()));
[email protected]7bae5742013-07-10 20:46:16511 db().Close();
512
[email protected]a8848a72013-11-18 04:18:47513 // Corrupt the database so that nothing works, including PRAGMAs.
514 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path()));
[email protected]7bae5742013-07-10 20:46:16515
[email protected]fed734a2013-07-17 04:45:13516 // 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
[email protected]7bae5742013-07-10 20:46:16527 db().set_error_callback(base::Bind(&SQLConnectionTest::RazeErrorCallback,
528 base::Unretained(this),
529 SQLITE_CORRUPT));
530
[email protected]fed734a2013-07-17 04:45:13531 // 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"));
[email protected]7bae5742013-07-10 20:46:16537 EXPECT_EQ(0, SqliteMasterCount(&db()));
538}
539
[email protected]41a97c812013-02-07 02:35:38540// Basic test of RazeAndClose() operation.
541TEST_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()));
[email protected]7bae5742013-07-10 20:46:16553 ASSERT_EQ(0, SqliteMasterCount(&db()));
[email protected]41a97c812013-02-07 02:35:38554
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()));
[email protected]7bae5742013-07-10 20:46:16564 ASSERT_EQ(0, SqliteMasterCount(&db()));
[email protected]41a97c812013-02-07 02:35:38565}
566
567// Test that various operations fail without crashing after
568// RazeAndClose().
569TEST_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
[email protected]1348765a2012-07-24 08:25:53639#if defined(OS_ANDROID)
640TEST_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
[email protected]8d2e39e2013-06-24 05:55:08651
652TEST_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"));
[email protected]7567484142013-07-11 17:36:07659 ASSERT_TRUE(base::PathExists(db_path()));
660 ASSERT_TRUE(base::PathExists(journal));
[email protected]8d2e39e2013-06-24 05:55:08661
662 sql::Connection::Delete(db_path());
[email protected]7567484142013-07-11 17:36:07663 EXPECT_FALSE(base::PathExists(db_path()));
664 EXPECT_FALSE(base::PathExists(journal));
[email protected]8d2e39e2013-06-24 05:55:08665}
[email protected]7bae5742013-07-10 20:46:16666
[email protected]81a2a602013-07-17 19:10:36667#if defined(OS_POSIX)
668// Test that set_restrict_to_user() trims database permissions so that
669// only the owner (and root) can read.
670TEST_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));
[email protected]b264eab2013-11-27 23:22:08693 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);
[email protected]81a2a602013-07-17 19:10:36699
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));
[email protected]b264eab2013-11-27 23:22:08707 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);
[email protected]81a2a602013-07-17 19:10:36713
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));
[email protected]b264eab2013-11-27 23:22:08720 mode = base::FILE_PERMISSION_MASK;
721 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
722 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36723
724 // Verify that journal creation inherits the restriction.
725 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
726 ASSERT_TRUE(base::PathExists(journal));
[email protected]b264eab2013-11-27 23:22:08727 mode = base::FILE_PERMISSION_MASK;
728 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
729 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36730}
731#endif // defined(OS_POSIX)
732
[email protected]8d409412013-07-19 18:25:30733// Test that errors start happening once Poison() is called.
734TEST_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.
770TEST_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
[email protected]579446c2013-12-16 18:36:52826TEST_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
843TEST_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
[email protected]7bae5742013-07-10 20:46:16870} // namespace