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