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