• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2006-2009 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_HTTP_HTTP_TRANSACTION_UNITTEST_H_
6 #define NET_HTTP_HTTP_TRANSACTION_UNITTEST_H_
7 
8 #include "net/http/http_transaction.h"
9 
10 #include <algorithm>
11 #include <string>
12 
13 #include "base/compiler_specific.h"
14 #include "base/message_loop.h"
15 #include "base/string_util.h"
16 #include "net/base/io_buffer.h"
17 #include "net/base/net_errors.h"
18 #include "net/base/load_flags.h"
19 #include "net/base/test_completion_callback.h"
20 #include "net/disk_cache/disk_cache.h"
21 #include "net/http/http_cache.h"
22 #include "net/http/http_request_info.h"
23 #include "net/http/http_response_headers.h"
24 #include "net/http/http_response_info.h"
25 
26 //-----------------------------------------------------------------------------
27 // mock transaction data
28 
29 // these flags may be combined to form the test_mode field
30 enum {
31   TEST_MODE_NORMAL = 0,
32   TEST_MODE_SYNC_NET_START = 1 << 0,
33   TEST_MODE_SYNC_NET_READ  = 1 << 1,
34   TEST_MODE_SYNC_CACHE_START = 1 << 2,
35   TEST_MODE_SYNC_CACHE_READ  = 1 << 3,
36   TEST_MODE_SYNC_CACHE_WRITE  = 1 << 4,
37   TEST_MODE_SYNC_ALL = TEST_MODE_SYNC_NET_START | TEST_MODE_SYNC_NET_READ |
38                        TEST_MODE_SYNC_CACHE_START | TEST_MODE_SYNC_CACHE_READ |
39                        TEST_MODE_SYNC_CACHE_WRITE
40 };
41 
42 typedef void (*MockTransactionHandler)(const net::HttpRequestInfo* request,
43                                        std::string* response_status,
44                                        std::string* response_headers,
45                                        std::string* response_data);
46 
47 struct MockTransaction {
48   const char* url;
49   const char* method;
50   // If |request_time| is unspecified, the current time will be used.
51   base::Time request_time;
52   const char* request_headers;
53   int load_flags;
54   const char* status;
55   const char* response_headers;
56   // If |response_time| is unspecified, the current time will be used.
57   base::Time response_time;
58   const char* data;
59   int test_mode;
60   MockTransactionHandler handler;
61   int cert_status;
62 };
63 
64 extern const MockTransaction kSimpleGET_Transaction;
65 extern const MockTransaction kSimplePOST_Transaction;
66 extern const MockTransaction kTypicalGET_Transaction;
67 extern const MockTransaction kETagGET_Transaction;
68 extern const MockTransaction kRangeGET_Transaction;
69 
70 // returns the mock transaction for the given URL
71 const MockTransaction* FindMockTransaction(const GURL& url);
72 
73 // Add/Remove a mock transaction that can be accessed via FindMockTransaction.
74 // There can be only one MockTransaction associated with a given URL.
75 void AddMockTransaction(const MockTransaction* trans);
76 void RemoveMockTransaction(const MockTransaction* trans);
77 
78 struct ScopedMockTransaction : MockTransaction {
ScopedMockTransactionScopedMockTransaction79   ScopedMockTransaction() {
80     AddMockTransaction(this);
81   }
ScopedMockTransactionScopedMockTransaction82   explicit ScopedMockTransaction(const MockTransaction& t)
83       : MockTransaction(t) {
84     AddMockTransaction(this);
85   }
~ScopedMockTransactionScopedMockTransaction86   ~ScopedMockTransaction() {
87     RemoveMockTransaction(this);
88   }
89 };
90 
91 //-----------------------------------------------------------------------------
92 // mock http request
93 
94 class MockHttpRequest : public net::HttpRequestInfo {
95  public:
MockHttpRequest(const MockTransaction & t)96   explicit MockHttpRequest(const MockTransaction& t) {
97     url = GURL(t.url);
98     method = t.method;
99     extra_headers = t.request_headers;
100     load_flags = t.load_flags;
101   }
102 };
103 
104 //-----------------------------------------------------------------------------
105 // use this class to test completely consuming a transaction
106 
107 class TestTransactionConsumer : public CallbackRunner< Tuple1<int> > {
108  public:
TestTransactionConsumer(net::HttpTransactionFactory * factory)109   explicit TestTransactionConsumer(net::HttpTransactionFactory* factory)
110       : state_(IDLE),
111         trans_(NULL),
112         error_(net::OK) {
113     // Disregard the error code.
114     factory->CreateTransaction(&trans_);
115     ++quit_counter_;
116   }
117 
~TestTransactionConsumer()118   ~TestTransactionConsumer() {
119   }
120 
Start(const net::HttpRequestInfo * request,net::LoadLog * load_log)121   void Start(const net::HttpRequestInfo* request, net::LoadLog* load_log) {
122     state_ = STARTING;
123     int result = trans_->Start(request, this, load_log);
124     if (result != net::ERR_IO_PENDING)
125       DidStart(result);
126   }
127 
is_done()128   bool is_done() const { return state_ == DONE; }
error()129   int error() const { return error_; }
130 
response_info()131   const net::HttpResponseInfo* response_info() const {
132     return trans_->GetResponseInfo();
133   }
content()134   const std::string& content() const { return content_; }
135 
136  private:
137   // Callback implementation:
RunWithParams(const Tuple1<int> & params)138   virtual void RunWithParams(const Tuple1<int>& params) {
139     int result = params.a;
140     switch (state_) {
141       case STARTING:
142         DidStart(result);
143         break;
144       case READING:
145         DidRead(result);
146         break;
147       default:
148         NOTREACHED();
149     }
150   }
151 
DidStart(int result)152   void DidStart(int result) {
153     if (result != net::OK) {
154       DidFinish(result);
155     } else {
156       Read();
157     }
158   }
159 
DidRead(int result)160   void DidRead(int result) {
161     if (result <= 0) {
162       DidFinish(result);
163     } else {
164       content_.append(read_buf_->data(), result);
165       Read();
166     }
167   }
168 
DidFinish(int result)169   void DidFinish(int result) {
170     state_ = DONE;
171     error_ = result;
172     if (--quit_counter_ == 0)
173       MessageLoop::current()->Quit();
174   }
175 
Read()176   void Read() {
177     state_ = READING;
178     read_buf_ = new net::IOBuffer(1024);
179     int result = trans_->Read(read_buf_, 1024, this);
180     if (result != net::ERR_IO_PENDING)
181       DidRead(result);
182   }
183 
184   enum State {
185     IDLE,
186     STARTING,
187     READING,
188     DONE
189   } state_;
190 
191   scoped_ptr<net::HttpTransaction> trans_;
192   std::string content_;
193   scoped_refptr<net::IOBuffer> read_buf_;
194   int error_;
195 
196   static int quit_counter_;
197 };
198 
199 //-----------------------------------------------------------------------------
200 // mock network layer
201 
202 // This transaction class inspects the available set of mock transactions to
203 // find data for the request URL.  It supports IO operations that complete
204 // synchronously or asynchronously to help exercise different code paths in the
205 // HttpCache implementation.
206 class MockNetworkTransaction : public net::HttpTransaction {
207  public:
MockNetworkTransaction()208   MockNetworkTransaction() :
209       ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), data_cursor_(0) {
210   }
211 
Start(const net::HttpRequestInfo * request,net::CompletionCallback * callback,net::LoadLog * load_log)212   virtual int Start(const net::HttpRequestInfo* request,
213                     net::CompletionCallback* callback,
214                     net::LoadLog* load_log) {
215     const MockTransaction* t = FindMockTransaction(request->url);
216     if (!t)
217       return net::ERR_FAILED;
218 
219     std::string resp_status = t->status;
220     std::string resp_headers = t->response_headers;
221     std::string resp_data = t->data;
222     if (t->handler)
223       (t->handler)(request, &resp_status, &resp_headers, &resp_data);
224 
225     std::string header_data =
226         StringPrintf("%s\n%s\n", resp_status.c_str(), resp_headers.c_str());
227     std::replace(header_data.begin(), header_data.end(), '\n', '\0');
228 
229     response_.request_time = base::Time::Now();
230     if (!t->request_time.is_null())
231       response_.request_time = t->request_time;
232 
233     response_.was_cached = false;
234 
235     response_.response_time = base::Time::Now();
236     if (!t->response_time.is_null())
237       response_.response_time = t->response_time;
238 
239     response_.headers = new net::HttpResponseHeaders(header_data);
240     response_.ssl_info.cert_status = t->cert_status;
241     data_ = resp_data;
242     test_mode_ = t->test_mode;
243 
244     if (test_mode_ & TEST_MODE_SYNC_NET_START)
245       return net::OK;
246 
247     CallbackLater(callback, net::OK);
248     return net::ERR_IO_PENDING;
249   }
250 
RestartIgnoringLastError(net::CompletionCallback * callback)251   virtual int RestartIgnoringLastError(net::CompletionCallback* callback) {
252     return net::ERR_FAILED;
253   }
254 
RestartWithCertificate(net::X509Certificate * client_cert,net::CompletionCallback * callback)255   virtual int RestartWithCertificate(net::X509Certificate* client_cert,
256                                      net::CompletionCallback* callback) {
257     return net::ERR_FAILED;
258   }
259 
RestartWithAuth(const std::wstring & username,const std::wstring & password,net::CompletionCallback * callback)260   virtual int RestartWithAuth(const std::wstring& username,
261                               const std::wstring& password,
262                               net::CompletionCallback* callback) {
263     return net::ERR_FAILED;
264   }
265 
IsReadyToRestartForAuth()266   virtual bool IsReadyToRestartForAuth() {
267     return false;
268   }
269 
Read(net::IOBuffer * buf,int buf_len,net::CompletionCallback * callback)270   virtual int Read(net::IOBuffer* buf, int buf_len,
271                    net::CompletionCallback* callback) {
272     int data_len = static_cast<int>(data_.size());
273     int num = std::min(buf_len, data_len - data_cursor_);
274     if (num) {
275       memcpy(buf->data(), data_.data() + data_cursor_, num);
276       data_cursor_ += num;
277     }
278     if (test_mode_ & TEST_MODE_SYNC_NET_READ)
279       return num;
280 
281     CallbackLater(callback, num);
282     return net::ERR_IO_PENDING;
283   }
284 
GetResponseInfo()285   virtual const net::HttpResponseInfo* GetResponseInfo() const {
286     return &response_;
287   }
288 
GetLoadState()289   virtual net::LoadState GetLoadState() const {
290     NOTREACHED() << "define some mock state transitions";
291     return net::LOAD_STATE_IDLE;
292   }
293 
GetUploadProgress()294   virtual uint64 GetUploadProgress() const {
295     return 0;
296   }
297 
298  private:
CallbackLater(net::CompletionCallback * callback,int result)299   void CallbackLater(net::CompletionCallback* callback, int result) {
300     MessageLoop::current()->PostTask(FROM_HERE, task_factory_.NewRunnableMethod(
301         &MockNetworkTransaction::RunCallback, callback, result));
302   }
RunCallback(net::CompletionCallback * callback,int result)303   void RunCallback(net::CompletionCallback* callback, int result) {
304     callback->Run(result);
305   }
306 
307   ScopedRunnableMethodFactory<MockNetworkTransaction> task_factory_;
308   net::HttpResponseInfo response_;
309   std::string data_;
310   int data_cursor_;
311   int test_mode_;
312 };
313 
314 class MockNetworkLayer : public net::HttpTransactionFactory {
315  public:
MockNetworkLayer()316   MockNetworkLayer() : transaction_count_(0) {
317   }
318 
CreateTransaction(scoped_ptr<net::HttpTransaction> * trans)319   virtual int CreateTransaction(scoped_ptr<net::HttpTransaction>* trans) {
320     transaction_count_++;
321     trans->reset(new MockNetworkTransaction());
322     return net::OK;
323   }
324 
GetCache()325   virtual net::HttpCache* GetCache() {
326     return NULL;
327   }
328 
GetSession()329   virtual net::HttpNetworkSession* GetSession() {
330     return NULL;
331   }
332 
Suspend(bool suspend)333   virtual void Suspend(bool suspend) {}
334 
transaction_count()335   int transaction_count() const { return transaction_count_; }
336 
337  private:
338   int transaction_count_;
339 };
340 
341 
342 //-----------------------------------------------------------------------------
343 // helpers
344 
345 // read the transaction completely
346 int ReadTransaction(net::HttpTransaction* trans, std::string* result);
347 
348 #endif  // NET_HTTP_HTTP_TRANSACTION_UNITTEST_H_
349