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

Side by Side Diff: sql/recovery_unittest.cc

Issue 2441153002: [sql] Test helpers to ease testing of simple queries. (Closed)
Patch Set: Created 4 years, 1 month 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 | « no previous file | sql/test/test_helpers.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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "sql/recovery.h" 5 #include "sql/recovery.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <string> 10 #include <string>
(...skipping 11 matching lines...) Expand all
22 #include "sql/statement.h" 22 #include "sql/statement.h"
23 #include "sql/test/paths.h" 23 #include "sql/test/paths.h"
24 #include "sql/test/scoped_error_expecter.h" 24 #include "sql/test/scoped_error_expecter.h"
25 #include "sql/test/sql_test_base.h" 25 #include "sql/test/sql_test_base.h"
26 #include "sql/test/test_helpers.h" 26 #include "sql/test/test_helpers.h"
27 #include "testing/gtest/include/gtest/gtest.h" 27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "third_party/sqlite/sqlite3.h" 28 #include "third_party/sqlite/sqlite3.h"
29 29
30 namespace { 30 namespace {
31 31
32 // Execute |sql|, and stringify the results with |column_sep| between 32 using sql::test::ExecuteWithResults;
33 // columns and |row_sep| between rows. 33 using sql::test::ExecuteWithResult;
34 // TODO(shess): Promote this to a central testing helper.
35 std::string ExecuteWithResults(sql::Connection* db,
36 const char* sql,
37 const char* column_sep,
38 const char* row_sep) {
39 sql::Statement s(db->GetUniqueStatement(sql));
40 std::string ret;
41 while (s.Step()) {
42 if (!ret.empty())
43 ret += row_sep;
44 for (int i = 0; i < s.ColumnCount(); ++i) {
45 if (i > 0)
46 ret += column_sep;
47 if (s.ColumnType(i) == sql::COLUMN_TYPE_NULL) {
48 ret += "<null>";
49 } else if (s.ColumnType(i) == sql::COLUMN_TYPE_BLOB) {
50 ret += "<x'";
51 ret += base::HexEncode(s.ColumnBlob(i), s.ColumnByteLength(i));
52 ret += "'>";
53 } else {
54 ret += s.ColumnString(i);
55 }
56 }
57 }
58 return ret;
59 }
60 34
61 // Dump consistent human-readable representation of the database 35 // Dump consistent human-readable representation of the database
62 // schema. For tables or indices, this will contain the sql command 36 // schema. For tables or indices, this will contain the sql command
63 // to create the table or index. For certain automatic SQLite 37 // to create the table or index. For certain automatic SQLite
64 // structures with no sql, the name is used. 38 // structures with no sql, the name is used.
65 std::string GetSchema(sql::Connection* db) { 39 std::string GetSchema(sql::Connection* db) {
66 const char kSql[] = 40 const char kSql[] =
67 "SELECT COALESCE(sql, name) FROM sqlite_master ORDER BY 1"; 41 "SELECT COALESCE(sql, name) FROM sqlite_master ORDER BY 1";
68 return ExecuteWithResults(db, kSql, "|", "\n"); 42 return ExecuteWithResults(db, kSql, "|", "\n");
69 } 43 }
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 120
147 // Successfully recovered. 121 // Successfully recovered.
148 ASSERT_TRUE(sql::Recovery::Recovered(std::move(recovery))); 122 ASSERT_TRUE(sql::Recovery::Recovered(std::move(recovery)));
149 } 123 }
150 EXPECT_FALSE(db().is_open()); 124 EXPECT_FALSE(db().is_open());
151 ASSERT_TRUE(Reopen()); 125 ASSERT_TRUE(Reopen());
152 EXPECT_TRUE(db().is_open()); 126 EXPECT_TRUE(db().is_open());
153 ASSERT_EQ("CREATE TABLE x (t TEXT)", GetSchema(&db())); 127 ASSERT_EQ("CREATE TABLE x (t TEXT)", GetSchema(&db()));
154 128
155 const char* kXSql = "SELECT * FROM x ORDER BY 1"; 129 const char* kXSql = "SELECT * FROM x ORDER BY 1";
156 ASSERT_EQ("That was a test", 130 ASSERT_EQ("That was a test", ExecuteWithResult(&db(), kXSql));
157 ExecuteWithResults(&db(), kXSql, "|", "\n"));
158 131
159 // Reset the database contents. 132 // Reset the database contents.
160 ASSERT_TRUE(db().Execute("DELETE FROM x")); 133 ASSERT_TRUE(db().Execute("DELETE FROM x"));
161 ASSERT_TRUE(db().Execute(kInsertSql)); 134 ASSERT_TRUE(db().Execute(kInsertSql));
162 135
163 // Rollback() discards recovery progress and leaves the database as it was. 136 // Rollback() discards recovery progress and leaves the database as it was.
164 { 137 {
165 std::unique_ptr<sql::Recovery> recovery = 138 std::unique_ptr<sql::Recovery> recovery =
166 sql::Recovery::Begin(&db(), db_path()); 139 sql::Recovery::Begin(&db(), db_path());
167 ASSERT_TRUE(recovery.get()); 140 ASSERT_TRUE(recovery.get());
168 141
169 ASSERT_TRUE(recovery->db()->Execute(kCreateSql)); 142 ASSERT_TRUE(recovery->db()->Execute(kCreateSql));
170 ASSERT_TRUE(recovery->db()->Execute(kAltInsertSql)); 143 ASSERT_TRUE(recovery->db()->Execute(kAltInsertSql));
171 144
172 sql::Recovery::Rollback(std::move(recovery)); 145 sql::Recovery::Rollback(std::move(recovery));
173 } 146 }
174 EXPECT_FALSE(db().is_open()); 147 EXPECT_FALSE(db().is_open());
175 ASSERT_TRUE(Reopen()); 148 ASSERT_TRUE(Reopen());
176 EXPECT_TRUE(db().is_open()); 149 EXPECT_TRUE(db().is_open());
177 ASSERT_EQ("CREATE TABLE x (t TEXT)", GetSchema(&db())); 150 ASSERT_EQ("CREATE TABLE x (t TEXT)", GetSchema(&db()));
178 151
179 ASSERT_EQ("This is a test", 152 ASSERT_EQ("This is a test", ExecuteWithResult(&db(), kXSql));
180 ExecuteWithResults(&db(), kXSql, "|", "\n"));
181 } 153 }
182 154
183 // Test operation of the virtual table used by sql::Recovery. 155 // Test operation of the virtual table used by sql::Recovery.
184 TEST_F(SQLRecoveryTest, VirtualTable) { 156 TEST_F(SQLRecoveryTest, VirtualTable) {
185 const char kCreateSql[] = "CREATE TABLE x (t TEXT)"; 157 const char kCreateSql[] = "CREATE TABLE x (t TEXT)";
186 ASSERT_TRUE(db().Execute(kCreateSql)); 158 ASSERT_TRUE(db().Execute(kCreateSql));
187 ASSERT_TRUE(db().Execute("INSERT INTO x VALUES ('This is a test')")); 159 ASSERT_TRUE(db().Execute("INSERT INTO x VALUES ('This is a test')"));
188 ASSERT_TRUE(db().Execute("INSERT INTO x VALUES ('That was a test')")); 160 ASSERT_TRUE(db().Execute("INSERT INTO x VALUES ('That was a test')"));
189 161
190 // Successfully recover the database. 162 // Successfully recover the database.
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 ASSERT_TRUE(sql::test::CorruptTableOrIndex(db_path(), "x", kDeleteSql)); 305 ASSERT_TRUE(sql::test::CorruptTableOrIndex(db_path(), "x", kDeleteSql));
334 306
335 ASSERT_TRUE(Reopen()); 307 ASSERT_TRUE(Reopen());
336 308
337 int error = SQLITE_OK; 309 int error = SQLITE_OK;
338 db().set_error_callback(base::Bind(&RecoveryCallback, &db(), db_path(), 310 db().set_error_callback(base::Bind(&RecoveryCallback, &db(), db_path(),
339 kCreateTable, kCreateIndex, &error)); 311 kCreateTable, kCreateIndex, &error));
340 312
341 // Index shows one less than originally inserted. 313 // Index shows one less than originally inserted.
342 const char kCountSql[] = "SELECT COUNT (*) FROM x"; 314 const char kCountSql[] = "SELECT COUNT (*) FROM x";
343 EXPECT_EQ("9", ExecuteWithResults(&db(), kCountSql, "|", ",")); 315 EXPECT_EQ("9", ExecuteWithResult(&db(), kCountSql));
344 316
345 // A full table scan shows all of the original data. Using column [v] to 317 // A full table scan shows all of the original data. Using column [v] to
346 // force use of the table rather than the index. 318 // force use of the table rather than the index.
347 const char kDistinctSql[] = "SELECT DISTINCT COUNT (v) FROM x"; 319 const char kDistinctSql[] = "SELECT DISTINCT COUNT (v) FROM x";
348 EXPECT_EQ("10", ExecuteWithResults(&db(), kDistinctSql, "|", ",")); 320 EXPECT_EQ("10", ExecuteWithResult(&db(), kDistinctSql));
349 321
350 // Insert id 0 again. Since it is not in the index, the insert 322 // Insert id 0 again. Since it is not in the index, the insert
351 // succeeds, but results in a duplicate value in the table. 323 // succeeds, but results in a duplicate value in the table.
352 const char kInsertSql[] = "INSERT INTO x (id, v) VALUES (0, 100)"; 324 const char kInsertSql[] = "INSERT INTO x (id, v) VALUES (0, 100)";
353 ASSERT_TRUE(db().Execute(kInsertSql)); 325 ASSERT_TRUE(db().Execute(kInsertSql));
354 326
355 // Duplication is visible. 327 // Duplication is visible.
356 EXPECT_EQ("10", ExecuteWithResults(&db(), kCountSql, "|", ",")); 328 EXPECT_EQ("10", ExecuteWithResult(&db(), kCountSql));
357 EXPECT_EQ("11", ExecuteWithResults(&db(), kDistinctSql, "|", ",")); 329 EXPECT_EQ("11", ExecuteWithResult(&db(), kDistinctSql));
358 330
359 // This works before the callback is called. 331 // This works before the callback is called.
360 const char kTrivialSql[] = "SELECT COUNT(*) FROM sqlite_master"; 332 const char kTrivialSql[] = "SELECT COUNT(*) FROM sqlite_master";
361 EXPECT_TRUE(db().IsSQLValid(kTrivialSql)); 333 EXPECT_TRUE(db().IsSQLValid(kTrivialSql));
362 334
363 // TODO(shess): Figure out a statement which causes SQLite to notice the 335 // TODO(shess): Figure out a statement which causes SQLite to notice the
364 // corruption. SELECT doesn't see errors because missing index values aren't 336 // corruption. SELECT doesn't see errors because missing index values aren't
365 // visible. UPDATE or DELETE against v=0 don't see errors, even though the 337 // visible. UPDATE or DELETE against v=0 don't see errors, even though the
366 // index item is missing. I suspect SQLite only deletes the key in these 338 // index item is missing. I suspect SQLite only deletes the key in these
367 // cases, but doesn't verify that one or more keys were deleted. 339 // cases, but doesn't verify that one or more keys were deleted.
368 ASSERT_FALSE(db().Execute("INSERT INTO x (id, v) VALUES (0, 101)")); 340 ASSERT_FALSE(db().Execute("INSERT INTO x (id, v) VALUES (0, 101)"));
369 EXPECT_EQ(SQLITE_CONSTRAINT_UNIQUE, error); 341 EXPECT_EQ(SQLITE_CONSTRAINT_UNIQUE, error);
370 342
371 // Database handle has been poisoned. 343 // Database handle has been poisoned.
372 EXPECT_FALSE(db().IsSQLValid(kTrivialSql)); 344 EXPECT_FALSE(db().IsSQLValid(kTrivialSql));
373 345
374 ASSERT_TRUE(Reopen()); 346 ASSERT_TRUE(Reopen());
375 347
376 // The recovered table has consistency between the index and the table. 348 // The recovered table has consistency between the index and the table.
377 EXPECT_EQ("10", ExecuteWithResults(&db(), kCountSql, "|", ",")); 349 EXPECT_EQ("10", ExecuteWithResult(&db(), kCountSql));
378 EXPECT_EQ("10", ExecuteWithResults(&db(), kDistinctSql, "|", ",")); 350 EXPECT_EQ("10", ExecuteWithResult(&db(), kDistinctSql));
379 351
380 // Only one of the values is retained. 352 // Only one of the values is retained.
381 const char kSelectSql[] = "SELECT v FROM x WHERE id = 0"; 353 const char kSelectSql[] = "SELECT v FROM x WHERE id = 0";
382 const std::string results = ExecuteWithResults(&db(), kSelectSql, "|", ","); 354 const std::string results = ExecuteWithResult(&db(), kSelectSql);
383 EXPECT_TRUE(results=="100" || results=="0") << "Actual results: " << results; 355 EXPECT_TRUE(results=="100" || results=="0") << "Actual results: " << results;
384 } 356 }
385 357
386 TEST_F(SQLRecoveryTest, Meta) { 358 TEST_F(SQLRecoveryTest, Meta) {
387 const int kVersion = 3; 359 const int kVersion = 3;
388 const int kCompatibleVersion = 2; 360 const int kCompatibleVersion = 2;
389 361
390 { 362 {
391 sql::MetaTable meta; 363 sql::MetaTable meta;
392 EXPECT_TRUE(meta.Init(&db(), kVersion, kCompatibleVersion)); 364 EXPECT_TRUE(meta.Init(&db(), kVersion, kCompatibleVersion));
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 833
862 ASSERT_TRUE(expecter.SawExpectedErrors()); 834 ASSERT_TRUE(expecter.SawExpectedErrors());
863 } 835 }
864 836
865 // Verify that the failure was in the right place with the expected code. 837 // Verify that the failure was in the right place with the expected code.
866 tester.ExpectBucketCount(kEventHistogramName, kEventEnum, 1); 838 tester.ExpectBucketCount(kEventHistogramName, kEventEnum, 1);
867 tester.ExpectBucketCount(kErrorHistogramName, SQLITE_NOTADB, 1); 839 tester.ExpectBucketCount(kErrorHistogramName, SQLITE_NOTADB, 1);
868 } 840 }
869 841
870 } // namespace 842 } // namespace
OLDNEW
« no previous file with comments | « no previous file | sql/test/test_helpers.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698