blob: e325fb3d342750d8aa64a0ed203e9715ec21cee6 [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 Le3426c8f2012-01-11 17:35:11 -080064 : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
Eric Shienbrood3e20a232012-02-16 11:35:56 -050065 callback_(Bind(&RTNLHandlerTest::HandlerCallback, Unretained(this))) {
Chris Masone2aa97072011-08-09 17:35:08 -070066 }
67
68 virtual void TearDown() {
69 RTNLHandler::GetInstance()->Stop();
70 SetSockets(NULL);
71 }
72
Eric Shienbrood3e20a232012-02-16 11:35:56 -050073 MOCK_METHOD1(HandlerCallback, void(const RTNLMessage &));
Chris Masone2aa97072011-08-09 17:35:08 -070074
Darin Petkove0a312e2011-07-20 13:45:28 -070075 protected:
Chris Masone2aa97072011-08-09 17:35:08 -070076 static const int kTestSocket;
77 static const int kTestDeviceIndex;
78 static const char kTestDeviceName[];
79
80 void AddLink();
81 void StartRTNLHandler();
82 void StopRTNLHandler();
83
Darin Petkove0a312e2011-07-20 13:45:28 -070084 void SetSockets(Sockets *sockets) {
85 RTNLHandler::GetInstance()->sockets_ = sockets;
86 }
87
Darin Petkove0a312e2011-07-20 13:45:28 -070088 StrictMock<MockSockets> sockets_;
Chris Masone2aa97072011-08-09 17:35:08 -070089 MockGLib glib_;
90 MockControl control_interface_;
Thieu Le3426c8f2012-01-11 17:35:11 -080091 MockMetrics metrics_;
Chris Masone2ae797d2011-08-23 20:41:00 -070092 MockManager manager_;
Chris Masone2aa97072011-08-09 17:35:08 -070093 TestEventDispatcher dispatcher_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -050094 Callback<void(const RTNLMessage &)> callback_;
Darin Petkove0a312e2011-07-20 13:45:28 -070095};
96
Chris Masone2aa97072011-08-09 17:35:08 -070097const int RTNLHandlerTest::kTestSocket = 123;
98const int RTNLHandlerTest::kTestDeviceIndex = 123456;
99const char RTNLHandlerTest::kTestDeviceName[] = "test-device";
100
101void RTNLHandlerTest::StartRTNLHandler() {
102 EXPECT_CALL(sockets_, Socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE))
103 .WillOnce(Return(kTestSocket));
104 EXPECT_CALL(sockets_, Bind(kTestSocket, _, sizeof(sockaddr_nl)))
105 .WillOnce(Return(0));
Julius Wernerf253c842012-12-20 14:52:30 -0800106 EXPECT_CALL(sockets_, SetReceiveBuffer(kTestSocket, _)).WillOnce(Return(0));
Chris Masone2aa97072011-08-09 17:35:08 -0700107 RTNLHandler::GetInstance()->Start(&dispatcher_, &sockets_);
108}
109
110void RTNLHandlerTest::StopRTNLHandler() {
111 EXPECT_CALL(sockets_, Close(kTestSocket)).WillOnce(Return(0));
112 RTNLHandler::GetInstance()->Stop();
113}
114
115void RTNLHandlerTest::AddLink() {
Paul Stewart9a908082011-08-31 12:18:48 -0700116 RTNLMessage message(RTNLMessage::kTypeLink,
117 RTNLMessage::kModeAdd,
Chris Masone2aa97072011-08-09 17:35:08 -0700118 0,
119 0,
120 0,
121 kTestDeviceIndex,
Paul Stewart7355ce12011-09-02 10:47:01 -0700122 IPAddress::kFamilyIPv4);
Chris Masone2aa97072011-08-09 17:35:08 -0700123 message.SetAttribute(static_cast<uint16>(IFLA_IFNAME),
Gary Morain41780232012-07-31 15:08:31 -0700124 ByteString(string(kTestDeviceName), true));
Chris Masone2aa97072011-08-09 17:35:08 -0700125 ByteString b(message.Encode());
126 InputData data(b.GetData(), b.GetLength());
127 RTNLHandler::GetInstance()->ParseRTNL(&data);
128}
129
130TEST_F(RTNLHandlerTest, AddLinkTest) {
131 StartRTNLHandler();
132 scoped_ptr<RTNLListener> link_listener(
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500133 new RTNLListener(RTNLHandler::kRequestLink, callback_));
Chris Masone2aa97072011-08-09 17:35:08 -0700134
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500135 EXPECT_CALL(*this, HandlerCallback(A<const RTNLMessage &>())).Times(1);
Chris Masone2aa97072011-08-09 17:35:08 -0700136
137 AddLink();
138
139 StopRTNLHandler();
140}
141
142
Darin Petkove0a312e2011-07-20 13:45:28 -0700143TEST_F(RTNLHandlerTest, GetInterfaceName) {
Chris Masone2aa97072011-08-09 17:35:08 -0700144 SetSockets(&sockets_);
Darin Petkove0a312e2011-07-20 13:45:28 -0700145 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex(""));
146 {
147 struct ifreq ifr;
148 string name(sizeof(ifr.ifr_name), 'x');
149 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex(name));
150 }
151
152 const int kTestSocket = 123;
153 EXPECT_CALL(sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
154 .Times(3)
155 .WillOnce(Return(-1))
156 .WillRepeatedly(Return(kTestSocket));
157 EXPECT_CALL(sockets_, Ioctl(kTestSocket, SIOCGIFINDEX, _))
158 .WillOnce(Return(-1))
159 .WillOnce(DoAll(SetInterfaceIndex(), Return(0)));
160 EXPECT_CALL(sockets_, Close(kTestSocket))
Chris Masone2aa97072011-08-09 17:35:08 -0700161 .Times(3)
Darin Petkove0a312e2011-07-20 13:45:28 -0700162 .WillRepeatedly(Return(0));
163 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex("eth0"));
164 EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex("wlan0"));
165 EXPECT_EQ(kTestInterfaceIndex,
166 RTNLHandler::GetInstance()->GetInterfaceIndex("usb0"));
167}
168
169} // namespace shill