Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1208)

Unified Diff: chrome/browser/download/download_manager_unittest.cc

Issue 7646025: Detect file system errors during downloads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed Clang problem by moving MockFileStream method bodies to a cc file. Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | content/browser/download/base_file.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 58c39fa36df05fc6b64bca79419515ae2768b082..532e734ff0082ec8c1be74f4db28dd9ab2d217cd 100644
--- a/chrome/browser/download/download_manager_unittest.cc
+++ b/chrome/browser/download/download_manager_unittest.cc
@@ -30,6 +30,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"
@@ -67,8 +69,9 @@ class DownloadManagerTest : public testing::Test {
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) {
@@ -79,6 +82,30 @@ class DownloadManagerTest : public testing::Test {
download_manager_->ContinueDownloadWithPath(download, path);
}
+ void UpdateData(int32 id, const char* 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 we 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);
}
@@ -99,6 +126,7 @@ class DownloadManagerTest : public testing::Test {
MessageLoopForUI message_loop_;
BrowserThread ui_thread_;
BrowserThread file_thread_;
+ DownloadBuffer download_buffer_;
DownloadFileManager* file_manager() {
if (!file_manager_) {
@@ -126,6 +154,39 @@ 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,
+ testing::MockFileStream* stream)
+ : DownloadFile(info, manager) {
+ DCHECK(file_stream_ == NULL);
+ file_stream_.reset(stream);
+ }
+ virtual ~DownloadFileWithMockStream() {
+ }
+
+ void SetForcedError(int error)
+ {
+ // |file_stream_| can only be set in the constructor and in
+ // CreateFileStream(), both of which insure that it is a |MockFileStream|.
+ testing::MockFileStream* mock_stream =
+ static_cast<testing::MockFileStream *>(file_stream_.get());
+ mock_stream->set_forced_error(error);
+ }
+
+ protected:
+ // This version creates a |MockFileStream| instead of a |FileStream|.
+ virtual void CreateFileStream() OVERRIDE;
+};
+
+void DownloadFileWithMockStream::CreateFileStream() {
Randy Smith (Not in Mondays) 2011/08/29 17:02:07 nit: I'd like to see the class written consistentl
ahendrickson 2011/08/29 17:51:38 Done.
+ file_stream_.reset(new testing::MockFileStream);
+}
+
namespace {
const struct {
@@ -384,13 +445,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();
@@ -482,6 +543,91 @@ TEST_F(DownloadManagerTest, DownloadInterruptTest) {
EXPECT_EQ(download->total_bytes(), static_cast<int64>(kTestDataLen));
}
+// Test the behavior of DownloadFileManager and DownloadManager in the event
+// of a file error while writing the download to disk.
+TEST_F(DownloadManagerTest, DownloadFileErrorTest) {
+ // Create a temporary file and a mock stream.
+ FilePath path;
+ ASSERT_TRUE(file_util::CreateTemporaryFile(&path));
+
+ // This file stream will be used, until the first rename occurs.
+ testing::MockFileStream* mock_stream = new testing::MockFileStream;
+ ASSERT_EQ(0, mock_stream->Open(
+ path,
+ base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE));
+
+ // 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 can use a stack variable.
+ DownloadCreateInfo info;
+ 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);
+ info.save_info.file_path = path;
+
+ // Create a download file that we can insert errors into.
+ DownloadFileWithMockStream* download_file(new DownloadFileWithMockStream(
+ &info, download_manager_, mock_stream));
+ AddDownloadToFileManager(id, download_file);
+
+ // |download_file| is owned by DownloadFileManager.
+ download_manager_->CreateDownloadItem(&info);
+
+ DownloadItem* download = GetActiveDownloadItem(0);
+ ASSERT_TRUE(download != NULL);
+ // This will keep track of what should be displayed on the shelf.
+ scoped_ptr<DownloadItemModel> download_item_model(
+ new DownloadItemModel(download));
+
+ EXPECT_EQ(DownloadItem::IN_PROGRESS, download->state());
+ scoped_ptr<ItemObserver> observer(new ItemObserver(download));
+
+ // Add some data before finalizing the file name.
+ UpdateData(id, kTestData, kTestDataLen);
+
+ // Finalize the file name.
+ ContinueDownloadWithPath(download, path);
+ message_loop_.RunAllPending();
+ EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
+
+ // Add more data.
+ UpdateData(id, kTestData, kTestDataLen);
+
+ // Add more data, but an error occurs.
+ download_file->SetForcedError(net::ERR_FAILED);
+ UpdateData(id, kTestData, kTestDataLen);
+
+ // Check the state. The download should have been interrupted.
+ 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());
+
+ // Check the download shelf's information.
+ 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());
+
+ // Clean up.
+ download->Cancel(true);
+ message_loop_.RunAllPending();
+}
+
TEST_F(DownloadManagerTest, DownloadCancelTest) {
using ::testing::_;
using ::testing::CreateFunctor;
@@ -609,7 +755,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.
@@ -685,7 +831,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.
« no previous file with comments | « no previous file | content/browser/download/base_file.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698