Chromium Code Reviews| Index: chrome/browser/download/download_browsertest.cc |
| diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc |
| index 0ff4be8172626b303cdd8209ebcd4e6bd4da73d1..6c628f785e6a15e214e552aaf531e2e63f41263a 100644 |
| --- a/chrome/browser/download/download_browsertest.cc |
| +++ b/chrome/browser/download/download_browsertest.cc |
| @@ -2,6 +2,8 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| +#include <sstream> |
|
cbentzel
2012/03/02 20:07:57
Why not just use stringprintf to create this?
|
| + |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/file_path.h" |
| @@ -55,6 +57,7 @@ |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/common/context_menu_params.h" |
| #include "content/public/common/page_transition_types.h" |
| +#include "content/test/test_file_error_injector.h" |
| #include "content/test/test_navigation_observer.h" |
| #include "net/base/net_util.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| @@ -306,6 +309,11 @@ class DownloadTest : public InProcessBrowserTest { |
| bool show_download_item; // True if the download item appears on the shelf. |
| }; |
| + struct FileErrorInjectInfo { |
| + DownloadInfo download_info; |
| + content::TestFileErrorInjector::FileErrorInfo error_info; |
| + }; |
| + |
| DownloadTest() { |
| EnableDOMAutomation(); |
| } |
| @@ -680,36 +688,56 @@ class DownloadTest : public InProcessBrowserTest { |
| return true; |
| } |
| - // Attempts to download a file, based on information in |download_info|. |
| - void DownloadFileCheckErrors(const DownloadInfo& download_info) { |
| + void DownloadFilesCheckErrorsSetup() { |
| ASSERT_TRUE(test_server()->Start()); |
| std::vector<DownloadItem*> download_items; |
| GetDownloads(browser(), &download_items); |
| ASSERT_TRUE(download_items.empty()); |
| NullSelectFile(browser()); |
| + } |
| + |
| + void DownloadFilesCheckErrorsLoop(const DownloadInfo& download_info, |
| + size_t i) { |
| + std::stringstream s; |
| + s << " " << __FUNCTION__ << "()" |
|
cbentzel
2012/03/02 20:45:19
I guess stringstream makes sense here.
|
| + << " index = " << i |
| + << " url = '" << download_info.url_name << "'" |
| + << " method = " |
| + << ((download_info.download_method == DOWNLOAD_DIRECT) ? |
| + "DOWNLOAD_DIRECT" : "DOWNLOAD_NAVIGATE") |
| + << " show_item = " << download_info.show_download_item |
| + << " reason = " |
| + << InterruptReasonDebugString(download_info.reason); |
| + |
| + std::vector<DownloadItem*> download_items; |
| + GetDownloads(browser(), &download_items); |
| + size_t downloads_expected = download_items.size(); |
| std::string server_path = "files/downloads/"; |
| server_path += download_info.url_name; |
| GURL url = test_server()->GetURL(server_path); |
| - ASSERT_TRUE(url.is_valid()); |
| + ASSERT_TRUE(url.is_valid()) << s.str(); |
| DownloadManager* download_manager = DownloadManagerForBrowser(browser()); |
| + WebContents* web_contents = browser()->GetSelectedWebContents(); |
| + ASSERT_TRUE(web_contents) << s.str(); |
| + |
| + size_t direct_downloads_expected = 0; |
| scoped_ptr<DownloadTestObserver> observer( |
| new DownloadTestObserver( |
| download_manager, |
| 1, |
| download_info.reason == DOWNLOAD_INTERRUPT_REASON_NONE ? |
| - DownloadItem::COMPLETE : // Really done |
| - DownloadItem::INTERRUPTED, |
| + DownloadItem::COMPLETE : // Really done. |
| + DownloadItem::INTERRUPTED, // Error detected. |
| false, // Don't bail on select file. |
| DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL)); |
| if (download_info.download_method == DOWNLOAD_DIRECT) { |
| - // Go directly to download. |
| - WebContents* web_contents = browser()->GetSelectedWebContents(); |
| - ASSERT_TRUE(web_contents); |
| + // Go directly to download. Don't wait until it's done. |
| DownloadSaveInfo save_info; |
| + // NOTE: |prompt_for_save_location| may change during the download. |
| save_info.prompt_for_save_location = false; |
| scoped_refptr<DownloadTestItemCreationObserver> creation_observer( |
| @@ -732,21 +760,92 @@ class DownloadTest : public InProcessBrowserTest { |
| } |
| if (download_info.show_download_item) { |
| + downloads_expected++; |
| observer->WaitForFinished(); |
| DCHECK_EQ(0u, observer->NumOtherDownloadsSeen()); |
| } |
| - // Validate that the correct file was downloaded. |
| + // Wait till the download files are destroyed. |
| + ui_test_utils::RunAllPendingInMessageLoop(content::BrowserThread::FILE); |
| + ui_test_utils::RunAllPendingInMessageLoop(content::BrowserThread::UI); |
| + |
| + // Validate that the correct files were downloaded. |
| download_items.clear(); |
| GetDownloads(browser(), &download_items); |
| - size_t item_count = download_info.show_download_item ? 1 : 0; |
| - ASSERT_EQ(item_count, download_items.size()); |
| + ASSERT_EQ(downloads_expected, download_items.size()) << s.str(); |
| if (download_info.show_download_item) { |
| + // Find the last download item. |
| DownloadItem* item = download_items[0]; |
| - ASSERT_EQ(url, item->GetOriginalUrl()); |
| + for (size_t d = 1; d < downloads_expected; ++d) { |
| + if (download_items[d]->GetStartTime() > item->GetStartTime()) |
| + item = download_items[d]; |
| + } |
| + |
| + ASSERT_EQ(url, item->GetOriginalUrl()) << s.str(); |
| + |
| + ASSERT_EQ(download_info.reason, item->GetLastReason()) << s.str(); |
| + } |
| + } |
| + |
| + // Attempts to download a set of files, based on information in the |
| + // |download_info| array. |count| is the number of files. |
| + // If a Select File dialog appears, it will choose the default and return |
| + // immediately. |
| + void DownloadFilesCheckErrors(size_t count, DownloadInfo* download_info) { |
| + DownloadFilesCheckErrorsSetup(); |
| + |
| + for (size_t i = 0; i < count; ++i) { |
| + DownloadFilesCheckErrorsLoop(download_info[i], i); |
| + } |
| + } |
| + |
| + void DownloadInsertFilesErrorCheckErrorsLoop( |
| + scoped_refptr<content::TestFileErrorInjector> injector, |
| + const FileErrorInjectInfo& info, |
| + size_t i) { |
| + std::stringstream s; |
| + s << " " << __FUNCTION__ << "()" |
| + << " index = " << i |
| + << " url = " << info.error_info.url |
| + << " operation code = " << |
| + content::TestFileErrorInjector::DebugString( |
| + info.error_info.code) |
| + << " instance = " << info.error_info.operation_instance |
| + << " error = " << net::ErrorToString( |
| + info.error_info.net_error); |
| + |
| + injector->ClearErrors(); |
| + injector->AddError(info.error_info); |
| + |
| + injector->InjectErrors(); |
| + |
| + DownloadFilesCheckErrorsLoop(info.download_info, i); |
| + |
| + size_t expected_successes = info.download_info.show_download_item ? 1u : 0u; |
| + EXPECT_EQ(expected_successes, injector->TotalFileCount()) << s.str(); |
| + EXPECT_EQ(0u, injector->CurrentFileCount()) << s.str(); |
| + |
| + if (info.download_info.show_download_item) |
| + EXPECT_TRUE(injector->HadFile(GURL(info.error_info.url))) << s.str(); |
| + } |
| + |
| + void DownloadInsertFilesErrorCheckErrors(size_t count, |
| + FileErrorInjectInfo* info) { |
| + DownloadFilesCheckErrorsSetup(); |
| - ASSERT_EQ(download_info.reason, item->GetLastReason()); |
| + // Set up file failures. |
| + scoped_refptr<content::TestFileErrorInjector> injector( |
| + content::TestFileErrorInjector::Get()); |
| + |
| + for (size_t i = 0; i < count; ++i) { |
| + // Set up the full URL, for download file tracking. |
| + std::string server_path = "files/downloads/"; |
| + server_path += info[i].download_info.url_name; |
| + GURL url = test_server()->GetURL(server_path); |
| + info[i].error_info.url = url.spec(); |
| + |
| + DownloadInsertFilesErrorCheckErrorsLoop(injector, info[i], i); |
| } |
| } |
| @@ -2020,80 +2119,225 @@ IN_PROC_BROWSER_TEST_F(DownloadTest, SavePageNonHTMLViaPost) { |
| ASSERT_EQ(jpeg_url, download_items[1]->GetOriginalUrl()); |
| } |
| -IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadNavigate) { |
| - DownloadInfo download_info = { |
| - "a_zip_file.zip", |
| - DOWNLOAD_NAVIGATE, |
| - DOWNLOAD_INTERRUPT_REASON_NONE, |
| - true |
| - }; |
| - |
| - // Do initial setup. |
| - ASSERT_TRUE(InitialSetup(false)); |
| - DownloadFileCheckErrors(download_info); |
| -} |
| - |
| -IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadDirect) { |
| - DownloadInfo download_info = { |
| - "a_zip_file.zip", |
| - DOWNLOAD_DIRECT, |
| - DOWNLOAD_INTERRUPT_REASON_NONE, |
| - true |
| - }; |
| - |
| - // Do initial setup. |
| - ASSERT_TRUE(InitialSetup(false)); |
| - DownloadFileCheckErrors(download_info); |
| -} |
| - |
| -IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadError404Direct) { |
| - DownloadInfo download_info = { |
| - "there_IS_no_spoon.zip", |
| - DOWNLOAD_DIRECT, |
| - DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT, |
| - true |
| - }; |
| - |
| - // Do initial setup. |
| - ASSERT_TRUE(InitialSetup(false)); |
| - DownloadFileCheckErrors(download_info); |
| -} |
| - |
| -IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadError404Navigate) { |
| - DownloadInfo download_info = { |
| - "there_IS_no_spoon.zip", |
| - DOWNLOAD_NAVIGATE, |
| - DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT, |
| - false |
| +IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadErrorsServer) { |
| + DownloadInfo download_info[] = { |
| + { // Normal navigated download. |
| + "a_zip_file.zip", |
| + DOWNLOAD_NAVIGATE, |
| + DOWNLOAD_INTERRUPT_REASON_NONE, |
| + true |
| + }, |
| + { // Normal direct download. |
| + "a_zip_file.zip", |
| + DOWNLOAD_DIRECT, |
| + DOWNLOAD_INTERRUPT_REASON_NONE, |
| + true |
| + }, |
| + { // Direct download with 404 error. |
| + "there_IS_no_spoon.zip", |
| + DOWNLOAD_DIRECT, |
| + DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT, |
| + true |
| + }, |
| + { // Navigated download with 404 error. |
| + "there_IS_no_spoon.zip", |
| + DOWNLOAD_NAVIGATE, |
| + DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT, |
| + false |
| + }, |
| + { // Direct download with 400 error. |
| + "zip_file_not_found.zip", |
| + DOWNLOAD_DIRECT, |
| + DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, |
| + true |
| + }, |
| + { // Navigated download with 400 error. |
| + "zip_file_not_found.zip", |
| + DOWNLOAD_NAVIGATE, |
| + DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, |
| + false |
| + } |
| }; |
| // Do initial setup. |
| ASSERT_TRUE(InitialSetup(false)); |
| - DownloadFileCheckErrors(download_info); |
| -} |
| - |
| -IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadError400Direct) { |
| - DownloadInfo download_info = { |
| - "zip_file_not_found.zip", |
| - DOWNLOAD_DIRECT, |
| - DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, |
| - true |
| - }; |
| - // Do initial setup. |
| - ASSERT_TRUE(InitialSetup(false)); |
| - DownloadFileCheckErrors(download_info); |
| + DownloadFilesCheckErrors(ARRAYSIZE_UNSAFE(download_info), download_info); |
| } |
| -IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadError400Navigate) { |
| - DownloadInfo download_info = { |
| - "zip_file_not_found.zip", |
| - DOWNLOAD_NAVIGATE, |
| - DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, |
| - false |
| +IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadErrorsFile) { |
| + FileErrorInjectInfo error_info[] = { |
| + { // Navigated download with injected "Disk full" error in Initialize(). |
| + { "a_zip_file.zip", |
| + DOWNLOAD_NAVIGATE, |
| + DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, |
| + 1 |
| + }, |
| + { |
| + "", |
| + content::TestFileErrorInjector::FILE_OPERATION_INITIALIZE, |
| + 0, |
| + net::ERR_FILE_NO_SPACE |
| + } |
| + }, |
| + { // Direct download with injected "Disk full" error in Initialize(). |
| + { "a_zip_file.zip", |
| + DOWNLOAD_DIRECT, |
| + DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, |
| + 1 |
| + }, |
| + { |
| + "", |
| + content::TestFileErrorInjector::FILE_OPERATION_INITIALIZE, |
| + 0, |
| + net::ERR_FILE_NO_SPACE |
| + } |
| + }, |
| + { // Navigated download with injected "Disk full" error in Write(). |
| + { "a_zip_file.zip", |
| + DOWNLOAD_NAVIGATE, |
| + DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, |
| + 1 |
| + }, |
| + { |
| + "", |
| + content::TestFileErrorInjector::FILE_OPERATION_WRITE, |
| + 0, |
| + net::ERR_FILE_NO_SPACE |
| + } |
| + }, |
| + { // Direct download with injected "Disk full" error in Write(). |
| + { "a_zip_file.zip", |
| + DOWNLOAD_DIRECT, |
| + DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, |
| + 1 |
| + }, |
| + { |
| + "", |
| + content::TestFileErrorInjector::FILE_OPERATION_WRITE, |
| + 0, |
| + net::ERR_FILE_NO_SPACE |
| + } |
| + }, |
| + { // Navigated download with injected "Failed" error in Initialize(). |
| + { "a_zip_file.zip", |
| + DOWNLOAD_NAVIGATE, |
| + DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, |
| + 1 |
| + }, |
| + { |
| + "", |
| + content::TestFileErrorInjector::FILE_OPERATION_INITIALIZE, |
| + 0, |
| + net::ERR_FAILED |
| + } |
| + }, |
| + { // Direct download with injected "Failed" error in Initialize(). |
| + { "a_zip_file.zip", |
| + DOWNLOAD_DIRECT, |
| + DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, |
| + 1 |
| + }, |
| + { |
| + "", |
| + content::TestFileErrorInjector::FILE_OPERATION_INITIALIZE, |
| + 0, |
| + net::ERR_FAILED |
| + } |
| + }, |
| + { // Navigated download with injected "Failed" error in Write(). |
| + { "a_zip_file.zip", |
| + DOWNLOAD_NAVIGATE, |
| + DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, |
| + 1 |
| + }, |
| + { |
| + "", |
| + content::TestFileErrorInjector::FILE_OPERATION_WRITE, |
| + 0, |
| + net::ERR_FAILED |
| + } |
| + }, |
| + { // Direct download with injected "Failed" error in Write(). |
| + { "a_zip_file.zip", |
| + DOWNLOAD_DIRECT, |
| + DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, |
| + 1 |
| + }, |
| + { |
| + "", |
| + content::TestFileErrorInjector::FILE_OPERATION_WRITE, |
| + 0, |
| + net::ERR_FAILED |
| + } |
| + }, |
| + { // Navigated download with injected "Name too long" error in |
| + // Initialize(). |
| + { "a_zip_file.zip", |
| + DOWNLOAD_NAVIGATE, |
| + DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG, |
| + 1 |
| + }, |
| + { |
| + "", |
| + content::TestFileErrorInjector::FILE_OPERATION_INITIALIZE, |
| + 0, |
| + net::ERR_FILE_PATH_TOO_LONG |
| + } |
| + }, |
| + { // Direct download with injected "Name too long" error in Initialize(). |
| + { "a_zip_file.zip", |
| + DOWNLOAD_DIRECT, |
| + DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG, |
| + 1 |
| + }, |
| + { |
| + "", |
| + content::TestFileErrorInjector::FILE_OPERATION_INITIALIZE, |
| + 0, |
| + net::ERR_FILE_PATH_TOO_LONG |
| + } |
| + }, |
| + { // Navigated download with injected "Name too long" error in Write(). |
| + { "a_zip_file.zip", |
| + DOWNLOAD_NAVIGATE, |
| + DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, |
| + 1 |
| + }, |
| + { |
| + "", |
| + content::TestFileErrorInjector::FILE_OPERATION_WRITE, |
| + 0, |
| + net::ERR_INVALID_HANDLE |
| + } |
| + }, |
| + { // Direct download with injected "Name too long" error in Write(). |
| + { "a_zip_file.zip", |
| + DOWNLOAD_DIRECT, |
| + DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, |
| + 1 |
| + }, |
| + { |
| + "", |
| + content::TestFileErrorInjector::FILE_OPERATION_WRITE, |
| + 0, |
| + net::ERR_INVALID_HANDLE |
| + } |
| + }, |
| + { // Direct download with injected "Disk full" error in 2nd Write(). |
| + { "06bESSE21Evolution.ppt", |
| + DOWNLOAD_DIRECT, |
| + DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, |
| + 1 |
| + }, |
| + { |
| + "", |
| + content::TestFileErrorInjector::FILE_OPERATION_WRITE, |
| + 1, |
| + net::ERR_FILE_NO_SPACE |
| + } |
| + } |
| }; |
| - // Do initial setup. |
| - ASSERT_TRUE(InitialSetup(false)); |
| - DownloadFileCheckErrors(download_info); |
| + DownloadInsertFilesErrorCheckErrors(ARRAYSIZE_UNSAFE(error_info), error_info); |
| } |