// 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 NET_TEST_URL_REQUEST_URL_REQUEST_FAILED_JOB_H_
#define NET_TEST_URL_REQUEST_URL_REQUEST_FAILED_JOB_H_

#include <string>

#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
#include "net/url_request/url_request_job.h"
#include "url/gurl.h"

namespace net {

// This class simulates a URLRequestJob failing with a given error code at
// a particular phase while trying to connect.
class URLRequestFailedJob : public URLRequestJob {
 public:
  // A Java counterpart will be generated for this enum.
  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.net.test
  enum FailurePhase {
    START = 0,
    READ_SYNC = 1,
    READ_ASYNC = 2,
    MAX_FAILURE_PHASE = 3,
  };

  URLRequestFailedJob(URLRequest* request,
                      NetworkDelegate* network_delegate,
                      FailurePhase phase,
                      int net_error);

  // Same as above, except that the job fails at FailurePhase.START.
  URLRequestFailedJob(URLRequest* request,
                      NetworkDelegate* network_delegate,
                      int net_error);

  // URLRequestJob implementation:
  void Start() override;
  bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override;
  int GetResponseCode() const override;
  void GetResponseInfo(HttpResponseInfo* info) override;

  // Adds the testing URLs to the URLRequestFilter.
  static void AddUrlHandler();
  static void AddUrlHandlerForHostname(const std::string& hostname);

  // Given a net error code, constructs a mock URL that will return that error
  // asynchronously when started. |net_error| must be a valid net error code
  // other than net::OK. Passing net::ERR_IO_PENDING for |net_error| causes the
  // resulting request to hang.
  static GURL GetMockHttpUrl(int net_error);
  static GURL GetMockHttpsUrl(int net_error);

  // Constructs a mock URL that reports |net_error| at given |phase| of the
  // request. |net_error| must be a valid net error code other than net::OK.
  // Passing net::ERR_IO_PENDING for |net_error| causes the resulting request to
  // hang.
  static GURL GetMockHttpUrlWithFailurePhase(FailurePhase phase, int net_error);

  // Given a net error code and a host name, constructs a mock URL that will
  // return that error asynchronously when started. |net_error| must be a valid
  // net error code other than net::OK. Passing net::ERR_IO_PENDING for
  // |net_error| causes the resulting request to hang.
  static GURL GetMockHttpUrlForHostname(int net_error,
                                        const std::string& hostname);
  static GURL GetMockHttpsUrlForHostname(int net_error,
                                         const std::string& hostname);

 protected:
  ~URLRequestFailedJob() override;

 private:
  HttpResponseInfo response_info_;
  const FailurePhase phase_;
  const int net_error_;

  base::WeakPtrFactory<URLRequestFailedJob> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(URLRequestFailedJob);
};

}  // namespace net

#endif  // NET_TEST_URL_REQUEST_URL_REQUEST_FAILED_JOB_H_
