blob: 415437308473c19829bda8e984b1e596439348c4 [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::_;
29using testing::NiceMock;
30using testing::Return;
Darin Petkov13e6d552012-05-09 14:22:23 +020031using testing::ReturnRef;
Paul Stewartdd60e452011-08-08 11:38:36 -070032using testing::StrictMock;
33using testing::Test;
34
35namespace shill {
36
37namespace {
38const char kTestDeviceName0[] = "netdev0";
39const int kTestDeviceInterfaceIndex0 = 123;
40const char kTestDeviceName1[] = "netdev1";
41const int kTestDeviceInterfaceIndex1 = 321;
42const char kIPAddress0[] = "192.168.1.1";
43const char kGatewayAddress0[] = "192.168.1.254";
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070044const char kGatewayAddress1[] = "192.168.2.254";
Paul Stewart9a908082011-08-31 12:18:48 -070045const char kBroadcastAddress0[] = "192.168.1.255";
Paul Stewartdd60e452011-08-08 11:38:36 -070046const char kNameServer0[] = "8.8.8.8";
47const char kNameServer1[] = "8.8.9.9";
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070048const int32 kPrefix0 = 24;
49const int32 kPrefix1 = 31;
Paul Stewartdd60e452011-08-08 11:38:36 -070050const char kSearchDomain0[] = "chromium.org";
51const char kSearchDomain1[] = "google.com";
52} // namespace {}
53
54class ConnectionTest : public Test {
55 public:
56 ConnectionTest()
Paul Stewart9a908082011-08-31 12:18:48 -070057 : device_info_(new StrictMock<MockDeviceInfo>(
58 &control_,
59 static_cast<EventDispatcher*>(NULL),
Thieu Le3426c8f2012-01-11 17:35:11 -080060 static_cast<Metrics*>(NULL),
Paul Stewart9a908082011-08-31 12:18:48 -070061 static_cast<Manager*>(NULL))),
62 connection_(new Connection(
63 kTestDeviceInterfaceIndex0,
64 kTestDeviceName0,
Paul Stewarte00600e2012-03-16 07:08:00 -070065 Technology::kUnknown,
Paul Stewart9a908082011-08-31 12:18:48 -070066 device_info_.get())),
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070067 ipconfig_(new IPConfig(&control_, kTestDeviceName0)),
68 local_address_(IPAddress::kFamilyIPv4),
69 broadcast_address_(IPAddress::kFamilyIPv4),
70 gateway_address_(IPAddress::kFamilyIPv4),
71 default_address_(IPAddress::kFamilyIPv4) {}
Paul Stewartdd60e452011-08-08 11:38:36 -070072
73 virtual void SetUp() {
Paul Stewartc8f4bef2011-12-13 09:45:51 -080074 ReplaceSingletons(connection_);
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070075 properties_.address = kIPAddress0;
76 properties_.subnet_prefix = kPrefix0;
77 properties_.gateway = kGatewayAddress0;
78 properties_.broadcast_address = kBroadcastAddress0;
79 properties_.dns_servers.push_back(kNameServer0);
80 properties_.dns_servers.push_back(kNameServer1);
81 properties_.domain_search.push_back(kSearchDomain0);
82 properties_.domain_search.push_back(kSearchDomain1);
83 properties_.address_family = IPAddress::kFamilyIPv4;
84 UpdateProperties();
85 EXPECT_TRUE(local_address_.SetAddressFromString(kIPAddress0));
86 EXPECT_TRUE(broadcast_address_.SetAddressFromString(kBroadcastAddress0));
87 EXPECT_TRUE(gateway_address_.SetAddressFromString(kGatewayAddress0));
Paul Stewartdd60e452011-08-08 11:38:36 -070088 }
89
Paul Stewart9a908082011-08-31 12:18:48 -070090 virtual void TearDown() {
Darin Petkov13e6d552012-05-09 14:22:23 +020091 AddDestructorExpectations();
Paul Stewarte93b0382012-04-24 13:11:28 -070092 connection_ = NULL;
Paul Stewart9a908082011-08-31 12:18:48 -070093 }
94
Paul Stewartc8f4bef2011-12-13 09:45:51 -080095 void ReplaceSingletons(ConnectionRefPtr connection) {
96 connection->resolver_ = &resolver_;
97 connection->routing_table_ = &routing_table_;
98 connection->rtnl_handler_ = &rtnl_handler_;
99 }
100
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700101 void UpdateProperties() {
102 ipconfig_->UpdateProperties(properties_, true);
103 }
104
Paul Stewarte93b0382012-04-24 13:11:28 -0700105 bool PinHostRoute(ConnectionRefPtr connection,
106 const IPConfig::Properties &properties) {
107 return connection->PinHostRoute(properties);
108 }
109
Paul Stewartdd60e452011-08-08 11:38:36 -0700110 protected:
Darin Petkov13e6d552012-05-09 14:22:23 +0200111 class DisconnectCallbackTarget {
112 public:
113 DisconnectCallbackTarget()
114 : callback_(base::Bind(&DisconnectCallbackTarget::CallTarget,
115 base::Unretained(this))) {}
116
117 MOCK_METHOD0(CallTarget, void());
118 const base::Closure &callback() { return callback_; }
119
120 private:
121 base::Closure callback_;
122 };
123
124 void AddDestructorExpectations() {
125 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
126 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex0));
127 EXPECT_CALL(*device_info_.get(),
128 FlushAddresses(kTestDeviceInterfaceIndex0));
129 }
130
131 // Returns a new test connection object. The caller usually needs to call
132 // AddDestructorExpectations before destroying the object.
133 ConnectionRefPtr GetNewConnection() {
134 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex0,
135 kTestDeviceName0,
136 Technology::kUnknown,
137 device_info_.get()));
138 ReplaceSingletons(connection);
139 return connection;
140 }
141
Paul Stewart9a908082011-08-31 12:18:48 -0700142 scoped_ptr<StrictMock<MockDeviceInfo> > device_info_;
Paul Stewartdd60e452011-08-08 11:38:36 -0700143 ConnectionRefPtr connection_;
144 MockControl control_;
145 IPConfigRefPtr ipconfig_;
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700146 IPConfig::Properties properties_;
147 IPAddress local_address_;
148 IPAddress broadcast_address_;
149 IPAddress gateway_address_;
150 IPAddress default_address_;
Paul Stewartdd60e452011-08-08 11:38:36 -0700151 StrictMock<MockResolver> resolver_;
152 StrictMock<MockRoutingTable> routing_table_;
153 StrictMock<MockRTNLHandler> rtnl_handler_;
154};
155
Darin Petkov13e6d552012-05-09 14:22:23 +0200156namespace {
Paul Stewartdd60e452011-08-08 11:38:36 -0700157
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700158MATCHER_P2(IsIPAddress, address, prefix, "") {
159 IPAddress match_address(address);
160 match_address.set_prefix(prefix);
161 return match_address.Equals(arg);
162}
163
Darin Petkov13e6d552012-05-09 14:22:23 +0200164MATCHER(IsNonNullCallback, "") {
165 return !arg.is_null();
166}
167
168} // namespace
169
170TEST_F(ConnectionTest, InitState) {
171 EXPECT_EQ(kTestDeviceInterfaceIndex0, connection_->interface_index_);
172 EXPECT_EQ(kTestDeviceName0, connection_->interface_name_);
173 EXPECT_FALSE(connection_->is_default());
174 EXPECT_FALSE(connection_->routing_request_count_);
175}
176
Paul Stewartdd60e452011-08-08 11:38:36 -0700177TEST_F(ConnectionTest, AddConfig) {
178 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700179 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
180 IsIPAddress(local_address_, kPrefix0),
181 IsIPAddress(broadcast_address_, 0),
182 IsIPAddress(default_address_, 0)));
Paul Stewart7cfca042011-12-08 14:18:17 -0800183 EXPECT_CALL(routing_table_,
184 SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700185 IsIPAddress(gateway_address_, 0),
Paul Stewart7cfca042011-12-08 14:18:17 -0800186 Connection::kNonDefaultMetricBase +
187 kTestDeviceInterfaceIndex0));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700188 EXPECT_CALL(routing_table_,
189 ConfigureRoutes(kTestDeviceInterfaceIndex0,
190 ipconfig_,
191 Connection::kDefaultMetric));
Paul Stewartdd60e452011-08-08 11:38:36 -0700192 connection_->UpdateFromIPConfig(ipconfig_);
193
194 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
195 Connection::kDefaultMetric));
196 EXPECT_CALL(resolver_, SetDNSFromLists(
197 ipconfig_->properties().dns_servers,
198 ipconfig_->properties().domain_search));
199
Paul Stewartc681fa02012-03-02 19:40:04 -0800200 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
201 &control_,
202 reinterpret_cast<EventDispatcher *>(NULL),
203 reinterpret_cast<Metrics *>(NULL),
204 reinterpret_cast<Manager *>(NULL),
205 kTestDeviceName0,
206 string(),
207 kTestDeviceInterfaceIndex0));
208 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
209 .WillOnce(Return(device));
210 EXPECT_CALL(*device.get(), RequestPortalDetection())
211 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800212 connection_->SetIsDefault(true);
Paul Stewartdd60e452011-08-08 11:38:36 -0700213 EXPECT_TRUE(connection_->is_default());
214
Paul Stewart7cfca042011-12-08 14:18:17 -0800215 EXPECT_CALL(routing_table_,
216 SetDefaultMetric(kTestDeviceInterfaceIndex0,
217 Connection::kNonDefaultMetricBase +
218 kTestDeviceInterfaceIndex0));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800219 connection_->SetIsDefault(false);
Paul Stewartdd60e452011-08-08 11:38:36 -0700220 EXPECT_FALSE(connection_->is_default());
221}
222
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700223TEST_F(ConnectionTest, AddConfigWithPeer) {
224 const string kPeerAddress("192.168.1.222");
225 IPAddress peer_address(IPAddress::kFamilyIPv4);
226 EXPECT_TRUE(peer_address.SetAddressFromString(kPeerAddress));
227 properties_.peer_address = kPeerAddress;
228 properties_.gateway = string();
229 UpdateProperties();
230 EXPECT_CALL(rtnl_handler_,
231 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
232 IsIPAddress(local_address_, kPrefix0),
233 IsIPAddress(broadcast_address_, 0),
234 IsIPAddress(peer_address, 0)));
235 EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _)).Times(0);
236 EXPECT_CALL(routing_table_,
237 ConfigureRoutes(kTestDeviceInterfaceIndex0,
238 ipconfig_,
239 Connection::kDefaultMetric));
240 connection_->UpdateFromIPConfig(ipconfig_);
241}
242
243TEST_F(ConnectionTest, AddConfigWithBrokenNetmask) {
244 // Assign a prefix that makes the gateway unreachable.
245 properties_.subnet_prefix = kPrefix1;
246 UpdateProperties();
247
248 // Connection should override with a prefix which will allow the
249 // gateway to be reachable.
250 EXPECT_CALL(rtnl_handler_,
251 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
252 IsIPAddress(local_address_, kPrefix0),
253 IsIPAddress(broadcast_address_, 0),
254 IsIPAddress(default_address_, 0)));
255 EXPECT_CALL(routing_table_,
256 SetDefaultRoute(kTestDeviceInterfaceIndex0,
257 IsIPAddress(gateway_address_, 0),
258 Connection::kNonDefaultMetricBase +
259 kTestDeviceInterfaceIndex0));
260 EXPECT_CALL(routing_table_,
261 ConfigureRoutes(kTestDeviceInterfaceIndex0,
262 ipconfig_,
263 Connection::kDefaultMetric));
264 connection_->UpdateFromIPConfig(ipconfig_);
265
266 // Assign a gateway address that violates the minimum plausible prefix
267 // the Connection can assign.
268 properties_.gateway = kGatewayAddress1;
269 UpdateProperties();
270
271 // Connection cannot override this prefix, so it will revert to the
272 // configured prefix, expecting the default route to fail.
273 EXPECT_CALL(rtnl_handler_,
274 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
275 IsIPAddress(local_address_, kPrefix1),
276 IsIPAddress(broadcast_address_, 0),
277 IsIPAddress(default_address_, 0)));
278 EXPECT_CALL(routing_table_,
279 SetDefaultRoute(kTestDeviceInterfaceIndex0, _, _));
280 EXPECT_CALL(routing_table_,
281 ConfigureRoutes(kTestDeviceInterfaceIndex0, _, _));
282 connection_->UpdateFromIPConfig(ipconfig_);
283}
284
Paul Stewartdd60e452011-08-08 11:38:36 -0700285TEST_F(ConnectionTest, AddConfigReverse) {
286 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
287 Connection::kDefaultMetric));
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800288 vector<string> empty_list;
Paul Stewartdd60e452011-08-08 11:38:36 -0700289 EXPECT_CALL(resolver_, SetDNSFromLists(empty_list, empty_list));
Paul Stewartc681fa02012-03-02 19:40:04 -0800290 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
291 &control_,
292 reinterpret_cast<EventDispatcher *>(NULL),
293 reinterpret_cast<Metrics *>(NULL),
294 reinterpret_cast<Manager *>(NULL),
295 kTestDeviceName0,
296 string(),
297 kTestDeviceInterfaceIndex0));
298 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
299 .WillOnce(Return(device));
300 EXPECT_CALL(*device.get(), RequestPortalDetection())
301 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800302 connection_->SetIsDefault(true);
Paul Stewartdd60e452011-08-08 11:38:36 -0700303
304 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700305 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
306 IsIPAddress(local_address_, kPrefix0),
307 IsIPAddress(broadcast_address_, 0),
308 IsIPAddress(default_address_, 0)));
Paul Stewartdd60e452011-08-08 11:38:36 -0700309 EXPECT_CALL(routing_table_, SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700310 IsIPAddress(gateway_address_, 0),
311 Connection::kDefaultMetric));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700312 EXPECT_CALL(routing_table_,
313 ConfigureRoutes(kTestDeviceInterfaceIndex0,
314 ipconfig_,
315 Connection::kDefaultMetric));
Paul Stewartdd60e452011-08-08 11:38:36 -0700316 EXPECT_CALL(resolver_, SetDNSFromIPConfig(ipconfig_));
317
318 connection_->UpdateFromIPConfig(ipconfig_);
319}
320
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800321TEST_F(ConnectionTest, RouteRequest) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200322 ConnectionRefPtr connection = GetNewConnection();
Paul Stewartf748a362012-03-07 12:01:20 -0800323 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
324 &control_,
325 reinterpret_cast<EventDispatcher *>(NULL),
326 reinterpret_cast<Metrics *>(NULL),
327 reinterpret_cast<Manager *>(NULL),
328 kTestDeviceName0,
329 string(),
330 kTestDeviceInterfaceIndex0));
331 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
332 .WillRepeatedly(Return(device));
333 EXPECT_CALL(*device.get(), DisableReversePathFilter()).Times(1);
334 connection->RequestRouting();
335 connection->RequestRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800336
Paul Stewartf748a362012-03-07 12:01:20 -0800337 // The first release should only decrement the reference counter.
338 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800339
Paul Stewartf748a362012-03-07 12:01:20 -0800340 // Another release will re-enable reverse-path filter.
341 EXPECT_CALL(*device.get(), EnableReversePathFilter());
342 EXPECT_CALL(routing_table_, FlushCache());
343 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800344
Paul Stewartf748a362012-03-07 12:01:20 -0800345 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200346 AddDestructorExpectations();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800347}
348
Paul Stewartdd60e452011-08-08 11:38:36 -0700349TEST_F(ConnectionTest, Destructor) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200350 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex1,
351 kTestDeviceName1,
352 Technology::kUnknown,
353 device_info_.get()));
354 connection->resolver_ = &resolver_;
355 connection->routing_table_ = &routing_table_;
356 connection->rtnl_handler_ = &rtnl_handler_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800357 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex1));
Paul Stewarte93b0382012-04-24 13:11:28 -0700358 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex1));
Paul Stewart9a908082011-08-31 12:18:48 -0700359 EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex1));
Darin Petkov13e6d552012-05-09 14:22:23 +0200360 connection = NULL;
Paul Stewartdd60e452011-08-08 11:38:36 -0700361}
362
Paul Stewartf748a362012-03-07 12:01:20 -0800363TEST_F(ConnectionTest, RequestHostRoute) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200364 ConnectionRefPtr connection = GetNewConnection();
Paul Stewartf748a362012-03-07 12:01:20 -0800365 IPAddress address(IPAddress::kFamilyIPv4);
366 ASSERT_TRUE(address.SetAddressFromString(kIPAddress0));
367 size_t prefix_len = address.GetLength() * 8;
Darin Petkov13e6d552012-05-09 14:22:23 +0200368 EXPECT_CALL(routing_table_,
369 RequestRouteToHost(IsIPAddress(address, prefix_len),
370 -1,
371 kTestDeviceInterfaceIndex0,
372 IsNonNullCallback()))
Paul Stewartf748a362012-03-07 12:01:20 -0800373 .WillOnce(Return(true));
374 EXPECT_TRUE(connection->RequestHostRoute(address));
375
376 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200377 AddDestructorExpectations();
Paul Stewarte93b0382012-04-24 13:11:28 -0700378}
379
380TEST_F(ConnectionTest, PinHostRoute) {
381 static const char kGateway[] = "10.242.2.13";
382 static const char kNetwork[] = "10.242.2.1";
383
Darin Petkov13e6d552012-05-09 14:22:23 +0200384 ConnectionRefPtr connection = GetNewConnection();
Paul Stewarte93b0382012-04-24 13:11:28 -0700385
386 IPConfig::Properties props;
387 props.address_family = IPAddress::kFamilyIPv4;
388 EXPECT_FALSE(PinHostRoute(connection, props));
389
390 props.gateway = kGateway;
391 EXPECT_FALSE(PinHostRoute(connection, props));
392
393 props.gateway.clear();
394 props.trusted_ip = "xxx";
395 EXPECT_FALSE(PinHostRoute(connection, props));
396
397 props.gateway = kGateway;
398 EXPECT_FALSE(PinHostRoute(connection, props));
399
400 props.trusted_ip = kNetwork;
401 IPAddress address(IPAddress::kFamilyIPv4);
402 ASSERT_TRUE(address.SetAddressFromString(kNetwork));
403 size_t prefix_len = address.GetLength() * 8;
404 EXPECT_CALL(routing_table_, RequestRouteToHost(
Darin Petkovabf6d282012-05-08 15:49:05 +0200405 IsIPAddress(address, prefix_len), -1, kTestDeviceInterfaceIndex0, _))
Paul Stewarte93b0382012-04-24 13:11:28 -0700406 .WillOnce(Return(false));
407 EXPECT_FALSE(PinHostRoute(connection, props));
408
409 EXPECT_CALL(routing_table_, RequestRouteToHost(
Darin Petkovabf6d282012-05-08 15:49:05 +0200410 IsIPAddress(address, prefix_len), -1, kTestDeviceInterfaceIndex0, _))
Paul Stewarte93b0382012-04-24 13:11:28 -0700411 .WillOnce(Return(true));
412 EXPECT_TRUE(PinHostRoute(connection, props));
413
414 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200415 AddDestructorExpectations();
Paul Stewartf748a362012-03-07 12:01:20 -0800416}
417
Paul Stewart53a30382012-04-26 09:06:59 -0700418TEST_F(ConnectionTest, FixGatewayReachability) {
419 static const char kLocal[] = "10.242.2.13";
420 IPAddress local(IPAddress::kFamilyIPv4);
421 ASSERT_TRUE(local.SetAddressFromString(kLocal));
422 const int kPrefix = 24;
423 local.set_prefix(kPrefix);
424 IPAddress gateway(IPAddress::kFamilyIPv4);
425 IPAddress peer(IPAddress::kFamilyIPv4);
426
427 // Should fail because no gateway is set.
428 EXPECT_FALSE(Connection::FixGatewayReachability(&local, gateway, peer));
429 EXPECT_EQ(kPrefix, local.prefix());
430
431 // Should succeed because with the given prefix, this gateway is reachable.
432 static const char kReachableGateway[] = "10.242.2.14";
433 ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
434 EXPECT_TRUE(Connection::FixGatewayReachability(&local, gateway, peer));
435 // Prefix should remain unchanged.
436 EXPECT_EQ(kPrefix, local.prefix());
437
438 // Should succeed because we modified the prefix to match the gateway.
439 static const char kExpandableGateway[] = "10.242.3.14";
440 ASSERT_TRUE(gateway.SetAddressFromString(kExpandableGateway));
441 EXPECT_TRUE(Connection::FixGatewayReachability(&local, gateway, peer));
442 // Prefix should have opened up by 1 bit.
443 EXPECT_EQ(kPrefix - 1, local.prefix());
444
445 // Should fail because we cannot plausibly expand the prefix past 8.
446 local.set_prefix(kPrefix);
447 static const char kUnreachableGateway[] = "11.242.2.14";
448 ASSERT_TRUE(gateway.SetAddressFromString(kUnreachableGateway));
449 EXPECT_FALSE(Connection::FixGatewayReachability(&local, gateway, peer));
450 // Prefix should not have changed.
451 EXPECT_EQ(kPrefix, local.prefix());
452
453 // However, if this is a peer-to-peer interface and the peer matches
454 // the gateway, we should succeed.
455 ASSERT_TRUE(peer.SetAddressFromString(kUnreachableGateway));
456 EXPECT_TRUE(Connection::FixGatewayReachability(&local, gateway, peer));
457 EXPECT_EQ(kPrefix, local.prefix());
458
459 // If there is a peer specified and it does not match the gateway (even
460 // if it was reachable via netmask), we should fail.
461 ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
462 EXPECT_FALSE(Connection::FixGatewayReachability(&local, gateway, peer));
463 EXPECT_EQ(kPrefix, local.prefix());
464}
465
Darin Petkov13e6d552012-05-09 14:22:23 +0200466TEST_F(ConnectionTest, Binders) {
467 EXPECT_TRUE(connection_->binders_.empty());
468 DisconnectCallbackTarget target0;
469 DisconnectCallbackTarget target1;
470 DisconnectCallbackTarget target2;
471 DisconnectCallbackTarget target3;
472 Connection::Binder binder0("binder0", target0.callback());
473 Connection::Binder binder1("binder1", target1.callback());
474 Connection::Binder binder2("binder2", target2.callback());
475 Connection::Binder binder3("binder3", target3.callback());
476
477 binder0.Attach(connection_);
478 binder1.Attach(connection_);
479
480 EXPECT_CALL(target1, CallTarget()).Times(0);
481 binder1.Attach(connection_);
482
483 binder3.Attach(connection_);
484 binder2.Attach(connection_);
485
486 EXPECT_CALL(target3, CallTarget()).Times(0);
487 binder3.Attach(NULL);
488
489 ASSERT_EQ(3, connection_->binders_.size());
490 EXPECT_TRUE(connection_->binders_.at(0) == &binder0);
491 EXPECT_TRUE(connection_->binders_.at(1) == &binder1);
492 EXPECT_TRUE(connection_->binders_.at(2) == &binder2);
493
494 EXPECT_CALL(target0, CallTarget()).Times(1);
495 EXPECT_CALL(target1, CallTarget()).Times(1);
496 EXPECT_CALL(target2, CallTarget()).Times(1);
497 connection_->NotifyBindersOnDisconnect();
498 EXPECT_TRUE(connection_->binders_.empty());
499
500 // Should be a no-op.
501 connection_->NotifyBindersOnDisconnect();
502}
503
504TEST_F(ConnectionTest, Binder) {
505 // No connection should be bound initially.
506 Connection::Binder *binder = &connection_->lower_binder_;
507 EXPECT_EQ(connection_->interface_name(), binder->name_);
508 EXPECT_FALSE(binder->client_disconnect_callback_.is_null());
509 EXPECT_FALSE(binder->IsBound());
510
511 ConnectionRefPtr connection1 = GetNewConnection();
512 EXPECT_TRUE(connection1->binders_.empty());
513
514 // Bind lower |connection1| and check if it's bound.
515 binder->Attach(connection1);
516 EXPECT_TRUE(binder->IsBound());
517 EXPECT_EQ(connection1.get(), binder->connection().get());
518 ASSERT_FALSE(connection1->binders_.empty());
519 EXPECT_TRUE(binder == connection1->binders_.at(0));
520
521 // Unbind lower |connection1| and check if it's unbound.
522 binder->Attach(NULL);
523 EXPECT_FALSE(binder->IsBound());
524 EXPECT_TRUE(connection1->binders_.empty());
525
526 ConnectionRefPtr connection2 = GetNewConnection();
527
528 // Bind lower |connection1| to upper |connection2| and destroy the upper
529 // |connection2|. Make sure lower |connection1| is unbound (i.e., the
530 // disconnect callback is deregistered).
531 connection2->lower_binder_.Attach(connection1);
532 EXPECT_FALSE(connection1->binders_.empty());
533 AddDestructorExpectations();
534 connection2 = NULL;
535 EXPECT_TRUE(connection1->binders_.empty());
536
537 // Bind lower |connection1| to upper |connection_| and destroy lower
538 // |connection1|. Make sure lower |connection1| is unbound from upper
539 // |connection_| and upper |connection_|'s registered disconnect callbacks are
540 // run.
541 binder->Attach(connection1);
542 DisconnectCallbackTarget target;
543 Connection::Binder test_binder("from_test", target.callback());
544 test_binder.Attach(connection_);
545 EXPECT_CALL(target, CallTarget()).Times(1);
546 ASSERT_FALSE(connection_->binders_.empty());
547 AddDestructorExpectations();
548 connection1 = NULL;
549 EXPECT_FALSE(binder->IsBound());
550 EXPECT_FALSE(test_binder.IsBound());
551 EXPECT_TRUE(connection_->binders_.empty());
552
553 {
554 // Binding a connection to itself should be safe.
555 ConnectionRefPtr connection = GetNewConnection();
556
557 connection->lower_binder_.Attach(connection);
558
559 EXPECT_FALSE(connection->binders_.empty());
560
561 DisconnectCallbackTarget target;
562 Connection::Binder binder("test", target.callback());
563 binder.Attach(connection);
564
565 AddDestructorExpectations();
566 EXPECT_CALL(target, CallTarget()).Times(1);
567 connection = NULL;
568 }
Darin Petkov13e6d552012-05-09 14:22:23 +0200569 {
570 // Circular binding of multiple connections should be safe.
571 ConnectionRefPtr connection_a = GetNewConnection();
572 ConnectionRefPtr connection_b = GetNewConnection();
573
574 connection_a->lower_binder_.Attach(connection_b);
575 connection_b->lower_binder_.Attach(connection_a);
576
577 EXPECT_FALSE(connection_a->binders_.empty());
578 EXPECT_FALSE(connection_b->binders_.empty());
579
580 DisconnectCallbackTarget target_a;
581 DisconnectCallbackTarget target_b;
582 Connection::Binder binder_a("test_a", target_a.callback());
583 Connection::Binder binder_b("test_b", target_b.callback());
584 binder_a.Attach(connection_a);
585 binder_b.Attach(connection_b);
586
587 AddDestructorExpectations();
588 EXPECT_CALL(target_a, CallTarget()).Times(1);
589 EXPECT_CALL(target_b, CallTarget()).Times(1);
590 connection_b = NULL;
591
592 EXPECT_TRUE(connection_a->binders_.empty());
593
594 AddDestructorExpectations();
595 connection_a = NULL;
596 }
Darin Petkovef1f9fe2012-05-11 16:51:52 +0200597 {
598 // Test the weak pointer to the bound Connection. This is not a case that
599 // should occur but the weak pointer should handle it gracefully.
600 DisconnectCallbackTarget target;
601 Connection::Binder binder("test_weak", target.callback());
602 ConnectionRefPtr connection = GetNewConnection();
603 binder.Attach(connection);
604
605 // Make sure the connection doesn't notify the binder on destruction.
606 connection->binders_.clear();
607 AddDestructorExpectations();
608 EXPECT_CALL(target, CallTarget()).Times(0);
609 connection = NULL;
610
611 // Ensure no crash -- the weak pointer to connection should be NULL.
612 binder.Attach(NULL);
613 }
Darin Petkov13e6d552012-05-09 14:22:23 +0200614}
615
616TEST_F(ConnectionTest, OnRouteQueryResponse) {
617 Connection::Binder *binder = &connection_->lower_binder_;
618 ConnectionRefPtr connection = GetNewConnection();
619 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
620 &control_,
621 reinterpret_cast<EventDispatcher *>(NULL),
622 reinterpret_cast<Metrics *>(NULL),
623 reinterpret_cast<Manager *>(NULL),
624 kTestDeviceName1,
625 string(),
626 kTestDeviceInterfaceIndex1));
627
628 // Make sure we unbind the old lower connection even if we can't lookup the
629 // lower connection device.
630 binder->Attach(connection);
631 scoped_refptr<MockDevice> null_device;
632 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
633 .WillOnce(Return(null_device));
634 connection_->OnRouteQueryResponse(
635 kTestDeviceInterfaceIndex1, RoutingTableEntry());
636 EXPECT_FALSE(binder->IsBound());
637
638 // Check for graceful handling of a device with no connection.
639 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
640 .WillOnce(Return(device));
641 connection_->OnRouteQueryResponse(
642 kTestDeviceInterfaceIndex1, RoutingTableEntry());
643 EXPECT_FALSE(binder->IsBound());
644
645 // Check that the upper connection is bound to the lower connection.
646 device->connection_ = connection;
647 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
648 .WillOnce(Return(device));
649 connection_->OnRouteQueryResponse(
650 kTestDeviceInterfaceIndex1, RoutingTableEntry());
651 EXPECT_TRUE(binder->IsBound());
652 EXPECT_EQ(connection.get(), binder->connection().get());
653
654 device->connection_ = NULL;
655 AddDestructorExpectations();
656 connection = NULL;
657}
658
Paul Stewartdd60e452011-08-08 11:38:36 -0700659} // namespace shill