| Index: content/browser/download/download_browsertest.cc
|
| diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
|
| index 006b64025c24e1338203b60d5dc2d4da1bbe944c..3ad6b7a0a2abd6fc92b5c666d95a94f6ce28f76a 100644
|
| --- a/content/browser/download/download_browsertest.cc
|
| +++ b/content/browser/download/download_browsertest.cc
|
| @@ -5,6 +5,7 @@
|
| // This file contains download browser tests that are known to be runnable
|
| // in a pure content context. Over time tests should be migrated here.
|
|
|
| +#include "base/command_line.h"
|
| #include "base/file_path.h"
|
| #include "base/file_util.h"
|
| #include "base/files/scoped_temp_dir.h"
|
| @@ -14,6 +15,7 @@
|
| #include "content/browser/download/download_manager_impl.h"
|
| #include "content/browser/power_save_blocker.h"
|
| #include "content/browser/web_contents/web_contents_impl.h"
|
| +#include "content/public/common/content_switches.h"
|
| #include "content/public/test/download_test_observer.h"
|
| #include "content/public/test/test_utils.h"
|
| #include "content/shell/shell.h"
|
| @@ -24,6 +26,7 @@
|
| #include "content/test/net/url_request_mock_http_job.h"
|
| #include "content/test/net/url_request_slow_download_job.h"
|
| #include "googleurl/src/gurl.h"
|
| +#include "net/test/test_server.h"
|
| #include "testing/gmock/include/gmock/gmock.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| @@ -343,6 +346,29 @@ class TestShellDownloadManagerDelegate : public ShellDownloadManagerDelegate {
|
| std::vector<DownloadOpenDelayedCallback> delayed_callbacks_;
|
| };
|
|
|
| +// Filter for handling resumption; don't return true until
|
| +// we see first a transition to IN_PROGRESS then a transition to
|
| +// some final state. Since this is a stateful filter, we
|
| +// must provide a flag in which to store the state; that flag
|
| +// must be false on initialization. The flag must be the first argument
|
| +// so that Bind() can be used to produce the callback expected by
|
| +// DownloadUpdatedObserver.
|
| +bool DownloadResumptionFilter(bool* state_flag, DownloadItem* download) {
|
| + if (*state_flag && DownloadItem::IN_PROGRESS != download->GetState()) {
|
| + return true;
|
| + }
|
| +
|
| + if (DownloadItem::IN_PROGRESS == download->GetState())
|
| + *state_flag = true;
|
| +
|
| + return false;
|
| +}
|
| +
|
| +// Filter for waiting for intermediate file rename.
|
| +bool IntermediateFileRenameFilter(DownloadItem* download) {
|
| + return !download->GetFullPath().empty();
|
| +}
|
| +
|
| } // namespace
|
|
|
| class DownloadContentTest : public ContentBrowserTest {
|
| @@ -406,11 +432,12 @@ class DownloadContentTest : public ContentBrowserTest {
|
| (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
|
| }
|
|
|
| - void DownloadAndWait(Shell* shell, const GURL& url) {
|
| + void DownloadAndWait(Shell* shell, const GURL& url,
|
| + DownloadItem::DownloadState expected_terminal_state) {
|
| scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell, 1));
|
| NavigateToURL(shell, url);
|
| observer->WaitForFinished();
|
| - EXPECT_EQ(1u, observer->NumDownloadsSeenInState(DownloadItem::COMPLETE));
|
| + EXPECT_EQ(1u, observer->NumDownloadsSeenInState(expected_terminal_state));
|
| }
|
|
|
| // Checks that |path| is has |file_size| bytes, and matches the |value|
|
| @@ -500,7 +527,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, MultiDownload) {
|
| FilePath file(FILE_PATH_LITERAL("download-test.lib"));
|
| GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
|
| // Download the file and wait.
|
| - DownloadAndWait(shell(), url);
|
| + DownloadAndWait(shell(), url, DownloadItem::COMPLETE);
|
|
|
| // Should now have 2 items on the manager.
|
| downloads.clear();
|
| @@ -733,4 +760,79 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownAtRelease) {
|
| DownloadManagerForShell(shell())->Shutdown();
|
| }
|
|
|
| +IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownload) {
|
| + CommandLine::ForCurrentProcess()->AppendSwitch(
|
| + switches::kEnableDownloadResumption);
|
| + ASSERT_TRUE(test_server()->Start());
|
| + // Default behavior is a 15K file with a RST at 10K. We request
|
| + // a hold on the response so that we can get the target name determined
|
| + // before handling the RST.
|
| + // TODO(rdsmith): Figure out how to handle the races needed
|
| + // so that we don't have to wait for the target name determination.
|
| + GURL url = test_server()->GetURL("rangereset?hold");
|
| +
|
| + // Download and wait for file determination.
|
| + scoped_ptr<DownloadTestObserver> observer(CreateInProgressWaiter(shell(), 1));
|
| + NavigateToURL(shell(), url);
|
| + observer->WaitForFinished();
|
| +
|
| + std::vector<DownloadItem*> downloads;
|
| + DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
|
| + ASSERT_EQ(1u, downloads.size());
|
| + DownloadItem* download(downloads[0]);
|
| + if (download->GetFullPath().empty()) {
|
| + DownloadUpdatedObserver intermediate_observer(
|
| + download, base::Bind(&IntermediateFileRenameFilter));
|
| + intermediate_observer.WaitForEvent();
|
| + }
|
| +
|
| + // Unleash the RST!
|
| + scoped_ptr<DownloadTestObserver> rst_observer(CreateWaiter(shell(), 1));
|
| + GURL release_url = test_server()->GetURL("download-finish");
|
| + NavigateToURL(shell(), release_url);
|
| + rst_observer->WaitForFinished();
|
| + EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState());
|
| + EXPECT_EQ(10000u, download->GetReceivedBytes());
|
| + EXPECT_EQ(15000u, download->GetTotalBytes());
|
| + EXPECT_EQ(FILE_PATH_LITERAL("rangereset.crdownload"),
|
| + download->GetFullPath().BaseName().value());
|
| +
|
| + {
|
| + std::string file_contents;
|
| + std::string expected_contents(10000, 'X');
|
| + ASSERT_TRUE(file_util::ReadFileToString(
|
| + download->GetFullPath(), &file_contents));
|
| + EXPECT_EQ(10000u, file_contents.size());
|
| + // In conditional to avoid spamming the console with two 15000 char strings.
|
| + if (expected_contents != file_contents)
|
| + EXPECT_TRUE(false) << "File contents do not have expected value.";
|
| + }
|
| +
|
| + // Resume; should get entire file (note that a restart will fail
|
| + // here because it'll produce another RST).
|
| + bool flag(false);
|
| + DownloadUpdatedObserver complete_observer(
|
| + download, base::Bind(&DownloadResumptionFilter, &flag));
|
| + download->ResumeInterruptedDownload();
|
| + NavigateToURL(shell(), release_url); // Needed to get past hold.
|
| + complete_observer.WaitForEvent();
|
| + EXPECT_EQ(DownloadItem::COMPLETE, download->GetState());
|
| + EXPECT_EQ(15000u, download->GetReceivedBytes());
|
| + EXPECT_EQ(15000u, download->GetTotalBytes());
|
| + EXPECT_EQ(FILE_PATH_LITERAL("rangereset"),
|
| + download->GetFullPath().BaseName().value())
|
| + << "Target path name: " << download->GetTargetFilePath().value();
|
| +
|
| + {
|
| + std::string file_contents;
|
| + std::string expected_contents(15000, 'X');
|
| + ASSERT_TRUE(file_util::ReadFileToString(
|
| + download->GetFullPath(), &file_contents));
|
| + EXPECT_EQ(15000u, file_contents.size());
|
| + // In conditional to avoid spamming the console with two 15000 char strings.
|
| + if (expected_contents != file_contents)
|
| + EXPECT_TRUE(false) << "File contents do not have expected value.";
|
| + }
|
| +}
|
| +
|
| } // namespace content
|
|
|