Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(160)

Side by Side Diff: sql/sqlite_features_unittest.cc

Issue 2827673006: [sql] Verify control of close-time WAL checkpoint. (Closed)
Patch Set: comment tweaks Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sql/connection.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stddef.h> 5 #include <stddef.h>
6 #include <stdint.h> 6 #include <stdint.h>
7 7
8 #include <string> 8 #include <string>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 14 matching lines...) Expand all
25 #if defined(OS_MACOSX) && !defined(OS_IOS) 25 #if defined(OS_MACOSX) && !defined(OS_IOS)
26 #include <CoreFoundation/CoreFoundation.h> 26 #include <CoreFoundation/CoreFoundation.h>
27 #include <CoreServices/CoreServices.h> 27 #include <CoreServices/CoreServices.h>
28 28
29 #include "base/mac/mac_util.h" 29 #include "base/mac/mac_util.h"
30 #include "base/mac/scoped_cftyperef.h" 30 #include "base/mac/scoped_cftyperef.h"
31 #endif 31 #endif
32 32
33 // Test that certain features are/are-not enabled in our SQLite. 33 // Test that certain features are/are-not enabled in our SQLite.
34 34
35 namespace sql {
35 namespace { 36 namespace {
36 37
38 using sql::test::ExecuteWithResult;
39 using sql::test::ExecuteWithResults;
40
37 void CaptureErrorCallback(int* error_pointer, std::string* sql_text, 41 void CaptureErrorCallback(int* error_pointer, std::string* sql_text,
38 int error, sql::Statement* stmt) { 42 int error, sql::Statement* stmt) {
39 *error_pointer = error; 43 *error_pointer = error;
40 const char* text = stmt ? stmt->GetSQLStatement() : NULL; 44 const char* text = stmt ? stmt->GetSQLStatement() : NULL;
41 *sql_text = text ? text : "no statement available"; 45 *sql_text = text ? text : "no statement available";
42 } 46 }
43 47
48 } // namespace
49
44 class SQLiteFeaturesTest : public sql::SQLTestBase { 50 class SQLiteFeaturesTest : public sql::SQLTestBase {
45 public: 51 public:
46 SQLiteFeaturesTest() : error_(SQLITE_OK) {} 52 SQLiteFeaturesTest() : error_(SQLITE_OK) {}
47 53
48 void SetUp() override { 54 void SetUp() override {
49 SQLTestBase::SetUp(); 55 SQLTestBase::SetUp();
50 56
51 // The error delegate will set |error_| and |sql_text_| when any sqlite 57 // The error delegate will set |error_| and |sql_text_| when any sqlite
52 // statement operation returns an error code. 58 // statement operation returns an error code.
53 db().set_error_callback( 59 db().set_error_callback(
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 // Originally history used fts2, which Chromium patched to treat "foo*" as a 101 // Originally history used fts2, which Chromium patched to treat "foo*" as a
96 // prefix search, though the icu tokenizer would return it as two tokens {"foo", 102 // prefix search, though the icu tokenizer would return it as two tokens {"foo",
97 // "*"}. Test that fts3 works correctly. 103 // "*"}. Test that fts3 works correctly.
98 TEST_F(SQLiteFeaturesTest, FTS3_Prefix) { 104 TEST_F(SQLiteFeaturesTest, FTS3_Prefix) {
99 const char kCreateSql[] = 105 const char kCreateSql[] =
100 "CREATE VIRTUAL TABLE foo USING fts3(x, tokenize icu)"; 106 "CREATE VIRTUAL TABLE foo USING fts3(x, tokenize icu)";
101 ASSERT_TRUE(db().Execute(kCreateSql)); 107 ASSERT_TRUE(db().Execute(kCreateSql));
102 108
103 ASSERT_TRUE(db().Execute("INSERT INTO foo (x) VALUES ('test')")); 109 ASSERT_TRUE(db().Execute("INSERT INTO foo (x) VALUES ('test')"));
104 110
105 sql::Statement s(db().GetUniqueStatement( 111 EXPECT_EQ("test",
106 "SELECT x FROM foo WHERE x MATCH 'te*'")); 112 ExecuteWithResult(&db(), "SELECT x FROM foo WHERE x MATCH 'te*'"));
107 ASSERT_TRUE(s.Step());
108 EXPECT_EQ("test", s.ColumnString(0));
109 } 113 }
110 #endif 114 #endif
111 115
112 #if !defined(USE_SYSTEM_SQLITE) 116 #if !defined(USE_SYSTEM_SQLITE)
113 // Verify that Chromium's SQLite is compiled with HAVE_USLEEP defined. With 117 // Verify that Chromium's SQLite is compiled with HAVE_USLEEP defined. With
114 // HAVE_USLEEP, SQLite uses usleep() with millisecond granularity. Otherwise it 118 // HAVE_USLEEP, SQLite uses usleep() with millisecond granularity. Otherwise it
115 // uses sleep() with second granularity. 119 // uses sleep() with second granularity.
116 TEST_F(SQLiteFeaturesTest, UsesUsleep) { 120 TEST_F(SQLiteFeaturesTest, UsesUsleep) {
117 base::TimeTicks before = base::TimeTicks::Now(); 121 base::TimeTicks before = base::TimeTicks::Now();
118 sqlite3_sleep(1); 122 sqlite3_sleep(1);
119 base::TimeDelta delta = base::TimeTicks::Now() - before; 123 base::TimeDelta delta = base::TimeTicks::Now() - before;
120 124
121 // It is not impossible for this to be over 1000 if things are compiled the 125 // It is not impossible for this to be over 1000 if things are compiled
122 // right way. But it is very unlikely, most platforms seem to be around 126 // correctly, but that is very unlikely. Most platforms seem to be exactly
123 // <TBD>. 127 // 1ms, with the rest at 2ms, and the worst observed cases was ASAN at 7ms.
124 LOG(ERROR) << "Milliseconds: " << delta.InMilliseconds();
125 EXPECT_LT(delta.InMilliseconds(), 1000); 128 EXPECT_LT(delta.InMilliseconds(), 1000);
126 } 129 }
127 #endif 130 #endif
128 131
129 // Ensure that our SQLite version has working foreign key support with cascade 132 // Ensure that our SQLite version has working foreign key support with cascade
130 // delete support. 133 // delete support.
131 TEST_F(SQLiteFeaturesTest, ForeignKeySupport) { 134 TEST_F(SQLiteFeaturesTest, ForeignKeySupport) {
132 ASSERT_TRUE(db().Execute("PRAGMA foreign_keys=1")); 135 ASSERT_TRUE(db().Execute("PRAGMA foreign_keys=1"));
133 ASSERT_TRUE(db().Execute("CREATE TABLE parents (id INTEGER PRIMARY KEY)")); 136 ASSERT_TRUE(db().Execute("CREATE TABLE parents (id INTEGER PRIMARY KEY)"));
134 ASSERT_TRUE(db().Execute( 137 ASSERT_TRUE(db().Execute(
135 "CREATE TABLE children (" 138 "CREATE TABLE children ("
136 " id INTEGER PRIMARY KEY," 139 " id INTEGER PRIMARY KEY,"
137 " pid INTEGER NOT NULL REFERENCES parents(id) ON DELETE CASCADE)")); 140 " pid INTEGER NOT NULL REFERENCES parents(id) ON DELETE CASCADE)"));
141 const char kSelectParents[] = "SELECT * FROM parents ORDER BY id";
142 const char kSelectChildren[] = "SELECT * FROM children ORDER BY id";
138 143
139 // Inserting without a matching parent should fail with constraint violation. 144 // Inserting without a matching parent should fail with constraint violation.
140 // Mask off any extended error codes for USE_SYSTEM_SQLITE. 145 // Mask off any extended error codes for USE_SYSTEM_SQLITE.
141 int insertErr = db().ExecuteAndReturnErrorCode( 146 EXPECT_EQ("", ExecuteWithResult(&db(), kSelectParents));
142 "INSERT INTO children VALUES (10, 1)"); 147 const int insert_error =
143 EXPECT_EQ(SQLITE_CONSTRAINT, (insertErr&0xff)); 148 db().ExecuteAndReturnErrorCode("INSERT INTO children VALUES (10, 1)");
144 149 EXPECT_EQ(SQLITE_CONSTRAINT, (insert_error & 0xff));
145 size_t rows; 150 EXPECT_EQ("", ExecuteWithResult(&db(), kSelectChildren));
146 EXPECT_TRUE(sql::test::CountTableRows(&db(), "children", &rows));
147 EXPECT_EQ(0u, rows);
148 151
149 // Inserting with a matching parent should work. 152 // Inserting with a matching parent should work.
150 ASSERT_TRUE(db().Execute("INSERT INTO parents VALUES (1)")); 153 ASSERT_TRUE(db().Execute("INSERT INTO parents VALUES (1)"));
154 EXPECT_EQ("1", ExecuteWithResults(&db(), kSelectParents, "|", "\n"));
151 EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (11, 1)")); 155 EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (11, 1)"));
152 EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (12, 1)")); 156 EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (12, 1)"));
153 EXPECT_TRUE(sql::test::CountTableRows(&db(), "children", &rows)); 157 EXPECT_EQ("11|1\n12|1",
154 EXPECT_EQ(2u, rows); 158 ExecuteWithResults(&db(), kSelectChildren, "|", "\n"));
155 159
156 // Deleting the parent should cascade, i.e., delete the children as well. 160 // Deleting the parent should cascade, deleting the children as well.
157 ASSERT_TRUE(db().Execute("DELETE FROM parents")); 161 ASSERT_TRUE(db().Execute("DELETE FROM parents"));
158 EXPECT_TRUE(sql::test::CountTableRows(&db(), "children", &rows)); 162 EXPECT_EQ("", ExecuteWithResult(&db(), kSelectParents));
159 EXPECT_EQ(0u, rows); 163 EXPECT_EQ("", ExecuteWithResult(&db(), kSelectChildren));
160 } 164 }
161 165
162 #if defined(MOJO_APPTEST_IMPL) || defined(OS_IOS) 166 #if defined(MOJO_APPTEST_IMPL) || defined(OS_IOS)
163 // If the platform cannot support SQLite mmap'ed I/O, make sure SQLite isn't 167 // If the platform cannot support SQLite mmap'ed I/O, make sure SQLite isn't
164 // offering to support it. 168 // offering to support it.
165 TEST_F(SQLiteFeaturesTest, NoMmap) { 169 TEST_F(SQLiteFeaturesTest, NoMmap) {
166 #if defined(OS_IOS) && defined(USE_SYSTEM_SQLITE) 170 #if defined(OS_IOS) && defined(USE_SYSTEM_SQLITE)
167 if (base::ios::IsRunningOnIOS10OrLater()) { 171 if (base::ios::IsRunningOnIOS10OrLater()) {
168 // iOS 10 added mmap support for sqlite. 172 // iOS 10 added mmap support for sqlite.
169 return; 173 return;
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 s.Reset(true); 450 s.Reset(true);
447 ASSERT_TRUE(s.Run()); 451 ASSERT_TRUE(s.Run());
448 452
449 ASSERT_TRUE(base::GetFileSize(db_path(), &file_size_after)); 453 ASSERT_TRUE(base::GetFileSize(db_path(), &file_size_after));
450 ASSERT_EQ(file_size_after, file_size_before - 4096); 454 ASSERT_EQ(file_size_after, file_size_before - 4096);
451 } 455 }
452 #endif 456 #endif
453 } 457 }
454 #endif // !defined(USE_SYSTEM_SQLITE) 458 #endif // !defined(USE_SYSTEM_SQLITE)
455 459
456 } // namespace 460 #if !defined(USE_SYSTEM_SQLITE)
pwnall 2017/04/19 20:02:23 Would tests fail anywhere if we removed this #if?
Scott Hess - ex-Googler 2017/04/19 20:15:33 iOS uses the system SQLite. Also maybe Linux dist
pwnall 2017/04/19 20:56:54 TL;DR: If the test passes on bots, I'd leave it on
Scott Hess - ex-Googler 2017/04/19 22:03:16 The SQLite change landed last fall, so it's pretty
461 // SQLite WAL mode defaults to checkpointing the WAL on close. This would push
462 // additional work into Chromium shutdown. Verify that SQLite supports a config
463 // option to not checkpoint on close.
464 TEST_F(SQLiteFeaturesTest, WALNoClose) {
Scott Hess - ex-Googler 2017/04/18 23:53:39 Um, this is the main test for whether the desired
465 base::FilePath wal_path(db_path().value() + FILE_PATH_LITERAL("-wal"));
466
467 // Turn on WAL mode, then verify that the mode changed (WAL is supported).
468 ASSERT_TRUE(db().Execute("PRAGMA journal_mode = WAL"));
469 ASSERT_EQ("wal", ExecuteWithResult(&db(), "PRAGMA journal_mode"));
470
471 // The WAL file is created lazily on first change.
472 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
473
474 // By default, the WAL is checkpointed then deleted on close.
475 ASSERT_TRUE(GetPathExists(wal_path));
476 db().Close();
477 ASSERT_FALSE(GetPathExists(wal_path));
478
479 // Reopen and configure the database to not checkpoint WAL on close.
480 ASSERT_TRUE(Reopen());
481 ASSERT_TRUE(db().Execute("PRAGMA journal_mode = WAL"));
482 ASSERT_TRUE(db().Execute("ALTER TABLE foo ADD COLUMN c"));
483 ASSERT_EQ(
484 SQLITE_OK,
485 sqlite3_db_config(db().db_, SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, 1, NULL));
486 ASSERT_TRUE(GetPathExists(wal_path));
487 db().Close();
488 ASSERT_TRUE(GetPathExists(wal_path));
489 }
490 #endif
491
492 } // namespace sql
OLDNEW
« no previous file with comments | « sql/connection.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698