blob: 05d60139735d70b77f8112c7622c814544792781 [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
Paul Stewart49258292012-05-26 06:37:14 -0700270 IPAddress gateway_address1(IPAddress::kFamilyIPv4);
271 EXPECT_TRUE(gateway_address1.SetAddressFromString(kGatewayAddress1));
272 // Connection cannot override this prefix, so it will switch to a
273 // model where the peer address is set to the value of the gateway
274 // address.
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700275 EXPECT_CALL(rtnl_handler_,
276 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
277 IsIPAddress(local_address_, kPrefix1),
278 IsIPAddress(broadcast_address_, 0),
Paul Stewart49258292012-05-26 06:37:14 -0700279 IsIPAddress(gateway_address1, 0)));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700280 EXPECT_CALL(routing_table_,
281 SetDefaultRoute(kTestDeviceInterfaceIndex0, _, _));
282 EXPECT_CALL(routing_table_,
283 ConfigureRoutes(kTestDeviceInterfaceIndex0, _, _));
284 connection_->UpdateFromIPConfig(ipconfig_);
285}
286
Paul Stewartdd60e452011-08-08 11:38:36 -0700287TEST_F(ConnectionTest, AddConfigReverse) {
288 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
289 Connection::kDefaultMetric));
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800290 vector<string> empty_list;
Paul Stewartdd60e452011-08-08 11:38:36 -0700291 EXPECT_CALL(resolver_, SetDNSFromLists(empty_list, empty_list));
Paul Stewartc681fa02012-03-02 19:40:04 -0800292 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
293 &control_,
294 reinterpret_cast<EventDispatcher *>(NULL),
295 reinterpret_cast<Metrics *>(NULL),
296 reinterpret_cast<Manager *>(NULL),
297 kTestDeviceName0,
298 string(),
299 kTestDeviceInterfaceIndex0));
300 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
301 .WillOnce(Return(device));
302 EXPECT_CALL(*device.get(), RequestPortalDetection())
303 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800304 connection_->SetIsDefault(true);
Paul Stewartdd60e452011-08-08 11:38:36 -0700305
306 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700307 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
308 IsIPAddress(local_address_, kPrefix0),
309 IsIPAddress(broadcast_address_, 0),
310 IsIPAddress(default_address_, 0)));
Paul Stewartdd60e452011-08-08 11:38:36 -0700311 EXPECT_CALL(routing_table_, SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700312 IsIPAddress(gateway_address_, 0),
313 Connection::kDefaultMetric));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700314 EXPECT_CALL(routing_table_,
315 ConfigureRoutes(kTestDeviceInterfaceIndex0,
316 ipconfig_,
317 Connection::kDefaultMetric));
Paul Stewartdd60e452011-08-08 11:38:36 -0700318 EXPECT_CALL(resolver_, SetDNSFromIPConfig(ipconfig_));
319
320 connection_->UpdateFromIPConfig(ipconfig_);
321}
322
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800323TEST_F(ConnectionTest, RouteRequest) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200324 ConnectionRefPtr connection = GetNewConnection();
Paul Stewartf748a362012-03-07 12:01:20 -0800325 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
326 &control_,
327 reinterpret_cast<EventDispatcher *>(NULL),
328 reinterpret_cast<Metrics *>(NULL),
329 reinterpret_cast<Manager *>(NULL),
330 kTestDeviceName0,
331 string(),
332 kTestDeviceInterfaceIndex0));
333 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
334 .WillRepeatedly(Return(device));
335 EXPECT_CALL(*device.get(), DisableReversePathFilter()).Times(1);
336 connection->RequestRouting();
337 connection->RequestRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800338
Paul Stewartf748a362012-03-07 12:01:20 -0800339 // The first release should only decrement the reference counter.
340 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800341
Paul Stewartf748a362012-03-07 12:01:20 -0800342 // Another release will re-enable reverse-path filter.
343 EXPECT_CALL(*device.get(), EnableReversePathFilter());
344 EXPECT_CALL(routing_table_, FlushCache());
345 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800346
Paul Stewartf748a362012-03-07 12:01:20 -0800347 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200348 AddDestructorExpectations();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800349}
350
Paul Stewartdd60e452011-08-08 11:38:36 -0700351TEST_F(ConnectionTest, Destructor) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200352 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex1,
353 kTestDeviceName1,
354 Technology::kUnknown,
355 device_info_.get()));
356 connection->resolver_ = &resolver_;
357 connection->routing_table_ = &routing_table_;
358 connection->rtnl_handler_ = &rtnl_handler_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800359 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex1));
Paul Stewarte93b0382012-04-24 13:11:28 -0700360 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex1));
Paul Stewart9a908082011-08-31 12:18:48 -0700361 EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex1));
Darin Petkov13e6d552012-05-09 14:22:23 +0200362 connection = NULL;
Paul Stewartdd60e452011-08-08 11:38:36 -0700363}
364
Paul Stewartf748a362012-03-07 12:01:20 -0800365TEST_F(ConnectionTest, RequestHostRoute) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200366 ConnectionRefPtr connection = GetNewConnection();
Paul Stewartf748a362012-03-07 12:01:20 -0800367 IPAddress address(IPAddress::kFamilyIPv4);
368 ASSERT_TRUE(address.SetAddressFromString(kIPAddress0));
369 size_t prefix_len = address.GetLength() * 8;
Darin Petkov13e6d552012-05-09 14:22:23 +0200370 EXPECT_CALL(routing_table_,
371 RequestRouteToHost(IsIPAddress(address, prefix_len),
372 -1,
373 kTestDeviceInterfaceIndex0,
374 IsNonNullCallback()))
Paul Stewartf748a362012-03-07 12:01:20 -0800375 .WillOnce(Return(true));
376 EXPECT_TRUE(connection->RequestHostRoute(address));
377
378 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200379 AddDestructorExpectations();
Paul Stewarte93b0382012-04-24 13:11:28 -0700380}
381
382TEST_F(ConnectionTest, PinHostRoute) {
383 static const char kGateway[] = "10.242.2.13";
384 static const char kNetwork[] = "10.242.2.1";
385
Darin Petkov13e6d552012-05-09 14:22:23 +0200386 ConnectionRefPtr connection = GetNewConnection();
Paul Stewarte93b0382012-04-24 13:11:28 -0700387
388 IPConfig::Properties props;
389 props.address_family = IPAddress::kFamilyIPv4;
390 EXPECT_FALSE(PinHostRoute(connection, props));
391
392 props.gateway = kGateway;
393 EXPECT_FALSE(PinHostRoute(connection, props));
394
395 props.gateway.clear();
396 props.trusted_ip = "xxx";
397 EXPECT_FALSE(PinHostRoute(connection, props));
398
399 props.gateway = kGateway;
400 EXPECT_FALSE(PinHostRoute(connection, props));
401
402 props.trusted_ip = kNetwork;
403 IPAddress address(IPAddress::kFamilyIPv4);
404 ASSERT_TRUE(address.SetAddressFromString(kNetwork));
405 size_t prefix_len = address.GetLength() * 8;
406 EXPECT_CALL(routing_table_, RequestRouteToHost(
Darin Petkovabf6d282012-05-08 15:49:05 +0200407 IsIPAddress(address, prefix_len), -1, kTestDeviceInterfaceIndex0, _))
Paul Stewarte93b0382012-04-24 13:11:28 -0700408 .WillOnce(Return(false));
409 EXPECT_FALSE(PinHostRoute(connection, props));
410
411 EXPECT_CALL(routing_table_, RequestRouteToHost(
Darin Petkovabf6d282012-05-08 15:49:05 +0200412 IsIPAddress(address, prefix_len), -1, kTestDeviceInterfaceIndex0, _))
Paul Stewarte93b0382012-04-24 13:11:28 -0700413 .WillOnce(Return(true));
414 EXPECT_TRUE(PinHostRoute(connection, props));
415
416 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200417 AddDestructorExpectations();
Paul Stewartf748a362012-03-07 12:01:20 -0800418}
419
Paul Stewart53a30382012-04-26 09:06:59 -0700420TEST_F(ConnectionTest, FixGatewayReachability) {
421 static const char kLocal[] = "10.242.2.13";
422 IPAddress local(IPAddress::kFamilyIPv4);
423 ASSERT_TRUE(local.SetAddressFromString(kLocal));
424 const int kPrefix = 24;
425 local.set_prefix(kPrefix);
426 IPAddress gateway(IPAddress::kFamilyIPv4);
427 IPAddress peer(IPAddress::kFamilyIPv4);
428
429 // Should fail because no gateway is set.
Paul Stewart49258292012-05-26 06:37:14 -0700430 EXPECT_FALSE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700431 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700432 EXPECT_FALSE(peer.IsValid());
Paul Stewart53a30382012-04-26 09:06:59 -0700433
434 // Should succeed because with the given prefix, this gateway is reachable.
435 static const char kReachableGateway[] = "10.242.2.14";
436 ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700437 peer = IPAddress(IPAddress::kFamilyIPv4);
438 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700439 // Prefix should remain unchanged.
440 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700441 // Peer should remain unchanged.
442 EXPECT_FALSE(peer.IsValid());
Paul Stewart53a30382012-04-26 09:06:59 -0700443
444 // Should succeed because we modified the prefix to match the gateway.
445 static const char kExpandableGateway[] = "10.242.3.14";
446 ASSERT_TRUE(gateway.SetAddressFromString(kExpandableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700447 peer = IPAddress(IPAddress::kFamilyIPv4);
448 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700449 // Prefix should have opened up by 1 bit.
450 EXPECT_EQ(kPrefix - 1, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700451 // Peer should remain unchanged.
452 EXPECT_FALSE(peer.IsValid());
Paul Stewart53a30382012-04-26 09:06:59 -0700453
Paul Stewart49258292012-05-26 06:37:14 -0700454 // Should change models to assuming peer-to-pear because we cannot
455 // plausibly expand the prefix past 8.
Paul Stewart53a30382012-04-26 09:06:59 -0700456 local.set_prefix(kPrefix);
457 static const char kUnreachableGateway[] = "11.242.2.14";
458 ASSERT_TRUE(gateway.SetAddressFromString(kUnreachableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700459 peer = IPAddress(IPAddress::kFamilyIPv4);
460 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700461 // Prefix should not have changed.
462 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700463 // Peer address should be set to the gateway address.
464 EXPECT_TRUE(peer.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700465
Paul Stewart49258292012-05-26 06:37:14 -0700466 // If this is a peer-to-peer interface and the peer matches the gateway,
467 // we should succeed.
Paul Stewart53a30382012-04-26 09:06:59 -0700468 ASSERT_TRUE(peer.SetAddressFromString(kUnreachableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700469 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700470 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700471 EXPECT_TRUE(peer.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700472
473 // If there is a peer specified and it does not match the gateway (even
474 // if it was reachable via netmask), we should fail.
475 ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700476 EXPECT_FALSE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700477 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700478 EXPECT_FALSE(peer.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700479}
480
Darin Petkov13e6d552012-05-09 14:22:23 +0200481TEST_F(ConnectionTest, Binders) {
482 EXPECT_TRUE(connection_->binders_.empty());
483 DisconnectCallbackTarget target0;
484 DisconnectCallbackTarget target1;
485 DisconnectCallbackTarget target2;
486 DisconnectCallbackTarget target3;
487 Connection::Binder binder0("binder0", target0.callback());
488 Connection::Binder binder1("binder1", target1.callback());
489 Connection::Binder binder2("binder2", target2.callback());
490 Connection::Binder binder3("binder3", target3.callback());
491
492 binder0.Attach(connection_);
493 binder1.Attach(connection_);
494
495 EXPECT_CALL(target1, CallTarget()).Times(0);
496 binder1.Attach(connection_);
497
498 binder3.Attach(connection_);
499 binder2.Attach(connection_);
500
501 EXPECT_CALL(target3, CallTarget()).Times(0);
502 binder3.Attach(NULL);
503
504 ASSERT_EQ(3, connection_->binders_.size());
505 EXPECT_TRUE(connection_->binders_.at(0) == &binder0);
506 EXPECT_TRUE(connection_->binders_.at(1) == &binder1);
507 EXPECT_TRUE(connection_->binders_.at(2) == &binder2);
508
509 EXPECT_CALL(target0, CallTarget()).Times(1);
510 EXPECT_CALL(target1, CallTarget()).Times(1);
511 EXPECT_CALL(target2, CallTarget()).Times(1);
512 connection_->NotifyBindersOnDisconnect();
513 EXPECT_TRUE(connection_->binders_.empty());
514
515 // Should be a no-op.
516 connection_->NotifyBindersOnDisconnect();
517}
518
519TEST_F(ConnectionTest, Binder) {
520 // No connection should be bound initially.
521 Connection::Binder *binder = &connection_->lower_binder_;
522 EXPECT_EQ(connection_->interface_name(), binder->name_);
523 EXPECT_FALSE(binder->client_disconnect_callback_.is_null());
524 EXPECT_FALSE(binder->IsBound());
525
526 ConnectionRefPtr connection1 = GetNewConnection();
527 EXPECT_TRUE(connection1->binders_.empty());
528
529 // Bind lower |connection1| and check if it's bound.
530 binder->Attach(connection1);
531 EXPECT_TRUE(binder->IsBound());
532 EXPECT_EQ(connection1.get(), binder->connection().get());
533 ASSERT_FALSE(connection1->binders_.empty());
534 EXPECT_TRUE(binder == connection1->binders_.at(0));
535
536 // Unbind lower |connection1| and check if it's unbound.
537 binder->Attach(NULL);
538 EXPECT_FALSE(binder->IsBound());
539 EXPECT_TRUE(connection1->binders_.empty());
540
541 ConnectionRefPtr connection2 = GetNewConnection();
542
543 // Bind lower |connection1| to upper |connection2| and destroy the upper
544 // |connection2|. Make sure lower |connection1| is unbound (i.e., the
545 // disconnect callback is deregistered).
546 connection2->lower_binder_.Attach(connection1);
547 EXPECT_FALSE(connection1->binders_.empty());
548 AddDestructorExpectations();
549 connection2 = NULL;
550 EXPECT_TRUE(connection1->binders_.empty());
551
552 // Bind lower |connection1| to upper |connection_| and destroy lower
553 // |connection1|. Make sure lower |connection1| is unbound from upper
554 // |connection_| and upper |connection_|'s registered disconnect callbacks are
555 // run.
556 binder->Attach(connection1);
557 DisconnectCallbackTarget target;
558 Connection::Binder test_binder("from_test", target.callback());
559 test_binder.Attach(connection_);
560 EXPECT_CALL(target, CallTarget()).Times(1);
561 ASSERT_FALSE(connection_->binders_.empty());
562 AddDestructorExpectations();
563 connection1 = NULL;
564 EXPECT_FALSE(binder->IsBound());
565 EXPECT_FALSE(test_binder.IsBound());
566 EXPECT_TRUE(connection_->binders_.empty());
567
568 {
569 // Binding a connection to itself should be safe.
570 ConnectionRefPtr connection = GetNewConnection();
571
572 connection->lower_binder_.Attach(connection);
573
574 EXPECT_FALSE(connection->binders_.empty());
575
576 DisconnectCallbackTarget target;
577 Connection::Binder binder("test", target.callback());
578 binder.Attach(connection);
579
580 AddDestructorExpectations();
581 EXPECT_CALL(target, CallTarget()).Times(1);
582 connection = NULL;
583 }
Darin Petkov13e6d552012-05-09 14:22:23 +0200584 {
585 // Circular binding of multiple connections should be safe.
586 ConnectionRefPtr connection_a = GetNewConnection();
587 ConnectionRefPtr connection_b = GetNewConnection();
588
589 connection_a->lower_binder_.Attach(connection_b);
590 connection_b->lower_binder_.Attach(connection_a);
591
592 EXPECT_FALSE(connection_a->binders_.empty());
593 EXPECT_FALSE(connection_b->binders_.empty());
594
595 DisconnectCallbackTarget target_a;
596 DisconnectCallbackTarget target_b;
597 Connection::Binder binder_a("test_a", target_a.callback());
598 Connection::Binder binder_b("test_b", target_b.callback());
599 binder_a.Attach(connection_a);
600 binder_b.Attach(connection_b);
601
602 AddDestructorExpectations();
603 EXPECT_CALL(target_a, CallTarget()).Times(1);
604 EXPECT_CALL(target_b, CallTarget()).Times(1);
605 connection_b = NULL;
606
607 EXPECT_TRUE(connection_a->binders_.empty());
608
609 AddDestructorExpectations();
610 connection_a = NULL;
611 }
Darin Petkovef1f9fe2012-05-11 16:51:52 +0200612 {
613 // Test the weak pointer to the bound Connection. This is not a case that
614 // should occur but the weak pointer should handle it gracefully.
615 DisconnectCallbackTarget target;
616 Connection::Binder binder("test_weak", target.callback());
617 ConnectionRefPtr connection = GetNewConnection();
618 binder.Attach(connection);
619
620 // Make sure the connection doesn't notify the binder on destruction.
621 connection->binders_.clear();
622 AddDestructorExpectations();
623 EXPECT_CALL(target, CallTarget()).Times(0);
624 connection = NULL;
625
626 // Ensure no crash -- the weak pointer to connection should be NULL.
Darin Petkov5eb05422012-05-11 15:45:25 +0200627 EXPECT_FALSE(binder.connection());
Darin Petkovef1f9fe2012-05-11 16:51:52 +0200628 binder.Attach(NULL);
629 }
Darin Petkov13e6d552012-05-09 14:22:23 +0200630}
631
632TEST_F(ConnectionTest, OnRouteQueryResponse) {
633 Connection::Binder *binder = &connection_->lower_binder_;
634 ConnectionRefPtr connection = GetNewConnection();
635 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
636 &control_,
637 reinterpret_cast<EventDispatcher *>(NULL),
638 reinterpret_cast<Metrics *>(NULL),
639 reinterpret_cast<Manager *>(NULL),
640 kTestDeviceName1,
641 string(),
642 kTestDeviceInterfaceIndex1));
643
644 // Make sure we unbind the old lower connection even if we can't lookup the
645 // lower connection device.
646 binder->Attach(connection);
647 scoped_refptr<MockDevice> null_device;
648 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
649 .WillOnce(Return(null_device));
650 connection_->OnRouteQueryResponse(
651 kTestDeviceInterfaceIndex1, RoutingTableEntry());
652 EXPECT_FALSE(binder->IsBound());
653
654 // Check for graceful handling of a device with no connection.
655 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
656 .WillOnce(Return(device));
657 connection_->OnRouteQueryResponse(
658 kTestDeviceInterfaceIndex1, RoutingTableEntry());
659 EXPECT_FALSE(binder->IsBound());
660
661 // Check that the upper connection is bound to the lower connection.
662 device->connection_ = connection;
663 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
664 .WillOnce(Return(device));
665 connection_->OnRouteQueryResponse(
666 kTestDeviceInterfaceIndex1, RoutingTableEntry());
667 EXPECT_TRUE(binder->IsBound());
668 EXPECT_EQ(connection.get(), binder->connection().get());
669
670 device->connection_ = NULL;
671 AddDestructorExpectations();
672 connection = NULL;
673}
674
Paul Stewartdd60e452011-08-08 11:38:36 -0700675} // namespace shill