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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/test/test_file_error_injector.h"
6
7 #include <map>
8 #include <vector>
9
10 #include "base/compiler_specific.h"
11 #include "base/logging.h"
12 #include "content/browser/download/download_file_impl.h"
13 #include "content/browser/download/download_file_manager.h"
14 #include "content/browser/renderer_host/resource_dispatcher_host.h"
15
16 class DownloadFileWithErrors;
17
18 namespace {
19
20 // Structure that encapsulates the information needed to inject a file error.
21 struct FileErrorInfo {
22 FileErrorInfo()
23 : file_index(-1),
24 code(FILE_OPERATION_INITIALIZE),
25 operation_instance(-1),
26 net_error(net::OK) {
27 }
28
29 int file_index; // 0-based.
30 FileOperationCode code;
31 int operation_instance; // 0-based.
32 net::Error net_error;
33 };
34
35 // List of errors.
36 typedef std::vector<FileErrorInfo> ErrorList;
37
38 // Structure that associates a file with a set of errors.
39 struct FileErrors {
40 FileErrors() : file(NULL) {}
41
42 DownloadFileWithErrors* file;
43 ErrorList error_list;
44 };
45
46 DownloadFileManager* GetDownloadFileManager() {
47 ResourceDispatcherHost* rdh = ResourceDispatcherHost::Get();
48 DCHECK(rdh != NULL);
49 return rdh->download_file_manager();
50 }
51
52 std::string DebugString(FileOperationCode code) {
53
54 #define TO_STRING(code) case FILE_OPERATION_##code: return #code
55
56 switch (code) {
57 TO_STRING(INITIALIZE);
58 TO_STRING(WRITE);
59 TO_STRING(RENAME);
60 default:
61 break;
62 }
63
64 #undef TO_STRING
65
66 return "Unknown";
67 }
68
69 } // namespace
70
71 class TestFileErrorInjectorImpl : public TestFileErrorInjector {
72 public:
73 TestFileErrorInjectorImpl();
74
75 // TestFileErrorInjector interface.
76 virtual bool InjectError(int file_index,
77 FileOperationCode operation,
78 int operation_instance,
79 net::Error net_error) OVERRIDE;
80 virtual size_t CurrentFileCount() const OVERRIDE;
81 virtual size_t FileCreationCount() const OVERRIDE { return file_counter_; }
82
83 // Callbacks from the download file.
84 virtual int DownloadFileCreated(DownloadFileWithErrors* download_file);
85 virtual void DestroyingDownloadFile(DownloadFileWithErrors* download_file);
86
87 private:
88 virtual ~TestFileErrorInjectorImpl();
89
90 // The number of files we've created.
91 int file_counter_;
92
93 // Our injected error list, mapped by file index.
94 std::map<int, FileErrors> injected_errors_;
95
96 DISALLOW_COPY_AND_ASSIGN(TestFileErrorInjectorImpl);
97 };
98
99 // A class that performs file operations and injects errors.
100 class DownloadFileWithErrors: public DownloadFileImpl {
101 public:
102 DownloadFileWithErrors(const DownloadCreateInfo* info,
103 DownloadRequestHandleInterface* request_handle,
104 content::DownloadManager* download_manager,
105 bool calculate_hash,
106 const net::BoundNetLog& bound_net_log,
107 scoped_refptr<TestFileErrorInjectorImpl> injector);
108
109 ~DownloadFileWithErrors();
110
111 // DownloadFile interface.
112 virtual net::Error Initialize() OVERRIDE;
113 virtual net::Error AppendDataToFile(const char* data,
114 size_t data_len) OVERRIDE;
115 virtual net::Error Rename(const FilePath& full_path) OVERRIDE;
116
117 // Error generating helpers.
118 net::Error ShouldReturnError(FileOperationCode code,
119 net::Error original_net_error);
120
121 void AddError(const FileErrorInfo& info);
122 void SetErrorList(int index,
123 const ErrorList& error_list);
124 int index() const { return index_; }
125
126 private:
127 // Map from instance number to file error information.
128 typedef std::map<int, FileErrorInfo> InstanceMap;
129
130 // Map of errors by operation code
131 typedef std::map<FileOperationCode,
132 InstanceMap> ErrorMap;
133
134 // The class that manages errors.
135 scoped_refptr<TestFileErrorInjectorImpl> injector_;
136
137 // Our file index.
138 int index_;
139
140 // Our injected error list.
141 ErrorMap error_map_;
142
143 // Count per operation. 0-based.
144 std::map<FileOperationCode, int> operation_counter_;
145 };
146
147 // A factory for constructing DownloadFiles that inject errors.
148 class DownloadFileWithErrorsFactory
149 : public DownloadFileManager::DownloadFileFactory {
150 public:
151
152 explicit DownloadFileWithErrorsFactory(
153 scoped_refptr<TestFileErrorInjectorImpl> injector);
154
155 virtual ~DownloadFileWithErrorsFactory();
156
157 virtual content::DownloadFile* CreateFile(
158 DownloadCreateInfo* info,
159 const DownloadRequestHandle& request_handle,
160 content::DownloadManager* download_manager,
161 bool calculate_hash,
162 const net::BoundNetLog& bound_net_log);
163
164 private:
165
166 scoped_refptr<TestFileErrorInjectorImpl> injector_;
167 };
168
169
170 // Implementations.
171
172 // static
173 TestFileErrorInjector* TestFileErrorInjector::Create() {
174 return new TestFileErrorInjectorImpl;
175 }
176
177 TestFileErrorInjectorImpl::TestFileErrorInjectorImpl() : file_counter_(0) {
178 DownloadFileWithErrorsFactory* download_file_factory =
179 new DownloadFileWithErrorsFactory(this);
180 DownloadFileManager* download_file_manager = GetDownloadFileManager();
181 DCHECK(download_file_manager);
182 // Transfers ownership.
183 download_file_manager->SetFileFactory(download_file_factory);
184 }
185
186 TestFileErrorInjectorImpl::~TestFileErrorInjectorImpl() {
187 }
188
189 bool TestFileErrorInjectorImpl::InjectError(int file_index,
190 FileOperationCode operation,
191 int operation_instance,
192 net::Error net_error) {
193 DCHECK_LE(0, file_index);
194 DCHECK_LE(0, operation_instance);
195
196 // Fill in a new entry.
197 FileErrorInfo info;
198 info.file_index = file_index;
199 info.code = operation;
200 info.operation_instance = operation_instance;
201 info.net_error = net_error;
202
203 // Creates an empty entry if necessary.
204 FileErrors& file_errors = injected_errors_[file_index];
205 file_errors.error_list.push_back(info);
206
207 // 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.
208 if (file_errors.file != NULL)
209 file_errors.file->AddError(info);
210
211 return true;
212 }
213
214 size_t TestFileErrorInjectorImpl::CurrentFileCount() const {
215 size_t count = 0;
216
217 // Count the map entries with a non-NULL file pointer.
218 for (std::map<int, FileErrors>::const_iterator it = injected_errors_.begin();
219 it != injected_errors_.end();
220 ++it) {
221 if (it->second.file != NULL)
222 count++;
223 }
224
225 return count;
226 }
227
228 int TestFileErrorInjectorImpl::DownloadFileCreated(
229 DownloadFileWithErrors* download_file) {
230 DCHECK(download_file != NULL);
231
232 // Creates an empty instance if necessary.
233 FileErrors& file_errors = injected_errors_[file_counter_];
234 DCHECK(file_errors.file == NULL);
235 file_errors.file = download_file; // Set the file.
236
237 download_file->SetErrorList(file_counter_, file_errors.error_list);
238
239 return file_counter_++;
240 }
241
242 void TestFileErrorInjectorImpl::DestroyingDownloadFile(
243 DownloadFileWithErrors* download_file) {
244 DCHECK(download_file != NULL);
245
246 // Mark as gone by making the file NULL.
247 injected_errors_[download_file->index()].file = NULL;
248 }
249
250 DownloadFileWithErrors::DownloadFileWithErrors(
251 const DownloadCreateInfo* info,
252 DownloadRequestHandleInterface* request_handle,
253 content::DownloadManager* download_manager,
254 bool calculate_hash,
255 const net::BoundNetLog& bound_net_log,
256 scoped_refptr<TestFileErrorInjectorImpl> injector)
257 : DownloadFileImpl(info,
258 request_handle,
259 download_manager,
260 calculate_hash,
261 bound_net_log),
262 injector_(injector),
263 index_(-1) {
264 if (injector_)
265 injector_->DownloadFileCreated(this);
266 }
267
268 DownloadFileWithErrors::~DownloadFileWithErrors() {
269 if (injector_)
270 injector_->DestroyingDownloadFile(this);
271 }
272
273
274 net::Error DownloadFileWithErrors::Initialize() {
275 return ShouldReturnError(FILE_OPERATION_INITIALIZE,
276 DownloadFileImpl::Initialize());
277 }
278
279 net::Error DownloadFileWithErrors::AppendDataToFile(const char* data,
280 size_t data_len) {
281 return ShouldReturnError(FILE_OPERATION_WRITE,
282 DownloadFileImpl::AppendDataToFile(data, data_len));
283 }
284
285 net::Error DownloadFileWithErrors::Rename(const FilePath& full_path) {
286 return ShouldReturnError(FILE_OPERATION_RENAME,
287 DownloadFileImpl::Rename(full_path));
288 }
289
290 net::Error DownloadFileWithErrors::ShouldReturnError(
291 FileOperationCode code,
292 net::Error original_net_error) {
293 int counter = operation_counter_[code];
294 ++operation_counter_[code];
295
296 if (error_map_.find(code) == error_map_.end())
297 return original_net_error; // No errors for this operation.
298
299 InstanceMap& instance_map = error_map_[code];
300
301 if (instance_map.find(counter) == instance_map.end())
302 return original_net_error; // No error for this instance of the operation.
303
304 DVLOG(20) << " " << __FUNCTION__ << "()"
305 << " code = " << ::DebugString(code) << " (" << code << ")"
306 << " counter = " << counter
307 << " original_error = " << original_net_error
308 << " new error = " << instance_map[counter].net_error;
309
310 return instance_map[counter].net_error; // Error!
311 }
312
313 void DownloadFileWithErrors::AddError(
314 const FileErrorInfo& info) {
315 // Get the instance map for the operation code.
316 InstanceMap& instance_map = error_map_[info.code];
317
318 // Duplicate entries are an error.
319 DCHECK(instance_map.end() == instance_map.find(info.operation_instance));
320
321 // Set the error information in the map.
322 instance_map[info.operation_instance] = info;
323 }
324
325 void DownloadFileWithErrors::SetErrorList(
326 int index, const ErrorList& error_list) {
327 DCHECK_EQ(-1, index_);
328 DCHECK_LE(0, index);
329 index_ = index;
330
331 // Parcel out the error list by operation code and instance.
332 for (size_t i = 0; i < error_list.size(); ++i)
333 AddError(error_list[i]);
334 }
335
336 DownloadFileWithErrorsFactory::DownloadFileWithErrorsFactory(
337 scoped_refptr<TestFileErrorInjectorImpl> injector) : injector_(injector) {
338 }
339
340 DownloadFileWithErrorsFactory::~DownloadFileWithErrorsFactory() {
341 }
342
343 content::DownloadFile* DownloadFileWithErrorsFactory::CreateFile(
344 DownloadCreateInfo* info,
345 const DownloadRequestHandle& request_handle,
346 content::DownloadManager* download_manager,
347 bool calculate_hash,
348 const net::BoundNetLog& bound_net_log) {
349 return new DownloadFileWithErrors(info,
350 new DownloadRequestHandle(request_handle),
351 download_manager,
352 calculate_hash,
353 bound_net_log,
354 injector_);
355 }
OLDNEW
« 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