blob: 12f33b5ce8e02c507b0a4734c8260d753ff5cc43 [file] [log] [blame]
Prathmesh Prabhu40daa012013-04-03 10:35:03 -07001// Copyright (c) 2013 The Chromium OS 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#include "shill/connection_health_checker.h"
6
7#include <arpa/inet.h>
8#include <string>
9#include <vector>
10
11#include <base/bind.h>
12#include <base/callback.h>
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -070013#include <base/cancelable_callback.h>
Prathmesh Prabhu40daa012013-04-03 10:35:03 -070014#include <base/memory/scoped_ptr.h>
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -070015#include <base/memory/scoped_vector.h>
Prathmesh Prabhu40daa012013-04-03 10:35:03 -070016#include <gtest/gtest.h>
17
18#include "shill/mock_async_connection.h"
19#include "shill/mock_connection.h"
20#include "shill/mock_control.h"
21#include "shill/mock_dns_client.h"
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -070022#include "shill/mock_dns_client_factory.h"
Prathmesh Prabhu40daa012013-04-03 10:35:03 -070023#include "shill/mock_device_info.h"
24#include "shill/mock_event_dispatcher.h"
Prathmesh Prabhuba99b592013-04-17 15:13:14 -070025#include "shill/mock_ip_address_store.h"
Prathmesh Prabhu40daa012013-04-03 10:35:03 -070026#include "shill/mock_sockets.h"
27#include "shill/mock_socket_info_reader.h"
28
29using base::Bind;
30using base::Callback;
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -070031using base::Closure;
Prathmesh Prabhu40daa012013-04-03 10:35:03 -070032using base::Unretained;
33using std::string;
34using std::vector;
Prathmesh Prabhuba99b592013-04-17 15:13:14 -070035using ::testing::AtLeast;
Prathmesh Prabhu40daa012013-04-03 10:35:03 -070036using ::testing::DoAll;
37using ::testing::Gt;
38using ::testing::Invoke;
39using ::testing::Mock;
40using ::testing::NiceMock;
41using ::testing::Return;
42using ::testing::ReturnRef;
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -070043using ::testing::SaveArg;
Prathmesh Prabhu40daa012013-04-03 10:35:03 -070044using ::testing::Sequence;
45using ::testing::SetArgumentPointee;
46using ::testing::StrictMock;
47using ::testing::Test;
48using ::testing::_;
49
50namespace shill {
51
52namespace {
53const char kInterfaceName[] = "int0";
54const char kIPAddress_0_0_0_0[] = "0.0.0.0";
55const char kIPAddress_8_8_8_8[] = "8.8.8.8";
56const char kProxyIPAddressRemote[] = "74.125.224.84";
57const char kProxyIPAddressLocal[] = "192.23.34.1";
58const char kProxyIPv6AddressLocal[] = "::ffff:192.23.34.1";
59const char kProxyURLRemote[] = "http://www.google.com";
60const int kProxyFD = 100;
61const short kProxyPortLocal = 5540;
62const short kProxyPortRemote = 80;
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -070063const int kSocketError = 3000;
Prathmesh Prabhu40daa012013-04-03 10:35:03 -070064} // namespace {}
65
66MATCHER_P(IsSameIPAddress, ip_addr, "") {
67 return arg.Equals(ip_addr);
68}
69
70class ConnectionHealthCheckerTest : public Test {
71 public:
72 ConnectionHealthCheckerTest()
73 : interface_name_(kInterfaceName),
74 device_info_(&control_, &dispatcher_,
75 reinterpret_cast<Metrics*>(NULL),
76 reinterpret_cast<Manager*>(NULL)),
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -070077 connection_(new NiceMock<MockConnection>(&device_info_)),
Prathmesh Prabhu40daa012013-04-03 10:35:03 -070078 socket_(NULL) {}
79
80 // Invokes
81 int GetSockName(int fd, struct sockaddr *addr_out, socklen_t *sockaddr_size) {
82 struct sockaddr_in addr;
83 EXPECT_EQ(kProxyFD, fd);
84 EXPECT_LE(sizeof(sockaddr_in), *sockaddr_size);
85 addr.sin_family = AF_INET;
86 inet_pton(AF_INET, kProxyIPAddressLocal, &addr.sin_addr);
87 addr.sin_port = htons(kProxyPortLocal);
88 memcpy(addr_out, &addr, sizeof(addr));
89 *sockaddr_size = sizeof(sockaddr_in);
90 return 0;
91 }
92
93 int GetSockNameReturnsIPv6(int fd, struct sockaddr *addr_out,
94 socklen_t *sockaddr_size) {
95 struct sockaddr_in6 addr;
96 EXPECT_EQ(kProxyFD, fd);
97 EXPECT_LE(sizeof(sockaddr_in6), *sockaddr_size);
98 addr.sin6_family = AF_INET6;
99 inet_pton(AF_INET6, kProxyIPv6AddressLocal, &addr.sin6_addr);
100 addr.sin6_port = htons(kProxyPortLocal);
101 memcpy(addr_out, &addr, sizeof(addr));
102 *sockaddr_size = sizeof(sockaddr_in6);
103 return 0;
104 }
105
106 void InvokeOnConnectionComplete(bool success, int sock_fd) {
107 health_checker_->OnConnectionComplete(success, sock_fd);
108 }
109
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700110 void InvokeGetDNSResultFailure() {
111 Error error(Error::kOperationFailed, "");
112 IPAddress address(IPAddress::kFamilyUnknown);
113 health_checker_->GetDNSResult(error, address);
114 }
115
116 void InvokeGetDNSResultSuccess(const IPAddress &address) {
117 Error error;
118 health_checker_->GetDNSResult(error, address);
119 }
120
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700121 protected:
122 void SetUp() {
123 EXPECT_CALL(*connection_.get(), interface_name())
124 .WillRepeatedly(ReturnRef(interface_name_));
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700125 ON_CALL(*connection_.get(), dns_servers())
126 .WillByDefault(ReturnRef(dns_servers_));
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700127 // ConnectionHealthChecker constructor should add some IPs
128 EXPECT_CALL(remote_ips_, AddUnique(_)).Times(AtLeast(1));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700129 health_checker_.reset(
130 new ConnectionHealthChecker(
131 connection_,
132 &dispatcher_,
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700133 &remote_ips_,
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700134 Bind(&ConnectionHealthCheckerTest::ResultCallbackTarget,
135 Unretained(this))));
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700136 Mock::VerifyAndClearExpectations(&remote_ips_);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700137 socket_ = new StrictMock<MockSockets>();
138 tcp_connection_ = new StrictMock<MockAsyncConnection>();
139 socket_info_reader_ = new StrictMock<MockSocketInfoReader>();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700140 // Passes ownership for all of these.
141 health_checker_->socket_.reset(socket_);
142 health_checker_->tcp_connection_.reset(tcp_connection_);
143 health_checker_->socket_info_reader_.reset(socket_info_reader_);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700144 health_checker_->dns_client_factory_ = MockDNSClientFactory::GetInstance();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700145 }
146
147 void TearDown() {
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700148 ExpectStop();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700149 }
150
151 // Accessors for private data in ConnectionHealthChecker.
152 const Sockets *socket() {
153 return health_checker_->socket_.get();
154 }
155 const AsyncConnection *tcp_connection() {
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700156 return health_checker_->tcp_connection_.get();
157 }
158 ScopedVector<DNSClient> &dns_clients() {
159 return health_checker_->dns_clients_;
160 }
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700161 int NumDNSQueries() {
162 return ConnectionHealthChecker::kNumDNSQueries;
163 }
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700164 int MaxFailedConnectionAttempts() {
165 return ConnectionHealthChecker::kMaxFailedConnectionAttempts;
166 }
167 int MaxSentDataPollingAttempts() {
168 return ConnectionHealthChecker::kMaxSentDataPollingAttempts;
169 }
170 int MinCongestedQueueAttempts() {
171 return ConnectionHealthChecker::kMinCongestedQueueAttempts;
172 }
173 int MinSuccessfulSendAttempts() {
174 return ConnectionHealthChecker::kMinSuccessfulSendAttempts;
175 }
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700176
177 // Mock Callbacks
178 MOCK_METHOD1(ResultCallbackTarget,
179 void(ConnectionHealthChecker::Result result));
180
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700181 // Helper methods
182 IPAddress StringToIPv4Address(const string &address_string) {
183 IPAddress ip_address(IPAddress::kFamilyIPv4);
184 EXPECT_TRUE(ip_address.SetAddressFromString(address_string));
185 return ip_address;
186 }
187 // Naming: CreateSocketInfo
188 // + (Proxy/Other) : TCP connection for proxy socket / some other
189 // socket.
190 // + arg1: Pass in any SocketInfo::ConnectionState you want.
191 // + arg2: Pass in any value of transmit_queue_value you want.
192 SocketInfo CreateSocketInfoOther() {
193 return SocketInfo(
194 SocketInfo::kConnectionStateUnknown,
195 StringToIPv4Address(kIPAddress_8_8_8_8),
196 0,
197 StringToIPv4Address(kProxyIPAddressRemote),
198 kProxyPortRemote,
199 0,
200 0,
201 SocketInfo::kTimerStateUnknown);
202 }
203 SocketInfo CreateSocketInfoProxy(SocketInfo::ConnectionState state) {
204 return SocketInfo(
205 state,
206 StringToIPv4Address(kProxyIPAddressLocal),
207 kProxyPortLocal,
208 StringToIPv4Address(kProxyIPAddressRemote),
209 kProxyPortRemote,
210 0,
211 0,
212 SocketInfo::kTimerStateUnknown);
213 }
214 SocketInfo CreateSocketInfoProxy(SocketInfo::ConnectionState state,
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700215 SocketInfo::TimerState timer_state,
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700216 uint64 transmit_queue_value) {
217 return SocketInfo(
218 state,
219 StringToIPv4Address(kProxyIPAddressLocal),
220 kProxyPortLocal,
221 StringToIPv4Address(kProxyIPAddressRemote),
222 kProxyPortRemote,
223 transmit_queue_value,
224 0,
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700225 timer_state);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700226 }
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700227
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700228
229 // Expectations
230 void ExpectReset() {
231 EXPECT_EQ(connection_.get(), health_checker_->connection_.get());
232 EXPECT_EQ(&dispatcher_, health_checker_->dispatcher_);
233 EXPECT_EQ(socket_, health_checker_->socket_.get());
234 EXPECT_FALSE(socket_ == NULL);
235 EXPECT_EQ(socket_info_reader_, health_checker_->socket_info_reader_.get());
236 EXPECT_FALSE(socket_info_reader_ == NULL);
237 EXPECT_FALSE(health_checker_->connection_complete_callback_.is_null());
238 EXPECT_EQ(tcp_connection_, health_checker_->tcp_connection_.get());
239 EXPECT_FALSE(tcp_connection_ == NULL);
240 EXPECT_FALSE(health_checker_->health_check_in_progress_);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700241 }
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700242
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700243 // Setup ConnectionHealthChecker::GetSocketInfo to return sock_info.
244 // This only works if GetSocketInfo is called with kProxyFD.
245 // If no matching sock_info is provided (Does not belong to proxy socket),
246 // GetSocketInfo will (correctly) return false.
247 void ExpectGetSocketInfoReturns(SocketInfo sock_info) {
248 vector<SocketInfo> info_list;
249 info_list.push_back(sock_info);
250 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
251 .InSequence(seq_)
252 .WillOnce(Invoke(this,
253 &ConnectionHealthCheckerTest::GetSockName));
254 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
255 .InSequence(seq_)
256 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
257 Return(true)));
258
259 }
260 void ExpectSuccessfulStart() {
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700261 EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(false));
262 EXPECT_CALL(remote_ips_, GetRandomIP())
263 .WillRepeatedly(Return(StringToIPv4Address(kProxyIPAddressRemote)));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700264 EXPECT_CALL(
265 *tcp_connection_,
266 Start(IsSameIPAddress(StringToIPv4Address(kProxyIPAddressRemote)),
267 kProxyPortRemote))
268 .InSequence(seq_)
269 .WillOnce(Return(true));
270 }
271 void ExpectRetry() {
272 EXPECT_CALL(*socket_, Close(kProxyFD))
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700273 .InSequence(seq_);
274 EXPECT_CALL(
275 *tcp_connection_,
276 Start(IsSameIPAddress(StringToIPv4Address(kProxyIPAddressRemote)),
277 kProxyPortRemote))
278 .InSequence(seq_)
279 .WillOnce(Return(true));
280 }
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700281 void ExpectStop() {
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700282 if (tcp_connection_)
283 EXPECT_CALL(*tcp_connection_, Stop())
284 .InSequence(seq_);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700285 }
286 void ExpectCleanUp() {
287 EXPECT_CALL(*socket_, Close(kProxyFD))
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700288 .InSequence(seq_);
289 EXPECT_CALL(*tcp_connection_, Stop())
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700290 .InSequence(seq_);
291 }
292
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700293 void VerifyAndClearAllExpectations() {
294 Mock::VerifyAndClearExpectations(this);
295 Mock::VerifyAndClearExpectations(tcp_connection_);
296 Mock::VerifyAndClearExpectations(socket_);
297 Mock::VerifyAndClearExpectations(socket_info_reader_);
298 }
299
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700300 // Needed for other mocks, but not for the tests directly.
301 const string interface_name_;
302 NiceMock<MockControl> control_;
303 NiceMock<MockDeviceInfo> device_info_;
304 vector<string> dns_servers_;
305
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700306 scoped_refptr<NiceMock<MockConnection> > connection_;
307 EventDispatcher dispatcher_;
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700308 MockIPAddressStore remote_ips_;
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700309 StrictMock<MockSockets> *socket_;
310 StrictMock<MockSocketInfoReader> *socket_info_reader_;
311 StrictMock<MockAsyncConnection> *tcp_connection_;
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700312 // Expectations in the Expect* functions are put in this sequence.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700313 // This allows us to chain calls to Expect* functions.
314 Sequence seq_;
315
316 scoped_ptr<ConnectionHealthChecker> health_checker_;
317};
318
319TEST_F(ConnectionHealthCheckerTest, Constructor) {
320 ExpectReset();
321}
322
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700323TEST_F(ConnectionHealthCheckerTest, SetConnection) {
324 scoped_refptr<NiceMock<MockConnection> > new_connection
325 = new NiceMock<MockConnection>(&device_info_);
326 // If a health check was in progress when SetConnection is called, verify
327 // that it restarts with the new connection.
328 ExpectSuccessfulStart();
329 health_checker_->Start();
330 VerifyAndClearAllExpectations();
Paul Stewart41a071e2013-04-26 07:56:04 -0700331
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700332 EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(true));
333 EXPECT_CALL(*new_connection.get(), interface_name())
334 .WillRepeatedly(ReturnRef(interface_name_));
335 EXPECT_CALL(*this,
336 ResultCallbackTarget(ConnectionHealthChecker::kResultUnknown));
337 health_checker_->SetConnection(new_connection);
338 EXPECT_NE(tcp_connection_, health_checker_->tcp_connection());
339 EXPECT_EQ(new_connection.get(), health_checker_->connection());
Paul Stewart41a071e2013-04-26 07:56:04 -0700340
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700341 // health_checker_ has reset tcp_connection_ to a new object.
342 // Since it owned tcp_connection_, the object has been destroyed.
343 tcp_connection_ = NULL;
Paul Stewart41a071e2013-04-26 07:56:04 -0700344}
345
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700346TEST_F(ConnectionHealthCheckerTest, GarbageCollectDNSClients) {
347 dns_clients().clear();
348 health_checker_->GarbageCollectDNSClients();
349 EXPECT_TRUE(dns_clients().empty());
350
351 for (int i = 0; i < 3; ++i) {
352 MockDNSClient *dns_client = new MockDNSClient();
353 EXPECT_CALL(*dns_client, IsActive())
354 .WillOnce(Return(true))
355 .WillOnce(Return(true))
356 .WillOnce(Return(false));
357 // Takes ownership.
358 dns_clients().push_back(dns_client);
359 }
360 for (int i = 0; i < 2; ++i) {
361 MockDNSClient *dns_client = new MockDNSClient();
362 EXPECT_CALL(*dns_client, IsActive())
363 .WillOnce(Return(false));
364 // Takes ownership.
365 dns_clients().push_back(dns_client);
366 }
367
368 EXPECT_EQ(5, dns_clients().size());
369 health_checker_->GarbageCollectDNSClients();
370 EXPECT_EQ(3, dns_clients().size());
371 health_checker_->GarbageCollectDNSClients();
372 EXPECT_EQ(3, dns_clients().size());
373 health_checker_->GarbageCollectDNSClients();
374 EXPECT_TRUE(dns_clients().empty());
375}
376
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700377TEST_F(ConnectionHealthCheckerTest, AddRemoteURL) {
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700378 HTTPURL url;
379 url.ParseFromString(kProxyURLRemote);
380 string host = url.host();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700381 IPAddress remote_ip = StringToIPv4Address(kProxyIPAddressRemote);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700382 IPAddress remote_ip_2 = StringToIPv4Address(kIPAddress_8_8_8_8);
383
384 MockDNSClientFactory *dns_client_factory
385 = MockDNSClientFactory::GetInstance();
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700386 vector<MockDNSClient *> dns_client_buffer;
387
388 // All DNS queries fail.
389 for (int i = 0; i < NumDNSQueries(); ++i) {
390 MockDNSClient *dns_client = new MockDNSClient();
391 EXPECT_CALL(*dns_client, Start(host, _))
392 .WillOnce(Return(false));
393 dns_client_buffer.push_back(dns_client);
394 }
395 // Will pass ownership of dns_clients elements.
396 for (int i = 0; i < NumDNSQueries(); ++i) {
397 EXPECT_CALL(*dns_client_factory, CreateDNSClient(_,_,_,_,_,_))
398 .InSequence(seq_)
399 .WillOnce(Return(dns_client_buffer[i]));
400 }
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700401 EXPECT_CALL(remote_ips_, AddUnique(_)).Times(0);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700402 health_checker_->AddRemoteURL(kProxyURLRemote);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700403 Mock::VerifyAndClearExpectations(dns_client_factory);
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700404 Mock::VerifyAndClearExpectations(&remote_ips_);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700405 dns_client_buffer.clear();
406 dns_clients().clear();
407
408 // All but one DNS queries fail, 1 succeeds.
409 for (int i = 0; i < NumDNSQueries(); ++i) {
410 MockDNSClient *dns_client = new MockDNSClient();
411 EXPECT_CALL(*dns_client, Start(host, _))
412 .WillOnce(Return(true));
413 dns_client_buffer.push_back(dns_client);
414 }
415 // Will pass ownership of dns_clients elements.
416 for (int i = 0; i < NumDNSQueries(); ++i) {
417 EXPECT_CALL(*dns_client_factory, CreateDNSClient(_,_,_,_,_,_))
418 .InSequence(seq_)
419 .WillOnce(Return(dns_client_buffer[i]));
420 }
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700421 EXPECT_CALL(remote_ips_, AddUnique(_));
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700422 health_checker_->AddRemoteURL(kProxyURLRemote);
423 for(int i = 0; i < NumDNSQueries() - 1; ++i) {
424 InvokeGetDNSResultFailure();
425 }
426 InvokeGetDNSResultSuccess(remote_ip);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700427 Mock::VerifyAndClearExpectations(dns_client_factory);
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700428 Mock::VerifyAndClearExpectations(&remote_ips_);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700429 dns_client_buffer.clear();
430 dns_clients().clear();
431
432 // Only 2 distinct IP addresses are returned.
433 for (int i = 0; i < NumDNSQueries(); ++i) {
434 MockDNSClient *dns_client = new MockDNSClient();
435 EXPECT_CALL(*dns_client, Start(host, _))
436 .WillOnce(Return(true));
437 dns_client_buffer.push_back(dns_client);
438 }
439 // Will pass ownership of dns_clients elements.
440 for (int i = 0; i < NumDNSQueries(); ++i) {
441 EXPECT_CALL(*dns_client_factory, CreateDNSClient(_,_,_,_,_,_))
442 .InSequence(seq_)
443 .WillOnce(Return(dns_client_buffer[i]));
444 }
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700445 EXPECT_CALL(remote_ips_, AddUnique(IsSameIPAddress(remote_ip))).Times(4);
446 EXPECT_CALL(remote_ips_, AddUnique(IsSameIPAddress(remote_ip_2)));
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700447 health_checker_->AddRemoteURL(kProxyURLRemote);
448 for (int i = 0; i < NumDNSQueries() - 1; ++i) {
449 InvokeGetDNSResultSuccess(remote_ip);
450 }
451 InvokeGetDNSResultSuccess(remote_ip_2);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700452 Mock::VerifyAndClearExpectations(dns_client_factory);
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700453 Mock::VerifyAndClearExpectations(&remote_ips_);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700454 dns_client_buffer.clear();
455 dns_clients().clear();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700456}
457
458TEST_F(ConnectionHealthCheckerTest, GetSocketInfo) {
459 SocketInfo sock_info;
460 vector<SocketInfo> info_list;
461
462 // GetSockName fails.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700463 EXPECT_CALL(*socket_, GetSockName(_,_,_))
464 .WillOnce(Return(-1));
465 EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
466 Mock::VerifyAndClearExpectations(socket_);
467
468 // GetSockName returns IPv6.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700469 EXPECT_CALL(*socket_, GetSockName(_,_,_))
470 .WillOnce(
471 Invoke(this,
472 &ConnectionHealthCheckerTest::GetSockNameReturnsIPv6));
473 EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
474 Mock::VerifyAndClearExpectations(socket_);
475
476 // LoadTcpSocketInfo fails.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700477 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
478 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
479 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
480 .WillOnce(Return(false));
481 EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
482 Mock::VerifyAndClearExpectations(socket_);
483 Mock::VerifyAndClearExpectations(socket_info_reader_);
484
485 // LoadTcpSocketInfo returns empty list.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700486 info_list.clear();
487 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
488 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
489 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
490 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
491 Return(true)));
492 EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
493 Mock::VerifyAndClearExpectations(socket_);
494 Mock::VerifyAndClearExpectations(socket_info_reader_);
495
496 // LoadTcpSocketInfo returns a list without our socket.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700497 info_list.clear();
498 info_list.push_back(CreateSocketInfoOther());
499 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
500 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
501 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
502 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
503 Return(true)));
504 EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
505 Mock::VerifyAndClearExpectations(socket_);
506 Mock::VerifyAndClearExpectations(socket_info_reader_);
507
508 // LoadTcpSocketInfo returns a list with only our socket.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700509 info_list.clear();
510 info_list.push_back(
511 CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
512 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
513 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
514 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
515 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
516 Return(true)));
517 EXPECT_TRUE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
518 EXPECT_TRUE(CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown)
519 .IsSameSocketAs(sock_info));
520 Mock::VerifyAndClearExpectations(socket_);
521 Mock::VerifyAndClearExpectations(socket_info_reader_);
522
523 // LoadTcpSocketInfo returns a list with two sockets, including ours.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700524 info_list.clear();
525 info_list.push_back(CreateSocketInfoOther());
526 info_list.push_back(
527 CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
528 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
529 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
530 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
531 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
532 Return(true)));
533 EXPECT_TRUE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
534 EXPECT_TRUE(CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown)
535 .IsSameSocketAs(sock_info));
536 Mock::VerifyAndClearExpectations(socket_);
537 Mock::VerifyAndClearExpectations(socket_info_reader_);
538
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700539 info_list.clear();
540 info_list.push_back(
541 CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
542 info_list.push_back(CreateSocketInfoOther());
543 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
544 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
545 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
546 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
547 Return(true)));
548 EXPECT_TRUE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
549 EXPECT_TRUE(CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown)
550 .IsSameSocketAs(sock_info));
551 Mock::VerifyAndClearExpectations(socket_);
552 Mock::VerifyAndClearExpectations(socket_info_reader_);
553}
554
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700555TEST_F(ConnectionHealthCheckerTest, NextHealthCheckSample) {
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700556 IPAddress ip = StringToIPv4Address(kProxyIPAddressRemote);
557 ON_CALL(remote_ips_, GetRandomIP())
558 .WillByDefault(Return(ip));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700559
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700560 health_checker_->set_num_connection_failures(MaxFailedConnectionAttempts());
561 ExpectStop();
562 EXPECT_CALL(
563 *this,
564 ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
565 health_checker_->NextHealthCheckSample();
566 dispatcher_.DispatchPendingEvents();
567 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700568
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700569 health_checker_->set_num_congested_queue_detected(
570 MinCongestedQueueAttempts());
571 ExpectStop();
572 EXPECT_CALL(
573 *this,
574 ResultCallbackTarget(ConnectionHealthChecker::kResultCongestedTxQueue));
575 health_checker_->NextHealthCheckSample();
576 dispatcher_.DispatchPendingEvents();
577 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700578
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700579 health_checker_->set_num_successful_sends(MinSuccessfulSendAttempts());
580 ExpectStop();
581 EXPECT_CALL(
582 *this,
583 ResultCallbackTarget(ConnectionHealthChecker::kResultSuccess));
584 health_checker_->NextHealthCheckSample();
585 dispatcher_.DispatchPendingEvents();
586 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700587
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700588 EXPECT_CALL(*tcp_connection_, Start(_,_)).WillOnce(Return(true));
589 health_checker_->NextHealthCheckSample();
590 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700591
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700592 // This test assumes that there are at least 2 connection attempts left
593 // before ConnectionHealthChecker gives up.
594 EXPECT_CALL(*tcp_connection_, Start(_,_))
595 .WillOnce(Return(false))
596 .WillOnce(Return(true));
597 short num_connection_failures = health_checker_->num_connection_failures();
598 health_checker_->NextHealthCheckSample();
599 EXPECT_EQ(num_connection_failures + 1,
600 health_checker_->num_connection_failures());
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700601}
602
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700603TEST_F(ConnectionHealthCheckerTest, OnConnectionComplete) {
604 // Test that num_connection_attempts is incremented on failure when
605 // (1) Async Connection fails.
606 health_checker_->set_num_connection_failures(
607 MaxFailedConnectionAttempts() - 1);
608 ExpectStop();
609 EXPECT_CALL(
610 *this,
611 ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
612 health_checker_->OnConnectionComplete(false, -1);
613 dispatcher_.DispatchPendingEvents();
614 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700615
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700616 // (2) The connection state is garbled up.
617 health_checker_->set_num_connection_failures(
618 MaxFailedConnectionAttempts() - 1);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700619 ExpectGetSocketInfoReturns(
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700620 CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
621 EXPECT_CALL(*socket_, Close(kProxyFD));
622 ExpectStop();
623 EXPECT_CALL(
624 *this,
625 ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
626 health_checker_->OnConnectionComplete(true, kProxyFD);
627 dispatcher_.DispatchPendingEvents();
628 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700629
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700630 // (3) Send fails.
631 health_checker_->set_num_connection_failures(
632 MaxFailedConnectionAttempts() - 1);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700633 ExpectGetSocketInfoReturns(
634 CreateSocketInfoProxy(SocketInfo::kConnectionStateEstablished));
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700635 EXPECT_CALL(*socket_, Send(kProxyFD, _, Gt(0), _)).WillOnce(Return(-1));
636 EXPECT_CALL(*socket_, Error()).WillOnce(Return(kSocketError));
637 EXPECT_CALL(*socket_, Close(kProxyFD));
638 ExpectStop();
639 EXPECT_CALL(
640 *this,
641 ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
642 health_checker_->OnConnectionComplete(true, kProxyFD);
643 dispatcher_.DispatchPendingEvents();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700644}
645
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700646TEST_F(ConnectionHealthCheckerTest, VerifySentData) {
647 health_checker_->AddRemoteIP(StringToIPv4Address(kProxyIPAddressRemote));
648
649 // (1) Test that num_connection_attempts is incremented when the connection
650 // state is garbled up.
651 health_checker_->set_num_connection_failures(
652 MaxFailedConnectionAttempts() - 1);
653 ExpectGetSocketInfoReturns(
654 CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
655 EXPECT_CALL(*socket_, Close(kProxyFD));
656 ExpectStop();
657 EXPECT_CALL(
658 *this,
659 ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
660 health_checker_->set_sock_fd(kProxyFD);
661 health_checker_->VerifySentData();
662 dispatcher_.DispatchPendingEvents();
663 VerifyAndClearAllExpectations();
664
665 // (2) Test that num_congested_queue_detected is incremented when all polling
666 // attempts have expired.
667 health_checker_->set_num_congested_queue_detected(
668 MinCongestedQueueAttempts() - 1);
669 health_checker_->set_num_tx_queue_polling_attempts(
670 MaxSentDataPollingAttempts());
671 health_checker_->set_old_transmit_queue_value(0);
672 ExpectGetSocketInfoReturns(
673 CreateSocketInfoProxy(SocketInfo::kConnectionStateEstablished,
674 SocketInfo::kTimerStateRetransmitTimerPending,
675 1));
676 EXPECT_CALL(*socket_, Close(kProxyFD));
677 ExpectStop();
678 EXPECT_CALL(
679 *this,
680 ResultCallbackTarget(ConnectionHealthChecker::kResultCongestedTxQueue));
681 health_checker_->set_sock_fd(kProxyFD);
682 health_checker_->VerifySentData();
683 dispatcher_.DispatchPendingEvents();
684 VerifyAndClearAllExpectations();
685
686 // (3) Test that num_successful_sends is incremented if everything goes fine.
687 health_checker_->set_num_successful_sends(MinSuccessfulSendAttempts() - 1);
688 health_checker_->set_old_transmit_queue_value(0);
689 ExpectGetSocketInfoReturns(
690 CreateSocketInfoProxy(SocketInfo::kConnectionStateEstablished,
691 SocketInfo::kTimerStateNoTimerPending,
692 0));
693 EXPECT_CALL(*socket_, Close(kProxyFD));
694 ExpectStop();
695 EXPECT_CALL(
696 *this,
697 ResultCallbackTarget(ConnectionHealthChecker::kResultSuccess));
698 health_checker_->set_sock_fd(kProxyFD);
699 health_checker_->VerifySentData();
700 dispatcher_.DispatchPendingEvents();
701 VerifyAndClearAllExpectations();
702}
703
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700704// Flow: Start() -> Start()
705// Expectation: Only one AsyncConnection is setup
706TEST_F(ConnectionHealthCheckerTest, StartStartSkipsSecond) {
707 EXPECT_CALL(*tcp_connection_, Start(_,_))
708 .WillOnce(Return(true));
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700709 EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(false));
710 EXPECT_CALL(remote_ips_, GetRandomIP())
711 .WillOnce(Return(StringToIPv4Address(kProxyIPAddressRemote)));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700712 health_checker_->Start();
713 health_checker_->Start();
714}
715
716// Precondition: size(|remote_ips_|) > 0
717// Flow: Start() -> Stop() before ConnectionComplete()
718// Expectation: No call to |result_callback|
719TEST_F(ConnectionHealthCheckerTest, StartStopNoCallback) {
720 EXPECT_CALL(*tcp_connection_, Start(_,_))
721 .WillOnce(Return(true));
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700722 EXPECT_CALL(*tcp_connection_, Stop());
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700723 EXPECT_CALL(*this, ResultCallbackTarget(_))
724 .Times(0);
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700725 EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(false));
726 EXPECT_CALL(remote_ips_, GetRandomIP())
727 .WillOnce(Return(StringToIPv4Address(kProxyIPAddressRemote)));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700728 health_checker_->Start();
729 health_checker_->Stop();
730}
731
732// Precondition: Empty remote_ips_
733// Flow: Start()
734// Expectation: call |result_callback| with kResultUnknown
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700735TEST_F(ConnectionHealthCheckerTest, StartImmediateFailure) {
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700736 EXPECT_CALL(remote_ips_, Empty()).WillOnce(Return(true));
737 EXPECT_CALL(*tcp_connection_, Stop());
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700738 EXPECT_CALL(*this, ResultCallbackTarget(
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700739 ConnectionHealthChecker::kResultUnknown));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700740 health_checker_->Start();
741 Mock::VerifyAndClearExpectations(this);
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700742 Mock::VerifyAndClearExpectations(&remote_ips_);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700743 Mock::VerifyAndClearExpectations(tcp_connection_);
744
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700745 EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(false));
746 EXPECT_CALL(remote_ips_, GetRandomIP())
747 .WillRepeatedly(Return(StringToIPv4Address(kProxyIPAddressRemote)));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700748 EXPECT_CALL(*tcp_connection_,
749 Start(IsSameIPAddress(StringToIPv4Address(kProxyIPAddressRemote)),
750 kProxyPortRemote))
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700751 .Times(MaxFailedConnectionAttempts())
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700752 .WillRepeatedly(Return(false));
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700753 EXPECT_CALL(*tcp_connection_, Stop());
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700754 EXPECT_CALL(*this, ResultCallbackTarget(
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700755 ConnectionHealthChecker::kResultConnectionFailure));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700756 health_checker_->Start();
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700757 dispatcher_.DispatchPendingEvents();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700758 Mock::VerifyAndClearExpectations(this);
759 Mock::VerifyAndClearExpectations(tcp_connection_);
760}
761
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700762} // namespace shill