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 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |