1 #include "ipmi.hpp"
2 #include "manager_mock.hpp"
3 
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_REQ_DATA_LEN_INVALID,
39               commitBlob(&mgr, request, reply, &dataLen));
40 }
41 
42 TEST(BlobCommitTest, ValidCommitNoDataHandlerRejectsReturnsFailure)
43 {
44     // The commit packet is valid and the manager's commit call returns failure.
45 
46     ManagerMock mgr;
47     size_t dataLen;
48     uint8_t request[MAX_IPMI_BUFFER] = {0};
49     uint8_t reply[MAX_IPMI_BUFFER] = {0};
50     auto req = reinterpret_cast<struct BmcBlobCommitTx*>(request);
51 
52     req->cmd = BlobOEMCommands::bmcBlobCommit;
53     req->crc = 0;
54     req->sessionId = 0x54;
55     req->commitDataLen = 0;
56 
57     dataLen = sizeof(struct BmcBlobCommitTx);
58 
59     EXPECT_CALL(mgr, commit(req->sessionId, _)).WillOnce(Return(false));
60 
61     EXPECT_EQ(IPMI_CC_UNSPECIFIED_ERROR,
62               commitBlob(&mgr, request, reply, &dataLen));
63 }
64 
65 TEST(BlobCommitTest, ValidCommitNoDataHandlerAcceptsReturnsSuccess)
66 {
67     // Commit called with no data and everything returns success.
68 
69     ManagerMock mgr;
70     size_t dataLen;
71     uint8_t request[MAX_IPMI_BUFFER] = {0};
72     uint8_t reply[MAX_IPMI_BUFFER] = {0};
73     auto req = reinterpret_cast<struct BmcBlobCommitTx*>(request);
74 
75     req->cmd = BlobOEMCommands::bmcBlobCommit;
76     req->crc = 0;
77     req->sessionId = 0x54;
78     req->commitDataLen = 0;
79 
80     dataLen = sizeof(struct BmcBlobCommitTx);
81 
82     EXPECT_CALL(mgr, commit(req->sessionId, _)).WillOnce(Return(true));
83 
84     EXPECT_EQ(IPMI_CC_OK, commitBlob(&mgr, request, reply, &dataLen));
85 }
86 
87 TEST(BlobCommitTest, ValidCommitWithDataHandlerAcceptsReturnsSuccess)
88 {
89     // Commit called with extra data and everything returns success.
90 
91     ManagerMock mgr;
92     size_t dataLen;
93     uint8_t request[MAX_IPMI_BUFFER] = {0};
94     uint8_t reply[MAX_IPMI_BUFFER] = {0};
95     auto req = reinterpret_cast<struct BmcBlobCommitTx*>(request);
96 
97     uint8_t expectedBlob[4] = {0x25, 0x33, 0x45, 0x67};
98 
99     req->cmd = BlobOEMCommands::bmcBlobCommit;
100     req->crc = 0;
101     req->sessionId = 0x54;
102     req->commitDataLen = sizeof(expectedBlob);
103     std::memcpy(req->commitData, &expectedBlob[0], sizeof(expectedBlob));
104 
105     dataLen = sizeof(struct BmcBlobCommitTx) + sizeof(expectedBlob);
106 
107     EXPECT_CALL(mgr,
108                 commit(req->sessionId,
109                        ElementsAreArray(expectedBlob, sizeof(expectedBlob))))
110         .WillOnce(Return(true));
111 
112     EXPECT_EQ(IPMI_CC_OK, commitBlob(&mgr, request, reply, &dataLen));
113 }
114 } // namespace blobs
115