blob: 41a2c62bbe40b612da0470e6fc7134dbc560f9ed [file] [log] [blame]
Patrick Ventureaca98132019-03-18 11:14:16 -07001#include "ethstats.hpp"
2#include "handler_mock.hpp"
3
4#include <cstdint>
5#include <cstring>
6#include <string>
7#include <vector>
8
9#include <gtest/gtest.h>
10
11#define MAX_IPMI_BUFFER 64
12
13using ::testing::Return;
14using ::testing::StrEq;
15using ::testing::StrictMock;
16
17namespace ethstats
18{
19
20TEST(EthStatsTest, InvalidStatReturnsFailure)
21{
22 // Verify that the enum of valid statistic IDs is checked.
23
24 std::string ifName = "eth0";
25 struct EthStatRequest requestStruct;
26 requestStruct.statId = EthernetStatisticsIds::TX_WINDOW_ERRORS + 1;
27 requestStruct.if_name_len = ifName.length();
28
29 std::vector<std::uint8_t> request(sizeof(requestStruct) + ifName.length());
30 std::memcpy(request.data(), &requestStruct, sizeof(requestStruct));
31 std::memcpy(&request[sizeof(requestStruct)], ifName.c_str(),
32 ifName.length());
33
34 size_t dataLen = request.size();
35 std::uint8_t reply[MAX_IPMI_BUFFER];
36
37 // Using StrictMock to ensure it isn't called.
38 StrictMock<HandlerMock> hMock;
39
40 EXPECT_EQ(IPMI_CC_INVALID_FIELD_REQUEST,
41 handleEthStatCommand(request.data(), reply, &dataLen, &hMock));
42}
43
44TEST(EthStatsTest, InvalidIpmiPacketSize)
45{
46 // An IPMI packet for this command has a minimum length.
47
48 std::string ifName = "e";
49 struct EthStatRequest requestStruct;
50 requestStruct.statId = EthernetStatisticsIds::RX_BYTES;
51 requestStruct.if_name_len = ifName.length();
52
53 std::vector<std::uint8_t> request(sizeof(requestStruct) + ifName.length());
54 std::memcpy(request.data(), &requestStruct, sizeof(requestStruct));
55 std::memcpy(&request[sizeof(requestStruct)], ifName.c_str(),
56 ifName.length());
57
58 // The minimum length is a 1-byte ifname - this gives one, but dataLen is
59 // set to smaller.
60 size_t dataLen = request.size() - 1;
61 std::uint8_t reply[MAX_IPMI_BUFFER];
62
63 // Using StrictMock to ensure it isn't called.
64 StrictMock<HandlerMock> hMock;
65
66 EXPECT_EQ(IPMI_CC_REQ_DATA_LEN_INVALID,
67 handleEthStatCommand(request.data(), reply, &dataLen, &hMock));
68}
69
70TEST(EthStatsTest, InvalidIpmiPacketContents)
71{
72 // The packet has a name length and name contents, if the name length is
73 // longer than the packet size, it should fail.
74
75 std::string ifName = "eth0";
76 struct EthStatRequest requestStruct;
77 requestStruct.statId = EthernetStatisticsIds::RX_BYTES;
78 requestStruct.if_name_len = ifName.length() + 1;
79
80 std::vector<std::uint8_t> request(sizeof(requestStruct) + ifName.length());
81 std::memcpy(request.data(), &requestStruct, sizeof(requestStruct));
82 std::memcpy(&request[sizeof(requestStruct)], ifName.c_str(),
83 ifName.length());
84
85 size_t dataLen = request.size();
86 std::uint8_t reply[MAX_IPMI_BUFFER];
87
88 // Using StrictMock to ensure it isn't called.
89 StrictMock<HandlerMock> hMock;
90
91 EXPECT_EQ(IPMI_CC_REQ_DATA_LEN_INVALID,
92 handleEthStatCommand(request.data(), reply, &dataLen, &hMock));
93}
94
95TEST(EthStatsTest, NameHasIllegalCharacters)
96{
97 // The interface name cannot have slashes.
98 std::string ifName = "et/h0";
99 struct EthStatRequest requestStruct;
100 requestStruct.statId = EthernetStatisticsIds::RX_BYTES;
101 requestStruct.if_name_len = ifName.length();
102
103 std::vector<std::uint8_t> request(sizeof(requestStruct) + ifName.length());
104 std::memcpy(request.data(), &requestStruct, sizeof(requestStruct));
105 std::memcpy(&request[sizeof(requestStruct)], ifName.c_str(),
106 ifName.length());
107
108 size_t dataLen = request.size();
109 std::uint8_t reply[MAX_IPMI_BUFFER];
110
111 // Using StrictMock to ensure it isn't called.
112 StrictMock<HandlerMock> hMock;
113
114 EXPECT_EQ(IPMI_CC_INVALID_FIELD_REQUEST,
115 handleEthStatCommand(request.data(), reply, &dataLen, &hMock));
116}
117
118TEST(EthStatsTest, InvalidNameOrField)
119{
120 // The handler returns failure on the input validity check.
121 std::string ifName = "eth0";
122 struct EthStatRequest requestStruct;
123 requestStruct.statId = EthernetStatisticsIds::RX_BYTES;
124 requestStruct.if_name_len = ifName.length();
125
126 std::vector<std::uint8_t> request(sizeof(requestStruct) + ifName.length());
127 std::memcpy(request.data(), &requestStruct, sizeof(requestStruct));
128 std::memcpy(&request[sizeof(requestStruct)], ifName.c_str(),
129 ifName.length());
130
131 size_t dataLen = request.size();
132 std::uint8_t reply[MAX_IPMI_BUFFER];
133
134 std::string expectedPath = buildPath(ifName, "rx_bytes");
135
136 HandlerMock hMock;
137 EXPECT_CALL(hMock, validIfNameAndField(StrEq(expectedPath)))
138 .WillOnce(Return(false));
139
140 EXPECT_EQ(IPMI_CC_INVALID_FIELD_REQUEST,
141 handleEthStatCommand(request.data(), reply, &dataLen, &hMock));
142}
143
144TEST(EthStatsTest, EverythingHappy)
145{
146 std::string ifName = "eth0";
147 struct EthStatRequest requestStruct;
148 requestStruct.statId = EthernetStatisticsIds::RX_BYTES;
149 requestStruct.if_name_len = ifName.length();
150
151 std::vector<std::uint8_t> request(sizeof(requestStruct) + ifName.length());
152 std::memcpy(request.data(), &requestStruct, sizeof(requestStruct));
153 std::memcpy(&request[sizeof(requestStruct)], ifName.c_str(),
154 ifName.length());
155
156 size_t dataLen = request.size();
157 std::uint8_t reply[MAX_IPMI_BUFFER];
158
159 std::string expectedPath = buildPath(ifName, "rx_bytes");
160
161 HandlerMock hMock;
162 EXPECT_CALL(hMock, validIfNameAndField(StrEq(expectedPath)))
163 .WillOnce(Return(true));
164 EXPECT_CALL(hMock, readStatistic(StrEq(expectedPath))).WillOnce(Return(1));
165
166 EXPECT_EQ(IPMI_CC_OK,
167 handleEthStatCommand(request.data(), reply, &dataLen, &hMock));
168
169 struct EthStatReply expectedReply, realReply;
170 expectedReply.statId = EthernetStatisticsIds::RX_BYTES;
171 expectedReply.value = 1;
172
173 std::memcpy(&realReply, reply, sizeof(realReply));
174 EXPECT_EQ(0, std::memcmp(&expectedReply, &realReply, sizeof(realReply)));
175}
176
177} // namespace ethstats