blob: a1fda3b2949b6b99973b4f0fa9784ef412c11741 [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;
31using testing::StrictMock;
32using testing::Test;
33
34namespace shill {
35
36namespace {
37const char kTestDeviceName0[] = "netdev0";
38const int kTestDeviceInterfaceIndex0 = 123;
39const char kTestDeviceName1[] = "netdev1";
40const int kTestDeviceInterfaceIndex1 = 321;
41const char kIPAddress0[] = "192.168.1.1";
42const char kGatewayAddress0[] = "192.168.1.254";
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070043const char kGatewayAddress1[] = "192.168.2.254";
Paul Stewart9a908082011-08-31 12:18:48 -070044const char kBroadcastAddress0[] = "192.168.1.255";
Paul Stewartdd60e452011-08-08 11:38:36 -070045const char kNameServer0[] = "8.8.8.8";
46const char kNameServer1[] = "8.8.9.9";
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070047const int32 kPrefix0 = 24;
48const int32 kPrefix1 = 31;
Paul Stewartdd60e452011-08-08 11:38:36 -070049const char kSearchDomain0[] = "chromium.org";
50const char kSearchDomain1[] = "google.com";
51} // namespace {}
52
53class ConnectionTest : public Test {
54 public:
55 ConnectionTest()
Paul Stewart9a908082011-08-31 12:18:48 -070056 : device_info_(new StrictMock<MockDeviceInfo>(
57 &control_,
58 static_cast<EventDispatcher*>(NULL),
Thieu Le3426c8f2012-01-11 17:35:11 -080059 static_cast<Metrics*>(NULL),
Paul Stewart9a908082011-08-31 12:18:48 -070060 static_cast<Manager*>(NULL))),
61 connection_(new Connection(
62 kTestDeviceInterfaceIndex0,
63 kTestDeviceName0,
Paul Stewarte00600e2012-03-16 07:08:00 -070064 Technology::kUnknown,
Paul Stewart9a908082011-08-31 12:18:48 -070065 device_info_.get())),
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070066 ipconfig_(new IPConfig(&control_, kTestDeviceName0)),
67 local_address_(IPAddress::kFamilyIPv4),
68 broadcast_address_(IPAddress::kFamilyIPv4),
69 gateway_address_(IPAddress::kFamilyIPv4),
70 default_address_(IPAddress::kFamilyIPv4) {}
Paul Stewartdd60e452011-08-08 11:38:36 -070071
72 virtual void SetUp() {
Paul Stewartc8f4bef2011-12-13 09:45:51 -080073 ReplaceSingletons(connection_);
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070074 properties_.address = kIPAddress0;
75 properties_.subnet_prefix = kPrefix0;
76 properties_.gateway = kGatewayAddress0;
77 properties_.broadcast_address = kBroadcastAddress0;
78 properties_.dns_servers.push_back(kNameServer0);
79 properties_.dns_servers.push_back(kNameServer1);
80 properties_.domain_search.push_back(kSearchDomain0);
81 properties_.domain_search.push_back(kSearchDomain1);
82 properties_.address_family = IPAddress::kFamilyIPv4;
83 UpdateProperties();
84 EXPECT_TRUE(local_address_.SetAddressFromString(kIPAddress0));
85 EXPECT_TRUE(broadcast_address_.SetAddressFromString(kBroadcastAddress0));
86 EXPECT_TRUE(gateway_address_.SetAddressFromString(kGatewayAddress0));
Paul Stewartdd60e452011-08-08 11:38:36 -070087 }
88
Paul Stewart9a908082011-08-31 12:18:48 -070089 virtual void TearDown() {
Darin Petkov13e6d552012-05-09 14:22:23 +020090 AddDestructorExpectations();
Paul Stewarte93b0382012-04-24 13:11:28 -070091 connection_ = NULL;
Paul Stewart9a908082011-08-31 12:18:48 -070092 }
93
Paul Stewartc8f4bef2011-12-13 09:45:51 -080094 void ReplaceSingletons(ConnectionRefPtr connection) {
95 connection->resolver_ = &resolver_;
96 connection->routing_table_ = &routing_table_;
97 connection->rtnl_handler_ = &rtnl_handler_;
98 }
99
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700100 void UpdateProperties() {
101 ipconfig_->UpdateProperties(properties_, true);
102 }
103
Paul Stewarte93b0382012-04-24 13:11:28 -0700104 bool PinHostRoute(ConnectionRefPtr connection,
105 const IPConfig::Properties &properties) {
106 return connection->PinHostRoute(properties);
107 }
108
Paul Stewartdd60e452011-08-08 11:38:36 -0700109 protected:
Darin Petkov13e6d552012-05-09 14:22:23 +0200110 class DisconnectCallbackTarget {
111 public:
112 DisconnectCallbackTarget()
113 : callback_(base::Bind(&DisconnectCallbackTarget::CallTarget,
114 base::Unretained(this))) {}
115
116 MOCK_METHOD0(CallTarget, void());
117 const base::Closure &callback() { return callback_; }
118
119 private:
120 base::Closure callback_;
121 };
122
123 void AddDestructorExpectations() {
124 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
125 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex0));
126 EXPECT_CALL(*device_info_.get(),
127 FlushAddresses(kTestDeviceInterfaceIndex0));
128 }
129
130 // Returns a new test connection object. The caller usually needs to call
131 // AddDestructorExpectations before destroying the object.
132 ConnectionRefPtr GetNewConnection() {
133 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex0,
134 kTestDeviceName0,
135 Technology::kUnknown,
136 device_info_.get()));
137 ReplaceSingletons(connection);
138 return connection;
139 }
140
Paul Stewart9a908082011-08-31 12:18:48 -0700141 scoped_ptr<StrictMock<MockDeviceInfo> > device_info_;
Paul Stewartdd60e452011-08-08 11:38:36 -0700142 ConnectionRefPtr connection_;
143 MockControl control_;
144 IPConfigRefPtr ipconfig_;
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700145 IPConfig::Properties properties_;
146 IPAddress local_address_;
147 IPAddress broadcast_address_;
148 IPAddress gateway_address_;
149 IPAddress default_address_;
Paul Stewartdd60e452011-08-08 11:38:36 -0700150 StrictMock<MockResolver> resolver_;
151 StrictMock<MockRoutingTable> routing_table_;
152 StrictMock<MockRTNLHandler> rtnl_handler_;
153};
154
Darin Petkov13e6d552012-05-09 14:22:23 +0200155namespace {
Paul Stewartdd60e452011-08-08 11:38:36 -0700156
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700157MATCHER_P2(IsIPAddress, address, prefix, "") {
158 IPAddress match_address(address);
159 match_address.set_prefix(prefix);
160 return match_address.Equals(arg);
161}
162
Darin Petkov13e6d552012-05-09 14:22:23 +0200163MATCHER(IsNonNullCallback, "") {
164 return !arg.is_null();
165}
166
167} // namespace
168
169TEST_F(ConnectionTest, InitState) {
170 EXPECT_EQ(kTestDeviceInterfaceIndex0, connection_->interface_index_);
171 EXPECT_EQ(kTestDeviceName0, connection_->interface_name_);
172 EXPECT_FALSE(connection_->is_default());
173 EXPECT_FALSE(connection_->routing_request_count_);
174}
175
Paul Stewartdd60e452011-08-08 11:38:36 -0700176TEST_F(ConnectionTest, AddConfig) {
177 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700178 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
179 IsIPAddress(local_address_, kPrefix0),
180 IsIPAddress(broadcast_address_, 0),
181 IsIPAddress(default_address_, 0)));
Paul Stewart7cfca042011-12-08 14:18:17 -0800182 EXPECT_CALL(routing_table_,
183 SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700184 IsIPAddress(gateway_address_, 0),
Paul Stewart7cfca042011-12-08 14:18:17 -0800185 Connection::kNonDefaultMetricBase +
186 kTestDeviceInterfaceIndex0));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700187 EXPECT_CALL(routing_table_,
188 ConfigureRoutes(kTestDeviceInterfaceIndex0,
189 ipconfig_,
190 Connection::kDefaultMetric));
Paul Stewartdd60e452011-08-08 11:38:36 -0700191 connection_->UpdateFromIPConfig(ipconfig_);
192
193 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
194 Connection::kDefaultMetric));
195 EXPECT_CALL(resolver_, SetDNSFromLists(
196 ipconfig_->properties().dns_servers,
197 ipconfig_->properties().domain_search));
198
Paul Stewartc681fa02012-03-02 19:40:04 -0800199 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
200 &control_,
201 reinterpret_cast<EventDispatcher *>(NULL),
202 reinterpret_cast<Metrics *>(NULL),
203 reinterpret_cast<Manager *>(NULL),
204 kTestDeviceName0,
205 string(),
206 kTestDeviceInterfaceIndex0));
207 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
208 .WillOnce(Return(device));
209 EXPECT_CALL(*device.get(), RequestPortalDetection())
210 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800211 connection_->SetIsDefault(true);
Paul Stewartdd60e452011-08-08 11:38:36 -0700212 EXPECT_TRUE(connection_->is_default());
213
Paul Stewart7cfca042011-12-08 14:18:17 -0800214 EXPECT_CALL(routing_table_,
215 SetDefaultMetric(kTestDeviceInterfaceIndex0,
216 Connection::kNonDefaultMetricBase +
217 kTestDeviceInterfaceIndex0));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800218 connection_->SetIsDefault(false);
Paul Stewartdd60e452011-08-08 11:38:36 -0700219 EXPECT_FALSE(connection_->is_default());
220}
221
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700222TEST_F(ConnectionTest, AddConfigWithPeer) {
223 const string kPeerAddress("192.168.1.222");
224 IPAddress peer_address(IPAddress::kFamilyIPv4);
225 EXPECT_TRUE(peer_address.SetAddressFromString(kPeerAddress));
226 properties_.peer_address = kPeerAddress;
227 properties_.gateway = string();
228 UpdateProperties();
229 EXPECT_CALL(rtnl_handler_,
230 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
231 IsIPAddress(local_address_, kPrefix0),
232 IsIPAddress(broadcast_address_, 0),
233 IsIPAddress(peer_address, 0)));
234 EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _)).Times(0);
235 EXPECT_CALL(routing_table_,
236 ConfigureRoutes(kTestDeviceInterfaceIndex0,
237 ipconfig_,
238 Connection::kDefaultMetric));
239 connection_->UpdateFromIPConfig(ipconfig_);
240}
241
242TEST_F(ConnectionTest, AddConfigWithBrokenNetmask) {
243 // Assign a prefix that makes the gateway unreachable.
244 properties_.subnet_prefix = kPrefix1;
245 UpdateProperties();
246
247 // Connection should override with a prefix which will allow the
248 // gateway to be reachable.
249 EXPECT_CALL(rtnl_handler_,
250 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
251 IsIPAddress(local_address_, kPrefix0),
252 IsIPAddress(broadcast_address_, 0),
253 IsIPAddress(default_address_, 0)));
254 EXPECT_CALL(routing_table_,
255 SetDefaultRoute(kTestDeviceInterfaceIndex0,
256 IsIPAddress(gateway_address_, 0),
257 Connection::kNonDefaultMetricBase +
258 kTestDeviceInterfaceIndex0));
259 EXPECT_CALL(routing_table_,
260 ConfigureRoutes(kTestDeviceInterfaceIndex0,
261 ipconfig_,
262 Connection::kDefaultMetric));
263 connection_->UpdateFromIPConfig(ipconfig_);
264
265 // Assign a gateway address that violates the minimum plausible prefix
266 // the Connection can assign.
267 properties_.gateway = kGatewayAddress1;
268 UpdateProperties();
269
270 // Connection cannot override this prefix, so it will revert to the
271 // configured prefix, expecting the default route to fail.
272 EXPECT_CALL(rtnl_handler_,
273 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
274 IsIPAddress(local_address_, kPrefix1),
275 IsIPAddress(broadcast_address_, 0),
276 IsIPAddress(default_address_, 0)));
277 EXPECT_CALL(routing_table_,
278 SetDefaultRoute(kTestDeviceInterfaceIndex0, _, _));
279 EXPECT_CALL(routing_table_,
280 ConfigureRoutes(kTestDeviceInterfaceIndex0, _, _));
281 connection_->UpdateFromIPConfig(ipconfig_);
282}
283
Paul Stewartdd60e452011-08-08 11:38:36 -0700284TEST_F(ConnectionTest, AddConfigReverse) {
285 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
286 Connection::kDefaultMetric));
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800287 vector<string> empty_list;
Paul Stewartdd60e452011-08-08 11:38:36 -0700288 EXPECT_CALL(resolver_, SetDNSFromLists(empty_list, empty_list));
Paul Stewartc681fa02012-03-02 19:40:04 -0800289 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
290 &control_,
291 reinterpret_cast<EventDispatcher *>(NULL),
292 reinterpret_cast<Metrics *>(NULL),
293 reinterpret_cast<Manager *>(NULL),
294 kTestDeviceName0,
295 string(),
296 kTestDeviceInterfaceIndex0));
297 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
298 .WillOnce(Return(device));
299 EXPECT_CALL(*device.get(), RequestPortalDetection())
300 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800301 connection_->SetIsDefault(true);
Paul Stewartdd60e452011-08-08 11:38:36 -0700302
303 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700304 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
305 IsIPAddress(local_address_, kPrefix0),
306 IsIPAddress(broadcast_address_, 0),
307 IsIPAddress(default_address_, 0)));
Paul Stewartdd60e452011-08-08 11:38:36 -0700308 EXPECT_CALL(routing_table_, SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700309 IsIPAddress(gateway_address_, 0),
310 Connection::kDefaultMetric));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700311 EXPECT_CALL(routing_table_,
312 ConfigureRoutes(kTestDeviceInterfaceIndex0,
313 ipconfig_,
314 Connection::kDefaultMetric));
Paul Stewartdd60e452011-08-08 11:38:36 -0700315 EXPECT_CALL(resolver_, SetDNSFromIPConfig(ipconfig_));
316
317 connection_->UpdateFromIPConfig(ipconfig_);
318}
319
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800320TEST_F(ConnectionTest, RouteRequest) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200321 ConnectionRefPtr connection = GetNewConnection();
Paul Stewartf748a362012-03-07 12:01:20 -0800322 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
323 &control_,
324 reinterpret_cast<EventDispatcher *>(NULL),
325 reinterpret_cast<Metrics *>(NULL),
326 reinterpret_cast<Manager *>(NULL),
327 kTestDeviceName0,
328 string(),
329 kTestDeviceInterfaceIndex0));
330 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
331 .WillRepeatedly(Return(device));
332 EXPECT_CALL(*device.get(), DisableReversePathFilter()).Times(1);
333 connection->RequestRouting();
334 connection->RequestRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800335
Paul Stewartf748a362012-03-07 12:01:20 -0800336 // The first release should only decrement the reference counter.
337 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800338
Paul Stewartf748a362012-03-07 12:01:20 -0800339 // Another release will re-enable reverse-path filter.
340 EXPECT_CALL(*device.get(), EnableReversePathFilter());
341 EXPECT_CALL(routing_table_, FlushCache());
342 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800343
Paul Stewartf748a362012-03-07 12:01:20 -0800344 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200345 AddDestructorExpectations();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800346}
347
Paul Stewartdd60e452011-08-08 11:38:36 -0700348TEST_F(ConnectionTest, Destructor) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200349 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex1,
350 kTestDeviceName1,
351 Technology::kUnknown,
352 device_info_.get()));
353 connection->resolver_ = &resolver_;
354 connection->routing_table_ = &routing_table_;
355 connection->rtnl_handler_ = &rtnl_handler_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800356 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex1));
Paul Stewarte93b0382012-04-24 13:11:28 -0700357 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex1));
Paul Stewart9a908082011-08-31 12:18:48 -0700358 EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex1));
Darin Petkov13e6d552012-05-09 14:22:23 +0200359 connection = NULL;
Paul Stewartdd60e452011-08-08 11:38:36 -0700360}
361
Paul Stewartf748a362012-03-07 12:01:20 -0800362TEST_F(ConnectionTest, RequestHostRoute) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200363 ConnectionRefPtr connection = GetNewConnection();
Paul Stewartf748a362012-03-07 12:01:20 -0800364 IPAddress address(IPAddress::kFamilyIPv4);
365 ASSERT_TRUE(address.SetAddressFromString(kIPAddress0));
366 size_t prefix_len = address.GetLength() * 8;
Darin Petkov13e6d552012-05-09 14:22:23 +0200367 EXPECT_CALL(routing_table_,
368 RequestRouteToHost(IsIPAddress(address, prefix_len),
369 -1,
370 kTestDeviceInterfaceIndex0,
371 IsNonNullCallback()))
Paul Stewartf748a362012-03-07 12:01:20 -0800372 .WillOnce(Return(true));
373 EXPECT_TRUE(connection->RequestHostRoute(address));
374
375 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200376 AddDestructorExpectations();
Paul Stewarte93b0382012-04-24 13:11:28 -0700377}
378
379TEST_F(ConnectionTest, PinHostRoute) {
380 static const char kGateway[] = "10.242.2.13";
381 static const char kNetwork[] = "10.242.2.1";
382
Darin Petkov13e6d552012-05-09 14:22:23 +0200383 ConnectionRefPtr connection = GetNewConnection();
Paul Stewarte93b0382012-04-24 13:11:28 -0700384
385 IPConfig::Properties props;
386 props.address_family = IPAddress::kFamilyIPv4;
387 EXPECT_FALSE(PinHostRoute(connection, props));
388
389 props.gateway = kGateway;
390 EXPECT_FALSE(PinHostRoute(connection, props));
391
392 props.gateway.clear();
393 props.trusted_ip = "xxx";
394 EXPECT_FALSE(PinHostRoute(connection, props));
395
396 props.gateway = kGateway;
397 EXPECT_FALSE(PinHostRoute(connection, props));
398
399 props.trusted_ip = kNetwork;
400 IPAddress address(IPAddress::kFamilyIPv4);
401 ASSERT_TRUE(address.SetAddressFromString(kNetwork));
402 size_t prefix_len = address.GetLength() * 8;
403 EXPECT_CALL(routing_table_, RequestRouteToHost(
Darin Petkovabf6d282012-05-08 15:49:05 +0200404 IsIPAddress(address, prefix_len), -1, kTestDeviceInterfaceIndex0, _))
Paul Stewarte93b0382012-04-24 13:11:28 -0700405 .WillOnce(Return(false));
406 EXPECT_FALSE(PinHostRoute(connection, props));
407
408 EXPECT_CALL(routing_table_, RequestRouteToHost(
Darin Petkovabf6d282012-05-08 15:49:05 +0200409 IsIPAddress(address, prefix_len), -1, kTestDeviceInterfaceIndex0, _))
Paul Stewarte93b0382012-04-24 13:11:28 -0700410 .WillOnce(Return(true));
411 EXPECT_TRUE(PinHostRoute(connection, props));
412
413 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200414 AddDestructorExpectations();
Paul Stewartf748a362012-03-07 12:01:20 -0800415}
416
Paul Stewart53a30382012-04-26 09:06:59 -0700417TEST_F(ConnectionTest, FixGatewayReachability) {
418 static const char kLocal[] = "10.242.2.13";
419 IPAddress local(IPAddress::kFamilyIPv4);
420 ASSERT_TRUE(local.SetAddressFromString(kLocal));
421 const int kPrefix = 24;
422 local.set_prefix(kPrefix);
423 IPAddress gateway(IPAddress::kFamilyIPv4);
424 IPAddress peer(IPAddress::kFamilyIPv4);
425
426 // Should fail because no gateway is set.
427 EXPECT_FALSE(Connection::FixGatewayReachability(&local, gateway, peer));
428 EXPECT_EQ(kPrefix, local.prefix());
429
430 // Should succeed because with the given prefix, this gateway is reachable.
431 static const char kReachableGateway[] = "10.242.2.14";
432 ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
433 EXPECT_TRUE(Connection::FixGatewayReachability(&local, gateway, peer));
434 // Prefix should remain unchanged.
435 EXPECT_EQ(kPrefix, local.prefix());
436
437 // Should succeed because we modified the prefix to match the gateway.
438 static const char kExpandableGateway[] = "10.242.3.14";
439 ASSERT_TRUE(gateway.SetAddressFromString(kExpandableGateway));
440 EXPECT_TRUE(Connection::FixGatewayReachability(&local, gateway, peer));
441 // Prefix should have opened up by 1 bit.
442 EXPECT_EQ(kPrefix - 1, local.prefix());
443
444 // Should fail because we cannot plausibly expand the prefix past 8.
445 local.set_prefix(kPrefix);
446 static const char kUnreachableGateway[] = "11.242.2.14";
447 ASSERT_TRUE(gateway.SetAddressFromString(kUnreachableGateway));
448 EXPECT_FALSE(Connection::FixGatewayReachability(&local, gateway, peer));
449 // Prefix should not have changed.
450 EXPECT_EQ(kPrefix, local.prefix());
451
452 // However, if this is a peer-to-peer interface and the peer matches
453 // the gateway, we should succeed.
454 ASSERT_TRUE(peer.SetAddressFromString(kUnreachableGateway));
455 EXPECT_TRUE(Connection::FixGatewayReachability(&local, gateway, peer));
456 EXPECT_EQ(kPrefix, local.prefix());
457
458 // If there is a peer specified and it does not match the gateway (even
459 // if it was reachable via netmask), we should fail.
460 ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
461 EXPECT_FALSE(Connection::FixGatewayReachability(&local, gateway, peer));
462 EXPECT_EQ(kPrefix, local.prefix());
463}
464
Darin Petkov13e6d552012-05-09 14:22:23 +0200465TEST_F(ConnectionTest, Binders) {
466 EXPECT_TRUE(connection_->binders_.empty());
467 DisconnectCallbackTarget target0;
468 DisconnectCallbackTarget target1;
469 DisconnectCallbackTarget target2;
470 DisconnectCallbackTarget target3;
471 Connection::Binder binder0("binder0", target0.callback());
472 Connection::Binder binder1("binder1", target1.callback());
473 Connection::Binder binder2("binder2", target2.callback());
474 Connection::Binder binder3("binder3", target3.callback());
475
476 binder0.Attach(connection_);
477 binder1.Attach(connection_);
478
479 EXPECT_CALL(target1, CallTarget()).Times(0);
480 binder1.Attach(connection_);
481
482 binder3.Attach(connection_);
483 binder2.Attach(connection_);
484
485 EXPECT_CALL(target3, CallTarget()).Times(0);
486 binder3.Attach(NULL);
487
488 ASSERT_EQ(3, connection_->binders_.size());
489 EXPECT_TRUE(connection_->binders_.at(0) == &binder0);
490 EXPECT_TRUE(connection_->binders_.at(1) == &binder1);
491 EXPECT_TRUE(connection_->binders_.at(2) == &binder2);
492
493 EXPECT_CALL(target0, CallTarget()).Times(1);
494 EXPECT_CALL(target1, CallTarget()).Times(1);
495 EXPECT_CALL(target2, CallTarget()).Times(1);
496 connection_->NotifyBindersOnDisconnect();
497 EXPECT_TRUE(connection_->binders_.empty());
498
499 // Should be a no-op.
500 connection_->NotifyBindersOnDisconnect();
501}
502
503TEST_F(ConnectionTest, Binder) {
504 // No connection should be bound initially.
505 Connection::Binder *binder = &connection_->lower_binder_;
506 EXPECT_EQ(connection_->interface_name(), binder->name_);
507 EXPECT_FALSE(binder->client_disconnect_callback_.is_null());
508 EXPECT_FALSE(binder->IsBound());
509
510 ConnectionRefPtr connection1 = GetNewConnection();
511 EXPECT_TRUE(connection1->binders_.empty());
512
513 // Bind lower |connection1| and check if it's bound.
514 binder->Attach(connection1);
515 EXPECT_TRUE(binder->IsBound());
516 EXPECT_EQ(connection1.get(), binder->connection().get());
517 ASSERT_FALSE(connection1->binders_.empty());
518 EXPECT_TRUE(binder == connection1->binders_.at(0));
519
520 // Unbind lower |connection1| and check if it's unbound.
521 binder->Attach(NULL);
522 EXPECT_FALSE(binder->IsBound());
523 EXPECT_TRUE(connection1->binders_.empty());
524
525 ConnectionRefPtr connection2 = GetNewConnection();
526
527 // Bind lower |connection1| to upper |connection2| and destroy the upper
528 // |connection2|. Make sure lower |connection1| is unbound (i.e., the
529 // disconnect callback is deregistered).
530 connection2->lower_binder_.Attach(connection1);
531 EXPECT_FALSE(connection1->binders_.empty());
532 AddDestructorExpectations();
533 connection2 = NULL;
534 EXPECT_TRUE(connection1->binders_.empty());
535
536 // Bind lower |connection1| to upper |connection_| and destroy lower
537 // |connection1|. Make sure lower |connection1| is unbound from upper
538 // |connection_| and upper |connection_|'s registered disconnect callbacks are
539 // run.
540 binder->Attach(connection1);
541 DisconnectCallbackTarget target;
542 Connection::Binder test_binder("from_test", target.callback());
543 test_binder.Attach(connection_);
544 EXPECT_CALL(target, CallTarget()).Times(1);
545 ASSERT_FALSE(connection_->binders_.empty());
546 AddDestructorExpectations();
547 connection1 = NULL;
548 EXPECT_FALSE(binder->IsBound());
549 EXPECT_FALSE(test_binder.IsBound());
550 EXPECT_TRUE(connection_->binders_.empty());
551
552 {
553 // Binding a connection to itself should be safe.
554 ConnectionRefPtr connection = GetNewConnection();
555
556 connection->lower_binder_.Attach(connection);
557
558 EXPECT_FALSE(connection->binders_.empty());
559
560 DisconnectCallbackTarget target;
561 Connection::Binder binder("test", target.callback());
562 binder.Attach(connection);
563
564 AddDestructorExpectations();
565 EXPECT_CALL(target, CallTarget()).Times(1);
566 connection = NULL;
567 }
Darin Petkov13e6d552012-05-09 14:22:23 +0200568 {
569 // Circular binding of multiple connections should be safe.
570 ConnectionRefPtr connection_a = GetNewConnection();
571 ConnectionRefPtr connection_b = GetNewConnection();
572
573 connection_a->lower_binder_.Attach(connection_b);
574 connection_b->lower_binder_.Attach(connection_a);
575
576 EXPECT_FALSE(connection_a->binders_.empty());
577 EXPECT_FALSE(connection_b->binders_.empty());
578
579 DisconnectCallbackTarget target_a;
580 DisconnectCallbackTarget target_b;
581 Connection::Binder binder_a("test_a", target_a.callback());
582 Connection::Binder binder_b("test_b", target_b.callback());
583 binder_a.Attach(connection_a);
584 binder_b.Attach(connection_b);
585
586 AddDestructorExpectations();
587 EXPECT_CALL(target_a, CallTarget()).Times(1);
588 EXPECT_CALL(target_b, CallTarget()).Times(1);
589 connection_b = NULL;
590
591 EXPECT_TRUE(connection_a->binders_.empty());
592
593 AddDestructorExpectations();
594 connection_a = NULL;
595 }
Darin Petkovef1f9fe2012-05-11 16:51:52 +0200596 {
597 // Test the weak pointer to the bound Connection. This is not a case that
598 // should occur but the weak pointer should handle it gracefully.
599 DisconnectCallbackTarget target;
600 Connection::Binder binder("test_weak", target.callback());
601 ConnectionRefPtr connection = GetNewConnection();
602 binder.Attach(connection);
603
604 // Make sure the connection doesn't notify the binder on destruction.
605 connection->binders_.clear();
606 AddDestructorExpectations();
607 EXPECT_CALL(target, CallTarget()).Times(0);
608 connection = NULL;
609
610 // Ensure no crash -- the weak pointer to connection should be NULL.
Darin Petkov5eb05422012-05-11 15:45:25 +0200611 EXPECT_FALSE(binder.connection());
Darin Petkovef1f9fe2012-05-11 16:51:52 +0200612 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