root/content/public/test/test_file_error_injector.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


// Copyright (c) 2012 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.

#ifndef CONTENT_PUBLIC_TEST_TEST_FILE_ERROR_INJECTOR_H_
#define CONTENT_PUBLIC_TEST_TEST_FILE_ERROR_INJECTOR_H_

#include <map>
#include <set>
#include <string>

#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/ref_counted.h"
#include "content/public/browser/download_interrupt_reasons.h"
#include "url/gurl.h"

namespace content {

class DownloadId;
class DownloadFileWithErrorsFactory;
class DownloadManager;
class DownloadManagerImpl;

// Test helper for injecting errors into download file operations.
// All errors for a download must be injected before it starts.
// This class needs to be |RefCountedThreadSafe| because the implementation
// is referenced by other classes that live past the time when the user is
// nominally done with it.  These classes are internal to content/.
//
// NOTE: No more than one download with the same URL can be in progress at
// the same time.  You can have multiple simultaneous downloads as long as the
// URLs are different, as the URLs are used as keys to get information about
// the download.
//
// Example:
//
// FileErrorInfo a = { url1, ... };
// FileErrorInfo b = { url2, ... };
//
// scoped_refptr<TestFileErrorInjector> injector =
//     TestFileErrorInjector::Create(download_manager);
//
// injector->AddError(a);
// injector->AddError(b);
// injector->InjectErrors();
//
// download_manager->DownloadUrl(url1, ...);
// download_manager->DownloadUrl(url2, ...);
// ... wait for downloads to finish or get an injected error ...
class TestFileErrorInjector
    : public base::RefCountedThreadSafe<TestFileErrorInjector> {
 public:
  enum FileOperationCode {
    FILE_OPERATION_INITIALIZE,
    FILE_OPERATION_WRITE,
    FILE_OPERATION_RENAME_UNIQUIFY,
    FILE_OPERATION_RENAME_ANNOTATE,
  };

  // Structure that encapsulates the information needed to inject a file error.
  struct FileErrorInfo {
    std::string url;  // Full URL of the download.  Identifies the download.
    FileOperationCode code;  // Operation to affect.
    int operation_instance;  // 0-based count of operation calls, for each code.
    DownloadInterruptReason error;  // Error to inject.
  };

  typedef std::map<std::string, FileErrorInfo> ErrorMap;

  // Creates an instance.  May only be called once.
  // Lives until all callbacks (in the implementation) are complete and the
  // creator goes out of scope.
  // TODO(rdsmith): Allow multiple calls for different download managers.
  static scoped_refptr<TestFileErrorInjector> Create(
      DownloadManager* download_manager);

  // Adds an error.
  // Must be called before |InjectErrors()| for a particular download file.
  // It is an error to call |AddError()| more than once for the same file
  // (URL), unless you call |ClearErrors()| in between them.
  bool AddError(const FileErrorInfo& error_info);

  // Clears all errors.
  // Only affects files created after the next call to InjectErrors().
  void ClearErrors();

  // Injects the errors such that new download files will be affected.
  // The download system must already be initialized before calling this.
  // Multiple calls are allowed, but only useful if the errors have changed.
  // Replaces the injected error list.
  bool InjectErrors();

  // Tells how many files are currently open.
  size_t CurrentFileCount() const;

  // Tells how many files have ever been open (since construction or the
  // last call to |ClearFoundFiles()|).
  size_t TotalFileCount() const;

  // Returns whether or not a file matching |url| has been created.
  bool HadFile(const GURL& url) const;

  // Resets the found file list.
  void ClearFoundFiles();

  static std::string DebugString(FileOperationCode code);

 private:
  friend class base::RefCountedThreadSafe<TestFileErrorInjector>;

  typedef std::set<GURL> FileSet;

  explicit TestFileErrorInjector(DownloadManager* download_manager);

  virtual ~TestFileErrorInjector();

  // Callbacks from the download file, to record lifetimes.
  // These may be called on any thread.
  void RecordDownloadFileConstruction(const GURL& url);
  void RecordDownloadFileDestruction(const GURL& url);

  // These run on the UI thread.
  void DownloadFileCreated(GURL url);
  void DestroyingDownloadFile(GURL url);

  // All the data is used on the UI thread.
  // Our injected error list, mapped by URL.  One per file.
  ErrorMap injected_errors_;

  // Keep track of active DownloadFiles.
  FileSet files_;

  // Keep track of found DownloadFiles.
  FileSet found_files_;

  // The factory we created.  May outlive this class.
  DownloadFileWithErrorsFactory* created_factory_;

  // The download manager we set the factory on.
  DownloadManagerImpl* download_manager_;

  DISALLOW_COPY_AND_ASSIGN(TestFileErrorInjector);
};

}  // namespace content

#endif  // CONTENT_PUBLIC_TEST_TEST_FILE_ERROR_INJECTOR_H_

/* [<][>][^][v][top][bottom][index][help] */