OLD | NEW |
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 "components/omnibox/browser/shortcuts_database.h" | 5 #include "components/omnibox/browser/shortcuts_database.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include "base/files/scoped_temp_dir.h" | 9 #include "base/files/scoped_temp_dir.h" |
10 #include "base/format_macros.h" | 10 #include "base/format_macros.h" |
11 #include "base/macros.h" | 11 #include "base/macros.h" |
12 #include "base/path_service.h" | 12 #include "base/path_service.h" |
13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
15 #include "base/time/time.h" | 15 #include "base/time/time.h" |
16 #include "build/build_config.h" | 16 #include "build/build_config.h" |
17 #include "components/omnibox/browser/autocomplete_match_type.h" | 17 #include "components/omnibox/browser/autocomplete_match_type.h" |
18 #include "components/omnibox/browser/shortcuts_constants.h" | 18 #include "components/omnibox/browser/shortcuts_constants.h" |
19 #include "sql/statement.h" | 19 #include "sql/statement.h" |
| 20 #include "sql/test/scoped_error_expecter.h" |
20 #include "sql/test/test_helpers.h" | 21 #include "sql/test/test_helpers.h" |
21 #include "testing/gtest/include/gtest/gtest.h" | 22 #include "testing/gtest/include/gtest/gtest.h" |
22 #include "ui/base/page_transition_types.h" | 23 #include "ui/base/page_transition_types.h" |
23 | 24 |
24 using base::ASCIIToUTF16; | 25 using base::ASCIIToUTF16; |
25 | 26 |
26 // Helpers -------------------------------------------------------------------- | 27 // Helpers -------------------------------------------------------------------- |
27 | 28 |
28 namespace { | 29 namespace { |
29 | 30 |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 TEST(ShortcutsDatabaseMigrationTest, MigrateTableAddFillIntoEdit) { | 227 TEST(ShortcutsDatabaseMigrationTest, MigrateTableAddFillIntoEdit) { |
227 // Use the pre-v0 test file to create a test database in a temp dir. | 228 // Use the pre-v0 test file to create a test database in a temp dir. |
228 base::FilePath sql_path = GetTestDataDir().AppendASCII( | 229 base::FilePath sql_path = GetTestDataDir().AppendASCII( |
229 #if defined(OS_ANDROID) | 230 #if defined(OS_ANDROID) |
230 "Shortcuts.v1.sql"); | 231 "Shortcuts.v1.sql"); |
231 #else | 232 #else |
232 "Shortcuts.no_fill_into_edit.sql"); | 233 "Shortcuts.no_fill_into_edit.sql"); |
233 #endif | 234 #endif |
234 base::ScopedTempDir temp_dir; | 235 base::ScopedTempDir temp_dir; |
235 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 236 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
236 base::FilePath db_path(temp_dir.path().AppendASCII("TestShortcuts1.db")); | 237 base::FilePath db_path(temp_dir.path().AppendASCII("TestShortcuts.db")); |
237 ASSERT_TRUE(sql::test::CreateDatabaseFromSQL(db_path, sql_path)); | 238 ASSERT_TRUE(sql::test::CreateDatabaseFromSQL(db_path, sql_path)); |
238 | 239 |
239 CheckV2ColumnExistence(db_path, false); | 240 CheckV2ColumnExistence(db_path, false); |
240 | 241 |
241 // Create a ShortcutsDatabase from the test database, which will migrate the | 242 // Create a ShortcutsDatabase from the test database, which will migrate the |
242 // test database to the current version. | 243 // test database to the current version. |
243 { | 244 { |
244 scoped_refptr<ShortcutsDatabase> db(new ShortcutsDatabase(db_path)); | 245 scoped_refptr<ShortcutsDatabase> db(new ShortcutsDatabase(db_path)); |
245 db->Init(); | 246 db->Init(); |
246 } | 247 } |
(...skipping 23 matching lines...) Expand all Loading... |
270 #if !defined(OS_WIN) | 271 #if !defined(OS_WIN) |
271 EXPECT_TRUE(temp_dir.Delete()); | 272 EXPECT_TRUE(temp_dir.Delete()); |
272 #endif | 273 #endif |
273 } | 274 } |
274 | 275 |
275 TEST(ShortcutsDatabaseMigrationTest, MigrateV0ToV1) { | 276 TEST(ShortcutsDatabaseMigrationTest, MigrateV0ToV1) { |
276 // Use the v0 test file to create a test database in a temp dir. | 277 // Use the v0 test file to create a test database in a temp dir. |
277 base::FilePath sql_path = GetTestDataDir().AppendASCII("Shortcuts.v0.sql"); | 278 base::FilePath sql_path = GetTestDataDir().AppendASCII("Shortcuts.v0.sql"); |
278 base::ScopedTempDir temp_dir; | 279 base::ScopedTempDir temp_dir; |
279 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 280 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
280 base::FilePath db_path(temp_dir.path().AppendASCII("TestShortcuts2.db")); | 281 base::FilePath db_path(temp_dir.path().AppendASCII("TestShortcuts.db")); |
281 ASSERT_TRUE(sql::test::CreateDatabaseFromSQL(db_path, sql_path)); | 282 ASSERT_TRUE(sql::test::CreateDatabaseFromSQL(db_path, sql_path)); |
282 | 283 |
283 // Create a ShortcutsDatabase from the test database, which will migrate the | 284 // Create a ShortcutsDatabase from the test database, which will migrate the |
284 // test database to the current version. | 285 // test database to the current version. |
285 { | 286 { |
286 scoped_refptr<ShortcutsDatabase> db(new ShortcutsDatabase(db_path)); | 287 scoped_refptr<ShortcutsDatabase> db(new ShortcutsDatabase(db_path)); |
287 db->Init(); | 288 db->Init(); |
288 } | 289 } |
289 | 290 |
290 // Check that all the old type values got converted to new values. | 291 // Check that all the old type values got converted to new values. |
291 sql::Connection connection; | 292 sql::Connection connection; |
292 ASSERT_TRUE(connection.Open(db_path)); | 293 ASSERT_TRUE(connection.Open(db_path)); |
293 sql::Statement statement(connection.GetUniqueStatement( | 294 sql::Statement statement(connection.GetUniqueStatement( |
294 "SELECT count(1) FROM omni_box_shortcuts WHERE type in (9, 10, 11, 12)")); | 295 "SELECT count(1) FROM omni_box_shortcuts WHERE type in (9, 10, 11, 12)")); |
295 ASSERT_TRUE(statement.is_valid()); | 296 ASSERT_TRUE(statement.is_valid()); |
296 while (statement.Step()) | 297 while (statement.Step()) |
297 EXPECT_EQ(0, statement.ColumnInt(0)); | 298 EXPECT_EQ(0, statement.ColumnInt(0)); |
298 EXPECT_TRUE(statement.Succeeded()); | 299 EXPECT_TRUE(statement.Succeeded()); |
299 #if !defined(OS_WIN) | 300 #if !defined(OS_WIN) |
300 EXPECT_TRUE(temp_dir.Delete()); | 301 EXPECT_TRUE(temp_dir.Delete()); |
301 #endif | 302 #endif |
302 } | 303 } |
| 304 |
| 305 TEST(ShortcutsDatabaseMigrationTest, Recovery1) { |
| 306 #if defined(OS_ANDROID) |
| 307 char kBasename[] = "Shortcuts.v1.sql"; |
| 308 #else |
| 309 char kBasename[] = "Shortcuts.no_fill_into_edit.sql"; |
| 310 #endif |
| 311 // Use the pre-v0 test file to create a test database in a temp dir. |
| 312 base::FilePath sql_path = GetTestDataDir().AppendASCII(kBasename); |
| 313 base::ScopedTempDir temp_dir; |
| 314 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 315 base::FilePath db_path(temp_dir.path().AppendASCII("TestShortcuts.db")); |
| 316 ASSERT_TRUE(sql::test::CreateDatabaseFromSQL(db_path, sql_path)); |
| 317 |
| 318 // Capture the row count from the golden file before corrupting the database. |
| 319 const char kCountSql[] = "SELECT COUNT(*) FROM omni_box_shortcuts"; |
| 320 int row_count; |
| 321 { |
| 322 sql::Connection connection; |
| 323 ASSERT_TRUE(connection.Open(db_path)); |
| 324 sql::Statement statement(connection.GetUniqueStatement(kCountSql)); |
| 325 ASSERT_TRUE(statement.is_valid()); |
| 326 ASSERT_TRUE(statement.Step()); |
| 327 row_count = statement.ColumnInt(0); |
| 328 } |
| 329 |
| 330 // Break the database. |
| 331 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path)); |
| 332 |
| 333 // Verify that the database is broken. The corruption will prevent reading |
| 334 // the schema, causing the prepared statement to not compile. |
| 335 { |
| 336 sql::test::ScopedErrorExpecter expecter; |
| 337 expecter.ExpectError(SQLITE_CORRUPT); |
| 338 |
| 339 sql::Connection connection; |
| 340 ASSERT_TRUE(connection.Open(db_path)); |
| 341 sql::Statement statement(connection.GetUniqueStatement(kCountSql)); |
| 342 ASSERT_FALSE(statement.is_valid()); |
| 343 |
| 344 ASSERT_TRUE(expecter.SawExpectedErrors()); |
| 345 } |
| 346 |
| 347 // The sql::Connection::Open() called by ShortcutsDatabase::Init() will hit |
| 348 // the corruption, the error callback will recover and poison the database, |
| 349 // then Open() will retry successfully, allowing Init() to succeed. |
| 350 { |
| 351 sql::test::ScopedErrorExpecter expecter; |
| 352 expecter.ExpectError(SQLITE_CORRUPT); |
| 353 |
| 354 scoped_refptr<ShortcutsDatabase> db(new ShortcutsDatabase(db_path)); |
| 355 ASSERT_TRUE(db->Init()); |
| 356 |
| 357 ASSERT_TRUE(expecter.SawExpectedErrors()); |
| 358 } |
| 359 |
| 360 CheckV2ColumnExistence(db_path, true); |
| 361 |
| 362 // The previously-broken statement works and all of the data should have been |
| 363 // recovered. |
| 364 { |
| 365 sql::Connection connection; |
| 366 ASSERT_TRUE(connection.Open(db_path)); |
| 367 sql::Statement statement(connection.GetUniqueStatement(kCountSql)); |
| 368 ASSERT_TRUE(statement.is_valid()); |
| 369 ASSERT_TRUE(statement.Step()); |
| 370 EXPECT_EQ(row_count, statement.ColumnInt(0)); |
| 371 } |
| 372 } |
OLD | NEW |