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

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: Changed ordering of target_path and current_path everywhere to match that of DownloadItemImpl. Created 8 years 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 DownloadRow download( 143 DownloadRow 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 base::ScopedTempDir temp_dir_; 159 base::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 // Initially there should be nothing in the downloads database. 209 // Initially there should be nothing in the downloads database.
192 std::vector<DownloadRow> downloads; 210 std::vector<DownloadRow> downloads;
193 db_->QueryDownloads(&downloads); 211 db_->QueryDownloads(&downloads);
194 EXPECT_EQ(0U, downloads.size()); 212 EXPECT_EQ(0U, downloads.size());
195 213
196 // Add a download, test that it was added, remove it, test that it was 214 // Add a download, test that it was added, remove it, test that it was
197 // removed. 215 // removed.
(...skipping 13 matching lines...) Expand all
211 { 229 {
212 // Re-open the db for manual manipulation. 230 // Re-open the db for manual manipulation.
213 sql::Connection db; 231 sql::Connection db;
214 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename))); 232 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
215 { 233 {
216 // Manually force the version to 22. 234 // Manually force the version to 22.
217 sql::Statement version22(db.GetUniqueStatement( 235 sql::Statement version22(db.GetUniqueStatement(
218 "UPDATE meta SET value=22 WHERE key='version'")); 236 "UPDATE meta SET value=22 WHERE key='version'"));
219 ASSERT_TRUE(version22.Run()); 237 ASSERT_TRUE(version22.Run());
220 } 238 }
239 // Nuke the new tables and create an old one.
240 ASSERT_TRUE(db.Execute("DROP TABLE downloads"));
241 ASSERT_TRUE(db.Execute("DROP TABLE downloads_url_chains"));
242 ASSERT_TRUE(db.Execute(kVersion23DownloadsSchema));
243
221 // Manually insert corrupted rows; there's infrastructure in place now to 244 // Manually insert corrupted rows; there's infrastructure in place now to
222 // make this impossible, at least according to the test above. 245 // make this impossible, at least according to the test above.
223 for (int state = 0; state < 5; ++state) { 246 for (int state = 0; state < 5; ++state) {
224 sql::Statement s(db.GetUniqueStatement( 247 sql::Statement s(db.GetUniqueStatement(
225 "INSERT INTO downloads (id, full_path, url, start_time, " 248 "INSERT INTO downloads (id, full_path, url, start_time, "
226 "received_bytes, total_bytes, state, end_time, opened) VALUES " 249 "received_bytes, total_bytes, state, end_time, opened) VALUES "
227 "(?, ?, ?, ?, ?, ?, ?, ?, ?)")); 250 "(?, ?, ?, ?, ?, ?, ?, ?, ?)"));
228 s.BindInt64(0, 1 + state); 251 s.BindInt64(0, 1 + state);
229 s.BindString(1, "path"); 252 s.BindString(1, "path");
230 s.BindString(2, "url"); 253 s.BindString(2, "url");
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 // 4. 291 // 4.
269 EXPECT_EQ(((counter == 3) ? 4 : counter), statement.ColumnInt(1)); 292 EXPECT_EQ(((counter == 3) ? 4 : counter), statement.ColumnInt(1));
270 EXPECT_EQ(counter % 2, statement.ColumnInt(2)); 293 EXPECT_EQ(counter % 2, statement.ColumnInt(2));
271 ++counter; 294 ++counter;
272 } 295 }
273 EXPECT_EQ(5, counter); 296 EXPECT_EQ(5, counter);
274 } 297 }
275 } 298 }
276 } 299 }
277 300
301 TEST_F(HistoryBackendDBTest, MigrateDownloadsReasonAndPaths) {
302 Time now(base::Time::Now());
303
304 // Create the db and close it so that we can reopen it directly.
305 CreateBackendAndDatabase();
306 DeleteBackend();
307 {
308 // Re-open the db for manual manipulation.
309 sql::Connection db;
310 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
311 {
312 // Manually force the version to 23.
313 sql::Statement version23(db.GetUniqueStatement(
314 "UPDATE meta SET value=23 WHERE key='version'"));
315 ASSERT_TRUE(version23.Run());
316 }
317
318 // Nuke the new tables and create an old one with some hand crafted
319 // values in it.
320 ASSERT_TRUE(db.Execute("DROP TABLE downloads"));
321 ASSERT_TRUE(db.Execute("DROP TABLE downloads_url_chains"));
322 ASSERT_TRUE(db.Execute(kVersion23DownloadsSchema));
323
324 // Manually insert some rows.
325 sql::Statement s(db.GetUniqueStatement(
326 "INSERT INTO downloads (id, full_path, url, start_time, "
327 "received_bytes, total_bytes, state, end_time, opened) VALUES "
328 "(?, ?, ?, ?, ?, ?, ?, ?, ?)"));
329
330 int64 db_handle = 0;
331 // Null path.
332 s.BindInt64(0, ++db_handle);
333 s.BindString(1, "");
334 s.BindString(2, "http://whatever.com/index.html");
335 s.BindInt64(3, now.ToTimeT());
336 s.BindInt64(4, 100);
337 s.BindInt64(5, 100);
338 s.BindInt(6, 1);
339 s.BindInt64(7, now.ToTimeT());
340 s.BindInt(8, 1);
341 ASSERT_TRUE(s.Run());
342 s.Reset(true);
343
344 // Non-null path.
345 s.BindInt64(0, ++db_handle);
346 s.BindString(1, "/path/to/some/file");
347 s.BindString(2, "http://whatever.com/index1.html");
348 s.BindInt64(3, now.ToTimeT());
349 s.BindInt64(4, 100);
350 s.BindInt64(5, 100);
351 s.BindInt(6, 1);
352 s.BindInt64(7, now.ToTimeT());
353 s.BindInt(8, 1);
354 ASSERT_TRUE(s.Run());
355 }
356
357 // Re-open the db using the HistoryDatabase, which should migrate from version
358 // 23 to 24, creating the new tables and creating the new path and reason
359 // columns.
360 CreateBackendAndDatabase();
361 DeleteBackend();
362 {
363 // Re-open the db for manual manipulation.
364 sql::Connection db;
365 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
366 {
367 // The version should have been updated.
368 int cur_version = HistoryDatabase::GetCurrentVersion();
369 ASSERT_LT(23, cur_version);
370 sql::Statement s(db.GetUniqueStatement(
371 "SELECT value FROM meta WHERE key = 'version'"));
372 EXPECT_TRUE(s.Step());
373 EXPECT_EQ(cur_version, s.ColumnInt(0));
374 }
375 {
376 base::Time nowish(base::Time::FromTimeT(now.ToTimeT()));
377
378 // Confirm downloads table is valid.
379 sql::Statement statement(db.GetUniqueStatement(
380 "SELECT id, interrupt_reason, current_path, target_path, "
381 " start_time, end_time "
382 "FROM downloads ORDER BY id"));
383 EXPECT_TRUE(statement.Step());
384 EXPECT_EQ(1, statement.ColumnInt64(0));
385 EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE,
386 statement.ColumnInt(1));
387 EXPECT_EQ("", statement.ColumnString(2));
388 EXPECT_EQ("", statement.ColumnString(3));
389 EXPECT_EQ(nowish.ToInternalValue(), statement.ColumnInt64(4));
390 EXPECT_EQ(nowish.ToInternalValue(), statement.ColumnInt64(5));
391
392 EXPECT_TRUE(statement.Step());
393 EXPECT_EQ(2, statement.ColumnInt64(0));
394 EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE,
395 statement.ColumnInt(1));
396 EXPECT_EQ("/path/to/some/file", statement.ColumnString(2));
397 EXPECT_EQ("/path/to/some/file", statement.ColumnString(3));
398 EXPECT_EQ(nowish.ToInternalValue(), statement.ColumnInt64(4));
399 EXPECT_EQ(nowish.ToInternalValue(), statement.ColumnInt64(5));
400
401 EXPECT_FALSE(statement.Step());
402 }
403 {
404 // Confirm donwloads_url_chains table is valid.
benjhayden 2012/12/10 16:38:42 downloads_url_chains
Randy Smith (Not in Mondays) 2012/12/11 18:17:30 Done.
405 sql::Statement statement(db.GetUniqueStatement(
406 "SELECT id, chain_index, url FROM downloads_url_chains "
407 " ORDER BY id, chain_index"));
408 EXPECT_TRUE(statement.Step());
409 EXPECT_EQ(1, statement.ColumnInt64(0));
410 EXPECT_EQ(0, statement.ColumnInt(1));
411 EXPECT_EQ("http://whatever.com/index.html", statement.ColumnString(2));
412
413 EXPECT_TRUE(statement.Step());
414 EXPECT_EQ(2, statement.ColumnInt64(0));
415 EXPECT_EQ(0, statement.ColumnInt(1));
416 EXPECT_EQ("http://whatever.com/index1.html", statement.ColumnString(2));
417
418 EXPECT_FALSE(statement.Step());
419 }
420 }
421 }
422
423 TEST_F(HistoryBackendDBTest, ConfirmDownloadRowCreateAndDelete) {
424 // Create the DB.
425 CreateBackendAndDatabase();
426
427 base::Time now(base::Time::Now());
428
429 // Add some downloads.
430 AddDownload(DownloadItem::COMPLETE, now);
431 int64 did2 = AddDownload(DownloadItem::COMPLETE, now +
432 base::TimeDelta::FromDays(2));
433 int64 did3 = AddDownload(DownloadItem::COMPLETE, now -
434 base::TimeDelta::FromDays(2));
435
436 // Confirm that resulted in the correct number of rows in the DB.
437 DeleteBackend();
438 {
439 sql::Connection db;
440 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
441 sql::Statement statement(db.GetUniqueStatement(
442 "Select Count(*) from downloads"));
443 EXPECT_TRUE(statement.Step());
444 EXPECT_EQ(3, statement.ColumnInt(0));
445
446 sql::Statement statement1(db.GetUniqueStatement(
447 "Select Count(*) from downloads_url_chains"));
448 EXPECT_TRUE(statement1.Step());
449 EXPECT_EQ(3, statement1.ColumnInt(0));
450 }
451
452 // Delete some rows and make sure the results are still correct.
453 CreateBackendAndDatabase();
454 db_->RemoveDownload(did2);
455 db_->RemoveDownload(did3);
456 DeleteBackend();
457 {
458 sql::Connection db;
459 ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
460 sql::Statement statement(db.GetUniqueStatement(
461 "Select Count(*) from downloads"));
462 EXPECT_TRUE(statement.Step());
463 EXPECT_EQ(1, statement.ColumnInt(0));
464
465 sql::Statement statement1(db.GetUniqueStatement(
466 "Select Count(*) from downloads_url_chains"));
467 EXPECT_TRUE(statement1.Step());
468 EXPECT_EQ(1, statement1.ColumnInt(0));
469 }
470 }
471
472 struct InterruptReasonAssociation {
473 std::string name;
474 int value;
475 };
476
477 // Test is dependent on interrupt reasons being listed in header file
478 // in order.
479 const InterruptReasonAssociation current_reasons[] = {
480 #define INTERRUPT_REASON(a, b) { #a, b },
481 #include "content/public/browser/download_interrupt_reason_values.h"
482 #undef INTERRUPT_REASON
483 };
484
485 // This represents a list of all reasons we've previously used;
486 // Do Not Remove Any Entries From This List.
487 const InterruptReasonAssociation historical_reasons[] = {
488 { "FILE_FAILED", 1 },
benjhayden 2012/12/10 16:38:42 I thought that spaces inside braces was unstylish.
Randy Smith (Not in Mondays) 2012/12/11 18:17:30 Switched to the style I see in history_query_unitt
489 { "FILE_ACCESS_DENIED", 2 },
490 { "FILE_NO_SPACE", 3 },
491 { "FILE_NAME_TOO_LONG", 5 },
492 { "FILE_TOO_LARGE", 6 },
493 { "FILE_VIRUS_INFECTED", 7 },
494 { "FILE_TRANSIENT_ERROR", 10 },
495 { "FILE_BLOCKED", 11 },
496 { "FILE_SECURITY_CHECK_FAILED", 12 },
497 { "NETWORK_FAILED", 20 },
498 { "NETWORK_TIMEOUT", 21 },
499 { "NETWORK_DISCONNECTED", 22 },
500 { "NETWORK_SERVER_DOWN", 23 },
501 { "SERVER_FAILED", 30 },
502 { "SERVER_NO_RANGE", 31 },
503 { "SERVER_PRECONDITION", 32 },
504 { "SERVER_BAD_CONTENT", 33 },
505 { "USER_CANCELED", 40 },
506 { "USER_SHUTDOWN", 41 },
507 { "CRASH", 50 },
508 };
509
510 // Make sure no one has changed a DownloadInterruptReason we've previously
511 // persisted.
512 TEST_F(HistoryBackendDBTest,
513 ConfirmDownloadInterruptReasonBackwardsCompatible) {
514 // Are there any cases in which a historical number has been repurposed
515 // for an error other than it's original?
516 for (size_t i = 0; i < arraysize(current_reasons); i++) {
517 const InterruptReasonAssociation& cur_reason(current_reasons[i]);
518 bool found = false;
519
520 for (size_t j = 0; j < arraysize(historical_reasons); ++j) {
521 const InterruptReasonAssociation& hist_reason(historical_reasons[j]);
522
523 if (hist_reason.value == cur_reason.value) {
524 EXPECT_EQ(cur_reason.name, hist_reason.name)
525 << "Same integer value used for old error \""
526 << hist_reason.name
527 << "\" as for new error \""
528 << cur_reason.name
529 << "\"." << std::endl
530 << "**This will cause database conflicts with persisted values**"
531 << std::endl
532 << "Please assign a new, non-conflicting value for the new error.";
533 }
534
535 if (hist_reason.name == cur_reason.name) {
536 EXPECT_EQ(cur_reason.value, hist_reason.value)
537 << "Same name (\"" << hist_reason.name
538 << "\") maps to a different value historically ("
539 << hist_reason.value << ") and currently ("
540 << cur_reason.value << ")" << std::endl
541 << "This may cause database conflicts with persisted values"
542 << std::endl
543 << "If this error is the same as the old one, you should"
544 << std::endl
545 << "use the old value, and if it is different, you should"
546 << std::endl
547 << "use a new name.";
548
549 found = true;
550 }
551 }
552
553 EXPECT_TRUE(found)
554 << "Error \"" << cur_reason.name << "\" not found in historical list."
555 << std::endl
556 << "Please add it.";
557 }
558 }
559
278 // The tracker uses RenderProcessHost pointers for scoping but never 560 // The tracker uses RenderProcessHost pointers for scoping but never
279 // dereferences them. We use ints because it's easier. This function converts 561 // dereferences them. We use ints because it's easier. This function converts
280 // between the two. 562 // between the two.
281 static void* MakeFakeHost(int id) { 563 static void* MakeFakeHost(int id) {
282 void* host = 0; 564 void* host = 0;
283 memcpy(&host, &id, sizeof(id)); 565 memcpy(&host, &id, sizeof(id));
284 return host; 566 return host;
285 } 567 }
286 568
287 class HistoryTest : public testing::Test { 569 class HistoryTest : public testing::Test {
(...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after
1033 1315
1034 history_service_->ProcessDeleteDirectiveForTest(delete_directive); 1316 history_service_->ProcessDeleteDirectiveForTest(delete_directive);
1035 1317
1036 EXPECT_TRUE(QueryURL(history_service_.get(), test_url)); 1318 EXPECT_TRUE(QueryURL(history_service_.get(), test_url));
1037 EXPECT_EQ(2, query_url_row_.visit_count()); 1319 EXPECT_EQ(2, query_url_row_.visit_count());
1038 } 1320 }
1039 1321
1040 } // namespace 1322 } // namespace
1041 1323
1042 } // namespace history 1324 } // namespace history
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698