• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2013 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/connection_health_checker.h"
18 
19 #include <arpa/inet.h>
20 
21 #include <memory>
22 #include <string>
23 #include <vector>
24 
25 #include <base/bind.h>
26 #include <base/callback.h>
27 #include <base/cancelable_callback.h>
28 #include <base/memory/scoped_vector.h>
29 #include <gtest/gtest.h>
30 
31 #include "shill/mock_async_connection.h"
32 #include "shill/mock_connection.h"
33 #include "shill/mock_control.h"
34 #include "shill/mock_device_info.h"
35 #include "shill/mock_dns_client.h"
36 #include "shill/mock_dns_client_factory.h"
37 #include "shill/mock_ip_address_store.h"
38 #include "shill/mock_socket_info_reader.h"
39 #include "shill/net/mock_sockets.h"
40 #include "shill/test_event_dispatcher.h"
41 
42 using base::Bind;
43 using base::Callback;
44 using base::Closure;
45 using base::Unretained;
46 using std::string;
47 using std::vector;
48 using ::testing::AtLeast;
49 using ::testing::DoAll;
50 using ::testing::Gt;
51 using ::testing::Invoke;
52 using ::testing::Mock;
53 using ::testing::NiceMock;
54 using ::testing::Return;
55 using ::testing::ReturnRef;
56 using ::testing::SaveArg;
57 using ::testing::Sequence;
58 using ::testing::SetArgumentPointee;
59 using ::testing::StrictMock;
60 using ::testing::Test;
61 using ::testing::_;
62 
63 namespace shill {
64 
65 namespace {
66 const char kInterfaceName[] = "int0";
67 const char kIPAddress_8_8_8_8[] = "8.8.8.8";
68 const char kProxyIPAddressRemote[] = "74.125.224.84";
69 const char kProxyIPAddressLocal[] = "192.23.34.1";
70 const char kProxyIPv6AddressLocal[] = "::ffff:192.23.34.1";
71 const char kProxyURLRemote[] = "http://www.google.com";
72 const int kProxyFD = 100;
73 const int16_t kProxyPortLocal = 5540;
74 const int16_t kProxyPortRemote = 80;
75 }  // namespace
76 
77 MATCHER_P(IsSameIPAddress, ip_addr, "") {
78   return arg.Equals(ip_addr);
79 }
80 
81 class ConnectionHealthCheckerTest : public Test {
82  public:
ConnectionHealthCheckerTest()83   ConnectionHealthCheckerTest()
84       : interface_name_(kInterfaceName),
85         device_info_(&control_, &dispatcher_, nullptr, nullptr),
86         connection_(new NiceMock<MockConnection>(&device_info_)),
87         socket_(nullptr) {}
88 
89   // Invokes
GetSockName(int fd,struct sockaddr * addr_out,socklen_t * sockaddr_size)90   int GetSockName(int fd, struct sockaddr* addr_out, socklen_t* sockaddr_size) {
91     struct sockaddr_in addr;
92     EXPECT_EQ(kProxyFD, fd);
93     EXPECT_LE(sizeof(sockaddr_in), *sockaddr_size);
94     addr.sin_family = AF_INET;
95     inet_pton(AF_INET, kProxyIPAddressLocal, &addr.sin_addr);
96     addr.sin_port = htons(kProxyPortLocal);
97     memcpy(addr_out, &addr, sizeof(addr));
98     *sockaddr_size = sizeof(sockaddr_in);
99     return 0;
100   }
101 
GetSockNameReturnsIPv6(int fd,struct sockaddr * addr_out,socklen_t * sockaddr_size)102   int GetSockNameReturnsIPv6(int fd, struct sockaddr* addr_out,
103                              socklen_t* sockaddr_size) {
104     struct sockaddr_in6 addr;
105     EXPECT_EQ(kProxyFD, fd);
106     EXPECT_LE(sizeof(sockaddr_in6), *sockaddr_size);
107     addr.sin6_family = AF_INET6;
108     inet_pton(AF_INET6, kProxyIPv6AddressLocal, &addr.sin6_addr);
109     addr.sin6_port = htons(kProxyPortLocal);
110     memcpy(addr_out, &addr, sizeof(addr));
111     *sockaddr_size = sizeof(sockaddr_in6);
112     return 0;
113   }
114 
InvokeOnConnectionComplete(bool success,int sock_fd)115   void InvokeOnConnectionComplete(bool success, int sock_fd) {
116     health_checker_->OnConnectionComplete(success, sock_fd);
117   }
118 
InvokeGetDNSResultFailure()119   void InvokeGetDNSResultFailure() {
120     Error error(Error::kOperationFailed, "");
121     IPAddress address(IPAddress::kFamilyUnknown);
122     health_checker_->GetDNSResult(error, address);
123   }
124 
InvokeGetDNSResultSuccess(const IPAddress & address)125   void InvokeGetDNSResultSuccess(const IPAddress& address) {
126     Error error;
127     health_checker_->GetDNSResult(error, address);
128   }
129 
130  protected:
SetUp()131   void SetUp() {
132     EXPECT_CALL(*connection_.get(), interface_name())
133         .WillRepeatedly(ReturnRef(interface_name_));
134     ON_CALL(*connection_.get(), dns_servers())
135         .WillByDefault(ReturnRef(dns_servers_));
136     // ConnectionHealthChecker constructor should add some IPs
137     EXPECT_CALL(remote_ips_, AddUnique(_)).Times(AtLeast(1));
138     health_checker_.reset(
139         new ConnectionHealthChecker(
140              connection_,
141              &dispatcher_,
142              &remote_ips_,
143              Bind(&ConnectionHealthCheckerTest::ResultCallbackTarget,
144                   Unretained(this))));
145     Mock::VerifyAndClearExpectations(&remote_ips_);
146     socket_ = new StrictMock<MockSockets>();
147     tcp_connection_ = new StrictMock<MockAsyncConnection>();
148     socket_info_reader_ = new StrictMock<MockSocketInfoReader>();
149     // Passes ownership for all of these.
150     health_checker_->socket_.reset(socket_);
151     health_checker_->tcp_connection_.reset(tcp_connection_);
152     health_checker_->socket_info_reader_.reset(socket_info_reader_);
153     health_checker_->dns_client_factory_ = MockDNSClientFactory::GetInstance();
154   }
155 
TearDown()156   void TearDown() {
157     ExpectStop();
158   }
159 
160   // Accessors for private data in ConnectionHealthChecker.
socket()161   const Sockets* socket() {
162     return health_checker_->socket_.get();
163   }
tcp_connection()164   const AsyncConnection* tcp_connection() {
165     return health_checker_->tcp_connection_.get();
166   }
dns_clients()167   ScopedVector<DNSClient>& dns_clients() {
168     return health_checker_->dns_clients_;
169   }
NumDNSQueries()170   int NumDNSQueries() {
171     return ConnectionHealthChecker::kNumDNSQueries;
172   }
MaxFailedConnectionAttempts()173   int MaxFailedConnectionAttempts() {
174     return ConnectionHealthChecker::kMaxFailedConnectionAttempts;
175   }
MaxSentDataPollingAttempts()176   int MaxSentDataPollingAttempts() {
177     return ConnectionHealthChecker::kMaxSentDataPollingAttempts;
178   }
MinCongestedQueueAttempts()179   int MinCongestedQueueAttempts() {
180     return ConnectionHealthChecker::kMinCongestedQueueAttempts;
181   }
MinSuccessfulSendAttempts()182   int MinSuccessfulSendAttempts() {
183     return ConnectionHealthChecker::kMinSuccessfulSendAttempts;
184   }
SetTCPStateUpdateWaitMilliseconds(int new_wait)185   void SetTCPStateUpdateWaitMilliseconds(int new_wait) {
186     health_checker_->tcp_state_update_wait_milliseconds_ = new_wait;
187   }
188 
189   // Mock Callbacks
190   MOCK_METHOD1(ResultCallbackTarget,
191                void(ConnectionHealthChecker::Result result));
192 
193   // Helper methods
StringToIPv4Address(const string & address_string)194   IPAddress StringToIPv4Address(const string& address_string) {
195     IPAddress ip_address(IPAddress::kFamilyIPv4);
196     EXPECT_TRUE(ip_address.SetAddressFromString(address_string));
197     return ip_address;
198   }
199   // Naming: CreateSocketInfo
200   //         + (Proxy/Other) : TCP connection for proxy socket / some other
201   //         socket.
202   //         + arg1: Pass in any SocketInfo::ConnectionState you want.
203   //         + arg2: Pass in any value of transmit_queue_value you want.
CreateSocketInfoOther()204   SocketInfo CreateSocketInfoOther() {
205     return SocketInfo(
206         SocketInfo::kConnectionStateUnknown,
207         StringToIPv4Address(kIPAddress_8_8_8_8),
208         0,
209         StringToIPv4Address(kProxyIPAddressRemote),
210         kProxyPortRemote,
211         0,
212         0,
213         SocketInfo::kTimerStateUnknown);
214   }
CreateSocketInfoProxy(SocketInfo::ConnectionState state)215   SocketInfo CreateSocketInfoProxy(SocketInfo::ConnectionState state) {
216     return SocketInfo(
217         state,
218         StringToIPv4Address(kProxyIPAddressLocal),
219         kProxyPortLocal,
220         StringToIPv4Address(kProxyIPAddressRemote),
221         kProxyPortRemote,
222         0,
223         0,
224         SocketInfo::kTimerStateUnknown);
225   }
CreateSocketInfoProxy(SocketInfo::ConnectionState state,SocketInfo::TimerState timer_state,uint64_t transmit_queue_value)226   SocketInfo CreateSocketInfoProxy(SocketInfo::ConnectionState state,
227                                    SocketInfo::TimerState timer_state,
228                                    uint64_t transmit_queue_value) {
229     return SocketInfo(
230         state,
231         StringToIPv4Address(kProxyIPAddressLocal),
232         kProxyPortLocal,
233         StringToIPv4Address(kProxyIPAddressRemote),
234         kProxyPortRemote,
235         transmit_queue_value,
236         0,
237         timer_state);
238   }
239 
240 
241   // Expectations
ExpectReset()242   void ExpectReset() {
243     EXPECT_EQ(connection_.get(), health_checker_->connection_.get());
244     EXPECT_EQ(&dispatcher_, health_checker_->dispatcher_);
245     EXPECT_EQ(socket_, health_checker_->socket_.get());
246     EXPECT_FALSE(socket_ == nullptr);
247     EXPECT_EQ(socket_info_reader_, health_checker_->socket_info_reader_.get());
248     EXPECT_FALSE(socket_info_reader_ == nullptr);
249     EXPECT_FALSE(health_checker_->connection_complete_callback_.is_null());
250     EXPECT_EQ(tcp_connection_, health_checker_->tcp_connection_.get());
251     EXPECT_FALSE(tcp_connection_ == nullptr);
252     EXPECT_FALSE(health_checker_->health_check_in_progress_);
253   }
254 
255   // Setup ConnectionHealthChecker::GetSocketInfo to return sock_info.
256   // This only works if GetSocketInfo is called with kProxyFD.
257   // If no matching sock_info is provided (Does not belong to proxy socket),
258   // GetSocketInfo will (correctly) return false.
ExpectGetSocketInfoReturns(SocketInfo sock_info)259   void ExpectGetSocketInfoReturns(SocketInfo sock_info) {
260     vector<SocketInfo> info_list;
261     info_list.push_back(sock_info);
262     EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
263         .InSequence(seq_)
264         .WillOnce(Invoke(this,
265                          &ConnectionHealthCheckerTest::GetSockName));
266     EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
267         .InSequence(seq_)
268         .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
269                         Return(true)));
270   }
ExpectSuccessfulStart()271   void ExpectSuccessfulStart() {
272     EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(false));
273     EXPECT_CALL(remote_ips_, GetRandomIP())
274         .WillRepeatedly(Return(StringToIPv4Address(kProxyIPAddressRemote)));
275     EXPECT_CALL(
276         *tcp_connection_,
277         Start(IsSameIPAddress(StringToIPv4Address(kProxyIPAddressRemote)),
278               kProxyPortRemote))
279         .InSequence(seq_)
280         .WillOnce(Return(true));
281   }
ExpectRetry()282   void ExpectRetry() {
283     EXPECT_CALL(*socket_, Close(kProxyFD))
284         .InSequence(seq_);
285     EXPECT_CALL(
286         *tcp_connection_,
287         Start(IsSameIPAddress(StringToIPv4Address(kProxyIPAddressRemote)),
288               kProxyPortRemote))
289         .InSequence(seq_)
290         .WillOnce(Return(true));
291   }
ExpectStop()292   void ExpectStop() {
293     if (tcp_connection_)
294       EXPECT_CALL(*tcp_connection_, Stop())
295           .InSequence(seq_);
296   }
ExpectCleanUp()297   void ExpectCleanUp() {
298     EXPECT_CALL(*socket_, Close(kProxyFD))
299         .InSequence(seq_);
300     EXPECT_CALL(*tcp_connection_, Stop())
301         .InSequence(seq_);
302   }
303 
VerifyAndClearAllExpectations()304   void VerifyAndClearAllExpectations() {
305     Mock::VerifyAndClearExpectations(this);
306     Mock::VerifyAndClearExpectations(tcp_connection_);
307     Mock::VerifyAndClearExpectations(socket_);
308     Mock::VerifyAndClearExpectations(socket_info_reader_);
309   }
310 
311   // Needed for other mocks, but not for the tests directly.
312   const string interface_name_;
313   NiceMock<MockControl> control_;
314   NiceMock<MockDeviceInfo> device_info_;
315   vector<string> dns_servers_;
316 
317   scoped_refptr<NiceMock<MockConnection>> connection_;
318   EventDispatcherForTest dispatcher_;
319   MockIPAddressStore remote_ips_;
320   StrictMock<MockSockets>* socket_;
321   StrictMock<MockSocketInfoReader>* socket_info_reader_;
322   StrictMock<MockAsyncConnection>* tcp_connection_;
323   // Expectations in the Expect* functions are put in this sequence.
324   // This allows us to chain calls to Expect* functions.
325   Sequence seq_;
326 
327   std::unique_ptr<ConnectionHealthChecker> health_checker_;
328 };
329 
TEST_F(ConnectionHealthCheckerTest,Constructor)330 TEST_F(ConnectionHealthCheckerTest, Constructor) {
331   ExpectReset();
332 }
333 
TEST_F(ConnectionHealthCheckerTest,SetConnection)334 TEST_F(ConnectionHealthCheckerTest, SetConnection) {
335   scoped_refptr<NiceMock<MockConnection>> new_connection =
336       new NiceMock<MockConnection>(&device_info_);
337   // If a health check was in progress when SetConnection is called, verify
338   // that it restarts with the new connection.
339   ExpectSuccessfulStart();
340   health_checker_->Start();
341   VerifyAndClearAllExpectations();
342 
343   EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(true));
344   EXPECT_CALL(*new_connection.get(), interface_name())
345       .WillRepeatedly(ReturnRef(interface_name_));
346   EXPECT_CALL(*this,
347               ResultCallbackTarget(ConnectionHealthChecker::kResultUnknown));
348   health_checker_->SetConnection(new_connection);
349   EXPECT_NE(tcp_connection_, health_checker_->tcp_connection());
350   EXPECT_EQ(new_connection.get(), health_checker_->connection());
351 
352   // health_checker_ has reset tcp_connection_ to a new object.
353   // Since it owned tcp_connection_, the object has been destroyed.
354   tcp_connection_ = nullptr;
355 }
356 
TEST_F(ConnectionHealthCheckerTest,GarbageCollectDNSClients)357 TEST_F(ConnectionHealthCheckerTest, GarbageCollectDNSClients) {
358   dns_clients().clear();
359   health_checker_->GarbageCollectDNSClients();
360   EXPECT_TRUE(dns_clients().empty());
361 
362   for (int i = 0; i < 3; ++i) {
363     MockDNSClient* dns_client = new MockDNSClient();
364     EXPECT_CALL(*dns_client, IsActive())
365         .WillOnce(Return(true))
366         .WillOnce(Return(true))
367         .WillOnce(Return(false));
368     // Takes ownership.
369     dns_clients().push_back(dns_client);
370   }
371   for (int i = 0; i < 2; ++i) {
372     MockDNSClient* dns_client = new MockDNSClient();
373     EXPECT_CALL(*dns_client, IsActive())
374         .WillOnce(Return(false));
375     // Takes ownership.
376     dns_clients().push_back(dns_client);
377   }
378 
379   EXPECT_EQ(5, dns_clients().size());
380   health_checker_->GarbageCollectDNSClients();
381   EXPECT_EQ(3, dns_clients().size());
382   health_checker_->GarbageCollectDNSClients();
383   EXPECT_EQ(3, dns_clients().size());
384   health_checker_->GarbageCollectDNSClients();
385   EXPECT_TRUE(dns_clients().empty());
386 }
387 
TEST_F(ConnectionHealthCheckerTest,AddRemoteURL)388 TEST_F(ConnectionHealthCheckerTest, AddRemoteURL) {
389   HTTPURL url;
390   url.ParseFromString(kProxyURLRemote);
391   string host = url.host();
392   IPAddress remote_ip = StringToIPv4Address(kProxyIPAddressRemote);
393   IPAddress remote_ip_2 = StringToIPv4Address(kIPAddress_8_8_8_8);
394 
395   MockDNSClientFactory* dns_client_factory
396       = MockDNSClientFactory::GetInstance();
397   vector<MockDNSClient*> dns_client_buffer;
398 
399   // All DNS queries fail.
400   for (int i = 0; i < NumDNSQueries(); ++i) {
401     MockDNSClient* dns_client = new MockDNSClient();
402     EXPECT_CALL(*dns_client, Start(host, _))
403         .WillOnce(Return(false));
404     dns_client_buffer.push_back(dns_client);
405   }
406   // Will pass ownership of dns_clients elements.
407   for (int i = 0; i < NumDNSQueries(); ++i) {
408     EXPECT_CALL(*dns_client_factory, CreateDNSClient(_, _, _, _, _, _))
409         .InSequence(seq_)
410         .WillOnce(Return(dns_client_buffer[i]));
411   }
412   EXPECT_CALL(remote_ips_, AddUnique(_)).Times(0);
413   health_checker_->AddRemoteURL(kProxyURLRemote);
414   Mock::VerifyAndClearExpectations(dns_client_factory);
415   Mock::VerifyAndClearExpectations(&remote_ips_);
416   dns_client_buffer.clear();
417   dns_clients().clear();
418 
419   // All but one DNS queries fail, 1 succeeds.
420   for (int i = 0; i < NumDNSQueries(); ++i) {
421     MockDNSClient* dns_client = new MockDNSClient();
422     EXPECT_CALL(*dns_client, Start(host, _))
423         .WillOnce(Return(true));
424     dns_client_buffer.push_back(dns_client);
425   }
426   // Will pass ownership of dns_clients elements.
427   for (int i = 0; i < NumDNSQueries(); ++i) {
428     EXPECT_CALL(*dns_client_factory, CreateDNSClient(_, _, _, _, _, _))
429         .InSequence(seq_)
430         .WillOnce(Return(dns_client_buffer[i]));
431   }
432   EXPECT_CALL(remote_ips_, AddUnique(_));
433   health_checker_->AddRemoteURL(kProxyURLRemote);
434   for (int i = 0; i < NumDNSQueries() - 1; ++i) {
435     InvokeGetDNSResultFailure();
436   }
437   InvokeGetDNSResultSuccess(remote_ip);
438   Mock::VerifyAndClearExpectations(dns_client_factory);
439   Mock::VerifyAndClearExpectations(&remote_ips_);
440   dns_client_buffer.clear();
441   dns_clients().clear();
442 
443   // Only 2 distinct IP addresses are returned.
444   for (int i = 0; i < NumDNSQueries(); ++i) {
445     MockDNSClient* dns_client = new MockDNSClient();
446     EXPECT_CALL(*dns_client, Start(host, _))
447         .WillOnce(Return(true));
448     dns_client_buffer.push_back(dns_client);
449   }
450   // Will pass ownership of dns_clients elements.
451   for (int i = 0; i < NumDNSQueries(); ++i) {
452     EXPECT_CALL(*dns_client_factory, CreateDNSClient(_, _, _, _, _, _))
453         .InSequence(seq_)
454         .WillOnce(Return(dns_client_buffer[i]));
455   }
456   EXPECT_CALL(remote_ips_, AddUnique(IsSameIPAddress(remote_ip))).Times(4);
457   EXPECT_CALL(remote_ips_, AddUnique(IsSameIPAddress(remote_ip_2)));
458   health_checker_->AddRemoteURL(kProxyURLRemote);
459   for (int i = 0; i < NumDNSQueries() - 1; ++i) {
460     InvokeGetDNSResultSuccess(remote_ip);
461   }
462   InvokeGetDNSResultSuccess(remote_ip_2);
463   Mock::VerifyAndClearExpectations(dns_client_factory);
464   Mock::VerifyAndClearExpectations(&remote_ips_);
465   dns_client_buffer.clear();
466   dns_clients().clear();
467 }
468 
TEST_F(ConnectionHealthCheckerTest,GetSocketInfo)469 TEST_F(ConnectionHealthCheckerTest, GetSocketInfo) {
470   SocketInfo sock_info;
471   vector<SocketInfo> info_list;
472 
473   // GetSockName fails.
474   EXPECT_CALL(*socket_, GetSockName(_, _, _))
475       .WillOnce(Return(-1));
476   EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
477   Mock::VerifyAndClearExpectations(socket_);
478 
479   // GetSockName returns IPv6.
480   EXPECT_CALL(*socket_, GetSockName(_, _, _))
481       .WillOnce(
482           Invoke(this,
483                  &ConnectionHealthCheckerTest::GetSockNameReturnsIPv6));
484   EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
485   Mock::VerifyAndClearExpectations(socket_);
486 
487   // LoadTcpSocketInfo fails.
488   EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
489       .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
490   EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
491     .WillOnce(Return(false));
492   EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
493   Mock::VerifyAndClearExpectations(socket_);
494   Mock::VerifyAndClearExpectations(socket_info_reader_);
495 
496   // LoadTcpSocketInfo returns empty list.
497   info_list.clear();
498   EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
499       .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
500   EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
501       .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
502                       Return(true)));
503   EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
504   Mock::VerifyAndClearExpectations(socket_);
505   Mock::VerifyAndClearExpectations(socket_info_reader_);
506 
507   // LoadTcpSocketInfo returns a list without our socket.
508   info_list.clear();
509   info_list.push_back(CreateSocketInfoOther());
510   EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
511       .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
512   EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
513       .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
514                       Return(true)));
515   EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
516   Mock::VerifyAndClearExpectations(socket_);
517   Mock::VerifyAndClearExpectations(socket_info_reader_);
518 
519   // LoadTcpSocketInfo returns a list with only our socket.
520   info_list.clear();
521   info_list.push_back(
522       CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
523   EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
524       .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
525   EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
526       .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
527                       Return(true)));
528   EXPECT_TRUE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
529   EXPECT_TRUE(CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown)
530                   .IsSameSocketAs(sock_info));
531   Mock::VerifyAndClearExpectations(socket_);
532   Mock::VerifyAndClearExpectations(socket_info_reader_);
533 
534   // LoadTcpSocketInfo returns a list with two sockets, including ours.
535   info_list.clear();
536   info_list.push_back(CreateSocketInfoOther());
537   info_list.push_back(
538       CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
539   EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
540       .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
541   EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
542       .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
543                       Return(true)));
544   EXPECT_TRUE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
545   EXPECT_TRUE(CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown)
546                   .IsSameSocketAs(sock_info));
547   Mock::VerifyAndClearExpectations(socket_);
548   Mock::VerifyAndClearExpectations(socket_info_reader_);
549 
550   info_list.clear();
551   info_list.push_back(
552       CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
553   info_list.push_back(CreateSocketInfoOther());
554   EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
555       .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
556   EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
557       .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
558                       Return(true)));
559   EXPECT_TRUE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
560   EXPECT_TRUE(CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown)
561                   .IsSameSocketAs(sock_info));
562   Mock::VerifyAndClearExpectations(socket_);
563   Mock::VerifyAndClearExpectations(socket_info_reader_);
564 }
565 
TEST_F(ConnectionHealthCheckerTest,NextHealthCheckSample)566 TEST_F(ConnectionHealthCheckerTest, NextHealthCheckSample) {
567   IPAddress ip = StringToIPv4Address(kProxyIPAddressRemote);
568   ON_CALL(remote_ips_, GetRandomIP())
569       .WillByDefault(Return(ip));
570 
571   health_checker_->set_num_connection_failures(MaxFailedConnectionAttempts());
572   ExpectStop();
573   EXPECT_CALL(
574       *this,
575       ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
576   health_checker_->NextHealthCheckSample();
577   dispatcher_.DispatchPendingEvents();
578   VerifyAndClearAllExpectations();
579 
580   health_checker_->set_num_congested_queue_detected(
581       MinCongestedQueueAttempts());
582   ExpectStop();
583   EXPECT_CALL(
584       *this,
585       ResultCallbackTarget(ConnectionHealthChecker::kResultCongestedTxQueue));
586   health_checker_->NextHealthCheckSample();
587   dispatcher_.DispatchPendingEvents();
588   VerifyAndClearAllExpectations();
589 
590   health_checker_->set_num_successful_sends(MinSuccessfulSendAttempts());
591   ExpectStop();
592   EXPECT_CALL(
593       *this,
594       ResultCallbackTarget(ConnectionHealthChecker::kResultSuccess));
595   health_checker_->NextHealthCheckSample();
596   dispatcher_.DispatchPendingEvents();
597   VerifyAndClearAllExpectations();
598 
599   EXPECT_CALL(*tcp_connection_, Start(_, _)).WillOnce(Return(true));
600   health_checker_->NextHealthCheckSample();
601   VerifyAndClearAllExpectations();
602 
603   // This test assumes that there are at least 2 connection attempts left
604   // before ConnectionHealthChecker gives up.
605   EXPECT_CALL(*tcp_connection_, Start(_, _))
606     .WillOnce(Return(false))
607     .WillOnce(Return(true));
608   int16_t num_connection_failures = health_checker_->num_connection_failures();
609   health_checker_->NextHealthCheckSample();
610   EXPECT_EQ(num_connection_failures + 1,
611             health_checker_->num_connection_failures());
612 }
613 
TEST_F(ConnectionHealthCheckerTest,OnConnectionComplete)614 TEST_F(ConnectionHealthCheckerTest, OnConnectionComplete) {
615   // Test that num_connection_attempts is incremented on failure when
616   // (1) Async Connection fails.
617   health_checker_->set_num_connection_failures(
618       MaxFailedConnectionAttempts() - 1);
619   ExpectStop();
620   EXPECT_CALL(
621       *this,
622       ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
623   health_checker_->OnConnectionComplete(false, -1);
624   dispatcher_.DispatchPendingEvents();
625   VerifyAndClearAllExpectations();
626 
627   // (2) The connection state is garbled up.
628   health_checker_->set_num_connection_failures(
629       MaxFailedConnectionAttempts() - 1);
630   ExpectGetSocketInfoReturns(
631       CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
632   EXPECT_CALL(*socket_, Close(kProxyFD));
633   ExpectStop();
634   EXPECT_CALL(
635       *this,
636       ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
637   health_checker_->OnConnectionComplete(true, kProxyFD);
638   dispatcher_.DispatchPendingEvents();
639   VerifyAndClearAllExpectations();
640 
641   // (3) Send fails.
642   health_checker_->set_num_connection_failures(
643       MaxFailedConnectionAttempts() - 1);
644   ExpectGetSocketInfoReturns(
645       CreateSocketInfoProxy(SocketInfo::kConnectionStateEstablished));
646   EXPECT_CALL(*socket_, Send(kProxyFD, _, Gt(0), _)).WillOnce(Return(-1));
647   EXPECT_CALL(*socket_, Close(kProxyFD));
648   ExpectStop();
649   EXPECT_CALL(
650       *this,
651       ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
652   health_checker_->OnConnectionComplete(true, kProxyFD);
653   dispatcher_.DispatchPendingEvents();
654 }
655 
TEST_F(ConnectionHealthCheckerTest,VerifySentData)656 TEST_F(ConnectionHealthCheckerTest, VerifySentData) {
657   // (1) Test that num_connection_attempts is incremented when the connection
658   // state is garbled up.
659   health_checker_->set_num_connection_failures(
660       MaxFailedConnectionAttempts() - 1);
661   ExpectGetSocketInfoReturns(
662       CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
663   EXPECT_CALL(*socket_, Close(kProxyFD));
664   ExpectStop();
665   EXPECT_CALL(
666       *this,
667       ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
668   health_checker_->set_sock_fd(kProxyFD);
669   health_checker_->VerifySentData();
670   dispatcher_.DispatchPendingEvents();
671   VerifyAndClearAllExpectations();
672 
673   // (2) Test that num_congested_queue_detected is incremented when all polling
674   // attempts have expired.
675   health_checker_->set_num_congested_queue_detected(
676       MinCongestedQueueAttempts() - 1);
677   health_checker_->set_num_tx_queue_polling_attempts(
678       MaxSentDataPollingAttempts());
679   health_checker_->set_old_transmit_queue_value(0);
680   ExpectGetSocketInfoReturns(
681       CreateSocketInfoProxy(SocketInfo::kConnectionStateEstablished,
682                             SocketInfo::kTimerStateRetransmitTimerPending,
683                             1));
684   EXPECT_CALL(*socket_, Close(kProxyFD));
685   ExpectStop();
686   EXPECT_CALL(
687       *this,
688       ResultCallbackTarget(ConnectionHealthChecker::kResultCongestedTxQueue));
689   health_checker_->set_sock_fd(kProxyFD);
690   health_checker_->VerifySentData();
691   dispatcher_.DispatchPendingEvents();
692   VerifyAndClearAllExpectations();
693 
694   // (3) Test that num_successful_sends is incremented if everything goes fine.
695   health_checker_->set_num_successful_sends(MinSuccessfulSendAttempts() - 1);
696   health_checker_->set_old_transmit_queue_value(0);
697   ExpectGetSocketInfoReturns(
698       CreateSocketInfoProxy(SocketInfo::kConnectionStateEstablished,
699                             SocketInfo::kTimerStateNoTimerPending,
700                             0));
701   EXPECT_CALL(*socket_, Close(kProxyFD));
702   ExpectStop();
703   EXPECT_CALL(
704       *this,
705       ResultCallbackTarget(ConnectionHealthChecker::kResultSuccess));
706   health_checker_->set_sock_fd(kProxyFD);
707   health_checker_->VerifySentData();
708   dispatcher_.DispatchPendingEvents();
709   VerifyAndClearAllExpectations();
710 
711   // (4) Test that VerifySentData correctly polls the tcpinfo twice.
712   // We want to immediately dispatch posted tasks.
713   SetTCPStateUpdateWaitMilliseconds(0);
714   health_checker_->set_num_congested_queue_detected(
715       MinCongestedQueueAttempts() - 1);
716   health_checker_->set_num_tx_queue_polling_attempts(
717       MaxSentDataPollingAttempts() - 1);
718   health_checker_->set_old_transmit_queue_value(0);
719   ExpectGetSocketInfoReturns(
720       CreateSocketInfoProxy(SocketInfo::kConnectionStateEstablished,
721                             SocketInfo::kTimerStateRetransmitTimerPending,
722                             1));
723   ExpectGetSocketInfoReturns(
724       CreateSocketInfoProxy(SocketInfo::kConnectionStateEstablished,
725                             SocketInfo::kTimerStateRetransmitTimerPending,
726                             1));
727   EXPECT_CALL(*socket_, Close(kProxyFD));
728   ExpectStop();
729   EXPECT_CALL(
730       *this, ResultCallbackTarget(
731           ConnectionHealthChecker::kResultCongestedTxQueue))
732       .InSequence(seq_);
733   health_checker_->set_sock_fd(kProxyFD);
734   health_checker_->VerifySentData();
735   dispatcher_.DispatchPendingEvents();
736   dispatcher_.DispatchPendingEvents();
737   // Force an extra dispatch to make sure that VerifySentData did not poll an
738   // extra time. This dispatch should be a no-op.
739   dispatcher_.DispatchPendingEvents();
740   VerifyAndClearAllExpectations();
741 }
742 
743 // Flow: Start() -> Start()
744 // Expectation: Only one AsyncConnection is setup
TEST_F(ConnectionHealthCheckerTest,StartStartSkipsSecond)745 TEST_F(ConnectionHealthCheckerTest, StartStartSkipsSecond) {
746   EXPECT_CALL(*tcp_connection_, Start(_, _))
747       .WillOnce(Return(true));
748   EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(false));
749   EXPECT_CALL(remote_ips_, GetRandomIP())
750       .WillOnce(Return(StringToIPv4Address(kProxyIPAddressRemote)));
751   health_checker_->Start();
752   health_checker_->Start();
753 }
754 
755 // Precondition: size(|remote_ips_|) > 0
756 // Flow: Start() -> Stop() before ConnectionComplete()
757 // Expectation: No call to |result_callback|
TEST_F(ConnectionHealthCheckerTest,StartStopNoCallback)758 TEST_F(ConnectionHealthCheckerTest, StartStopNoCallback) {
759   EXPECT_CALL(*tcp_connection_, Start(_, _))
760       .WillOnce(Return(true));
761   EXPECT_CALL(*tcp_connection_, Stop());
762   EXPECT_CALL(*this, ResultCallbackTarget(_))
763       .Times(0);
764   EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(false));
765   EXPECT_CALL(remote_ips_, GetRandomIP())
766       .WillOnce(Return(StringToIPv4Address(kProxyIPAddressRemote)));
767   health_checker_->Start();
768   health_checker_->Stop();
769 }
770 
771 // Precondition: Empty remote_ips_
772 // Flow: Start()
773 // Expectation: call |result_callback| with kResultUnknown
TEST_F(ConnectionHealthCheckerTest,StartImmediateFailure)774 TEST_F(ConnectionHealthCheckerTest, StartImmediateFailure) {
775   EXPECT_CALL(remote_ips_, Empty()).WillOnce(Return(true));
776   EXPECT_CALL(*tcp_connection_, Stop());
777   EXPECT_CALL(*this, ResultCallbackTarget(
778                            ConnectionHealthChecker::kResultUnknown));
779   health_checker_->Start();
780   Mock::VerifyAndClearExpectations(this);
781   Mock::VerifyAndClearExpectations(&remote_ips_);
782   Mock::VerifyAndClearExpectations(tcp_connection_);
783 
784   EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(false));
785   EXPECT_CALL(remote_ips_, GetRandomIP())
786       .WillRepeatedly(Return(StringToIPv4Address(kProxyIPAddressRemote)));
787   EXPECT_CALL(*tcp_connection_,
788               Start(IsSameIPAddress(StringToIPv4Address(kProxyIPAddressRemote)),
789                     kProxyPortRemote))
790       .Times(MaxFailedConnectionAttempts())
791       .WillRepeatedly(Return(false));
792   EXPECT_CALL(*tcp_connection_, Stop());
793   EXPECT_CALL(*this, ResultCallbackTarget(
794                            ConnectionHealthChecker::kResultConnectionFailure));
795   health_checker_->Start();
796   dispatcher_.DispatchPendingEvents();
797   Mock::VerifyAndClearExpectations(this);
798   Mock::VerifyAndClearExpectations(tcp_connection_);
799 }
800 
801 }  // namespace shill
802