blob: b32460f2f51967c99ad24c276805d8609735bb30 [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*/,
Eric Shienbrood3e20a232012-02-16 11:35:56 -050053 const Callback<void(InputData*)> &/*callback*/) {
Chris Masone2aa97072011-08-09 17:35:08 -070054 return NULL;
55 }
56};
57
Darin Petkove0a312e2011-07-20 13:45:28 -070058} // namespace
59
60class RTNLHandlerTest : public Test {
Chris Masone2aa97072011-08-09 17:35:08 -070061 public:
62 RTNLHandlerTest()
Thieu Le3426c8f2012-01-11 17:35:11 -080063 : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
Eric Shienbrood3e20a232012-02-16 11:35:56 -050064 callback_(Bind(&RTNLHandlerTest::HandlerCallback, Unretained(this))) {
Chris Masone2aa97072011-08-09 17:35:08 -070065 }
66
67 virtual void TearDown() {
68 RTNLHandler::GetInstance()->Stop();
69 SetSockets(NULL);
70 }
71
Eric Shienbrood3e20a232012-02-16 11:35:56 -050072 MOCK_METHOD1(HandlerCallback, void(const RTNLMessage &));
Chris Masone2aa97072011-08-09 17:35:08 -070073
Darin Petkove0a312e2011-07-20 13:45:28 -070074 protected:
Chris Masone2aa97072011-08-09 17:35:08 -070075 static const int kTestSocket;
76 static const int kTestDeviceIndex;
77 static const char kTestDeviceName[];
78
79 void AddLink();
80 void StartRTNLHandler();
81 void StopRTNLHandler();
82
Darin Petkove0a312e2011-07-20 13:45:28 -070083 void SetSockets(Sockets *sockets) {
84 RTNLHandler::GetInstance()->sockets_ = sockets;
85 }
86
Darin Petkove0a312e2011-07-20 13:45:28 -070087 StrictMock<MockSockets> sockets_;
Chris Masone2aa97072011-08-09 17:35:08 -070088 MockGLib glib_;
89 MockControl control_interface_;
Thieu Le3426c8f2012-01-11 17:35:11 -080090 MockMetrics metrics_;
Chris Masone2ae797d2011-08-23 20:41:00 -070091 MockManager manager_;
Chris Masone2aa97072011-08-09 17:35:08 -070092 TestEventDispatcher dispatcher_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -050093 Callback<void(const RTNLMessage &)> callback_;
Darin Petkove0a312e2011-07-20 13:45:28 -070094};
95
Chris Masone2aa97072011-08-09 17:35:08 -070096const int RTNLHandlerTest::kTestSocket = 123;
97const int RTNLHandlerTest::kTestDeviceIndex = 123456;
98const char RTNLHandlerTest::kTestDeviceName[] = "test-device";
99
100void RTNLHandlerTest::StartRTNLHandler() {
101 EXPECT_CALL(sockets_, Socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE))
102 .WillOnce(Return(kTestSocket));
103 EXPECT_CALL(sockets_, Bind(kTestSocket, _, sizeof(sockaddr_nl)))
104 .WillOnce(Return(0));
105 RTNLHandler::GetInstance()->Start(&dispatcher_, &sockets_);
106}
107
108void RTNLHandlerTest::StopRTNLHandler() {
109 EXPECT_CALL(sockets_, Close(kTestSocket)).WillOnce(Return(0));
110 RTNLHandler::GetInstance()->Stop();
111}
112
113void RTNLHandlerTest::AddLink() {
Paul Stewart9a908082011-08-31 12:18:48 -0700114 RTNLMessage message(RTNLMessage::kTypeLink,
115 RTNLMessage::kModeAdd,
Chris Masone2aa97072011-08-09 17:35:08 -0700116 0,
117 0,
118 0,
119 kTestDeviceIndex,
Paul Stewart7355ce12011-09-02 10:47:01 -0700120 IPAddress::kFamilyIPv4);
Chris Masone2aa97072011-08-09 17:35:08 -0700121 message.SetAttribute(static_cast<uint16>(IFLA_IFNAME),
122 ByteString(kTestDeviceName, true));
123 ByteString b(message.Encode());
124 InputData data(b.GetData(), b.GetLength());
125 RTNLHandler::GetInstance()->ParseRTNL(&data);
126}
127
128TEST_F(RTNLHandlerTest, AddLinkTest) {
129 StartRTNLHandler();
130 scoped_ptr<RTNLListener> link_listener(
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500131 new RTNLListener(RTNLHandler::kRequestLink, callback_));
Chris Masone2aa97072011-08-09 17:35:08 -0700132
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500133 EXPECT_CALL(*this, HandlerCallback(A<const RTNLMessage &>())).Times(1);
Chris Masone2aa97072011-08-09 17:35:08 -0700134
135 AddLink();
136
137 StopRTNLHandler();
138}
139
140
Darin Petkove0a312e2011-07-20 13:45:28 -0700141TEST_F(RTNLHandlerTest, GetInterfaceName) {
Chris Masone2aa97072011-08-09 17:35:08 -0700142 SetSockets(&sockets_);
Darin Petkove0a312e2011-07-20 13:45:28 -0700143 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex(""));
144 {
145 struct ifreq ifr;
146 string name(sizeof(ifr.ifr_name), 'x');
147 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex(name));
148 }
149
150 const int kTestSocket = 123;
151 EXPECT_CALL(sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
152 .Times(3)
153 .WillOnce(Return(-1))
154 .WillRepeatedly(Return(kTestSocket));
155 EXPECT_CALL(sockets_, Ioctl(kTestSocket, SIOCGIFINDEX, _))
156 .WillOnce(Return(-1))
157 .WillOnce(DoAll(SetInterfaceIndex(), Return(0)));
158 EXPECT_CALL(sockets_, Close(kTestSocket))
Chris Masone2aa97072011-08-09 17:35:08 -0700159 .Times(3)
Darin Petkove0a312e2011-07-20 13:45:28 -0700160 .WillRepeatedly(Return(0));
161 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex("eth0"));
162 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex("wlan0"));
163 EXPECT_EQ(kTestInterfaceIndex,
164 RTNLHandler::GetInstance()->GetInterfaceIndex("usb0"));
165}
166
167} // namespace shill