blob: 5a23456970526cd38d85bf5cc36ecaff58f8f5f7 [file] [log] [blame]
Thieu Le3426c8f2012-01-11 17:35:11 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Darin Petkove0a312e2011-07-20 13:45:28 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <string>
6
Chris Masone2aa97072011-08-09 17:35:08 -07007#include <glib.h>
Darin Petkove0a312e2011-07-20 13:45:28 -07008#include <gtest/gtest.h>
9#include <net/if.h>
Chris Masone2aa97072011-08-09 17:35:08 -070010#include <sys/socket.h>
11#include <linux/netlink.h> // Needs typedefs from sys/socket.h.
12#include <linux/rtnetlink.h>
Darin Petkove0a312e2011-07-20 13:45:28 -070013#include <sys/ioctl.h>
14
Eric Shienbrood3e20a232012-02-16 11:35:56 -050015#include <base/bind.h>
16
Chris Masone2aa97072011-08-09 17:35:08 -070017#include "shill/manager.h"
18#include "shill/mock_control.h"
19#include "shill/mock_glib.h"
Chris Masone2ae797d2011-08-23 20:41:00 -070020#include "shill/mock_manager.h"
Thieu Le3426c8f2012-01-11 17:35:11 -080021#include "shill/mock_metrics.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070022#include "shill/mock_sockets.h"
23#include "shill/rtnl_handler.h"
Chris Masone2aa97072011-08-09 17:35:08 -070024#include "shill/rtnl_message.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070025
Eric Shienbrood3e20a232012-02-16 11:35:56 -050026using base::Bind;
27using base::Callback;
28using base::Unretained;
Darin Petkove0a312e2011-07-20 13:45:28 -070029using std::string;
30using testing::_;
Chris Masone2aa97072011-08-09 17:35:08 -070031using testing::A;
Darin Petkove0a312e2011-07-20 13:45:28 -070032using testing::DoAll;
33using testing::Return;
34using testing::StrictMock;
35using testing::Test;
36
37namespace shill {
38
39namespace {
40
41const int kTestInterfaceIndex = 4;
42
43ACTION(SetInterfaceIndex) {
44 if (arg2) {
45 reinterpret_cast<struct ifreq *>(arg2)->ifr_ifindex = kTestInterfaceIndex;
46 }
47}
48
Chris Masone2aa97072011-08-09 17:35:08 -070049class TestEventDispatcher : public EventDispatcher {
50 public:
Paul Stewart26b327e2011-10-19 11:38:09 -070051 virtual IOHandler *CreateInputHandler(
mukesh agrawal1830fa12011-09-26 14:31:40 -070052 int /*fd*/,
Paul Stewart5f06a0e2012-12-20 11:11:33 -080053 const IOHandler::InputCallback &/*input_callback*/,
54 const IOHandler::ErrorCallback &/*error_callback*/) {
Chris Masone2aa97072011-08-09 17:35:08 -070055 return NULL;
56 }
57};
58
Darin Petkove0a312e2011-07-20 13:45:28 -070059} // namespace
60
61class RTNLHandlerTest : public Test {
Chris Masone2aa97072011-08-09 17:35:08 -070062 public:
63 RTNLHandlerTest()
Thieu Le6c1e3bb2013-02-06 15:20:35 -080064 : metrics_(&dispatcher_),
65 manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
Eric Shienbrood3e20a232012-02-16 11:35:56 -050066 callback_(Bind(&RTNLHandlerTest::HandlerCallback, Unretained(this))) {
Chris Masone2aa97072011-08-09 17:35:08 -070067 }
68
69 virtual void TearDown() {
70 RTNLHandler::GetInstance()->Stop();
71 SetSockets(NULL);
72 }
73
Eric Shienbrood3e20a232012-02-16 11:35:56 -050074 MOCK_METHOD1(HandlerCallback, void(const RTNLMessage &));
Chris Masone2aa97072011-08-09 17:35:08 -070075
Darin Petkove0a312e2011-07-20 13:45:28 -070076 protected:
Chris Masone2aa97072011-08-09 17:35:08 -070077 static const int kTestSocket;
78 static const int kTestDeviceIndex;
79 static const char kTestDeviceName[];
80
81 void AddLink();
82 void StartRTNLHandler();
83 void StopRTNLHandler();
84
Darin Petkove0a312e2011-07-20 13:45:28 -070085 void SetSockets(Sockets *sockets) {
86 RTNLHandler::GetInstance()->sockets_ = sockets;
87 }
88
Darin Petkove0a312e2011-07-20 13:45:28 -070089 StrictMock<MockSockets> sockets_;
Chris Masone2aa97072011-08-09 17:35:08 -070090 MockGLib glib_;
91 MockControl control_interface_;
Thieu Le3426c8f2012-01-11 17:35:11 -080092 MockMetrics metrics_;
Chris Masone2ae797d2011-08-23 20:41:00 -070093 MockManager manager_;
Chris Masone2aa97072011-08-09 17:35:08 -070094 TestEventDispatcher dispatcher_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -050095 Callback<void(const RTNLMessage &)> callback_;
Darin Petkove0a312e2011-07-20 13:45:28 -070096};
97
Chris Masone2aa97072011-08-09 17:35:08 -070098const int RTNLHandlerTest::kTestSocket = 123;
99const int RTNLHandlerTest::kTestDeviceIndex = 123456;
100const char RTNLHandlerTest::kTestDeviceName[] = "test-device";
101
102void RTNLHandlerTest::StartRTNLHandler() {
103 EXPECT_CALL(sockets_, Socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE))
104 .WillOnce(Return(kTestSocket));
105 EXPECT_CALL(sockets_, Bind(kTestSocket, _, sizeof(sockaddr_nl)))
106 .WillOnce(Return(0));
Julius Wernerf253c842012-12-20 14:52:30 -0800107 EXPECT_CALL(sockets_, SetReceiveBuffer(kTestSocket, _)).WillOnce(Return(0));
Chris Masone2aa97072011-08-09 17:35:08 -0700108 RTNLHandler::GetInstance()->Start(&dispatcher_, &sockets_);
109}
110
111void RTNLHandlerTest::StopRTNLHandler() {
112 EXPECT_CALL(sockets_, Close(kTestSocket)).WillOnce(Return(0));
113 RTNLHandler::GetInstance()->Stop();
114}
115
116void RTNLHandlerTest::AddLink() {
Paul Stewart9a908082011-08-31 12:18:48 -0700117 RTNLMessage message(RTNLMessage::kTypeLink,
118 RTNLMessage::kModeAdd,
Chris Masone2aa97072011-08-09 17:35:08 -0700119 0,
120 0,
121 0,
122 kTestDeviceIndex,
Paul Stewart7355ce12011-09-02 10:47:01 -0700123 IPAddress::kFamilyIPv4);
Chris Masone2aa97072011-08-09 17:35:08 -0700124 message.SetAttribute(static_cast<uint16>(IFLA_IFNAME),
Gary Morain41780232012-07-31 15:08:31 -0700125 ByteString(string(kTestDeviceName), true));
Chris Masone2aa97072011-08-09 17:35:08 -0700126 ByteString b(message.Encode());
127 InputData data(b.GetData(), b.GetLength());
128 RTNLHandler::GetInstance()->ParseRTNL(&data);
129}
130
131TEST_F(RTNLHandlerTest, AddLinkTest) {
132 StartRTNLHandler();
133 scoped_ptr<RTNLListener> link_listener(
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500134 new RTNLListener(RTNLHandler::kRequestLink, callback_));
Chris Masone2aa97072011-08-09 17:35:08 -0700135
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500136 EXPECT_CALL(*this, HandlerCallback(A<const RTNLMessage &>())).Times(1);
Chris Masone2aa97072011-08-09 17:35:08 -0700137
138 AddLink();
139
140 StopRTNLHandler();
141}
142
143
Darin Petkove0a312e2011-07-20 13:45:28 -0700144TEST_F(RTNLHandlerTest, GetInterfaceName) {
Chris Masone2aa97072011-08-09 17:35:08 -0700145 SetSockets(&sockets_);
Darin Petkove0a312e2011-07-20 13:45:28 -0700146 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex(""));
147 {
148 struct ifreq ifr;
149 string name(sizeof(ifr.ifr_name), 'x');
150 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex(name));
151 }
152
153 const int kTestSocket = 123;
154 EXPECT_CALL(sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
155 .Times(3)
156 .WillOnce(Return(-1))
157 .WillRepeatedly(Return(kTestSocket));
158 EXPECT_CALL(sockets_, Ioctl(kTestSocket, SIOCGIFINDEX, _))
159 .WillOnce(Return(-1))
160 .WillOnce(DoAll(SetInterfaceIndex(), Return(0)));
161 EXPECT_CALL(sockets_, Close(kTestSocket))
Chris Masone2aa97072011-08-09 17:35:08 -0700162 .Times(3)
Darin Petkove0a312e2011-07-20 13:45:28 -0700163 .WillRepeatedly(Return(0));
164 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex("eth0"));
165 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex("wlan0"));
166 EXPECT_EQ(kTestInterfaceIndex,
167 RTNLHandler::GetInstance()->GetInterfaceIndex("usb0"));
168}
169
170} // namespace shill