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

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 binary files based on c#37 Created 7 years, 11 months 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 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698