1 #include "ipmi.hpp"
2 #include "manager_mock.hpp"
3 
4 #include <cstring>
5 #include <string>
6 
7 #include <gtest/gtest.h>
8 
9 namespace blobs
10 {
11 
12 using ::testing::_;
13 using ::testing::Invoke;
14 using ::testing::NotNull;
15 using ::testing::Return;
16 using ::testing::StrEq;
17 
18 // ipmid.hpp isn't installed where we can grab it and this value is per BMC
19 // SoC.
20 #define MAX_IPMI_BUFFER 64
21 
22 TEST(BlobOpenTest, InvalidRequestLengthReturnsFailure)
23 {
24     // There is a minimum blobId length of one character, this test verifies
25     // we check that.
26 
27     ManagerMock mgr;
28     size_t dataLen;
29     uint8_t request[MAX_IPMI_BUFFER] = {0};
30     uint8_t reply[MAX_IPMI_BUFFER] = {0};
31     auto req = reinterpret_cast<struct BmcBlobOpenTx*>(request);
32     std::string blobId = "abc";
33 
34     req->cmd = BlobOEMCommands::bmcBlobOpen;
35     req->crc = 0;
36     req->flags = 0;
37     // length() doesn't include the nul-terminator.
38     std::memcpy(req->blobId, blobId.c_str(), blobId.length());
39 
40     dataLen = sizeof(struct BmcBlobOpenTx) + blobId.length();
41 
42     EXPECT_EQ(IPMI_CC_INVALID, openBlob(&mgr, request, reply, &dataLen));
43 }
44 
45 TEST(BlobOpenTest, RequestRejectedReturnsFailure)
46 {
47     // The blobId is rejected for any reason.
48 
49     ManagerMock mgr;
50     size_t dataLen;
51     uint8_t request[MAX_IPMI_BUFFER] = {0};
52     uint8_t reply[MAX_IPMI_BUFFER] = {0};
53     auto req = reinterpret_cast<struct BmcBlobOpenTx*>(request);
54     std::string blobId = "a";
55 
56     req->cmd = BlobOEMCommands::bmcBlobOpen;
57     req->crc = 0;
58     req->flags = 0;
59     // length() doesn't include the nul-terminator, request buff is initialized
60     // to 0s
61     std::memcpy(req->blobId, blobId.c_str(), blobId.length());
62 
63     dataLen = sizeof(struct BmcBlobOpenTx) + blobId.length() + 1;
64 
65     EXPECT_CALL(mgr, open(req->flags, StrEq(blobId), _))
66         .WillOnce(Return(false));
67 
68     EXPECT_EQ(IPMI_CC_INVALID, openBlob(&mgr, request, reply, &dataLen));
69 }
70 
71 TEST(BlobOpenTest, BlobOpenReturnsOk)
72 {
73     // The boring case where the blobId opens.
74 
75     ManagerMock mgr;
76     size_t dataLen;
77     uint8_t request[MAX_IPMI_BUFFER] = {0};
78     uint8_t reply[MAX_IPMI_BUFFER] = {0};
79     auto req = reinterpret_cast<struct BmcBlobOpenTx*>(request);
80     struct BmcBlobOpenRx rep;
81     std::string blobId = "a";
82 
83     req->cmd = BlobOEMCommands::bmcBlobOpen;
84     req->crc = 0;
85     req->flags = 0;
86     // length() doesn't include the nul-terminator, request buff is initialized
87     // to 0s
88     std::memcpy(req->blobId, blobId.c_str(), blobId.length());
89 
90     dataLen = sizeof(struct BmcBlobOpenTx) + blobId.length() + 1;
91     uint16_t returnedSession = 0x54;
92 
93     EXPECT_CALL(mgr, open(req->flags, StrEq(blobId), NotNull()))
94         .WillOnce(Invoke(
95             [&](uint16_t flags, const std::string& path, uint16_t* session) {
96                 (*session) = returnedSession;
97                 return true;
98             }));
99 
100     EXPECT_EQ(IPMI_CC_OK, openBlob(&mgr, request, reply, &dataLen));
101 
102     rep.crc = 0;
103     rep.sessionId = returnedSession;
104 
105     EXPECT_EQ(sizeof(rep), dataLen);
106     EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep)));
107 }
108 } // namespace blobs
109