blob: c30d914e5a37042a0b209f172e24beff48b4f25d [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";
Ben Chan7fab8972014-08-10 17:14:46 -070049const int32_t kPrefix0 = 24;
50const int32_t kPrefix1 = 31;
Paul Stewartdd60e452011-08-08 11:38:36 -070051const char kSearchDomain0[] = "chromium.org";
52const char kSearchDomain1[] = "google.com";
Ben Chana6bfe872012-09-26 09:48:34 -070053} // namespace
Paul Stewartdd60e452011-08-08 11:38:36 -070054
55class ConnectionTest : public Test {
56 public:
57 ConnectionTest()
Paul Stewart9a908082011-08-31 12:18:48 -070058 : device_info_(new StrictMock<MockDeviceInfo>(
59 &control_,
60 static_cast<EventDispatcher*>(NULL),
Thieu Le3426c8f2012-01-11 17:35:11 -080061 static_cast<Metrics*>(NULL),
Paul Stewart9a908082011-08-31 12:18:48 -070062 static_cast<Manager*>(NULL))),
63 connection_(new Connection(
64 kTestDeviceInterfaceIndex0,
65 kTestDeviceName0,
Paul Stewarte00600e2012-03-16 07:08:00 -070066 Technology::kUnknown,
mukesh agrawal23ac6b72013-01-31 18:52:37 -080067 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() {
Paul Stewartc5099532013-12-12 07:53:15 -0800103 ipconfig_->UpdateProperties(properties_);
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700104 }
105
Paul Stewarte93b0382012-04-24 13:11:28 -0700106 bool PinHostRoute(ConnectionRefPtr connection,
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800107 const IPAddress trusted_ip,
108 const IPAddress gateway) {
109 return connection->PinHostRoute(trusted_ip, gateway);
Paul Stewarte93b0382012-04-24 13:11:28 -0700110 }
111
Paul Stewart4a6748d2012-07-17 14:31:36 -0700112 const IPAddress &GetLocalAddress(ConnectionRefPtr connection) {
113 return connection->local_;
114 }
115
116 const IPAddress &GetGatewayAddress(ConnectionRefPtr connection) {
117 return connection->gateway_;
118 }
119
120 bool GetHasBroadcastDomain(ConnectionRefPtr connection) {
121 return connection->has_broadcast_domain_;
122 }
123
Ben Chan7fab8972014-08-10 17:14:46 -0700124 uint32_t GetDefaultMetric() {
Paul Stewart05a42c22012-08-02 16:47:21 -0700125 return Connection::kDefaultMetric;
126 }
127
Ben Chan7fab8972014-08-10 17:14:46 -0700128 uint32_t GetNonDefaultMetricBase() {
Paul Stewart05a42c22012-08-02 16:47:21 -0700129 return Connection::kNonDefaultMetricBase;
130 }
131
Paul Stewartdd60e452011-08-08 11:38:36 -0700132 protected:
Darin Petkov13e6d552012-05-09 14:22:23 +0200133 class DisconnectCallbackTarget {
134 public:
135 DisconnectCallbackTarget()
136 : callback_(base::Bind(&DisconnectCallbackTarget::CallTarget,
137 base::Unretained(this))) {}
138
139 MOCK_METHOD0(CallTarget, void());
140 const base::Closure &callback() { return callback_; }
141
142 private:
143 base::Closure callback_;
144 };
145
146 void AddDestructorExpectations() {
147 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
148 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex0));
149 EXPECT_CALL(*device_info_.get(),
150 FlushAddresses(kTestDeviceInterfaceIndex0));
151 }
152
153 // Returns a new test connection object. The caller usually needs to call
154 // AddDestructorExpectations before destroying the object.
155 ConnectionRefPtr GetNewConnection() {
156 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex0,
157 kTestDeviceName0,
158 Technology::kUnknown,
mukesh agrawal23ac6b72013-01-31 18:52:37 -0800159 device_info_.get()));
Darin Petkov13e6d552012-05-09 14:22:23 +0200160 ReplaceSingletons(connection);
161 return connection;
162 }
163
Paul Stewart9a908082011-08-31 12:18:48 -0700164 scoped_ptr<StrictMock<MockDeviceInfo> > device_info_;
Paul Stewartdd60e452011-08-08 11:38:36 -0700165 ConnectionRefPtr connection_;
166 MockControl control_;
167 IPConfigRefPtr ipconfig_;
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700168 IPConfig::Properties properties_;
169 IPAddress local_address_;
170 IPAddress broadcast_address_;
171 IPAddress gateway_address_;
172 IPAddress default_address_;
Paul Stewartdd60e452011-08-08 11:38:36 -0700173 StrictMock<MockResolver> resolver_;
174 StrictMock<MockRoutingTable> routing_table_;
175 StrictMock<MockRTNLHandler> rtnl_handler_;
176};
177
Darin Petkov13e6d552012-05-09 14:22:23 +0200178namespace {
Paul Stewartdd60e452011-08-08 11:38:36 -0700179
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700180MATCHER_P2(IsIPAddress, address, prefix, "") {
181 IPAddress match_address(address);
182 match_address.set_prefix(prefix);
183 return match_address.Equals(arg);
184}
185
Darin Petkov13e6d552012-05-09 14:22:23 +0200186MATCHER(IsNonNullCallback, "") {
187 return !arg.is_null();
188}
189
190} // namespace
191
192TEST_F(ConnectionTest, InitState) {
193 EXPECT_EQ(kTestDeviceInterfaceIndex0, connection_->interface_index_);
194 EXPECT_EQ(kTestDeviceName0, connection_->interface_name_);
195 EXPECT_FALSE(connection_->is_default());
196 EXPECT_FALSE(connection_->routing_request_count_);
197}
198
Paul Stewartdd60e452011-08-08 11:38:36 -0700199TEST_F(ConnectionTest, AddConfig) {
Paul Stewart05a42c22012-08-02 16:47:21 -0700200 EXPECT_CALL(*device_info_,
201 HasOtherAddress(kTestDeviceInterfaceIndex0,
202 IsIPAddress(local_address_, kPrefix0)))
203 .WillOnce(Return(false));
Paul Stewartdd60e452011-08-08 11:38:36 -0700204 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700205 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
206 IsIPAddress(local_address_, kPrefix0),
207 IsIPAddress(broadcast_address_, 0),
208 IsIPAddress(default_address_, 0)));
Paul Stewart7cfca042011-12-08 14:18:17 -0800209 EXPECT_CALL(routing_table_,
210 SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700211 IsIPAddress(gateway_address_, 0),
Paul Stewart05a42c22012-08-02 16:47:21 -0700212 GetNonDefaultMetricBase() +
Paul Stewart7cfca042011-12-08 14:18:17 -0800213 kTestDeviceInterfaceIndex0));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700214 EXPECT_CALL(routing_table_,
215 ConfigureRoutes(kTestDeviceInterfaceIndex0,
216 ipconfig_,
Paul Stewart05a42c22012-08-02 16:47:21 -0700217 GetDefaultMetric()));
Paul Stewartdd60e452011-08-08 11:38:36 -0700218 connection_->UpdateFromIPConfig(ipconfig_);
Paul Stewart4a6748d2012-07-17 14:31:36 -0700219 IPAddress test_local_address(local_address_);
220 test_local_address.set_prefix(kPrefix0);
221 EXPECT_TRUE(test_local_address.Equals(GetLocalAddress(connection_)));
222 EXPECT_TRUE(gateway_address_.Equals(GetGatewayAddress(connection_)));
223 EXPECT_TRUE(GetHasBroadcastDomain(connection_));
224
225 EXPECT_CALL(routing_table_,
226 CreateLinkRoute(kTestDeviceInterfaceIndex0,
227 IsIPAddress(local_address_, kPrefix0),
228 IsIPAddress(gateway_address_, 0)))
229 .WillOnce(Return(true))
230 .WillOnce(Return(false));
231 EXPECT_TRUE(connection_->CreateGatewayRoute());
232 EXPECT_FALSE(connection_->CreateGatewayRoute());
233 connection_->has_broadcast_domain_ = false;
234 EXPECT_FALSE(connection_->CreateGatewayRoute());
Paul Stewartdd60e452011-08-08 11:38:36 -0700235
236 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
Paul Stewart05a42c22012-08-02 16:47:21 -0700237 GetDefaultMetric()));
Paul Stewartdd60e452011-08-08 11:38:36 -0700238 EXPECT_CALL(resolver_, SetDNSFromLists(
239 ipconfig_->properties().dns_servers,
mukesh agrawal23ac6b72013-01-31 18:52:37 -0800240 ipconfig_->properties().domain_search));
Paul Stewartdd60e452011-08-08 11:38:36 -0700241
Paul Stewartc681fa02012-03-02 19:40:04 -0800242 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
243 &control_,
244 reinterpret_cast<EventDispatcher *>(NULL),
245 reinterpret_cast<Metrics *>(NULL),
246 reinterpret_cast<Manager *>(NULL),
247 kTestDeviceName0,
248 string(),
249 kTestDeviceInterfaceIndex0));
250 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
251 .WillOnce(Return(device));
252 EXPECT_CALL(*device.get(), RequestPortalDetection())
253 .WillOnce(Return(true));
Paul Stewarte78ec542012-06-08 18:28:50 -0700254 EXPECT_CALL(routing_table_, FlushCache())
255 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800256 connection_->SetIsDefault(true);
Paul Stewarte78ec542012-06-08 18:28:50 -0700257 Mock::VerifyAndClearExpectations(&routing_table_);
Paul Stewartdd60e452011-08-08 11:38:36 -0700258 EXPECT_TRUE(connection_->is_default());
259
Paul Stewart7cfca042011-12-08 14:18:17 -0800260 EXPECT_CALL(routing_table_,
261 SetDefaultMetric(kTestDeviceInterfaceIndex0,
Paul Stewart05a42c22012-08-02 16:47:21 -0700262 GetNonDefaultMetricBase() +
Paul Stewart7cfca042011-12-08 14:18:17 -0800263 kTestDeviceInterfaceIndex0));
Paul Stewarte78ec542012-06-08 18:28:50 -0700264 EXPECT_CALL(routing_table_, FlushCache())
265 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800266 connection_->SetIsDefault(false);
Paul Stewartdd60e452011-08-08 11:38:36 -0700267 EXPECT_FALSE(connection_->is_default());
268}
269
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700270TEST_F(ConnectionTest, AddConfigWithPeer) {
271 const string kPeerAddress("192.168.1.222");
272 IPAddress peer_address(IPAddress::kFamilyIPv4);
273 EXPECT_TRUE(peer_address.SetAddressFromString(kPeerAddress));
274 properties_.peer_address = kPeerAddress;
275 properties_.gateway = string();
276 UpdateProperties();
Paul Stewart05a42c22012-08-02 16:47:21 -0700277 EXPECT_CALL(*device_info_,
278 HasOtherAddress(kTestDeviceInterfaceIndex0,
279 IsIPAddress(local_address_, kPrefix0)))
280 .WillOnce(Return(false));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700281 EXPECT_CALL(rtnl_handler_,
282 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
283 IsIPAddress(local_address_, kPrefix0),
284 IsIPAddress(broadcast_address_, 0),
285 IsIPAddress(peer_address, 0)));
286 EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _)).Times(0);
287 EXPECT_CALL(routing_table_,
288 ConfigureRoutes(kTestDeviceInterfaceIndex0,
289 ipconfig_,
Paul Stewart05a42c22012-08-02 16:47:21 -0700290 GetDefaultMetric()));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700291 connection_->UpdateFromIPConfig(ipconfig_);
Paul Stewart4a6748d2012-07-17 14:31:36 -0700292 EXPECT_FALSE(GetHasBroadcastDomain(connection_));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700293}
294
295TEST_F(ConnectionTest, AddConfigWithBrokenNetmask) {
296 // Assign a prefix that makes the gateway unreachable.
297 properties_.subnet_prefix = kPrefix1;
298 UpdateProperties();
299
300 // Connection should override with a prefix which will allow the
301 // gateway to be reachable.
Paul Stewart05a42c22012-08-02 16:47:21 -0700302 EXPECT_CALL(*device_info_,
303 HasOtherAddress(kTestDeviceInterfaceIndex0,
304 IsIPAddress(local_address_, kPrefix0)))
305 .WillOnce(Return(false));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700306 EXPECT_CALL(rtnl_handler_,
307 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
308 IsIPAddress(local_address_, kPrefix0),
309 IsIPAddress(broadcast_address_, 0),
310 IsIPAddress(default_address_, 0)));
311 EXPECT_CALL(routing_table_,
312 SetDefaultRoute(kTestDeviceInterfaceIndex0,
313 IsIPAddress(gateway_address_, 0),
Paul Stewart05a42c22012-08-02 16:47:21 -0700314 GetNonDefaultMetricBase() +
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700315 kTestDeviceInterfaceIndex0));
316 EXPECT_CALL(routing_table_,
317 ConfigureRoutes(kTestDeviceInterfaceIndex0,
318 ipconfig_,
Paul Stewart05a42c22012-08-02 16:47:21 -0700319 GetDefaultMetric()));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700320 connection_->UpdateFromIPConfig(ipconfig_);
321
322 // Assign a gateway address that violates the minimum plausible prefix
323 // the Connection can assign.
324 properties_.gateway = kGatewayAddress1;
325 UpdateProperties();
326
Paul Stewart49258292012-05-26 06:37:14 -0700327 IPAddress gateway_address1(IPAddress::kFamilyIPv4);
328 EXPECT_TRUE(gateway_address1.SetAddressFromString(kGatewayAddress1));
329 // Connection cannot override this prefix, so it will switch to a
330 // model where the peer address is set to the value of the gateway
331 // address.
Paul Stewart05a42c22012-08-02 16:47:21 -0700332 EXPECT_CALL(*device_info_,
333 HasOtherAddress(kTestDeviceInterfaceIndex0,
334 IsIPAddress(local_address_, kPrefix1)))
335 .WillOnce(Return(false));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700336 EXPECT_CALL(rtnl_handler_,
337 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
338 IsIPAddress(local_address_, kPrefix1),
339 IsIPAddress(broadcast_address_, 0),
Paul Stewart49258292012-05-26 06:37:14 -0700340 IsIPAddress(gateway_address1, 0)));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700341 EXPECT_CALL(routing_table_,
342 SetDefaultRoute(kTestDeviceInterfaceIndex0, _, _));
343 EXPECT_CALL(routing_table_,
344 ConfigureRoutes(kTestDeviceInterfaceIndex0, _, _));
345 connection_->UpdateFromIPConfig(ipconfig_);
346}
347
Paul Stewartdd60e452011-08-08 11:38:36 -0700348TEST_F(ConnectionTest, AddConfigReverse) {
349 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
Paul Stewart05a42c22012-08-02 16:47:21 -0700350 GetDefaultMetric()));
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800351 vector<string> empty_list;
mukesh agrawal23ac6b72013-01-31 18:52:37 -0800352 EXPECT_CALL(resolver_, SetDNSFromLists(empty_list, empty_list));
Paul Stewartc681fa02012-03-02 19:40:04 -0800353 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
354 &control_,
355 reinterpret_cast<EventDispatcher *>(NULL),
356 reinterpret_cast<Metrics *>(NULL),
357 reinterpret_cast<Manager *>(NULL),
358 kTestDeviceName0,
359 string(),
360 kTestDeviceInterfaceIndex0));
361 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
362 .WillOnce(Return(device));
363 EXPECT_CALL(*device.get(), RequestPortalDetection())
364 .WillOnce(Return(true));
Paul Stewarte78ec542012-06-08 18:28:50 -0700365 EXPECT_CALL(routing_table_, FlushCache())
366 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800367 connection_->SetIsDefault(true);
Paul Stewarte78ec542012-06-08 18:28:50 -0700368 Mock::VerifyAndClearExpectations(&routing_table_);
Paul Stewartdd60e452011-08-08 11:38:36 -0700369
Paul Stewart05a42c22012-08-02 16:47:21 -0700370 EXPECT_CALL(*device_info_,
371 HasOtherAddress(kTestDeviceInterfaceIndex0,
372 IsIPAddress(local_address_, kPrefix0)))
373 .WillOnce(Return(false));
Paul Stewartdd60e452011-08-08 11:38:36 -0700374 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700375 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
376 IsIPAddress(local_address_, kPrefix0),
377 IsIPAddress(broadcast_address_, 0),
378 IsIPAddress(default_address_, 0)));
Paul Stewartdd60e452011-08-08 11:38:36 -0700379 EXPECT_CALL(routing_table_, SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700380 IsIPAddress(gateway_address_, 0),
Paul Stewart05a42c22012-08-02 16:47:21 -0700381 GetDefaultMetric()));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700382 EXPECT_CALL(routing_table_,
383 ConfigureRoutes(kTestDeviceInterfaceIndex0,
384 ipconfig_,
Paul Stewart05a42c22012-08-02 16:47:21 -0700385 GetDefaultMetric()));
mukesh agrawal23ac6b72013-01-31 18:52:37 -0800386 EXPECT_CALL(resolver_,
387 SetDNSFromLists(ipconfig_->properties().dns_servers,
388 ipconfig_->properties().domain_search));
Paul Stewartdd60e452011-08-08 11:38:36 -0700389
390 connection_->UpdateFromIPConfig(ipconfig_);
391}
392
Paul Stewart4d1868b2012-09-10 11:58:46 -0700393TEST_F(ConnectionTest, AddConfigWithDNSDomain) {
394 const string kDomainName("chromium.org");
395 properties_.domain_search.clear();
396 properties_.domain_name = kDomainName;
397 UpdateProperties();
398 EXPECT_CALL(*device_info_, HasOtherAddress(_, _))
399 .WillOnce(Return(false));
400 EXPECT_CALL(rtnl_handler_, AddInterfaceAddress(_, _, _, _));
401 EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _));
402 EXPECT_CALL(routing_table_, ConfigureRoutes(_, _, _));
403 connection_->UpdateFromIPConfig(ipconfig_);
404
405 EXPECT_CALL(routing_table_, SetDefaultMetric(_, _));
406 vector<string> domain_search_list;
407 domain_search_list.push_back(kDomainName + ".");
mukesh agrawal23ac6b72013-01-31 18:52:37 -0800408 EXPECT_CALL(resolver_, SetDNSFromLists(_, domain_search_list));
Paul Stewart4d1868b2012-09-10 11:58:46 -0700409 DeviceRefPtr device;
410 EXPECT_CALL(*device_info_, GetDevice(_)).WillOnce(Return(device));
411 EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
412 connection_->SetIsDefault(true);
413}
414
Paul Stewart05a42c22012-08-02 16:47:21 -0700415TEST_F(ConnectionTest, HasOtherAddress) {
416 EXPECT_CALL(*device_info_,
417 HasOtherAddress(kTestDeviceInterfaceIndex0,
418 IsIPAddress(local_address_, kPrefix0)))
419 .WillOnce(Return(true));
420 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
421 EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex0));
422 EXPECT_CALL(rtnl_handler_,
423 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
424 IsIPAddress(local_address_, kPrefix0),
425 IsIPAddress(broadcast_address_, 0),
426 IsIPAddress(default_address_, 0)));
427 EXPECT_CALL(routing_table_,
428 SetDefaultRoute(kTestDeviceInterfaceIndex0,
429 IsIPAddress(gateway_address_, 0),
430 GetNonDefaultMetricBase() +
431 kTestDeviceInterfaceIndex0));
432 EXPECT_CALL(routing_table_,
433 ConfigureRoutes(kTestDeviceInterfaceIndex0,
434 ipconfig_,
435 GetDefaultMetric()));
436 connection_->UpdateFromIPConfig(ipconfig_);
437}
438
Peter Qiua89154b2014-05-23 15:45:42 -0700439TEST_F(ConnectionTest, UpdateDNSServers) {
440 const char* kDnsServers[] = {"1.1.1.1", "1.1.1.2"};
441 vector<string> dns_servers(kDnsServers, std::end(kDnsServers));
442
443 // Non-default connection.
444 connection_->is_default_ = false;
445 EXPECT_CALL(resolver_, SetDNSFromLists(_, _)).Times(0);
446 connection_->UpdateDNSServers(dns_servers);
447 Mock::VerifyAndClearExpectations(&resolver_);
448
449 // Default connection.
450 connection_->is_default_ = true;
451 EXPECT_CALL(resolver_, SetDNSFromLists(dns_servers, _));
452 connection_->UpdateDNSServers(dns_servers);
453 Mock::VerifyAndClearExpectations(&resolver_);
454}
455
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800456TEST_F(ConnectionTest, RouteRequest) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200457 ConnectionRefPtr connection = GetNewConnection();
Paul Stewartf748a362012-03-07 12:01:20 -0800458 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
459 &control_,
460 reinterpret_cast<EventDispatcher *>(NULL),
461 reinterpret_cast<Metrics *>(NULL),
462 reinterpret_cast<Manager *>(NULL),
463 kTestDeviceName0,
464 string(),
465 kTestDeviceInterfaceIndex0));
466 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
467 .WillRepeatedly(Return(device));
468 EXPECT_CALL(*device.get(), DisableReversePathFilter()).Times(1);
469 connection->RequestRouting();
470 connection->RequestRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800471
Paul Stewartf748a362012-03-07 12:01:20 -0800472 // The first release should only decrement the reference counter.
473 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800474
Paul Stewartf748a362012-03-07 12:01:20 -0800475 // Another release will re-enable reverse-path filter.
476 EXPECT_CALL(*device.get(), EnableReversePathFilter());
477 EXPECT_CALL(routing_table_, FlushCache());
478 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800479
Paul Stewartf748a362012-03-07 12:01:20 -0800480 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200481 AddDestructorExpectations();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800482}
483
Paul Stewartdd60e452011-08-08 11:38:36 -0700484TEST_F(ConnectionTest, Destructor) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200485 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex1,
486 kTestDeviceName1,
487 Technology::kUnknown,
mukesh agrawal23ac6b72013-01-31 18:52:37 -0800488 device_info_.get()));
Darin Petkov13e6d552012-05-09 14:22:23 +0200489 connection->resolver_ = &resolver_;
490 connection->routing_table_ = &routing_table_;
491 connection->rtnl_handler_ = &rtnl_handler_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800492 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex1));
Paul Stewarte93b0382012-04-24 13:11:28 -0700493 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex1));
Paul Stewart9a908082011-08-31 12:18:48 -0700494 EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex1));
Darin Petkov13e6d552012-05-09 14:22:23 +0200495 connection = NULL;
Paul Stewartdd60e452011-08-08 11:38:36 -0700496}
497
Paul Stewartf748a362012-03-07 12:01:20 -0800498TEST_F(ConnectionTest, RequestHostRoute) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200499 ConnectionRefPtr connection = GetNewConnection();
Paul Stewartf748a362012-03-07 12:01:20 -0800500 IPAddress address(IPAddress::kFamilyIPv4);
501 ASSERT_TRUE(address.SetAddressFromString(kIPAddress0));
502 size_t prefix_len = address.GetLength() * 8;
Darin Petkov13e6d552012-05-09 14:22:23 +0200503 EXPECT_CALL(routing_table_,
504 RequestRouteToHost(IsIPAddress(address, prefix_len),
505 -1,
506 kTestDeviceInterfaceIndex0,
507 IsNonNullCallback()))
Paul Stewartf748a362012-03-07 12:01:20 -0800508 .WillOnce(Return(true));
509 EXPECT_TRUE(connection->RequestHostRoute(address));
510
511 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200512 AddDestructorExpectations();
Paul Stewarte93b0382012-04-24 13:11:28 -0700513}
514
Ben Chana0163122012-09-25 15:10:52 -0700515TEST_F(ConnectionTest, BlackholeIPv6) {
516 properties_.blackhole_ipv6 = true;
517 UpdateProperties();
518 EXPECT_CALL(*device_info_, HasOtherAddress(_, _))
519 .WillOnce(Return(false));
520 EXPECT_CALL(rtnl_handler_, AddInterfaceAddress(_, _, _, _));
521 EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _));
522 EXPECT_CALL(routing_table_, ConfigureRoutes(_, _, _));
523 EXPECT_CALL(routing_table_,
524 CreateBlackholeRoute(kTestDeviceInterfaceIndex0,
525 IPAddress::kFamilyIPv6,
526 Connection::kDefaultMetric))
527 .WillOnce(Return(true));
528 connection_->UpdateFromIPConfig(ipconfig_);
529}
530
Paul Stewarte93b0382012-04-24 13:11:28 -0700531TEST_F(ConnectionTest, PinHostRoute) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200532 ConnectionRefPtr connection = GetNewConnection();
Paul Stewarte93b0382012-04-24 13:11:28 -0700533
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800534 IPAddress gateway(IPAddress::kFamilyIPv4);
535 IPAddress trusted_ip(IPAddress::kFamilyIPv4);
Paul Stewarte93b0382012-04-24 13:11:28 -0700536
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800537 // Should fail because neither IP address is set.
538 EXPECT_FALSE(PinHostRoute(connection, trusted_ip, gateway));
Paul Stewarte93b0382012-04-24 13:11:28 -0700539
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800540 static const char kGateway[] = "10.242.2.13";
541 ASSERT_TRUE(gateway.SetAddressFromString(kGateway));
Paul Stewarte93b0382012-04-24 13:11:28 -0700542
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800543 // Should fail because trusted IP is not set.
544 EXPECT_FALSE(PinHostRoute(connection, trusted_ip, gateway));
Paul Stewarte93b0382012-04-24 13:11:28 -0700545
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800546 static const char kTrustedIP[] = "10.0.1.1";
547 ASSERT_TRUE(trusted_ip.SetAddressFromString(kTrustedIP));
548
Paul Stewarte435d342013-09-27 16:41:00 -0700549 // Should pass without calling RequestRouteToHost since if the gateway
550 // is not set, there is no work to be done.
551 EXPECT_CALL(routing_table_, RequestRouteToHost(_, _, _, _)).Times(0);
552 EXPECT_TRUE(PinHostRoute(connection, trusted_ip,
553 IPAddress(gateway.family())));
554 Mock::VerifyAndClearExpectations(&routing_table_);
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800555
556 size_t prefix_len = IPAddress::GetMaxPrefixLength(trusted_ip.family());
Paul Stewarte93b0382012-04-24 13:11:28 -0700557 EXPECT_CALL(routing_table_, RequestRouteToHost(
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800558 IsIPAddress(trusted_ip, prefix_len), -1, kTestDeviceInterfaceIndex0, _))
Paul Stewarte93b0382012-04-24 13:11:28 -0700559 .WillOnce(Return(false));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800560 EXPECT_FALSE(PinHostRoute(connection, trusted_ip, gateway));
Paul Stewarte93b0382012-04-24 13:11:28 -0700561
562 EXPECT_CALL(routing_table_, RequestRouteToHost(
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800563 IsIPAddress(trusted_ip, prefix_len), -1, kTestDeviceInterfaceIndex0, _))
Paul Stewarte93b0382012-04-24 13:11:28 -0700564 .WillOnce(Return(true));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800565 EXPECT_TRUE(PinHostRoute(connection, trusted_ip, gateway));
Paul Stewarte93b0382012-04-24 13:11:28 -0700566
567 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200568 AddDestructorExpectations();
Paul Stewartf748a362012-03-07 12:01:20 -0800569}
570
Paul Stewart53a30382012-04-26 09:06:59 -0700571TEST_F(ConnectionTest, FixGatewayReachability) {
572 static const char kLocal[] = "10.242.2.13";
573 IPAddress local(IPAddress::kFamilyIPv4);
574 ASSERT_TRUE(local.SetAddressFromString(kLocal));
575 const int kPrefix = 24;
576 local.set_prefix(kPrefix);
577 IPAddress gateway(IPAddress::kFamilyIPv4);
578 IPAddress peer(IPAddress::kFamilyIPv4);
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800579 IPAddress trusted_ip(IPAddress::kFamilyIPv4);
Paul Stewart53a30382012-04-26 09:06:59 -0700580
581 // Should fail because no gateway is set.
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800582 EXPECT_FALSE(Connection::FixGatewayReachability(
583 &local, &peer, &gateway, trusted_ip));
Paul Stewart53a30382012-04-26 09:06:59 -0700584 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700585 EXPECT_FALSE(peer.IsValid());
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800586 EXPECT_FALSE(gateway.IsValid());
Paul Stewart53a30382012-04-26 09:06:59 -0700587
588 // Should succeed because with the given prefix, this gateway is reachable.
589 static const char kReachableGateway[] = "10.242.2.14";
590 ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800591 IPAddress gateway_backup(gateway);
Paul Stewart49258292012-05-26 06:37:14 -0700592 peer = IPAddress(IPAddress::kFamilyIPv4);
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800593 EXPECT_TRUE(Connection::FixGatewayReachability(
594 &local, &peer, &gateway, trusted_ip));
Paul Stewart53a30382012-04-26 09:06:59 -0700595 // Prefix should remain unchanged.
596 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700597 // Peer should remain unchanged.
598 EXPECT_FALSE(peer.IsValid());
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800599 // Gateway should remain unchanged.
600 EXPECT_TRUE(gateway_backup.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700601
602 // Should succeed because we modified the prefix to match the gateway.
603 static const char kExpandableGateway[] = "10.242.3.14";
604 ASSERT_TRUE(gateway.SetAddressFromString(kExpandableGateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800605 gateway_backup = gateway;
Paul Stewart49258292012-05-26 06:37:14 -0700606 peer = IPAddress(IPAddress::kFamilyIPv4);
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800607 EXPECT_TRUE(Connection::FixGatewayReachability(
608 &local, &peer, &gateway, trusted_ip));
Paul Stewart53a30382012-04-26 09:06:59 -0700609 // Prefix should have opened up by 1 bit.
610 EXPECT_EQ(kPrefix - 1, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700611 // Peer should remain unchanged.
612 EXPECT_FALSE(peer.IsValid());
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800613 // Gateway should remain unchanged.
614 EXPECT_TRUE(gateway_backup.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700615
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700616 // Should change models to assuming point-to-point because we cannot
Paul Stewart49258292012-05-26 06:37:14 -0700617 // plausibly expand the prefix past 8.
Paul Stewart53a30382012-04-26 09:06:59 -0700618 local.set_prefix(kPrefix);
619 static const char kUnreachableGateway[] = "11.242.2.14";
620 ASSERT_TRUE(gateway.SetAddressFromString(kUnreachableGateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800621 gateway_backup = gateway;
Paul Stewart49258292012-05-26 06:37:14 -0700622 peer = IPAddress(IPAddress::kFamilyIPv4);
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800623 EXPECT_TRUE(Connection::FixGatewayReachability(
624 &local, &peer, &gateway, trusted_ip));
Paul Stewart53a30382012-04-26 09:06:59 -0700625 // Prefix should not have changed.
626 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700627 // Peer address should be set to the gateway address.
628 EXPECT_TRUE(peer.Equals(gateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800629 // Gateway should remain unchanged.
630 EXPECT_TRUE(gateway_backup.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700631
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700632 // Should also use point-to-point model if the netmask is set to the
633 // "all-ones" addresss, even if this address could have been made
634 // accessible by plausibly changing the prefix.
635 const int kIPv4MaxPrefix =
636 IPAddress::GetMaxPrefixLength(IPAddress::kFamilyIPv4);
637 local.set_prefix(kIPv4MaxPrefix);
638 ASSERT_TRUE(gateway.SetAddressFromString(kExpandableGateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800639 gateway_backup = gateway;
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700640 peer = IPAddress(IPAddress::kFamilyIPv4);
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800641 EXPECT_TRUE(Connection::FixGatewayReachability(
642 &local, &peer, &gateway, trusted_ip));
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700643 // Prefix should not have changed.
644 EXPECT_EQ(kIPv4MaxPrefix, local.prefix());
645 // Peer address should be set to the gateway address.
646 EXPECT_TRUE(peer.Equals(gateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800647 // Gateway should remain unchanged.
648 EXPECT_TRUE(gateway_backup.Equals(gateway));
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700649
Paul Stewart49258292012-05-26 06:37:14 -0700650 // If this is a peer-to-peer interface and the peer matches the gateway,
651 // we should succeed.
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700652 local.set_prefix(kPrefix);
653 ASSERT_TRUE(gateway.SetAddressFromString(kUnreachableGateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800654 gateway_backup = gateway;
Paul Stewart53a30382012-04-26 09:06:59 -0700655 ASSERT_TRUE(peer.SetAddressFromString(kUnreachableGateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800656 EXPECT_TRUE(Connection::FixGatewayReachability(
657 &local, &peer, &gateway, trusted_ip));
Paul Stewart53a30382012-04-26 09:06:59 -0700658 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700659 EXPECT_TRUE(peer.Equals(gateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800660 EXPECT_TRUE(gateway_backup.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700661
662 // If there is a peer specified and it does not match the gateway (even
663 // if it was reachable via netmask), we should fail.
664 ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800665 EXPECT_FALSE(Connection::FixGatewayReachability(
666 &local, &peer, &gateway, trusted_ip));
Paul Stewart53a30382012-04-26 09:06:59 -0700667 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700668 EXPECT_FALSE(peer.Equals(gateway));
Paul Stewart73fcc3f2013-02-25 12:16:53 -0800669
670 // If this is a peer-to-peer interface and the peer matches the gateway,
671 // but it also matches the trusted IP address, the gateway and peer address
672 // should be modified to allow routing to work correctly.
673 ASSERT_TRUE(gateway.SetAddressFromString(kUnreachableGateway));
674 ASSERT_TRUE(peer.SetAddressFromString(kUnreachableGateway));
675 ASSERT_TRUE(trusted_ip.SetAddressFromString(kUnreachableGateway));
676 EXPECT_TRUE(Connection::FixGatewayReachability(
677 &local, &peer, &gateway, trusted_ip));
678 EXPECT_TRUE(peer.IsDefault());
679 EXPECT_TRUE(gateway.IsDefault());
Paul Stewart53a30382012-04-26 09:06:59 -0700680}
681
Darin Petkov13e6d552012-05-09 14:22:23 +0200682TEST_F(ConnectionTest, Binders) {
683 EXPECT_TRUE(connection_->binders_.empty());
684 DisconnectCallbackTarget target0;
685 DisconnectCallbackTarget target1;
686 DisconnectCallbackTarget target2;
687 DisconnectCallbackTarget target3;
688 Connection::Binder binder0("binder0", target0.callback());
689 Connection::Binder binder1("binder1", target1.callback());
690 Connection::Binder binder2("binder2", target2.callback());
691 Connection::Binder binder3("binder3", target3.callback());
692
693 binder0.Attach(connection_);
694 binder1.Attach(connection_);
695
696 EXPECT_CALL(target1, CallTarget()).Times(0);
697 binder1.Attach(connection_);
698
699 binder3.Attach(connection_);
700 binder2.Attach(connection_);
701
702 EXPECT_CALL(target3, CallTarget()).Times(0);
703 binder3.Attach(NULL);
704
705 ASSERT_EQ(3, connection_->binders_.size());
706 EXPECT_TRUE(connection_->binders_.at(0) == &binder0);
707 EXPECT_TRUE(connection_->binders_.at(1) == &binder1);
708 EXPECT_TRUE(connection_->binders_.at(2) == &binder2);
709
710 EXPECT_CALL(target0, CallTarget()).Times(1);
711 EXPECT_CALL(target1, CallTarget()).Times(1);
712 EXPECT_CALL(target2, CallTarget()).Times(1);
713 connection_->NotifyBindersOnDisconnect();
714 EXPECT_TRUE(connection_->binders_.empty());
715
716 // Should be a no-op.
717 connection_->NotifyBindersOnDisconnect();
718}
719
720TEST_F(ConnectionTest, Binder) {
721 // No connection should be bound initially.
722 Connection::Binder *binder = &connection_->lower_binder_;
723 EXPECT_EQ(connection_->interface_name(), binder->name_);
724 EXPECT_FALSE(binder->client_disconnect_callback_.is_null());
725 EXPECT_FALSE(binder->IsBound());
726
727 ConnectionRefPtr connection1 = GetNewConnection();
728 EXPECT_TRUE(connection1->binders_.empty());
729
730 // Bind lower |connection1| and check if it's bound.
731 binder->Attach(connection1);
732 EXPECT_TRUE(binder->IsBound());
733 EXPECT_EQ(connection1.get(), binder->connection().get());
734 ASSERT_FALSE(connection1->binders_.empty());
735 EXPECT_TRUE(binder == connection1->binders_.at(0));
736
737 // Unbind lower |connection1| and check if it's unbound.
738 binder->Attach(NULL);
739 EXPECT_FALSE(binder->IsBound());
740 EXPECT_TRUE(connection1->binders_.empty());
741
742 ConnectionRefPtr connection2 = GetNewConnection();
743
744 // Bind lower |connection1| to upper |connection2| and destroy the upper
745 // |connection2|. Make sure lower |connection1| is unbound (i.e., the
746 // disconnect callback is deregistered).
747 connection2->lower_binder_.Attach(connection1);
748 EXPECT_FALSE(connection1->binders_.empty());
749 AddDestructorExpectations();
750 connection2 = NULL;
751 EXPECT_TRUE(connection1->binders_.empty());
752
753 // Bind lower |connection1| to upper |connection_| and destroy lower
754 // |connection1|. Make sure lower |connection1| is unbound from upper
755 // |connection_| and upper |connection_|'s registered disconnect callbacks are
756 // run.
757 binder->Attach(connection1);
758 DisconnectCallbackTarget target;
759 Connection::Binder test_binder("from_test", target.callback());
760 test_binder.Attach(connection_);
761 EXPECT_CALL(target, CallTarget()).Times(1);
762 ASSERT_FALSE(connection_->binders_.empty());
763 AddDestructorExpectations();
764 connection1 = NULL;
765 EXPECT_FALSE(binder->IsBound());
766 EXPECT_FALSE(test_binder.IsBound());
767 EXPECT_TRUE(connection_->binders_.empty());
768
769 {
770 // Binding a connection to itself should be safe.
771 ConnectionRefPtr connection = GetNewConnection();
772
773 connection->lower_binder_.Attach(connection);
774
775 EXPECT_FALSE(connection->binders_.empty());
776
777 DisconnectCallbackTarget target;
778 Connection::Binder binder("test", target.callback());
779 binder.Attach(connection);
780
781 AddDestructorExpectations();
782 EXPECT_CALL(target, CallTarget()).Times(1);
783 connection = NULL;
784 }
Darin Petkov13e6d552012-05-09 14:22:23 +0200785 {
786 // Circular binding of multiple connections should be safe.
787 ConnectionRefPtr connection_a = GetNewConnection();
788 ConnectionRefPtr connection_b = GetNewConnection();
789
790 connection_a->lower_binder_.Attach(connection_b);
791 connection_b->lower_binder_.Attach(connection_a);
792
793 EXPECT_FALSE(connection_a->binders_.empty());
794 EXPECT_FALSE(connection_b->binders_.empty());
795
796 DisconnectCallbackTarget target_a;
797 DisconnectCallbackTarget target_b;
798 Connection::Binder binder_a("test_a", target_a.callback());
799 Connection::Binder binder_b("test_b", target_b.callback());
800 binder_a.Attach(connection_a);
801 binder_b.Attach(connection_b);
802
803 AddDestructorExpectations();
804 EXPECT_CALL(target_a, CallTarget()).Times(1);
805 EXPECT_CALL(target_b, CallTarget()).Times(1);
806 connection_b = NULL;
807
808 EXPECT_TRUE(connection_a->binders_.empty());
809
810 AddDestructorExpectations();
811 connection_a = NULL;
812 }
Darin Petkovef1f9fe2012-05-11 16:51:52 +0200813 {
814 // Test the weak pointer to the bound Connection. This is not a case that
815 // should occur but the weak pointer should handle it gracefully.
816 DisconnectCallbackTarget target;
817 Connection::Binder binder("test_weak", target.callback());
818 ConnectionRefPtr connection = GetNewConnection();
819 binder.Attach(connection);
820
821 // Make sure the connection doesn't notify the binder on destruction.
822 connection->binders_.clear();
823 AddDestructorExpectations();
824 EXPECT_CALL(target, CallTarget()).Times(0);
825 connection = NULL;
826
827 // Ensure no crash -- the weak pointer to connection should be NULL.
Darin Petkov5eb05422012-05-11 15:45:25 +0200828 EXPECT_FALSE(binder.connection());
Darin Petkovef1f9fe2012-05-11 16:51:52 +0200829 binder.Attach(NULL);
830 }
Darin Petkov13e6d552012-05-09 14:22:23 +0200831}
832
833TEST_F(ConnectionTest, OnRouteQueryResponse) {
834 Connection::Binder *binder = &connection_->lower_binder_;
835 ConnectionRefPtr connection = GetNewConnection();
836 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
837 &control_,
838 reinterpret_cast<EventDispatcher *>(NULL),
839 reinterpret_cast<Metrics *>(NULL),
840 reinterpret_cast<Manager *>(NULL),
841 kTestDeviceName1,
842 string(),
843 kTestDeviceInterfaceIndex1));
844
845 // Make sure we unbind the old lower connection even if we can't lookup the
846 // lower connection device.
847 binder->Attach(connection);
848 scoped_refptr<MockDevice> null_device;
849 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
850 .WillOnce(Return(null_device));
851 connection_->OnRouteQueryResponse(
852 kTestDeviceInterfaceIndex1, RoutingTableEntry());
853 EXPECT_FALSE(binder->IsBound());
854
855 // Check for graceful handling of a device with no connection.
856 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
857 .WillOnce(Return(device));
858 connection_->OnRouteQueryResponse(
859 kTestDeviceInterfaceIndex1, RoutingTableEntry());
860 EXPECT_FALSE(binder->IsBound());
861
mukesh agrawalf407d592013-07-31 11:37:57 -0700862 // Create a mock connection that will be used for binding.
Paul Stewart4a6748d2012-07-17 14:31:36 -0700863 scoped_refptr<MockConnection> mock_connection(
864 new StrictMock<MockConnection>(device_info_.get()));
865 EXPECT_CALL(*device_info_.get(),
866 FlushAddresses(mock_connection->interface_index()));
867 const string kInterfaceName(kTestDeviceName0);
868 EXPECT_CALL(*mock_connection, interface_name())
869 .WillRepeatedly(ReturnRef(kInterfaceName));
870 device->connection_ = mock_connection;
Darin Petkov13e6d552012-05-09 14:22:23 +0200871 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
872 .WillOnce(Return(device));
Paul Stewart4a6748d2012-07-17 14:31:36 -0700873
Ben Chana6bfe872012-09-26 09:48:34 -0700874 // Check that the binding process completes, causing its upper
Paul Stewart4a6748d2012-07-17 14:31:36 -0700875 // connection to create a gateway route.
876 EXPECT_CALL(*mock_connection, CreateGatewayRoute())
877 .WillOnce(Return(true));
Paul Stewart8596f9f2013-03-14 07:58:26 -0700878
879 // Ensure that the Device is notified of the change to the connection.
880 EXPECT_CALL(*device, OnConnectionUpdated()).Times(1);
Darin Petkov13e6d552012-05-09 14:22:23 +0200881 connection_->OnRouteQueryResponse(
882 kTestDeviceInterfaceIndex1, RoutingTableEntry());
Paul Stewart4a6748d2012-07-17 14:31:36 -0700883
884 // Check that the upper connection is bound to the lower connection.
Darin Petkov13e6d552012-05-09 14:22:23 +0200885 EXPECT_TRUE(binder->IsBound());
Paul Stewart4a6748d2012-07-17 14:31:36 -0700886 EXPECT_EQ(mock_connection.get(), binder->connection().get());
Darin Petkov13e6d552012-05-09 14:22:23 +0200887
888 device->connection_ = NULL;
889 AddDestructorExpectations();
890 connection = NULL;
891}
892
Alex Deymofddc09a2013-07-03 18:41:31 -0700893TEST_F(ConnectionTest, GetCarrierConnection) {
894 EXPECT_EQ(connection_.get(), connection_->GetCarrierConnection().get());
895
896 ConnectionRefPtr connection1 = GetNewConnection();
897 ConnectionRefPtr connection2 = GetNewConnection();
898 ConnectionRefPtr connection3 = GetNewConnection();
899
900 connection_->lower_binder_.Attach(connection1);
901 EXPECT_EQ(connection1.get(), connection_->GetCarrierConnection().get());
902
903 connection1->lower_binder_.Attach(connection2);
904 EXPECT_EQ(connection2.get(), connection_->GetCarrierConnection().get());
905
906 connection2->lower_binder_.Attach(connection3);
907 EXPECT_EQ(connection3.get(), connection_->GetCarrierConnection().get());
908
909 // Create a cycle back to |connection1|.
910 connection3->lower_binder_.Attach(connection1);
911 EXPECT_EQ(NULL, connection_->GetCarrierConnection().get());
912
913 AddDestructorExpectations();
914 connection3 = NULL;
915
916 AddDestructorExpectations();
917 connection2 = NULL;
918
919 AddDestructorExpectations();
920 connection1 = NULL;
921}
922
Paul Stewartdd60e452011-08-08 11:38:36 -0700923} // namespace shill