Index: chrome/browser/download/download_manager_unittest.cc |
diff --git a/chrome/browser/download/download_manager_unittest.cc b/chrome/browser/download/download_manager_unittest.cc |
index 36849eb252997f48d73fb1d10de4ddc38ba7a659..94d94ffed7a34c454cdad4e07dfad0dabfa03bd2 100644 |
--- a/chrome/browser/download/download_manager_unittest.cc |
+++ b/chrome/browser/download/download_manager_unittest.cc |
@@ -31,6 +31,8 @@ |
#include "content/browser/download/download_status_updater.h" |
#include "content/browser/download/mock_download_manager.h" |
#include "grit/generated_resources.h" |
+#include "net/base/io_buffer.h" |
+#include "net/base/mock_file_stream.h" |
#include "testing/gmock/include/gmock/gmock.h" |
#include "testing/gmock_mutant.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -68,8 +70,9 @@ class DownloadManagerTest : public TestingBrowserProcessTest { |
file_manager()->downloads_[id] = download_file; |
} |
- void OnAllDataSaved(int32 download_id, int64 size, const std::string& hash) { |
- download_manager_->OnAllDataSaved(download_id, size, hash); |
+ void OnResponseCompleted(int32 download_id, int64 size, |
+ const std::string& hash) { |
+ download_manager_->OnResponseCompleted(download_id, size, hash); |
} |
void FileSelected(const FilePath& path, void* params) { |
@@ -80,6 +83,31 @@ class DownloadManagerTest : public TestingBrowserProcessTest { |
download_manager_->ContinueDownloadWithPath(download, path); |
} |
+ void UpdateData(int32 id, const void* data, size_t length) { |
+ // We are passing ownership of this buffer to the download file manager. |
+ net::IOBuffer* io_buffer = new net::IOBuffer(length); |
+ // We need |AddRef()| because io_buffer is not a |scoped_refptr|, and we |
+ // will do a |Release()| in |UpdateDownload()|. |
+ io_buffer->AddRef(); |
+ memcpy(io_buffer->data(), data, length); |
+ |
+ { |
+ base::AutoLock auto_lock(download_buffer_.lock); |
+ |
+ download_buffer_.contents.push_back( |
+ std::make_pair(io_buffer, length)); |
+ } |
+ |
+ BrowserThread::PostTask( |
+ BrowserThread::FILE, FROM_HERE, |
+ NewRunnableMethod(file_manager_.get(), |
+ &DownloadFileManager::UpdateDownload, |
+ id, |
+ &download_buffer_)); |
+ |
+ message_loop_.RunAllPending(); |
+ } |
+ |
void OnDownloadError(int32 download_id, int64 size, int os_error) { |
download_manager_->OnDownloadError(download_id, size, os_error); |
} |
@@ -100,6 +128,7 @@ class DownloadManagerTest : public TestingBrowserProcessTest { |
MessageLoopForUI message_loop_; |
BrowserThread ui_thread_; |
BrowserThread file_thread_; |
+ DownloadBuffer download_buffer_; |
DownloadFileManager* file_manager() { |
if (!file_manager_) { |
@@ -127,6 +156,31 @@ const char* DownloadManagerTest::kTestData = "a;sdlfalsdfjalsdkfjad"; |
const size_t DownloadManagerTest::kTestDataLen = |
strlen(DownloadManagerTest::kTestData); |
+// A DownloadFile that we can inject errors into. Uses MockFileStream. |
+// Note: This can't be in an anonymous namespace because it must be declared |
+// as a friend of |DownloadFile| in order to access its private members. |
+class DownloadFileWithMockStream : public DownloadFile { |
+ public: |
+ DownloadFileWithMockStream(DownloadCreateInfo* info, DownloadManager* manager) |
+ : DownloadFile(info, manager) { |
+ } |
+ virtual ~DownloadFileWithMockStream() { |
+ } |
+ |
+ void SetForcedError(int error) |
+ { |
+ testing::MockFileStream* mock_stream = |
+ static_cast<testing::MockFileStream *>(file_stream_.get()); |
Randy Smith (Not in Mondays)
2011/08/26 18:51:40
This kind of upcasting is nervous making and shoul
ahendrickson
2011/08/26 21:06:54
Leaving it in, per our conversation, but adding an
|
+ mock_stream->set_forced_error(error); |
+ } |
+ |
+ protected: |
+ // This version creates a |MockFileStream| instead of a |FileStream|. |
+ virtual void CreateFileStream() { |
+ file_stream_.reset(new testing::MockFileStream); |
+ } |
+}; |
+ |
namespace { |
const struct { |
@@ -385,13 +439,13 @@ TEST_F(DownloadManagerTest, DownloadRenameTest) { |
int32* id_ptr = new int32; |
*id_ptr = i; // Deleted in FileSelected(). |
if (kDownloadRenameCases[i].finish_before_rename) { |
- OnAllDataSaved(i, 1024, std::string("fake_hash")); |
+ OnResponseCompleted(i, 1024, std::string("fake_hash")); |
message_loop_.RunAllPending(); |
FileSelected(new_path, id_ptr); |
} else { |
FileSelected(new_path, id_ptr); |
message_loop_.RunAllPending(); |
- OnAllDataSaved(i, 1024, std::string("fake_hash")); |
+ OnResponseCompleted(i, 1024, std::string("fake_hash")); |
} |
message_loop_.RunAllPending(); |
@@ -483,6 +537,95 @@ TEST_F(DownloadManagerTest, DownloadInterruptTest) { |
EXPECT_EQ(download->total_bytes(), static_cast<int64>(kTestDataLen)); |
} |
+TEST_F(DownloadManagerTest, DownloadFileErrorTest) { |
Randy Smith (Not in Mondays)
2011/08/26 18:51:40
There's enough "stuff" in this test that I think i
Randy Smith (Not in Mondays)
2011/08/26 18:51:40
Comment before the function saying what functional
Randy Smith (Not in Mondays)
2011/08/26 18:51:40
I don't think this belongs under DownloadManagerTe
ahendrickson
2011/08/26 21:06:54
Done.
ahendrickson
2011/08/26 21:06:54
Done.
ahendrickson
2011/08/26 21:06:54
OK. Keeping.
|
+ using ::testing::_; |
+ using ::testing::CreateFunctor; |
Randy Smith (Not in Mondays)
2011/08/26 18:51:40
This has the look of a pattern copied from elsewhe
ahendrickson
2011/08/26 21:06:54
Yes, it was copied. The pattern is from using the
|
+ using ::testing::Invoke; |
+ using ::testing::Return; |
+ |
+ // Normally, the download system takes ownership of info, and is |
+ // responsible for deleting it. In these unit tests, however, we |
+ // don't call the function that deletes it, so we do so ourselves. |
+ scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo); |
Randy Smith (Not in Mondays)
2011/08/26 18:51:40
Any reason to make it a scoped_ptr rather than jus
ahendrickson
2011/08/26 21:06:54
Not really, other than as an example of how it is
|
+ int32 id = 0; |
+ info->download_id = id; |
+ info->prompt_user_for_save_location = false; |
+ info->url_chain.push_back(GURL()); |
+ info->total_bytes = static_cast<int64>(kTestDataLen * 3); |
+ FilePath path; |
+ ASSERT_TRUE(file_util::CreateTemporaryFile(&path)); |
+ testing::MockFileStream* mock_stream = new testing::MockFileStream; |
+ linked_ptr<net::FileStream> stream(mock_stream); |
Randy Smith (Not in Mondays)
2011/08/26 18:51:40
Why a linked_ptr? They're rare enough that I thin
ahendrickson
2011/08/26 21:06:54
This was necessary in order to assign it to info->
|
+ ASSERT_EQ(0, mock_stream->Open( |
+ path, |
+ base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE)); |
+ info->save_info.file_path = path; |
+ info->save_info.file_stream = stream; |
Randy Smith (Not in Mondays)
2011/08/26 18:51:40
I'd suggest moving the stream initialization to be
ahendrickson
2011/08/26 21:06:54
Done.
|
+ |
+ DownloadFileWithMockStream* download_file(new DownloadFileWithMockStream( |
+ info.get(), download_manager_)); |
+ AddDownloadToFileManager(id, download_file); |
+ |
+ // |download_file| is owned by DownloadFileManager. |
+ ::testing::Mock::AllowLeak(download_file); |
+ download_manager_->CreateDownloadItem(info.get()); |
+ |
+ DownloadItem* download = GetActiveDownloadItem(0); |
+ ASSERT_TRUE(download != NULL); |
+ scoped_ptr<DownloadItemModel> download_item_model( |
+ new DownloadItemModel(download)); |
+ |
+ EXPECT_EQ(DownloadItem::IN_PROGRESS, download->state()); |
+ scoped_ptr<ItemObserver> observer(new ItemObserver(download)); |
+ |
+ UpdateData(id, kTestData, kTestDataLen); |
+ |
+ ContinueDownloadWithPath(download, path); |
+ message_loop_.RunAllPending(); |
+ EXPECT_TRUE(GetActiveDownloadItem(0) != NULL); |
+ |
+ UpdateData(id, kTestData, kTestDataLen); |
+ |
+ download_file->SetForcedError(net::ERR_FAILED); |
+ UpdateData(id, kTestData, kTestDataLen); |
+ |
+ EXPECT_TRUE(GetActiveDownloadItem(0) == NULL); |
+ EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS)); |
+ EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED)); |
+ EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE)); |
+ EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED)); |
+ EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING)); |
+ EXPECT_TRUE(observer->was_updated()); |
+ EXPECT_FALSE(observer->was_opened()); |
+ EXPECT_FALSE(download->file_externally_removed()); |
+ EXPECT_EQ(DownloadItem::INTERRUPTED, download->state()); |
+ |
+ size_t error_size = kTestDataLen * 3; |
+ ui::DataUnits amount_units = ui::GetByteDisplayUnits(kTestDataLen); |
+ string16 simple_size = |
+ ui::FormatBytesWithUnits(error_size, amount_units, false); |
+ string16 simple_total = base::i18n::GetDisplayStringInLTRDirectionality( |
+ ui::FormatBytesWithUnits(error_size, amount_units, true)); |
+ EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_INTERRUPTED, |
+ simple_size, |
+ simple_total), |
+ download_item_model->GetStatusText()); |
+ |
+ download->Cancel(true); |
Randy Smith (Not in Mondays)
2011/08/26 18:51:40
Everything from here on in doesn't test any error
ahendrickson
2011/08/26 21:06:54
Done.
|
+ |
+ EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS)); |
+ EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED)); |
+ EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE)); |
+ EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED)); |
+ EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING)); |
+ EXPECT_TRUE(observer->was_updated()); |
+ EXPECT_FALSE(observer->was_opened()); |
+ EXPECT_FALSE(download->file_externally_removed()); |
+ EXPECT_EQ(DownloadItem::INTERRUPTED, download->state()); |
+ EXPECT_EQ(static_cast<int64>(error_size), download->received_bytes()); |
+ EXPECT_EQ(static_cast<int64>(kTestDataLen) * 3, download->total_bytes()); |
+} |
+ |
TEST_F(DownloadManagerTest, DownloadCancelTest) { |
using ::testing::_; |
using ::testing::CreateFunctor; |
@@ -610,7 +753,7 @@ TEST_F(DownloadManagerTest, DownloadOverwriteTest) { |
download_file->AppendDataToFile(kTestData, kTestDataLen); |
// Finish the download. |
- OnAllDataSaved(0, kTestDataLen, ""); |
+ OnResponseCompleted(0, kTestDataLen, ""); |
message_loop_.RunAllPending(); |
// Download is complete. |
@@ -686,7 +829,7 @@ TEST_F(DownloadManagerTest, DownloadRemoveTest) { |
download_file->AppendDataToFile(kTestData, kTestDataLen); |
// Finish the download. |
- OnAllDataSaved(0, kTestDataLen, ""); |
+ OnResponseCompleted(0, kTestDataLen, ""); |
message_loop_.RunAllPending(); |
// Download is complete. |