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 NET_URL_REQUEST_URL_REQUEST_TEST_JOB_H_
6#define NET_URL_REQUEST_URL_REQUEST_TEST_JOB_H_
7
8#include <string>
9
10#include "base/memory/weak_ptr.h"
11#include "net/base/load_timing_info.h"
12#include "net/url_request/url_request.h"
13#include "net/url_request/url_request_job.h"
14
15namespace net {
16
17// This job type is designed to help with simple unit tests. To use, you
18// probably want to inherit from it to set up the state you want. Then install
19// it as the protocol handler for the "test" scheme.
20//
21// It will respond to several URLs, which you can retrieve using the test_url*
22// getters, which will in turn respond with the corresponding responses returned
23// by test_data*. Any other URLs that begin with "test:" will return an error,
24// which might also be useful, you can use test_url_error() to retreive a
25// standard one.
26//
27// You can override the known URLs or the response data by overriding Start().
28//
29// Optionally, you can also construct test jobs to return a headers and data
30// provided to the contstructor in response to any request url.
31//
32// When a job is created, it gets put on a queue of pending test jobs. To
33// process jobs on this queue, use ProcessOnePendingMessage, which will process
34// one step of the next job. If the job is incomplete, it will be added to the
35// end of the queue.
36//
37// Optionally, you can also construct test jobs that advance automatically
38// without having to call ProcessOnePendingMessage.
39class NET_EXPORT_PRIVATE URLRequestTestJob : public URLRequestJob {
40 public:
41  // Constructs a job to return one of the canned responses depending on the
42  // request url, with auto advance disabled.
43  URLRequestTestJob(URLRequest* request, NetworkDelegate* network_delegate);
44
45  // Constructs a job to return one of the canned responses depending on the
46  // request url, optionally with auto advance enabled.
47  URLRequestTestJob(URLRequest* request,
48                    NetworkDelegate* network_delegate,
49                    bool auto_advance);
50
51  // Constructs a job to return the given response regardless of the request
52  // url. The headers should include the HTTP status line and be formatted as
53  // expected by HttpResponseHeaders.
54  URLRequestTestJob(URLRequest* request,
55                    net::NetworkDelegate* network_delegate,
56                    const std::string& response_headers,
57                    const std::string& response_data,
58                    bool auto_advance);
59
60  // The canned URLs this handler will respond to without having been
61  // explicitly initialized with response headers and data.
62  // FIXME(brettw): we should probably also have a redirect one
63  static GURL test_url_1();
64  static GURL test_url_2();
65  static GURL test_url_3();
66  static GURL test_url_4();
67  static GURL test_url_error();
68  static GURL test_url_redirect_to_url_2();
69
70  // The data that corresponds to each of the URLs above
71  static std::string test_data_1();
72  static std::string test_data_2();
73  static std::string test_data_3();
74  static std::string test_data_4();
75
76  // The headers that correspond to each of the URLs above
77  static std::string test_headers();
78
79  // The headers for a redirect response
80  static std::string test_redirect_headers();
81
82  // The headers for a redirect response to the second test url.
83  static std::string test_redirect_to_url_2_headers();
84
85  // The headers for a server error response
86  static std::string test_error_headers();
87
88  // Processes one pending message from the stack, returning true if any
89  // message was processed, or false if there are no more pending request
90  // notifications to send. This is not applicable when using auto_advance.
91  static bool ProcessOnePendingMessage();
92
93  // With auto advance enabled, the job will advance thru the stages without
94  // the caller having to call ProcessOnePendingMessage. Auto advance depends
95  // on having a message loop running. The default is to not auto advance.
96  // Should not be altered after the job has started.
97  bool auto_advance() { return auto_advance_; }
98  void set_auto_advance(bool auto_advance) { auto_advance_ = auto_advance; }
99
100  void set_load_timing_info(const LoadTimingInfo& load_timing_info) {
101    load_timing_info_ = load_timing_info;
102  }
103
104  RequestPriority priority() const { return priority_; }
105
106  // Factory method for protocol factory registration if callers don't subclass
107  static URLRequest::ProtocolFactory Factory;
108
109  // Job functions
110  virtual void SetPriority(RequestPriority priority) OVERRIDE;
111  virtual void Start() OVERRIDE;
112  virtual bool ReadRawData(IOBuffer* buf,
113                           int buf_size,
114                           int *bytes_read) OVERRIDE;
115  virtual void Kill() OVERRIDE;
116  virtual bool GetMimeType(std::string* mime_type) const OVERRIDE;
117  virtual void GetResponseInfo(HttpResponseInfo* info) OVERRIDE;
118  virtual void GetLoadTimingInfo(
119      LoadTimingInfo* load_timing_info) const OVERRIDE;
120  virtual int GetResponseCode() const OVERRIDE;
121  virtual bool IsRedirectResponse(GURL* location,
122                                  int* http_status_code) OVERRIDE;
123
124 protected:
125  // Override to specify whether the next read done from this job will
126  // return IO pending.  This controls whether or not the WAITING state will
127  // transition back to WAITING or to DATA_AVAILABLE after an asynchronous
128  // read is processed.
129  virtual bool NextReadAsync();
130
131  // This is what operation we are going to do next when this job is handled.
132  // When the stage is DONE, this job will not be put on the queue.
133  enum Stage { WAITING, DATA_AVAILABLE, ALL_DATA, DONE };
134
135  virtual ~URLRequestTestJob();
136
137  // Call to process the next opeation, usually sending a notification, and
138  // advancing the stage if necessary. THIS MAY DELETE THE OBJECT.
139  void ProcessNextOperation();
140
141  // Call to move the job along to the next operation.
142  void AdvanceJob();
143
144  // Called via InvokeLater to cause callbacks to occur after Start() returns.
145  virtual void StartAsync();
146
147  bool auto_advance_;
148
149  Stage stage_;
150
151  RequestPriority priority_;
152
153  // The headers the job should return, will be set in Start() if not provided
154  // in the explicit ctor.
155  scoped_refptr<HttpResponseHeaders> response_headers_;
156
157  // The data to send, will be set in Start() if not provided in the explicit
158  // ctor.
159  std::string response_data_;
160
161  // current offset within response_data_
162  int offset_;
163
164  // Holds the buffer for an asynchronous ReadRawData call
165  IOBuffer* async_buf_;
166  int async_buf_size_;
167
168  LoadTimingInfo load_timing_info_;
169
170  base::WeakPtrFactory<URLRequestTestJob> weak_factory_;
171};
172
173}  // namespace net
174
175#endif  // NET_URL_REQUEST_URL_REQUEST_TEST_JOB_H_
176