blob: 3530631ebd2e0955affc989bdbc62e89b6da6b4e [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"
Darin Petkove0a312e2011-07-20 13:45:28 -070018#include "shill/mock_sockets.h"
19#include "shill/rtnl_handler.h"
Chris Masone2aa97072011-08-09 17:35:08 -070020#include "shill/rtnl_message.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070021
22using std::string;
23using testing::_;
Chris Masone2aa97072011-08-09 17:35:08 -070024using testing::A;
Darin Petkove0a312e2011-07-20 13:45:28 -070025using testing::DoAll;
26using testing::Return;
27using testing::StrictMock;
28using testing::Test;
29
30namespace shill {
31
32namespace {
33
34const int kTestInterfaceIndex = 4;
35
36ACTION(SetInterfaceIndex) {
37 if (arg2) {
38 reinterpret_cast<struct ifreq *>(arg2)->ifr_ifindex = kTestInterfaceIndex;
39 }
40}
41
Chris Masone2aa97072011-08-09 17:35:08 -070042class TestEventDispatcher : public EventDispatcher {
43 public:
44 virtual IOInputHandler *CreateInputHandler(
45 int fd,
46 Callback1<InputData*>::Type *callback) {
47 return NULL;
48 }
49};
50
Darin Petkove0a312e2011-07-20 13:45:28 -070051} // namespace
52
53class RTNLHandlerTest : public Test {
Chris Masone2aa97072011-08-09 17:35:08 -070054 public:
55 RTNLHandlerTest()
56 : manager_(&control_interface_, &dispatcher_, &glib_),
57 callback_(NewCallback(this, &RTNLHandlerTest::Callback)),
58 task_factory_(this) {
59 }
60
61 virtual void TearDown() {
62 RTNLHandler::GetInstance()->Stop();
63 SetSockets(NULL);
64 }
65
66 MOCK_METHOD1(Callback, void(const RTNLMessage &));
67
Darin Petkove0a312e2011-07-20 13:45:28 -070068 protected:
Chris Masone2aa97072011-08-09 17:35:08 -070069 static const int kTestSocket;
70 static const int kTestDeviceIndex;
71 static const char kTestDeviceName[];
72
73 void AddLink();
74 void StartRTNLHandler();
75 void StopRTNLHandler();
76
Darin Petkove0a312e2011-07-20 13:45:28 -070077 void SetSockets(Sockets *sockets) {
78 RTNLHandler::GetInstance()->sockets_ = sockets;
79 }
80
Darin Petkove0a312e2011-07-20 13:45:28 -070081 StrictMock<MockSockets> sockets_;
Chris Masone2aa97072011-08-09 17:35:08 -070082 MockGLib glib_;
83 MockControl control_interface_;
84 Manager manager_;
85 TestEventDispatcher dispatcher_;
86 scoped_ptr<Callback1<const RTNLMessage &>::Type> callback_;
87 ScopedRunnableMethodFactory<RTNLHandlerTest> task_factory_;
Darin Petkove0a312e2011-07-20 13:45:28 -070088};
89
Chris Masone2aa97072011-08-09 17:35:08 -070090const int RTNLHandlerTest::kTestSocket = 123;
91const int RTNLHandlerTest::kTestDeviceIndex = 123456;
92const char RTNLHandlerTest::kTestDeviceName[] = "test-device";
93
94void RTNLHandlerTest::StartRTNLHandler() {
95 EXPECT_CALL(sockets_, Socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE))
96 .WillOnce(Return(kTestSocket));
97 EXPECT_CALL(sockets_, Bind(kTestSocket, _, sizeof(sockaddr_nl)))
98 .WillOnce(Return(0));
99 RTNLHandler::GetInstance()->Start(&dispatcher_, &sockets_);
100}
101
102void RTNLHandlerTest::StopRTNLHandler() {
103 EXPECT_CALL(sockets_, Close(kTestSocket)).WillOnce(Return(0));
104 RTNLHandler::GetInstance()->Stop();
105}
106
107void RTNLHandlerTest::AddLink() {
108 RTNLMessage message(RTNLMessage::kMessageTypeLink,
109 RTNLMessage::kMessageModeAdd,
110 0,
111 0,
112 0,
113 kTestDeviceIndex,
114 IPAddress::kAddressFamilyIPv4);
115 message.SetAttribute(static_cast<uint16>(IFLA_IFNAME),
116 ByteString(kTestDeviceName, true));
117 ByteString b(message.Encode());
118 InputData data(b.GetData(), b.GetLength());
119 RTNLHandler::GetInstance()->ParseRTNL(&data);
120}
121
122TEST_F(RTNLHandlerTest, AddLinkTest) {
123 StartRTNLHandler();
124 scoped_ptr<RTNLListener> link_listener(
125 new RTNLListener(RTNLHandler::kRequestLink, callback_.get()));
126
127 EXPECT_CALL(*this, Callback(A<const RTNLMessage &>())).Times(1);
128
129 AddLink();
130
131 StopRTNLHandler();
132}
133
134
Darin Petkove0a312e2011-07-20 13:45:28 -0700135TEST_F(RTNLHandlerTest, GetInterfaceName) {
Chris Masone2aa97072011-08-09 17:35:08 -0700136 SetSockets(&sockets_);
Darin Petkove0a312e2011-07-20 13:45:28 -0700137 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex(""));
138 {
139 struct ifreq ifr;
140 string name(sizeof(ifr.ifr_name), 'x');
141 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex(name));
142 }
143
144 const int kTestSocket = 123;
145 EXPECT_CALL(sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
146 .Times(3)
147 .WillOnce(Return(-1))
148 .WillRepeatedly(Return(kTestSocket));
149 EXPECT_CALL(sockets_, Ioctl(kTestSocket, SIOCGIFINDEX, _))
150 .WillOnce(Return(-1))
151 .WillOnce(DoAll(SetInterfaceIndex(), Return(0)));
152 EXPECT_CALL(sockets_, Close(kTestSocket))
Chris Masone2aa97072011-08-09 17:35:08 -0700153 .Times(3)
Darin Petkove0a312e2011-07-20 13:45:28 -0700154 .WillRepeatedly(Return(0));
155 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex("eth0"));
156 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex("wlan0"));
157 EXPECT_EQ(kTestInterfaceIndex,
158 RTNLHandler::GetInstance()->GetInterfaceIndex("usb0"));
159}
160
161} // namespace shill