1 // Copyright (c) 2012 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 #ifndef CONTENT_PUBLIC_TEST_TEST_FILE_ERROR_INJECTOR_H_ 6 #define CONTENT_PUBLIC_TEST_TEST_FILE_ERROR_INJECTOR_H_ 7 8 #include <map> 9 #include <set> 10 #include <string> 11 12 #include "base/memory/ref_counted.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/ref_counted.h" 15 #include "content/public/browser/download_interrupt_reasons.h" 16 17 class GURL; 18 19 namespace content { 20 21 class DownloadId; 22 class DownloadFileWithErrorsFactory; 23 class DownloadManager; 24 class DownloadManagerImpl; 25 26 // Test helper for injecting errors into download file operations. 27 // All errors for a download must be injected before it starts. 28 // This class needs to be |RefCountedThreadSafe| because the implementation 29 // is referenced by other classes that live past the time when the user is 30 // nominally done with it. These classes are internal to content/. 31 // 32 // NOTE: No more than one download with the same URL can be in progress at 33 // the same time. You can have multiple simultaneous downloads as long as the 34 // URLs are different, as the URLs are used as keys to get information about 35 // the download. 36 // 37 // Example: 38 // 39 // FileErrorInfo a = { url1, ... }; 40 // FileErrorInfo b = { url2, ... }; 41 // 42 // scoped_refptr<TestFileErrorInjector> injector = 43 // TestFileErrorInjector::Create(download_manager); 44 // 45 // injector->AddError(a); 46 // injector->AddError(b); 47 // injector->InjectErrors(); 48 // 49 // download_manager->DownloadUrl(url1, ...); 50 // download_manager->DownloadUrl(url2, ...); 51 // ... wait for downloads to finish or get an injected error ... 52 class TestFileErrorInjector 53 : public base::RefCountedThreadSafe<TestFileErrorInjector> { 54 public: 55 enum FileOperationCode { 56 FILE_OPERATION_INITIALIZE, 57 FILE_OPERATION_WRITE, 58 FILE_OPERATION_RENAME_UNIQUIFY, 59 FILE_OPERATION_RENAME_ANNOTATE, 60 }; 61 62 // Structure that encapsulates the information needed to inject a file error. 63 struct FileErrorInfo { 64 std::string url; // Full URL of the download. Identifies the download. 65 FileOperationCode code; // Operation to affect. 66 int operation_instance; // 0-based count of operation calls, for each code. 67 DownloadInterruptReason error; // Error to inject. 68 }; 69 70 typedef std::map<std::string, FileErrorInfo> ErrorMap; 71 72 // Creates an instance. May only be called once. 73 // Lives until all callbacks (in the implementation) are complete and the 74 // creator goes out of scope. 75 // TODO(rdsmith): Allow multiple calls for different download managers. 76 static scoped_refptr<TestFileErrorInjector> Create( 77 DownloadManager* download_manager); 78 79 // Adds an error. 80 // Must be called before |InjectErrors()| for a particular download file. 81 // It is an error to call |AddError()| more than once for the same file 82 // (URL), unless you call |ClearErrors()| in between them. 83 bool AddError(const FileErrorInfo& error_info); 84 85 // Clears all errors. 86 // Only affects files created after the next call to InjectErrors(). 87 void ClearErrors(); 88 89 // Injects the errors such that new download files will be affected. 90 // The download system must already be initialized before calling this. 91 // Multiple calls are allowed, but only useful if the errors have changed. 92 // Replaces the injected error list. 93 bool InjectErrors(); 94 95 // Tells how many files are currently open. 96 size_t CurrentFileCount() const; 97 98 // Tells how many files have ever been open (since construction or the 99 // last call to |ClearFoundFiles()|). 100 size_t TotalFileCount() const; 101 102 // Returns whether or not a file matching |url| has been created. 103 bool HadFile(const GURL& url) const; 104 105 // Resets the found file list. 106 void ClearFoundFiles(); 107 108 static std::string DebugString(FileOperationCode code); 109 110 private: 111 friend class base::RefCountedThreadSafe<TestFileErrorInjector>; 112 113 typedef std::set<GURL> FileSet; 114 115 explicit TestFileErrorInjector(DownloadManager* download_manager); 116 117 virtual ~TestFileErrorInjector(); 118 119 // Callbacks from the download file, to record lifetimes. 120 // These may be called on any thread. 121 void RecordDownloadFileConstruction(const GURL& url); 122 void RecordDownloadFileDestruction(const GURL& url); 123 124 // These run on the UI thread. 125 void DownloadFileCreated(GURL url); 126 void DestroyingDownloadFile(GURL url); 127 128 // All the data is used on the UI thread. 129 // Our injected error list, mapped by URL. One per file. 130 ErrorMap injected_errors_; 131 132 // Keep track of active DownloadFiles. 133 FileSet files_; 134 135 // Keep track of found DownloadFiles. 136 FileSet found_files_; 137 138 // The factory we created. May outlive this class. 139 DownloadFileWithErrorsFactory* created_factory_; 140 141 // The download manager we set the factory on. 142 DownloadManagerImpl* download_manager_; 143 144 DISALLOW_COPY_AND_ASSIGN(TestFileErrorInjector); 145 }; 146 147 } // namespace content 148 149 #endif // CONTENT_PUBLIC_TEST_TEST_FILE_ERROR_INJECTOR_H_ 150