blob: 2fd5bd0940737394f1155f10feda27d99ef75406 [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";
53} // namespace {}
54
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 Stewart9a908082011-08-31 12:18:48 -070067 device_info_.get())),
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070068 ipconfig_(new IPConfig(&control_, kTestDeviceName0)),
69 local_address_(IPAddress::kFamilyIPv4),
70 broadcast_address_(IPAddress::kFamilyIPv4),
71 gateway_address_(IPAddress::kFamilyIPv4),
72 default_address_(IPAddress::kFamilyIPv4) {}
Paul Stewartdd60e452011-08-08 11:38:36 -070073
74 virtual void SetUp() {
Paul Stewartc8f4bef2011-12-13 09:45:51 -080075 ReplaceSingletons(connection_);
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070076 properties_.address = kIPAddress0;
77 properties_.subnet_prefix = kPrefix0;
78 properties_.gateway = kGatewayAddress0;
79 properties_.broadcast_address = kBroadcastAddress0;
80 properties_.dns_servers.push_back(kNameServer0);
81 properties_.dns_servers.push_back(kNameServer1);
82 properties_.domain_search.push_back(kSearchDomain0);
83 properties_.domain_search.push_back(kSearchDomain1);
84 properties_.address_family = IPAddress::kFamilyIPv4;
85 UpdateProperties();
86 EXPECT_TRUE(local_address_.SetAddressFromString(kIPAddress0));
87 EXPECT_TRUE(broadcast_address_.SetAddressFromString(kBroadcastAddress0));
88 EXPECT_TRUE(gateway_address_.SetAddressFromString(kGatewayAddress0));
Paul Stewartdd60e452011-08-08 11:38:36 -070089 }
90
Paul Stewart9a908082011-08-31 12:18:48 -070091 virtual void TearDown() {
Darin Petkov13e6d552012-05-09 14:22:23 +020092 AddDestructorExpectations();
Paul Stewarte93b0382012-04-24 13:11:28 -070093 connection_ = NULL;
Paul Stewart9a908082011-08-31 12:18:48 -070094 }
95
Paul Stewartc8f4bef2011-12-13 09:45:51 -080096 void ReplaceSingletons(ConnectionRefPtr connection) {
97 connection->resolver_ = &resolver_;
98 connection->routing_table_ = &routing_table_;
99 connection->rtnl_handler_ = &rtnl_handler_;
100 }
101
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700102 void UpdateProperties() {
103 ipconfig_->UpdateProperties(properties_, true);
104 }
105
Paul Stewarte93b0382012-04-24 13:11:28 -0700106 bool PinHostRoute(ConnectionRefPtr connection,
107 const IPConfig::Properties &properties) {
108 return connection->PinHostRoute(properties);
109 }
110
Paul Stewart4a6748d2012-07-17 14:31:36 -0700111 const IPAddress &GetLocalAddress(ConnectionRefPtr connection) {
112 return connection->local_;
113 }
114
115 const IPAddress &GetGatewayAddress(ConnectionRefPtr connection) {
116 return connection->gateway_;
117 }
118
119 bool GetHasBroadcastDomain(ConnectionRefPtr connection) {
120 return connection->has_broadcast_domain_;
121 }
122
Paul Stewartdd60e452011-08-08 11:38:36 -0700123 protected:
Darin Petkov13e6d552012-05-09 14:22:23 +0200124 class DisconnectCallbackTarget {
125 public:
126 DisconnectCallbackTarget()
127 : callback_(base::Bind(&DisconnectCallbackTarget::CallTarget,
128 base::Unretained(this))) {}
129
130 MOCK_METHOD0(CallTarget, void());
131 const base::Closure &callback() { return callback_; }
132
133 private:
134 base::Closure callback_;
135 };
136
137 void AddDestructorExpectations() {
138 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
139 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex0));
140 EXPECT_CALL(*device_info_.get(),
141 FlushAddresses(kTestDeviceInterfaceIndex0));
142 }
143
144 // Returns a new test connection object. The caller usually needs to call
145 // AddDestructorExpectations before destroying the object.
146 ConnectionRefPtr GetNewConnection() {
147 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex0,
148 kTestDeviceName0,
149 Technology::kUnknown,
150 device_info_.get()));
151 ReplaceSingletons(connection);
152 return connection;
153 }
154
Paul Stewart9a908082011-08-31 12:18:48 -0700155 scoped_ptr<StrictMock<MockDeviceInfo> > device_info_;
Paul Stewartdd60e452011-08-08 11:38:36 -0700156 ConnectionRefPtr connection_;
157 MockControl control_;
158 IPConfigRefPtr ipconfig_;
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700159 IPConfig::Properties properties_;
160 IPAddress local_address_;
161 IPAddress broadcast_address_;
162 IPAddress gateway_address_;
163 IPAddress default_address_;
Paul Stewartdd60e452011-08-08 11:38:36 -0700164 StrictMock<MockResolver> resolver_;
165 StrictMock<MockRoutingTable> routing_table_;
166 StrictMock<MockRTNLHandler> rtnl_handler_;
167};
168
Darin Petkov13e6d552012-05-09 14:22:23 +0200169namespace {
Paul Stewartdd60e452011-08-08 11:38:36 -0700170
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700171MATCHER_P2(IsIPAddress, address, prefix, "") {
172 IPAddress match_address(address);
173 match_address.set_prefix(prefix);
174 return match_address.Equals(arg);
175}
176
Darin Petkov13e6d552012-05-09 14:22:23 +0200177MATCHER(IsNonNullCallback, "") {
178 return !arg.is_null();
179}
180
181} // namespace
182
183TEST_F(ConnectionTest, InitState) {
184 EXPECT_EQ(kTestDeviceInterfaceIndex0, connection_->interface_index_);
185 EXPECT_EQ(kTestDeviceName0, connection_->interface_name_);
186 EXPECT_FALSE(connection_->is_default());
187 EXPECT_FALSE(connection_->routing_request_count_);
188}
189
Paul Stewartdd60e452011-08-08 11:38:36 -0700190TEST_F(ConnectionTest, AddConfig) {
191 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700192 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
193 IsIPAddress(local_address_, kPrefix0),
194 IsIPAddress(broadcast_address_, 0),
195 IsIPAddress(default_address_, 0)));
Paul Stewart7cfca042011-12-08 14:18:17 -0800196 EXPECT_CALL(routing_table_,
197 SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700198 IsIPAddress(gateway_address_, 0),
Paul Stewart7cfca042011-12-08 14:18:17 -0800199 Connection::kNonDefaultMetricBase +
200 kTestDeviceInterfaceIndex0));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700201 EXPECT_CALL(routing_table_,
202 ConfigureRoutes(kTestDeviceInterfaceIndex0,
203 ipconfig_,
204 Connection::kDefaultMetric));
Paul Stewartdd60e452011-08-08 11:38:36 -0700205 connection_->UpdateFromIPConfig(ipconfig_);
Paul Stewart4a6748d2012-07-17 14:31:36 -0700206 IPAddress test_local_address(local_address_);
207 test_local_address.set_prefix(kPrefix0);
208 EXPECT_TRUE(test_local_address.Equals(GetLocalAddress(connection_)));
209 EXPECT_TRUE(gateway_address_.Equals(GetGatewayAddress(connection_)));
210 EXPECT_TRUE(GetHasBroadcastDomain(connection_));
211
212 EXPECT_CALL(routing_table_,
213 CreateLinkRoute(kTestDeviceInterfaceIndex0,
214 IsIPAddress(local_address_, kPrefix0),
215 IsIPAddress(gateway_address_, 0)))
216 .WillOnce(Return(true))
217 .WillOnce(Return(false));
218 EXPECT_TRUE(connection_->CreateGatewayRoute());
219 EXPECT_FALSE(connection_->CreateGatewayRoute());
220 connection_->has_broadcast_domain_ = false;
221 EXPECT_FALSE(connection_->CreateGatewayRoute());
Paul Stewartdd60e452011-08-08 11:38:36 -0700222
223 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
224 Connection::kDefaultMetric));
225 EXPECT_CALL(resolver_, SetDNSFromLists(
226 ipconfig_->properties().dns_servers,
227 ipconfig_->properties().domain_search));
228
Paul Stewartc681fa02012-03-02 19:40:04 -0800229 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
230 &control_,
231 reinterpret_cast<EventDispatcher *>(NULL),
232 reinterpret_cast<Metrics *>(NULL),
233 reinterpret_cast<Manager *>(NULL),
234 kTestDeviceName0,
235 string(),
236 kTestDeviceInterfaceIndex0));
237 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
238 .WillOnce(Return(device));
239 EXPECT_CALL(*device.get(), RequestPortalDetection())
240 .WillOnce(Return(true));
Paul Stewarte78ec542012-06-08 18:28:50 -0700241 EXPECT_CALL(routing_table_, FlushCache())
242 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800243 connection_->SetIsDefault(true);
Paul Stewarte78ec542012-06-08 18:28:50 -0700244 Mock::VerifyAndClearExpectations(&routing_table_);
Paul Stewartdd60e452011-08-08 11:38:36 -0700245 EXPECT_TRUE(connection_->is_default());
246
Paul Stewart7cfca042011-12-08 14:18:17 -0800247 EXPECT_CALL(routing_table_,
248 SetDefaultMetric(kTestDeviceInterfaceIndex0,
249 Connection::kNonDefaultMetricBase +
250 kTestDeviceInterfaceIndex0));
Paul Stewarte78ec542012-06-08 18:28:50 -0700251 EXPECT_CALL(routing_table_, FlushCache())
252 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800253 connection_->SetIsDefault(false);
Paul Stewartdd60e452011-08-08 11:38:36 -0700254 EXPECT_FALSE(connection_->is_default());
255}
256
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700257TEST_F(ConnectionTest, AddConfigWithPeer) {
258 const string kPeerAddress("192.168.1.222");
259 IPAddress peer_address(IPAddress::kFamilyIPv4);
260 EXPECT_TRUE(peer_address.SetAddressFromString(kPeerAddress));
261 properties_.peer_address = kPeerAddress;
262 properties_.gateway = string();
263 UpdateProperties();
264 EXPECT_CALL(rtnl_handler_,
265 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
266 IsIPAddress(local_address_, kPrefix0),
267 IsIPAddress(broadcast_address_, 0),
268 IsIPAddress(peer_address, 0)));
269 EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _)).Times(0);
270 EXPECT_CALL(routing_table_,
271 ConfigureRoutes(kTestDeviceInterfaceIndex0,
272 ipconfig_,
273 Connection::kDefaultMetric));
274 connection_->UpdateFromIPConfig(ipconfig_);
Paul Stewart4a6748d2012-07-17 14:31:36 -0700275 EXPECT_FALSE(GetHasBroadcastDomain(connection_));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700276}
277
278TEST_F(ConnectionTest, AddConfigWithBrokenNetmask) {
279 // Assign a prefix that makes the gateway unreachable.
280 properties_.subnet_prefix = kPrefix1;
281 UpdateProperties();
282
283 // Connection should override with a prefix which will allow the
284 // gateway to be reachable.
285 EXPECT_CALL(rtnl_handler_,
286 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
287 IsIPAddress(local_address_, kPrefix0),
288 IsIPAddress(broadcast_address_, 0),
289 IsIPAddress(default_address_, 0)));
290 EXPECT_CALL(routing_table_,
291 SetDefaultRoute(kTestDeviceInterfaceIndex0,
292 IsIPAddress(gateway_address_, 0),
293 Connection::kNonDefaultMetricBase +
294 kTestDeviceInterfaceIndex0));
295 EXPECT_CALL(routing_table_,
296 ConfigureRoutes(kTestDeviceInterfaceIndex0,
297 ipconfig_,
298 Connection::kDefaultMetric));
299 connection_->UpdateFromIPConfig(ipconfig_);
300
301 // Assign a gateway address that violates the minimum plausible prefix
302 // the Connection can assign.
303 properties_.gateway = kGatewayAddress1;
304 UpdateProperties();
305
Paul Stewart49258292012-05-26 06:37:14 -0700306 IPAddress gateway_address1(IPAddress::kFamilyIPv4);
307 EXPECT_TRUE(gateway_address1.SetAddressFromString(kGatewayAddress1));
308 // Connection cannot override this prefix, so it will switch to a
309 // model where the peer address is set to the value of the gateway
310 // address.
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700311 EXPECT_CALL(rtnl_handler_,
312 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
313 IsIPAddress(local_address_, kPrefix1),
314 IsIPAddress(broadcast_address_, 0),
Paul Stewart49258292012-05-26 06:37:14 -0700315 IsIPAddress(gateway_address1, 0)));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700316 EXPECT_CALL(routing_table_,
317 SetDefaultRoute(kTestDeviceInterfaceIndex0, _, _));
318 EXPECT_CALL(routing_table_,
319 ConfigureRoutes(kTestDeviceInterfaceIndex0, _, _));
320 connection_->UpdateFromIPConfig(ipconfig_);
321}
322
Paul Stewartdd60e452011-08-08 11:38:36 -0700323TEST_F(ConnectionTest, AddConfigReverse) {
324 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
325 Connection::kDefaultMetric));
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800326 vector<string> empty_list;
Paul Stewartdd60e452011-08-08 11:38:36 -0700327 EXPECT_CALL(resolver_, SetDNSFromLists(empty_list, empty_list));
Paul Stewartc681fa02012-03-02 19:40:04 -0800328 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
329 &control_,
330 reinterpret_cast<EventDispatcher *>(NULL),
331 reinterpret_cast<Metrics *>(NULL),
332 reinterpret_cast<Manager *>(NULL),
333 kTestDeviceName0,
334 string(),
335 kTestDeviceInterfaceIndex0));
336 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
337 .WillOnce(Return(device));
338 EXPECT_CALL(*device.get(), RequestPortalDetection())
339 .WillOnce(Return(true));
Paul Stewarte78ec542012-06-08 18:28:50 -0700340 EXPECT_CALL(routing_table_, FlushCache())
341 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800342 connection_->SetIsDefault(true);
Paul Stewarte78ec542012-06-08 18:28:50 -0700343 Mock::VerifyAndClearExpectations(&routing_table_);
Paul Stewartdd60e452011-08-08 11:38:36 -0700344
345 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700346 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
347 IsIPAddress(local_address_, kPrefix0),
348 IsIPAddress(broadcast_address_, 0),
349 IsIPAddress(default_address_, 0)));
Paul Stewartdd60e452011-08-08 11:38:36 -0700350 EXPECT_CALL(routing_table_, SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700351 IsIPAddress(gateway_address_, 0),
352 Connection::kDefaultMetric));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700353 EXPECT_CALL(routing_table_,
354 ConfigureRoutes(kTestDeviceInterfaceIndex0,
355 ipconfig_,
356 Connection::kDefaultMetric));
Paul Stewartdd60e452011-08-08 11:38:36 -0700357 EXPECT_CALL(resolver_, SetDNSFromIPConfig(ipconfig_));
358
359 connection_->UpdateFromIPConfig(ipconfig_);
360}
361
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800362TEST_F(ConnectionTest, RouteRequest) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200363 ConnectionRefPtr connection = GetNewConnection();
Paul Stewartf748a362012-03-07 12:01:20 -0800364 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
365 &control_,
366 reinterpret_cast<EventDispatcher *>(NULL),
367 reinterpret_cast<Metrics *>(NULL),
368 reinterpret_cast<Manager *>(NULL),
369 kTestDeviceName0,
370 string(),
371 kTestDeviceInterfaceIndex0));
372 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
373 .WillRepeatedly(Return(device));
374 EXPECT_CALL(*device.get(), DisableReversePathFilter()).Times(1);
375 connection->RequestRouting();
376 connection->RequestRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800377
Paul Stewartf748a362012-03-07 12:01:20 -0800378 // The first release should only decrement the reference counter.
379 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800380
Paul Stewartf748a362012-03-07 12:01:20 -0800381 // Another release will re-enable reverse-path filter.
382 EXPECT_CALL(*device.get(), EnableReversePathFilter());
383 EXPECT_CALL(routing_table_, FlushCache());
384 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800385
Paul Stewartf748a362012-03-07 12:01:20 -0800386 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200387 AddDestructorExpectations();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800388}
389
Paul Stewartdd60e452011-08-08 11:38:36 -0700390TEST_F(ConnectionTest, Destructor) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200391 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex1,
392 kTestDeviceName1,
393 Technology::kUnknown,
394 device_info_.get()));
395 connection->resolver_ = &resolver_;
396 connection->routing_table_ = &routing_table_;
397 connection->rtnl_handler_ = &rtnl_handler_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800398 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex1));
Paul Stewarte93b0382012-04-24 13:11:28 -0700399 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex1));
Paul Stewart9a908082011-08-31 12:18:48 -0700400 EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex1));
Darin Petkov13e6d552012-05-09 14:22:23 +0200401 connection = NULL;
Paul Stewartdd60e452011-08-08 11:38:36 -0700402}
403
Paul Stewartf748a362012-03-07 12:01:20 -0800404TEST_F(ConnectionTest, RequestHostRoute) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200405 ConnectionRefPtr connection = GetNewConnection();
Paul Stewartf748a362012-03-07 12:01:20 -0800406 IPAddress address(IPAddress::kFamilyIPv4);
407 ASSERT_TRUE(address.SetAddressFromString(kIPAddress0));
408 size_t prefix_len = address.GetLength() * 8;
Darin Petkov13e6d552012-05-09 14:22:23 +0200409 EXPECT_CALL(routing_table_,
410 RequestRouteToHost(IsIPAddress(address, prefix_len),
411 -1,
412 kTestDeviceInterfaceIndex0,
413 IsNonNullCallback()))
Paul Stewartf748a362012-03-07 12:01:20 -0800414 .WillOnce(Return(true));
415 EXPECT_TRUE(connection->RequestHostRoute(address));
416
417 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200418 AddDestructorExpectations();
Paul Stewarte93b0382012-04-24 13:11:28 -0700419}
420
421TEST_F(ConnectionTest, PinHostRoute) {
422 static const char kGateway[] = "10.242.2.13";
423 static const char kNetwork[] = "10.242.2.1";
424
Darin Petkov13e6d552012-05-09 14:22:23 +0200425 ConnectionRefPtr connection = GetNewConnection();
Paul Stewarte93b0382012-04-24 13:11:28 -0700426
427 IPConfig::Properties props;
428 props.address_family = IPAddress::kFamilyIPv4;
429 EXPECT_FALSE(PinHostRoute(connection, props));
430
431 props.gateway = kGateway;
432 EXPECT_FALSE(PinHostRoute(connection, props));
433
434 props.gateway.clear();
435 props.trusted_ip = "xxx";
436 EXPECT_FALSE(PinHostRoute(connection, props));
437
438 props.gateway = kGateway;
439 EXPECT_FALSE(PinHostRoute(connection, props));
440
441 props.trusted_ip = kNetwork;
442 IPAddress address(IPAddress::kFamilyIPv4);
443 ASSERT_TRUE(address.SetAddressFromString(kNetwork));
444 size_t prefix_len = address.GetLength() * 8;
445 EXPECT_CALL(routing_table_, RequestRouteToHost(
Darin Petkovabf6d282012-05-08 15:49:05 +0200446 IsIPAddress(address, prefix_len), -1, kTestDeviceInterfaceIndex0, _))
Paul Stewarte93b0382012-04-24 13:11:28 -0700447 .WillOnce(Return(false));
448 EXPECT_FALSE(PinHostRoute(connection, props));
449
450 EXPECT_CALL(routing_table_, RequestRouteToHost(
Darin Petkovabf6d282012-05-08 15:49:05 +0200451 IsIPAddress(address, prefix_len), -1, kTestDeviceInterfaceIndex0, _))
Paul Stewarte93b0382012-04-24 13:11:28 -0700452 .WillOnce(Return(true));
453 EXPECT_TRUE(PinHostRoute(connection, props));
454
455 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200456 AddDestructorExpectations();
Paul Stewartf748a362012-03-07 12:01:20 -0800457}
458
Paul Stewart53a30382012-04-26 09:06:59 -0700459TEST_F(ConnectionTest, FixGatewayReachability) {
460 static const char kLocal[] = "10.242.2.13";
461 IPAddress local(IPAddress::kFamilyIPv4);
462 ASSERT_TRUE(local.SetAddressFromString(kLocal));
463 const int kPrefix = 24;
464 local.set_prefix(kPrefix);
465 IPAddress gateway(IPAddress::kFamilyIPv4);
466 IPAddress peer(IPAddress::kFamilyIPv4);
467
468 // Should fail because no gateway is set.
Paul Stewart49258292012-05-26 06:37:14 -0700469 EXPECT_FALSE(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_FALSE(peer.IsValid());
Paul Stewart53a30382012-04-26 09:06:59 -0700472
473 // Should succeed because with the given prefix, this gateway is reachable.
474 static const char kReachableGateway[] = "10.242.2.14";
475 ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700476 peer = IPAddress(IPAddress::kFamilyIPv4);
477 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700478 // Prefix should remain unchanged.
479 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700480 // Peer should remain unchanged.
481 EXPECT_FALSE(peer.IsValid());
Paul Stewart53a30382012-04-26 09:06:59 -0700482
483 // Should succeed because we modified the prefix to match the gateway.
484 static const char kExpandableGateway[] = "10.242.3.14";
485 ASSERT_TRUE(gateway.SetAddressFromString(kExpandableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700486 peer = IPAddress(IPAddress::kFamilyIPv4);
487 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700488 // Prefix should have opened up by 1 bit.
489 EXPECT_EQ(kPrefix - 1, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700490 // Peer should remain unchanged.
491 EXPECT_FALSE(peer.IsValid());
Paul Stewart53a30382012-04-26 09:06:59 -0700492
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700493 // Should change models to assuming point-to-point because we cannot
Paul Stewart49258292012-05-26 06:37:14 -0700494 // plausibly expand the prefix past 8.
Paul Stewart53a30382012-04-26 09:06:59 -0700495 local.set_prefix(kPrefix);
496 static const char kUnreachableGateway[] = "11.242.2.14";
497 ASSERT_TRUE(gateway.SetAddressFromString(kUnreachableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700498 peer = IPAddress(IPAddress::kFamilyIPv4);
499 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700500 // Prefix should not have changed.
501 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700502 // Peer address should be set to the gateway address.
503 EXPECT_TRUE(peer.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700504
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700505 // Should also use point-to-point model if the netmask is set to the
506 // "all-ones" addresss, even if this address could have been made
507 // accessible by plausibly changing the prefix.
508 const int kIPv4MaxPrefix =
509 IPAddress::GetMaxPrefixLength(IPAddress::kFamilyIPv4);
510 local.set_prefix(kIPv4MaxPrefix);
511 ASSERT_TRUE(gateway.SetAddressFromString(kExpandableGateway));
512 peer = IPAddress(IPAddress::kFamilyIPv4);
513 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
514 // Prefix should not have changed.
515 EXPECT_EQ(kIPv4MaxPrefix, local.prefix());
516 // Peer address should be set to the gateway address.
517 EXPECT_TRUE(peer.Equals(gateway));
518
Paul Stewart49258292012-05-26 06:37:14 -0700519 // If this is a peer-to-peer interface and the peer matches the gateway,
520 // we should succeed.
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700521 local.set_prefix(kPrefix);
522 ASSERT_TRUE(gateway.SetAddressFromString(kUnreachableGateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700523 ASSERT_TRUE(peer.SetAddressFromString(kUnreachableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700524 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700525 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700526 EXPECT_TRUE(peer.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700527
528 // If there is a peer specified and it does not match the gateway (even
529 // if it was reachable via netmask), we should fail.
530 ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700531 EXPECT_FALSE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700532 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700533 EXPECT_FALSE(peer.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700534}
535
Darin Petkov13e6d552012-05-09 14:22:23 +0200536TEST_F(ConnectionTest, Binders) {
537 EXPECT_TRUE(connection_->binders_.empty());
538 DisconnectCallbackTarget target0;
539 DisconnectCallbackTarget target1;
540 DisconnectCallbackTarget target2;
541 DisconnectCallbackTarget target3;
542 Connection::Binder binder0("binder0", target0.callback());
543 Connection::Binder binder1("binder1", target1.callback());
544 Connection::Binder binder2("binder2", target2.callback());
545 Connection::Binder binder3("binder3", target3.callback());
546
547 binder0.Attach(connection_);
548 binder1.Attach(connection_);
549
550 EXPECT_CALL(target1, CallTarget()).Times(0);
551 binder1.Attach(connection_);
552
553 binder3.Attach(connection_);
554 binder2.Attach(connection_);
555
556 EXPECT_CALL(target3, CallTarget()).Times(0);
557 binder3.Attach(NULL);
558
559 ASSERT_EQ(3, connection_->binders_.size());
560 EXPECT_TRUE(connection_->binders_.at(0) == &binder0);
561 EXPECT_TRUE(connection_->binders_.at(1) == &binder1);
562 EXPECT_TRUE(connection_->binders_.at(2) == &binder2);
563
564 EXPECT_CALL(target0, CallTarget()).Times(1);
565 EXPECT_CALL(target1, CallTarget()).Times(1);
566 EXPECT_CALL(target2, CallTarget()).Times(1);
567 connection_->NotifyBindersOnDisconnect();
568 EXPECT_TRUE(connection_->binders_.empty());
569
570 // Should be a no-op.
571 connection_->NotifyBindersOnDisconnect();
572}
573
574TEST_F(ConnectionTest, Binder) {
575 // No connection should be bound initially.
576 Connection::Binder *binder = &connection_->lower_binder_;
577 EXPECT_EQ(connection_->interface_name(), binder->name_);
578 EXPECT_FALSE(binder->client_disconnect_callback_.is_null());
579 EXPECT_FALSE(binder->IsBound());
580
581 ConnectionRefPtr connection1 = GetNewConnection();
582 EXPECT_TRUE(connection1->binders_.empty());
583
584 // Bind lower |connection1| and check if it's bound.
585 binder->Attach(connection1);
586 EXPECT_TRUE(binder->IsBound());
587 EXPECT_EQ(connection1.get(), binder->connection().get());
588 ASSERT_FALSE(connection1->binders_.empty());
589 EXPECT_TRUE(binder == connection1->binders_.at(0));
590
591 // Unbind lower |connection1| and check if it's unbound.
592 binder->Attach(NULL);
593 EXPECT_FALSE(binder->IsBound());
594 EXPECT_TRUE(connection1->binders_.empty());
595
596 ConnectionRefPtr connection2 = GetNewConnection();
597
598 // Bind lower |connection1| to upper |connection2| and destroy the upper
599 // |connection2|. Make sure lower |connection1| is unbound (i.e., the
600 // disconnect callback is deregistered).
601 connection2->lower_binder_.Attach(connection1);
602 EXPECT_FALSE(connection1->binders_.empty());
603 AddDestructorExpectations();
604 connection2 = NULL;
605 EXPECT_TRUE(connection1->binders_.empty());
606
607 // Bind lower |connection1| to upper |connection_| and destroy lower
608 // |connection1|. Make sure lower |connection1| is unbound from upper
609 // |connection_| and upper |connection_|'s registered disconnect callbacks are
610 // run.
611 binder->Attach(connection1);
612 DisconnectCallbackTarget target;
613 Connection::Binder test_binder("from_test", target.callback());
614 test_binder.Attach(connection_);
615 EXPECT_CALL(target, CallTarget()).Times(1);
616 ASSERT_FALSE(connection_->binders_.empty());
617 AddDestructorExpectations();
618 connection1 = NULL;
619 EXPECT_FALSE(binder->IsBound());
620 EXPECT_FALSE(test_binder.IsBound());
621 EXPECT_TRUE(connection_->binders_.empty());
622
623 {
624 // Binding a connection to itself should be safe.
625 ConnectionRefPtr connection = GetNewConnection();
626
627 connection->lower_binder_.Attach(connection);
628
629 EXPECT_FALSE(connection->binders_.empty());
630
631 DisconnectCallbackTarget target;
632 Connection::Binder binder("test", target.callback());
633 binder.Attach(connection);
634
635 AddDestructorExpectations();
636 EXPECT_CALL(target, CallTarget()).Times(1);
637 connection = NULL;
638 }
Darin Petkov13e6d552012-05-09 14:22:23 +0200639 {
640 // Circular binding of multiple connections should be safe.
641 ConnectionRefPtr connection_a = GetNewConnection();
642 ConnectionRefPtr connection_b = GetNewConnection();
643
644 connection_a->lower_binder_.Attach(connection_b);
645 connection_b->lower_binder_.Attach(connection_a);
646
647 EXPECT_FALSE(connection_a->binders_.empty());
648 EXPECT_FALSE(connection_b->binders_.empty());
649
650 DisconnectCallbackTarget target_a;
651 DisconnectCallbackTarget target_b;
652 Connection::Binder binder_a("test_a", target_a.callback());
653 Connection::Binder binder_b("test_b", target_b.callback());
654 binder_a.Attach(connection_a);
655 binder_b.Attach(connection_b);
656
657 AddDestructorExpectations();
658 EXPECT_CALL(target_a, CallTarget()).Times(1);
659 EXPECT_CALL(target_b, CallTarget()).Times(1);
660 connection_b = NULL;
661
662 EXPECT_TRUE(connection_a->binders_.empty());
663
664 AddDestructorExpectations();
665 connection_a = NULL;
666 }
Darin Petkovef1f9fe2012-05-11 16:51:52 +0200667 {
668 // Test the weak pointer to the bound Connection. This is not a case that
669 // should occur but the weak pointer should handle it gracefully.
670 DisconnectCallbackTarget target;
671 Connection::Binder binder("test_weak", target.callback());
672 ConnectionRefPtr connection = GetNewConnection();
673 binder.Attach(connection);
674
675 // Make sure the connection doesn't notify the binder on destruction.
676 connection->binders_.clear();
677 AddDestructorExpectations();
678 EXPECT_CALL(target, CallTarget()).Times(0);
679 connection = NULL;
680
681 // Ensure no crash -- the weak pointer to connection should be NULL.
Darin Petkov5eb05422012-05-11 15:45:25 +0200682 EXPECT_FALSE(binder.connection());
Darin Petkovef1f9fe2012-05-11 16:51:52 +0200683 binder.Attach(NULL);
684 }
Darin Petkov13e6d552012-05-09 14:22:23 +0200685}
686
687TEST_F(ConnectionTest, OnRouteQueryResponse) {
688 Connection::Binder *binder = &connection_->lower_binder_;
689 ConnectionRefPtr connection = GetNewConnection();
690 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
691 &control_,
692 reinterpret_cast<EventDispatcher *>(NULL),
693 reinterpret_cast<Metrics *>(NULL),
694 reinterpret_cast<Manager *>(NULL),
695 kTestDeviceName1,
696 string(),
697 kTestDeviceInterfaceIndex1));
698
699 // Make sure we unbind the old lower connection even if we can't lookup the
700 // lower connection device.
701 binder->Attach(connection);
702 scoped_refptr<MockDevice> null_device;
703 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
704 .WillOnce(Return(null_device));
705 connection_->OnRouteQueryResponse(
706 kTestDeviceInterfaceIndex1, RoutingTableEntry());
707 EXPECT_FALSE(binder->IsBound());
708
709 // Check for graceful handling of a device with no connection.
710 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
711 .WillOnce(Return(device));
712 connection_->OnRouteQueryResponse(
713 kTestDeviceInterfaceIndex1, RoutingTableEntry());
714 EXPECT_FALSE(binder->IsBound());
715
Paul Stewart4a6748d2012-07-17 14:31:36 -0700716 // Create a mock connection that will be used fo binding.
717 scoped_refptr<MockConnection> mock_connection(
718 new StrictMock<MockConnection>(device_info_.get()));
719 EXPECT_CALL(*device_info_.get(),
720 FlushAddresses(mock_connection->interface_index()));
721 const string kInterfaceName(kTestDeviceName0);
722 EXPECT_CALL(*mock_connection, interface_name())
723 .WillRepeatedly(ReturnRef(kInterfaceName));
724 device->connection_ = mock_connection;
Darin Petkov13e6d552012-05-09 14:22:23 +0200725 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
726 .WillOnce(Return(device));
Paul Stewart4a6748d2012-07-17 14:31:36 -0700727
728 // Check that the the binding process completes, causing its upper
729 // connection to create a gateway route.
730 EXPECT_CALL(*mock_connection, CreateGatewayRoute())
731 .WillOnce(Return(true));
Darin Petkov13e6d552012-05-09 14:22:23 +0200732 connection_->OnRouteQueryResponse(
733 kTestDeviceInterfaceIndex1, RoutingTableEntry());
Paul Stewart4a6748d2012-07-17 14:31:36 -0700734
735 // Check that the upper connection is bound to the lower connection.
Darin Petkov13e6d552012-05-09 14:22:23 +0200736 EXPECT_TRUE(binder->IsBound());
Paul Stewart4a6748d2012-07-17 14:31:36 -0700737 EXPECT_EQ(mock_connection.get(), binder->connection().get());
Darin Petkov13e6d552012-05-09 14:22:23 +0200738
739 device->connection_ = NULL;
740 AddDestructorExpectations();
741 connection = NULL;
742}
743
Paul Stewartdd60e452011-08-08 11:38:36 -0700744} // namespace shill