Refactor to use new version of OEM IPMI Handler
Using the new version of ipmi handler provide a higher level wrapper
over the same functionalities. It helps us parse the input and output to
have more control of the input/output we see.
Changes to note,
- All cmd are removed from the request data. That is automatically
extracted now.
Tested:
Unit Test Passed.
All IPMI OEM command still works the same as before this change.
```
$ burn_my_bmc -command stage -image /tmp/test.txt -interface ipmipci
Set up ipmi flash updater with /flash/dummy
Received failure on delete: Received IPMI_CC: 255
Sending over the firmware image.
Find [0x1050 0x750]
bar0[0x94000000]
Upload to BMC 100% |Goooooooooooooooooooooooooooooooooooooooooooooooooooooooogle| Time: 00:00:00
Opening the verification file
Committing to /flash/verify to trigger service
Calling stat on /flash/verify session to check status
success
succeeded
```
Also tested gBMC Update workflow which worked fine.
Change-Id: Ib2bfeab0c2ec5aa72ede1ff457ef5f90e488053c
Signed-off-by: Willy Tu <wltu@google.com>
diff --git a/test/helper.cpp b/test/helper.cpp
new file mode 100644
index 0000000..73e19aa
--- /dev/null
+++ b/test/helper.cpp
@@ -0,0 +1,32 @@
+#include "helper.hpp"
+
+#include "ipmi.hpp"
+
+#include <ipmid/api-types.hpp>
+#include <optional>
+#include <span>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+namespace blobs
+{
+std::vector<std::uint8_t>
+ validateReply(ipmi::RspType<std::vector<uint8_t>> reply, bool hasData)
+{
+ // Reply is in the form of
+ // std::tuple<ipmi::Cc, std::optional<std::tuple<RetTypes...>>>
+ EXPECT_EQ(::ipmi::ccSuccess, std::get<0>(reply));
+
+ auto actualReply = std::get<1>(reply);
+ EXPECT_TRUE(actualReply.has_value());
+
+ auto data = std::get<0>(*actualReply);
+ EXPECT_EQ(hasData, !data.empty());
+
+ return hasData ? data : std::vector<uint8_t>{};
+}
+
+} // namespace blobs
diff --git a/test/helper.hpp b/test/helper.hpp
new file mode 100644
index 0000000..8d33f5c
--- /dev/null
+++ b/test/helper.hpp
@@ -0,0 +1,15 @@
+#include <ipmid/api-types.hpp>
+#include <optional>
+#include <span>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+namespace blobs
+{
+std::vector<std::uint8_t>
+ validateReply(ipmi::RspType<std::vector<uint8_t>> reply,
+ bool hasData = true);
+} // namespace blobs
diff --git a/test/ipmi_close_unittest.cpp b/test/ipmi_close_unittest.cpp
index af2e03e..d4bcb41 100644
--- a/test/ipmi_close_unittest.cpp
+++ b/test/ipmi_close_unittest.cpp
@@ -11,10 +11,6 @@
using ::testing::Return;
-// ipmid.hpp isn't installed where we can grab it and this value is per BMC
-// SoC.
-#define MAX_IPMI_BUFFER 64
-
TEST(BlobCloseTest, ManagerRejectsCloseReturnsFailure)
{
// The session manager returned failure to close, which we need to pass on.
@@ -22,21 +18,18 @@
ManagerMock mgr;
uint16_t sessionId = 0x54;
size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
+ std::vector<uint8_t> request;
struct BmcBlobCloseTx req;
- req.cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobClose);
req.crc = 0;
req.sessionId = sessionId;
dataLen = sizeof(req);
-
- std::memcpy(request, &req, sizeof(req));
+ request.resize(dataLen);
+ std::memcpy(request.data(), &req, dataLen);
EXPECT_CALL(mgr, close(sessionId)).WillOnce(Return(false));
- EXPECT_EQ(IPMI_CC_UNSPECIFIED_ERROR,
- closeBlob(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseUnspecifiedError(), closeBlob(&mgr, request));
}
TEST(BlobCloseTest, BlobClosedReturnsSuccess)
@@ -46,19 +39,18 @@
ManagerMock mgr;
uint16_t sessionId = 0x54;
size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
+ std::vector<uint8_t> request;
struct BmcBlobCloseTx req;
- req.cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobClose);
req.crc = 0;
req.sessionId = sessionId;
dataLen = sizeof(req);
-
- std::memcpy(request, &req, sizeof(req));
+ request.resize(dataLen);
+ std::memcpy(request.data(), &req, dataLen);
EXPECT_CALL(mgr, close(sessionId)).WillOnce(Return(true));
- EXPECT_EQ(IPMI_CC_OK, closeBlob(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseSuccess(std::vector<uint8_t>{}),
+ closeBlob(&mgr, request));
}
} // namespace blobs
diff --git a/test/ipmi_commit_unittest.cpp b/test/ipmi_commit_unittest.cpp
index d4b9c58..6cc8223 100644
--- a/test/ipmi_commit_unittest.cpp
+++ b/test/ipmi_commit_unittest.cpp
@@ -12,31 +12,22 @@
using ::testing::ElementsAreArray;
using ::testing::Return;
-// ipmid.hpp isn't installed where we can grab it and this value is per BMC
-// SoC.
-#define MAX_IPMI_BUFFER 64
-
TEST(BlobCommitTest, InvalidCommitDataLengthReturnsFailure)
{
// The commit command supports an optional commit blob. This test verifies
// we sanity check the length of that blob.
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobCommitTx*>(request);
-
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobCommit);
- req->crc = 0;
- req->sessionId = 0x54;
- req->commitDataLen =
+ std::vector<uint8_t> request;
+ struct BmcBlobCommitTx req;
+ req.crc = 0;
+ req.sessionId = 0x54;
+ req.commitDataLen =
1; // It's one byte, but that's more than the packet size.
- dataLen = sizeof(struct BmcBlobCommitTx);
-
- EXPECT_EQ(IPMI_CC_REQ_DATA_LEN_INVALID,
- commitBlob(&mgr, request, reply, &dataLen));
+ request.resize(sizeof(struct BmcBlobCommitTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobCommitTx));
+ EXPECT_EQ(ipmi::responseReqDataLenInvalid(), commitBlob(&mgr, request));
}
TEST(BlobCommitTest, ValidCommitNoDataHandlerRejectsReturnsFailure)
@@ -44,22 +35,17 @@
// The commit packet is valid and the manager's commit call returns failure.
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobCommitTx*>(request);
+ std::vector<uint8_t> request;
+ struct BmcBlobCommitTx req;
+ req.crc = 0;
+ req.sessionId = 0x54;
+ req.commitDataLen = 0;
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobCommit);
- req->crc = 0;
- req->sessionId = 0x54;
- req->commitDataLen = 0;
+ request.resize(sizeof(struct BmcBlobCommitTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobCommitTx));
- dataLen = sizeof(struct BmcBlobCommitTx);
-
- EXPECT_CALL(mgr, commit(req->sessionId, _)).WillOnce(Return(false));
-
- EXPECT_EQ(IPMI_CC_UNSPECIFIED_ERROR,
- commitBlob(&mgr, request, reply, &dataLen));
+ EXPECT_CALL(mgr, commit(req.sessionId, _)).WillOnce(Return(false));
+ EXPECT_EQ(ipmi::responseUnspecifiedError(), commitBlob(&mgr, request));
}
TEST(BlobCommitTest, ValidCommitNoDataHandlerAcceptsReturnsSuccess)
@@ -67,21 +53,18 @@
// Commit called with no data and everything returns success.
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobCommitTx*>(request);
+ std::vector<uint8_t> request;
+ struct BmcBlobCommitTx req;
+ req.crc = 0;
+ req.sessionId = 0x54;
+ req.commitDataLen = 0;
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobCommit);
- req->crc = 0;
- req->sessionId = 0x54;
- req->commitDataLen = 0;
+ request.resize(sizeof(struct BmcBlobCommitTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobCommitTx));
+ EXPECT_CALL(mgr, commit(req.sessionId, _)).WillOnce(Return(true));
- dataLen = sizeof(struct BmcBlobCommitTx);
-
- EXPECT_CALL(mgr, commit(req->sessionId, _)).WillOnce(Return(true));
-
- EXPECT_EQ(IPMI_CC_OK, commitBlob(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseSuccess(std::vector<uint8_t>{}),
+ commitBlob(&mgr, request));
}
TEST(BlobCommitTest, ValidCommitWithDataHandlerAcceptsReturnsSuccess)
@@ -89,26 +72,21 @@
// Commit called with extra data and everything returns success.
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobCommitTx*>(request);
+ std::vector<uint8_t> request;
+ std::array<uint8_t, 4> expectedBlob = {0x25, 0x33, 0x45, 0x67};
+ struct BmcBlobCommitTx req;
+ req.crc = 0;
+ req.sessionId = 0x54;
+ req.commitDataLen = sizeof(expectedBlob);
- uint8_t expectedBlob[4] = {0x25, 0x33, 0x45, 0x67};
+ request.resize(sizeof(struct BmcBlobCommitTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobCommitTx));
+ request.insert(request.end(), expectedBlob.begin(), expectedBlob.end());
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobCommit);
- req->crc = 0;
- req->sessionId = 0x54;
- req->commitDataLen = sizeof(expectedBlob);
- std::memcpy(req + 1, &expectedBlob[0], sizeof(expectedBlob));
-
- dataLen = sizeof(struct BmcBlobCommitTx) + sizeof(expectedBlob);
-
- EXPECT_CALL(mgr,
- commit(req->sessionId,
- ElementsAreArray(expectedBlob, sizeof(expectedBlob))))
+ EXPECT_CALL(mgr, commit(req.sessionId, ElementsAreArray(expectedBlob)))
.WillOnce(Return(true));
- EXPECT_EQ(IPMI_CC_OK, commitBlob(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseSuccess(std::vector<uint8_t>{}),
+ commitBlob(&mgr, request));
}
} // namespace blobs
diff --git a/test/ipmi_delete_unittest.cpp b/test/ipmi_delete_unittest.cpp
index 3336b2d..cb1401a 100644
--- a/test/ipmi_delete_unittest.cpp
+++ b/test/ipmi_delete_unittest.cpp
@@ -12,79 +12,58 @@
using ::testing::Return;
using ::testing::StrEq;
-// ipmid.hpp isn't installed where we can grab it and this value is per BMC
-// SoC.
-#define MAX_IPMI_BUFFER 64
-
TEST(BlobDeleteTest, InvalidRequestLengthReturnsFailure)
{
// There is a minimum blobId length of one character, this test verifies
// we check that.
-
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobDeleteTx*>(request);
+ std::vector<uint8_t> request;
+ struct BmcBlobDeleteTx req;
+ req.crc = 0;
std::string blobId = "abc";
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobDelete);
- req->crc = 0;
- // length() doesn't include the nul-terminator.
- std::memcpy(req + 1, blobId.c_str(), blobId.length());
+ request.resize(sizeof(struct BmcBlobDeleteTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobDeleteTx));
+ request.insert(request.end(), blobId.begin(), blobId.end());
- dataLen = sizeof(struct BmcBlobDeleteTx) + blobId.length();
-
- EXPECT_EQ(IPMI_CC_REQ_DATA_LEN_INVALID,
- deleteBlob(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseReqDataLenInvalid(), deleteBlob(&mgr, request));
}
TEST(BlobDeleteTest, RequestRejectedReturnsFailure)
{
// The blobId is rejected for any reason.
-
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobDeleteTx*>(request);
+ std::vector<uint8_t> request;
+ struct BmcBlobDeleteTx req;
+ req.crc = 0;
std::string blobId = "a";
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobDelete);
- req->crc = 0;
- // length() doesn't include the nul-terminator, request buff is initialized
- // to 0s
- std::memcpy(req + 1, blobId.c_str(), blobId.length());
-
- dataLen = sizeof(struct BmcBlobDeleteTx) + blobId.length() + 1;
+ request.resize(sizeof(struct BmcBlobDeleteTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobDeleteTx));
+ request.insert(request.end(), blobId.begin(), blobId.end());
+ request.emplace_back('\0');
EXPECT_CALL(mgr, deleteBlob(StrEq(blobId))).WillOnce(Return(false));
-
- EXPECT_EQ(IPMI_CC_UNSPECIFIED_ERROR,
- deleteBlob(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseUnspecifiedError(), deleteBlob(&mgr, request));
}
TEST(BlobDeleteTest, BlobDeleteReturnsOk)
{
// The boring case where the blobId is deleted.
-
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobDeleteTx*>(request);
+ std::vector<uint8_t> request;
+ struct BmcBlobDeleteTx req;
+ req.crc = 0;
std::string blobId = "a";
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobDelete);
- req->crc = 0;
- // length() doesn't include the nul-terminator, request buff is initialized
- // to 0s
- std::memcpy(req + 1, blobId.c_str(), blobId.length());
-
- dataLen = sizeof(struct BmcBlobDeleteTx) + blobId.length() + 1;
+ request.resize(sizeof(struct BmcBlobDeleteTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobDeleteTx));
+ request.insert(request.end(), blobId.begin(), blobId.end());
+ request.emplace_back('\0');
EXPECT_CALL(mgr, deleteBlob(StrEq(blobId))).WillOnce(Return(true));
- EXPECT_EQ(IPMI_CC_OK, deleteBlob(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseSuccess(std::vector<uint8_t>{}),
+ deleteBlob(&mgr, request));
}
} // namespace blobs
diff --git a/test/ipmi_enumerate_unittest.cpp b/test/ipmi_enumerate_unittest.cpp
index edea82b..87752ea 100644
--- a/test/ipmi_enumerate_unittest.cpp
+++ b/test/ipmi_enumerate_unittest.cpp
@@ -1,3 +1,4 @@
+#include "helper.hpp"
#include "ipmi.hpp"
#include "manager_mock.hpp"
@@ -11,28 +12,21 @@
using ::testing::Return;
-// ipmid.hpp isn't installed where we can grab it and this value is per BMC
-// SoC.
-#define MAX_IPMI_BUFFER 64
-
TEST(BlobEnumerateTest, VerifyIfRequestByIdInvalidReturnsFailure)
{
// This tests to verify that if the index is invalid, it'll return failure.
ManagerMock mgr;
- size_t dataLen;
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
+ std::vector<uint8_t> request;
struct BmcBlobEnumerateTx req;
- uint8_t* request = reinterpret_cast<uint8_t*>(&req);
-
- req.cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobEnumerate);
req.blobIdx = 0;
- dataLen = sizeof(struct BmcBlobEnumerateTx);
+
+ request.resize(sizeof(struct BmcBlobEnumerateTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobEnumerateTx));
EXPECT_CALL(mgr, getBlobId(req.blobIdx)).WillOnce(Return(""));
-
- EXPECT_EQ(IPMI_CC_INVALID_FIELD_REQUEST,
- enumerateBlob(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseInvalidFieldRequest(),
+ enumerateBlob(&mgr, request));
}
TEST(BlobEnumerateTest, BoringRequestByIdAndReceive)
@@ -41,26 +35,23 @@
// will return the blobId.
ManagerMock mgr;
- size_t dataLen;
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
+ std::vector<uint8_t> request;
struct BmcBlobEnumerateTx req;
- struct BmcBlobEnumerateRx* rep;
- uint8_t* request = reinterpret_cast<uint8_t*>(&req);
+ req.blobIdx = 0;
std::string blobId = "/asdf";
- req.cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobEnumerate);
- req.blobIdx = 0;
- dataLen = sizeof(struct BmcBlobEnumerateTx);
+ request.resize(sizeof(struct BmcBlobEnumerateTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobEnumerateTx));
EXPECT_CALL(mgr, getBlobId(req.blobIdx)).WillOnce(Return(blobId));
- EXPECT_EQ(IPMI_CC_OK, enumerateBlob(&mgr, request, reply, &dataLen));
+ auto result = validateReply(enumerateBlob(&mgr, request));
// We're expecting this as a response.
// blobId.length + 1 + sizeof(uint16_t);
- EXPECT_EQ(blobId.length() + 1 + sizeof(uint16_t), dataLen);
-
- rep = reinterpret_cast<struct BmcBlobEnumerateRx*>(reply);
- EXPECT_EQ(0, std::memcmp(rep + 1, blobId.c_str(), blobId.length() + 1));
+ EXPECT_EQ(blobId.length() + 1 + sizeof(uint16_t), result.size());
+ EXPECT_EQ(blobId,
+ // Remove crc and nul-terminator.
+ std::string(result.begin() + sizeof(uint16_t), result.end() - 1));
}
} // namespace blobs
diff --git a/test/ipmi_getcount_unittest.cpp b/test/ipmi_getcount_unittest.cpp
index 34fc33d..dc1202d 100644
--- a/test/ipmi_getcount_unittest.cpp
+++ b/test/ipmi_getcount_unittest.cpp
@@ -1,3 +1,4 @@
+#include "helper.hpp"
#include "ipmi.hpp"
#include "manager_mock.hpp"
@@ -11,10 +12,6 @@
using ::testing::Return;
-// ipmid.hpp isn't installed where we can grab it and this value is per BMC
-// SoC.
-#define MAX_IPMI_BUFFER 64
-
// the request here is only the subcommand byte and therefore there's no invalid
// length check, etc to handle within the method.
@@ -24,24 +21,17 @@
// return that there are 0 blobs.
ManagerMock mgr;
- size_t dataLen;
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- struct BmcBlobCountTx req;
struct BmcBlobCountRx rep;
- uint8_t* request = reinterpret_cast<uint8_t*>(&req);
-
- req.cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobGetCount);
- dataLen = sizeof(req);
rep.crc = 0;
rep.blobCount = 0;
EXPECT_CALL(mgr, buildBlobList()).WillOnce(Return(0));
- EXPECT_EQ(IPMI_CC_OK, getBlobCount(&mgr, request, reply, &dataLen));
+ auto result = validateReply(getBlobCount(&mgr, {}));
- EXPECT_EQ(sizeof(rep), dataLen);
- EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep)));
+ EXPECT_EQ(sizeof(rep), result.size());
+ EXPECT_EQ(0, std::memcmp(result.data(), &rep, sizeof(rep)));
}
TEST(BlobCountTest, ReturnsTwoBlobs)
@@ -50,23 +40,16 @@
// blobs will return that it found two blobs.
ManagerMock mgr;
- size_t dataLen;
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- struct BmcBlobCountTx req;
struct BmcBlobCountRx rep;
- uint8_t* request = reinterpret_cast<uint8_t*>(&req);
-
- req.cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobGetCount);
- dataLen = sizeof(req);
rep.crc = 0;
rep.blobCount = 2;
EXPECT_CALL(mgr, buildBlobList()).WillOnce(Return(2));
- EXPECT_EQ(IPMI_CC_OK, getBlobCount(&mgr, request, reply, &dataLen));
+ auto result = validateReply(getBlobCount(&mgr, {}));
- EXPECT_EQ(sizeof(rep), dataLen);
- EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep)));
+ EXPECT_EQ(sizeof(rep), result.size());
+ EXPECT_EQ(0, std::memcmp(result.data(), &rep, sizeof(rep)));
}
} // namespace blobs
diff --git a/test/ipmi_open_unittest.cpp b/test/ipmi_open_unittest.cpp
index 5b18631..b938cbe 100644
--- a/test/ipmi_open_unittest.cpp
+++ b/test/ipmi_open_unittest.cpp
@@ -1,3 +1,4 @@
+#include "helper.hpp"
#include "ipmi.hpp"
#include "manager_mock.hpp"
@@ -15,59 +16,44 @@
using ::testing::Return;
using ::testing::StrEq;
-// ipmid.hpp isn't installed where we can grab it and this value is per BMC
-// SoC.
-#define MAX_IPMI_BUFFER 64
-
TEST(BlobOpenTest, InvalidRequestLengthReturnsFailure)
{
// There is a minimum blobId length of one character, this test verifies
// we check that.
-
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobOpenTx*>(request);
+ std::vector<uint8_t> request;
+ BmcBlobOpenTx req;
std::string blobId = "abc";
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobOpen);
- req->crc = 0;
- req->flags = 0;
- // length() doesn't include the nul-terminator.
- std::memcpy(req + 1, blobId.c_str(), blobId.length());
+ req.crc = 0;
+ req.flags = 0;
- dataLen = sizeof(struct BmcBlobOpenTx) + blobId.length();
+ // Missintg the nul-terminator.
+ request.resize(sizeof(struct BmcBlobOpenTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobOpenTx));
+ request.insert(request.end(), blobId.begin(), blobId.end());
- EXPECT_EQ(IPMI_CC_REQ_DATA_LEN_INVALID,
- openBlob(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseReqDataLenInvalid(), openBlob(&mgr, request));
}
TEST(BlobOpenTest, RequestRejectedReturnsFailure)
{
// The blobId is rejected for any reason.
-
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobOpenTx*>(request);
+ std::vector<uint8_t> request;
+ BmcBlobOpenTx req;
std::string blobId = "a";
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobOpen);
- req->crc = 0;
- req->flags = 0;
- // length() doesn't include the nul-terminator, request buff is initialized
- // to 0s
- std::memcpy(req + 1, blobId.c_str(), blobId.length());
+ req.crc = 0;
+ req.flags = 0;
+ request.resize(sizeof(struct BmcBlobOpenTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobOpenTx));
+ request.insert(request.end(), blobId.begin(), blobId.end());
+ request.emplace_back('\0');
- dataLen = sizeof(struct BmcBlobOpenTx) + blobId.length() + 1;
+ EXPECT_CALL(mgr, open(req.flags, StrEq(blobId), _)).WillOnce(Return(false));
- EXPECT_CALL(mgr, open(req->flags, StrEq(blobId), _))
- .WillOnce(Return(false));
-
- EXPECT_EQ(IPMI_CC_UNSPECIFIED_ERROR,
- openBlob(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseUnspecifiedError(), openBlob(&mgr, request));
}
TEST(BlobOpenTest, BlobOpenReturnsOk)
@@ -75,35 +61,32 @@
// The boring case where the blobId opens.
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobOpenTx*>(request);
+ std::vector<uint8_t> request;
+ BmcBlobOpenTx req;
struct BmcBlobOpenRx rep;
std::string blobId = "a";
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobOpen);
- req->crc = 0;
- req->flags = 0;
- // length() doesn't include the nul-terminator, request buff is initialized
- // to 0s
- std::memcpy(req + 1, blobId.c_str(), blobId.length());
+ req.crc = 0;
+ req.flags = 0;
+ request.resize(sizeof(struct BmcBlobOpenTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobOpenTx));
+ request.insert(request.end(), blobId.begin(), blobId.end());
+ request.emplace_back('\0');
- dataLen = sizeof(struct BmcBlobOpenTx) + blobId.length() + 1;
uint16_t returnedSession = 0x54;
- EXPECT_CALL(mgr, open(req->flags, StrEq(blobId), NotNull()))
+ EXPECT_CALL(mgr, open(req.flags, StrEq(blobId), NotNull()))
.WillOnce(Invoke([&](uint16_t, const std::string&, uint16_t* session) {
(*session) = returnedSession;
return true;
}));
- EXPECT_EQ(IPMI_CC_OK, openBlob(&mgr, request, reply, &dataLen));
+ auto result = validateReply(openBlob(&mgr, request));
rep.crc = 0;
rep.sessionId = returnedSession;
- EXPECT_EQ(sizeof(rep), dataLen);
- EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep)));
+ EXPECT_EQ(sizeof(rep), result.size());
+ EXPECT_EQ(0, std::memcmp(result.data(), &rep, sizeof(rep)));
}
} // namespace blobs
diff --git a/test/ipmi_read_unittest.cpp b/test/ipmi_read_unittest.cpp
index 8d1b55f..80e1cbc 100644
--- a/test/ipmi_read_unittest.cpp
+++ b/test/ipmi_read_unittest.cpp
@@ -1,3 +1,4 @@
+#include "helper.hpp"
#include "ipmi.hpp"
#include "manager_mock.hpp"
@@ -11,64 +12,50 @@
using ::testing::Return;
-// ipmid.hpp isn't installed where we can grab it and this value is per BMC
-// SoC.
-#define MAX_IPMI_BUFFER 64
-
TEST(BlobReadTest, ManagerReturnsNoData)
{
// Verify that if no data is returned the IPMI command reply has no
// payload. The manager, in all failures, will just return 0 bytes.
-
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobReadTx*>(request);
+ std::vector<uint8_t> request;
+ struct BmcBlobReadTx req;
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobRead);
- req->crc = 0;
- req->sessionId = 0x54;
- req->offset = 0x100;
- req->requestedSize = 0x10;
-
- dataLen = sizeof(struct BmcBlobReadTx);
-
+ req.crc = 0;
+ req.sessionId = 0x54;
+ req.offset = 0x100;
+ req.requestedSize = 0x10;
+ request.resize(sizeof(struct BmcBlobReadTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobReadTx));
std::vector<uint8_t> data;
- EXPECT_CALL(mgr, read(req->sessionId, req->offset, req->requestedSize))
+ EXPECT_CALL(mgr, read(req.sessionId, req.offset, req.requestedSize))
.WillOnce(Return(data));
- EXPECT_EQ(IPMI_CC_OK, readBlob(&mgr, request, reply, &dataLen));
- EXPECT_EQ(sizeof(struct BmcBlobReadRx), dataLen);
+ auto result = validateReply(readBlob(&mgr, request));
+ EXPECT_EQ(sizeof(struct BmcBlobReadRx), result.size());
}
TEST(BlobReadTest, ManagerReturnsData)
{
// Verify that if data is returned, it's placed in the expected location.
-
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobReadTx*>(request);
+ std::vector<uint8_t> request;
+ struct BmcBlobReadTx req;
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobRead);
- req->crc = 0;
- req->sessionId = 0x54;
- req->offset = 0x100;
- req->requestedSize = 0x10;
-
- dataLen = sizeof(struct BmcBlobReadTx);
-
+ req.crc = 0;
+ req.sessionId = 0x54;
+ req.offset = 0x100;
+ req.requestedSize = 0x10;
+ request.resize(sizeof(struct BmcBlobReadTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobReadTx));
std::vector<uint8_t> data = {0x02, 0x03, 0x05, 0x06};
- EXPECT_CALL(mgr, read(req->sessionId, req->offset, req->requestedSize))
+ EXPECT_CALL(mgr, read(req.sessionId, req.offset, req.requestedSize))
.WillOnce(Return(data));
- EXPECT_EQ(IPMI_CC_OK, readBlob(&mgr, request, reply, &dataLen));
- EXPECT_EQ(sizeof(struct BmcBlobReadRx) + data.size(), dataLen);
- EXPECT_EQ(0, std::memcmp(&reply[sizeof(struct BmcBlobReadRx)], data.data(),
+ auto result = validateReply(readBlob(&mgr, request));
+ EXPECT_EQ(sizeof(struct BmcBlobReadRx) + data.size(), result.size());
+ EXPECT_EQ(0, std::memcmp(&result[sizeof(struct BmcBlobReadRx)], data.data(),
data.size()));
}
diff --git a/test/ipmi_sessionstat_unittest.cpp b/test/ipmi_sessionstat_unittest.cpp
index 4bf1125..3278f25 100644
--- a/test/ipmi_sessionstat_unittest.cpp
+++ b/test/ipmi_sessionstat_unittest.cpp
@@ -1,3 +1,4 @@
+#include "helper.hpp"
#include "ipmi.hpp"
#include "manager_mock.hpp"
@@ -23,22 +24,19 @@
// If the session ID is invalid, the request must fail.
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobSessionStatTx*>(request);
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobSessionStat);
- req->crc = 0;
- req->sessionId = 0x54;
+ std::vector<uint8_t> request;
+ struct BmcBlobSessionStatTx req;
+ req.crc = 0;
+ req.sessionId = 0x54;
- dataLen = sizeof(struct BmcBlobSessionStatTx);
+ request.resize(sizeof(struct BmcBlobSessionStatTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobSessionStatTx));
EXPECT_CALL(mgr,
- stat(Matcher<uint16_t>(req->sessionId), Matcher<BlobMeta*>(_)))
+ stat(Matcher<uint16_t>(req.sessionId), Matcher<BlobMeta*>(_)))
.WillOnce(Return(false));
- EXPECT_EQ(IPMI_CC_UNSPECIFIED_ERROR,
- sessionStatBlob(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseUnspecifiedError(), sessionStatBlob(&mgr, request));
}
TEST(BlobSessionStatTest, RequestSucceedsNoMetadata)
@@ -46,15 +44,13 @@
// Stat request succeeeds but there were no metadata bytes.
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobSessionStatTx*>(request);
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobSessionStat);
- req->crc = 0;
- req->sessionId = 0x54;
+ std::vector<uint8_t> request;
+ struct BmcBlobSessionStatTx req;
+ req.crc = 0;
+ req.sessionId = 0x54;
- dataLen = sizeof(struct BmcBlobSessionStatTx);
+ request.resize(sizeof(struct BmcBlobSessionStatTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobSessionStatTx));
struct BmcBlobStatRx rep;
rep.crc = 0x00;
@@ -65,7 +61,7 @@
uint16_t blobState = rep.blobState;
uint32_t size = rep.size;
- EXPECT_CALL(mgr, stat(Matcher<uint16_t>(req->sessionId),
+ EXPECT_CALL(mgr, stat(Matcher<uint16_t>(req.sessionId),
Matcher<BlobMeta*>(NotNull())))
.WillOnce(Invoke([&](uint16_t, BlobMeta* meta) {
meta->blobState = blobState;
@@ -73,10 +69,10 @@
return true;
}));
- EXPECT_EQ(IPMI_CC_OK, sessionStatBlob(&mgr, request, reply, &dataLen));
+ auto result = validateReply(sessionStatBlob(&mgr, request));
- EXPECT_EQ(sizeof(rep), dataLen);
- EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep)));
+ EXPECT_EQ(sizeof(rep), result.size());
+ EXPECT_EQ(0, std::memcmp(result.data(), &rep, sizeof(rep)));
}
TEST(BlobSessionStatTest, RequestSucceedsWithMetadata)
@@ -84,15 +80,13 @@
// Stat request succeeds and there were metadata bytes.
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobSessionStatTx*>(request);
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobSessionStat);
- req->crc = 0;
- req->sessionId = 0x54;
+ std::vector<uint8_t> request;
+ struct BmcBlobSessionStatTx req;
+ req.crc = 0;
+ req.sessionId = 0x54;
- dataLen = sizeof(struct BmcBlobSessionStatTx);
+ request.resize(sizeof(struct BmcBlobSessionStatTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobSessionStatTx));
BlobMeta lmeta;
lmeta.blobState = 0x01;
@@ -108,18 +102,18 @@
rep.size = lmeta.size;
rep.metadataLen = lmeta.metadata.size();
- EXPECT_CALL(mgr, stat(Matcher<uint16_t>(req->sessionId),
+ EXPECT_CALL(mgr, stat(Matcher<uint16_t>(req.sessionId),
Matcher<BlobMeta*>(NotNull())))
.WillOnce(Invoke([&](uint16_t, BlobMeta* meta) {
(*meta) = lmeta;
return true;
}));
- EXPECT_EQ(IPMI_CC_OK, sessionStatBlob(&mgr, request, reply, &dataLen));
+ auto result = validateReply(sessionStatBlob(&mgr, request));
- EXPECT_EQ(sizeof(rep) + lmeta.metadata.size(), dataLen);
- EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep)));
- EXPECT_EQ(0, std::memcmp(reply + sizeof(rep), lmeta.metadata.data(),
+ EXPECT_EQ(sizeof(rep) + lmeta.metadata.size(), result.size());
+ EXPECT_EQ(0, std::memcmp(result.data(), &rep, sizeof(rep)));
+ EXPECT_EQ(0, std::memcmp(result.data() + sizeof(rep), lmeta.metadata.data(),
lmeta.metadata.size()));
}
} // namespace blobs
diff --git a/test/ipmi_stat_unittest.cpp b/test/ipmi_stat_unittest.cpp
index 6d4d7b2..ab091ad 100644
--- a/test/ipmi_stat_unittest.cpp
+++ b/test/ipmi_stat_unittest.cpp
@@ -1,3 +1,4 @@
+#include "helper.hpp"
#include "ipmi.hpp"
#include "manager_mock.hpp"
@@ -24,23 +25,18 @@
{
// There is a minimum blobId length of one character, this test verifies
// we check that.
-
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobStatTx*>(request);
+ std::vector<uint8_t> request;
+ struct BmcBlobStatTx req;
std::string blobId = "abc";
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobStat);
- req->crc = 0;
- // length() doesn't include the nul-terminator.
- std::memcpy(req + 1, blobId.c_str(), blobId.length());
+ req.crc = 0;
+ request.resize(sizeof(struct BmcBlobStatTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobStatTx));
+ // Do not include the nul-terminator
+ request.insert(request.end(), blobId.begin(), blobId.end());
- dataLen = sizeof(struct BmcBlobStatTx) + blobId.length();
-
- EXPECT_EQ(IPMI_CC_REQ_DATA_LEN_INVALID,
- statBlob(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseReqDataLenInvalid(), statBlob(&mgr, request));
}
TEST(BlobStatTest, RequestRejectedReturnsFailure)
@@ -48,26 +44,21 @@
// The blobId is rejected for any reason.
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobStatTx*>(request);
+ std::vector<uint8_t> request;
+ struct BmcBlobStatTx req;
std::string blobId = "a";
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobStat);
- req->crc = 0;
- // length() doesn't include the nul-terminator, request buff is initialized
- // to 0s
- std::memcpy(req + 1, blobId.c_str(), blobId.length());
-
- dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1;
+ req.crc = 0;
+ request.resize(sizeof(struct BmcBlobStatTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobStatTx));
+ request.insert(request.end(), blobId.begin(), blobId.end());
+ request.emplace_back('\0');
EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)),
Matcher<BlobMeta*>(_)))
.WillOnce(Return(false));
- EXPECT_EQ(IPMI_CC_UNSPECIFIED_ERROR,
- statBlob(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseUnspecifiedError(), statBlob(&mgr, request));
}
TEST(BlobStatTest, RequestSucceedsNoMetadata)
@@ -75,19 +66,15 @@
// Stat request succeeeds but there were no metadata bytes.
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobStatTx*>(request);
+ std::vector<uint8_t> request;
+ struct BmcBlobStatTx req;
std::string blobId = "a";
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobStat);
- req->crc = 0;
- // length() doesn't include the nul-terminator, request buff is initialized
- // to 0s
- std::memcpy(req + 1, blobId.c_str(), blobId.length());
-
- dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1;
+ req.crc = 0;
+ request.resize(sizeof(struct BmcBlobStatTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobStatTx));
+ request.insert(request.end(), blobId.begin(), blobId.end());
+ request.emplace_back('\0');
struct BmcBlobStatRx rep;
rep.crc = 0x00;
@@ -106,10 +93,10 @@
return true;
}));
- EXPECT_EQ(IPMI_CC_OK, statBlob(&mgr, request, reply, &dataLen));
+ auto result = validateReply(statBlob(&mgr, request));
- EXPECT_EQ(sizeof(rep), dataLen);
- EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep)));
+ EXPECT_EQ(sizeof(rep), result.size());
+ EXPECT_EQ(0, std::memcmp(result.data(), &rep, sizeof(rep)));
}
TEST(BlobStatTest, RequestSucceedsWithMetadata)
@@ -117,19 +104,15 @@
// Stat request succeeds and there were metadata bytes.
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobStatTx*>(request);
+ std::vector<uint8_t> request;
+ struct BmcBlobStatTx req;
std::string blobId = "a";
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobStat);
- req->crc = 0;
- // length() doesn't include the nul-terminator, request buff is initialized
- // to 0s
- std::memcpy(req + 1, blobId.c_str(), blobId.length());
-
- dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1;
+ req.crc = 0;
+ request.resize(sizeof(struct BmcBlobStatTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobStatTx));
+ request.insert(request.end(), blobId.begin(), blobId.end());
+ request.emplace_back('\0');
BlobMeta lmeta;
lmeta.blobState = 0x01;
@@ -152,11 +135,11 @@
return true;
}));
- EXPECT_EQ(IPMI_CC_OK, statBlob(&mgr, request, reply, &dataLen));
+ auto result = validateReply(statBlob(&mgr, request));
- EXPECT_EQ(sizeof(rep) + lmeta.metadata.size(), dataLen);
- EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep)));
- EXPECT_EQ(0, std::memcmp(reply + sizeof(rep), lmeta.metadata.data(),
+ EXPECT_EQ(sizeof(rep) + lmeta.metadata.size(), result.size());
+ EXPECT_EQ(0, std::memcmp(result.data(), &rep, sizeof(rep)));
+ EXPECT_EQ(0, std::memcmp(result.data() + sizeof(rep), lmeta.metadata.data(),
lmeta.metadata.size()));
}
} // namespace blobs
diff --git a/test/ipmi_unittest.cpp b/test/ipmi_unittest.cpp
index 8f27ed7..ed2f026 100644
--- a/test/ipmi_unittest.cpp
+++ b/test/ipmi_unittest.cpp
@@ -14,47 +14,37 @@
TEST(StringInputTest, NullPointerInput)
{
// The method should verify it did receive a non-null input pointer.
-
- EXPECT_STREQ("", stringFromBuffer(NULL, 5).c_str());
+ EXPECT_STREQ("", stringFromBuffer({}).c_str());
}
TEST(StringInputTest, ZeroBytesInput)
{
// Verify that if the input length is 0 that it'll return the empty string.
-
- const char* request = "asdf";
- EXPECT_STREQ("", stringFromBuffer(request, 0).c_str());
+ const std::string request = "asdf";
+ EXPECT_STREQ("", stringFromBuffer(
+ std::vector<uint8_t>(request.begin(), request.end()))
+ .c_str());
}
TEST(StringInputTest, NulTerminatorNotFound)
{
// Verify that if there isn't a nul-terminator found in an otherwise valid
// string, it'll return the emptry string.
-
- char request[MAX_IPMI_BUFFER];
- std::memset(request, 'a', sizeof(request));
- EXPECT_STREQ("", stringFromBuffer(request, sizeof(request)).c_str());
-}
-
-TEST(StringInputTest, TwoNulsFound)
-{
- // Verify it makes you use the entire data region for the string.
- char request[MAX_IPMI_BUFFER];
- request[0] = 'a';
- request[1] = 0;
- std::memset(&request[2], 'b', sizeof(request) - 2);
- request[MAX_IPMI_BUFFER - 1] = 0;
-
- // This case has two strings, and the last character is a nul-terminator.
- EXPECT_STREQ("", stringFromBuffer(request, sizeof(request)).c_str());
+ std::array<char, MAX_IPMI_BUFFER> request;
+ std::memset(request.data(), 'a', sizeof(request));
+ EXPECT_STREQ("", stringFromBuffer(
+ std::vector<uint8_t>(request.begin(), request.end()))
+ .c_str());
}
TEST(StringInputTest, NulTerminatorFound)
{
// Verify that if it's provided a valid nul-terminated string, it'll
// return it.
-
- const char* request = "asdf";
- EXPECT_STREQ("asdf", stringFromBuffer(request, 5).c_str());
+ std::string request = "asdf";
+ request.push_back('\0');
+ EXPECT_STREQ("asdf", stringFromBuffer(std::vector<uint8_t>(request.begin(),
+ request.end()))
+ .c_str());
}
} // namespace blobs
diff --git a/test/ipmi_write_unittest.cpp b/test/ipmi_write_unittest.cpp
index 229ebd3..12cf1bc 100644
--- a/test/ipmi_write_unittest.cpp
+++ b/test/ipmi_write_unittest.cpp
@@ -1,47 +1,38 @@
+#include "helper.hpp"
#include "ipmi.hpp"
#include "manager_mock.hpp"
#include <cstring>
#include <gtest/gtest.h>
-
namespace blobs
{
using ::testing::ElementsAreArray;
using ::testing::Return;
-// ipmid.hpp isn't installed where we can grab it and this value is per BMC
-// SoC.
-#define MAX_IPMI_BUFFER 64
-
TEST(BlobWriteTest, ManagerReturnsFailureReturnsFailure)
{
// This verifies a failure from the manager is passed back.
-
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobWriteTx*>(request);
+ std::vector<uint8_t> request;
+ struct BmcBlobWriteTx req;
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobWrite);
- req->crc = 0;
- req->sessionId = 0x54;
- req->offset = 0x100;
+ req.crc = 0;
+ req.sessionId = 0x54;
+ req.offset = 0x100;
- uint8_t expectedBytes[2] = {0x66, 0x67};
- std::memcpy(req + 1, &expectedBytes[0], sizeof(expectedBytes));
+ request.resize(sizeof(struct BmcBlobWriteTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobWriteTx));
- dataLen = sizeof(struct BmcBlobWriteTx) + sizeof(expectedBytes);
+ std::array<uint8_t, 2> expectedBytes = {0x66, 0x67};
+ request.insert(request.end(), expectedBytes.begin(), expectedBytes.end());
- EXPECT_CALL(mgr,
- write(req->sessionId, req->offset,
- ElementsAreArray(expectedBytes, sizeof(expectedBytes))))
+ EXPECT_CALL(
+ mgr, write(req.sessionId, req.offset, ElementsAreArray(expectedBytes)))
.WillOnce(Return(false));
- EXPECT_EQ(IPMI_CC_UNSPECIFIED_ERROR,
- writeBlob(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseUnspecifiedError(), writeBlob(&mgr, request));
}
TEST(BlobWriteTest, ManagerReturnsTrueWriteSucceeds)
@@ -49,26 +40,24 @@
// The case where everything works.
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobWriteTx*>(request);
+ std::vector<uint8_t> request;
+ struct BmcBlobWriteTx req;
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobWrite);
- req->crc = 0;
- req->sessionId = 0x54;
- req->offset = 0x100;
+ req.crc = 0;
+ req.sessionId = 0x54;
+ req.offset = 0x100;
- uint8_t expectedBytes[2] = {0x66, 0x67};
- std::memcpy(req + 1, &expectedBytes[0], sizeof(expectedBytes));
+ request.resize(sizeof(struct BmcBlobWriteTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobWriteTx));
- dataLen = sizeof(struct BmcBlobWriteTx) + sizeof(expectedBytes);
+ std::array<uint8_t, 2> expectedBytes = {0x66, 0x67};
+ request.insert(request.end(), expectedBytes.begin(), expectedBytes.end());
- EXPECT_CALL(mgr,
- write(req->sessionId, req->offset,
- ElementsAreArray(expectedBytes, sizeof(expectedBytes))))
+ EXPECT_CALL(
+ mgr, write(req.sessionId, req.offset, ElementsAreArray(expectedBytes)))
.WillOnce(Return(true));
- EXPECT_EQ(IPMI_CC_OK, writeBlob(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseSuccess(std::vector<uint8_t>{}),
+ writeBlob(&mgr, request));
}
} // namespace blobs
diff --git a/test/ipmi_writemeta_unittest.cpp b/test/ipmi_writemeta_unittest.cpp
index dd9e742..bc8669d 100644
--- a/test/ipmi_writemeta_unittest.cpp
+++ b/test/ipmi_writemeta_unittest.cpp
@@ -17,57 +17,49 @@
TEST(BlobWriteMetaTest, ManagerReturnsFailureReturnsFailure)
{
// This verifies a failure from the manager is passed back.
-
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobWriteMetaTx*>(request);
+ std::vector<uint8_t> request;
+ struct BmcBlobWriteMetaTx req;
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobWrite);
- req->crc = 0;
- req->sessionId = 0x54;
- req->offset = 0x100;
+ req.crc = 0;
+ req.sessionId = 0x54;
+ req.offset = 0x100;
- uint8_t expectedBytes[2] = {0x66, 0x67};
- std::memcpy(req + 1, &expectedBytes[0], sizeof(expectedBytes));
+ request.resize(sizeof(struct BmcBlobWriteMetaTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobWriteMetaTx));
- dataLen = sizeof(struct BmcBlobWriteMetaTx) + sizeof(expectedBytes);
+ std::array<uint8_t, 2> expectedBytes = {0x66, 0x67};
+ request.insert(request.end(), expectedBytes.begin(), expectedBytes.end());
- EXPECT_CALL(
- mgr, writeMeta(req->sessionId, req->offset,
- ElementsAreArray(expectedBytes, sizeof(expectedBytes))))
+ EXPECT_CALL(mgr, writeMeta(req.sessionId, req.offset,
+ ElementsAreArray(expectedBytes)))
.WillOnce(Return(false));
- EXPECT_EQ(IPMI_CC_UNSPECIFIED_ERROR,
- writeMeta(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseUnspecifiedError(), writeMeta(&mgr, request));
}
TEST(BlobWriteMetaTest, ManagerReturnsTrueWriteSucceeds)
{
// The case where everything works.
-
ManagerMock mgr;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
- auto req = reinterpret_cast<struct BmcBlobWriteMetaTx*>(request);
+ std::vector<uint8_t> request;
+ struct BmcBlobWriteMetaTx req;
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobWrite);
- req->crc = 0;
- req->sessionId = 0x54;
- req->offset = 0x100;
+ req.crc = 0;
+ req.sessionId = 0x54;
+ req.offset = 0x100;
- uint8_t expectedBytes[2] = {0x66, 0x67};
- std::memcpy(req + 1, &expectedBytes[0], sizeof(expectedBytes));
+ request.resize(sizeof(struct BmcBlobWriteMetaTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobWriteMetaTx));
- dataLen = sizeof(struct BmcBlobWriteMetaTx) + sizeof(expectedBytes);
+ std::array<uint8_t, 2> expectedBytes = {0x66, 0x67};
+ request.insert(request.end(), expectedBytes.begin(), expectedBytes.end());
- EXPECT_CALL(
- mgr, writeMeta(req->sessionId, req->offset,
- ElementsAreArray(expectedBytes, sizeof(expectedBytes))))
+ EXPECT_CALL(mgr, writeMeta(req.sessionId, req.offset,
+ ElementsAreArray(expectedBytes)))
.WillOnce(Return(true));
- EXPECT_EQ(IPMI_CC_OK, writeMeta(&mgr, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseSuccess(std::vector<uint8_t>{}),
+ writeMeta(&mgr, request));
}
} // namespace blobs
diff --git a/test/meson.build b/test/meson.build
index db240b3..b5bdd99 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -37,6 +37,7 @@
executable(
t.underscorify(),
t + '.cpp',
+ 'helper.cpp',
implicit_include_directories: false,
dependencies: [blob_manager_dep, gtest, gmock]))
endforeach
diff --git a/test/process_unittest.cpp b/test/process_unittest.cpp
index b72fe9a..02014d4 100644
--- a/test/process_unittest.cpp
+++ b/test/process_unittest.cpp
@@ -1,9 +1,11 @@
+#include "helper.hpp"
#include "ipmi.hpp"
#include "manager_mock.hpp"
#include "process.hpp"
#include <cstring>
#include <ipmiblob/test/crc_mock.hpp>
+#include <span>
#include <gtest/gtest.h>
@@ -12,6 +14,7 @@
#define MAX_IPMI_BUFFER 64
using ::testing::_;
+using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::Return;
using ::testing::StrictMock;
@@ -36,15 +39,11 @@
EXPECT_FALSE(lhs == nullptr);
EXPECT_FALSE(rhs == nullptr);
- ipmi_ret_t (*const* lPtr)(ManagerInterface*, const uint8_t*, uint8_t*,
- size_t*) =
- lhs.target<ipmi_ret_t (*)(ManagerInterface*, const uint8_t*, uint8_t*,
- size_t*)>();
+ Resp (*const* lPtr)(ManagerInterface*, std::span<const uint8_t>) =
+ lhs.target<Resp (*)(ManagerInterface*, std::span<const uint8_t>)>();
- ipmi_ret_t (*const* rPtr)(ManagerInterface*, const uint8_t*, uint8_t*,
- size_t*) =
- rhs.target<ipmi_ret_t (*)(ManagerInterface*, const uint8_t*, uint8_t*,
- size_t*)>();
+ Resp (*const* rPtr)(ManagerInterface*, std::span<const uint8_t>) =
+ rhs.target<Resp (*)(ManagerInterface*, std::span<const uint8_t>)>();
EXPECT_TRUE(lPtr);
EXPECT_TRUE(rPtr);
@@ -67,34 +66,20 @@
TEST_F(ValidateBlobCommandTest, InvalidCommandReturnsFailure)
{
// Verify we handle an invalid command.
-
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
-
- request[0] = 0xff; // There is no command 0xff.
- dataLen = sizeof(uint8_t); // There is no payload for CRC.
- ipmi_ret_t rc;
-
- EXPECT_EQ(nullptr, validateBlobCommand(request, reply, &dataLen, &rc));
- EXPECT_EQ(IPMI_CC_INVALID_FIELD_REQUEST, rc);
+ std::vector<uint8_t> request(MAX_IPMI_BUFFER - 1);
+ // There is no command 0xff.
+ IpmiBlobHandler handler = validateBlobCommand(0xff, request);
+ EXPECT_EQ(ipmi::responseInvalidFieldRequest(), handler(nullptr, {}));
}
TEST_F(ValidateBlobCommandTest, ValidCommandWithoutPayload)
{
// Verify we handle a valid command that doesn't have a payload.
-
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
-
- request[0] = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobGetCount);
- dataLen = sizeof(uint8_t); // There is no payload for CRC.
- ipmi_ret_t rc;
-
- IpmiBlobHandler res = validateBlobCommand(request, reply, &dataLen, &rc);
- EXPECT_FALSE(res == nullptr);
- EqualFunctions(getBlobCount, res);
+ std::vector<uint8_t> request(MAX_IPMI_BUFFER - 1);
+ IpmiBlobHandler handler = validateBlobCommand(
+ static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobGetCount), request);
+ EXPECT_FALSE(handler == nullptr);
+ EqualFunctions(getBlobCount, handler);
}
TEST_F(ValidateBlobCommandTest, WithPayloadMinimumLengthIs3VerifyChecks)
@@ -102,76 +87,61 @@
// Verify that if there's a payload, it's at least one command byte and
// two bytes for the crc16 and then one data byte.
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
-
- request[0] = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobGetCount);
- dataLen = sizeof(uint8_t) + sizeof(uint16_t);
+ std::vector<uint8_t> request(sizeof(uint16_t));
// There is a payload, but there are insufficient bytes.
- ipmi_ret_t rc;
- EXPECT_EQ(nullptr, validateBlobCommand(request, reply, &dataLen, &rc));
- EXPECT_EQ(IPMI_CC_REQ_DATA_LEN_INVALID, rc);
+ IpmiBlobHandler handler = validateBlobCommand(
+ static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobGetCount), request);
+ EXPECT_EQ(ipmi::responseReqDataLenInvalid(), handler(nullptr, {}));
}
TEST_F(ValidateBlobCommandTest, WithPayloadAndInvalidCrc)
{
// Verify that the CRC is checked, and failure is reported.
+ std::vector<uint8_t> request;
+ BmcBlobWriteTx req;
+ req.crc = 0x34;
+ req.sessionId = 0x54;
+ req.offset = 0x100;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
-
- auto req = reinterpret_cast<struct BmcBlobWriteTx*>(request);
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobWrite);
- req->crc = 0x34;
- req->sessionId = 0x54;
- req->offset = 0x100;
-
- uint8_t expectedBytes[2] = {0x66, 0x67};
- std::memcpy(req + 1, &expectedBytes[0], sizeof(expectedBytes));
-
- dataLen = sizeof(struct BmcBlobWriteTx) + sizeof(expectedBytes);
+ std::array<uint8_t, 2> expectedBytes = {0x66, 0x67};
+ request.resize(sizeof(struct BmcBlobWriteTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobWriteTx));
+ request.insert(request.end(), expectedBytes.begin(), expectedBytes.end());
// skip over cmd and crc.
- std::vector<std::uint8_t> bytes(&request[3], request + dataLen);
+ std::vector<uint8_t> bytes(request.begin() + sizeof(req.crc),
+ request.end());
EXPECT_CALL(crcMock, generateCrc(Eq(bytes))).WillOnce(Return(0x1234));
- ipmi_ret_t rc;
-
- EXPECT_EQ(nullptr, validateBlobCommand(request, reply, &dataLen, &rc));
- EXPECT_EQ(IPMI_CC_UNSPECIFIED_ERROR, rc);
+ IpmiBlobHandler handler = validateBlobCommand(
+ static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobWrite), request);
+ EXPECT_EQ(ipmi::responseUnspecifiedError(), handler(nullptr, {}));
}
TEST_F(ValidateBlobCommandTest, WithPayloadAndValidCrc)
{
// Verify the CRC is checked and if it matches, return the handler.
+ std::vector<uint8_t> request;
+ BmcBlobWriteTx req;
+ req.crc = 0x3412;
+ req.sessionId = 0x54;
+ req.offset = 0x100;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
-
- auto req = reinterpret_cast<struct BmcBlobWriteTx*>(request);
- req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobWrite);
- req->crc = 0x3412;
- req->sessionId = 0x54;
- req->offset = 0x100;
-
- uint8_t expectedBytes[2] = {0x66, 0x67};
- std::memcpy(req + 1, &expectedBytes[0], sizeof(expectedBytes));
-
- dataLen = sizeof(struct BmcBlobWriteTx) + sizeof(expectedBytes);
+ std::array<uint8_t, 2> expectedBytes = {0x66, 0x67};
+ request.resize(sizeof(struct BmcBlobWriteTx));
+ std::memcpy(request.data(), &req, sizeof(struct BmcBlobWriteTx));
+ request.insert(request.end(), expectedBytes.begin(), expectedBytes.end());
// skip over cmd and crc.
- std::vector<std::uint8_t> bytes(&request[3], request + dataLen);
+ std::vector<uint8_t> bytes(request.begin() + sizeof(req.crc),
+ request.end());
EXPECT_CALL(crcMock, generateCrc(Eq(bytes))).WillOnce(Return(0x3412));
- ipmi_ret_t rc;
-
- IpmiBlobHandler res = validateBlobCommand(request, reply, &dataLen, &rc);
- EXPECT_FALSE(res == nullptr);
- EqualFunctions(writeBlob, res);
+ IpmiBlobHandler handler = validateBlobCommand(
+ static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobWrite), request);
+ EXPECT_FALSE(handler == nullptr);
+ EqualFunctions(writeBlob, handler);
}
class ProcessBlobCommandTest : public ::testing::Test
@@ -191,17 +161,14 @@
// noticed and returned.
StrictMock<ManagerMock> manager;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
+ std::vector<uint8_t> request(MAX_IPMI_BUFFER - 1);
- IpmiBlobHandler h = [](ManagerInterface*, const uint8_t*, uint8_t*,
- size_t*) { return IPMI_CC_INVALID; };
+ IpmiBlobHandler h = [](ManagerInterface*, std::span<const uint8_t>) {
+ return ipmi::responseInvalidCommand();
+ };
- dataLen = sizeof(request);
-
- EXPECT_EQ(IPMI_CC_INVALID,
- processBlobCommand(h, &manager, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseInvalidCommand(),
+ processBlobCommand(h, &manager, request));
}
TEST_F(ProcessBlobCommandTest, CommandReturnsOkWithNoPayload)
@@ -210,20 +177,14 @@
// it doesn't try to compute a CRC.
StrictMock<ManagerMock> manager;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
+ std::vector<uint8_t> request(MAX_IPMI_BUFFER - 1);
- IpmiBlobHandler h = [](ManagerInterface*, const uint8_t*, uint8_t*,
- size_t* dataLen) {
- (*dataLen) = 0;
- return IPMI_CC_OK;
+ IpmiBlobHandler h = [](ManagerInterface*, std::span<const uint8_t>) {
+ return ipmi::responseSuccess(std::vector<uint8_t>());
};
- dataLen = sizeof(request);
-
- EXPECT_EQ(IPMI_CC_OK,
- processBlobCommand(h, &manager, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseSuccess(std::vector<uint8_t>()),
+ processBlobCommand(h, &manager, request));
}
TEST_F(ProcessBlobCommandTest, CommandReturnsOkWithInvalidPayloadLength)
@@ -232,20 +193,14 @@
// read), this returns 1.
StrictMock<ManagerMock> manager;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
+ std::vector<uint8_t> request(MAX_IPMI_BUFFER - 1);
- IpmiBlobHandler h = [](ManagerInterface*, const uint8_t*, uint8_t*,
- size_t* dataLen) {
- (*dataLen) = sizeof(uint8_t);
- return IPMI_CC_OK;
+ IpmiBlobHandler h = [](ManagerInterface*, std::span<const uint8_t>) {
+ return ipmi::responseSuccess(std::vector<uint8_t>(1));
};
- dataLen = sizeof(request);
-
- EXPECT_EQ(IPMI_CC_UNSPECIFIED_ERROR,
- processBlobCommand(h, &manager, request, reply, &dataLen));
+ EXPECT_EQ(ipmi::responseUnspecifiedError(),
+ processBlobCommand(h, &manager, request));
}
TEST_F(ProcessBlobCommandTest, CommandReturnsOkWithValidPayloadLength)
@@ -254,27 +209,22 @@
// payload of 3 bytes and the crc code is called to process the payload.
StrictMock<ManagerMock> manager;
- size_t dataLen;
- uint8_t request[MAX_IPMI_BUFFER] = {0};
- uint8_t reply[MAX_IPMI_BUFFER] = {0};
+ std::vector<uint8_t> request(MAX_IPMI_BUFFER - 1);
uint32_t payloadLen = sizeof(uint16_t) + sizeof(uint8_t);
- IpmiBlobHandler h = [payloadLen](ManagerInterface*, const uint8_t*,
- uint8_t* replyCmdBuf, size_t* dataLen) {
- (*dataLen) = payloadLen;
- replyCmdBuf[2] = 0x56;
- return IPMI_CC_OK;
+ IpmiBlobHandler h = [payloadLen](ManagerInterface*,
+ std::span<const uint8_t>) {
+ std::vector<uint8_t> output(payloadLen, 0);
+ output[2] = 0x56;
+ return ipmi::responseSuccess(output);
};
- dataLen = sizeof(request);
-
EXPECT_CALL(crcMock, generateCrc(_)).WillOnce(Return(0x3412));
- EXPECT_EQ(IPMI_CC_OK,
- processBlobCommand(h, &manager, request, reply, &dataLen));
- EXPECT_EQ(dataLen, payloadLen);
+ auto result = validateReply(processBlobCommand(h, &manager, request));
- uint8_t expectedBytes[3] = {0x12, 0x34, 0x56};
- EXPECT_EQ(0, std::memcmp(expectedBytes, reply, sizeof(expectedBytes)));
+ EXPECT_EQ(result.size(), payloadLen);
+ EXPECT_THAT(result, ElementsAre(0x12, 0x34, 0x56));
}
+
} // namespace blobs