blob: 43ac0e6010a8f74738a9cde75dc62a7d02ff7c1b [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";
Prathmesh Prabhu40daa012013-04-03 10:35:03 -070054const char kIPAddress_8_8_8_8[] = "8.8.8.8";
55const char kProxyIPAddressRemote[] = "74.125.224.84";
56const char kProxyIPAddressLocal[] = "192.23.34.1";
57const char kProxyIPv6AddressLocal[] = "::ffff:192.23.34.1";
58const char kProxyURLRemote[] = "http://www.google.com";
59const int kProxyFD = 100;
60const short kProxyPortLocal = 5540;
61const short kProxyPortRemote = 80;
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -070062const int kSocketError = 3000;
Prathmesh Prabhu40daa012013-04-03 10:35:03 -070063} // namespace {}
64
65MATCHER_P(IsSameIPAddress, ip_addr, "") {
66 return arg.Equals(ip_addr);
67}
68
69class ConnectionHealthCheckerTest : public Test {
70 public:
71 ConnectionHealthCheckerTest()
72 : interface_name_(kInterfaceName),
73 device_info_(&control_, &dispatcher_,
74 reinterpret_cast<Metrics*>(NULL),
75 reinterpret_cast<Manager*>(NULL)),
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -070076 connection_(new NiceMock<MockConnection>(&device_info_)),
Prathmesh Prabhu40daa012013-04-03 10:35:03 -070077 socket_(NULL) {}
78
79 // Invokes
80 int GetSockName(int fd, struct sockaddr *addr_out, socklen_t *sockaddr_size) {
81 struct sockaddr_in addr;
82 EXPECT_EQ(kProxyFD, fd);
83 EXPECT_LE(sizeof(sockaddr_in), *sockaddr_size);
84 addr.sin_family = AF_INET;
85 inet_pton(AF_INET, kProxyIPAddressLocal, &addr.sin_addr);
86 addr.sin_port = htons(kProxyPortLocal);
87 memcpy(addr_out, &addr, sizeof(addr));
88 *sockaddr_size = sizeof(sockaddr_in);
89 return 0;
90 }
91
92 int GetSockNameReturnsIPv6(int fd, struct sockaddr *addr_out,
93 socklen_t *sockaddr_size) {
94 struct sockaddr_in6 addr;
95 EXPECT_EQ(kProxyFD, fd);
96 EXPECT_LE(sizeof(sockaddr_in6), *sockaddr_size);
97 addr.sin6_family = AF_INET6;
98 inet_pton(AF_INET6, kProxyIPv6AddressLocal, &addr.sin6_addr);
99 addr.sin6_port = htons(kProxyPortLocal);
100 memcpy(addr_out, &addr, sizeof(addr));
101 *sockaddr_size = sizeof(sockaddr_in6);
102 return 0;
103 }
104
105 void InvokeOnConnectionComplete(bool success, int sock_fd) {
106 health_checker_->OnConnectionComplete(success, sock_fd);
107 }
108
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700109 void InvokeGetDNSResultFailure() {
110 Error error(Error::kOperationFailed, "");
111 IPAddress address(IPAddress::kFamilyUnknown);
112 health_checker_->GetDNSResult(error, address);
113 }
114
115 void InvokeGetDNSResultSuccess(const IPAddress &address) {
116 Error error;
117 health_checker_->GetDNSResult(error, address);
118 }
119
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700120 protected:
121 void SetUp() {
122 EXPECT_CALL(*connection_.get(), interface_name())
123 .WillRepeatedly(ReturnRef(interface_name_));
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700124 ON_CALL(*connection_.get(), dns_servers())
125 .WillByDefault(ReturnRef(dns_servers_));
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700126 // ConnectionHealthChecker constructor should add some IPs
127 EXPECT_CALL(remote_ips_, AddUnique(_)).Times(AtLeast(1));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700128 health_checker_.reset(
129 new ConnectionHealthChecker(
130 connection_,
131 &dispatcher_,
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700132 &remote_ips_,
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700133 Bind(&ConnectionHealthCheckerTest::ResultCallbackTarget,
134 Unretained(this))));
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700135 Mock::VerifyAndClearExpectations(&remote_ips_);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700136 socket_ = new StrictMock<MockSockets>();
137 tcp_connection_ = new StrictMock<MockAsyncConnection>();
138 socket_info_reader_ = new StrictMock<MockSocketInfoReader>();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700139 // Passes ownership for all of these.
140 health_checker_->socket_.reset(socket_);
141 health_checker_->tcp_connection_.reset(tcp_connection_);
142 health_checker_->socket_info_reader_.reset(socket_info_reader_);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700143 health_checker_->dns_client_factory_ = MockDNSClientFactory::GetInstance();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700144 }
145
146 void TearDown() {
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700147 ExpectStop();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700148 }
149
150 // Accessors for private data in ConnectionHealthChecker.
151 const Sockets *socket() {
152 return health_checker_->socket_.get();
153 }
154 const AsyncConnection *tcp_connection() {
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700155 return health_checker_->tcp_connection_.get();
156 }
157 ScopedVector<DNSClient> &dns_clients() {
158 return health_checker_->dns_clients_;
159 }
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700160 int NumDNSQueries() {
161 return ConnectionHealthChecker::kNumDNSQueries;
162 }
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700163 int MaxFailedConnectionAttempts() {
164 return ConnectionHealthChecker::kMaxFailedConnectionAttempts;
165 }
166 int MaxSentDataPollingAttempts() {
167 return ConnectionHealthChecker::kMaxSentDataPollingAttempts;
168 }
169 int MinCongestedQueueAttempts() {
170 return ConnectionHealthChecker::kMinCongestedQueueAttempts;
171 }
172 int MinSuccessfulSendAttempts() {
173 return ConnectionHealthChecker::kMinSuccessfulSendAttempts;
174 }
Prathmesh Prabhu81404c62013-05-08 17:04:28 -0700175 void SetTCPStateUpdateWaitMilliseconds(int new_wait) {
176 health_checker_->tcp_state_update_wait_milliseconds_ = new_wait;
177 }
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700178
179 // Mock Callbacks
180 MOCK_METHOD1(ResultCallbackTarget,
181 void(ConnectionHealthChecker::Result result));
182
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700183 // Helper methods
184 IPAddress StringToIPv4Address(const string &address_string) {
185 IPAddress ip_address(IPAddress::kFamilyIPv4);
186 EXPECT_TRUE(ip_address.SetAddressFromString(address_string));
187 return ip_address;
188 }
189 // Naming: CreateSocketInfo
190 // + (Proxy/Other) : TCP connection for proxy socket / some other
191 // socket.
192 // + arg1: Pass in any SocketInfo::ConnectionState you want.
193 // + arg2: Pass in any value of transmit_queue_value you want.
194 SocketInfo CreateSocketInfoOther() {
195 return SocketInfo(
196 SocketInfo::kConnectionStateUnknown,
197 StringToIPv4Address(kIPAddress_8_8_8_8),
198 0,
199 StringToIPv4Address(kProxyIPAddressRemote),
200 kProxyPortRemote,
201 0,
202 0,
203 SocketInfo::kTimerStateUnknown);
204 }
205 SocketInfo CreateSocketInfoProxy(SocketInfo::ConnectionState state) {
206 return SocketInfo(
207 state,
208 StringToIPv4Address(kProxyIPAddressLocal),
209 kProxyPortLocal,
210 StringToIPv4Address(kProxyIPAddressRemote),
211 kProxyPortRemote,
212 0,
213 0,
214 SocketInfo::kTimerStateUnknown);
215 }
216 SocketInfo CreateSocketInfoProxy(SocketInfo::ConnectionState state,
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700217 SocketInfo::TimerState timer_state,
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700218 uint64 transmit_queue_value) {
219 return SocketInfo(
220 state,
221 StringToIPv4Address(kProxyIPAddressLocal),
222 kProxyPortLocal,
223 StringToIPv4Address(kProxyIPAddressRemote),
224 kProxyPortRemote,
225 transmit_queue_value,
226 0,
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700227 timer_state);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700228 }
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700229
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700230
231 // Expectations
232 void ExpectReset() {
233 EXPECT_EQ(connection_.get(), health_checker_->connection_.get());
234 EXPECT_EQ(&dispatcher_, health_checker_->dispatcher_);
235 EXPECT_EQ(socket_, health_checker_->socket_.get());
236 EXPECT_FALSE(socket_ == NULL);
237 EXPECT_EQ(socket_info_reader_, health_checker_->socket_info_reader_.get());
238 EXPECT_FALSE(socket_info_reader_ == NULL);
239 EXPECT_FALSE(health_checker_->connection_complete_callback_.is_null());
240 EXPECT_EQ(tcp_connection_, health_checker_->tcp_connection_.get());
241 EXPECT_FALSE(tcp_connection_ == NULL);
242 EXPECT_FALSE(health_checker_->health_check_in_progress_);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700243 }
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700244
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700245 // Setup ConnectionHealthChecker::GetSocketInfo to return sock_info.
246 // This only works if GetSocketInfo is called with kProxyFD.
247 // If no matching sock_info is provided (Does not belong to proxy socket),
248 // GetSocketInfo will (correctly) return false.
249 void ExpectGetSocketInfoReturns(SocketInfo sock_info) {
250 vector<SocketInfo> info_list;
251 info_list.push_back(sock_info);
252 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
253 .InSequence(seq_)
254 .WillOnce(Invoke(this,
255 &ConnectionHealthCheckerTest::GetSockName));
256 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
257 .InSequence(seq_)
258 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
259 Return(true)));
260
261 }
262 void ExpectSuccessfulStart() {
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700263 EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(false));
264 EXPECT_CALL(remote_ips_, GetRandomIP())
265 .WillRepeatedly(Return(StringToIPv4Address(kProxyIPAddressRemote)));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700266 EXPECT_CALL(
267 *tcp_connection_,
268 Start(IsSameIPAddress(StringToIPv4Address(kProxyIPAddressRemote)),
269 kProxyPortRemote))
270 .InSequence(seq_)
271 .WillOnce(Return(true));
272 }
273 void ExpectRetry() {
274 EXPECT_CALL(*socket_, Close(kProxyFD))
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700275 .InSequence(seq_);
276 EXPECT_CALL(
277 *tcp_connection_,
278 Start(IsSameIPAddress(StringToIPv4Address(kProxyIPAddressRemote)),
279 kProxyPortRemote))
280 .InSequence(seq_)
281 .WillOnce(Return(true));
282 }
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700283 void ExpectStop() {
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700284 if (tcp_connection_)
285 EXPECT_CALL(*tcp_connection_, Stop())
286 .InSequence(seq_);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700287 }
288 void ExpectCleanUp() {
289 EXPECT_CALL(*socket_, Close(kProxyFD))
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700290 .InSequence(seq_);
291 EXPECT_CALL(*tcp_connection_, Stop())
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700292 .InSequence(seq_);
293 }
294
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700295 void VerifyAndClearAllExpectations() {
296 Mock::VerifyAndClearExpectations(this);
297 Mock::VerifyAndClearExpectations(tcp_connection_);
298 Mock::VerifyAndClearExpectations(socket_);
299 Mock::VerifyAndClearExpectations(socket_info_reader_);
300 }
301
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700302 // Needed for other mocks, but not for the tests directly.
303 const string interface_name_;
304 NiceMock<MockControl> control_;
305 NiceMock<MockDeviceInfo> device_info_;
306 vector<string> dns_servers_;
307
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700308 scoped_refptr<NiceMock<MockConnection> > connection_;
309 EventDispatcher dispatcher_;
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700310 MockIPAddressStore remote_ips_;
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700311 StrictMock<MockSockets> *socket_;
312 StrictMock<MockSocketInfoReader> *socket_info_reader_;
313 StrictMock<MockAsyncConnection> *tcp_connection_;
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700314 // Expectations in the Expect* functions are put in this sequence.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700315 // This allows us to chain calls to Expect* functions.
316 Sequence seq_;
317
318 scoped_ptr<ConnectionHealthChecker> health_checker_;
319};
320
321TEST_F(ConnectionHealthCheckerTest, Constructor) {
322 ExpectReset();
323}
324
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700325TEST_F(ConnectionHealthCheckerTest, SetConnection) {
326 scoped_refptr<NiceMock<MockConnection> > new_connection
327 = new NiceMock<MockConnection>(&device_info_);
328 // If a health check was in progress when SetConnection is called, verify
329 // that it restarts with the new connection.
330 ExpectSuccessfulStart();
331 health_checker_->Start();
332 VerifyAndClearAllExpectations();
Paul Stewart41a071e2013-04-26 07:56:04 -0700333
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700334 EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(true));
335 EXPECT_CALL(*new_connection.get(), interface_name())
336 .WillRepeatedly(ReturnRef(interface_name_));
337 EXPECT_CALL(*this,
338 ResultCallbackTarget(ConnectionHealthChecker::kResultUnknown));
339 health_checker_->SetConnection(new_connection);
340 EXPECT_NE(tcp_connection_, health_checker_->tcp_connection());
341 EXPECT_EQ(new_connection.get(), health_checker_->connection());
Paul Stewart41a071e2013-04-26 07:56:04 -0700342
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700343 // health_checker_ has reset tcp_connection_ to a new object.
344 // Since it owned tcp_connection_, the object has been destroyed.
345 tcp_connection_ = NULL;
Paul Stewart41a071e2013-04-26 07:56:04 -0700346}
347
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700348TEST_F(ConnectionHealthCheckerTest, GarbageCollectDNSClients) {
349 dns_clients().clear();
350 health_checker_->GarbageCollectDNSClients();
351 EXPECT_TRUE(dns_clients().empty());
352
353 for (int i = 0; i < 3; ++i) {
354 MockDNSClient *dns_client = new MockDNSClient();
355 EXPECT_CALL(*dns_client, IsActive())
356 .WillOnce(Return(true))
357 .WillOnce(Return(true))
358 .WillOnce(Return(false));
359 // Takes ownership.
360 dns_clients().push_back(dns_client);
361 }
362 for (int i = 0; i < 2; ++i) {
363 MockDNSClient *dns_client = new MockDNSClient();
364 EXPECT_CALL(*dns_client, IsActive())
365 .WillOnce(Return(false));
366 // Takes ownership.
367 dns_clients().push_back(dns_client);
368 }
369
370 EXPECT_EQ(5, dns_clients().size());
371 health_checker_->GarbageCollectDNSClients();
372 EXPECT_EQ(3, dns_clients().size());
373 health_checker_->GarbageCollectDNSClients();
374 EXPECT_EQ(3, dns_clients().size());
375 health_checker_->GarbageCollectDNSClients();
376 EXPECT_TRUE(dns_clients().empty());
377}
378
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700379TEST_F(ConnectionHealthCheckerTest, AddRemoteURL) {
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700380 HTTPURL url;
381 url.ParseFromString(kProxyURLRemote);
382 string host = url.host();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700383 IPAddress remote_ip = StringToIPv4Address(kProxyIPAddressRemote);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700384 IPAddress remote_ip_2 = StringToIPv4Address(kIPAddress_8_8_8_8);
385
386 MockDNSClientFactory *dns_client_factory
387 = MockDNSClientFactory::GetInstance();
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700388 vector<MockDNSClient *> dns_client_buffer;
389
390 // All DNS queries fail.
391 for (int i = 0; i < NumDNSQueries(); ++i) {
392 MockDNSClient *dns_client = new MockDNSClient();
393 EXPECT_CALL(*dns_client, Start(host, _))
394 .WillOnce(Return(false));
395 dns_client_buffer.push_back(dns_client);
396 }
397 // Will pass ownership of dns_clients elements.
398 for (int i = 0; i < NumDNSQueries(); ++i) {
399 EXPECT_CALL(*dns_client_factory, CreateDNSClient(_,_,_,_,_,_))
400 .InSequence(seq_)
401 .WillOnce(Return(dns_client_buffer[i]));
402 }
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700403 EXPECT_CALL(remote_ips_, AddUnique(_)).Times(0);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700404 health_checker_->AddRemoteURL(kProxyURLRemote);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700405 Mock::VerifyAndClearExpectations(dns_client_factory);
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700406 Mock::VerifyAndClearExpectations(&remote_ips_);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700407 dns_client_buffer.clear();
408 dns_clients().clear();
409
410 // All but one DNS queries fail, 1 succeeds.
411 for (int i = 0; i < NumDNSQueries(); ++i) {
412 MockDNSClient *dns_client = new MockDNSClient();
413 EXPECT_CALL(*dns_client, Start(host, _))
414 .WillOnce(Return(true));
415 dns_client_buffer.push_back(dns_client);
416 }
417 // Will pass ownership of dns_clients elements.
418 for (int i = 0; i < NumDNSQueries(); ++i) {
419 EXPECT_CALL(*dns_client_factory, CreateDNSClient(_,_,_,_,_,_))
420 .InSequence(seq_)
421 .WillOnce(Return(dns_client_buffer[i]));
422 }
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700423 EXPECT_CALL(remote_ips_, AddUnique(_));
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700424 health_checker_->AddRemoteURL(kProxyURLRemote);
425 for(int i = 0; i < NumDNSQueries() - 1; ++i) {
426 InvokeGetDNSResultFailure();
427 }
428 InvokeGetDNSResultSuccess(remote_ip);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700429 Mock::VerifyAndClearExpectations(dns_client_factory);
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700430 Mock::VerifyAndClearExpectations(&remote_ips_);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700431 dns_client_buffer.clear();
432 dns_clients().clear();
433
434 // Only 2 distinct IP addresses are returned.
435 for (int i = 0; i < NumDNSQueries(); ++i) {
436 MockDNSClient *dns_client = new MockDNSClient();
437 EXPECT_CALL(*dns_client, Start(host, _))
438 .WillOnce(Return(true));
439 dns_client_buffer.push_back(dns_client);
440 }
441 // Will pass ownership of dns_clients elements.
442 for (int i = 0; i < NumDNSQueries(); ++i) {
443 EXPECT_CALL(*dns_client_factory, CreateDNSClient(_,_,_,_,_,_))
444 .InSequence(seq_)
445 .WillOnce(Return(dns_client_buffer[i]));
446 }
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700447 EXPECT_CALL(remote_ips_, AddUnique(IsSameIPAddress(remote_ip))).Times(4);
448 EXPECT_CALL(remote_ips_, AddUnique(IsSameIPAddress(remote_ip_2)));
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700449 health_checker_->AddRemoteURL(kProxyURLRemote);
450 for (int i = 0; i < NumDNSQueries() - 1; ++i) {
451 InvokeGetDNSResultSuccess(remote_ip);
452 }
453 InvokeGetDNSResultSuccess(remote_ip_2);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700454 Mock::VerifyAndClearExpectations(dns_client_factory);
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700455 Mock::VerifyAndClearExpectations(&remote_ips_);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700456 dns_client_buffer.clear();
457 dns_clients().clear();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700458}
459
460TEST_F(ConnectionHealthCheckerTest, GetSocketInfo) {
461 SocketInfo sock_info;
462 vector<SocketInfo> info_list;
463
464 // GetSockName fails.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700465 EXPECT_CALL(*socket_, GetSockName(_,_,_))
466 .WillOnce(Return(-1));
467 EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
468 Mock::VerifyAndClearExpectations(socket_);
469
470 // GetSockName returns IPv6.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700471 EXPECT_CALL(*socket_, GetSockName(_,_,_))
472 .WillOnce(
473 Invoke(this,
474 &ConnectionHealthCheckerTest::GetSockNameReturnsIPv6));
475 EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
476 Mock::VerifyAndClearExpectations(socket_);
477
478 // LoadTcpSocketInfo fails.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700479 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
480 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
481 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
482 .WillOnce(Return(false));
483 EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
484 Mock::VerifyAndClearExpectations(socket_);
485 Mock::VerifyAndClearExpectations(socket_info_reader_);
486
487 // LoadTcpSocketInfo returns empty list.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700488 info_list.clear();
489 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
490 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
491 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
492 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
493 Return(true)));
494 EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
495 Mock::VerifyAndClearExpectations(socket_);
496 Mock::VerifyAndClearExpectations(socket_info_reader_);
497
498 // LoadTcpSocketInfo returns a list without our socket.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700499 info_list.clear();
500 info_list.push_back(CreateSocketInfoOther());
501 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
502 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
503 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
504 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
505 Return(true)));
506 EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
507 Mock::VerifyAndClearExpectations(socket_);
508 Mock::VerifyAndClearExpectations(socket_info_reader_);
509
510 // LoadTcpSocketInfo returns a list with only our socket.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700511 info_list.clear();
512 info_list.push_back(
513 CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
514 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
515 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
516 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
517 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
518 Return(true)));
519 EXPECT_TRUE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
520 EXPECT_TRUE(CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown)
521 .IsSameSocketAs(sock_info));
522 Mock::VerifyAndClearExpectations(socket_);
523 Mock::VerifyAndClearExpectations(socket_info_reader_);
524
525 // LoadTcpSocketInfo returns a list with two sockets, including ours.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700526 info_list.clear();
527 info_list.push_back(CreateSocketInfoOther());
528 info_list.push_back(
529 CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
530 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
531 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
532 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
533 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
534 Return(true)));
535 EXPECT_TRUE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
536 EXPECT_TRUE(CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown)
537 .IsSameSocketAs(sock_info));
538 Mock::VerifyAndClearExpectations(socket_);
539 Mock::VerifyAndClearExpectations(socket_info_reader_);
540
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700541 info_list.clear();
542 info_list.push_back(
543 CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
544 info_list.push_back(CreateSocketInfoOther());
545 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
546 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
547 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
548 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
549 Return(true)));
550 EXPECT_TRUE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
551 EXPECT_TRUE(CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown)
552 .IsSameSocketAs(sock_info));
553 Mock::VerifyAndClearExpectations(socket_);
554 Mock::VerifyAndClearExpectations(socket_info_reader_);
555}
556
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700557TEST_F(ConnectionHealthCheckerTest, NextHealthCheckSample) {
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700558 IPAddress ip = StringToIPv4Address(kProxyIPAddressRemote);
559 ON_CALL(remote_ips_, GetRandomIP())
560 .WillByDefault(Return(ip));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700561
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700562 health_checker_->set_num_connection_failures(MaxFailedConnectionAttempts());
563 ExpectStop();
564 EXPECT_CALL(
565 *this,
566 ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
567 health_checker_->NextHealthCheckSample();
568 dispatcher_.DispatchPendingEvents();
569 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700570
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700571 health_checker_->set_num_congested_queue_detected(
572 MinCongestedQueueAttempts());
573 ExpectStop();
574 EXPECT_CALL(
575 *this,
576 ResultCallbackTarget(ConnectionHealthChecker::kResultCongestedTxQueue));
577 health_checker_->NextHealthCheckSample();
578 dispatcher_.DispatchPendingEvents();
579 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700580
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700581 health_checker_->set_num_successful_sends(MinSuccessfulSendAttempts());
582 ExpectStop();
583 EXPECT_CALL(
584 *this,
585 ResultCallbackTarget(ConnectionHealthChecker::kResultSuccess));
586 health_checker_->NextHealthCheckSample();
587 dispatcher_.DispatchPendingEvents();
588 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700589
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700590 EXPECT_CALL(*tcp_connection_, Start(_,_)).WillOnce(Return(true));
591 health_checker_->NextHealthCheckSample();
592 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700593
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700594 // This test assumes that there are at least 2 connection attempts left
595 // before ConnectionHealthChecker gives up.
596 EXPECT_CALL(*tcp_connection_, Start(_,_))
597 .WillOnce(Return(false))
598 .WillOnce(Return(true));
599 short num_connection_failures = health_checker_->num_connection_failures();
600 health_checker_->NextHealthCheckSample();
601 EXPECT_EQ(num_connection_failures + 1,
602 health_checker_->num_connection_failures());
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700603}
604
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700605TEST_F(ConnectionHealthCheckerTest, OnConnectionComplete) {
606 // Test that num_connection_attempts is incremented on failure when
607 // (1) Async Connection fails.
608 health_checker_->set_num_connection_failures(
609 MaxFailedConnectionAttempts() - 1);
610 ExpectStop();
611 EXPECT_CALL(
612 *this,
613 ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
614 health_checker_->OnConnectionComplete(false, -1);
615 dispatcher_.DispatchPendingEvents();
616 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700617
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700618 // (2) The connection state is garbled up.
619 health_checker_->set_num_connection_failures(
620 MaxFailedConnectionAttempts() - 1);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700621 ExpectGetSocketInfoReturns(
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700622 CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
623 EXPECT_CALL(*socket_, Close(kProxyFD));
624 ExpectStop();
625 EXPECT_CALL(
626 *this,
627 ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
628 health_checker_->OnConnectionComplete(true, kProxyFD);
629 dispatcher_.DispatchPendingEvents();
630 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700631
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700632 // (3) Send fails.
633 health_checker_->set_num_connection_failures(
634 MaxFailedConnectionAttempts() - 1);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700635 ExpectGetSocketInfoReturns(
636 CreateSocketInfoProxy(SocketInfo::kConnectionStateEstablished));
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700637 EXPECT_CALL(*socket_, Send(kProxyFD, _, Gt(0), _)).WillOnce(Return(-1));
638 EXPECT_CALL(*socket_, Error()).WillOnce(Return(kSocketError));
639 EXPECT_CALL(*socket_, Close(kProxyFD));
640 ExpectStop();
641 EXPECT_CALL(
642 *this,
643 ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
644 health_checker_->OnConnectionComplete(true, kProxyFD);
645 dispatcher_.DispatchPendingEvents();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700646}
647
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700648TEST_F(ConnectionHealthCheckerTest, VerifySentData) {
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700649 // (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();
Prathmesh Prabhu81404c62013-05-08 17:04:28 -0700702
703 // (4) Test that VerifySentData correctly polls the tcpinfo twice.
704 // We want to immediately dispatch posted tasks.
705 SetTCPStateUpdateWaitMilliseconds(0);
706 health_checker_->set_num_congested_queue_detected(
707 MinCongestedQueueAttempts() - 1);
708 health_checker_->set_num_tx_queue_polling_attempts(
709 MaxSentDataPollingAttempts() - 1);
710 health_checker_->set_old_transmit_queue_value(0);
711 ExpectGetSocketInfoReturns(
712 CreateSocketInfoProxy(SocketInfo::kConnectionStateEstablished,
713 SocketInfo::kTimerStateRetransmitTimerPending,
714 1));
715 ExpectGetSocketInfoReturns(
716 CreateSocketInfoProxy(SocketInfo::kConnectionStateEstablished,
717 SocketInfo::kTimerStateRetransmitTimerPending,
718 1));
719 EXPECT_CALL(*socket_, Close(kProxyFD));
720 ExpectStop();
721 EXPECT_CALL(
722 *this, ResultCallbackTarget(
723 ConnectionHealthChecker::kResultCongestedTxQueue))
724 .InSequence(seq_);
725 health_checker_->set_sock_fd(kProxyFD);
726 health_checker_->VerifySentData();
727 dispatcher_.DispatchPendingEvents();
728 dispatcher_.DispatchPendingEvents();
729 // Force an extra dispatch to make sure that VerifySentData did not poll an
730 // extra time. This dispatch should be a no-op.
731 dispatcher_.DispatchPendingEvents();
732 VerifyAndClearAllExpectations();
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700733}
734
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700735// Flow: Start() -> Start()
736// Expectation: Only one AsyncConnection is setup
737TEST_F(ConnectionHealthCheckerTest, StartStartSkipsSecond) {
738 EXPECT_CALL(*tcp_connection_, Start(_,_))
739 .WillOnce(Return(true));
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700740 EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(false));
741 EXPECT_CALL(remote_ips_, GetRandomIP())
742 .WillOnce(Return(StringToIPv4Address(kProxyIPAddressRemote)));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700743 health_checker_->Start();
744 health_checker_->Start();
745}
746
747// Precondition: size(|remote_ips_|) > 0
748// Flow: Start() -> Stop() before ConnectionComplete()
749// Expectation: No call to |result_callback|
750TEST_F(ConnectionHealthCheckerTest, StartStopNoCallback) {
751 EXPECT_CALL(*tcp_connection_, Start(_,_))
752 .WillOnce(Return(true));
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(_))
755 .Times(0);
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700756 EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(false));
757 EXPECT_CALL(remote_ips_, GetRandomIP())
758 .WillOnce(Return(StringToIPv4Address(kProxyIPAddressRemote)));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700759 health_checker_->Start();
760 health_checker_->Stop();
761}
762
763// Precondition: Empty remote_ips_
764// Flow: Start()
765// Expectation: call |result_callback| with kResultUnknown
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700766TEST_F(ConnectionHealthCheckerTest, StartImmediateFailure) {
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700767 EXPECT_CALL(remote_ips_, Empty()).WillOnce(Return(true));
768 EXPECT_CALL(*tcp_connection_, Stop());
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700769 EXPECT_CALL(*this, ResultCallbackTarget(
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700770 ConnectionHealthChecker::kResultUnknown));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700771 health_checker_->Start();
772 Mock::VerifyAndClearExpectations(this);
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700773 Mock::VerifyAndClearExpectations(&remote_ips_);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700774 Mock::VerifyAndClearExpectations(tcp_connection_);
775
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700776 EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(false));
777 EXPECT_CALL(remote_ips_, GetRandomIP())
778 .WillRepeatedly(Return(StringToIPv4Address(kProxyIPAddressRemote)));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700779 EXPECT_CALL(*tcp_connection_,
780 Start(IsSameIPAddress(StringToIPv4Address(kProxyIPAddressRemote)),
781 kProxyPortRemote))
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700782 .Times(MaxFailedConnectionAttempts())
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700783 .WillRepeatedly(Return(false));
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700784 EXPECT_CALL(*tcp_connection_, Stop());
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700785 EXPECT_CALL(*this, ResultCallbackTarget(
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700786 ConnectionHealthChecker::kResultConnectionFailure));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700787 health_checker_->Start();
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700788 dispatcher_.DispatchPendingEvents();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700789 Mock::VerifyAndClearExpectations(this);
790 Mock::VerifyAndClearExpectations(tcp_connection_);
791}
792
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700793} // namespace shill