blob: 15eab3afcf963f84e82c567ef59d35f65e24ecaa [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/download/download_file_manager.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/scoped_temp_dir.h"
#include "base/string_number_conversions.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/download/download_buffer.h"
#include "content/browser/download/download_create_info.h"
#include "content/browser/download/download_interrupt_reasons_impl.h"
#include "content/browser/download/download_request_handle.h"
#include "content/browser/download/mock_download_file.h"
#include "content/public/browser/download_id.h"
#include "content/test/mock_download_manager.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using content::BrowserThread;
using content::BrowserThreadImpl;
using content::DownloadId;
using content::MockDownloadManager;
using ::testing::_;
using ::testing::AtLeast;
using ::testing::Mock;
using ::testing::Return;
using ::testing::StrEq;
namespace {
class MockDownloadFileFactory :
public DownloadFileManager::DownloadFileFactory {
public:
MockDownloadFileFactory() {}
virtual ~MockDownloadFileFactory() {}
virtual content::DownloadFile* CreateFile(
DownloadCreateInfo* info,
const DownloadRequestHandle& request_handle,
content::DownloadManager* download_manager,
bool calculate_hash,
const net::BoundNetLog& bound_net_log) OVERRIDE;
MockDownloadFile* GetExistingFile(const DownloadId& id);
private:
std::map<DownloadId, MockDownloadFile*> files_;
};
content::DownloadFile* MockDownloadFileFactory::CreateFile(
DownloadCreateInfo* info,
const DownloadRequestHandle& request_handle,
content::DownloadManager* download_manager,
bool calculate_hash,
const net::BoundNetLog& bound_net_log) {
DCHECK(files_.end() == files_.find(info->download_id));
MockDownloadFile* created_file = new MockDownloadFile();
files_[info->download_id] = created_file;
ON_CALL(*created_file, GetDownloadManager())
.WillByDefault(Return(download_manager));
EXPECT_CALL(*created_file, Initialize());
return created_file;
}
MockDownloadFile* MockDownloadFileFactory::GetExistingFile(
const DownloadId& id) {
DCHECK(files_.find(id) != files_.end());
return files_[id];
}
class MockDownloadRequestHandle : public DownloadRequestHandle {
public:
MockDownloadRequestHandle(content::DownloadManager* manager)
: manager_(manager) {}
virtual content::DownloadManager* GetDownloadManager() const OVERRIDE;
private:
content::DownloadManager* manager_;
};
content::DownloadManager* MockDownloadRequestHandle::GetDownloadManager()
const {
return manager_;
}
} // namespace
class DownloadFileManagerTest : public testing::Test {
public:
// State of renamed file. Used with RenameFile().
enum RenameFileState {
IN_PROGRESS,
COMPLETE
};
// Whether to overwrite the target filename in RenameFile().
enum RenameFileOverwrite {
OVERWRITE,
DONT_OVERWRITE
};
static const char* kTestData1;
static const char* kTestData2;
static const char* kTestData3;
static const char* kTestData4;
static const char* kTestData5;
static const char* kTestData6;
static const int32 kDummyDownloadId;
static const int32 kDummyDownloadId2;
static const int kDummyChildId;
static const int kDummyRequestId;
// We need a UI |BrowserThread| in order to destruct |download_manager_|,
// which has trait |BrowserThread::DeleteOnUIThread|. Without this,
// calling Release() on |download_manager_| won't ever result in its
// destructor being called and we get a leak.
DownloadFileManagerTest()
: download_buffer_(new content::DownloadBuffer()),
ui_thread_(BrowserThread::UI, &loop_),
file_thread_(BrowserThread::FILE, &loop_) {
}
~DownloadFileManagerTest() {
}
virtual void SetUp() {
download_manager_ = new MockDownloadManager();
request_handle_.reset(new MockDownloadRequestHandle(download_manager_));
download_file_factory_ = new MockDownloadFileFactory;
download_file_manager_ = new DownloadFileManager(download_file_factory_);
}
virtual void TearDown() {
// When a DownloadManager's reference count drops to 0, it is not
// deleted immediately. Instead, a task is posted to the UI thread's
// message loop to delete it.
// So, drop the reference count to 0 and run the message loop once
// to ensure that all resources are cleaned up before the test exits.
download_manager_ = NULL;
ui_thread_.message_loop()->RunAllPending();
}
void ProcessAllPendingMessages() {
loop_.RunAllPending();
}
// Clears all gmock expectations for the download file |id| and the manager.
void ClearExpectations(DownloadId id) {
MockDownloadFile* file = download_file_factory_->GetExistingFile(id);
Mock::VerifyAndClearExpectations(file);
Mock::VerifyAndClearExpectations(download_manager_);
}
// Start a download.
// |info| is the information needed to create a new download file.
// |id| is the download ID of the new download file.
void StartDownload(DownloadCreateInfo* info, const DownloadId& id) {
// Expected call sequence:
// StartDownload
// DownloadManager::CreateDownloadItem
// DownloadManagerDelegate::GenerateFileHash
// Process one message in the message loop
// CreateDownloadFile
// new MockDownloadFile, add to downloads_[id]
// DownloadRequestHandle::ResumeRequest
// StartUpdateTimer
// DownloadCreateInfo is destroyed
// Process one message in the message loop
// DownloadManager::StartDownload
info->download_id = id;
// Set expectations and return values.
EXPECT_CALL(*download_manager_, CreateDownloadItem(info, _))
.Times(1)
.WillOnce(Return(net::BoundNetLog()));
EXPECT_CALL(*download_manager_, GenerateFileHash())
.Times(AtLeast(1))
.WillRepeatedly(Return(false));
EXPECT_CALL(*download_manager_, StartDownload(id.local()));
download_file_manager_->StartDownload(info, *request_handle_);
ProcessAllPendingMessages();
ClearExpectations(id);
}
// Creates a new |net::IOBuffer| of size |length| with |data|, and attaches
// it to the download buffer.
bool UpdateBuffer(const char* data, size_t length) {
// We are passing ownership of this buffer to the download file manager.
// NOTE: we are padding io_buffer with one extra character so that the
// mock testing framework can treat it as a NULL-delimited string.
net::IOBuffer* io_buffer = new net::IOBuffer(length + 1);
// We need |AddRef()| because we do a |Release()| in |UpdateDownload()|.
io_buffer->AddRef();
memcpy(io_buffer->data(), data, length);
io_buffer->data()[length] = 0;
download_buffer_->AddData(io_buffer, length);
return true;
}
// Updates the download file.
// |id| is the download ID of the download file.
// |data| is the buffer containing the data.
// |length| is the length of the data buffer.
// |error_to_insert| is the error to simulate. For no error, use net::OK.
void UpdateDownload(const DownloadId& id,
const char* data,
size_t length,
net::Error error_to_insert) {
// Expected call sequence:
// Create DownloadBuffer
// UpdateDownload
// GetDownloadFile
// DownloadFile::AppendDataToFile
//
// On error:
// DownloadFile::GetDownloadManager
// DownloadFile::BytesSoFar
// CancelDownload
// Process one message in the message loop
// DownloadManager::OnDownloadInterrupted
EXPECT_TRUE(UpdateBuffer(data, length));
MockDownloadFile* file = download_file_factory_->GetExistingFile(id);
ASSERT_TRUE(file != NULL);
byte_count_[id] += length;
// Make sure our comparison string is NULL-terminated.
char* expected_data = new char[length + 1];
memcpy(expected_data, data, length);
expected_data[length] = 0;
EXPECT_CALL(*file, AppendDataToFile(StrEq(expected_data), length))
.Times(1)
.WillOnce(Return(error_to_insert));
if (error_to_insert != net::OK) {
EXPECT_CALL(*file, GetDownloadManager())
.Times(AtLeast(1));
EXPECT_CALL(*file, BytesSoFar())
.Times(AtLeast(1))
.WillRepeatedly(Return(byte_count_[id]));
EXPECT_CALL(*file, GetHashState())
.Times(AtLeast(1));
EXPECT_CALL(*file, Cancel());
}
download_file_manager_->UpdateDownload(id, download_buffer_.get());
if (error_to_insert != net::OK) {
EXPECT_CALL(*download_manager_,
OnDownloadInterrupted(
id.local(),
byte_count_[id],
"",
content::ConvertNetErrorToInterruptReason(
error_to_insert, content::DOWNLOAD_INTERRUPT_FROM_DISK)));
ProcessAllPendingMessages();
++error_count_[id];
}
ClearExpectations(id);
delete [] expected_data;
}
// Renames the download file.
// |id| is the download ID of the download file.
// |new_path| is the new file path.
// |unique_path| is the actual path that the download file will be
// renamed to. If there is an existing file at
// |new_path| and |replace| is false, then |new_path|
// will be uniquified.
// |rename_error| is the error to inject. For no error, use net::OK.
// |state| whether we are renaming an in-progress download or a
// completed download.
// |should_overwrite| indicates whether to replace or uniquify the file.
void RenameFile(const DownloadId& id,
const FilePath& new_path,
const FilePath& unique_path,
net::Error rename_error,
RenameFileState state,
RenameFileOverwrite should_overwrite) {
// Expected call sequence:
// RenameInProgressDownloadFile/RenameCompletingDownloadFile
// GetDownloadFile
// DownloadFile::Rename
//
// On Error:
// CancelDownloadOnRename
// GetDownloadFile
// DownloadFile::GetDownloadManager
// No Manager:
// DownloadFile::CancelDownloadRequest/return
// Has Manager:
// DownloadFile::BytesSoFar
// Process one message in the message loop
// DownloadManager::OnDownloadInterrupted
//
// On Success, if final rename:
// Process one message in the message loop
// DownloadManager::OnDownloadRenamedToFinalName
MockDownloadFile* file = download_file_factory_->GetExistingFile(id);
ASSERT_TRUE(file != NULL);
if (state == COMPLETE || rename_error != net::OK) {
EXPECT_CALL(*file, GetDownloadManager())
.Times(AtLeast(1));
}
EXPECT_CALL(*file, Rename(unique_path))
.Times(1)
.WillOnce(Return(rename_error));
if (rename_error != net::OK) {
EXPECT_CALL(*file, BytesSoFar())
.Times(AtLeast(1))
.WillRepeatedly(Return(byte_count_[id]));
EXPECT_CALL(*file, GetHashState())
.Times(AtLeast(1));
}
if (state == IN_PROGRESS) {
download_file_manager_->RenameInProgressDownloadFile(id, new_path);
} else { // state == COMPLETE
download_file_manager_->RenameCompletingDownloadFile(
id, new_path, (should_overwrite == OVERWRITE));
}
if (rename_error != net::OK) {
EXPECT_CALL(*download_manager_,
OnDownloadInterrupted(
id.local(),
byte_count_[id],
"",
content::ConvertNetErrorToInterruptReason(
rename_error,
content::DOWNLOAD_INTERRUPT_FROM_DISK)));
ProcessAllPendingMessages();
++error_count_[id];
} else if (state == COMPLETE) {
EXPECT_CALL(*download_manager_, OnDownloadRenamedToFinalName(
id.local(), unique_path, _));
ProcessAllPendingMessages();
}
}
// Finish the download operation.
// |id| is the download ID of the download file.
// |reason| is the interrupt reason to inject. For no interrupt, use
// DOWNLOAD_INTERRUPT_REASON_NONE.
// |security_string| is the extra security information, if interrupted.
void OnResponseCompleted(const DownloadId& id,
content::DownloadInterruptReason reason,
const std::string& security_string) {
// OnResponseCompleted
// GetDownloadFile
// DownloadFile::Finish
// DownloadFile::GetDownloadManager
// DownloadFile::BytesSoFar
// Process one message in the message loop
//
// OK:
// DownloadFile::GetHash
// DownloadManager::OnResponseCompleted
//
// On Error:
// DownloadManager::OnDownloadInterrupted
MockDownloadFile* file = download_file_factory_->GetExistingFile(id);
ASSERT_TRUE(file != NULL);
EXPECT_CALL(*file, Finish());
EXPECT_CALL(*file, GetDownloadManager());
if (reason == content::DOWNLOAD_INTERRUPT_REASON_NONE) {
EXPECT_CALL(*file, GetHash(_))
.WillOnce(Return(false));
} else {
EXPECT_CALL(*file, GetHashState());
}
EXPECT_CALL(*file, BytesSoFar())
.Times(AtLeast(1))
.WillRepeatedly(Return(byte_count_[id]));
download_file_manager_->OnResponseCompleted(id, reason, security_string);
if (reason == content::DOWNLOAD_INTERRUPT_REASON_NONE) {
EXPECT_CALL(*download_manager_,
OnResponseCompleted(id.local(), byte_count_[id], ""))
.Times(1);
} else {
EXPECT_EQ(0, error_count_[id]);
EXPECT_CALL(*download_manager_,
OnDownloadInterrupted(id.local(),
byte_count_[id],
"",
reason))
.Times(1);
}
ProcessAllPendingMessages();
if (reason != content::DOWNLOAD_INTERRUPT_REASON_NONE)
++error_count_[id];
ClearExpectations(id);
}
void CleanUp(DownloadId id) {
// Expected calls:
// DownloadFileManager::CancelDownload
// DownloadFile::Cancel
// DownloadFileManager::EraseDownload
// if no more downloads:
// DownloadFileManager::StopUpdateTimer
MockDownloadFile* file = download_file_factory_->GetExistingFile(id);
ASSERT_TRUE(file != NULL);
EXPECT_CALL(*file, Cancel());
download_file_manager_->CancelDownload(id);
EXPECT_TRUE(NULL == download_file_manager_->GetDownloadFile(id));
}
protected:
scoped_refptr<MockDownloadManager> download_manager_;
scoped_ptr<MockDownloadRequestHandle> request_handle_;
MockDownloadFileFactory* download_file_factory_;
scoped_refptr<DownloadFileManager> download_file_manager_;
scoped_refptr<content::DownloadBuffer> download_buffer_;
// Per-download statistics.
std::map<DownloadId, int64> byte_count_;
std::map<DownloadId, int> error_count_;
private:
MessageLoop loop_;
// UI thread.
BrowserThreadImpl ui_thread_;
// File thread to satisfy debug checks in DownloadFile.
BrowserThreadImpl file_thread_;
};
const char* DownloadFileManagerTest::kTestData1 =
"Let's write some data to the file!\n";
const char* DownloadFileManagerTest::kTestData2 = "Writing more data.\n";
const char* DownloadFileManagerTest::kTestData3 = "Final line.";
const char* DownloadFileManagerTest::kTestData4 = "Writing, writing, writing\n";
const char* DownloadFileManagerTest::kTestData5 = "All we do is writing,\n";
const char* DownloadFileManagerTest::kTestData6 = "Rawhide!";
const int32 DownloadFileManagerTest::kDummyDownloadId = 23;
const int32 DownloadFileManagerTest::kDummyDownloadId2 = 77;
const int DownloadFileManagerTest::kDummyChildId = 3;
const int DownloadFileManagerTest::kDummyRequestId = 67;
TEST_F(DownloadFileManagerTest, CancelAtStart) {
DownloadCreateInfo* info = new DownloadCreateInfo;
DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
StartDownload(info, dummy_id);
CleanUp(dummy_id);
}
TEST_F(DownloadFileManagerTest, CancelBeforeFinished) {
// Same as StartDownload, at first.
DownloadCreateInfo* info = new DownloadCreateInfo;
DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
StartDownload(info, dummy_id);
UpdateDownload(dummy_id, kTestData1, strlen(kTestData1), net::OK);
UpdateDownload(dummy_id, kTestData2, strlen(kTestData2), net::OK);
UpdateDownload(dummy_id, kTestData3, strlen(kTestData3), net::OK);
CleanUp(dummy_id);
}
TEST_F(DownloadFileManagerTest, DownloadWithError) {
// Same as StartDownload, at first.
DownloadCreateInfo* info = new DownloadCreateInfo;
DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
StartDownload(info, dummy_id);
UpdateDownload(dummy_id, kTestData1, strlen(kTestData1), net::OK);
UpdateDownload(dummy_id, kTestData2, strlen(kTestData2),
net::ERR_FILE_NO_SPACE);
}
TEST_F(DownloadFileManagerTest, CompleteDownload) {
// Same as StartDownload, at first.
DownloadCreateInfo* info = new DownloadCreateInfo;
DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
StartDownload(info, dummy_id);
UpdateDownload(dummy_id, kTestData1, strlen(kTestData1), net::OK);
UpdateDownload(dummy_id, kTestData2, strlen(kTestData2), net::OK);
UpdateDownload(dummy_id, kTestData3, strlen(kTestData3), net::OK);
OnResponseCompleted(dummy_id, content::DOWNLOAD_INTERRUPT_REASON_NONE, "");
CleanUp(dummy_id);
}
TEST_F(DownloadFileManagerTest, CompleteDownloadWithError) {
// Same as StartDownload, at first.
DownloadCreateInfo* info = new DownloadCreateInfo;
DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
StartDownload(info, dummy_id);
UpdateDownload(dummy_id, kTestData1, strlen(kTestData1), net::OK);
UpdateDownload(dummy_id, kTestData2, strlen(kTestData2), net::OK);
UpdateDownload(dummy_id, kTestData3, strlen(kTestData3), net::OK);
OnResponseCompleted(dummy_id,
content::DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED,
"");
CleanUp(dummy_id);
}
TEST_F(DownloadFileManagerTest, RenameInProgress) {
// Same as StartDownload, at first.
DownloadCreateInfo* info = new DownloadCreateInfo;
DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
ScopedTempDir download_dir;
ASSERT_TRUE(download_dir.CreateUniqueTempDir());
StartDownload(info, dummy_id);
UpdateDownload(dummy_id, kTestData1, strlen(kTestData1), net::OK);
UpdateDownload(dummy_id, kTestData2, strlen(kTestData2), net::OK);
FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt")));
RenameFile(dummy_id, foo, foo, net::OK, IN_PROGRESS, OVERWRITE);
UpdateDownload(dummy_id, kTestData3, strlen(kTestData3), net::OK);
OnResponseCompleted(dummy_id, content::DOWNLOAD_INTERRUPT_REASON_NONE, "");
CleanUp(dummy_id);
}
TEST_F(DownloadFileManagerTest, RenameInProgressWithError) {
// Same as StartDownload, at first.
DownloadCreateInfo* info = new DownloadCreateInfo;
DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
ScopedTempDir download_dir;
ASSERT_TRUE(download_dir.CreateUniqueTempDir());
StartDownload(info, dummy_id);
UpdateDownload(dummy_id, kTestData1, strlen(kTestData1), net::OK);
UpdateDownload(dummy_id, kTestData2, strlen(kTestData2), net::OK);
FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt")));
RenameFile(dummy_id, foo, foo, net::ERR_FILE_PATH_TOO_LONG,
IN_PROGRESS, OVERWRITE);
CleanUp(dummy_id);
}
TEST_F(DownloadFileManagerTest, RenameCompleting) {
// Same as StartDownload, at first.
DownloadCreateInfo* info = new DownloadCreateInfo;
DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
ScopedTempDir download_dir;
ASSERT_TRUE(download_dir.CreateUniqueTempDir());
StartDownload(info, dummy_id);
UpdateDownload(dummy_id, kTestData1, strlen(kTestData1), net::OK);
UpdateDownload(dummy_id, kTestData2, strlen(kTestData2), net::OK);
UpdateDownload(dummy_id, kTestData3, strlen(kTestData3), net::OK);
OnResponseCompleted(dummy_id, content::DOWNLOAD_INTERRUPT_REASON_NONE, "");
FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt")));
RenameFile(dummy_id, foo, foo, net::OK, COMPLETE, OVERWRITE);
CleanUp(dummy_id);
}
TEST_F(DownloadFileManagerTest, RenameCompletingWithUniquification) {
// Same as StartDownload, at first.
DownloadCreateInfo* info = new DownloadCreateInfo;
DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
ScopedTempDir download_dir;
ASSERT_TRUE(download_dir.CreateUniqueTempDir());
StartDownload(info, dummy_id);
UpdateDownload(dummy_id, kTestData1, strlen(kTestData1), net::OK);
UpdateDownload(dummy_id, kTestData2, strlen(kTestData2), net::OK);
UpdateDownload(dummy_id, kTestData3, strlen(kTestData3), net::OK);
OnResponseCompleted(dummy_id, content::DOWNLOAD_INTERRUPT_REASON_NONE, "");
FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt")));
FilePath unique_foo(foo.InsertBeforeExtension(FILE_PATH_LITERAL(" (1)")));
// Create a file at |foo|. Since we are specifying DONT_OVERWRITE,
// RenameCompletingDownloadFile() should pick "foo (1).txt" instead of
// overwriting this file.
ASSERT_EQ(0, file_util::WriteFile(foo, "", 0));
RenameFile(dummy_id, foo, unique_foo, net::OK, COMPLETE, DONT_OVERWRITE);
CleanUp(dummy_id);
}
TEST_F(DownloadFileManagerTest, RenameCompletingWithError) {
// Same as StartDownload, at first.
DownloadCreateInfo* info = new DownloadCreateInfo;
DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
ScopedTempDir download_dir;
ASSERT_TRUE(download_dir.CreateUniqueTempDir());
StartDownload(info, dummy_id);
UpdateDownload(dummy_id, kTestData1, strlen(kTestData1), net::OK);
UpdateDownload(dummy_id, kTestData2, strlen(kTestData2), net::OK);
UpdateDownload(dummy_id, kTestData3, strlen(kTestData3), net::OK);
OnResponseCompleted(dummy_id, content::DOWNLOAD_INTERRUPT_REASON_NONE, "");
FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt")));
RenameFile(dummy_id, foo, foo, net::ERR_FILE_PATH_TOO_LONG,
COMPLETE, OVERWRITE);
CleanUp(dummy_id);
}
TEST_F(DownloadFileManagerTest, RenameTwice) {
// Same as StartDownload, at first.
DownloadCreateInfo* info = new DownloadCreateInfo;
DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
ScopedTempDir download_dir;
ASSERT_TRUE(download_dir.CreateUniqueTempDir());
StartDownload(info, dummy_id);
UpdateDownload(dummy_id, kTestData1, strlen(kTestData1), net::OK);
UpdateDownload(dummy_id, kTestData2, strlen(kTestData2), net::OK);
FilePath crfoo(download_dir.path().Append(
FILE_PATH_LITERAL("foo.txt.crdownload")));
RenameFile(dummy_id, crfoo, crfoo, net::OK, IN_PROGRESS, OVERWRITE);
UpdateDownload(dummy_id, kTestData3, strlen(kTestData3), net::OK);
OnResponseCompleted(dummy_id, content::DOWNLOAD_INTERRUPT_REASON_NONE, "");
FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt")));
RenameFile(dummy_id, foo, foo, net::OK, COMPLETE, OVERWRITE);
CleanUp(dummy_id);
}
TEST_F(DownloadFileManagerTest, TwoDownloads) {
// Same as StartDownload, at first.
DownloadCreateInfo* info = new DownloadCreateInfo;
DownloadCreateInfo* info2 = new DownloadCreateInfo;
DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
DownloadId dummy_id2(download_manager_.get(), kDummyDownloadId2);
ScopedTempDir download_dir;
ASSERT_TRUE(download_dir.CreateUniqueTempDir());
StartDownload(info, dummy_id);
UpdateDownload(dummy_id, kTestData1, strlen(kTestData1), net::OK);
StartDownload(info2, dummy_id2);
UpdateDownload(dummy_id, kTestData2, strlen(kTestData2), net::OK);
UpdateDownload(dummy_id2, kTestData4, strlen(kTestData4), net::OK);
FilePath crbar(download_dir.path().Append(
FILE_PATH_LITERAL("bar.txt.crdownload")));
RenameFile(dummy_id2, crbar, crbar, net::OK, IN_PROGRESS, OVERWRITE);
FilePath crfoo(download_dir.path().Append(
FILE_PATH_LITERAL("foo.txt.crdownload")));
RenameFile(dummy_id, crfoo, crfoo, net::OK, IN_PROGRESS, OVERWRITE);
UpdateDownload(dummy_id, kTestData3, strlen(kTestData3), net::OK);
UpdateDownload(dummy_id2, kTestData5, strlen(kTestData5), net::OK);
UpdateDownload(dummy_id2, kTestData6, strlen(kTestData6), net::OK);
OnResponseCompleted(dummy_id2, content::DOWNLOAD_INTERRUPT_REASON_NONE, "");
OnResponseCompleted(dummy_id, content::DOWNLOAD_INTERRUPT_REASON_NONE, "");
FilePath bar(download_dir.path().Append(FILE_PATH_LITERAL("bar.txt")));
RenameFile(dummy_id2, bar, bar, net::OK, COMPLETE, OVERWRITE);
CleanUp(dummy_id2);
FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt")));
RenameFile(dummy_id, foo, foo, net::OK, COMPLETE, OVERWRITE);
CleanUp(dummy_id);
}
// TODO(ahendrickson) -- A test for updating progress.
// Expected call sequence:
// UpdateInProgressDownloads
// DownloadFile::GetDownloadFile
// Process one message in the message loop
// DownloadManager::UpdateDownload
// TODO(ahendrickson) -- A test for download manager shutdown.
// Expected call sequence:
// OnDownloadManagerShutdown
// DownloadFile::GetDownloadManager
// DownloadFile::CancelDownloadRequest
// DownloadFile::~DownloadFile