|  | #include "sample.h" | 
|  |  | 
|  | #include <ipmid/api.h> | 
|  |  | 
|  | #include <ipmid/oemrouter.hpp> | 
|  |  | 
|  | #include <cstring> | 
|  |  | 
|  | #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 |