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

Side by Side Diff: sql/sqlite_features_unittest.cc

Issue 2587603003: [sql] Patch SQLite to allow control of close-time WAL checkpoint. (Closed)
Patch Set: fix UsesUsleep comment from trybot results Created 4 years 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') | third_party/sqlite/amalgamation/sqlite3.h » ('j') | 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"
11 #include "base/files/file_util.h" 11 #include "base/files/file_util.h"
12 #include "base/files/memory_mapped_file.h" 12 #include "base/files/memory_mapped_file.h"
13 #include "base/files/scoped_temp_dir.h" 13 #include "base/files/scoped_temp_dir.h"
14 #include "sql/connection.h" 14 #include "sql/connection.h"
15 #include "sql/statement.h" 15 #include "sql/statement.h"
16 #include "sql/test/sql_test_base.h" 16 #include "sql/test/sql_test_base.h"
17 #include "sql/test/test_helpers.h" 17 #include "sql/test/test_helpers.h"
18 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/sqlite/sqlite3.h" 19 #include "third_party/sqlite/sqlite3.h"
20 20
21 #if defined(OS_IOS) 21 #if defined(OS_IOS)
22 #include "base/ios/ios_util.h" 22 #include "base/ios/ios_util.h"
23 #endif 23 #endif
24 24
25 // Test that certain features are/are-not enabled in our SQLite. 25 // Test that certain features are/are-not enabled in our SQLite.
26 26
27 namespace sql {
27 namespace { 28 namespace {
28 29
30 using sql::test::ExecuteWithResult;
31 using sql::test::ExecuteWithResults;
32
29 void CaptureErrorCallback(int* error_pointer, std::string* sql_text, 33 void CaptureErrorCallback(int* error_pointer, std::string* sql_text,
30 int error, sql::Statement* stmt) { 34 int error, sql::Statement* stmt) {
31 *error_pointer = error; 35 *error_pointer = error;
32 const char* text = stmt ? stmt->GetSQLStatement() : NULL; 36 const char* text = stmt ? stmt->GetSQLStatement() : NULL;
33 *sql_text = text ? text : "no statement available"; 37 *sql_text = text ? text : "no statement available";
34 } 38 }
35 39
40 } // namespace
41
36 class SQLiteFeaturesTest : public sql::SQLTestBase { 42 class SQLiteFeaturesTest : public sql::SQLTestBase {
37 public: 43 public:
38 SQLiteFeaturesTest() : error_(SQLITE_OK) {} 44 SQLiteFeaturesTest() : error_(SQLITE_OK) {}
39 45
40 void SetUp() override { 46 void SetUp() override {
41 SQLTestBase::SetUp(); 47 SQLTestBase::SetUp();
42 48
43 // The error delegate will set |error_| and |sql_text_| when any sqlite 49 // The error delegate will set |error_| and |sql_text_| when any sqlite
44 // statement operation returns an error code. 50 // statement operation returns an error code.
45 db().set_error_callback( 51 db().set_error_callback(
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 // Originally history used fts2, which Chromium patched to treat "foo*" as a 93 // Originally history used fts2, which Chromium patched to treat "foo*" as a
88 // prefix search, though the icu tokenizer would return it as two tokens {"foo", 94 // prefix search, though the icu tokenizer would return it as two tokens {"foo",
89 // "*"}. Test that fts3 works correctly. 95 // "*"}. Test that fts3 works correctly.
90 TEST_F(SQLiteFeaturesTest, FTS3_Prefix) { 96 TEST_F(SQLiteFeaturesTest, FTS3_Prefix) {
91 const char kCreateSql[] = 97 const char kCreateSql[] =
92 "CREATE VIRTUAL TABLE foo USING fts3(x, tokenize icu)"; 98 "CREATE VIRTUAL TABLE foo USING fts3(x, tokenize icu)";
93 ASSERT_TRUE(db().Execute(kCreateSql)); 99 ASSERT_TRUE(db().Execute(kCreateSql));
94 100
95 ASSERT_TRUE(db().Execute("INSERT INTO foo (x) VALUES ('test')")); 101 ASSERT_TRUE(db().Execute("INSERT INTO foo (x) VALUES ('test')"));
96 102
97 sql::Statement s(db().GetUniqueStatement( 103 EXPECT_EQ("test",
98 "SELECT x FROM foo WHERE x MATCH 'te*'")); 104 ExecuteWithResult(&db(), "SELECT x FROM foo WHERE x MATCH 'te*'"));
99 ASSERT_TRUE(s.Step());
100 EXPECT_EQ("test", s.ColumnString(0));
101 } 105 }
102 #endif 106 #endif
103 107
104 #if !defined(USE_SYSTEM_SQLITE) 108 #if !defined(USE_SYSTEM_SQLITE)
105 // Verify that Chromium's SQLite is compiled with HAVE_USLEEP defined. With 109 // Verify that Chromium's SQLite is compiled with HAVE_USLEEP defined. With
106 // HAVE_USLEEP, SQLite uses usleep() with millisecond granularity. Otherwise it 110 // HAVE_USLEEP, SQLite uses usleep() with millisecond granularity. Otherwise it
107 // uses sleep() with second granularity. 111 // uses sleep() with second granularity.
108 TEST_F(SQLiteFeaturesTest, UsesUsleep) { 112 TEST_F(SQLiteFeaturesTest, UsesUsleep) {
109 base::TimeTicks before = base::TimeTicks::Now(); 113 base::TimeTicks before = base::TimeTicks::Now();
110 sqlite3_sleep(1); 114 sqlite3_sleep(1);
111 base::TimeDelta delta = base::TimeTicks::Now() - before; 115 base::TimeDelta delta = base::TimeTicks::Now() - before;
112 116
113 // It is not impossible for this to be over 1000 if things are compiled the 117 // It is not impossible for this to be over 1000 if things are compiled
114 // right way. But it is very unlikely, most platforms seem to be around 118 // correctly, but that is very unlikely. Most platforms seem to be exactly
115 // <TBD>. 119 // 1ms, with the test at 2ms, the worst observed cases was ASAN at 7ms.
116 LOG(ERROR) << "Milliseconds: " << delta.InMilliseconds();
117 EXPECT_LT(delta.InMilliseconds(), 1000); 120 EXPECT_LT(delta.InMilliseconds(), 1000);
118 } 121 }
119 #endif 122 #endif
120 123
121 // Ensure that our SQLite version has working foreign key support with cascade 124 // Ensure that our SQLite version has working foreign key support with cascade
122 // delete support. 125 // delete support.
123 TEST_F(SQLiteFeaturesTest, ForeignKeySupport) { 126 TEST_F(SQLiteFeaturesTest, ForeignKeySupport) {
124 ASSERT_TRUE(db().Execute("PRAGMA foreign_keys=1")); 127 ASSERT_TRUE(db().Execute("PRAGMA foreign_keys=1"));
125 ASSERT_TRUE(db().Execute("CREATE TABLE parents (id INTEGER PRIMARY KEY)")); 128 ASSERT_TRUE(db().Execute("CREATE TABLE parents (id INTEGER PRIMARY KEY)"));
126 ASSERT_TRUE(db().Execute( 129 ASSERT_TRUE(db().Execute(
127 "CREATE TABLE children (" 130 "CREATE TABLE children ("
128 " id INTEGER PRIMARY KEY," 131 " id INTEGER PRIMARY KEY,"
129 " pid INTEGER NOT NULL REFERENCES parents(id) ON DELETE CASCADE)")); 132 " pid INTEGER NOT NULL REFERENCES parents(id) ON DELETE CASCADE)"));
133 const char kSelectParents[] = "SELECT * FROM parents ORDER BY id";
134 const char kSelectChildren[] = "SELECT * FROM children ORDER BY id";
130 135
131 // Inserting without a matching parent should fail with constraint violation. 136 // Inserting without a matching parent should fail with constraint violation.
132 // Mask off any extended error codes for USE_SYSTEM_SQLITE. 137 // Mask off any extended error codes for USE_SYSTEM_SQLITE.
133 int insertErr = db().ExecuteAndReturnErrorCode( 138 EXPECT_EQ("", ExecuteWithResult(&db(), kSelectParents));
139 const int insert_error = db().ExecuteAndReturnErrorCode(
134 "INSERT INTO children VALUES (10, 1)"); 140 "INSERT INTO children VALUES (10, 1)");
135 EXPECT_EQ(SQLITE_CONSTRAINT, (insertErr&0xff)); 141 EXPECT_EQ(SQLITE_CONSTRAINT, (insert_error&0xff));
136 142 EXPECT_EQ("", ExecuteWithResult(&db(), kSelectChildren));
137 size_t rows;
138 EXPECT_TRUE(sql::test::CountTableRows(&db(), "children", &rows));
139 EXPECT_EQ(0u, rows);
140 143
141 // Inserting with a matching parent should work. 144 // Inserting with a matching parent should work.
142 ASSERT_TRUE(db().Execute("INSERT INTO parents VALUES (1)")); 145 ASSERT_TRUE(db().Execute("INSERT INTO parents VALUES (1)"));
146 EXPECT_EQ("1", ExecuteWithResults(&db(), kSelectParents, "|", "\n"));
143 EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (11, 1)")); 147 EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (11, 1)"));
144 EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (12, 1)")); 148 EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (12, 1)"));
145 EXPECT_TRUE(sql::test::CountTableRows(&db(), "children", &rows)); 149 EXPECT_EQ("11|1\n12|1",
146 EXPECT_EQ(2u, rows); 150 ExecuteWithResults(&db(), kSelectChildren, "|", "\n"));
147 151
148 // Deleting the parent should cascade, i.e., delete the children as well. 152 // Deleting the parent should cascade, deleting the children as well.
149 ASSERT_TRUE(db().Execute("DELETE FROM parents")); 153 ASSERT_TRUE(db().Execute("DELETE FROM parents"));
150 EXPECT_TRUE(sql::test::CountTableRows(&db(), "children", &rows)); 154 EXPECT_EQ("", ExecuteWithResult(&db(), kSelectParents));
151 EXPECT_EQ(0u, rows); 155 EXPECT_EQ("", ExecuteWithResult(&db(), kSelectChildren));
152 } 156 }
153 157
154 #if defined(MOJO_APPTEST_IMPL) || defined(OS_IOS) 158 #if defined(MOJO_APPTEST_IMPL) || defined(OS_IOS)
155 // If the platform cannot support SQLite mmap'ed I/O, make sure SQLite isn't 159 // If the platform cannot support SQLite mmap'ed I/O, make sure SQLite isn't
156 // offering to support it. 160 // offering to support it.
157 TEST_F(SQLiteFeaturesTest, NoMmap) { 161 TEST_F(SQLiteFeaturesTest, NoMmap) {
158 #if defined(OS_IOS) && defined(USE_SYSTEM_SQLITE) 162 #if defined(OS_IOS) && defined(USE_SYSTEM_SQLITE)
159 if (base::ios::IsRunningOnIOS10OrLater()) { 163 if (base::ios::IsRunningOnIOS10OrLater()) {
160 // iOS 10 added mmap support for sqlite. 164 // iOS 10 added mmap support for sqlite.
161 return; 165 return;
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 s.BindString(0, ".*test"); 300 s.BindString(0, ".*test");
297 ASSERT_TRUE(s.Step()); 301 ASSERT_TRUE(s.Step());
298 EXPECT_EQ(3, s.ColumnInt(0)); 302 EXPECT_EQ(3, s.ColumnInt(0));
299 303
300 s.Reset(true); 304 s.Reset(true);
301 s.BindString(0, ".* s[a-z]+"); 305 s.BindString(0, ".* s[a-z]+");
302 ASSERT_TRUE(s.Step()); 306 ASSERT_TRUE(s.Step());
303 EXPECT_EQ(7, s.ColumnInt(0)); 307 EXPECT_EQ(7, s.ColumnInt(0));
304 } 308 }
305 309
306 } // namespace 310 #if !defined(USE_SYSTEM_SQLITE)
311 // SQLite WAL mode defaults to checkpointing the WAL on close. This would push
312 // additional work into Chromium shutdown. Verify that SQLite supports a config
313 // option to not checkpoint on close.
314 TEST_F(SQLiteFeaturesTest, WALNoClose) {
315 base::FilePath wal(db_path().value() + FILE_PATH_LITERAL("-wal"));
316
317 // Turn on WAL mode, then verify that it worked.
318 ASSERT_TRUE(db().Execute("PRAGMA journal_mode = WAL"));
319 ASSERT_EQ("wal", ExecuteWithResult(&db(), "PRAGMA journal_mode"));
320
321 // The WAL file is created lazily on first change.
322 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
323
324 // By default, the WAL is checkpointed and deleted on close.
325 ASSERT_TRUE(GetPathExists(wal));
326 db().Close();
327 ASSERT_FALSE(GetPathExists(wal));
328
329 // Reopen and configure the database to not checkpoint WAL on close.
330 ASSERT_TRUE(Reopen());
331 ASSERT_TRUE(db().Execute("PRAGMA journal_mode = WAL"));
332 ASSERT_TRUE(db().Execute("ALTER TABLE foo ADD COLUMN c"));
333 ASSERT_EQ(SQLITE_OK,
334 sqlite3_db_config(db().db_, SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE,
335 1, NULL));
336 ASSERT_TRUE(GetPathExists(wal));
337 db().Close();
338 ASSERT_TRUE(GetPathExists(wal));
339 }
340 #endif
341
342 } // namespace sql
OLDNEW
« no previous file with comments | « sql/connection.h ('k') | third_party/sqlite/amalgamation/sqlite3.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698