build: Some minor refactoring
Change-Id: I169d24356b883ba73327e1c6ab8d87a2398ced90
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/test/ethstats.cpp b/test/ethstats.cpp
new file mode 100644
index 0000000..db60319
--- /dev/null
+++ b/test/ethstats.cpp
@@ -0,0 +1,178 @@
+#include "ethstats.hpp"
+
+#include "handler_mock.hpp"
+
+#include <cstdint>
+#include <cstring>
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#define MAX_IPMI_BUFFER 64
+
+using ::testing::Return;
+using ::testing::StrEq;
+using ::testing::StrictMock;
+
+namespace ethstats
+{
+
+TEST(EthStatsTest, InvalidStatReturnsFailure)
+{
+ // Verify that the enum of valid statistic IDs is checked.
+
+ std::string ifName = "eth0";
+ struct EthStatRequest requestStruct;
+ requestStruct.statId = EthernetStatisticsIds::TX_WINDOW_ERRORS + 1;
+ requestStruct.if_name_len = ifName.length();
+
+ std::vector<std::uint8_t> request(sizeof(requestStruct) + ifName.length());
+ std::memcpy(request.data(), &requestStruct, sizeof(requestStruct));
+ std::memcpy(&request[sizeof(requestStruct)], ifName.c_str(),
+ ifName.length());
+
+ size_t dataLen = request.size();
+ std::uint8_t reply[MAX_IPMI_BUFFER];
+
+ // Using StrictMock to ensure it isn't called.
+ StrictMock<HandlerMock> hMock;
+
+ EXPECT_EQ(IPMI_CC_INVALID_FIELD_REQUEST,
+ handleEthStatCommand(request.data(), reply, &dataLen, &hMock));
+}
+
+TEST(EthStatsTest, InvalidIpmiPacketSize)
+{
+ // An IPMI packet for this command has a minimum length.
+
+ std::string ifName = "e";
+ struct EthStatRequest requestStruct;
+ requestStruct.statId = EthernetStatisticsIds::RX_BYTES;
+ requestStruct.if_name_len = ifName.length();
+
+ std::vector<std::uint8_t> request(sizeof(requestStruct) + ifName.length());
+ std::memcpy(request.data(), &requestStruct, sizeof(requestStruct));
+ std::memcpy(&request[sizeof(requestStruct)], ifName.c_str(),
+ ifName.length());
+
+ // The minimum length is a 1-byte ifname - this gives one, but dataLen is
+ // set to smaller.
+ size_t dataLen = request.size() - 1;
+ std::uint8_t reply[MAX_IPMI_BUFFER];
+
+ // Using StrictMock to ensure it isn't called.
+ StrictMock<HandlerMock> hMock;
+
+ EXPECT_EQ(IPMI_CC_REQ_DATA_LEN_INVALID,
+ handleEthStatCommand(request.data(), reply, &dataLen, &hMock));
+}
+
+TEST(EthStatsTest, InvalidIpmiPacketContents)
+{
+ // The packet has a name length and name contents, if the name length is
+ // longer than the packet size, it should fail.
+
+ std::string ifName = "eth0";
+ struct EthStatRequest requestStruct;
+ requestStruct.statId = EthernetStatisticsIds::RX_BYTES;
+ requestStruct.if_name_len = ifName.length() + 1;
+
+ std::vector<std::uint8_t> request(sizeof(requestStruct) + ifName.length());
+ std::memcpy(request.data(), &requestStruct, sizeof(requestStruct));
+ std::memcpy(&request[sizeof(requestStruct)], ifName.c_str(),
+ ifName.length());
+
+ size_t dataLen = request.size();
+ std::uint8_t reply[MAX_IPMI_BUFFER];
+
+ // Using StrictMock to ensure it isn't called.
+ StrictMock<HandlerMock> hMock;
+
+ EXPECT_EQ(IPMI_CC_REQ_DATA_LEN_INVALID,
+ handleEthStatCommand(request.data(), reply, &dataLen, &hMock));
+}
+
+TEST(EthStatsTest, NameHasIllegalCharacters)
+{
+ // The interface name cannot have slashes.
+ std::string ifName = "et/h0";
+ struct EthStatRequest requestStruct;
+ requestStruct.statId = EthernetStatisticsIds::RX_BYTES;
+ requestStruct.if_name_len = ifName.length();
+
+ std::vector<std::uint8_t> request(sizeof(requestStruct) + ifName.length());
+ std::memcpy(request.data(), &requestStruct, sizeof(requestStruct));
+ std::memcpy(&request[sizeof(requestStruct)], ifName.c_str(),
+ ifName.length());
+
+ size_t dataLen = request.size();
+ std::uint8_t reply[MAX_IPMI_BUFFER];
+
+ // Using StrictMock to ensure it isn't called.
+ StrictMock<HandlerMock> hMock;
+
+ EXPECT_EQ(IPMI_CC_INVALID_FIELD_REQUEST,
+ handleEthStatCommand(request.data(), reply, &dataLen, &hMock));
+}
+
+TEST(EthStatsTest, InvalidNameOrField)
+{
+ // The handler returns failure on the input validity check.
+ std::string ifName = "eth0";
+ struct EthStatRequest requestStruct;
+ requestStruct.statId = EthernetStatisticsIds::RX_BYTES;
+ requestStruct.if_name_len = ifName.length();
+
+ std::vector<std::uint8_t> request(sizeof(requestStruct) + ifName.length());
+ std::memcpy(request.data(), &requestStruct, sizeof(requestStruct));
+ std::memcpy(&request[sizeof(requestStruct)], ifName.c_str(),
+ ifName.length());
+
+ size_t dataLen = request.size();
+ std::uint8_t reply[MAX_IPMI_BUFFER];
+
+ std::string expectedPath = buildPath(ifName, "rx_bytes");
+
+ HandlerMock hMock;
+ EXPECT_CALL(hMock, validIfNameAndField(StrEq(expectedPath)))
+ .WillOnce(Return(false));
+
+ EXPECT_EQ(IPMI_CC_INVALID_FIELD_REQUEST,
+ handleEthStatCommand(request.data(), reply, &dataLen, &hMock));
+}
+
+TEST(EthStatsTest, EverythingHappy)
+{
+ std::string ifName = "eth0";
+ struct EthStatRequest requestStruct;
+ requestStruct.statId = EthernetStatisticsIds::RX_BYTES;
+ requestStruct.if_name_len = ifName.length();
+
+ std::vector<std::uint8_t> request(sizeof(requestStruct) + ifName.length());
+ std::memcpy(request.data(), &requestStruct, sizeof(requestStruct));
+ std::memcpy(&request[sizeof(requestStruct)], ifName.c_str(),
+ ifName.length());
+
+ size_t dataLen = request.size();
+ std::uint8_t reply[MAX_IPMI_BUFFER];
+
+ std::string expectedPath = buildPath(ifName, "rx_bytes");
+
+ HandlerMock hMock;
+ EXPECT_CALL(hMock, validIfNameAndField(StrEq(expectedPath)))
+ .WillOnce(Return(true));
+ EXPECT_CALL(hMock, readStatistic(StrEq(expectedPath))).WillOnce(Return(1));
+
+ EXPECT_EQ(IPMI_CC_OK,
+ handleEthStatCommand(request.data(), reply, &dataLen, &hMock));
+
+ struct EthStatReply expectedReply, realReply;
+ expectedReply.statId = EthernetStatisticsIds::RX_BYTES;
+ expectedReply.value = 1;
+
+ std::memcpy(&realReply, reply, sizeof(realReply));
+ EXPECT_EQ(0, std::memcmp(&expectedReply, &realReply, sizeof(realReply)));
+}
+
+} // namespace ethstats