blob: 2eb36daaf0c7b89b47403f218f55394010d0030a [file] [log] [blame]
Darin Petkove0a312e2011-07-20 13:45:28 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2// 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
Chris Masone2aa97072011-08-09 17:35:08 -070015#include "shill/manager.h"
16#include "shill/mock_control.h"
17#include "shill/mock_glib.h"
Chris Masone2ae797d2011-08-23 20:41:00 -070018#include "shill/mock_manager.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070019#include "shill/mock_sockets.h"
20#include "shill/rtnl_handler.h"
Chris Masone2aa97072011-08-09 17:35:08 -070021#include "shill/rtnl_message.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070022
23using std::string;
24using testing::_;
Chris Masone2aa97072011-08-09 17:35:08 -070025using testing::A;
Darin Petkove0a312e2011-07-20 13:45:28 -070026using testing::DoAll;
27using testing::Return;
28using testing::StrictMock;
29using testing::Test;
30
31namespace shill {
32
33namespace {
34
35const int kTestInterfaceIndex = 4;
36
37ACTION(SetInterfaceIndex) {
38 if (arg2) {
39 reinterpret_cast<struct ifreq *>(arg2)->ifr_ifindex = kTestInterfaceIndex;
40 }
41}
42
Chris Masone2aa97072011-08-09 17:35:08 -070043class TestEventDispatcher : public EventDispatcher {
44 public:
45 virtual IOInputHandler *CreateInputHandler(
46 int fd,
47 Callback1<InputData*>::Type *callback) {
48 return NULL;
49 }
50};
51
Darin Petkove0a312e2011-07-20 13:45:28 -070052} // namespace
53
54class RTNLHandlerTest : public Test {
Chris Masone2aa97072011-08-09 17:35:08 -070055 public:
56 RTNLHandlerTest()
57 : manager_(&control_interface_, &dispatcher_, &glib_),
58 callback_(NewCallback(this, &RTNLHandlerTest::Callback)),
59 task_factory_(this) {
60 }
61
62 virtual void TearDown() {
63 RTNLHandler::GetInstance()->Stop();
64 SetSockets(NULL);
65 }
66
67 MOCK_METHOD1(Callback, void(const RTNLMessage &));
68
Darin Petkove0a312e2011-07-20 13:45:28 -070069 protected:
Chris Masone2aa97072011-08-09 17:35:08 -070070 static const int kTestSocket;
71 static const int kTestDeviceIndex;
72 static const char kTestDeviceName[];
73
74 void AddLink();
75 void StartRTNLHandler();
76 void StopRTNLHandler();
77
Darin Petkove0a312e2011-07-20 13:45:28 -070078 void SetSockets(Sockets *sockets) {
79 RTNLHandler::GetInstance()->sockets_ = sockets;
80 }
81
Darin Petkove0a312e2011-07-20 13:45:28 -070082 StrictMock<MockSockets> sockets_;
Chris Masone2aa97072011-08-09 17:35:08 -070083 MockGLib glib_;
84 MockControl control_interface_;
Chris Masone2ae797d2011-08-23 20:41:00 -070085 MockManager manager_;
Chris Masone2aa97072011-08-09 17:35:08 -070086 TestEventDispatcher dispatcher_;
87 scoped_ptr<Callback1<const RTNLMessage &>::Type> callback_;
88 ScopedRunnableMethodFactory<RTNLHandlerTest> task_factory_;
Darin Petkove0a312e2011-07-20 13:45:28 -070089};
90
Chris Masone2aa97072011-08-09 17:35:08 -070091const int RTNLHandlerTest::kTestSocket = 123;
92const int RTNLHandlerTest::kTestDeviceIndex = 123456;
93const char RTNLHandlerTest::kTestDeviceName[] = "test-device";
94
95void RTNLHandlerTest::StartRTNLHandler() {
96 EXPECT_CALL(sockets_, Socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE))
97 .WillOnce(Return(kTestSocket));
98 EXPECT_CALL(sockets_, Bind(kTestSocket, _, sizeof(sockaddr_nl)))
99 .WillOnce(Return(0));
100 RTNLHandler::GetInstance()->Start(&dispatcher_, &sockets_);
101}
102
103void RTNLHandlerTest::StopRTNLHandler() {
104 EXPECT_CALL(sockets_, Close(kTestSocket)).WillOnce(Return(0));
105 RTNLHandler::GetInstance()->Stop();
106}
107
108void RTNLHandlerTest::AddLink() {
Paul Stewart9a908082011-08-31 12:18:48 -0700109 RTNLMessage message(RTNLMessage::kTypeLink,
110 RTNLMessage::kModeAdd,
Chris Masone2aa97072011-08-09 17:35:08 -0700111 0,
112 0,
113 0,
114 kTestDeviceIndex,
115 IPAddress::kAddressFamilyIPv4);
116 message.SetAttribute(static_cast<uint16>(IFLA_IFNAME),
117 ByteString(kTestDeviceName, true));
118 ByteString b(message.Encode());
119 InputData data(b.GetData(), b.GetLength());
120 RTNLHandler::GetInstance()->ParseRTNL(&data);
121}
122
123TEST_F(RTNLHandlerTest, AddLinkTest) {
124 StartRTNLHandler();
125 scoped_ptr<RTNLListener> link_listener(
126 new RTNLListener(RTNLHandler::kRequestLink, callback_.get()));
127
128 EXPECT_CALL(*this, Callback(A<const RTNLMessage &>())).Times(1);
129
130 AddLink();
131
132 StopRTNLHandler();
133}
134
135
Darin Petkove0a312e2011-07-20 13:45:28 -0700136TEST_F(RTNLHandlerTest, GetInterfaceName) {
Chris Masone2aa97072011-08-09 17:35:08 -0700137 SetSockets(&sockets_);
Darin Petkove0a312e2011-07-20 13:45:28 -0700138 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex(""));
139 {
140 struct ifreq ifr;
141 string name(sizeof(ifr.ifr_name), 'x');
142 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex(name));
143 }
144
145 const int kTestSocket = 123;
146 EXPECT_CALL(sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
147 .Times(3)
148 .WillOnce(Return(-1))
149 .WillRepeatedly(Return(kTestSocket));
150 EXPECT_CALL(sockets_, Ioctl(kTestSocket, SIOCGIFINDEX, _))
151 .WillOnce(Return(-1))
152 .WillOnce(DoAll(SetInterfaceIndex(), Return(0)));
153 EXPECT_CALL(sockets_, Close(kTestSocket))
Chris Masone2aa97072011-08-09 17:35:08 -0700154 .Times(3)
Darin Petkove0a312e2011-07-20 13:45:28 -0700155 .WillRepeatedly(Return(0));
156 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex("eth0"));
157 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex("wlan0"));
158 EXPECT_EQ(kTestInterfaceIndex,
159 RTNLHandler::GetInstance()->GetInterfaceIndex("usb0"));
160}
161
162} // namespace shill