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