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

Unified Diff: content/test/test_file_error_injector.cc

Issue 9426029: Test file errors in downloads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merged with parent Created 8 years, 10 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
Index: content/test/test_file_error_injector.cc
diff --git a/content/test/test_file_error_injector.cc b/content/test/test_file_error_injector.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e4204e6ade4c7ca5b6597ee7a2fc47ed54d04cd4
--- /dev/null
+++ b/content/test/test_file_error_injector.cc
@@ -0,0 +1,355 @@
+// Copyright (c) 2011 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/test/test_file_error_injector.h"
+
+#include <map>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "content/browser/download/download_file_impl.h"
+#include "content/browser/download/download_file_manager.h"
+#include "content/browser/renderer_host/resource_dispatcher_host.h"
+
+class DownloadFileWithErrors;
+
+namespace {
+
+// Structure that encapsulates the information needed to inject a file error.
+struct FileErrorInfo {
+ FileErrorInfo()
+ : file_index(-1),
+ code(FILE_OPERATION_INITIALIZE),
+ operation_instance(-1),
+ net_error(net::OK) {
+ }
+
+ int file_index; // 0-based.
+ FileOperationCode code;
+ int operation_instance; // 0-based.
+ net::Error net_error;
+};
+
+// List of errors.
+typedef std::vector<FileErrorInfo> ErrorList;
+
+// Structure that associates a file with a set of errors.
+struct FileErrors {
+ FileErrors() : file(NULL) {}
+
+ DownloadFileWithErrors* file;
+ ErrorList error_list;
+};
+
+DownloadFileManager* GetDownloadFileManager() {
+ ResourceDispatcherHost* rdh = ResourceDispatcherHost::Get();
+ DCHECK(rdh != NULL);
+ return rdh->download_file_manager();
+}
+
+std::string DebugString(FileOperationCode code) {
+
+#define TO_STRING(code) case FILE_OPERATION_##code: return #code
+
+ switch (code) {
+ TO_STRING(INITIALIZE);
+ TO_STRING(WRITE);
+ TO_STRING(RENAME);
+ default:
+ break;
+ }
+
+#undef TO_STRING
+
+ return "Unknown";
+}
+
+} // namespace
+
+class TestFileErrorInjectorImpl : public TestFileErrorInjector {
+ public:
+ TestFileErrorInjectorImpl();
+
+ // TestFileErrorInjector interface.
+ virtual bool InjectError(int file_index,
+ FileOperationCode operation,
+ int operation_instance,
+ net::Error net_error) OVERRIDE;
+ virtual size_t CurrentFileCount() const OVERRIDE;
+ virtual size_t FileCreationCount() const OVERRIDE { return file_counter_; }
+
+ // Callbacks from the download file.
+ virtual int DownloadFileCreated(DownloadFileWithErrors* download_file);
+ virtual void DestroyingDownloadFile(DownloadFileWithErrors* download_file);
+
+ private:
+ virtual ~TestFileErrorInjectorImpl();
+
+ // The number of files we've created.
+ int file_counter_;
+
+ // Our injected error list, mapped by file index.
+ std::map<int, FileErrors> injected_errors_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestFileErrorInjectorImpl);
+};
+
+// A class that performs file operations and injects errors.
+class DownloadFileWithErrors: public DownloadFileImpl {
+ public:
+ DownloadFileWithErrors(const DownloadCreateInfo* info,
+ DownloadRequestHandleInterface* request_handle,
+ content::DownloadManager* download_manager,
+ bool calculate_hash,
+ const net::BoundNetLog& bound_net_log,
+ scoped_refptr<TestFileErrorInjectorImpl> injector);
+
+ ~DownloadFileWithErrors();
+
+ // DownloadFile interface.
+ virtual net::Error Initialize() OVERRIDE;
+ virtual net::Error AppendDataToFile(const char* data,
+ size_t data_len) OVERRIDE;
+ virtual net::Error Rename(const FilePath& full_path) OVERRIDE;
+
+ // Error generating helpers.
+ net::Error ShouldReturnError(FileOperationCode code,
+ net::Error original_net_error);
+
+ void AddError(const FileErrorInfo& info);
+ void SetErrorList(int index,
+ const ErrorList& error_list);
+ int index() const { return index_; }
+
+ private:
+ // Map from instance number to file error information.
+ typedef std::map<int, FileErrorInfo> InstanceMap;
+
+ // Map of errors by operation code
+ typedef std::map<FileOperationCode,
+ InstanceMap> ErrorMap;
+
+ // The class that manages errors.
+ scoped_refptr<TestFileErrorInjectorImpl> injector_;
+
+ // Our file index.
+ int index_;
+
+ // Our injected error list.
+ ErrorMap error_map_;
+
+ // Count per operation. 0-based.
+ std::map<FileOperationCode, int> operation_counter_;
+};
+
+// A factory for constructing DownloadFiles that inject errors.
+class DownloadFileWithErrorsFactory
+ : public DownloadFileManager::DownloadFileFactory {
+ public:
+
+ explicit DownloadFileWithErrorsFactory(
+ scoped_refptr<TestFileErrorInjectorImpl> injector);
+
+ virtual ~DownloadFileWithErrorsFactory();
+
+ virtual content::DownloadFile* CreateFile(
+ DownloadCreateInfo* info,
+ const DownloadRequestHandle& request_handle,
+ content::DownloadManager* download_manager,
+ bool calculate_hash,
+ const net::BoundNetLog& bound_net_log);
+
+ private:
+
+ scoped_refptr<TestFileErrorInjectorImpl> injector_;
+};
+
+
+// Implementations.
+
+// static
+TestFileErrorInjector* TestFileErrorInjector::Create() {
+ return new TestFileErrorInjectorImpl;
+}
+
+TestFileErrorInjectorImpl::TestFileErrorInjectorImpl() : file_counter_(0) {
+ DownloadFileWithErrorsFactory* download_file_factory =
+ new DownloadFileWithErrorsFactory(this);
+ DownloadFileManager* download_file_manager = GetDownloadFileManager();
+ DCHECK(download_file_manager);
+ // Transfers ownership.
+ download_file_manager->SetFileFactory(download_file_factory);
+}
+
+TestFileErrorInjectorImpl::~TestFileErrorInjectorImpl() {
+}
+
+bool TestFileErrorInjectorImpl::InjectError(int file_index,
+ FileOperationCode operation,
+ int operation_instance,
+ net::Error net_error) {
+ DCHECK_LE(0, file_index);
+ DCHECK_LE(0, operation_instance);
+
+ // Fill in a new entry.
+ FileErrorInfo info;
+ info.file_index = file_index;
+ info.code = operation;
+ info.operation_instance = operation_instance;
+ info.net_error = net_error;
+
+ // Creates an empty entry if necessary.
+ FileErrors& file_errors = injected_errors_[file_index];
+ file_errors.error_list.push_back(info);
+
+ // If the file already exists, simply add this entry to the error list.
cbentzel 2012/02/24 02:25:12 Do you need to handle this case?
ahendrickson 2012/02/24 22:48:39 Removed.
+ if (file_errors.file != NULL)
+ file_errors.file->AddError(info);
+
+ return true;
+}
+
+size_t TestFileErrorInjectorImpl::CurrentFileCount() const {
+ size_t count = 0;
+
+ // Count the map entries with a non-NULL file pointer.
+ for (std::map<int, FileErrors>::const_iterator it = injected_errors_.begin();
+ it != injected_errors_.end();
+ ++it) {
+ if (it->second.file != NULL)
+ count++;
+ }
+
+ return count;
+}
+
+int TestFileErrorInjectorImpl::DownloadFileCreated(
+ DownloadFileWithErrors* download_file) {
+ DCHECK(download_file != NULL);
+
+ // Creates an empty instance if necessary.
+ FileErrors& file_errors = injected_errors_[file_counter_];
+ DCHECK(file_errors.file == NULL);
+ file_errors.file = download_file; // Set the file.
+
+ download_file->SetErrorList(file_counter_, file_errors.error_list);
+
+ return file_counter_++;
+}
+
+void TestFileErrorInjectorImpl::DestroyingDownloadFile(
+ DownloadFileWithErrors* download_file) {
+ DCHECK(download_file != NULL);
+
+ // Mark as gone by making the file NULL.
+ injected_errors_[download_file->index()].file = NULL;
+}
+
+DownloadFileWithErrors::DownloadFileWithErrors(
+ const DownloadCreateInfo* info,
+ DownloadRequestHandleInterface* request_handle,
+ content::DownloadManager* download_manager,
+ bool calculate_hash,
+ const net::BoundNetLog& bound_net_log,
+ scoped_refptr<TestFileErrorInjectorImpl> injector)
+ : DownloadFileImpl(info,
+ request_handle,
+ download_manager,
+ calculate_hash,
+ bound_net_log),
+ injector_(injector),
+ index_(-1) {
+ if (injector_)
+ injector_->DownloadFileCreated(this);
+}
+
+DownloadFileWithErrors::~DownloadFileWithErrors() {
+ if (injector_)
+ injector_->DestroyingDownloadFile(this);
+}
+
+
+net::Error DownloadFileWithErrors::Initialize() {
+ return ShouldReturnError(FILE_OPERATION_INITIALIZE,
+ DownloadFileImpl::Initialize());
+}
+
+net::Error DownloadFileWithErrors::AppendDataToFile(const char* data,
+ size_t data_len) {
+ return ShouldReturnError(FILE_OPERATION_WRITE,
+ DownloadFileImpl::AppendDataToFile(data, data_len));
+}
+
+net::Error DownloadFileWithErrors::Rename(const FilePath& full_path) {
+ return ShouldReturnError(FILE_OPERATION_RENAME,
+ DownloadFileImpl::Rename(full_path));
+}
+
+net::Error DownloadFileWithErrors::ShouldReturnError(
+ FileOperationCode code,
+ net::Error original_net_error) {
+ int counter = operation_counter_[code];
+ ++operation_counter_[code];
+
+ if (error_map_.find(code) == error_map_.end())
+ return original_net_error; // No errors for this operation.
+
+ InstanceMap& instance_map = error_map_[code];
+
+ if (instance_map.find(counter) == instance_map.end())
+ return original_net_error; // No error for this instance of the operation.
+
+ DVLOG(20) << " " << __FUNCTION__ << "()"
+ << " code = " << ::DebugString(code) << " (" << code << ")"
+ << " counter = " << counter
+ << " original_error = " << original_net_error
+ << " new error = " << instance_map[counter].net_error;
+
+ return instance_map[counter].net_error; // Error!
+}
+
+void DownloadFileWithErrors::AddError(
+ const FileErrorInfo& info) {
+ // Get the instance map for the operation code.
+ InstanceMap& instance_map = error_map_[info.code];
+
+ // Duplicate entries are an error.
+ DCHECK(instance_map.end() == instance_map.find(info.operation_instance));
+
+ // Set the error information in the map.
+ instance_map[info.operation_instance] = info;
+}
+
+void DownloadFileWithErrors::SetErrorList(
+ int index, const ErrorList& error_list) {
+ DCHECK_EQ(-1, index_);
+ DCHECK_LE(0, index);
+ index_ = index;
+
+ // Parcel out the error list by operation code and instance.
+ for (size_t i = 0; i < error_list.size(); ++i)
+ AddError(error_list[i]);
+}
+
+DownloadFileWithErrorsFactory::DownloadFileWithErrorsFactory(
+ scoped_refptr<TestFileErrorInjectorImpl> injector) : injector_(injector) {
+}
+
+DownloadFileWithErrorsFactory::~DownloadFileWithErrorsFactory() {
+}
+
+content::DownloadFile* DownloadFileWithErrorsFactory::CreateFile(
+ DownloadCreateInfo* info,
+ const DownloadRequestHandle& request_handle,
+ content::DownloadManager* download_manager,
+ bool calculate_hash,
+ const net::BoundNetLog& bound_net_log) {
+ return new DownloadFileWithErrors(info,
+ new DownloadRequestHandle(request_handle),
+ download_manager,
+ calculate_hash,
+ bound_net_log,
+ injector_);
+}
« content/test/test_file_error_injector.h ('K') | « content/test/test_file_error_injector.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698