diff options
author | ahendrickson@chromium.org <ahendrickson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-14 21:14:28 +0000 |
---|---|---|
committer | ahendrickson@chromium.org <ahendrickson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-14 21:14:28 +0000 |
commit | 1138ff02f706d8c777d7e503534871d85a921ece (patch) | |
tree | 8cc7662d900fb81c3915fe6e7cc7c128760e5b2e /chrome/browser/download | |
parent | 688303b4a7593cfc23afd1b599d0d0e3165ec51b (diff) | |
download | chromium_src-1138ff02f706d8c777d7e503534871d85a921ece.zip chromium_src-1138ff02f706d8c777d7e503534871d85a921ece.tar.gz chromium_src-1138ff02f706d8c777d7e503534871d85a921ece.tar.bz2 |
Test file errors in downloads.
Uses an error injection technique to simulate hard-to-reproduce file system errors.
BUG=None
TEST=None
Review URL: http://codereview.chromium.org/9426029
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@126732 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/download')
-rw-r--r-- | chrome/browser/download/download_browsertest.cc | 462 |
1 files changed, 353 insertions, 109 deletions
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc index 6c8f014..6c8d0ee 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> + #include "base/bind.h" #include "base/bind_helpers.h" #include "base/file_path.h" @@ -54,6 +56,7 @@ #include "content/public/common/page_transition_types.h" #include "content/test/net/url_request_mock_http_job.h" #include "content/test/net/url_request_slow_download_job.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" @@ -253,6 +256,11 @@ class DownloadTest : public InProcessBrowserTest { bool should_redirect_to_documents; // True if we save it in "My Documents". }; + struct FileErrorInjectInfo { + DownloadInfo download_info; + content::TestFileErrorInjector::FileErrorInfo error_info; + }; + DownloadTest() { EnableDOMAutomation(); } @@ -643,22 +651,41 @@ class DownloadTest : public InProcessBrowserTest { // Attempts to download a file, based on information in |download_info|. // If a Select File dialog opens, will automatically choose the default. - 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 DownloadFilesCheckErrorsLoopBody(const DownloadInfo& download_info, + size_t i) { + std::stringstream s; + s << " " << __FUNCTION__ << "()" + << " 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()); - - NullSelectFile(browser()); // Needed for read-only tests. + ASSERT_TRUE(url.is_valid()) << s.str(); DownloadManager* download_manager = DownloadManagerForBrowser(browser()); + WebContents* web_contents = browser()->GetSelectedWebContents(); + ASSERT_TRUE(web_contents) << s.str(); + scoped_ptr<DownloadTestObserver> observer( new DownloadTestObserverTerminal( download_manager, @@ -667,10 +694,9 @@ class DownloadTest : public InProcessBrowserTest { 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 for navigation. content::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( @@ -702,6 +728,7 @@ class DownloadTest : public InProcessBrowserTest { } if (download_info.show_download_item) { + downloads_expected++; observer->WaitForFinished(); DownloadItem::DownloadState final_state = (download_info.reason == content::DOWNLOAD_INTERRUPT_REASON_NONE) ? @@ -710,17 +737,26 @@ class DownloadTest : public InProcessBrowserTest { EXPECT_EQ(1u, observer->NumDownloadsSeenInState(final_state)); } - // Validate that the correct file was downloaded. + // Wait till the |DownloadFile|s 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()); + ASSERT_EQ(download_info.reason, item->GetLastReason()) << s.str(); if (item->GetState() == content::DownloadItem::COMPLETE) { // Clean up the file, in case it ended up in the My Documents folder. @@ -746,11 +782,75 @@ class DownloadTest : public InProcessBrowserTest { } } + // 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) { + DownloadFilesCheckErrorsLoopBody(download_info[i], i); + } + } + + void DownloadInsertFilesErrorCheckErrorsLoopBody( + 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(); + + DownloadFilesCheckErrorsLoopBody(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(); + + // Set up file failures. + scoped_refptr<content::TestFileErrorInjector> injector( + content::TestFileErrorInjector::Create()); + + 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(); + + DownloadInsertFilesErrorCheckErrorsLoopBody(injector, info[i], i); + } + } + // Attempts to download a file to a read-only folder, based on information // in |download_info|. - void DownloadFileToReadonlyFolder(const DownloadInfo& download_info) { + void DownloadFilesToReadonlyFolder(size_t count, + DownloadInfo* download_info) { ASSERT_TRUE(InitialSetup(false)); // Creates temporary download folder. + DownloadFilesCheckErrorsSetup(); + // Make the test folder unwritable. FilePath destination_folder = GetDownloadDirectory(browser()); DVLOG(1) << " " << __FUNCTION__ << "()" @@ -758,7 +858,9 @@ class DownloadTest : public InProcessBrowserTest { file_util::PermissionRestorer permission_restorer(destination_folder); EXPECT_TRUE(file_util::MakeFileUnwritable(destination_folder)); - DownloadFileCheckErrors(download_info); + for (size_t i = 0; i < count; ++i) { + DownloadFilesCheckErrorsLoopBody(download_info[i], i); + } } bool EnsureNoPendingDownloads() { @@ -2071,112 +2173,254 @@ 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, - content::DOWNLOAD_INTERRUPT_REASON_NONE, - true, - false - }; - - // 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, - content::DOWNLOAD_INTERRUPT_REASON_NONE, - true, - false - }; - - // 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, - content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT, - true, - false - }; - - // 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, - content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT, - false, - 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, - content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, - true, - false +IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadErrorsServer) { + DownloadInfo download_info[] = { + { // Normal navigated download. + "a_zip_file.zip", + DOWNLOAD_NAVIGATE, + content::DOWNLOAD_INTERRUPT_REASON_NONE, + true, + false + }, + { // Normal direct download. + "a_zip_file.zip", + DOWNLOAD_DIRECT, + content::DOWNLOAD_INTERRUPT_REASON_NONE, + true, + false + }, + { // Direct download with 404 error. + "there_IS_no_spoon.zip", + DOWNLOAD_DIRECT, + content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT, + true, + false + }, + { // Navigated download with 404 error. + "there_IS_no_spoon.zip", + DOWNLOAD_NAVIGATE, + content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT, + false, + false + }, + { // Direct download with 400 error. + "zip_file_not_found.zip", + DOWNLOAD_DIRECT, + content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, + true, + false + }, + { // Navigated download with 400 error. + "zip_file_not_found.zip", + DOWNLOAD_NAVIGATE, + content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, + false, + false + } }; // Do initial setup. ASSERT_TRUE(InitialSetup(false)); - DownloadFileCheckErrors(download_info); -} - -IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadError400Navigate) { - DownloadInfo download_info = { - "zip_file_not_found.zip", - DOWNLOAD_NAVIGATE, - content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, - false, - false - }; - // Do initial setup. - ASSERT_TRUE(InitialSetup(false)); - DownloadFileCheckErrors(download_info); + DownloadFilesCheckErrors(ARRAYSIZE_UNSAFE(download_info), download_info); } -IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadErrorReadonlyFolderDirect) { - DownloadInfo download_info = { - "a_zip_file.zip", - DOWNLOAD_DIRECT, - // This passes because we switch to the My Documents folder. - content::DOWNLOAD_INTERRUPT_REASON_NONE, - true, - true +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, + content::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, + content::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, + content::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, + content::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, + content::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, + content::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, + content::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, + content::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, + content::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, + content::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, + content::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, + content::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, + content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, + 1 + }, + { + "", + content::TestFileErrorInjector::FILE_OPERATION_WRITE, + 1, + net::ERR_FILE_NO_SPACE + } + } }; - DownloadFileToReadonlyFolder(download_info); + DownloadInsertFilesErrorCheckErrors(ARRAYSIZE_UNSAFE(error_info), error_info); } -IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadErrorReadonlyFolderNavigate) { - DownloadInfo download_info = { - "a_zip_file.zip", - DOWNLOAD_NAVIGATE, - // This passes because we switch to the My Documents folder. - content::DOWNLOAD_INTERRUPT_REASON_NONE, - true, - true +IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadErrorReadonlyFolder) { + DownloadInfo download_info[] = { + { + "a_zip_file.zip", + DOWNLOAD_DIRECT, + // This passes because we switch to the My Documents folder. + content::DOWNLOAD_INTERRUPT_REASON_NONE, + true, + true + }, + { + "a_zip_file.zip", + DOWNLOAD_NAVIGATE, + // This passes because we switch to the My Documents folder. + content::DOWNLOAD_INTERRUPT_REASON_NONE, + true, + true + } }; - DownloadFileToReadonlyFolder(download_info); + DownloadFilesToReadonlyFolder(ARRAYSIZE_UNSAFE(download_info), download_info); } |