blob: 306c7e29b807c9f223d81bc11830b65dc239fd56 [file] [log] [blame]
// 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_