blob: 49a13821119d885f14e8df0230655746f652844a [file] [log] [blame]
#include <ipmid/api.h>
#include <cstring>
#include <ipmid/oemrouter.hpp>
#include "sample.h"
#include <gtest/gtest.h>
// Watch for correct singleton behavior.
static oem::Router* singletonUnderTest;
static ipmid_callback_t wildHandler;
static ipmi_netfn_t lastNetFunction;
// Fake ipmi_register_callback() for this test.
void ipmi_register_callback(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
ipmi_context_t context, ipmid_callback_t cb,
ipmi_cmd_privilege_t priv)
{
EXPECT_EQ(NETFUN_OEM_GROUP, netfn);
EXPECT_EQ(IPMI_CMD_WILDCARD, cmd);
EXPECT_EQ(reinterpret_cast<void*>(singletonUnderTest), context);
EXPECT_EQ(PRIVILEGE_OEM, priv);
lastNetFunction = netfn;
wildHandler = cb;
}
namespace oem
{
namespace
{
void MakeRouter()
{
if (!singletonUnderTest)
{
singletonUnderTest = mutableRouter();
}
ASSERT_EQ(singletonUnderTest, mutableRouter());
}
void ActivateRouter()
{
MakeRouter();
singletonUnderTest->activate();
ASSERT_EQ(NETFUN_OEM_GROUP, lastNetFunction);
}
void RegisterWithRouter(Number oen, ipmi_cmd_t cmd, Handler cb)
{
ActivateRouter();
singletonUnderTest->registerHandler(oen, cmd, cb);
}
uint8_t msgPlain[] = {0x56, 0x34, 0x12};
uint8_t replyPlain[] = {0x56, 0x34, 0x12, 0x31, 0x41};
uint8_t msgPlus2[] = {0x67, 0x45, 0x23, 0x10, 0x20};
uint8_t msgBadOen[] = {0x57, 0x34, 0x12};
void RegisterTwoWays(ipmi_cmd_t* nextCmd)
{
Handler f = [](ipmi_cmd_t cmd, const uint8_t* reqBuf, uint8_t* replyBuf,
size_t* dataLen) {
// Check inputs
EXPECT_EQ(0x78, cmd);
EXPECT_EQ(0, *dataLen); // Excludes OEN
// Generate reply.
*dataLen = 2;
std::memcpy(replyBuf, replyPlain + 3, *dataLen);
return 0;
};
RegisterWithRouter(0x123456, 0x78, f);
*nextCmd = IPMI_CMD_WILDCARD;
Handler g = [nextCmd](ipmi_cmd_t cmd, const uint8_t* reqBuf,
uint8_t* replyBuf, size_t* dataLen) {
// Check inputs
EXPECT_EQ(*nextCmd, cmd);
EXPECT_EQ(2, *dataLen); // Excludes OEN
if (2 != *dataLen)
{
return 0xE0;
}
EXPECT_EQ(msgPlus2[3], reqBuf[0]);
EXPECT_EQ(msgPlus2[4], reqBuf[1]);
// Generate reply.
*dataLen = 0;
return 0;
};
RegisterWithRouter(0x234567, IPMI_CMD_WILDCARD, g);
}
} // namespace
TEST(OemRouterTest, MakeRouterProducesConsistentSingleton)
{
MakeRouter();
}
TEST(OemRouterTest, ActivateRouterSetsLastNetToOEMGROUP)
{
lastNetFunction = 0;
ActivateRouter();
}
TEST(OemRouterTest, VerifiesSpecificCommandMatches)
{
ipmi_cmd_t cmd;
uint8_t reply[256];
size_t dataLen;
RegisterTwoWays(&cmd);
dataLen = 3;
EXPECT_EQ(0, wildHandler(NETFUN_OEM_GROUP, 0x78, msgPlain, reply, &dataLen,
nullptr));
EXPECT_EQ(5, dataLen);
EXPECT_EQ(replyPlain[0], reply[0]);
EXPECT_EQ(replyPlain[1], reply[1]);
EXPECT_EQ(replyPlain[2], reply[2]);
EXPECT_EQ(replyPlain[3], reply[3]);
EXPECT_EQ(replyPlain[4], reply[4]);
}
TEST(OemRouterTest, WildCardMatchesTwoRandomCodes)
{
ipmi_cmd_t cmd;
uint8_t reply[256];
size_t dataLen;
RegisterTwoWays(&cmd);
// Check two random command codes.
dataLen = 5;
cmd = 0x89;
EXPECT_EQ(0, wildHandler(NETFUN_OEM_GROUP, cmd, msgPlus2, reply, &dataLen,
nullptr));
EXPECT_EQ(3, dataLen);
dataLen = 5;
cmd = 0x67;
EXPECT_EQ(0, wildHandler(NETFUN_OEM_GROUP, cmd, msgPlus2, reply, &dataLen,
nullptr));
EXPECT_EQ(3, dataLen);
}
TEST(OemRouterTest, CommandsAreRejectedIfInvalid)
{
ipmi_cmd_t cmd;
uint8_t reply[256];
size_t dataLen;
RegisterTwoWays(&cmd);
// Message too short to include whole OEN?
dataLen = 2;
EXPECT_EQ(IPMI_CC_REQ_DATA_LEN_INVALID,
wildHandler(NETFUN_OEM_GROUP, 0x78, msgPlain, reply, &dataLen,
nullptr));
// Wrong specific command?
dataLen = 3;
EXPECT_EQ(IPMI_CC_INVALID, wildHandler(NETFUN_OEM_GROUP, 0x89, msgPlain,
reply, &dataLen, nullptr));
// Wrong OEN?
dataLen = 3;
EXPECT_EQ(IPMI_CC_INVALID, wildHandler(NETFUN_OEM_GROUP, 0x78, msgBadOen,
reply, &dataLen, nullptr));
}
} // namespace oem