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 // History unit tests come in two flavors: | 5 // History unit tests come in two flavors: |
6 // | 6 // |
7 // 1. The more complicated style is that the unit test creates a full history | 7 // 1. The more complicated style is that the unit test creates a full history |
8 // service. This spawns a background thread for the history backend, and | 8 // service. This spawns a background thread for the history backend, and |
9 // all communication is asynchronous. This is useful for testing more | 9 // all communication is asynchronous. This is useful for testing more |
10 // complicated things or end-to-end behavior. | 10 // complicated things or end-to-end behavior. |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 virtual void TearDown() { | 138 virtual void TearDown() { |
139 DeleteBackend(); | 139 DeleteBackend(); |
140 | 140 |
141 // Make sure we don't have any event pending that could disrupt the next | 141 // Make sure we don't have any event pending that could disrupt the next |
142 // test. | 142 // test. |
143 MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | 143 MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
144 MessageLoop::current()->Run(); | 144 MessageLoop::current()->Run(); |
145 } | 145 } |
146 | 146 |
147 int64 AddDownload(DownloadItem::DownloadState state, const Time& time) { | 147 int64 AddDownload(DownloadItem::DownloadState state, const Time& time) { |
| 148 std::vector<GURL> url_chain; |
| 149 url_chain.push_back(GURL("foo-url")); |
| 150 |
148 DownloadRow download( | 151 DownloadRow download( |
149 FilePath(FILE_PATH_LITERAL("foo-path")), | 152 FilePath(FILE_PATH_LITERAL("foo-path")), |
150 GURL("foo-url"), | 153 FilePath(FILE_PATH_LITERAL("foo-path")), |
| 154 url_chain, |
151 GURL(""), | 155 GURL(""), |
152 time, | 156 time, |
153 time, | 157 time, |
154 0, | 158 0, |
155 512, | 159 512, |
156 state, | 160 state, |
| 161 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, |
| 162 content::DOWNLOAD_INTERRUPT_REASON_NONE, |
157 0, | 163 0, |
158 0); | 164 0); |
159 return db_->CreateDownload(download); | 165 return db_->CreateDownload(download); |
160 } | 166 } |
161 | 167 |
162 base::ScopedTempDir temp_dir_; | 168 base::ScopedTempDir temp_dir_; |
163 | 169 |
164 MessageLoopForUI message_loop_; | 170 MessageLoopForUI message_loop_; |
165 | 171 |
166 // names of the database files | 172 // names of the database files |
(...skipping 19 matching lines...) Expand all Loading... |
186 content::Details<HistoryDetails> det(details); | 192 content::Details<HistoryDetails> det(details); |
187 history_test_->in_mem_backend_->Observe(type, | 193 history_test_->in_mem_backend_->Observe(type, |
188 content::Source<HistoryBackendDBTest>(NULL), det); | 194 content::Source<HistoryBackendDBTest>(NULL), det); |
189 | 195 |
190 // The backend passes ownership of the details pointer to us. | 196 // The backend passes ownership of the details pointer to us. |
191 delete details; | 197 delete details; |
192 } | 198 } |
193 | 199 |
194 namespace { | 200 namespace { |
195 | 201 |
| 202 // Schema for the downloads database for verion 23 and earlier. |
| 203 const char* kVersion23DownloadsSchema = |
| 204 "CREATE TABLE downloads (" |
| 205 "id INTEGER PRIMARY KEY," |
| 206 "full_path LONGVARCHAR NOT NULL," |
| 207 "url LONGVARCHAR NOT NULL," |
| 208 "start_time INTEGER NOT NULL," |
| 209 "received_bytes INTEGER NOT NULL," |
| 210 "total_bytes INTEGER NOT NULL," |
| 211 "state INTEGER NOT NULL," |
| 212 "end_time INTEGER NOT NULL," |
| 213 "opened INTEGER NOT NULL)"; |
| 214 |
196 TEST_F(HistoryBackendDBTest, ClearBrowsingData_Downloads) { | 215 TEST_F(HistoryBackendDBTest, ClearBrowsingData_Downloads) { |
197 CreateBackendAndDatabase(); | 216 CreateBackendAndDatabase(); |
198 | 217 |
199 // Initially there should be nothing in the downloads database. | 218 // Initially there should be nothing in the downloads database. |
200 std::vector<DownloadRow> downloads; | 219 std::vector<DownloadRow> downloads; |
201 db_->QueryDownloads(&downloads); | 220 db_->QueryDownloads(&downloads); |
202 EXPECT_EQ(0U, downloads.size()); | 221 EXPECT_EQ(0U, downloads.size()); |
203 | 222 |
204 // Add a download, test that it was added, remove it, test that it was | 223 // Add a download, test that it was added, remove it, test that it was |
205 // removed. | 224 // removed. |
(...skipping 13 matching lines...) Expand all Loading... |
219 { | 238 { |
220 // Re-open the db for manual manipulation. | 239 // Re-open the db for manual manipulation. |
221 sql::Connection db; | 240 sql::Connection db; |
222 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename))); | 241 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename))); |
223 { | 242 { |
224 // Manually force the version to 22. | 243 // Manually force the version to 22. |
225 sql::Statement version22(db.GetUniqueStatement( | 244 sql::Statement version22(db.GetUniqueStatement( |
226 "UPDATE meta SET value=22 WHERE key='version'")); | 245 "UPDATE meta SET value=22 WHERE key='version'")); |
227 ASSERT_TRUE(version22.Run()); | 246 ASSERT_TRUE(version22.Run()); |
228 } | 247 } |
| 248 // Nuke the new tables and create an old one. |
| 249 ASSERT_TRUE(db.Execute("DROP TABLE downloads")); |
| 250 ASSERT_TRUE(db.Execute("DROP TABLE downloads_url_chains")); |
| 251 ASSERT_TRUE(db.Execute(kVersion23DownloadsSchema)); |
| 252 |
229 // Manually insert corrupted rows; there's infrastructure in place now to | 253 // Manually insert corrupted rows; there's infrastructure in place now to |
230 // make this impossible, at least according to the test above. | 254 // make this impossible, at least according to the test above. |
231 for (int state = 0; state < 5; ++state) { | 255 for (int state = 0; state < 5; ++state) { |
232 sql::Statement s(db.GetUniqueStatement( | 256 sql::Statement s(db.GetUniqueStatement( |
233 "INSERT INTO downloads (id, full_path, url, start_time, " | 257 "INSERT INTO downloads (id, full_path, url, start_time, " |
234 "received_bytes, total_bytes, state, end_time, opened) VALUES " | 258 "received_bytes, total_bytes, state, end_time, opened) VALUES " |
235 "(?, ?, ?, ?, ?, ?, ?, ?, ?)")); | 259 "(?, ?, ?, ?, ?, ?, ?, ?, ?)")); |
236 s.BindInt64(0, 1 + state); | 260 s.BindInt64(0, 1 + state); |
237 s.BindString(1, "path"); | 261 s.BindString(1, "path"); |
238 s.BindString(2, "url"); | 262 s.BindString(2, "url"); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 // 4. | 300 // 4. |
277 EXPECT_EQ(((counter == 3) ? 4 : counter), statement.ColumnInt(1)); | 301 EXPECT_EQ(((counter == 3) ? 4 : counter), statement.ColumnInt(1)); |
278 EXPECT_EQ(counter % 2, statement.ColumnInt(2)); | 302 EXPECT_EQ(counter % 2, statement.ColumnInt(2)); |
279 ++counter; | 303 ++counter; |
280 } | 304 } |
281 EXPECT_EQ(5, counter); | 305 EXPECT_EQ(5, counter); |
282 } | 306 } |
283 } | 307 } |
284 } | 308 } |
285 | 309 |
| 310 TEST_F(HistoryBackendDBTest, MigrateDownloadsReasonPathsAndDangerType) { |
| 311 Time now(base::Time::Now()); |
| 312 |
| 313 // Create the db and close it so that we can reopen it directly. |
| 314 CreateBackendAndDatabase(); |
| 315 DeleteBackend(); |
| 316 { |
| 317 // Re-open the db for manual manipulation. |
| 318 sql::Connection db; |
| 319 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename))); |
| 320 { |
| 321 // Manually force the version to 23. |
| 322 sql::Statement version23(db.GetUniqueStatement( |
| 323 "UPDATE meta SET value=23 WHERE key='version'")); |
| 324 ASSERT_TRUE(version23.Run()); |
| 325 } |
| 326 |
| 327 // Nuke the new tables and create an old one with some hand crafted |
| 328 // values in it. |
| 329 ASSERT_TRUE(db.Execute("DROP TABLE downloads")); |
| 330 ASSERT_TRUE(db.Execute("DROP TABLE downloads_url_chains")); |
| 331 ASSERT_TRUE(db.Execute(kVersion23DownloadsSchema)); |
| 332 |
| 333 // Manually insert some rows. |
| 334 sql::Statement s(db.GetUniqueStatement( |
| 335 "INSERT INTO downloads (id, full_path, url, start_time, " |
| 336 "received_bytes, total_bytes, state, end_time, opened) VALUES " |
| 337 "(?, ?, ?, ?, ?, ?, ?, ?, ?)")); |
| 338 |
| 339 int64 db_handle = 0; |
| 340 // Null path. |
| 341 s.BindInt64(0, ++db_handle); |
| 342 s.BindString(1, ""); |
| 343 s.BindString(2, "http://whatever.com/index.html"); |
| 344 s.BindInt64(3, now.ToTimeT()); |
| 345 s.BindInt64(4, 100); |
| 346 s.BindInt64(5, 100); |
| 347 s.BindInt(6, 1); |
| 348 s.BindInt64(7, now.ToTimeT()); |
| 349 s.BindInt(8, 1); |
| 350 ASSERT_TRUE(s.Run()); |
| 351 s.Reset(true); |
| 352 |
| 353 // Non-null path. |
| 354 s.BindInt64(0, ++db_handle); |
| 355 s.BindString(1, "/path/to/some/file"); |
| 356 s.BindString(2, "http://whatever.com/index1.html"); |
| 357 s.BindInt64(3, now.ToTimeT()); |
| 358 s.BindInt64(4, 100); |
| 359 s.BindInt64(5, 100); |
| 360 s.BindInt(6, 1); |
| 361 s.BindInt64(7, now.ToTimeT()); |
| 362 s.BindInt(8, 1); |
| 363 ASSERT_TRUE(s.Run()); |
| 364 } |
| 365 |
| 366 // Re-open the db using the HistoryDatabase, which should migrate from version |
| 367 // 23 to 24, creating the new tables and creating the new path, reason, |
| 368 // and danger columns. |
| 369 CreateBackendAndDatabase(); |
| 370 DeleteBackend(); |
| 371 { |
| 372 // Re-open the db for manual manipulation. |
| 373 sql::Connection db; |
| 374 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename))); |
| 375 { |
| 376 // The version should have been updated. |
| 377 int cur_version = HistoryDatabase::GetCurrentVersion(); |
| 378 ASSERT_LT(23, cur_version); |
| 379 sql::Statement s(db.GetUniqueStatement( |
| 380 "SELECT value FROM meta WHERE key = 'version'")); |
| 381 EXPECT_TRUE(s.Step()); |
| 382 EXPECT_EQ(cur_version, s.ColumnInt(0)); |
| 383 } |
| 384 { |
| 385 base::Time nowish(base::Time::FromTimeT(now.ToTimeT())); |
| 386 |
| 387 // Confirm downloads table is valid. |
| 388 sql::Statement statement(db.GetUniqueStatement( |
| 389 "SELECT id, interrupt_reason, current_path, target_path, " |
| 390 " danger_type, start_time, end_time " |
| 391 "FROM downloads ORDER BY id")); |
| 392 EXPECT_TRUE(statement.Step()); |
| 393 EXPECT_EQ(1, statement.ColumnInt64(0)); |
| 394 EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE, |
| 395 statement.ColumnInt(1)); |
| 396 EXPECT_EQ("", statement.ColumnString(2)); |
| 397 EXPECT_EQ("", statement.ColumnString(3)); |
| 398 // Implicit dependence on value of kDangerTypeNotDangerous from |
| 399 // download_database.cc. |
| 400 EXPECT_EQ(0, statement.ColumnInt(4)); |
| 401 EXPECT_EQ(nowish.ToInternalValue(), statement.ColumnInt64(5)); |
| 402 EXPECT_EQ(nowish.ToInternalValue(), statement.ColumnInt64(6)); |
| 403 |
| 404 EXPECT_TRUE(statement.Step()); |
| 405 EXPECT_EQ(2, statement.ColumnInt64(0)); |
| 406 EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE, |
| 407 statement.ColumnInt(1)); |
| 408 EXPECT_EQ("/path/to/some/file", statement.ColumnString(2)); |
| 409 EXPECT_EQ("/path/to/some/file", statement.ColumnString(3)); |
| 410 EXPECT_EQ(0, statement.ColumnInt(4)); |
| 411 EXPECT_EQ(nowish.ToInternalValue(), statement.ColumnInt64(5)); |
| 412 EXPECT_EQ(nowish.ToInternalValue(), statement.ColumnInt64(6)); |
| 413 |
| 414 EXPECT_FALSE(statement.Step()); |
| 415 } |
| 416 { |
| 417 // Confirm downloads_url_chains table is valid. |
| 418 sql::Statement statement(db.GetUniqueStatement( |
| 419 "SELECT id, chain_index, url FROM downloads_url_chains " |
| 420 " ORDER BY id, chain_index")); |
| 421 EXPECT_TRUE(statement.Step()); |
| 422 EXPECT_EQ(1, statement.ColumnInt64(0)); |
| 423 EXPECT_EQ(0, statement.ColumnInt(1)); |
| 424 EXPECT_EQ("http://whatever.com/index.html", statement.ColumnString(2)); |
| 425 |
| 426 EXPECT_TRUE(statement.Step()); |
| 427 EXPECT_EQ(2, statement.ColumnInt64(0)); |
| 428 EXPECT_EQ(0, statement.ColumnInt(1)); |
| 429 EXPECT_EQ("http://whatever.com/index1.html", statement.ColumnString(2)); |
| 430 |
| 431 EXPECT_FALSE(statement.Step()); |
| 432 } |
| 433 } |
| 434 } |
| 435 |
| 436 TEST_F(HistoryBackendDBTest, ConfirmDownloadRowCreateAndDelete) { |
| 437 // Create the DB. |
| 438 CreateBackendAndDatabase(); |
| 439 |
| 440 base::Time now(base::Time::Now()); |
| 441 |
| 442 // Add some downloads. |
| 443 AddDownload(DownloadItem::COMPLETE, now); |
| 444 int64 did2 = AddDownload(DownloadItem::COMPLETE, now + |
| 445 base::TimeDelta::FromDays(2)); |
| 446 int64 did3 = AddDownload(DownloadItem::COMPLETE, now - |
| 447 base::TimeDelta::FromDays(2)); |
| 448 |
| 449 // Confirm that resulted in the correct number of rows in the DB. |
| 450 DeleteBackend(); |
| 451 { |
| 452 sql::Connection db; |
| 453 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename))); |
| 454 sql::Statement statement(db.GetUniqueStatement( |
| 455 "Select Count(*) from downloads")); |
| 456 EXPECT_TRUE(statement.Step()); |
| 457 EXPECT_EQ(3, statement.ColumnInt(0)); |
| 458 |
| 459 sql::Statement statement1(db.GetUniqueStatement( |
| 460 "Select Count(*) from downloads_url_chains")); |
| 461 EXPECT_TRUE(statement1.Step()); |
| 462 EXPECT_EQ(3, statement1.ColumnInt(0)); |
| 463 } |
| 464 |
| 465 // Delete some rows and make sure the results are still correct. |
| 466 CreateBackendAndDatabase(); |
| 467 db_->RemoveDownload(did2); |
| 468 db_->RemoveDownload(did3); |
| 469 DeleteBackend(); |
| 470 { |
| 471 sql::Connection db; |
| 472 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename))); |
| 473 sql::Statement statement(db.GetUniqueStatement( |
| 474 "Select Count(*) from downloads")); |
| 475 EXPECT_TRUE(statement.Step()); |
| 476 EXPECT_EQ(1, statement.ColumnInt(0)); |
| 477 |
| 478 sql::Statement statement1(db.GetUniqueStatement( |
| 479 "Select Count(*) from downloads_url_chains")); |
| 480 EXPECT_TRUE(statement1.Step()); |
| 481 EXPECT_EQ(1, statement1.ColumnInt(0)); |
| 482 } |
| 483 } |
| 484 |
| 485 struct InterruptReasonAssociation { |
| 486 std::string name; |
| 487 int value; |
| 488 }; |
| 489 |
| 490 // Test is dependent on interrupt reasons being listed in header file |
| 491 // in order. |
| 492 const InterruptReasonAssociation current_reasons[] = { |
| 493 #define INTERRUPT_REASON(a, b) { #a, b }, |
| 494 #include "content/public/browser/download_interrupt_reason_values.h" |
| 495 #undef INTERRUPT_REASON |
| 496 }; |
| 497 |
| 498 // This represents a list of all reasons we've previously used; |
| 499 // Do Not Remove Any Entries From This List. |
| 500 const InterruptReasonAssociation historical_reasons[] = { |
| 501 {"FILE_FAILED", 1}, |
| 502 {"FILE_ACCESS_DENIED", 2}, |
| 503 {"FILE_NO_SPACE", 3}, |
| 504 {"FILE_NAME_TOO_LONG", 5}, |
| 505 {"FILE_TOO_LARGE", 6}, |
| 506 {"FILE_VIRUS_INFECTED", 7}, |
| 507 {"FILE_TRANSIENT_ERROR", 10}, |
| 508 {"FILE_BLOCKED", 11}, |
| 509 {"FILE_SECURITY_CHECK_FAILED", 12}, |
| 510 {"FILE_TOO_SHORT", 13}, |
| 511 {"NETWORK_FAILED", 20}, |
| 512 {"NETWORK_TIMEOUT", 21}, |
| 513 {"NETWORK_DISCONNECTED", 22}, |
| 514 {"NETWORK_SERVER_DOWN", 23}, |
| 515 {"SERVER_FAILED", 30}, |
| 516 {"SERVER_NO_RANGE", 31}, |
| 517 {"SERVER_PRECONDITION", 32}, |
| 518 {"SERVER_BAD_CONTENT", 33}, |
| 519 {"USER_CANCELED", 40}, |
| 520 {"USER_SHUTDOWN", 41}, |
| 521 {"CRASH", 50}, |
| 522 }; |
| 523 |
| 524 // Make sure no one has changed a DownloadInterruptReason we've previously |
| 525 // persisted. |
| 526 TEST_F(HistoryBackendDBTest, |
| 527 ConfirmDownloadInterruptReasonBackwardsCompatible) { |
| 528 // Are there any cases in which a historical number has been repurposed |
| 529 // for an error other than it's original? |
| 530 for (size_t i = 0; i < arraysize(current_reasons); i++) { |
| 531 const InterruptReasonAssociation& cur_reason(current_reasons[i]); |
| 532 bool found = false; |
| 533 |
| 534 for (size_t j = 0; j < arraysize(historical_reasons); ++j) { |
| 535 const InterruptReasonAssociation& hist_reason(historical_reasons[j]); |
| 536 |
| 537 if (hist_reason.value == cur_reason.value) { |
| 538 EXPECT_EQ(cur_reason.name, hist_reason.name) |
| 539 << "Same integer value used for old error \"" |
| 540 << hist_reason.name |
| 541 << "\" as for new error \"" |
| 542 << cur_reason.name |
| 543 << "\"." << std::endl |
| 544 << "**This will cause database conflicts with persisted values**" |
| 545 << std::endl |
| 546 << "Please assign a new, non-conflicting value for the new error."; |
| 547 } |
| 548 |
| 549 if (hist_reason.name == cur_reason.name) { |
| 550 EXPECT_EQ(cur_reason.value, hist_reason.value) |
| 551 << "Same name (\"" << hist_reason.name |
| 552 << "\") maps to a different value historically (" |
| 553 << hist_reason.value << ") and currently (" |
| 554 << cur_reason.value << ")" << std::endl |
| 555 << "This may cause database conflicts with persisted values" |
| 556 << std::endl |
| 557 << "If this error is the same as the old one, you should" |
| 558 << std::endl |
| 559 << "use the old value, and if it is different, you should" |
| 560 << std::endl |
| 561 << "use a new name."; |
| 562 |
| 563 found = true; |
| 564 } |
| 565 } |
| 566 |
| 567 EXPECT_TRUE(found) |
| 568 << "Error \"" << cur_reason.name << "\" not found in historical list." |
| 569 << std::endl |
| 570 << "Please add it."; |
| 571 } |
| 572 } |
| 573 |
286 // The tracker uses RenderProcessHost pointers for scoping but never | 574 // The tracker uses RenderProcessHost pointers for scoping but never |
287 // dereferences them. We use ints because it's easier. This function converts | 575 // dereferences them. We use ints because it's easier. This function converts |
288 // between the two. | 576 // between the two. |
289 static void* MakeFakeHost(int id) { | 577 static void* MakeFakeHost(int id) { |
290 void* host = 0; | 578 void* host = 0; |
291 memcpy(&host, &id, sizeof(id)); | 579 memcpy(&host, &id, sizeof(id)); |
292 return host; | 580 return host; |
293 } | 581 } |
294 | 582 |
295 class HistoryTest : public testing::Test { | 583 class HistoryTest : public testing::Test { |
(...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1175 | 1463 |
1176 history_service_->StopSyncing(syncer::HISTORY_DELETE_DIRECTIVES); | 1464 history_service_->StopSyncing(syncer::HISTORY_DELETE_DIRECTIVES); |
1177 EXPECT_TRUE( | 1465 EXPECT_TRUE( |
1178 history_service_->ProcessLocalDeleteDirective(delete_directive).IsSet()); | 1466 history_service_->ProcessLocalDeleteDirective(delete_directive).IsSet()); |
1179 EXPECT_EQ(1u, change_processor.GetChanges().size()); | 1467 EXPECT_EQ(1u, change_processor.GetChanges().size()); |
1180 } | 1468 } |
1181 | 1469 |
1182 } // namespace | 1470 } // namespace |
1183 | 1471 |
1184 } // namespace history | 1472 } // namespace history |
OLD | NEW |