blob: 337601e4ca02070f74652a1797c1bc23f5b0e65d [file] [log] [blame]
Thieu Le3426c8f2012-01-11 17:35:11 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Paul Stewartdd60e452011-08-08 11:38:36 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Paul Stewart9a908082011-08-31 12:18:48 -07005#include <arpa/inet.h>
6#include <linux/rtnetlink.h>
7
Paul Stewartc8f4bef2011-12-13 09:45:51 -08008#include <string>
Paul Stewart9a908082011-08-31 12:18:48 -07009#include <vector>
10
11#include <base/memory/scoped_ptr.h>
Paul Stewartdd60e452011-08-08 11:38:36 -070012#include <gtest/gtest.h>
13#include <gmock/gmock.h>
14
15#include "shill/connection.h"
Paul Stewartdd60e452011-08-08 11:38:36 -070016#include "shill/ipconfig.h"
Darin Petkov13e6d552012-05-09 14:22:23 +020017#include "shill/mock_connection.h"
Paul Stewartdd60e452011-08-08 11:38:36 -070018#include "shill/mock_control.h"
Paul Stewartc8f4bef2011-12-13 09:45:51 -080019#include "shill/mock_device.h"
Paul Stewart9a908082011-08-31 12:18:48 -070020#include "shill/mock_device_info.h"
Paul Stewartdd60e452011-08-08 11:38:36 -070021#include "shill/mock_resolver.h"
22#include "shill/mock_routing_table.h"
23#include "shill/mock_rtnl_handler.h"
24#include "shill/routing_table_entry.h"
25
Paul Stewartc8f4bef2011-12-13 09:45:51 -080026using std::string;
Paul Stewart9a908082011-08-31 12:18:48 -070027using std::vector;
Paul Stewartdd60e452011-08-08 11:38:36 -070028using testing::_;
Paul Stewarte78ec542012-06-08 18:28:50 -070029using testing::Mock;
Paul Stewartdd60e452011-08-08 11:38:36 -070030using testing::NiceMock;
31using testing::Return;
Paul Stewart4a6748d2012-07-17 14:31:36 -070032using testing::ReturnRef;
Paul Stewartdd60e452011-08-08 11:38:36 -070033using testing::StrictMock;
34using testing::Test;
35
36namespace shill {
37
38namespace {
39const char kTestDeviceName0[] = "netdev0";
40const int kTestDeviceInterfaceIndex0 = 123;
41const char kTestDeviceName1[] = "netdev1";
42const int kTestDeviceInterfaceIndex1 = 321;
43const char kIPAddress0[] = "192.168.1.1";
44const char kGatewayAddress0[] = "192.168.1.254";
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070045const char kGatewayAddress1[] = "192.168.2.254";
Paul Stewart9a908082011-08-31 12:18:48 -070046const char kBroadcastAddress0[] = "192.168.1.255";
Paul Stewartdd60e452011-08-08 11:38:36 -070047const char kNameServer0[] = "8.8.8.8";
48const char kNameServer1[] = "8.8.9.9";
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070049const int32 kPrefix0 = 24;
50const int32 kPrefix1 = 31;
Paul Stewartdd60e452011-08-08 11:38:36 -070051const char kSearchDomain0[] = "chromium.org";
52const char kSearchDomain1[] = "google.com";
Ben Chana6bfe872012-09-26 09:48:34 -070053} // namespace
Paul Stewartdd60e452011-08-08 11:38:36 -070054
55class ConnectionTest : public Test {
56 public:
57 ConnectionTest()
Paul Stewart9a908082011-08-31 12:18:48 -070058 : device_info_(new StrictMock<MockDeviceInfo>(
59 &control_,
60 static_cast<EventDispatcher*>(NULL),
Thieu Le3426c8f2012-01-11 17:35:11 -080061 static_cast<Metrics*>(NULL),
Paul Stewart9a908082011-08-31 12:18:48 -070062 static_cast<Manager*>(NULL))),
63 connection_(new Connection(
64 kTestDeviceInterfaceIndex0,
65 kTestDeviceName0,
Paul Stewarte00600e2012-03-16 07:08:00 -070066 Technology::kUnknown,
Paul Stewartbf667612012-06-29 14:49:54 -070067 device_info_.get(),
68 false)),
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070069 ipconfig_(new IPConfig(&control_, kTestDeviceName0)),
70 local_address_(IPAddress::kFamilyIPv4),
71 broadcast_address_(IPAddress::kFamilyIPv4),
72 gateway_address_(IPAddress::kFamilyIPv4),
73 default_address_(IPAddress::kFamilyIPv4) {}
Paul Stewartdd60e452011-08-08 11:38:36 -070074
75 virtual void SetUp() {
Paul Stewartc8f4bef2011-12-13 09:45:51 -080076 ReplaceSingletons(connection_);
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070077 properties_.address = kIPAddress0;
78 properties_.subnet_prefix = kPrefix0;
79 properties_.gateway = kGatewayAddress0;
80 properties_.broadcast_address = kBroadcastAddress0;
81 properties_.dns_servers.push_back(kNameServer0);
82 properties_.dns_servers.push_back(kNameServer1);
83 properties_.domain_search.push_back(kSearchDomain0);
84 properties_.domain_search.push_back(kSearchDomain1);
85 properties_.address_family = IPAddress::kFamilyIPv4;
86 UpdateProperties();
87 EXPECT_TRUE(local_address_.SetAddressFromString(kIPAddress0));
88 EXPECT_TRUE(broadcast_address_.SetAddressFromString(kBroadcastAddress0));
89 EXPECT_TRUE(gateway_address_.SetAddressFromString(kGatewayAddress0));
Paul Stewartdd60e452011-08-08 11:38:36 -070090 }
91
Paul Stewart9a908082011-08-31 12:18:48 -070092 virtual void TearDown() {
Darin Petkov13e6d552012-05-09 14:22:23 +020093 AddDestructorExpectations();
Paul Stewarte93b0382012-04-24 13:11:28 -070094 connection_ = NULL;
Paul Stewart9a908082011-08-31 12:18:48 -070095 }
96
Paul Stewartc8f4bef2011-12-13 09:45:51 -080097 void ReplaceSingletons(ConnectionRefPtr connection) {
98 connection->resolver_ = &resolver_;
99 connection->routing_table_ = &routing_table_;
100 connection->rtnl_handler_ = &rtnl_handler_;
101 }
102
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700103 void UpdateProperties() {
104 ipconfig_->UpdateProperties(properties_, true);
105 }
106
Paul Stewarte93b0382012-04-24 13:11:28 -0700107 bool PinHostRoute(ConnectionRefPtr connection,
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800108 const IPAddress trusted_ip,
109 const IPAddress gateway) {
110 return connection->PinHostRoute(trusted_ip, gateway);
Paul Stewarte93b0382012-04-24 13:11:28 -0700111 }
112
Paul Stewart4a6748d2012-07-17 14:31:36 -0700113 const IPAddress &GetLocalAddress(ConnectionRefPtr connection) {
114 return connection->local_;
115 }
116
117 const IPAddress &GetGatewayAddress(ConnectionRefPtr connection) {
118 return connection->gateway_;
119 }
120
121 bool GetHasBroadcastDomain(ConnectionRefPtr connection) {
122 return connection->has_broadcast_domain_;
123 }
124
Paul Stewart05a42c22012-08-02 16:47:21 -0700125 uint32 GetDefaultMetric() {
126 return Connection::kDefaultMetric;
127 }
128
129 uint32 GetNonDefaultMetricBase() {
130 return Connection::kNonDefaultMetricBase;
131 }
132
Paul Stewartdd60e452011-08-08 11:38:36 -0700133 protected:
Darin Petkov13e6d552012-05-09 14:22:23 +0200134 class DisconnectCallbackTarget {
135 public:
136 DisconnectCallbackTarget()
137 : callback_(base::Bind(&DisconnectCallbackTarget::CallTarget,
138 base::Unretained(this))) {}
139
140 MOCK_METHOD0(CallTarget, void());
141 const base::Closure &callback() { return callback_; }
142
143 private:
144 base::Closure callback_;
145 };
146
147 void AddDestructorExpectations() {
148 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
149 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex0));
150 EXPECT_CALL(*device_info_.get(),
151 FlushAddresses(kTestDeviceInterfaceIndex0));
152 }
153
154 // Returns a new test connection object. The caller usually needs to call
155 // AddDestructorExpectations before destroying the object.
156 ConnectionRefPtr GetNewConnection() {
157 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex0,
158 kTestDeviceName0,
159 Technology::kUnknown,
Paul Stewartbf667612012-06-29 14:49:54 -0700160 device_info_.get(),
161 false));
Darin Petkov13e6d552012-05-09 14:22:23 +0200162 ReplaceSingletons(connection);
163 return connection;
164 }
165
Paul Stewart9a908082011-08-31 12:18:48 -0700166 scoped_ptr<StrictMock<MockDeviceInfo> > device_info_;
Paul Stewartdd60e452011-08-08 11:38:36 -0700167 ConnectionRefPtr connection_;
168 MockControl control_;
169 IPConfigRefPtr ipconfig_;
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700170 IPConfig::Properties properties_;
171 IPAddress local_address_;
172 IPAddress broadcast_address_;
173 IPAddress gateway_address_;
174 IPAddress default_address_;
Paul Stewartdd60e452011-08-08 11:38:36 -0700175 StrictMock<MockResolver> resolver_;
176 StrictMock<MockRoutingTable> routing_table_;
177 StrictMock<MockRTNLHandler> rtnl_handler_;
178};
179
Darin Petkov13e6d552012-05-09 14:22:23 +0200180namespace {
Paul Stewartdd60e452011-08-08 11:38:36 -0700181
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700182MATCHER_P2(IsIPAddress, address, prefix, "") {
183 IPAddress match_address(address);
184 match_address.set_prefix(prefix);
185 return match_address.Equals(arg);
186}
187
Darin Petkov13e6d552012-05-09 14:22:23 +0200188MATCHER(IsNonNullCallback, "") {
189 return !arg.is_null();
190}
191
192} // namespace
193
194TEST_F(ConnectionTest, InitState) {
195 EXPECT_EQ(kTestDeviceInterfaceIndex0, connection_->interface_index_);
196 EXPECT_EQ(kTestDeviceName0, connection_->interface_name_);
197 EXPECT_FALSE(connection_->is_default());
198 EXPECT_FALSE(connection_->routing_request_count_);
199}
200
Paul Stewartdd60e452011-08-08 11:38:36 -0700201TEST_F(ConnectionTest, AddConfig) {
Paul Stewart05a42c22012-08-02 16:47:21 -0700202 EXPECT_CALL(*device_info_,
203 HasOtherAddress(kTestDeviceInterfaceIndex0,
204 IsIPAddress(local_address_, kPrefix0)))
205 .WillOnce(Return(false));
Paul Stewartdd60e452011-08-08 11:38:36 -0700206 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700207 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
208 IsIPAddress(local_address_, kPrefix0),
209 IsIPAddress(broadcast_address_, 0),
210 IsIPAddress(default_address_, 0)));
Paul Stewart7cfca042011-12-08 14:18:17 -0800211 EXPECT_CALL(routing_table_,
212 SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700213 IsIPAddress(gateway_address_, 0),
Paul Stewart05a42c22012-08-02 16:47:21 -0700214 GetNonDefaultMetricBase() +
Paul Stewart7cfca042011-12-08 14:18:17 -0800215 kTestDeviceInterfaceIndex0));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700216 EXPECT_CALL(routing_table_,
217 ConfigureRoutes(kTestDeviceInterfaceIndex0,
218 ipconfig_,
Paul Stewart05a42c22012-08-02 16:47:21 -0700219 GetDefaultMetric()));
Paul Stewartdd60e452011-08-08 11:38:36 -0700220 connection_->UpdateFromIPConfig(ipconfig_);
Paul Stewart4a6748d2012-07-17 14:31:36 -0700221 IPAddress test_local_address(local_address_);
222 test_local_address.set_prefix(kPrefix0);
223 EXPECT_TRUE(test_local_address.Equals(GetLocalAddress(connection_)));
224 EXPECT_TRUE(gateway_address_.Equals(GetGatewayAddress(connection_)));
225 EXPECT_TRUE(GetHasBroadcastDomain(connection_));
226
227 EXPECT_CALL(routing_table_,
228 CreateLinkRoute(kTestDeviceInterfaceIndex0,
229 IsIPAddress(local_address_, kPrefix0),
230 IsIPAddress(gateway_address_, 0)))
231 .WillOnce(Return(true))
232 .WillOnce(Return(false));
233 EXPECT_TRUE(connection_->CreateGatewayRoute());
234 EXPECT_FALSE(connection_->CreateGatewayRoute());
235 connection_->has_broadcast_domain_ = false;
236 EXPECT_FALSE(connection_->CreateGatewayRoute());
Paul Stewartdd60e452011-08-08 11:38:36 -0700237
238 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
Paul Stewart05a42c22012-08-02 16:47:21 -0700239 GetDefaultMetric()));
Paul Stewartdd60e452011-08-08 11:38:36 -0700240 EXPECT_CALL(resolver_, SetDNSFromLists(
241 ipconfig_->properties().dns_servers,
Paul Stewartbf667612012-06-29 14:49:54 -0700242 ipconfig_->properties().domain_search,
243 Resolver::kDefaultTimeout));
Paul Stewartdd60e452011-08-08 11:38:36 -0700244
Paul Stewartc681fa02012-03-02 19:40:04 -0800245 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
246 &control_,
247 reinterpret_cast<EventDispatcher *>(NULL),
248 reinterpret_cast<Metrics *>(NULL),
249 reinterpret_cast<Manager *>(NULL),
250 kTestDeviceName0,
251 string(),
252 kTestDeviceInterfaceIndex0));
253 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
254 .WillOnce(Return(device));
255 EXPECT_CALL(*device.get(), RequestPortalDetection())
256 .WillOnce(Return(true));
Paul Stewarte78ec542012-06-08 18:28:50 -0700257 EXPECT_CALL(routing_table_, FlushCache())
258 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800259 connection_->SetIsDefault(true);
Paul Stewarte78ec542012-06-08 18:28:50 -0700260 Mock::VerifyAndClearExpectations(&routing_table_);
Paul Stewartdd60e452011-08-08 11:38:36 -0700261 EXPECT_TRUE(connection_->is_default());
262
Paul Stewart7cfca042011-12-08 14:18:17 -0800263 EXPECT_CALL(routing_table_,
264 SetDefaultMetric(kTestDeviceInterfaceIndex0,
Paul Stewart05a42c22012-08-02 16:47:21 -0700265 GetNonDefaultMetricBase() +
Paul Stewart7cfca042011-12-08 14:18:17 -0800266 kTestDeviceInterfaceIndex0));
Paul Stewarte78ec542012-06-08 18:28:50 -0700267 EXPECT_CALL(routing_table_, FlushCache())
268 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800269 connection_->SetIsDefault(false);
Paul Stewartdd60e452011-08-08 11:38:36 -0700270 EXPECT_FALSE(connection_->is_default());
271}
272
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700273TEST_F(ConnectionTest, AddConfigWithPeer) {
274 const string kPeerAddress("192.168.1.222");
275 IPAddress peer_address(IPAddress::kFamilyIPv4);
276 EXPECT_TRUE(peer_address.SetAddressFromString(kPeerAddress));
277 properties_.peer_address = kPeerAddress;
278 properties_.gateway = string();
279 UpdateProperties();
Paul Stewart05a42c22012-08-02 16:47:21 -0700280 EXPECT_CALL(*device_info_,
281 HasOtherAddress(kTestDeviceInterfaceIndex0,
282 IsIPAddress(local_address_, kPrefix0)))
283 .WillOnce(Return(false));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700284 EXPECT_CALL(rtnl_handler_,
285 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
286 IsIPAddress(local_address_, kPrefix0),
287 IsIPAddress(broadcast_address_, 0),
288 IsIPAddress(peer_address, 0)));
289 EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _)).Times(0);
290 EXPECT_CALL(routing_table_,
291 ConfigureRoutes(kTestDeviceInterfaceIndex0,
292 ipconfig_,
Paul Stewart05a42c22012-08-02 16:47:21 -0700293 GetDefaultMetric()));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700294 connection_->UpdateFromIPConfig(ipconfig_);
Paul Stewart4a6748d2012-07-17 14:31:36 -0700295 EXPECT_FALSE(GetHasBroadcastDomain(connection_));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700296}
297
298TEST_F(ConnectionTest, AddConfigWithBrokenNetmask) {
299 // Assign a prefix that makes the gateway unreachable.
300 properties_.subnet_prefix = kPrefix1;
301 UpdateProperties();
302
303 // Connection should override with a prefix which will allow the
304 // gateway to be reachable.
Paul Stewart05a42c22012-08-02 16:47:21 -0700305 EXPECT_CALL(*device_info_,
306 HasOtherAddress(kTestDeviceInterfaceIndex0,
307 IsIPAddress(local_address_, kPrefix0)))
308 .WillOnce(Return(false));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700309 EXPECT_CALL(rtnl_handler_,
310 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
311 IsIPAddress(local_address_, kPrefix0),
312 IsIPAddress(broadcast_address_, 0),
313 IsIPAddress(default_address_, 0)));
314 EXPECT_CALL(routing_table_,
315 SetDefaultRoute(kTestDeviceInterfaceIndex0,
316 IsIPAddress(gateway_address_, 0),
Paul Stewart05a42c22012-08-02 16:47:21 -0700317 GetNonDefaultMetricBase() +
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700318 kTestDeviceInterfaceIndex0));
319 EXPECT_CALL(routing_table_,
320 ConfigureRoutes(kTestDeviceInterfaceIndex0,
321 ipconfig_,
Paul Stewart05a42c22012-08-02 16:47:21 -0700322 GetDefaultMetric()));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700323 connection_->UpdateFromIPConfig(ipconfig_);
324
325 // Assign a gateway address that violates the minimum plausible prefix
326 // the Connection can assign.
327 properties_.gateway = kGatewayAddress1;
328 UpdateProperties();
329
Paul Stewart49258292012-05-26 06:37:14 -0700330 IPAddress gateway_address1(IPAddress::kFamilyIPv4);
331 EXPECT_TRUE(gateway_address1.SetAddressFromString(kGatewayAddress1));
332 // Connection cannot override this prefix, so it will switch to a
333 // model where the peer address is set to the value of the gateway
334 // address.
Paul Stewart05a42c22012-08-02 16:47:21 -0700335 EXPECT_CALL(*device_info_,
336 HasOtherAddress(kTestDeviceInterfaceIndex0,
337 IsIPAddress(local_address_, kPrefix1)))
338 .WillOnce(Return(false));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700339 EXPECT_CALL(rtnl_handler_,
340 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
341 IsIPAddress(local_address_, kPrefix1),
342 IsIPAddress(broadcast_address_, 0),
Paul Stewart49258292012-05-26 06:37:14 -0700343 IsIPAddress(gateway_address1, 0)));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700344 EXPECT_CALL(routing_table_,
345 SetDefaultRoute(kTestDeviceInterfaceIndex0, _, _));
346 EXPECT_CALL(routing_table_,
347 ConfigureRoutes(kTestDeviceInterfaceIndex0, _, _));
348 connection_->UpdateFromIPConfig(ipconfig_);
349}
350
Paul Stewartdd60e452011-08-08 11:38:36 -0700351TEST_F(ConnectionTest, AddConfigReverse) {
352 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
Paul Stewart05a42c22012-08-02 16:47:21 -0700353 GetDefaultMetric()));
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800354 vector<string> empty_list;
Paul Stewartbf667612012-06-29 14:49:54 -0700355 EXPECT_CALL(resolver_, SetDNSFromLists(empty_list, empty_list,
356 Resolver::kDefaultTimeout));
Paul Stewartc681fa02012-03-02 19:40:04 -0800357 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
358 &control_,
359 reinterpret_cast<EventDispatcher *>(NULL),
360 reinterpret_cast<Metrics *>(NULL),
361 reinterpret_cast<Manager *>(NULL),
362 kTestDeviceName0,
363 string(),
364 kTestDeviceInterfaceIndex0));
365 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
366 .WillOnce(Return(device));
367 EXPECT_CALL(*device.get(), RequestPortalDetection())
368 .WillOnce(Return(true));
Paul Stewarte78ec542012-06-08 18:28:50 -0700369 EXPECT_CALL(routing_table_, FlushCache())
370 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800371 connection_->SetIsDefault(true);
Paul Stewarte78ec542012-06-08 18:28:50 -0700372 Mock::VerifyAndClearExpectations(&routing_table_);
Paul Stewartdd60e452011-08-08 11:38:36 -0700373
Paul Stewart05a42c22012-08-02 16:47:21 -0700374 EXPECT_CALL(*device_info_,
375 HasOtherAddress(kTestDeviceInterfaceIndex0,
376 IsIPAddress(local_address_, kPrefix0)))
377 .WillOnce(Return(false));
Paul Stewartdd60e452011-08-08 11:38:36 -0700378 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700379 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
380 IsIPAddress(local_address_, kPrefix0),
381 IsIPAddress(broadcast_address_, 0),
382 IsIPAddress(default_address_, 0)));
Paul Stewartdd60e452011-08-08 11:38:36 -0700383 EXPECT_CALL(routing_table_, SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700384 IsIPAddress(gateway_address_, 0),
Paul Stewart05a42c22012-08-02 16:47:21 -0700385 GetDefaultMetric()));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700386 EXPECT_CALL(routing_table_,
387 ConfigureRoutes(kTestDeviceInterfaceIndex0,
388 ipconfig_,
Paul Stewart05a42c22012-08-02 16:47:21 -0700389 GetDefaultMetric()));
Paul Stewart6f65c0b2012-09-11 14:57:32 -0700390 EXPECT_CALL(resolver_, SetDNSFromLists(ipconfig_->properties().dns_servers,
391 ipconfig_->properties().domain_search,
392 Resolver::kDefaultTimeout));
Paul Stewartdd60e452011-08-08 11:38:36 -0700393
394 connection_->UpdateFromIPConfig(ipconfig_);
395}
396
Paul Stewartbf667612012-06-29 14:49:54 -0700397TEST_F(ConnectionTest, AddConfigShortTimeout) {
398 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex0,
399 kTestDeviceName0,
400 Technology::kUnknown,
401 device_info_.get(),
402 true));
403 ReplaceSingletons(connection);
404 EXPECT_CALL(*device_info_, HasOtherAddress(_, _)).WillOnce(Return(false));
405 EXPECT_CALL(rtnl_handler_, AddInterfaceAddress(_, _, _, _))
406 .WillRepeatedly(Return(true));
407 EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _))
408 .WillRepeatedly(Return(true));
409 EXPECT_CALL(routing_table_, ConfigureRoutes(_, _, _))
410 .WillRepeatedly(Return(true));
411 connection->UpdateFromIPConfig(ipconfig_);
412 EXPECT_CALL(routing_table_, SetDefaultMetric(_, _));
413 EXPECT_CALL(resolver_, SetDNSFromLists(
414 ipconfig_->properties().dns_servers,
415 ipconfig_->properties().domain_search,
416 Resolver::kShortTimeout));
417 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
418 &control_,
419 reinterpret_cast<EventDispatcher *>(NULL),
420 reinterpret_cast<Metrics *>(NULL),
421 reinterpret_cast<Manager *>(NULL),
422 kTestDeviceName0,
423 string(),
424 kTestDeviceInterfaceIndex0));
425 EXPECT_CALL(*device_info_, GetDevice(_)).WillOnce(Return(device));
426 EXPECT_CALL(*device.get(), RequestPortalDetection()).WillOnce(Return(true));
427 EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
428 connection->SetIsDefault(true);
429 EXPECT_CALL(*device_info_, HasOtherAddress(_, _)).WillOnce(Return(false));
Paul Stewart6f65c0b2012-09-11 14:57:32 -0700430 EXPECT_CALL(resolver_, SetDNSFromLists(ipconfig_->properties().dns_servers,
431 ipconfig_->properties().domain_search,
432 Resolver::kShortTimeout));
Paul Stewartbf667612012-06-29 14:49:54 -0700433 connection->UpdateFromIPConfig(ipconfig_);
434 AddDestructorExpectations();
435}
436
Paul Stewart4d1868b2012-09-10 11:58:46 -0700437TEST_F(ConnectionTest, AddConfigWithDNSDomain) {
438 const string kDomainName("chromium.org");
439 properties_.domain_search.clear();
440 properties_.domain_name = kDomainName;
441 UpdateProperties();
442 EXPECT_CALL(*device_info_, HasOtherAddress(_, _))
443 .WillOnce(Return(false));
444 EXPECT_CALL(rtnl_handler_, AddInterfaceAddress(_, _, _, _));
445 EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _));
446 EXPECT_CALL(routing_table_, ConfigureRoutes(_, _, _));
447 connection_->UpdateFromIPConfig(ipconfig_);
448
449 EXPECT_CALL(routing_table_, SetDefaultMetric(_, _));
450 vector<string> domain_search_list;
451 domain_search_list.push_back(kDomainName + ".");
452 EXPECT_CALL(resolver_, SetDNSFromLists(_, domain_search_list, _));
453 DeviceRefPtr device;
454 EXPECT_CALL(*device_info_, GetDevice(_)).WillOnce(Return(device));
455 EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
456 connection_->SetIsDefault(true);
457}
458
Paul Stewart05a42c22012-08-02 16:47:21 -0700459TEST_F(ConnectionTest, HasOtherAddress) {
460 EXPECT_CALL(*device_info_,
461 HasOtherAddress(kTestDeviceInterfaceIndex0,
462 IsIPAddress(local_address_, kPrefix0)))
463 .WillOnce(Return(true));
464 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
465 EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex0));
466 EXPECT_CALL(rtnl_handler_,
467 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
468 IsIPAddress(local_address_, kPrefix0),
469 IsIPAddress(broadcast_address_, 0),
470 IsIPAddress(default_address_, 0)));
471 EXPECT_CALL(routing_table_,
472 SetDefaultRoute(kTestDeviceInterfaceIndex0,
473 IsIPAddress(gateway_address_, 0),
474 GetNonDefaultMetricBase() +
475 kTestDeviceInterfaceIndex0));
476 EXPECT_CALL(routing_table_,
477 ConfigureRoutes(kTestDeviceInterfaceIndex0,
478 ipconfig_,
479 GetDefaultMetric()));
480 connection_->UpdateFromIPConfig(ipconfig_);
481}
482
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800483TEST_F(ConnectionTest, RouteRequest) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200484 ConnectionRefPtr connection = GetNewConnection();
Paul Stewartf748a362012-03-07 12:01:20 -0800485 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
486 &control_,
487 reinterpret_cast<EventDispatcher *>(NULL),
488 reinterpret_cast<Metrics *>(NULL),
489 reinterpret_cast<Manager *>(NULL),
490 kTestDeviceName0,
491 string(),
492 kTestDeviceInterfaceIndex0));
493 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
494 .WillRepeatedly(Return(device));
495 EXPECT_CALL(*device.get(), DisableReversePathFilter()).Times(1);
496 connection->RequestRouting();
497 connection->RequestRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800498
Paul Stewartf748a362012-03-07 12:01:20 -0800499 // The first release should only decrement the reference counter.
500 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800501
Paul Stewartf748a362012-03-07 12:01:20 -0800502 // Another release will re-enable reverse-path filter.
503 EXPECT_CALL(*device.get(), EnableReversePathFilter());
504 EXPECT_CALL(routing_table_, FlushCache());
505 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800506
Paul Stewartf748a362012-03-07 12:01:20 -0800507 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200508 AddDestructorExpectations();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800509}
510
Paul Stewartdd60e452011-08-08 11:38:36 -0700511TEST_F(ConnectionTest, Destructor) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200512 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex1,
513 kTestDeviceName1,
514 Technology::kUnknown,
Paul Stewartbf667612012-06-29 14:49:54 -0700515 device_info_.get(),
516 false));
Darin Petkov13e6d552012-05-09 14:22:23 +0200517 connection->resolver_ = &resolver_;
518 connection->routing_table_ = &routing_table_;
519 connection->rtnl_handler_ = &rtnl_handler_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800520 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex1));
Paul Stewarte93b0382012-04-24 13:11:28 -0700521 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex1));
Paul Stewart9a908082011-08-31 12:18:48 -0700522 EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex1));
Darin Petkov13e6d552012-05-09 14:22:23 +0200523 connection = NULL;
Paul Stewartdd60e452011-08-08 11:38:36 -0700524}
525
Paul Stewartf748a362012-03-07 12:01:20 -0800526TEST_F(ConnectionTest, RequestHostRoute) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200527 ConnectionRefPtr connection = GetNewConnection();
Paul Stewartf748a362012-03-07 12:01:20 -0800528 IPAddress address(IPAddress::kFamilyIPv4);
529 ASSERT_TRUE(address.SetAddressFromString(kIPAddress0));
530 size_t prefix_len = address.GetLength() * 8;
Darin Petkov13e6d552012-05-09 14:22:23 +0200531 EXPECT_CALL(routing_table_,
532 RequestRouteToHost(IsIPAddress(address, prefix_len),
533 -1,
534 kTestDeviceInterfaceIndex0,
535 IsNonNullCallback()))
Paul Stewartf748a362012-03-07 12:01:20 -0800536 .WillOnce(Return(true));
537 EXPECT_TRUE(connection->RequestHostRoute(address));
538
539 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200540 AddDestructorExpectations();
Paul Stewarte93b0382012-04-24 13:11:28 -0700541}
542
Ben Chana0163122012-09-25 15:10:52 -0700543TEST_F(ConnectionTest, BlackholeIPv6) {
544 properties_.blackhole_ipv6 = true;
545 UpdateProperties();
546 EXPECT_CALL(*device_info_, HasOtherAddress(_, _))
547 .WillOnce(Return(false));
548 EXPECT_CALL(rtnl_handler_, AddInterfaceAddress(_, _, _, _));
549 EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _));
550 EXPECT_CALL(routing_table_, ConfigureRoutes(_, _, _));
551 EXPECT_CALL(routing_table_,
552 CreateBlackholeRoute(kTestDeviceInterfaceIndex0,
553 IPAddress::kFamilyIPv6,
554 Connection::kDefaultMetric))
555 .WillOnce(Return(true));
556 connection_->UpdateFromIPConfig(ipconfig_);
557}
558
Paul Stewarte93b0382012-04-24 13:11:28 -0700559TEST_F(ConnectionTest, PinHostRoute) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200560 ConnectionRefPtr connection = GetNewConnection();
Paul Stewarte93b0382012-04-24 13:11:28 -0700561
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800562 IPAddress gateway(IPAddress::kFamilyIPv4);
563 IPAddress trusted_ip(IPAddress::kFamilyIPv4);
Paul Stewarte93b0382012-04-24 13:11:28 -0700564
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800565 // Should fail because neither IP address is set.
566 EXPECT_FALSE(PinHostRoute(connection, trusted_ip, gateway));
Paul Stewarte93b0382012-04-24 13:11:28 -0700567
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800568 static const char kGateway[] = "10.242.2.13";
569 ASSERT_TRUE(gateway.SetAddressFromString(kGateway));
Paul Stewarte93b0382012-04-24 13:11:28 -0700570
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800571 // Should fail because trusted IP is not set.
572 EXPECT_FALSE(PinHostRoute(connection, trusted_ip, gateway));
Paul Stewarte93b0382012-04-24 13:11:28 -0700573
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800574 static const char kTrustedIP[] = "10.0.1.1";
575 ASSERT_TRUE(trusted_ip.SetAddressFromString(kTrustedIP));
576
577 // Should fail because gateway IP is not set.
578 EXPECT_FALSE(PinHostRoute(connection, trusted_ip,
579 IPAddress(gateway.family())));
580
581 size_t prefix_len = IPAddress::GetMaxPrefixLength(trusted_ip.family());
Paul Stewarte93b0382012-04-24 13:11:28 -0700582 EXPECT_CALL(routing_table_, RequestRouteToHost(
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800583 IsIPAddress(trusted_ip, prefix_len), -1, kTestDeviceInterfaceIndex0, _))
Paul Stewarte93b0382012-04-24 13:11:28 -0700584 .WillOnce(Return(false));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800585 EXPECT_FALSE(PinHostRoute(connection, trusted_ip, gateway));
Paul Stewarte93b0382012-04-24 13:11:28 -0700586
587 EXPECT_CALL(routing_table_, RequestRouteToHost(
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800588 IsIPAddress(trusted_ip, prefix_len), -1, kTestDeviceInterfaceIndex0, _))
Paul Stewarte93b0382012-04-24 13:11:28 -0700589 .WillOnce(Return(true));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800590 EXPECT_TRUE(PinHostRoute(connection, trusted_ip, gateway));
Paul Stewarte93b0382012-04-24 13:11:28 -0700591
592 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200593 AddDestructorExpectations();
Paul Stewartf748a362012-03-07 12:01:20 -0800594}
595
Paul Stewart53a30382012-04-26 09:06:59 -0700596TEST_F(ConnectionTest, FixGatewayReachability) {
597 static const char kLocal[] = "10.242.2.13";
598 IPAddress local(IPAddress::kFamilyIPv4);
599 ASSERT_TRUE(local.SetAddressFromString(kLocal));
600 const int kPrefix = 24;
601 local.set_prefix(kPrefix);
602 IPAddress gateway(IPAddress::kFamilyIPv4);
603 IPAddress peer(IPAddress::kFamilyIPv4);
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800604 IPAddress trusted_ip(IPAddress::kFamilyIPv4);
Paul Stewart53a30382012-04-26 09:06:59 -0700605
606 // Should fail because no gateway is set.
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800607 EXPECT_FALSE(Connection::FixGatewayReachability(
608 &local, &peer, &gateway, trusted_ip));
Paul Stewart53a30382012-04-26 09:06:59 -0700609 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700610 EXPECT_FALSE(peer.IsValid());
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800611 EXPECT_FALSE(gateway.IsValid());
Paul Stewart53a30382012-04-26 09:06:59 -0700612
613 // Should succeed because with the given prefix, this gateway is reachable.
614 static const char kReachableGateway[] = "10.242.2.14";
615 ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800616 IPAddress gateway_backup(gateway);
Paul Stewart49258292012-05-26 06:37:14 -0700617 peer = IPAddress(IPAddress::kFamilyIPv4);
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800618 EXPECT_TRUE(Connection::FixGatewayReachability(
619 &local, &peer, &gateway, trusted_ip));
Paul Stewart53a30382012-04-26 09:06:59 -0700620 // Prefix should remain unchanged.
621 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700622 // Peer should remain unchanged.
623 EXPECT_FALSE(peer.IsValid());
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800624 // Gateway should remain unchanged.
625 EXPECT_TRUE(gateway_backup.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700626
627 // Should succeed because we modified the prefix to match the gateway.
628 static const char kExpandableGateway[] = "10.242.3.14";
629 ASSERT_TRUE(gateway.SetAddressFromString(kExpandableGateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800630 gateway_backup = gateway;
Paul Stewart49258292012-05-26 06:37:14 -0700631 peer = IPAddress(IPAddress::kFamilyIPv4);
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800632 EXPECT_TRUE(Connection::FixGatewayReachability(
633 &local, &peer, &gateway, trusted_ip));
Paul Stewart53a30382012-04-26 09:06:59 -0700634 // Prefix should have opened up by 1 bit.
635 EXPECT_EQ(kPrefix - 1, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700636 // Peer should remain unchanged.
637 EXPECT_FALSE(peer.IsValid());
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800638 // Gateway should remain unchanged.
639 EXPECT_TRUE(gateway_backup.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700640
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700641 // Should change models to assuming point-to-point because we cannot
Paul Stewart49258292012-05-26 06:37:14 -0700642 // plausibly expand the prefix past 8.
Paul Stewart53a30382012-04-26 09:06:59 -0700643 local.set_prefix(kPrefix);
644 static const char kUnreachableGateway[] = "11.242.2.14";
645 ASSERT_TRUE(gateway.SetAddressFromString(kUnreachableGateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800646 gateway_backup = gateway;
Paul Stewart49258292012-05-26 06:37:14 -0700647 peer = IPAddress(IPAddress::kFamilyIPv4);
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800648 EXPECT_TRUE(Connection::FixGatewayReachability(
649 &local, &peer, &gateway, trusted_ip));
Paul Stewart53a30382012-04-26 09:06:59 -0700650 // Prefix should not have changed.
651 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700652 // Peer address should be set to the gateway address.
653 EXPECT_TRUE(peer.Equals(gateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800654 // Gateway should remain unchanged.
655 EXPECT_TRUE(gateway_backup.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700656
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700657 // Should also use point-to-point model if the netmask is set to the
658 // "all-ones" addresss, even if this address could have been made
659 // accessible by plausibly changing the prefix.
660 const int kIPv4MaxPrefix =
661 IPAddress::GetMaxPrefixLength(IPAddress::kFamilyIPv4);
662 local.set_prefix(kIPv4MaxPrefix);
663 ASSERT_TRUE(gateway.SetAddressFromString(kExpandableGateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800664 gateway_backup = gateway;
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700665 peer = IPAddress(IPAddress::kFamilyIPv4);
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800666 EXPECT_TRUE(Connection::FixGatewayReachability(
667 &local, &peer, &gateway, trusted_ip));
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700668 // Prefix should not have changed.
669 EXPECT_EQ(kIPv4MaxPrefix, local.prefix());
670 // Peer address should be set to the gateway address.
671 EXPECT_TRUE(peer.Equals(gateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800672 // Gateway should remain unchanged.
673 EXPECT_TRUE(gateway_backup.Equals(gateway));
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700674
Paul Stewart49258292012-05-26 06:37:14 -0700675 // If this is a peer-to-peer interface and the peer matches the gateway,
676 // we should succeed.
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700677 local.set_prefix(kPrefix);
678 ASSERT_TRUE(gateway.SetAddressFromString(kUnreachableGateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800679 gateway_backup = gateway;
Paul Stewart53a30382012-04-26 09:06:59 -0700680 ASSERT_TRUE(peer.SetAddressFromString(kUnreachableGateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800681 EXPECT_TRUE(Connection::FixGatewayReachability(
682 &local, &peer, &gateway, trusted_ip));
Paul Stewart53a30382012-04-26 09:06:59 -0700683 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700684 EXPECT_TRUE(peer.Equals(gateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800685 EXPECT_TRUE(gateway_backup.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700686
687 // If there is a peer specified and it does not match the gateway (even
688 // if it was reachable via netmask), we should fail.
689 ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800690 EXPECT_FALSE(Connection::FixGatewayReachability(
691 &local, &peer, &gateway, trusted_ip));
Paul Stewart53a30382012-04-26 09:06:59 -0700692 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700693 EXPECT_FALSE(peer.Equals(gateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800694
695 // If this is a peer-to-peer interface and the peer matches the gateway,
696 // but it also matches the trusted IP address, the gateway and peer address
697 // should be modified to allow routing to work correctly.
698 ASSERT_TRUE(gateway.SetAddressFromString(kUnreachableGateway));
699 ASSERT_TRUE(peer.SetAddressFromString(kUnreachableGateway));
700 ASSERT_TRUE(trusted_ip.SetAddressFromString(kUnreachableGateway));
701 EXPECT_TRUE(Connection::FixGatewayReachability(
702 &local, &peer, &gateway, trusted_ip));
703 EXPECT_TRUE(peer.IsDefault());
704 EXPECT_TRUE(gateway.IsDefault());
Paul Stewart53a30382012-04-26 09:06:59 -0700705}
706
Darin Petkov13e6d552012-05-09 14:22:23 +0200707TEST_F(ConnectionTest, Binders) {
708 EXPECT_TRUE(connection_->binders_.empty());
709 DisconnectCallbackTarget target0;
710 DisconnectCallbackTarget target1;
711 DisconnectCallbackTarget target2;
712 DisconnectCallbackTarget target3;
713 Connection::Binder binder0("binder0", target0.callback());
714 Connection::Binder binder1("binder1", target1.callback());
715 Connection::Binder binder2("binder2", target2.callback());
716 Connection::Binder binder3("binder3", target3.callback());
717
718 binder0.Attach(connection_);
719 binder1.Attach(connection_);
720
721 EXPECT_CALL(target1, CallTarget()).Times(0);
722 binder1.Attach(connection_);
723
724 binder3.Attach(connection_);
725 binder2.Attach(connection_);
726
727 EXPECT_CALL(target3, CallTarget()).Times(0);
728 binder3.Attach(NULL);
729
730 ASSERT_EQ(3, connection_->binders_.size());
731 EXPECT_TRUE(connection_->binders_.at(0) == &binder0);
732 EXPECT_TRUE(connection_->binders_.at(1) == &binder1);
733 EXPECT_TRUE(connection_->binders_.at(2) == &binder2);
734
735 EXPECT_CALL(target0, CallTarget()).Times(1);
736 EXPECT_CALL(target1, CallTarget()).Times(1);
737 EXPECT_CALL(target2, CallTarget()).Times(1);
738 connection_->NotifyBindersOnDisconnect();
739 EXPECT_TRUE(connection_->binders_.empty());
740
741 // Should be a no-op.
742 connection_->NotifyBindersOnDisconnect();
743}
744
745TEST_F(ConnectionTest, Binder) {
746 // No connection should be bound initially.
747 Connection::Binder *binder = &connection_->lower_binder_;
748 EXPECT_EQ(connection_->interface_name(), binder->name_);
749 EXPECT_FALSE(binder->client_disconnect_callback_.is_null());
750 EXPECT_FALSE(binder->IsBound());
751
752 ConnectionRefPtr connection1 = GetNewConnection();
753 EXPECT_TRUE(connection1->binders_.empty());
754
755 // Bind lower |connection1| and check if it's bound.
756 binder->Attach(connection1);
757 EXPECT_TRUE(binder->IsBound());
758 EXPECT_EQ(connection1.get(), binder->connection().get());
759 ASSERT_FALSE(connection1->binders_.empty());
760 EXPECT_TRUE(binder == connection1->binders_.at(0));
761
762 // Unbind lower |connection1| and check if it's unbound.
763 binder->Attach(NULL);
764 EXPECT_FALSE(binder->IsBound());
765 EXPECT_TRUE(connection1->binders_.empty());
766
767 ConnectionRefPtr connection2 = GetNewConnection();
768
769 // Bind lower |connection1| to upper |connection2| and destroy the upper
770 // |connection2|. Make sure lower |connection1| is unbound (i.e., the
771 // disconnect callback is deregistered).
772 connection2->lower_binder_.Attach(connection1);
773 EXPECT_FALSE(connection1->binders_.empty());
774 AddDestructorExpectations();
775 connection2 = NULL;
776 EXPECT_TRUE(connection1->binders_.empty());
777
778 // Bind lower |connection1| to upper |connection_| and destroy lower
779 // |connection1|. Make sure lower |connection1| is unbound from upper
780 // |connection_| and upper |connection_|'s registered disconnect callbacks are
781 // run.
782 binder->Attach(connection1);
783 DisconnectCallbackTarget target;
784 Connection::Binder test_binder("from_test", target.callback());
785 test_binder.Attach(connection_);
786 EXPECT_CALL(target, CallTarget()).Times(1);
787 ASSERT_FALSE(connection_->binders_.empty());
788 AddDestructorExpectations();
789 connection1 = NULL;
790 EXPECT_FALSE(binder->IsBound());
791 EXPECT_FALSE(test_binder.IsBound());
792 EXPECT_TRUE(connection_->binders_.empty());
793
794 {
795 // Binding a connection to itself should be safe.
796 ConnectionRefPtr connection = GetNewConnection();
797
798 connection->lower_binder_.Attach(connection);
799
800 EXPECT_FALSE(connection->binders_.empty());
801
802 DisconnectCallbackTarget target;
803 Connection::Binder binder("test", target.callback());
804 binder.Attach(connection);
805
806 AddDestructorExpectations();
807 EXPECT_CALL(target, CallTarget()).Times(1);
808 connection = NULL;
809 }
Darin Petkov13e6d552012-05-09 14:22:23 +0200810 {
811 // Circular binding of multiple connections should be safe.
812 ConnectionRefPtr connection_a = GetNewConnection();
813 ConnectionRefPtr connection_b = GetNewConnection();
814
815 connection_a->lower_binder_.Attach(connection_b);
816 connection_b->lower_binder_.Attach(connection_a);
817
818 EXPECT_FALSE(connection_a->binders_.empty());
819 EXPECT_FALSE(connection_b->binders_.empty());
820
821 DisconnectCallbackTarget target_a;
822 DisconnectCallbackTarget target_b;
823 Connection::Binder binder_a("test_a", target_a.callback());
824 Connection::Binder binder_b("test_b", target_b.callback());
825 binder_a.Attach(connection_a);
826 binder_b.Attach(connection_b);
827
828 AddDestructorExpectations();
829 EXPECT_CALL(target_a, CallTarget()).Times(1);
830 EXPECT_CALL(target_b, CallTarget()).Times(1);
831 connection_b = NULL;
832
833 EXPECT_TRUE(connection_a->binders_.empty());
834
835 AddDestructorExpectations();
836 connection_a = NULL;
837 }
Darin Petkovef1f9fe2012-05-11 16:51:52 +0200838 {
839 // Test the weak pointer to the bound Connection. This is not a case that
840 // should occur but the weak pointer should handle it gracefully.
841 DisconnectCallbackTarget target;
842 Connection::Binder binder("test_weak", target.callback());
843 ConnectionRefPtr connection = GetNewConnection();
844 binder.Attach(connection);
845
846 // Make sure the connection doesn't notify the binder on destruction.
847 connection->binders_.clear();
848 AddDestructorExpectations();
849 EXPECT_CALL(target, CallTarget()).Times(0);
850 connection = NULL;
851
852 // Ensure no crash -- the weak pointer to connection should be NULL.
Darin Petkov5eb05422012-05-11 15:45:25 +0200853 EXPECT_FALSE(binder.connection());
Darin Petkovef1f9fe2012-05-11 16:51:52 +0200854 binder.Attach(NULL);
855 }
Darin Petkov13e6d552012-05-09 14:22:23 +0200856}
857
858TEST_F(ConnectionTest, OnRouteQueryResponse) {
859 Connection::Binder *binder = &connection_->lower_binder_;
860 ConnectionRefPtr connection = GetNewConnection();
861 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
862 &control_,
863 reinterpret_cast<EventDispatcher *>(NULL),
864 reinterpret_cast<Metrics *>(NULL),
865 reinterpret_cast<Manager *>(NULL),
866 kTestDeviceName1,
867 string(),
868 kTestDeviceInterfaceIndex1));
869
870 // Make sure we unbind the old lower connection even if we can't lookup the
871 // lower connection device.
872 binder->Attach(connection);
873 scoped_refptr<MockDevice> null_device;
874 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
875 .WillOnce(Return(null_device));
876 connection_->OnRouteQueryResponse(
877 kTestDeviceInterfaceIndex1, RoutingTableEntry());
878 EXPECT_FALSE(binder->IsBound());
879
880 // Check for graceful handling of a device with no connection.
881 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
882 .WillOnce(Return(device));
883 connection_->OnRouteQueryResponse(
884 kTestDeviceInterfaceIndex1, RoutingTableEntry());
885 EXPECT_FALSE(binder->IsBound());
886
Paul Stewart4a6748d2012-07-17 14:31:36 -0700887 // Create a mock connection that will be used fo binding.
888 scoped_refptr<MockConnection> mock_connection(
889 new StrictMock<MockConnection>(device_info_.get()));
890 EXPECT_CALL(*device_info_.get(),
891 FlushAddresses(mock_connection->interface_index()));
892 const string kInterfaceName(kTestDeviceName0);
893 EXPECT_CALL(*mock_connection, interface_name())
894 .WillRepeatedly(ReturnRef(kInterfaceName));
895 device->connection_ = mock_connection;
Darin Petkov13e6d552012-05-09 14:22:23 +0200896 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
897 .WillOnce(Return(device));
Paul Stewart4a6748d2012-07-17 14:31:36 -0700898
Ben Chana6bfe872012-09-26 09:48:34 -0700899 // Check that the binding process completes, causing its upper
Paul Stewart4a6748d2012-07-17 14:31:36 -0700900 // connection to create a gateway route.
901 EXPECT_CALL(*mock_connection, CreateGatewayRoute())
902 .WillOnce(Return(true));
Paul Stewart8596f9f2013-03-14 07:58:26 -0700903
904 // Ensure that the Device is notified of the change to the connection.
905 EXPECT_CALL(*device, OnConnectionUpdated()).Times(1);
Darin Petkov13e6d552012-05-09 14:22:23 +0200906 connection_->OnRouteQueryResponse(
907 kTestDeviceInterfaceIndex1, RoutingTableEntry());
Paul Stewart4a6748d2012-07-17 14:31:36 -0700908
909 // Check that the upper connection is bound to the lower connection.
Darin Petkov13e6d552012-05-09 14:22:23 +0200910 EXPECT_TRUE(binder->IsBound());
Paul Stewart4a6748d2012-07-17 14:31:36 -0700911 EXPECT_EQ(mock_connection.get(), binder->connection().get());
Darin Petkov13e6d552012-05-09 14:22:23 +0200912
913 device->connection_ = NULL;
914 AddDestructorExpectations();
915 connection = NULL;
916}
917
Paul Stewartdd60e452011-08-08 11:38:36 -0700918} // namespace shill