• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "shill/http_request.h"
18 
19 #include <netinet/in.h>
20 
21 #include <memory>
22 #include <string>
23 #include <vector>
24 
25 #include <base/bind.h>
26 #include <base/strings/stringprintf.h>
27 #include <gtest/gtest.h>
28 
29 #include "shill/http_url.h"
30 #include "shill/mock_async_connection.h"
31 #include "shill/mock_connection.h"
32 #include "shill/mock_control.h"
33 #include "shill/mock_device_info.h"
34 #include "shill/mock_dns_client.h"
35 #include "shill/mock_event_dispatcher.h"
36 #include "shill/net/ip_address.h"
37 #include "shill/net/mock_sockets.h"
38 
39 using base::Bind;
40 using base::Callback;
41 using base::StringPrintf;
42 using base::Unretained;
43 using std::string;
44 using std::vector;
45 using ::testing::_;
46 using ::testing::AtLeast;
47 using ::testing::DoAll;
48 using ::testing::Invoke;
49 using ::testing::NiceMock;
50 using ::testing::Return;
51 using ::testing::ReturnArg;
52 using ::testing::ReturnNew;
53 using ::testing::ReturnRef;
54 using ::testing::SetArgumentPointee;
55 using ::testing::StrEq;
56 using ::testing::StrictMock;
57 using ::testing::Test;
58 
59 namespace shill {
60 
61 namespace {
62 const char kTextSiteName[] = "www.chromium.org";
63 const char kTextURL[] = "http://www.chromium.org/path/to/resource";
64 const char kNumericURL[] = "http://10.1.1.1";
65 const char kPath[] = "/path/to/resource";
66 const char kInterfaceName[] = "int0";
67 const char kDNSServer0[] = "8.8.8.8";
68 const char kDNSServer1[] = "8.8.4.4";
69 const char* kDNSServers[] = { kDNSServer0, kDNSServer1 };
70 const char kServerAddress[] = "10.1.1.1";
71 const int kServerFD = 10203;
72 const int kServerPort = 80;
73 }  // namespace
74 
75 MATCHER_P(IsIPAddress, address, "") {
76   IPAddress ip_address(IPAddress::kFamilyIPv4);
77   EXPECT_TRUE(ip_address.SetAddressFromString(address));
78   return ip_address.Equals(arg);
79 }
80 
81 MATCHER_P(ByteStringMatches, byte_string, "") {
82   return byte_string.Equals(arg);
83 }
84 
85 MATCHER_P(CallbackEq, callback, "") {
86   return arg.Equals(callback);
87 }
88 
89 class HTTPRequestTest : public Test {
90  public:
HTTPRequestTest()91   HTTPRequestTest()
92       : interface_name_(kInterfaceName),
93         server_async_connection_(new StrictMock<MockAsyncConnection>()),
94         dns_servers_(kDNSServers, kDNSServers + 2),
95         dns_client_(new StrictMock<MockDNSClient>()),
96         device_info_(
97             new NiceMock<MockDeviceInfo>(&control_, nullptr, nullptr, nullptr)),
98         connection_(new StrictMock<MockConnection>(device_info_.get())) {}
99 
100  protected:
101   class CallbackTarget {
102    public:
CallbackTarget()103     CallbackTarget()
104         : read_event_callback_(
105               Bind(&CallbackTarget::ReadEventCallTarget, Unretained(this))),
106           result_callback_(
107               Bind(&CallbackTarget::ResultCallTarget, Unretained(this))) {}
108 
109     MOCK_METHOD1(ReadEventCallTarget, void(const ByteString& response_data));
110     MOCK_METHOD2(ResultCallTarget, void(HTTPRequest::Result result,
111                                         const ByteString& response_data));
read_event_callback()112     const Callback<void(const ByteString&)>& read_event_callback() {
113       return read_event_callback_;
114     }
115     const Callback<void(HTTPRequest::Result,
result_callback()116                         const ByteString&)>& result_callback() {
117       return result_callback_;
118     }
119 
120    private:
121     Callback<void(const ByteString&)> read_event_callback_;
122     Callback<void(HTTPRequest::Result, const ByteString&)> result_callback_;
123   };
124 
SetUp()125   virtual void SetUp() {
126     EXPECT_CALL(*connection_.get(), IsIPv6())
127         .WillRepeatedly(Return(false));
128     EXPECT_CALL(*connection_.get(), interface_name())
129         .WillRepeatedly(ReturnRef(interface_name_));
130     EXPECT_CALL(*connection_.get(), dns_servers())
131         .WillRepeatedly(ReturnRef(dns_servers_));
132 
133     request_.reset(new HTTPRequest(connection_, &dispatcher_, &sockets_));
134     // Passes ownership.
135     request_->dns_client_.reset(dns_client_);
136     // Passes ownership.
137     request_->server_async_connection_.reset(server_async_connection_);
138   }
TearDown()139   virtual void TearDown() {
140     if (request_->is_running_) {
141       ExpectStop();
142 
143       // Subtle: Make sure the finalization of the request happens while our
144       // expectations are still active.
145       request_.reset();
146     }
147   }
FindInRequestData(const string & find_string)148   size_t FindInRequestData(const string& find_string) {
149     string request_string(
150         reinterpret_cast<char*>(request_->request_data_.GetData()),
151         request_->request_data_.GetLength());
152     return request_string.find(find_string);
153   }
154   // Accessors
GetRequestData()155   const ByteString& GetRequestData() {
156     return request_->request_data_;
157   }
request()158   HTTPRequest* request() { return request_.get(); }
sockets()159   MockSockets& sockets() { return sockets_; }
160 
161   // Expectations
ExpectReset()162   void ExpectReset() {
163     EXPECT_EQ(connection_.get(), request_->connection_.get());
164     EXPECT_EQ(&dispatcher_, request_->dispatcher_);
165     EXPECT_EQ(&sockets_, request_->sockets_);
166     EXPECT_TRUE(request_->result_callback_.is_null());
167     EXPECT_TRUE(request_->read_event_callback_.is_null());
168     EXPECT_FALSE(request_->connect_completion_callback_.is_null());
169     EXPECT_FALSE(request_->dns_client_callback_.is_null());
170     EXPECT_FALSE(request_->read_server_callback_.is_null());
171     EXPECT_FALSE(request_->write_server_callback_.is_null());
172     EXPECT_FALSE(request_->read_server_handler_.get());
173     EXPECT_FALSE(request_->write_server_handler_.get());
174     EXPECT_EQ(dns_client_, request_->dns_client_.get());
175     EXPECT_EQ(server_async_connection_,
176               request_->server_async_connection_.get());
177     EXPECT_TRUE(request_->server_hostname_.empty());
178     EXPECT_EQ(-1, request_->server_port_);
179     EXPECT_EQ(-1, request_->server_socket_);
180     EXPECT_EQ(HTTPRequest::kResultUnknown, request_->timeout_result_);
181     EXPECT_TRUE(request_->request_data_.IsEmpty());
182     EXPECT_TRUE(request_->response_data_.IsEmpty());
183     EXPECT_FALSE(request_->is_running_);
184   }
ExpectStop()185   void ExpectStop() {
186     if (request_->server_socket_ != -1) {
187       EXPECT_CALL(sockets(), Close(kServerFD))
188           .WillOnce(Return(0));
189     }
190     EXPECT_CALL(*dns_client_, Stop())
191         .Times(AtLeast(1));
192     EXPECT_CALL(*server_async_connection_, Stop())
193         .Times(AtLeast(1));
194     EXPECT_CALL(*connection_.get(), ReleaseRouting());
195   }
ExpectSetTimeout(int timeout)196   void ExpectSetTimeout(int timeout) {
197     EXPECT_CALL(dispatcher_, PostDelayedTask(_, timeout * 1000));
198   }
ExpectSetConnectTimeout()199   void ExpectSetConnectTimeout() {
200     ExpectSetTimeout(HTTPRequest::kConnectTimeoutSeconds);
201   }
ExpectSetInputTimeout()202   void ExpectSetInputTimeout() {
203     ExpectSetTimeout(HTTPRequest::kInputTimeoutSeconds);
204   }
ExpectInResponse(const string & expected_response_data)205   void ExpectInResponse(const string& expected_response_data) {
206     string response_string(
207         reinterpret_cast<char*>(request_->response_data_.GetData()),
208         request_->response_data_.GetLength());
209     EXPECT_NE(string::npos, response_string.find(expected_response_data));
210   }
ExpectDNSRequest(const string & host,bool return_value)211   void ExpectDNSRequest(const string& host, bool return_value) {
212     EXPECT_CALL(*dns_client_, Start(StrEq(host), _))
213         .WillOnce(Return(return_value));
214   }
ExpectAsyncConnect(const string & address,int port,bool return_value)215   void ExpectAsyncConnect(const string& address, int port,
216                           bool return_value) {
217     EXPECT_CALL(*server_async_connection_, Start(IsIPAddress(address), port))
218         .WillOnce(Return(return_value));
219     if (return_value) {
220       ExpectSetConnectTimeout();
221     }
222   }
InvokeSyncConnect(const IPAddress &,int)223   void  InvokeSyncConnect(const IPAddress& /*address*/, int /*port*/) {
224     CallConnectCompletion(true, kServerFD);
225   }
CallConnectCompletion(bool success,int fd)226   void CallConnectCompletion(bool success, int fd) {
227     request_->OnConnectCompletion(success, fd);
228   }
ExpectSyncConnect(const string & address,int port)229   void ExpectSyncConnect(const string& address, int port) {
230     EXPECT_CALL(*server_async_connection_, Start(IsIPAddress(address), port))
231         .WillOnce(DoAll(Invoke(this, &HTTPRequestTest::InvokeSyncConnect),
232                         Return(true)));
233   }
ExpectConnectFailure()234   void ExpectConnectFailure() {
235     EXPECT_CALL(*server_async_connection_, Start(_, _))
236         .WillOnce(Return(false));
237   }
ExpectMonitorServerInput()238   void ExpectMonitorServerInput() {
239     EXPECT_CALL(dispatcher_,
240                 CreateInputHandler(kServerFD,
241                                    CallbackEq(request_->read_server_callback_),
242                                    _))
243         .WillOnce(ReturnNew<IOHandler>());
244     ExpectSetInputTimeout();
245   }
ExpectMonitorServerOutput()246   void ExpectMonitorServerOutput() {
247     EXPECT_CALL(dispatcher_,
248                 CreateReadyHandler(
249                     kServerFD, IOHandler::kModeOutput,
250                     CallbackEq(request_->write_server_callback_)))
251         .WillOnce(ReturnNew<IOHandler>());
252     ExpectSetInputTimeout();
253   }
ExpectRouteRequest()254   void ExpectRouteRequest() {
255     EXPECT_CALL(*connection_.get(), RequestRouting());
256   }
ExpectRouteRelease()257   void ExpectRouteRelease() {
258     EXPECT_CALL(*connection_.get(), ReleaseRouting());
259   }
ExpectResultCallback(HTTPRequest::Result result)260   void ExpectResultCallback(HTTPRequest::Result result) {
261     EXPECT_CALL(target_, ResultCallTarget(result, _));
262   }
InvokeResultVerify(HTTPRequest::Result result,const ByteString & response_data)263   void InvokeResultVerify(HTTPRequest::Result result,
264                           const ByteString& response_data) {
265     EXPECT_EQ(HTTPRequest::kResultSuccess, result);
266     EXPECT_TRUE(expected_response_.Equals(response_data));
267   }
ExpectResultCallbackWithResponse(const string & response)268   void ExpectResultCallbackWithResponse(const string& response) {
269     expected_response_ = ByteString(response, false);
270     EXPECT_CALL(target_, ResultCallTarget(HTTPRequest::kResultSuccess, _))
271         .WillOnce(Invoke(this, &HTTPRequestTest::InvokeResultVerify));
272   }
ExpectReadEventCallback(const string & response)273   void ExpectReadEventCallback(const string& response) {
274     ByteString response_data(response, false);
275     EXPECT_CALL(target_, ReadEventCallTarget(ByteStringMatches(response_data)));
276   }
GetDNSResultFailure(const string & error_msg)277   void GetDNSResultFailure(const string& error_msg) {
278     Error error(Error::kOperationFailed, error_msg);
279     IPAddress address(IPAddress::kFamilyUnknown);
280     request_->GetDNSResult(error, address);
281   }
GetDNSResultSuccess(const IPAddress & address)282   void GetDNSResultSuccess(const IPAddress& address) {
283     Error error;
284     request_->GetDNSResult(error, address);
285   }
OnConnectCompletion(bool result,int sockfd)286   void OnConnectCompletion(bool result, int sockfd) {
287     request_->OnConnectCompletion(result, sockfd);
288   }
ReadFromServer(const string & data)289   void ReadFromServer(const string& data) {
290     const unsigned char* ptr =
291         reinterpret_cast<const unsigned char*>(data.c_str());
292     vector<unsigned char> data_writable(ptr, ptr + data.length());
293     InputData server_data(data_writable.data(), data_writable.size());
294     request_->ReadFromServer(&server_data);
295   }
WriteToServer(int fd)296   void WriteToServer(int fd) {
297     request_->WriteToServer(fd);
298   }
StartRequest(const string & url)299   HTTPRequest::Result StartRequest(const string& url) {
300     HTTPURL http_url;
301     EXPECT_TRUE(http_url.ParseFromString(url));
302     return request_->Start(http_url,
303                            target_.read_event_callback(),
304                            target_.result_callback());
305   }
SetupConnectWithURL(const string & url,const string & expected_hostname)306   void SetupConnectWithURL(const string& url, const string& expected_hostname) {
307     ExpectRouteRequest();
308     ExpectDNSRequest(expected_hostname, true);
309     EXPECT_EQ(HTTPRequest::kResultInProgress, StartRequest(url));
310     IPAddress addr(IPAddress::kFamilyIPv4);
311     EXPECT_TRUE(addr.SetAddressFromString(kServerAddress));
312     GetDNSResultSuccess(addr);
313   }
SetupConnect()314   void SetupConnect() {
315     SetupConnectWithURL(kTextURL, kTextSiteName);
316   }
SetupConnectAsync()317   void SetupConnectAsync() {
318     ExpectAsyncConnect(kServerAddress, kServerPort, true);
319     SetupConnect();
320   }
SetupConnectComplete()321   void SetupConnectComplete() {
322     SetupConnectAsync();
323     ExpectMonitorServerOutput();
324     OnConnectCompletion(true, kServerFD);
325   }
CallTimeoutTask()326   void CallTimeoutTask() {
327     request_->TimeoutTask();
328   }
CallServerErrorCallback()329   void CallServerErrorCallback() {
330     request_->OnServerReadError(string());
331   }
332 
333  private:
334   const string interface_name_;
335   // Owned by the HTTPRequest, but tracked here for EXPECT().
336   StrictMock<MockAsyncConnection>* server_async_connection_;
337   vector<string> dns_servers_;
338   // Owned by the HTTPRequest, but tracked here for EXPECT().
339   StrictMock<MockDNSClient>* dns_client_;
340   StrictMock<MockEventDispatcher> dispatcher_;
341   MockControl control_;
342   std::unique_ptr<MockDeviceInfo> device_info_;
343   scoped_refptr<MockConnection> connection_;
344   std::unique_ptr<HTTPRequest> request_;
345   StrictMock<MockSockets> sockets_;
346   StrictMock<CallbackTarget> target_;
347   ByteString expected_response_;
348 };
349 
TEST_F(HTTPRequestTest,Constructor)350 TEST_F(HTTPRequestTest, Constructor) {
351   ExpectReset();
352 }
353 
354 
TEST_F(HTTPRequestTest,FailConnectNumericSynchronous)355 TEST_F(HTTPRequestTest, FailConnectNumericSynchronous) {
356   ExpectRouteRequest();
357   ExpectConnectFailure();
358   ExpectStop();
359   EXPECT_EQ(HTTPRequest::kResultConnectionFailure, StartRequest(kNumericURL));
360   ExpectReset();
361 }
362 
TEST_F(HTTPRequestTest,FailConnectNumericAsynchronous)363 TEST_F(HTTPRequestTest, FailConnectNumericAsynchronous) {
364   ExpectRouteRequest();
365   ExpectAsyncConnect(kServerAddress, HTTPURL::kDefaultHTTPPort, true);
366   EXPECT_EQ(HTTPRequest::kResultInProgress, StartRequest(kNumericURL));
367   ExpectResultCallback(HTTPRequest::kResultConnectionFailure);
368   ExpectStop();
369   CallConnectCompletion(false, -1);
370   ExpectReset();
371 }
372 
TEST_F(HTTPRequestTest,FailConnectNumericTimeout)373 TEST_F(HTTPRequestTest, FailConnectNumericTimeout) {
374   ExpectRouteRequest();
375   ExpectAsyncConnect(kServerAddress, HTTPURL::kDefaultHTTPPort, true);
376   EXPECT_EQ(HTTPRequest::kResultInProgress, StartRequest(kNumericURL));
377   ExpectResultCallback(HTTPRequest::kResultConnectionTimeout);
378   ExpectStop();
379   CallTimeoutTask();
380   ExpectReset();
381 }
382 
TEST_F(HTTPRequestTest,SyncConnectNumeric)383 TEST_F(HTTPRequestTest, SyncConnectNumeric) {
384   ExpectRouteRequest();
385   ExpectSyncConnect(kServerAddress, HTTPURL::kDefaultHTTPPort);
386   ExpectMonitorServerOutput();
387   EXPECT_EQ(HTTPRequest::kResultInProgress, StartRequest(kNumericURL));
388 }
389 
TEST_F(HTTPRequestTest,FailDNSStart)390 TEST_F(HTTPRequestTest, FailDNSStart) {
391   ExpectRouteRequest();
392   ExpectDNSRequest(kTextSiteName, false);
393   ExpectStop();
394   EXPECT_EQ(HTTPRequest::kResultDNSFailure, StartRequest(kTextURL));
395   ExpectReset();
396 }
397 
TEST_F(HTTPRequestTest,FailDNSFailure)398 TEST_F(HTTPRequestTest, FailDNSFailure) {
399   ExpectRouteRequest();
400   ExpectDNSRequest(kTextSiteName, true);
401   EXPECT_EQ(HTTPRequest::kResultInProgress, StartRequest(kTextURL));
402   ExpectResultCallback(HTTPRequest::kResultDNSFailure);
403   ExpectStop();
404   GetDNSResultFailure(DNSClient::kErrorNoData);
405   ExpectReset();
406 }
407 
TEST_F(HTTPRequestTest,FailDNSTimeout)408 TEST_F(HTTPRequestTest, FailDNSTimeout) {
409   ExpectRouteRequest();
410   ExpectDNSRequest(kTextSiteName, true);
411   EXPECT_EQ(HTTPRequest::kResultInProgress, StartRequest(kTextURL));
412   ExpectResultCallback(HTTPRequest::kResultDNSTimeout);
413   ExpectStop();
414   const string error(DNSClient::kErrorTimedOut);
415   GetDNSResultFailure(error);
416   ExpectReset();
417 }
418 
TEST_F(HTTPRequestTest,FailConnectText)419 TEST_F(HTTPRequestTest, FailConnectText) {
420   ExpectConnectFailure();
421   ExpectResultCallback(HTTPRequest::kResultConnectionFailure);
422   ExpectStop();
423   SetupConnect();
424   ExpectReset();
425 }
426 
TEST_F(HTTPRequestTest,ConnectComplete)427 TEST_F(HTTPRequestTest, ConnectComplete) {
428   SetupConnectComplete();
429 }
430 
TEST_F(HTTPRequestTest,RequestTimeout)431 TEST_F(HTTPRequestTest, RequestTimeout) {
432   SetupConnectComplete();
433   ExpectResultCallback(HTTPRequest::kResultRequestTimeout);
434   ExpectStop();
435   CallTimeoutTask();
436 }
437 
TEST_F(HTTPRequestTest,RequestData)438 TEST_F(HTTPRequestTest, RequestData) {
439   SetupConnectComplete();
440   EXPECT_EQ(0, FindInRequestData(string("GET ") + kPath));
441   EXPECT_NE(string::npos,
442             FindInRequestData(string("\r\nHost: ") + kTextSiteName));
443   ByteString request_data = GetRequestData();
444   EXPECT_CALL(sockets(), Send(kServerFD, _, request_data.GetLength(), 0))
445       .WillOnce(Return(request_data.GetLength() - 1));
446   ExpectSetInputTimeout();
447   WriteToServer(kServerFD);
448   EXPECT_CALL(sockets(), Send(kServerFD, _, 1, 0))
449       .WillOnce(Return(1));
450   ExpectMonitorServerInput();
451   WriteToServer(kServerFD);
452 }
453 
TEST_F(HTTPRequestTest,ResponseTimeout)454 TEST_F(HTTPRequestTest, ResponseTimeout) {
455   SetupConnectComplete();
456   ByteString request_data = GetRequestData();
457   EXPECT_CALL(sockets(), Send(kServerFD, _, request_data.GetLength(), 0))
458       .WillOnce(Return(request_data.GetLength()));
459   ExpectMonitorServerInput();
460   WriteToServer(kServerFD);
461   ExpectResultCallback(HTTPRequest::kResultResponseTimeout);
462   ExpectStop();
463   CallTimeoutTask();
464 }
465 
TEST_F(HTTPRequestTest,ResponseInputError)466 TEST_F(HTTPRequestTest, ResponseInputError) {
467   SetupConnectComplete();
468   ByteString request_data = GetRequestData();
469   EXPECT_CALL(sockets(), Send(kServerFD, _, request_data.GetLength(), 0))
470       .WillOnce(Return(request_data.GetLength()));
471   ExpectMonitorServerInput();
472   WriteToServer(kServerFD);
473   ExpectResultCallback(HTTPRequest::kResultResponseFailure);
474   ExpectStop();
475   CallServerErrorCallback();
476 }
477 
TEST_F(HTTPRequestTest,ResponseData)478 TEST_F(HTTPRequestTest, ResponseData) {
479   SetupConnectComplete();
480   const string response0("hello");
481   ExpectReadEventCallback(response0);
482   ExpectSetInputTimeout();
483   ReadFromServer(response0);
484   ExpectInResponse(response0);
485 
486   const string response1(" to you");
487   ExpectReadEventCallback(response0 + response1);
488   ExpectSetInputTimeout();
489   ReadFromServer(response1);
490   ExpectInResponse(response1);
491 
492   ExpectResultCallbackWithResponse(response0 + response1);
493   ExpectStop();
494   ReadFromServer("");
495   ExpectReset();
496 }
497 
498 }  // namespace shill
499