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 
     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