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

Side by Side Diff: chrome/browser/history/history_unittest.cc

Issue 11363222: Persist download interrupt reason, both target and current paths, and url_chain. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added test requested by reviewers. Created 8 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 | Annotate | Revision Log
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 // 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 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 virtual void TearDown() { 130 virtual void TearDown() {
131 DeleteBackend(); 131 DeleteBackend();
132 132
133 // Make sure we don't have any event pending that could disrupt the next 133 // Make sure we don't have any event pending that could disrupt the next
134 // test. 134 // test.
135 MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); 135 MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
136 MessageLoop::current()->Run(); 136 MessageLoop::current()->Run();
137 } 137 }
138 138
139 int64 AddDownload(DownloadItem::DownloadState state, const Time& time) { 139 int64 AddDownload(DownloadItem::DownloadState state, const Time& time) {
140 std::vector<GURL> url_chain;
141 url_chain.push_back(GURL("foo-url"));
142
140 DownloadPersistentStoreInfo download( 143 DownloadPersistentStoreInfo download(
141 FilePath(FILE_PATH_LITERAL("foo-path")), 144 FilePath(FILE_PATH_LITERAL("foo-path")),
142 GURL("foo-url"), 145 FilePath(FILE_PATH_LITERAL("foo-path")),
146 url_chain,
143 GURL(""), 147 GURL(""),
144 time, 148 time,
145 time, 149 time,
146 0, 150 0,
147 512, 151 512,
148 state, 152 state,
153 content::DOWNLOAD_INTERRUPT_REASON_NONE,
149 0, 154 0,
150 0); 155 0);
151 return db_->CreateDownload(download); 156 return db_->CreateDownload(download);
152 } 157 }
153 158
154 ScopedTempDir temp_dir_; 159 ScopedTempDir temp_dir_;
155 160
156 MessageLoopForUI message_loop_; 161 MessageLoopForUI message_loop_;
157 162
158 // names of the database files 163 // names of the database files
(...skipping 19 matching lines...) Expand all
178 content::Details<HistoryDetails> det(details); 183 content::Details<HistoryDetails> det(details);
179 history_test_->in_mem_backend_->Observe(type, 184 history_test_->in_mem_backend_->Observe(type,
180 content::Source<HistoryBackendDBTest>(NULL), det); 185 content::Source<HistoryBackendDBTest>(NULL), det);
181 186
182 // The backend passes ownership of the details pointer to us. 187 // The backend passes ownership of the details pointer to us.
183 delete details; 188 delete details;
184 } 189 }
185 190
186 namespace { 191 namespace {
187 192
193 // Schema for the downloads database for verion 23 and earlier.
194 const char* kVersion23DownloadsSchema =
195 "CREATE TABLE downloads ("
196 "id INTEGER PRIMARY KEY,"
197 "full_path LONGVARCHAR NOT NULL,"
198 "url LONGVARCHAR NOT NULL,"
199 "start_time INTEGER NOT NULL,"
200 "received_bytes INTEGER NOT NULL,"
201 "total_bytes INTEGER NOT NULL,"
202 "state INTEGER NOT NULL,"
203 "end_time INTEGER NOT NULL,"
204 "opened INTEGER NOT NULL)";
205
188 TEST_F(HistoryBackendDBTest, ClearBrowsingData_Downloads) { 206 TEST_F(HistoryBackendDBTest, ClearBrowsingData_Downloads) {
189 CreateBackendAndDatabase(); 207 CreateBackendAndDatabase();
190 208
191 Time now = Time::Now(); 209 Time now = Time::Now();
192 TimeDelta one_day = TimeDelta::FromDays(1); 210 TimeDelta one_day = TimeDelta::FromDays(1);
193 Time month_ago = now - TimeDelta::FromDays(30); 211 Time month_ago = now - TimeDelta::FromDays(30);
194 212
195 // Initially there should be nothing in the downloads database. 213 // Initially there should be nothing in the downloads database.
196 std::vector<DownloadPersistentStoreInfo> downloads; 214 std::vector<DownloadPersistentStoreInfo> downloads;
197 db_->QueryDownloads(&downloads); 215 db_->QueryDownloads(&downloads);
(...skipping 23 matching lines...) Expand all
221 db_->RemoveDownloadsBetween(now, Time()); 239 db_->RemoveDownloadsBetween(now, Time());
222 db_->QueryDownloads(&downloads); 240 db_->QueryDownloads(&downloads);
223 EXPECT_EQ(6U, downloads.size()); 241 EXPECT_EQ(6U, downloads.size());
224 242
225 // Try removing from two months ago. This should not delete items that are 243 // Try removing from two months ago. This should not delete items that are
226 // 'in progress' or in 'removing' state. 244 // 'in progress' or in 'removing' state.
227 db_->RemoveDownloadsBetween(now - TimeDelta::FromDays(60), Time()); 245 db_->RemoveDownloadsBetween(now - TimeDelta::FromDays(60), Time());
228 db_->QueryDownloads(&downloads); 246 db_->QueryDownloads(&downloads);
229 EXPECT_EQ(2U, downloads.size()); 247 EXPECT_EQ(2U, downloads.size());
230 248
231 // Download manager converts to TimeT, which is lossy, so we do the same
232 // for comparison.
233 Time month_ago_lossy = Time::FromTimeT(month_ago.ToTimeT());
234
235 // Make sure the right values remain. 249 // Make sure the right values remain.
236 EXPECT_EQ(DownloadItem::COMPLETE, downloads[0].state); 250 EXPECT_EQ(DownloadItem::COMPLETE, downloads[0].state);
237 EXPECT_EQ(0, downloads[0].start_time.ToInternalValue()); 251 EXPECT_EQ(0, downloads[0].start_time.ToInternalValue());
238 EXPECT_EQ(DownloadItem::IN_PROGRESS, downloads[1].state); 252 EXPECT_EQ(DownloadItem::IN_PROGRESS, downloads[1].state);
239 EXPECT_EQ(month_ago_lossy.ToInternalValue(), 253 EXPECT_EQ(month_ago.ToInternalValue(),
240 downloads[1].start_time.ToInternalValue()); 254 downloads[1].start_time.ToInternalValue());
241 255
242 // Change state so we can delete the downloads. 256 // Change state so we can delete the downloads.
243 DownloadPersistentStoreInfo data; 257 DownloadPersistentStoreInfo data;
244 data.received_bytes = 512; 258 data.received_bytes = 512;
245 data.state = DownloadItem::COMPLETE; 259 data.state = DownloadItem::COMPLETE;
246 data.end_time = base::Time::Now(); 260 data.end_time = base::Time::Now();
247 data.opened = false; 261 data.opened = false;
248 data.db_handle = in_progress; 262 data.db_handle = in_progress;
249 EXPECT_TRUE(db_->UpdateDownload(data)); 263 EXPECT_TRUE(db_->UpdateDownload(data));
(...skipping 29 matching lines...) Expand all
279 { 293 {
280 // Re-open the db for manual manipulation. 294 // Re-open the db for manual manipulation.
281 sql::Connection db; 295 sql::Connection db;
282 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename))); 296 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
283 { 297 {
284 // Manually force the version to 22. 298 // Manually force the version to 22.
285 sql::Statement version22(db.GetUniqueStatement( 299 sql::Statement version22(db.GetUniqueStatement(
286 "UPDATE meta SET value=22 WHERE key='version'")); 300 "UPDATE meta SET value=22 WHERE key='version'"));
287 ASSERT_TRUE(version22.Run()); 301 ASSERT_TRUE(version22.Run());
288 } 302 }
303 // Nuke the new tables and create an old one.
304 ASSERT_TRUE(db.Execute("DROP TABLE downloads"));
305 ASSERT_TRUE(db.Execute("DROP TABLE downloads_url_chains"));
306 ASSERT_TRUE(db.Execute(kVersion23DownloadsSchema));
307
289 // Manually insert corrupted rows; there's infrastructure in place now to 308 // Manually insert corrupted rows; there's infrastructure in place now to
290 // make this impossible, at least according to the test above. 309 // make this impossible, at least according to the test above.
291 for (int state = 0; state < 5; ++state) { 310 for (int state = 0; state < 5; ++state) {
292 sql::Statement s(db.GetUniqueStatement( 311 sql::Statement s(db.GetUniqueStatement(
293 "INSERT INTO downloads (id, full_path, url, start_time, " 312 "INSERT INTO downloads (id, full_path, url, start_time, "
294 "received_bytes, total_bytes, state, end_time, opened) VALUES " 313 "received_bytes, total_bytes, state, end_time, opened) VALUES "
295 "(?, ?, ?, ?, ?, ?, ?, ?, ?)")); 314 "(?, ?, ?, ?, ?, ?, ?, ?, ?)"));
296 s.BindInt64(0, 1 + state); 315 s.BindInt64(0, 1 + state);
297 s.BindString(1, "path"); 316 s.BindString(1, "path");
298 s.BindString(2, "url"); 317 s.BindString(2, "url");
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 // 4. 355 // 4.
337 EXPECT_EQ(((counter == 3) ? 4 : counter), statement.ColumnInt(1)); 356 EXPECT_EQ(((counter == 3) ? 4 : counter), statement.ColumnInt(1));
338 EXPECT_EQ(counter % 2, statement.ColumnInt(2)); 357 EXPECT_EQ(counter % 2, statement.ColumnInt(2));
339 ++counter; 358 ++counter;
340 } 359 }
341 EXPECT_EQ(5, counter); 360 EXPECT_EQ(5, counter);
342 } 361 }
343 } 362 }
344 } 363 }
345 364
365 TEST_F(HistoryBackendDBTest, MigrateDownloadsReasonAndPaths) {
366 Time now(base::Time::Now());
367
368 // Create the db and close it so that we can reopen it directly.
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 // Manually force the version to 23.
377 sql::Statement version23(db.GetUniqueStatement(
378 "UPDATE meta SET value=23 WHERE key='version'"));
379 ASSERT_TRUE(version23.Run());
380 }
381
382 // Nuke the new tables and create an old one with some hand crafted
383 // values in it.
384 ASSERT_TRUE(db.Execute("DROP TABLE downloads"));
385 ASSERT_TRUE(db.Execute("DROP TABLE downloads_url_chains"));
386 ASSERT_TRUE(db.Execute(kVersion23DownloadsSchema));
387
388 // Manually insert some rows.
389 sql::Statement s(db.GetUniqueStatement(
390 "INSERT INTO downloads (id, full_path, url, start_time, "
391 "received_bytes, total_bytes, state, end_time, opened) VALUES "
392 "(?, ?, ?, ?, ?, ?, ?, ?, ?)"));
393
394 int64 db_handle = 0;
395 // Null path.
396 s.BindInt64(0, ++db_handle);
397 s.BindString(1, "");
398 s.BindString(2, "http://whatever.com/index.html");
399 s.BindInt64(3, now.ToTimeT());
400 s.BindInt64(4, 100);
401 s.BindInt64(5, 100);
402 s.BindInt(6, 1);
403 s.BindInt64(7, now.ToTimeT());
404 s.BindInt(8, 1);
405 ASSERT_TRUE(s.Run());
406 s.Reset(true);
407
408 // Non-null path.
409 s.BindInt64(0, ++db_handle);
410 s.BindString(1, "/path/to/some/file");
411 s.BindString(2, "http://whatever.com/index1.html");
412 s.BindInt64(3, now.ToTimeT());
413 s.BindInt64(4, 100);
414 s.BindInt64(5, 100);
415 s.BindInt(6, 1);
416 s.BindInt64(7, now.ToTimeT());
417 s.BindInt(8, 1);
418 ASSERT_TRUE(s.Run());
419 }
420
421 // Re-open the db using the HistoryDatabase, which should migrate from version
422 // 23 to 24, creating the new tables and creating the new path and reason
423 // columns.
424 CreateBackendAndDatabase();
425 DeleteBackend();
426 {
427 // Re-open the db for manual manipulation.
428 sql::Connection db;
429 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
430 {
431 // The version should have been updated.
432 int cur_version = HistoryDatabase::GetCurrentVersion();
433 ASSERT_LT(23, cur_version);
434 sql::Statement s(db.GetUniqueStatement(
435 "SELECT value FROM meta WHERE key = 'version'"));
436 EXPECT_TRUE(s.Step());
437 EXPECT_EQ(cur_version, s.ColumnInt(0));
438 }
439 {
440 base::Time nowish(base::Time::FromTimeT(now.ToTimeT()));
441
442 // Confirm downloads table is valid.
443 sql::Statement statement(db.GetUniqueStatement(
444 "SELECT id, interrupt_reason, target_path, current_path, "
445 " start_time, end_time "
446 "FROM downloads ORDER BY id"));
447 EXPECT_TRUE(statement.Step());
448 EXPECT_EQ(1, statement.ColumnInt64(0));
449 EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE,
450 statement.ColumnInt(1));
451 EXPECT_EQ("", statement.ColumnString(2));
452 EXPECT_EQ("", statement.ColumnString(3));
453 EXPECT_EQ(nowish.ToInternalValue(), statement.ColumnInt64(4));
454 EXPECT_EQ(nowish.ToInternalValue(), statement.ColumnInt64(5));
455
456 EXPECT_TRUE(statement.Step());
457 EXPECT_EQ(2, statement.ColumnInt64(0));
458 EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE,
459 statement.ColumnInt(1));
460 EXPECT_EQ("/path/to/some/file", statement.ColumnString(2));
461 EXPECT_EQ("/path/to/some/file", statement.ColumnString(3));
462 EXPECT_EQ(nowish.ToInternalValue(), statement.ColumnInt64(4));
463 EXPECT_EQ(nowish.ToInternalValue(), statement.ColumnInt64(5));
464
465 EXPECT_FALSE(statement.Step());
466 }
467 {
468 // Confirm donwloads_url_chains table is valid.
469 sql::Statement statement(db.GetUniqueStatement(
470 "SELECT id, chain_index, url FROM downloads_url_chains "
471 " ORDER BY id, chain_index"));
472 EXPECT_TRUE(statement.Step());
473 EXPECT_EQ(1, statement.ColumnInt64(0));
474 EXPECT_EQ(0, statement.ColumnInt(1));
475 EXPECT_EQ("http://whatever.com/index.html", statement.ColumnString(2));
476
477 EXPECT_TRUE(statement.Step());
478 EXPECT_EQ(2, statement.ColumnInt64(0));
479 EXPECT_EQ(0, statement.ColumnInt(1));
480 EXPECT_EQ("http://whatever.com/index1.html", statement.ColumnString(2));
481
482 EXPECT_FALSE(statement.Step());
483 }
484 }
485 }
486
487 TEST_F(HistoryBackendDBTest, ConfirmDownloadRowCreateAndDelete) {
488 // Create the DB.
489 CreateBackendAndDatabase();
490
491 base::Time now(base::Time::Now());
492
493 // Add some downloads.
494 AddDownload(DownloadItem::COMPLETE, now);
495 int64 did2 = AddDownload(DownloadItem::COMPLETE, now +
496 base::TimeDelta::FromDays(2));
497 int64 did3 = AddDownload(DownloadItem::COMPLETE, now -
498 base::TimeDelta::FromDays(2));
499
500 // Confirm that resulted in the correct number of rows in the DB.
501 DeleteBackend();
502 {
503 sql::Connection db;
504 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
505 sql::Statement statement(db.GetUniqueStatement(
506 "Select Count(*) from downloads"));
507 EXPECT_TRUE(statement.Step());
508 EXPECT_EQ(3, statement.ColumnInt(0));
509
510 sql::Statement statement1(db.GetUniqueStatement(
511 "Select Count(*) from downloads_url_chains"));
512 EXPECT_TRUE(statement1.Step());
513 EXPECT_EQ(3, statement1.ColumnInt(0));
514 }
515
516 // Delete some rows and make sure the results are still correct.
517 CreateBackendAndDatabase();
518 db_->RemoveDownload(did2);
519 db_->RemoveDownload(did3);
520 DeleteBackend();
521 {
522 sql::Connection db;
523 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
524 sql::Statement statement(db.GetUniqueStatement(
525 "Select Count(*) from downloads"));
526 EXPECT_TRUE(statement.Step());
527 EXPECT_EQ(1, statement.ColumnInt(0));
528
529 sql::Statement statement1(db.GetUniqueStatement(
530 "Select Count(*) from downloads_url_chains"));
531 EXPECT_TRUE(statement1.Step());
532 EXPECT_EQ(1, statement1.ColumnInt(0));
533 }
534 }
535
536 struct InterruptReasonAssociation {
537 std::string name;
538 int value;
539 };
540
541 // Test is dependent on interrupt reasons being listed in header file
542 // in order.
543 const InterruptReasonAssociation current_reasons[] = {
544 #define INTERRUPT_REASON(a, b) { #a, b },
545 #include "content/public/browser/download_interrupt_reason_values.h"
546 #undef INTERRUPT_REASON
547 };
548 const InterruptReasonAssociation historical_reasons[] = {
benjhayden 2012/11/19 15:22:07 Newline before this line and a comment forbidding
Randy Smith (Not in Mondays) 2012/12/09 15:14:45 Done.
549 { "FILE_FAILED", 1 },
550 { "FILE_ACCESS_DENIED", 2 },
551 { "FILE_NO_SPACE", 3 },
552 { "FILE_NAME_TOO_LONG", 5 },
553 { "FILE_TOO_LARGE", 6 },
554 { "FILE_VIRUS_INFECTED", 7 },
555 { "FILE_TRANSIENT_ERROR", 10 },
556 { "FILE_BLOCKED", 11 },
557 { "FILE_SECURITY_CHECK_FAILED", 12 },
558 { "NETWORK_FAILED", 20 },
559 { "NETWORK_TIMEOUT", 21 },
560 { "NETWORK_DISCONNECTED", 22 },
561 { "NETWORK_SERVER_DOWN", 23 },
562 { "SERVER_FAILED", 30 },
563 { "SERVER_NO_RANGE", 31 },
564 { "SERVER_PRECONDITION", 32 },
565 { "SERVER_BAD_CONTENT", 33 },
566 { "USER_CANCELED", 40 },
567 { "USER_SHUTDOWN", 41 },
568 { "CRASH", 50 },
569 };
570
571 // Make sure no one has changed a DownloadInterruptReason we've previously
572 // persisted.
573 TEST_F(HistoryBackendDBTest, ConfirmDownloadInterruptReasonOk) {
benjhayden 2012/11/19 15:22:07 "Confirm...Ok" is too vague. All tests confirm tha
Randy Smith (Not in Mondays) 2012/12/09 15:14:45 Done.
574 // Are there any casesin which a historical number has been repurposed
benjhayden 2012/11/19 15:22:07 "cases in"
Randy Smith (Not in Mondays) 2012/12/09 15:14:45 Done.
575 // for an error other than it's original?
576 for (size_t i = 0; i < arraysize(current_reasons); i++) {
577 const InterruptReasonAssociation& cur_reason(current_reasons[i]);
578 bool found = false;
579
580 for (size_t j = 0; j < arraysize(historical_reasons); ++j) {
581 const InterruptReasonAssociation& hist_reason(historical_reasons[j]);
582
583 if (hist_reason.value == cur_reason.value) {
584 EXPECT_EQ(cur_reason.name, hist_reason.name)
585 << "Same integer value used for old error \""
586 << hist_reason.name
587 << "\" as for new error \""
588 << cur_reason.name
589 << "\"." << std::endl
590 << "**This will cause database conflicts with persisted values**"
591 << std::endl
592 << "Please assign a new, non-conflicting value for the new error.";
593 }
594
595 if (hist_reason.name == cur_reason.name) {
596 EXPECT_EQ(cur_reason.value, hist_reason.value)
597 << "Same name (\"" << hist_reason.name
598 << "\") maps to a different value historically ("
599 << hist_reason.value << ") and currently ("
600 << cur_reason.value << ")" << std::endl
601 << "This may cause database conflicts with persisted values"
602 << std::endl
603 << "You are advised to use the same value for the same error, "
604 << "or to update this test with approriate commenting if you "
benjhayden 2012/11/19 15:22:07 When might this be appropriate?
Randy Smith (Not in Mondays) 2012/12/09 15:14:45 I couldn't think of a time, but it won't Seriously
605 << "know what you are doing.";
606
607 found = true;
608 }
609 }
610
611 EXPECT_TRUE(found)
612 << "Error \"" << cur_reason.name << "\" not found in historical list."
613 << std::endl
614 << "Please add it.";
615 }
616 }
617
346 // The tracker uses RenderProcessHost pointers for scoping but never 618 // The tracker uses RenderProcessHost pointers for scoping but never
347 // dereferences them. We use ints because it's easier. This function converts 619 // dereferences them. We use ints because it's easier. This function converts
348 // between the two. 620 // between the two.
349 static void* MakeFakeHost(int id) { 621 static void* MakeFakeHost(int id) {
350 void* host = 0; 622 void* host = 0;
351 memcpy(&host, &id, sizeof(id)); 623 memcpy(&host, &id, sizeof(id));
352 return host; 624 return host;
353 } 625 }
354 626
355 class HistoryTest : public testing::Test { 627 class HistoryTest : public testing::Test {
(...skipping 676 matching lines...) Expand 10 before | Expand all | Expand 10 after
1032 request_consumer.CancelAllRequests(); 1304 request_consumer.CancelAllRequests();
1033 CleanupHistoryService(); 1305 CleanupHistoryService();
1034 // WARNING: history has now been deleted. 1306 // WARNING: history has now been deleted.
1035 history_service_.reset(); 1307 history_service_.reset();
1036 ASSERT_FALSE(task->done_invoked); 1308 ASSERT_FALSE(task->done_invoked);
1037 } 1309 }
1038 1310
1039 } // namespace 1311 } // namespace
1040 1312
1041 } // namespace history 1313 } // namespace history
OLDNEW
« no previous file with comments | « chrome/browser/history/history_database.cc ('k') | chrome/browser/ui/webui/downloads_dom_handler_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698