blob: 5a6891118ade20be5d19e49ee3a1b350078d1e1c [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,
108 const IPConfig::Properties &properties) {
109 return connection->PinHostRoute(properties);
110 }
111
Paul Stewart4a6748d2012-07-17 14:31:36 -0700112 const IPAddress &GetLocalAddress(ConnectionRefPtr connection) {
113 return connection->local_;
114 }
115
116 const IPAddress &GetGatewayAddress(ConnectionRefPtr connection) {
117 return connection->gateway_;
118 }
119
120 bool GetHasBroadcastDomain(ConnectionRefPtr connection) {
121 return connection->has_broadcast_domain_;
122 }
123
Paul Stewart05a42c22012-08-02 16:47:21 -0700124 uint32 GetDefaultMetric() {
125 return Connection::kDefaultMetric;
126 }
127
128 uint32 GetNonDefaultMetricBase() {
129 return Connection::kNonDefaultMetricBase;
130 }
131
Paul Stewartdd60e452011-08-08 11:38:36 -0700132 protected:
Darin Petkov13e6d552012-05-09 14:22:23 +0200133 class DisconnectCallbackTarget {
134 public:
135 DisconnectCallbackTarget()
136 : callback_(base::Bind(&DisconnectCallbackTarget::CallTarget,
137 base::Unretained(this))) {}
138
139 MOCK_METHOD0(CallTarget, void());
140 const base::Closure &callback() { return callback_; }
141
142 private:
143 base::Closure callback_;
144 };
145
146 void AddDestructorExpectations() {
147 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
148 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex0));
149 EXPECT_CALL(*device_info_.get(),
150 FlushAddresses(kTestDeviceInterfaceIndex0));
151 }
152
153 // Returns a new test connection object. The caller usually needs to call
154 // AddDestructorExpectations before destroying the object.
155 ConnectionRefPtr GetNewConnection() {
156 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex0,
157 kTestDeviceName0,
158 Technology::kUnknown,
Paul Stewartbf667612012-06-29 14:49:54 -0700159 device_info_.get(),
160 false));
Darin Petkov13e6d552012-05-09 14:22:23 +0200161 ReplaceSingletons(connection);
162 return connection;
163 }
164
Paul Stewart9a908082011-08-31 12:18:48 -0700165 scoped_ptr<StrictMock<MockDeviceInfo> > device_info_;
Paul Stewartdd60e452011-08-08 11:38:36 -0700166 ConnectionRefPtr connection_;
167 MockControl control_;
168 IPConfigRefPtr ipconfig_;
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700169 IPConfig::Properties properties_;
170 IPAddress local_address_;
171 IPAddress broadcast_address_;
172 IPAddress gateway_address_;
173 IPAddress default_address_;
Paul Stewartdd60e452011-08-08 11:38:36 -0700174 StrictMock<MockResolver> resolver_;
175 StrictMock<MockRoutingTable> routing_table_;
176 StrictMock<MockRTNLHandler> rtnl_handler_;
177};
178
Darin Petkov13e6d552012-05-09 14:22:23 +0200179namespace {
Paul Stewartdd60e452011-08-08 11:38:36 -0700180
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700181MATCHER_P2(IsIPAddress, address, prefix, "") {
182 IPAddress match_address(address);
183 match_address.set_prefix(prefix);
184 return match_address.Equals(arg);
185}
186
Darin Petkov13e6d552012-05-09 14:22:23 +0200187MATCHER(IsNonNullCallback, "") {
188 return !arg.is_null();
189}
190
191} // namespace
192
193TEST_F(ConnectionTest, InitState) {
194 EXPECT_EQ(kTestDeviceInterfaceIndex0, connection_->interface_index_);
195 EXPECT_EQ(kTestDeviceName0, connection_->interface_name_);
196 EXPECT_FALSE(connection_->is_default());
197 EXPECT_FALSE(connection_->routing_request_count_);
198}
199
Paul Stewartdd60e452011-08-08 11:38:36 -0700200TEST_F(ConnectionTest, AddConfig) {
Paul Stewart05a42c22012-08-02 16:47:21 -0700201 EXPECT_CALL(*device_info_,
202 HasOtherAddress(kTestDeviceInterfaceIndex0,
203 IsIPAddress(local_address_, kPrefix0)))
204 .WillOnce(Return(false));
Paul Stewartdd60e452011-08-08 11:38:36 -0700205 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700206 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
207 IsIPAddress(local_address_, kPrefix0),
208 IsIPAddress(broadcast_address_, 0),
209 IsIPAddress(default_address_, 0)));
Paul Stewart7cfca042011-12-08 14:18:17 -0800210 EXPECT_CALL(routing_table_,
211 SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700212 IsIPAddress(gateway_address_, 0),
Paul Stewart05a42c22012-08-02 16:47:21 -0700213 GetNonDefaultMetricBase() +
Paul Stewart7cfca042011-12-08 14:18:17 -0800214 kTestDeviceInterfaceIndex0));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700215 EXPECT_CALL(routing_table_,
216 ConfigureRoutes(kTestDeviceInterfaceIndex0,
217 ipconfig_,
Paul Stewart05a42c22012-08-02 16:47:21 -0700218 GetDefaultMetric()));
Paul Stewartdd60e452011-08-08 11:38:36 -0700219 connection_->UpdateFromIPConfig(ipconfig_);
Paul Stewart4a6748d2012-07-17 14:31:36 -0700220 IPAddress test_local_address(local_address_);
221 test_local_address.set_prefix(kPrefix0);
222 EXPECT_TRUE(test_local_address.Equals(GetLocalAddress(connection_)));
223 EXPECT_TRUE(gateway_address_.Equals(GetGatewayAddress(connection_)));
224 EXPECT_TRUE(GetHasBroadcastDomain(connection_));
225
226 EXPECT_CALL(routing_table_,
227 CreateLinkRoute(kTestDeviceInterfaceIndex0,
228 IsIPAddress(local_address_, kPrefix0),
229 IsIPAddress(gateway_address_, 0)))
230 .WillOnce(Return(true))
231 .WillOnce(Return(false));
232 EXPECT_TRUE(connection_->CreateGatewayRoute());
233 EXPECT_FALSE(connection_->CreateGatewayRoute());
234 connection_->has_broadcast_domain_ = false;
235 EXPECT_FALSE(connection_->CreateGatewayRoute());
Paul Stewartdd60e452011-08-08 11:38:36 -0700236
237 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
Paul Stewart05a42c22012-08-02 16:47:21 -0700238 GetDefaultMetric()));
Paul Stewartdd60e452011-08-08 11:38:36 -0700239 EXPECT_CALL(resolver_, SetDNSFromLists(
240 ipconfig_->properties().dns_servers,
Paul Stewartbf667612012-06-29 14:49:54 -0700241 ipconfig_->properties().domain_search,
242 Resolver::kDefaultTimeout));
Paul Stewartdd60e452011-08-08 11:38:36 -0700243
Paul Stewartc681fa02012-03-02 19:40:04 -0800244 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
245 &control_,
246 reinterpret_cast<EventDispatcher *>(NULL),
247 reinterpret_cast<Metrics *>(NULL),
248 reinterpret_cast<Manager *>(NULL),
249 kTestDeviceName0,
250 string(),
251 kTestDeviceInterfaceIndex0));
252 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
253 .WillOnce(Return(device));
254 EXPECT_CALL(*device.get(), RequestPortalDetection())
255 .WillOnce(Return(true));
Paul Stewarte78ec542012-06-08 18:28:50 -0700256 EXPECT_CALL(routing_table_, FlushCache())
257 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800258 connection_->SetIsDefault(true);
Paul Stewarte78ec542012-06-08 18:28:50 -0700259 Mock::VerifyAndClearExpectations(&routing_table_);
Paul Stewartdd60e452011-08-08 11:38:36 -0700260 EXPECT_TRUE(connection_->is_default());
261
Paul Stewart7cfca042011-12-08 14:18:17 -0800262 EXPECT_CALL(routing_table_,
263 SetDefaultMetric(kTestDeviceInterfaceIndex0,
Paul Stewart05a42c22012-08-02 16:47:21 -0700264 GetNonDefaultMetricBase() +
Paul Stewart7cfca042011-12-08 14:18:17 -0800265 kTestDeviceInterfaceIndex0));
Paul Stewarte78ec542012-06-08 18:28:50 -0700266 EXPECT_CALL(routing_table_, FlushCache())
267 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800268 connection_->SetIsDefault(false);
Paul Stewartdd60e452011-08-08 11:38:36 -0700269 EXPECT_FALSE(connection_->is_default());
270}
271
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700272TEST_F(ConnectionTest, AddConfigWithPeer) {
273 const string kPeerAddress("192.168.1.222");
274 IPAddress peer_address(IPAddress::kFamilyIPv4);
275 EXPECT_TRUE(peer_address.SetAddressFromString(kPeerAddress));
276 properties_.peer_address = kPeerAddress;
277 properties_.gateway = string();
278 UpdateProperties();
Paul Stewart05a42c22012-08-02 16:47:21 -0700279 EXPECT_CALL(*device_info_,
280 HasOtherAddress(kTestDeviceInterfaceIndex0,
281 IsIPAddress(local_address_, kPrefix0)))
282 .WillOnce(Return(false));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700283 EXPECT_CALL(rtnl_handler_,
284 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
285 IsIPAddress(local_address_, kPrefix0),
286 IsIPAddress(broadcast_address_, 0),
287 IsIPAddress(peer_address, 0)));
288 EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _)).Times(0);
289 EXPECT_CALL(routing_table_,
290 ConfigureRoutes(kTestDeviceInterfaceIndex0,
291 ipconfig_,
Paul Stewart05a42c22012-08-02 16:47:21 -0700292 GetDefaultMetric()));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700293 connection_->UpdateFromIPConfig(ipconfig_);
Paul Stewart4a6748d2012-07-17 14:31:36 -0700294 EXPECT_FALSE(GetHasBroadcastDomain(connection_));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700295}
296
297TEST_F(ConnectionTest, AddConfigWithBrokenNetmask) {
298 // Assign a prefix that makes the gateway unreachable.
299 properties_.subnet_prefix = kPrefix1;
300 UpdateProperties();
301
302 // Connection should override with a prefix which will allow the
303 // gateway to be reachable.
Paul Stewart05a42c22012-08-02 16:47:21 -0700304 EXPECT_CALL(*device_info_,
305 HasOtherAddress(kTestDeviceInterfaceIndex0,
306 IsIPAddress(local_address_, kPrefix0)))
307 .WillOnce(Return(false));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700308 EXPECT_CALL(rtnl_handler_,
309 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
310 IsIPAddress(local_address_, kPrefix0),
311 IsIPAddress(broadcast_address_, 0),
312 IsIPAddress(default_address_, 0)));
313 EXPECT_CALL(routing_table_,
314 SetDefaultRoute(kTestDeviceInterfaceIndex0,
315 IsIPAddress(gateway_address_, 0),
Paul Stewart05a42c22012-08-02 16:47:21 -0700316 GetNonDefaultMetricBase() +
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700317 kTestDeviceInterfaceIndex0));
318 EXPECT_CALL(routing_table_,
319 ConfigureRoutes(kTestDeviceInterfaceIndex0,
320 ipconfig_,
Paul Stewart05a42c22012-08-02 16:47:21 -0700321 GetDefaultMetric()));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700322 connection_->UpdateFromIPConfig(ipconfig_);
323
324 // Assign a gateway address that violates the minimum plausible prefix
325 // the Connection can assign.
326 properties_.gateway = kGatewayAddress1;
327 UpdateProperties();
328
Paul Stewart49258292012-05-26 06:37:14 -0700329 IPAddress gateway_address1(IPAddress::kFamilyIPv4);
330 EXPECT_TRUE(gateway_address1.SetAddressFromString(kGatewayAddress1));
331 // Connection cannot override this prefix, so it will switch to a
332 // model where the peer address is set to the value of the gateway
333 // address.
Paul Stewart05a42c22012-08-02 16:47:21 -0700334 EXPECT_CALL(*device_info_,
335 HasOtherAddress(kTestDeviceInterfaceIndex0,
336 IsIPAddress(local_address_, kPrefix1)))
337 .WillOnce(Return(false));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700338 EXPECT_CALL(rtnl_handler_,
339 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
340 IsIPAddress(local_address_, kPrefix1),
341 IsIPAddress(broadcast_address_, 0),
Paul Stewart49258292012-05-26 06:37:14 -0700342 IsIPAddress(gateway_address1, 0)));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700343 EXPECT_CALL(routing_table_,
344 SetDefaultRoute(kTestDeviceInterfaceIndex0, _, _));
345 EXPECT_CALL(routing_table_,
346 ConfigureRoutes(kTestDeviceInterfaceIndex0, _, _));
347 connection_->UpdateFromIPConfig(ipconfig_);
348}
349
Paul Stewartdd60e452011-08-08 11:38:36 -0700350TEST_F(ConnectionTest, AddConfigReverse) {
351 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
Paul Stewart05a42c22012-08-02 16:47:21 -0700352 GetDefaultMetric()));
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800353 vector<string> empty_list;
Paul Stewartbf667612012-06-29 14:49:54 -0700354 EXPECT_CALL(resolver_, SetDNSFromLists(empty_list, empty_list,
355 Resolver::kDefaultTimeout));
Paul Stewartc681fa02012-03-02 19:40:04 -0800356 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
357 &control_,
358 reinterpret_cast<EventDispatcher *>(NULL),
359 reinterpret_cast<Metrics *>(NULL),
360 reinterpret_cast<Manager *>(NULL),
361 kTestDeviceName0,
362 string(),
363 kTestDeviceInterfaceIndex0));
364 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
365 .WillOnce(Return(device));
366 EXPECT_CALL(*device.get(), RequestPortalDetection())
367 .WillOnce(Return(true));
Paul Stewarte78ec542012-06-08 18:28:50 -0700368 EXPECT_CALL(routing_table_, FlushCache())
369 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800370 connection_->SetIsDefault(true);
Paul Stewarte78ec542012-06-08 18:28:50 -0700371 Mock::VerifyAndClearExpectations(&routing_table_);
Paul Stewartdd60e452011-08-08 11:38:36 -0700372
Paul Stewart05a42c22012-08-02 16:47:21 -0700373 EXPECT_CALL(*device_info_,
374 HasOtherAddress(kTestDeviceInterfaceIndex0,
375 IsIPAddress(local_address_, kPrefix0)))
376 .WillOnce(Return(false));
Paul Stewartdd60e452011-08-08 11:38:36 -0700377 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700378 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
379 IsIPAddress(local_address_, kPrefix0),
380 IsIPAddress(broadcast_address_, 0),
381 IsIPAddress(default_address_, 0)));
Paul Stewartdd60e452011-08-08 11:38:36 -0700382 EXPECT_CALL(routing_table_, SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700383 IsIPAddress(gateway_address_, 0),
Paul Stewart05a42c22012-08-02 16:47:21 -0700384 GetDefaultMetric()));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700385 EXPECT_CALL(routing_table_,
386 ConfigureRoutes(kTestDeviceInterfaceIndex0,
387 ipconfig_,
Paul Stewart05a42c22012-08-02 16:47:21 -0700388 GetDefaultMetric()));
Paul Stewart6f65c0b2012-09-11 14:57:32 -0700389 EXPECT_CALL(resolver_, SetDNSFromLists(ipconfig_->properties().dns_servers,
390 ipconfig_->properties().domain_search,
391 Resolver::kDefaultTimeout));
Paul Stewartdd60e452011-08-08 11:38:36 -0700392
393 connection_->UpdateFromIPConfig(ipconfig_);
394}
395
Paul Stewartbf667612012-06-29 14:49:54 -0700396TEST_F(ConnectionTest, AddConfigShortTimeout) {
397 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex0,
398 kTestDeviceName0,
399 Technology::kUnknown,
400 device_info_.get(),
401 true));
402 ReplaceSingletons(connection);
403 EXPECT_CALL(*device_info_, HasOtherAddress(_, _)).WillOnce(Return(false));
404 EXPECT_CALL(rtnl_handler_, AddInterfaceAddress(_, _, _, _))
405 .WillRepeatedly(Return(true));
406 EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _))
407 .WillRepeatedly(Return(true));
408 EXPECT_CALL(routing_table_, ConfigureRoutes(_, _, _))
409 .WillRepeatedly(Return(true));
410 connection->UpdateFromIPConfig(ipconfig_);
411 EXPECT_CALL(routing_table_, SetDefaultMetric(_, _));
412 EXPECT_CALL(resolver_, SetDNSFromLists(
413 ipconfig_->properties().dns_servers,
414 ipconfig_->properties().domain_search,
415 Resolver::kShortTimeout));
416 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
417 &control_,
418 reinterpret_cast<EventDispatcher *>(NULL),
419 reinterpret_cast<Metrics *>(NULL),
420 reinterpret_cast<Manager *>(NULL),
421 kTestDeviceName0,
422 string(),
423 kTestDeviceInterfaceIndex0));
424 EXPECT_CALL(*device_info_, GetDevice(_)).WillOnce(Return(device));
425 EXPECT_CALL(*device.get(), RequestPortalDetection()).WillOnce(Return(true));
426 EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
427 connection->SetIsDefault(true);
428 EXPECT_CALL(*device_info_, HasOtherAddress(_, _)).WillOnce(Return(false));
Paul Stewart6f65c0b2012-09-11 14:57:32 -0700429 EXPECT_CALL(resolver_, SetDNSFromLists(ipconfig_->properties().dns_servers,
430 ipconfig_->properties().domain_search,
431 Resolver::kShortTimeout));
Paul Stewartbf667612012-06-29 14:49:54 -0700432 connection->UpdateFromIPConfig(ipconfig_);
433 AddDestructorExpectations();
434}
435
Paul Stewart4d1868b2012-09-10 11:58:46 -0700436TEST_F(ConnectionTest, AddConfigWithDNSDomain) {
437 const string kDomainName("chromium.org");
438 properties_.domain_search.clear();
439 properties_.domain_name = kDomainName;
440 UpdateProperties();
441 EXPECT_CALL(*device_info_, HasOtherAddress(_, _))
442 .WillOnce(Return(false));
443 EXPECT_CALL(rtnl_handler_, AddInterfaceAddress(_, _, _, _));
444 EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _));
445 EXPECT_CALL(routing_table_, ConfigureRoutes(_, _, _));
446 connection_->UpdateFromIPConfig(ipconfig_);
447
448 EXPECT_CALL(routing_table_, SetDefaultMetric(_, _));
449 vector<string> domain_search_list;
450 domain_search_list.push_back(kDomainName + ".");
451 EXPECT_CALL(resolver_, SetDNSFromLists(_, domain_search_list, _));
452 DeviceRefPtr device;
453 EXPECT_CALL(*device_info_, GetDevice(_)).WillOnce(Return(device));
454 EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
455 connection_->SetIsDefault(true);
456}
457
Paul Stewart05a42c22012-08-02 16:47:21 -0700458TEST_F(ConnectionTest, HasOtherAddress) {
459 EXPECT_CALL(*device_info_,
460 HasOtherAddress(kTestDeviceInterfaceIndex0,
461 IsIPAddress(local_address_, kPrefix0)))
462 .WillOnce(Return(true));
463 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
464 EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex0));
465 EXPECT_CALL(rtnl_handler_,
466 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
467 IsIPAddress(local_address_, kPrefix0),
468 IsIPAddress(broadcast_address_, 0),
469 IsIPAddress(default_address_, 0)));
470 EXPECT_CALL(routing_table_,
471 SetDefaultRoute(kTestDeviceInterfaceIndex0,
472 IsIPAddress(gateway_address_, 0),
473 GetNonDefaultMetricBase() +
474 kTestDeviceInterfaceIndex0));
475 EXPECT_CALL(routing_table_,
476 ConfigureRoutes(kTestDeviceInterfaceIndex0,
477 ipconfig_,
478 GetDefaultMetric()));
479 connection_->UpdateFromIPConfig(ipconfig_);
480}
481
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800482TEST_F(ConnectionTest, RouteRequest) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200483 ConnectionRefPtr connection = GetNewConnection();
Paul Stewartf748a362012-03-07 12:01:20 -0800484 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
485 &control_,
486 reinterpret_cast<EventDispatcher *>(NULL),
487 reinterpret_cast<Metrics *>(NULL),
488 reinterpret_cast<Manager *>(NULL),
489 kTestDeviceName0,
490 string(),
491 kTestDeviceInterfaceIndex0));
492 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
493 .WillRepeatedly(Return(device));
494 EXPECT_CALL(*device.get(), DisableReversePathFilter()).Times(1);
495 connection->RequestRouting();
496 connection->RequestRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800497
Paul Stewartf748a362012-03-07 12:01:20 -0800498 // The first release should only decrement the reference counter.
499 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800500
Paul Stewartf748a362012-03-07 12:01:20 -0800501 // Another release will re-enable reverse-path filter.
502 EXPECT_CALL(*device.get(), EnableReversePathFilter());
503 EXPECT_CALL(routing_table_, FlushCache());
504 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800505
Paul Stewartf748a362012-03-07 12:01:20 -0800506 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200507 AddDestructorExpectations();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800508}
509
Paul Stewartdd60e452011-08-08 11:38:36 -0700510TEST_F(ConnectionTest, Destructor) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200511 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex1,
512 kTestDeviceName1,
513 Technology::kUnknown,
Paul Stewartbf667612012-06-29 14:49:54 -0700514 device_info_.get(),
515 false));
Darin Petkov13e6d552012-05-09 14:22:23 +0200516 connection->resolver_ = &resolver_;
517 connection->routing_table_ = &routing_table_;
518 connection->rtnl_handler_ = &rtnl_handler_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800519 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex1));
Paul Stewarte93b0382012-04-24 13:11:28 -0700520 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex1));
Paul Stewart9a908082011-08-31 12:18:48 -0700521 EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex1));
Darin Petkov13e6d552012-05-09 14:22:23 +0200522 connection = NULL;
Paul Stewartdd60e452011-08-08 11:38:36 -0700523}
524
Paul Stewartf748a362012-03-07 12:01:20 -0800525TEST_F(ConnectionTest, RequestHostRoute) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200526 ConnectionRefPtr connection = GetNewConnection();
Paul Stewartf748a362012-03-07 12:01:20 -0800527 IPAddress address(IPAddress::kFamilyIPv4);
528 ASSERT_TRUE(address.SetAddressFromString(kIPAddress0));
529 size_t prefix_len = address.GetLength() * 8;
Darin Petkov13e6d552012-05-09 14:22:23 +0200530 EXPECT_CALL(routing_table_,
531 RequestRouteToHost(IsIPAddress(address, prefix_len),
532 -1,
533 kTestDeviceInterfaceIndex0,
534 IsNonNullCallback()))
Paul Stewartf748a362012-03-07 12:01:20 -0800535 .WillOnce(Return(true));
536 EXPECT_TRUE(connection->RequestHostRoute(address));
537
538 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200539 AddDestructorExpectations();
Paul Stewarte93b0382012-04-24 13:11:28 -0700540}
541
Ben Chana0163122012-09-25 15:10:52 -0700542TEST_F(ConnectionTest, BlackholeIPv6) {
543 properties_.blackhole_ipv6 = true;
544 UpdateProperties();
545 EXPECT_CALL(*device_info_, HasOtherAddress(_, _))
546 .WillOnce(Return(false));
547 EXPECT_CALL(rtnl_handler_, AddInterfaceAddress(_, _, _, _));
548 EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _));
549 EXPECT_CALL(routing_table_, ConfigureRoutes(_, _, _));
550 EXPECT_CALL(routing_table_,
551 CreateBlackholeRoute(kTestDeviceInterfaceIndex0,
552 IPAddress::kFamilyIPv6,
553 Connection::kDefaultMetric))
554 .WillOnce(Return(true));
555 connection_->UpdateFromIPConfig(ipconfig_);
556}
557
Paul Stewarte93b0382012-04-24 13:11:28 -0700558TEST_F(ConnectionTest, PinHostRoute) {
559 static const char kGateway[] = "10.242.2.13";
560 static const char kNetwork[] = "10.242.2.1";
561
Darin Petkov13e6d552012-05-09 14:22:23 +0200562 ConnectionRefPtr connection = GetNewConnection();
Paul Stewarte93b0382012-04-24 13:11:28 -0700563
564 IPConfig::Properties props;
565 props.address_family = IPAddress::kFamilyIPv4;
566 EXPECT_FALSE(PinHostRoute(connection, props));
567
568 props.gateway = kGateway;
569 EXPECT_FALSE(PinHostRoute(connection, props));
570
571 props.gateway.clear();
572 props.trusted_ip = "xxx";
573 EXPECT_FALSE(PinHostRoute(connection, props));
574
575 props.gateway = kGateway;
576 EXPECT_FALSE(PinHostRoute(connection, props));
577
578 props.trusted_ip = kNetwork;
579 IPAddress address(IPAddress::kFamilyIPv4);
580 ASSERT_TRUE(address.SetAddressFromString(kNetwork));
581 size_t prefix_len = address.GetLength() * 8;
582 EXPECT_CALL(routing_table_, RequestRouteToHost(
Darin Petkovabf6d282012-05-08 15:49:05 +0200583 IsIPAddress(address, prefix_len), -1, kTestDeviceInterfaceIndex0, _))
Paul Stewarte93b0382012-04-24 13:11:28 -0700584 .WillOnce(Return(false));
585 EXPECT_FALSE(PinHostRoute(connection, props));
586
587 EXPECT_CALL(routing_table_, RequestRouteToHost(
Darin Petkovabf6d282012-05-08 15:49:05 +0200588 IsIPAddress(address, prefix_len), -1, kTestDeviceInterfaceIndex0, _))
Paul Stewarte93b0382012-04-24 13:11:28 -0700589 .WillOnce(Return(true));
590 EXPECT_TRUE(PinHostRoute(connection, props));
591
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);
604
605 // Should fail because no gateway is set.
Paul Stewart49258292012-05-26 06:37:14 -0700606 EXPECT_FALSE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700607 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700608 EXPECT_FALSE(peer.IsValid());
Paul Stewart53a30382012-04-26 09:06:59 -0700609
610 // Should succeed because with the given prefix, this gateway is reachable.
611 static const char kReachableGateway[] = "10.242.2.14";
612 ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700613 peer = IPAddress(IPAddress::kFamilyIPv4);
614 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700615 // Prefix should remain unchanged.
616 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700617 // Peer should remain unchanged.
618 EXPECT_FALSE(peer.IsValid());
Paul Stewart53a30382012-04-26 09:06:59 -0700619
620 // Should succeed because we modified the prefix to match the gateway.
621 static const char kExpandableGateway[] = "10.242.3.14";
622 ASSERT_TRUE(gateway.SetAddressFromString(kExpandableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700623 peer = IPAddress(IPAddress::kFamilyIPv4);
624 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700625 // Prefix should have opened up by 1 bit.
626 EXPECT_EQ(kPrefix - 1, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700627 // Peer should remain unchanged.
628 EXPECT_FALSE(peer.IsValid());
Paul Stewart53a30382012-04-26 09:06:59 -0700629
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700630 // Should change models to assuming point-to-point because we cannot
Paul Stewart49258292012-05-26 06:37:14 -0700631 // plausibly expand the prefix past 8.
Paul Stewart53a30382012-04-26 09:06:59 -0700632 local.set_prefix(kPrefix);
633 static const char kUnreachableGateway[] = "11.242.2.14";
634 ASSERT_TRUE(gateway.SetAddressFromString(kUnreachableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700635 peer = IPAddress(IPAddress::kFamilyIPv4);
636 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700637 // Prefix should not have changed.
638 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700639 // Peer address should be set to the gateway address.
640 EXPECT_TRUE(peer.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700641
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700642 // Should also use point-to-point model if the netmask is set to the
643 // "all-ones" addresss, even if this address could have been made
644 // accessible by plausibly changing the prefix.
645 const int kIPv4MaxPrefix =
646 IPAddress::GetMaxPrefixLength(IPAddress::kFamilyIPv4);
647 local.set_prefix(kIPv4MaxPrefix);
648 ASSERT_TRUE(gateway.SetAddressFromString(kExpandableGateway));
649 peer = IPAddress(IPAddress::kFamilyIPv4);
650 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
651 // Prefix should not have changed.
652 EXPECT_EQ(kIPv4MaxPrefix, local.prefix());
653 // Peer address should be set to the gateway address.
654 EXPECT_TRUE(peer.Equals(gateway));
655
Paul Stewart49258292012-05-26 06:37:14 -0700656 // If this is a peer-to-peer interface and the peer matches the gateway,
657 // we should succeed.
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700658 local.set_prefix(kPrefix);
659 ASSERT_TRUE(gateway.SetAddressFromString(kUnreachableGateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700660 ASSERT_TRUE(peer.SetAddressFromString(kUnreachableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700661 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700662 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700663 EXPECT_TRUE(peer.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700664
665 // If there is a peer specified and it does not match the gateway (even
666 // if it was reachable via netmask), we should fail.
667 ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700668 EXPECT_FALSE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700669 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700670 EXPECT_FALSE(peer.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700671}
672
Darin Petkov13e6d552012-05-09 14:22:23 +0200673TEST_F(ConnectionTest, Binders) {
674 EXPECT_TRUE(connection_->binders_.empty());
675 DisconnectCallbackTarget target0;
676 DisconnectCallbackTarget target1;
677 DisconnectCallbackTarget target2;
678 DisconnectCallbackTarget target3;
679 Connection::Binder binder0("binder0", target0.callback());
680 Connection::Binder binder1("binder1", target1.callback());
681 Connection::Binder binder2("binder2", target2.callback());
682 Connection::Binder binder3("binder3", target3.callback());
683
684 binder0.Attach(connection_);
685 binder1.Attach(connection_);
686
687 EXPECT_CALL(target1, CallTarget()).Times(0);
688 binder1.Attach(connection_);
689
690 binder3.Attach(connection_);
691 binder2.Attach(connection_);
692
693 EXPECT_CALL(target3, CallTarget()).Times(0);
694 binder3.Attach(NULL);
695
696 ASSERT_EQ(3, connection_->binders_.size());
697 EXPECT_TRUE(connection_->binders_.at(0) == &binder0);
698 EXPECT_TRUE(connection_->binders_.at(1) == &binder1);
699 EXPECT_TRUE(connection_->binders_.at(2) == &binder2);
700
701 EXPECT_CALL(target0, CallTarget()).Times(1);
702 EXPECT_CALL(target1, CallTarget()).Times(1);
703 EXPECT_CALL(target2, CallTarget()).Times(1);
704 connection_->NotifyBindersOnDisconnect();
705 EXPECT_TRUE(connection_->binders_.empty());
706
707 // Should be a no-op.
708 connection_->NotifyBindersOnDisconnect();
709}
710
711TEST_F(ConnectionTest, Binder) {
712 // No connection should be bound initially.
713 Connection::Binder *binder = &connection_->lower_binder_;
714 EXPECT_EQ(connection_->interface_name(), binder->name_);
715 EXPECT_FALSE(binder->client_disconnect_callback_.is_null());
716 EXPECT_FALSE(binder->IsBound());
717
718 ConnectionRefPtr connection1 = GetNewConnection();
719 EXPECT_TRUE(connection1->binders_.empty());
720
721 // Bind lower |connection1| and check if it's bound.
722 binder->Attach(connection1);
723 EXPECT_TRUE(binder->IsBound());
724 EXPECT_EQ(connection1.get(), binder->connection().get());
725 ASSERT_FALSE(connection1->binders_.empty());
726 EXPECT_TRUE(binder == connection1->binders_.at(0));
727
728 // Unbind lower |connection1| and check if it's unbound.
729 binder->Attach(NULL);
730 EXPECT_FALSE(binder->IsBound());
731 EXPECT_TRUE(connection1->binders_.empty());
732
733 ConnectionRefPtr connection2 = GetNewConnection();
734
735 // Bind lower |connection1| to upper |connection2| and destroy the upper
736 // |connection2|. Make sure lower |connection1| is unbound (i.e., the
737 // disconnect callback is deregistered).
738 connection2->lower_binder_.Attach(connection1);
739 EXPECT_FALSE(connection1->binders_.empty());
740 AddDestructorExpectations();
741 connection2 = NULL;
742 EXPECT_TRUE(connection1->binders_.empty());
743
744 // Bind lower |connection1| to upper |connection_| and destroy lower
745 // |connection1|. Make sure lower |connection1| is unbound from upper
746 // |connection_| and upper |connection_|'s registered disconnect callbacks are
747 // run.
748 binder->Attach(connection1);
749 DisconnectCallbackTarget target;
750 Connection::Binder test_binder("from_test", target.callback());
751 test_binder.Attach(connection_);
752 EXPECT_CALL(target, CallTarget()).Times(1);
753 ASSERT_FALSE(connection_->binders_.empty());
754 AddDestructorExpectations();
755 connection1 = NULL;
756 EXPECT_FALSE(binder->IsBound());
757 EXPECT_FALSE(test_binder.IsBound());
758 EXPECT_TRUE(connection_->binders_.empty());
759
760 {
761 // Binding a connection to itself should be safe.
762 ConnectionRefPtr connection = GetNewConnection();
763
764 connection->lower_binder_.Attach(connection);
765
766 EXPECT_FALSE(connection->binders_.empty());
767
768 DisconnectCallbackTarget target;
769 Connection::Binder binder("test", target.callback());
770 binder.Attach(connection);
771
772 AddDestructorExpectations();
773 EXPECT_CALL(target, CallTarget()).Times(1);
774 connection = NULL;
775 }
Darin Petkov13e6d552012-05-09 14:22:23 +0200776 {
777 // Circular binding of multiple connections should be safe.
778 ConnectionRefPtr connection_a = GetNewConnection();
779 ConnectionRefPtr connection_b = GetNewConnection();
780
781 connection_a->lower_binder_.Attach(connection_b);
782 connection_b->lower_binder_.Attach(connection_a);
783
784 EXPECT_FALSE(connection_a->binders_.empty());
785 EXPECT_FALSE(connection_b->binders_.empty());
786
787 DisconnectCallbackTarget target_a;
788 DisconnectCallbackTarget target_b;
789 Connection::Binder binder_a("test_a", target_a.callback());
790 Connection::Binder binder_b("test_b", target_b.callback());
791 binder_a.Attach(connection_a);
792 binder_b.Attach(connection_b);
793
794 AddDestructorExpectations();
795 EXPECT_CALL(target_a, CallTarget()).Times(1);
796 EXPECT_CALL(target_b, CallTarget()).Times(1);
797 connection_b = NULL;
798
799 EXPECT_TRUE(connection_a->binders_.empty());
800
801 AddDestructorExpectations();
802 connection_a = NULL;
803 }
Darin Petkovef1f9fe2012-05-11 16:51:52 +0200804 {
805 // Test the weak pointer to the bound Connection. This is not a case that
806 // should occur but the weak pointer should handle it gracefully.
807 DisconnectCallbackTarget target;
808 Connection::Binder binder("test_weak", target.callback());
809 ConnectionRefPtr connection = GetNewConnection();
810 binder.Attach(connection);
811
812 // Make sure the connection doesn't notify the binder on destruction.
813 connection->binders_.clear();
814 AddDestructorExpectations();
815 EXPECT_CALL(target, CallTarget()).Times(0);
816 connection = NULL;
817
818 // Ensure no crash -- the weak pointer to connection should be NULL.
Darin Petkov5eb05422012-05-11 15:45:25 +0200819 EXPECT_FALSE(binder.connection());
Darin Petkovef1f9fe2012-05-11 16:51:52 +0200820 binder.Attach(NULL);
821 }
Darin Petkov13e6d552012-05-09 14:22:23 +0200822}
823
824TEST_F(ConnectionTest, OnRouteQueryResponse) {
825 Connection::Binder *binder = &connection_->lower_binder_;
826 ConnectionRefPtr connection = GetNewConnection();
827 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
828 &control_,
829 reinterpret_cast<EventDispatcher *>(NULL),
830 reinterpret_cast<Metrics *>(NULL),
831 reinterpret_cast<Manager *>(NULL),
832 kTestDeviceName1,
833 string(),
834 kTestDeviceInterfaceIndex1));
835
836 // Make sure we unbind the old lower connection even if we can't lookup the
837 // lower connection device.
838 binder->Attach(connection);
839 scoped_refptr<MockDevice> null_device;
840 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
841 .WillOnce(Return(null_device));
842 connection_->OnRouteQueryResponse(
843 kTestDeviceInterfaceIndex1, RoutingTableEntry());
844 EXPECT_FALSE(binder->IsBound());
845
846 // Check for graceful handling of a device with no connection.
847 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
848 .WillOnce(Return(device));
849 connection_->OnRouteQueryResponse(
850 kTestDeviceInterfaceIndex1, RoutingTableEntry());
851 EXPECT_FALSE(binder->IsBound());
852
Paul Stewart4a6748d2012-07-17 14:31:36 -0700853 // Create a mock connection that will be used fo binding.
854 scoped_refptr<MockConnection> mock_connection(
855 new StrictMock<MockConnection>(device_info_.get()));
856 EXPECT_CALL(*device_info_.get(),
857 FlushAddresses(mock_connection->interface_index()));
858 const string kInterfaceName(kTestDeviceName0);
859 EXPECT_CALL(*mock_connection, interface_name())
860 .WillRepeatedly(ReturnRef(kInterfaceName));
861 device->connection_ = mock_connection;
Darin Petkov13e6d552012-05-09 14:22:23 +0200862 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
863 .WillOnce(Return(device));
Paul Stewart4a6748d2012-07-17 14:31:36 -0700864
Ben Chana6bfe872012-09-26 09:48:34 -0700865 // Check that the binding process completes, causing its upper
Paul Stewart4a6748d2012-07-17 14:31:36 -0700866 // connection to create a gateway route.
867 EXPECT_CALL(*mock_connection, CreateGatewayRoute())
868 .WillOnce(Return(true));
Darin Petkov13e6d552012-05-09 14:22:23 +0200869 connection_->OnRouteQueryResponse(
870 kTestDeviceInterfaceIndex1, RoutingTableEntry());
Paul Stewart4a6748d2012-07-17 14:31:36 -0700871
872 // Check that the upper connection is bound to the lower connection.
Darin Petkov13e6d552012-05-09 14:22:23 +0200873 EXPECT_TRUE(binder->IsBound());
Paul Stewart4a6748d2012-07-17 14:31:36 -0700874 EXPECT_EQ(mock_connection.get(), binder->connection().get());
Darin Petkov13e6d552012-05-09 14:22:23 +0200875
876 device->connection_ = NULL;
877 AddDestructorExpectations();
878 connection = NULL;
879}
880
Paul Stewartdd60e452011-08-08 11:38:36 -0700881} // namespace shill