1//
2// Copyright (C) 2015 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include <dhcp_client/device_info.h>
18
19#include <net/if.h>
20#include <sys/ioctl.h>
21
22#include <gmock/gmock.h>
23#include <gtest/gtest.h>
24
25#include <shill/net/byte_string.h>
26#include <shill/net/mock_sockets.h>
27#include <shill/net/mock_rtnl_handler.h>
28
29using shill::ByteString;
30using shill::MockRTNLHandler;
31using shill::MockSockets;
32using ::testing::_;
33using ::testing::DoAll;
34using ::testing::ElementsAreArray;
35using ::testing::Return;
36
37namespace {
38
39const int kFakeFd = 99;
40const unsigned int kFakeInterfaceIndex = 1;
41const std::string kFakeDeviceName = "eth0";
42const std::string kFakeLongDeviceName = "a_long_device_name";
43const uint8_t kFakeMacAddress[] = {0x00, 0x01, 0x02, 0xaa, 0xbb, 0xcc};
44
45}
46
47namespace dhcp_client {
48
49class DeviceInfoTest : public testing::Test {
50 public:
51  DeviceInfoTest() {}
52
53  void SetUp() {
54    device_info_ = DeviceInfo::GetInstance();
55    sockets_ = new MockSockets();
56    device_info_->sockets_.reset(sockets_);
57    device_info_->rtnl_handler_ = &rtnl_handler_;
58  }
59
60 protected:
61  DeviceInfo* device_info_;
62  MockRTNLHandler rtnl_handler_;
63  MockSockets* sockets_;  // Owned by device_info_.
64};
65
66ACTION_P(SetIfreq, ifr) {
67  struct ifreq* const ifr_arg = static_cast<struct ifreq*>(arg2);
68  *ifr_arg = ifr;
69}
70
71MATCHER_P(IfreqEquals, ifname, "") {
72  const struct ifreq* const ifr = static_cast<struct ifreq*>(arg);
73  return (ifr != nullptr) &&
74      (strcmp(ifname, ifr->ifr_name) == 0);
75}
76
77TEST_F(DeviceInfoTest, GetDeviceInfoSucceed) {
78  ByteString mac_address;
79  unsigned int interface_index;
80  struct ifreq ifr;
81  memcpy(ifr.ifr_hwaddr.sa_data, kFakeMacAddress, sizeof(kFakeMacAddress));
82  EXPECT_CALL(*sockets_, Socket(AF_INET, SOCK_DGRAM, 0))
83      .WillOnce(Return(kFakeFd));
84  EXPECT_CALL(*sockets_, Ioctl(kFakeFd,
85                               SIOCGIFHWADDR,
86                               IfreqEquals(kFakeDeviceName.c_str())))
87      .WillOnce(DoAll(SetIfreq(ifr), Return(0)));
88  EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(kFakeDeviceName))
89      .WillOnce(Return(kFakeInterfaceIndex));
90  EXPECT_TRUE(device_info_->GetDeviceInfo(kFakeDeviceName,
91                                          &mac_address,
92                                          &interface_index));
93  EXPECT_EQ(interface_index, kFakeInterfaceIndex);
94  EXPECT_THAT(kFakeMacAddress,
95              ElementsAreArray(mac_address.GetConstData(),
96                               sizeof(kFakeMacAddress)));
97}
98
99TEST_F(DeviceInfoTest, GetDeviceInfoNameTooLong) {
100  ByteString mac_address;
101  unsigned int interface_index;
102  EXPECT_FALSE(device_info_->GetDeviceInfo(kFakeLongDeviceName,
103                                           &mac_address,
104                                           &interface_index));
105}
106
107TEST_F(DeviceInfoTest, GetDeviceInfoFailedToCreateSocket) {
108  ByteString mac_address;
109  unsigned int interface_index;
110  EXPECT_CALL(*sockets_, Socket(AF_INET, SOCK_DGRAM, 0)).WillOnce(Return(-1));
111  EXPECT_FALSE(device_info_->GetDeviceInfo(kFakeDeviceName,
112                                           &mac_address,
113                                           &interface_index));
114}
115
116TEST_F(DeviceInfoTest, GetDeviceInfoFailedToGetHardwareAddr) {
117  ByteString mac_address;
118  unsigned int interface_index;
119  EXPECT_CALL(*sockets_, Socket(AF_INET, SOCK_DGRAM, 0))
120      .WillOnce(Return(kFakeFd));
121  EXPECT_CALL(*sockets_, Ioctl(kFakeFd, SIOCGIFHWADDR, _)).WillOnce(Return(-1));
122  EXPECT_FALSE(device_info_->GetDeviceInfo(kFakeDeviceName,
123                                           &mac_address,
124                                           &interface_index));
125}
126
127TEST_F(DeviceInfoTest, GetDeviceInfoFailedToGetInterfaceIndex) {
128  ByteString mac_address;
129  unsigned int interface_index;
130  EXPECT_CALL(*sockets_, Socket(AF_INET, SOCK_DGRAM, 0))
131      .WillOnce(Return(kFakeFd));
132  EXPECT_CALL(*sockets_, Ioctl(kFakeFd, SIOCGIFHWADDR, _)).WillOnce(Return(0));
133  EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(kFakeDeviceName))
134      .WillOnce(Return(-1));
135  EXPECT_FALSE(device_info_->GetDeviceInfo(kFakeDeviceName,
136                                           &mac_address,
137                                           &interface_index));
138}
139
140}  // namespace dhcp_client
141