blob: 0cf992683fa4889d1703ea933d50cf3dee2d22c0 [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 Prabhu81404c62013-05-08 17:04:28 -0700176 void SetTCPStateUpdateWaitMilliseconds(int new_wait) {
177 health_checker_->tcp_state_update_wait_milliseconds_ = new_wait;
178 }
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700179
180 // Mock Callbacks
181 MOCK_METHOD1(ResultCallbackTarget,
182 void(ConnectionHealthChecker::Result result));
183
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700184 // Helper methods
185 IPAddress StringToIPv4Address(const string &address_string) {
186 IPAddress ip_address(IPAddress::kFamilyIPv4);
187 EXPECT_TRUE(ip_address.SetAddressFromString(address_string));
188 return ip_address;
189 }
190 // Naming: CreateSocketInfo
191 // + (Proxy/Other) : TCP connection for proxy socket / some other
192 // socket.
193 // + arg1: Pass in any SocketInfo::ConnectionState you want.
194 // + arg2: Pass in any value of transmit_queue_value you want.
195 SocketInfo CreateSocketInfoOther() {
196 return SocketInfo(
197 SocketInfo::kConnectionStateUnknown,
198 StringToIPv4Address(kIPAddress_8_8_8_8),
199 0,
200 StringToIPv4Address(kProxyIPAddressRemote),
201 kProxyPortRemote,
202 0,
203 0,
204 SocketInfo::kTimerStateUnknown);
205 }
206 SocketInfo CreateSocketInfoProxy(SocketInfo::ConnectionState state) {
207 return SocketInfo(
208 state,
209 StringToIPv4Address(kProxyIPAddressLocal),
210 kProxyPortLocal,
211 StringToIPv4Address(kProxyIPAddressRemote),
212 kProxyPortRemote,
213 0,
214 0,
215 SocketInfo::kTimerStateUnknown);
216 }
217 SocketInfo CreateSocketInfoProxy(SocketInfo::ConnectionState state,
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700218 SocketInfo::TimerState timer_state,
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700219 uint64 transmit_queue_value) {
220 return SocketInfo(
221 state,
222 StringToIPv4Address(kProxyIPAddressLocal),
223 kProxyPortLocal,
224 StringToIPv4Address(kProxyIPAddressRemote),
225 kProxyPortRemote,
226 transmit_queue_value,
227 0,
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700228 timer_state);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700229 }
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700230
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700231
232 // Expectations
233 void ExpectReset() {
234 EXPECT_EQ(connection_.get(), health_checker_->connection_.get());
235 EXPECT_EQ(&dispatcher_, health_checker_->dispatcher_);
236 EXPECT_EQ(socket_, health_checker_->socket_.get());
237 EXPECT_FALSE(socket_ == NULL);
238 EXPECT_EQ(socket_info_reader_, health_checker_->socket_info_reader_.get());
239 EXPECT_FALSE(socket_info_reader_ == NULL);
240 EXPECT_FALSE(health_checker_->connection_complete_callback_.is_null());
241 EXPECT_EQ(tcp_connection_, health_checker_->tcp_connection_.get());
242 EXPECT_FALSE(tcp_connection_ == NULL);
243 EXPECT_FALSE(health_checker_->health_check_in_progress_);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700244 }
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700245
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700246 // Setup ConnectionHealthChecker::GetSocketInfo to return sock_info.
247 // This only works if GetSocketInfo is called with kProxyFD.
248 // If no matching sock_info is provided (Does not belong to proxy socket),
249 // GetSocketInfo will (correctly) return false.
250 void ExpectGetSocketInfoReturns(SocketInfo sock_info) {
251 vector<SocketInfo> info_list;
252 info_list.push_back(sock_info);
253 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
254 .InSequence(seq_)
255 .WillOnce(Invoke(this,
256 &ConnectionHealthCheckerTest::GetSockName));
257 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
258 .InSequence(seq_)
259 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
260 Return(true)));
261
262 }
263 void ExpectSuccessfulStart() {
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700264 EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(false));
265 EXPECT_CALL(remote_ips_, GetRandomIP())
266 .WillRepeatedly(Return(StringToIPv4Address(kProxyIPAddressRemote)));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700267 EXPECT_CALL(
268 *tcp_connection_,
269 Start(IsSameIPAddress(StringToIPv4Address(kProxyIPAddressRemote)),
270 kProxyPortRemote))
271 .InSequence(seq_)
272 .WillOnce(Return(true));
273 }
274 void ExpectRetry() {
275 EXPECT_CALL(*socket_, Close(kProxyFD))
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700276 .InSequence(seq_);
277 EXPECT_CALL(
278 *tcp_connection_,
279 Start(IsSameIPAddress(StringToIPv4Address(kProxyIPAddressRemote)),
280 kProxyPortRemote))
281 .InSequence(seq_)
282 .WillOnce(Return(true));
283 }
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700284 void ExpectStop() {
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700285 if (tcp_connection_)
286 EXPECT_CALL(*tcp_connection_, Stop())
287 .InSequence(seq_);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700288 }
289 void ExpectCleanUp() {
290 EXPECT_CALL(*socket_, Close(kProxyFD))
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700291 .InSequence(seq_);
292 EXPECT_CALL(*tcp_connection_, Stop())
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700293 .InSequence(seq_);
294 }
295
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700296 void VerifyAndClearAllExpectations() {
297 Mock::VerifyAndClearExpectations(this);
298 Mock::VerifyAndClearExpectations(tcp_connection_);
299 Mock::VerifyAndClearExpectations(socket_);
300 Mock::VerifyAndClearExpectations(socket_info_reader_);
301 }
302
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700303 // Needed for other mocks, but not for the tests directly.
304 const string interface_name_;
305 NiceMock<MockControl> control_;
306 NiceMock<MockDeviceInfo> device_info_;
307 vector<string> dns_servers_;
308
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700309 scoped_refptr<NiceMock<MockConnection> > connection_;
310 EventDispatcher dispatcher_;
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700311 MockIPAddressStore remote_ips_;
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700312 StrictMock<MockSockets> *socket_;
313 StrictMock<MockSocketInfoReader> *socket_info_reader_;
314 StrictMock<MockAsyncConnection> *tcp_connection_;
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700315 // Expectations in the Expect* functions are put in this sequence.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700316 // This allows us to chain calls to Expect* functions.
317 Sequence seq_;
318
319 scoped_ptr<ConnectionHealthChecker> health_checker_;
320};
321
322TEST_F(ConnectionHealthCheckerTest, Constructor) {
323 ExpectReset();
324}
325
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700326TEST_F(ConnectionHealthCheckerTest, SetConnection) {
327 scoped_refptr<NiceMock<MockConnection> > new_connection
328 = new NiceMock<MockConnection>(&device_info_);
329 // If a health check was in progress when SetConnection is called, verify
330 // that it restarts with the new connection.
331 ExpectSuccessfulStart();
332 health_checker_->Start();
333 VerifyAndClearAllExpectations();
Paul Stewart41a071e2013-04-26 07:56:04 -0700334
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700335 EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(true));
336 EXPECT_CALL(*new_connection.get(), interface_name())
337 .WillRepeatedly(ReturnRef(interface_name_));
338 EXPECT_CALL(*this,
339 ResultCallbackTarget(ConnectionHealthChecker::kResultUnknown));
340 health_checker_->SetConnection(new_connection);
341 EXPECT_NE(tcp_connection_, health_checker_->tcp_connection());
342 EXPECT_EQ(new_connection.get(), health_checker_->connection());
Paul Stewart41a071e2013-04-26 07:56:04 -0700343
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700344 // health_checker_ has reset tcp_connection_ to a new object.
345 // Since it owned tcp_connection_, the object has been destroyed.
346 tcp_connection_ = NULL;
Paul Stewart41a071e2013-04-26 07:56:04 -0700347}
348
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700349TEST_F(ConnectionHealthCheckerTest, GarbageCollectDNSClients) {
350 dns_clients().clear();
351 health_checker_->GarbageCollectDNSClients();
352 EXPECT_TRUE(dns_clients().empty());
353
354 for (int i = 0; i < 3; ++i) {
355 MockDNSClient *dns_client = new MockDNSClient();
356 EXPECT_CALL(*dns_client, IsActive())
357 .WillOnce(Return(true))
358 .WillOnce(Return(true))
359 .WillOnce(Return(false));
360 // Takes ownership.
361 dns_clients().push_back(dns_client);
362 }
363 for (int i = 0; i < 2; ++i) {
364 MockDNSClient *dns_client = new MockDNSClient();
365 EXPECT_CALL(*dns_client, IsActive())
366 .WillOnce(Return(false));
367 // Takes ownership.
368 dns_clients().push_back(dns_client);
369 }
370
371 EXPECT_EQ(5, dns_clients().size());
372 health_checker_->GarbageCollectDNSClients();
373 EXPECT_EQ(3, dns_clients().size());
374 health_checker_->GarbageCollectDNSClients();
375 EXPECT_EQ(3, dns_clients().size());
376 health_checker_->GarbageCollectDNSClients();
377 EXPECT_TRUE(dns_clients().empty());
378}
379
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700380TEST_F(ConnectionHealthCheckerTest, AddRemoteURL) {
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700381 HTTPURL url;
382 url.ParseFromString(kProxyURLRemote);
383 string host = url.host();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700384 IPAddress remote_ip = StringToIPv4Address(kProxyIPAddressRemote);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700385 IPAddress remote_ip_2 = StringToIPv4Address(kIPAddress_8_8_8_8);
386
387 MockDNSClientFactory *dns_client_factory
388 = MockDNSClientFactory::GetInstance();
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700389 vector<MockDNSClient *> dns_client_buffer;
390
391 // All DNS queries fail.
392 for (int i = 0; i < NumDNSQueries(); ++i) {
393 MockDNSClient *dns_client = new MockDNSClient();
394 EXPECT_CALL(*dns_client, Start(host, _))
395 .WillOnce(Return(false));
396 dns_client_buffer.push_back(dns_client);
397 }
398 // Will pass ownership of dns_clients elements.
399 for (int i = 0; i < NumDNSQueries(); ++i) {
400 EXPECT_CALL(*dns_client_factory, CreateDNSClient(_,_,_,_,_,_))
401 .InSequence(seq_)
402 .WillOnce(Return(dns_client_buffer[i]));
403 }
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700404 EXPECT_CALL(remote_ips_, AddUnique(_)).Times(0);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700405 health_checker_->AddRemoteURL(kProxyURLRemote);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700406 Mock::VerifyAndClearExpectations(dns_client_factory);
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700407 Mock::VerifyAndClearExpectations(&remote_ips_);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700408 dns_client_buffer.clear();
409 dns_clients().clear();
410
411 // All but one DNS queries fail, 1 succeeds.
412 for (int i = 0; i < NumDNSQueries(); ++i) {
413 MockDNSClient *dns_client = new MockDNSClient();
414 EXPECT_CALL(*dns_client, Start(host, _))
415 .WillOnce(Return(true));
416 dns_client_buffer.push_back(dns_client);
417 }
418 // Will pass ownership of dns_clients elements.
419 for (int i = 0; i < NumDNSQueries(); ++i) {
420 EXPECT_CALL(*dns_client_factory, CreateDNSClient(_,_,_,_,_,_))
421 .InSequence(seq_)
422 .WillOnce(Return(dns_client_buffer[i]));
423 }
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700424 EXPECT_CALL(remote_ips_, AddUnique(_));
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700425 health_checker_->AddRemoteURL(kProxyURLRemote);
426 for(int i = 0; i < NumDNSQueries() - 1; ++i) {
427 InvokeGetDNSResultFailure();
428 }
429 InvokeGetDNSResultSuccess(remote_ip);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700430 Mock::VerifyAndClearExpectations(dns_client_factory);
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700431 Mock::VerifyAndClearExpectations(&remote_ips_);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700432 dns_client_buffer.clear();
433 dns_clients().clear();
434
435 // Only 2 distinct IP addresses are returned.
436 for (int i = 0; i < NumDNSQueries(); ++i) {
437 MockDNSClient *dns_client = new MockDNSClient();
438 EXPECT_CALL(*dns_client, Start(host, _))
439 .WillOnce(Return(true));
440 dns_client_buffer.push_back(dns_client);
441 }
442 // Will pass ownership of dns_clients elements.
443 for (int i = 0; i < NumDNSQueries(); ++i) {
444 EXPECT_CALL(*dns_client_factory, CreateDNSClient(_,_,_,_,_,_))
445 .InSequence(seq_)
446 .WillOnce(Return(dns_client_buffer[i]));
447 }
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700448 EXPECT_CALL(remote_ips_, AddUnique(IsSameIPAddress(remote_ip))).Times(4);
449 EXPECT_CALL(remote_ips_, AddUnique(IsSameIPAddress(remote_ip_2)));
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700450 health_checker_->AddRemoteURL(kProxyURLRemote);
451 for (int i = 0; i < NumDNSQueries() - 1; ++i) {
452 InvokeGetDNSResultSuccess(remote_ip);
453 }
454 InvokeGetDNSResultSuccess(remote_ip_2);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700455 Mock::VerifyAndClearExpectations(dns_client_factory);
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700456 Mock::VerifyAndClearExpectations(&remote_ips_);
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700457 dns_client_buffer.clear();
458 dns_clients().clear();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700459}
460
461TEST_F(ConnectionHealthCheckerTest, GetSocketInfo) {
462 SocketInfo sock_info;
463 vector<SocketInfo> info_list;
464
465 // GetSockName fails.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700466 EXPECT_CALL(*socket_, GetSockName(_,_,_))
467 .WillOnce(Return(-1));
468 EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
469 Mock::VerifyAndClearExpectations(socket_);
470
471 // GetSockName returns IPv6.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700472 EXPECT_CALL(*socket_, GetSockName(_,_,_))
473 .WillOnce(
474 Invoke(this,
475 &ConnectionHealthCheckerTest::GetSockNameReturnsIPv6));
476 EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
477 Mock::VerifyAndClearExpectations(socket_);
478
479 // LoadTcpSocketInfo fails.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700480 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
481 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
482 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
483 .WillOnce(Return(false));
484 EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
485 Mock::VerifyAndClearExpectations(socket_);
486 Mock::VerifyAndClearExpectations(socket_info_reader_);
487
488 // LoadTcpSocketInfo returns empty list.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700489 info_list.clear();
490 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
491 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
492 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
493 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
494 Return(true)));
495 EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
496 Mock::VerifyAndClearExpectations(socket_);
497 Mock::VerifyAndClearExpectations(socket_info_reader_);
498
499 // LoadTcpSocketInfo returns a list without our socket.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700500 info_list.clear();
501 info_list.push_back(CreateSocketInfoOther());
502 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
503 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
504 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
505 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
506 Return(true)));
507 EXPECT_FALSE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
508 Mock::VerifyAndClearExpectations(socket_);
509 Mock::VerifyAndClearExpectations(socket_info_reader_);
510
511 // LoadTcpSocketInfo returns a list with only our socket.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700512 info_list.clear();
513 info_list.push_back(
514 CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
515 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
516 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
517 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
518 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
519 Return(true)));
520 EXPECT_TRUE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
521 EXPECT_TRUE(CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown)
522 .IsSameSocketAs(sock_info));
523 Mock::VerifyAndClearExpectations(socket_);
524 Mock::VerifyAndClearExpectations(socket_info_reader_);
525
526 // LoadTcpSocketInfo returns a list with two sockets, including ours.
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700527 info_list.clear();
528 info_list.push_back(CreateSocketInfoOther());
529 info_list.push_back(
530 CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
531 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
532 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
533 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
534 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
535 Return(true)));
536 EXPECT_TRUE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
537 EXPECT_TRUE(CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown)
538 .IsSameSocketAs(sock_info));
539 Mock::VerifyAndClearExpectations(socket_);
540 Mock::VerifyAndClearExpectations(socket_info_reader_);
541
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700542 info_list.clear();
543 info_list.push_back(
544 CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
545 info_list.push_back(CreateSocketInfoOther());
546 EXPECT_CALL(*socket_, GetSockName(kProxyFD, _, _))
547 .WillOnce(Invoke(this, &ConnectionHealthCheckerTest::GetSockName));
548 EXPECT_CALL(*socket_info_reader_, LoadTcpSocketInfo(_))
549 .WillOnce(DoAll(SetArgumentPointee<0>(info_list),
550 Return(true)));
551 EXPECT_TRUE(health_checker_->GetSocketInfo(kProxyFD, &sock_info));
552 EXPECT_TRUE(CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown)
553 .IsSameSocketAs(sock_info));
554 Mock::VerifyAndClearExpectations(socket_);
555 Mock::VerifyAndClearExpectations(socket_info_reader_);
556}
557
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700558TEST_F(ConnectionHealthCheckerTest, NextHealthCheckSample) {
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700559 IPAddress ip = StringToIPv4Address(kProxyIPAddressRemote);
560 ON_CALL(remote_ips_, GetRandomIP())
561 .WillByDefault(Return(ip));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700562
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700563 health_checker_->set_num_connection_failures(MaxFailedConnectionAttempts());
564 ExpectStop();
565 EXPECT_CALL(
566 *this,
567 ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
568 health_checker_->NextHealthCheckSample();
569 dispatcher_.DispatchPendingEvents();
570 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700571
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700572 health_checker_->set_num_congested_queue_detected(
573 MinCongestedQueueAttempts());
574 ExpectStop();
575 EXPECT_CALL(
576 *this,
577 ResultCallbackTarget(ConnectionHealthChecker::kResultCongestedTxQueue));
578 health_checker_->NextHealthCheckSample();
579 dispatcher_.DispatchPendingEvents();
580 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700581
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700582 health_checker_->set_num_successful_sends(MinSuccessfulSendAttempts());
583 ExpectStop();
584 EXPECT_CALL(
585 *this,
586 ResultCallbackTarget(ConnectionHealthChecker::kResultSuccess));
587 health_checker_->NextHealthCheckSample();
588 dispatcher_.DispatchPendingEvents();
589 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700590
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700591 EXPECT_CALL(*tcp_connection_, Start(_,_)).WillOnce(Return(true));
592 health_checker_->NextHealthCheckSample();
593 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700594
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700595 // This test assumes that there are at least 2 connection attempts left
596 // before ConnectionHealthChecker gives up.
597 EXPECT_CALL(*tcp_connection_, Start(_,_))
598 .WillOnce(Return(false))
599 .WillOnce(Return(true));
600 short num_connection_failures = health_checker_->num_connection_failures();
601 health_checker_->NextHealthCheckSample();
602 EXPECT_EQ(num_connection_failures + 1,
603 health_checker_->num_connection_failures());
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700604}
605
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700606TEST_F(ConnectionHealthCheckerTest, OnConnectionComplete) {
607 // Test that num_connection_attempts is incremented on failure when
608 // (1) Async Connection fails.
609 health_checker_->set_num_connection_failures(
610 MaxFailedConnectionAttempts() - 1);
611 ExpectStop();
612 EXPECT_CALL(
613 *this,
614 ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
615 health_checker_->OnConnectionComplete(false, -1);
616 dispatcher_.DispatchPendingEvents();
617 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700618
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700619 // (2) The connection state is garbled up.
620 health_checker_->set_num_connection_failures(
621 MaxFailedConnectionAttempts() - 1);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700622 ExpectGetSocketInfoReturns(
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700623 CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
624 EXPECT_CALL(*socket_, Close(kProxyFD));
625 ExpectStop();
626 EXPECT_CALL(
627 *this,
628 ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
629 health_checker_->OnConnectionComplete(true, kProxyFD);
630 dispatcher_.DispatchPendingEvents();
631 VerifyAndClearAllExpectations();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700632
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700633 // (3) Send fails.
634 health_checker_->set_num_connection_failures(
635 MaxFailedConnectionAttempts() - 1);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700636 ExpectGetSocketInfoReturns(
637 CreateSocketInfoProxy(SocketInfo::kConnectionStateEstablished));
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700638 EXPECT_CALL(*socket_, Send(kProxyFD, _, Gt(0), _)).WillOnce(Return(-1));
639 EXPECT_CALL(*socket_, Error()).WillOnce(Return(kSocketError));
640 EXPECT_CALL(*socket_, Close(kProxyFD));
641 ExpectStop();
642 EXPECT_CALL(
643 *this,
644 ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
645 health_checker_->OnConnectionComplete(true, kProxyFD);
646 dispatcher_.DispatchPendingEvents();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700647}
648
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700649TEST_F(ConnectionHealthCheckerTest, VerifySentData) {
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700650 // (1) Test that num_connection_attempts is incremented when the connection
651 // state is garbled up.
652 health_checker_->set_num_connection_failures(
653 MaxFailedConnectionAttempts() - 1);
654 ExpectGetSocketInfoReturns(
655 CreateSocketInfoProxy(SocketInfo::kConnectionStateUnknown));
656 EXPECT_CALL(*socket_, Close(kProxyFD));
657 ExpectStop();
658 EXPECT_CALL(
659 *this,
660 ResultCallbackTarget(ConnectionHealthChecker::kResultConnectionFailure));
661 health_checker_->set_sock_fd(kProxyFD);
662 health_checker_->VerifySentData();
663 dispatcher_.DispatchPendingEvents();
664 VerifyAndClearAllExpectations();
665
666 // (2) Test that num_congested_queue_detected is incremented when all polling
667 // attempts have expired.
668 health_checker_->set_num_congested_queue_detected(
669 MinCongestedQueueAttempts() - 1);
670 health_checker_->set_num_tx_queue_polling_attempts(
671 MaxSentDataPollingAttempts());
672 health_checker_->set_old_transmit_queue_value(0);
673 ExpectGetSocketInfoReturns(
674 CreateSocketInfoProxy(SocketInfo::kConnectionStateEstablished,
675 SocketInfo::kTimerStateRetransmitTimerPending,
676 1));
677 EXPECT_CALL(*socket_, Close(kProxyFD));
678 ExpectStop();
679 EXPECT_CALL(
680 *this,
681 ResultCallbackTarget(ConnectionHealthChecker::kResultCongestedTxQueue));
682 health_checker_->set_sock_fd(kProxyFD);
683 health_checker_->VerifySentData();
684 dispatcher_.DispatchPendingEvents();
685 VerifyAndClearAllExpectations();
686
687 // (3) Test that num_successful_sends is incremented if everything goes fine.
688 health_checker_->set_num_successful_sends(MinSuccessfulSendAttempts() - 1);
689 health_checker_->set_old_transmit_queue_value(0);
690 ExpectGetSocketInfoReturns(
691 CreateSocketInfoProxy(SocketInfo::kConnectionStateEstablished,
692 SocketInfo::kTimerStateNoTimerPending,
693 0));
694 EXPECT_CALL(*socket_, Close(kProxyFD));
695 ExpectStop();
696 EXPECT_CALL(
697 *this,
698 ResultCallbackTarget(ConnectionHealthChecker::kResultSuccess));
699 health_checker_->set_sock_fd(kProxyFD);
700 health_checker_->VerifySentData();
701 dispatcher_.DispatchPendingEvents();
702 VerifyAndClearAllExpectations();
Prathmesh Prabhu81404c62013-05-08 17:04:28 -0700703
704 // (4) Test that VerifySentData correctly polls the tcpinfo twice.
705 // We want to immediately dispatch posted tasks.
706 SetTCPStateUpdateWaitMilliseconds(0);
707 health_checker_->set_num_congested_queue_detected(
708 MinCongestedQueueAttempts() - 1);
709 health_checker_->set_num_tx_queue_polling_attempts(
710 MaxSentDataPollingAttempts() - 1);
711 health_checker_->set_old_transmit_queue_value(0);
712 ExpectGetSocketInfoReturns(
713 CreateSocketInfoProxy(SocketInfo::kConnectionStateEstablished,
714 SocketInfo::kTimerStateRetransmitTimerPending,
715 1));
716 ExpectGetSocketInfoReturns(
717 CreateSocketInfoProxy(SocketInfo::kConnectionStateEstablished,
718 SocketInfo::kTimerStateRetransmitTimerPending,
719 1));
720 EXPECT_CALL(*socket_, Close(kProxyFD));
721 ExpectStop();
722 EXPECT_CALL(
723 *this, ResultCallbackTarget(
724 ConnectionHealthChecker::kResultCongestedTxQueue))
725 .InSequence(seq_);
726 health_checker_->set_sock_fd(kProxyFD);
727 health_checker_->VerifySentData();
728 dispatcher_.DispatchPendingEvents();
729 dispatcher_.DispatchPendingEvents();
730 // Force an extra dispatch to make sure that VerifySentData did not poll an
731 // extra time. This dispatch should be a no-op.
732 dispatcher_.DispatchPendingEvents();
733 VerifyAndClearAllExpectations();
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700734}
735
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700736// Flow: Start() -> Start()
737// Expectation: Only one AsyncConnection is setup
738TEST_F(ConnectionHealthCheckerTest, StartStartSkipsSecond) {
739 EXPECT_CALL(*tcp_connection_, Start(_,_))
740 .WillOnce(Return(true));
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700741 EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(false));
742 EXPECT_CALL(remote_ips_, GetRandomIP())
743 .WillOnce(Return(StringToIPv4Address(kProxyIPAddressRemote)));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700744 health_checker_->Start();
745 health_checker_->Start();
746}
747
748// Precondition: size(|remote_ips_|) > 0
749// Flow: Start() -> Stop() before ConnectionComplete()
750// Expectation: No call to |result_callback|
751TEST_F(ConnectionHealthCheckerTest, StartStopNoCallback) {
752 EXPECT_CALL(*tcp_connection_, Start(_,_))
753 .WillOnce(Return(true));
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700754 EXPECT_CALL(*tcp_connection_, Stop());
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700755 EXPECT_CALL(*this, ResultCallbackTarget(_))
756 .Times(0);
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700757 EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(false));
758 EXPECT_CALL(remote_ips_, GetRandomIP())
759 .WillOnce(Return(StringToIPv4Address(kProxyIPAddressRemote)));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700760 health_checker_->Start();
761 health_checker_->Stop();
762}
763
764// Precondition: Empty remote_ips_
765// Flow: Start()
766// Expectation: call |result_callback| with kResultUnknown
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700767TEST_F(ConnectionHealthCheckerTest, StartImmediateFailure) {
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700768 EXPECT_CALL(remote_ips_, Empty()).WillOnce(Return(true));
769 EXPECT_CALL(*tcp_connection_, Stop());
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700770 EXPECT_CALL(*this, ResultCallbackTarget(
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700771 ConnectionHealthChecker::kResultUnknown));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700772 health_checker_->Start();
773 Mock::VerifyAndClearExpectations(this);
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700774 Mock::VerifyAndClearExpectations(&remote_ips_);
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700775 Mock::VerifyAndClearExpectations(tcp_connection_);
776
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700777 EXPECT_CALL(remote_ips_, Empty()).WillRepeatedly(Return(false));
778 EXPECT_CALL(remote_ips_, GetRandomIP())
779 .WillRepeatedly(Return(StringToIPv4Address(kProxyIPAddressRemote)));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700780 EXPECT_CALL(*tcp_connection_,
781 Start(IsSameIPAddress(StringToIPv4Address(kProxyIPAddressRemote)),
782 kProxyPortRemote))
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700783 .Times(MaxFailedConnectionAttempts())
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700784 .WillRepeatedly(Return(false));
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700785 EXPECT_CALL(*tcp_connection_, Stop());
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700786 EXPECT_CALL(*this, ResultCallbackTarget(
Prathmesh Prabhuba99b592013-04-17 15:13:14 -0700787 ConnectionHealthChecker::kResultConnectionFailure));
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700788 health_checker_->Start();
Prathmesh Prabhuade9b9a2013-04-22 18:01:19 -0700789 dispatcher_.DispatchPendingEvents();
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700790 Mock::VerifyAndClearExpectations(this);
791 Mock::VerifyAndClearExpectations(tcp_connection_);
792}
793
Prathmesh Prabhu40daa012013-04-03 10:35:03 -0700794} // namespace shill