1 #include "ipmi.hpp"
2 
3 #include <blobs-ipmid/test/manager_mock.hpp>
4 #include <cstring>
5 
6 #include <gtest/gtest.h>
7 
8 namespace blobs
9 {
10 
11 using ::testing::_;
12 using ::testing::ElementsAreArray;
13 using ::testing::Return;
14 
15 // ipmid.hpp isn't installed where we can grab it and this value is per BMC
16 // SoC.
17 #define MAX_IPMI_BUFFER 64
18 
19 TEST(BlobCommitTest, InvalidCommitDataLengthReturnsFailure)
20 {
21     // The commit command supports an optional commit blob.  This test verifies
22     // we sanity check the length of that blob.
23 
24     ManagerMock mgr;
25     size_t dataLen;
26     uint8_t request[MAX_IPMI_BUFFER] = {0};
27     uint8_t reply[MAX_IPMI_BUFFER] = {0};
28     auto req = reinterpret_cast<struct BmcBlobCommitTx*>(request);
29 
30     req->cmd = BlobOEMCommands::bmcBlobCommit;
31     req->crc = 0;
32     req->sessionId = 0x54;
33     req->commitDataLen =
34         1; // It's one byte, but that's more than the packet size.
35 
36     dataLen = sizeof(struct BmcBlobCommitTx);
37 
38     EXPECT_EQ(IPMI_CC_INVALID, commitBlob(&mgr, request, reply, &dataLen));
39 }
40 
41 TEST(BlobCommitTest, ValidCommitNoDataHandlerRejectsReturnsFailure)
42 {
43     // The commit packet is valid and the manager's commit call returns failure.
44 
45     ManagerMock mgr;
46     size_t dataLen;
47     uint8_t request[MAX_IPMI_BUFFER] = {0};
48     uint8_t reply[MAX_IPMI_BUFFER] = {0};
49     auto req = reinterpret_cast<struct BmcBlobCommitTx*>(request);
50 
51     req->cmd = BlobOEMCommands::bmcBlobCommit;
52     req->crc = 0;
53     req->sessionId = 0x54;
54     req->commitDataLen = 0;
55 
56     dataLen = sizeof(struct BmcBlobCommitTx);
57 
58     EXPECT_CALL(mgr, commit(req->sessionId, _)).WillOnce(Return(false));
59 
60     EXPECT_EQ(IPMI_CC_INVALID, commitBlob(&mgr, request, reply, &dataLen));
61 }
62 
63 TEST(BlobCommitTest, ValidCommitNoDataHandlerAcceptsReturnsSuccess)
64 {
65     // Commit called with no data and everything returns success.
66 
67     ManagerMock mgr;
68     size_t dataLen;
69     uint8_t request[MAX_IPMI_BUFFER] = {0};
70     uint8_t reply[MAX_IPMI_BUFFER] = {0};
71     auto req = reinterpret_cast<struct BmcBlobCommitTx*>(request);
72 
73     req->cmd = BlobOEMCommands::bmcBlobCommit;
74     req->crc = 0;
75     req->sessionId = 0x54;
76     req->commitDataLen = 0;
77 
78     dataLen = sizeof(struct BmcBlobCommitTx);
79 
80     EXPECT_CALL(mgr, commit(req->sessionId, _)).WillOnce(Return(true));
81 
82     EXPECT_EQ(IPMI_CC_OK, commitBlob(&mgr, request, reply, &dataLen));
83 }
84 
85 TEST(BlobCommitTest, ValidCommitWithDataHandlerAcceptsReturnsSuccess)
86 {
87     // Commit called with extra data and everything returns success.
88 
89     ManagerMock mgr;
90     size_t dataLen;
91     uint8_t request[MAX_IPMI_BUFFER] = {0};
92     uint8_t reply[MAX_IPMI_BUFFER] = {0};
93     auto req = reinterpret_cast<struct BmcBlobCommitTx*>(request);
94 
95     uint8_t expectedBlob[4] = {0x25, 0x33, 0x45, 0x67};
96 
97     req->cmd = BlobOEMCommands::bmcBlobCommit;
98     req->crc = 0;
99     req->sessionId = 0x54;
100     req->commitDataLen = sizeof(expectedBlob);
101     std::memcpy(req->commitData, &expectedBlob[0], sizeof(expectedBlob));
102 
103     dataLen = sizeof(struct BmcBlobCommitTx) + sizeof(expectedBlob);
104 
105     EXPECT_CALL(mgr,
106                 commit(req->sessionId,
107                        ElementsAreArray(expectedBlob, sizeof(expectedBlob))))
108         .WillOnce(Return(true));
109 
110     EXPECT_EQ(IPMI_CC_OK, commitBlob(&mgr, request, reply, &dataLen));
111 }
112 } // namespace blobs
113