blob: f17398574418a82f955b7bae8a1b823dd0444e92 [file] [log] [blame]
Patrick Ventureef3aead2018-09-12 08:53:29 -07001#include "ipmi.hpp"
Patrick Venturecd8dab42019-01-15 19:57:38 -08002#include "manager_mock.hpp"
Patrick Ventureef3aead2018-09-12 08:53:29 -07003
Patrick Ventureef3aead2018-09-12 08:53:29 -07004#include <cstring>
5#include <string>
6
7#include <gtest/gtest.h>
8
9namespace blobs
10{
11
12using ::testing::_;
13using ::testing::Invoke;
14using ::testing::Matcher;
15using ::testing::NotNull;
16using ::testing::Return;
17using ::testing::StrEq;
18
19// ipmid.hpp isn't installed where we can grab it and this value is per BMC
20// SoC.
21#define MAX_IPMI_BUFFER 64
22
23TEST(BlobStatTest, InvalidRequestLengthReturnsFailure)
24{
25 // There is a minimum blobId length of one character, this test verifies
26 // we check that.
27
28 ManagerMock mgr;
29 size_t dataLen;
30 uint8_t request[MAX_IPMI_BUFFER] = {0};
31 uint8_t reply[MAX_IPMI_BUFFER] = {0};
32 auto req = reinterpret_cast<struct BmcBlobStatTx*>(request);
33 std::string blobId = "abc";
34
Patrick Venture00d5f0d2019-05-17 19:21:35 -070035 req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobStat);
Patrick Ventureef3aead2018-09-12 08:53:29 -070036 req->crc = 0;
37 // length() doesn't include the nul-terminator.
38 std::memcpy(req->blobId, blobId.c_str(), blobId.length());
39
40 dataLen = sizeof(struct BmcBlobStatTx) + blobId.length();
41
Patrick Venture41258802018-11-12 10:46:30 -080042 EXPECT_EQ(IPMI_CC_REQ_DATA_LEN_INVALID,
43 statBlob(&mgr, request, reply, &dataLen));
Patrick Ventureef3aead2018-09-12 08:53:29 -070044}
45
46TEST(BlobStatTest, RequestRejectedReturnsFailure)
47{
48 // The blobId is rejected for any reason.
49
50 ManagerMock mgr;
51 size_t dataLen;
52 uint8_t request[MAX_IPMI_BUFFER] = {0};
53 uint8_t reply[MAX_IPMI_BUFFER] = {0};
54 auto req = reinterpret_cast<struct BmcBlobStatTx*>(request);
55 std::string blobId = "a";
56
Patrick Venture00d5f0d2019-05-17 19:21:35 -070057 req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobStat);
Patrick Ventureef3aead2018-09-12 08:53:29 -070058 req->crc = 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 BmcBlobStatTx) + blobId.length() + 1;
64
65 EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)),
Patrick Venture8bc11772019-06-04 07:20:24 -070066 Matcher<BlobMeta*>(_)))
Patrick Ventureef3aead2018-09-12 08:53:29 -070067 .WillOnce(Return(false));
68
Patrick Venture41258802018-11-12 10:46:30 -080069 EXPECT_EQ(IPMI_CC_UNSPECIFIED_ERROR,
70 statBlob(&mgr, request, reply, &dataLen));
Patrick Ventureef3aead2018-09-12 08:53:29 -070071}
72
73TEST(BlobStatTest, RequestSucceedsNoMetadata)
74{
75 // Stat request succeeeds but there were no metadata bytes.
76
77 ManagerMock mgr;
78 size_t dataLen;
79 uint8_t request[MAX_IPMI_BUFFER] = {0};
80 uint8_t reply[MAX_IPMI_BUFFER] = {0};
81 auto req = reinterpret_cast<struct BmcBlobStatTx*>(request);
82 std::string blobId = "a";
83
Patrick Venture00d5f0d2019-05-17 19:21:35 -070084 req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobStat);
Patrick Ventureef3aead2018-09-12 08:53:29 -070085 req->crc = 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 BmcBlobStatTx) + blobId.length() + 1;
91
92 struct BmcBlobStatRx rep;
93 rep.crc = 0x00;
94 rep.blobState = 0x01;
95 rep.size = 0x100;
96 rep.metadataLen = 0x00;
97
Patrick Ventureb6ed5622020-09-28 13:17:14 -070098 uint16_t blobState = rep.blobState;
99 uint32_t size = rep.size;
100
Patrick Ventureef3aead2018-09-12 08:53:29 -0700101 EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)),
Patrick Venture8bc11772019-06-04 07:20:24 -0700102 Matcher<BlobMeta*>(NotNull())))
103 .WillOnce(Invoke([&](const std::string& path, BlobMeta* meta) {
Patrick Ventureb6ed5622020-09-28 13:17:14 -0700104 meta->blobState = blobState;
105 meta->size = size;
Patrick Ventureef3aead2018-09-12 08:53:29 -0700106 return true;
107 }));
108
109 EXPECT_EQ(IPMI_CC_OK, statBlob(&mgr, request, reply, &dataLen));
110
111 EXPECT_EQ(sizeof(rep), dataLen);
112 EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep)));
113}
114
115TEST(BlobStatTest, RequestSucceedsWithMetadata)
116{
117 // Stat request succeeds and there were metadata bytes.
118
119 ManagerMock mgr;
120 size_t dataLen;
121 uint8_t request[MAX_IPMI_BUFFER] = {0};
122 uint8_t reply[MAX_IPMI_BUFFER] = {0};
123 auto req = reinterpret_cast<struct BmcBlobStatTx*>(request);
124 std::string blobId = "a";
125
Patrick Venture00d5f0d2019-05-17 19:21:35 -0700126 req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobStat);
Patrick Ventureef3aead2018-09-12 08:53:29 -0700127 req->crc = 0;
128 // length() doesn't include the nul-terminator, request buff is initialized
129 // to 0s
130 std::memcpy(req->blobId, blobId.c_str(), blobId.length());
131
132 dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1;
133
Patrick Venture8bc11772019-06-04 07:20:24 -0700134 BlobMeta lmeta;
Patrick Ventureef3aead2018-09-12 08:53:29 -0700135 lmeta.blobState = 0x01;
136 lmeta.size = 0x100;
137 lmeta.metadata.push_back(0x01);
138 lmeta.metadata.push_back(0x02);
139 lmeta.metadata.push_back(0x03);
140 lmeta.metadata.push_back(0x04);
141
142 struct BmcBlobStatRx rep;
143 rep.crc = 0x00;
144 rep.blobState = lmeta.blobState;
145 rep.size = lmeta.size;
146 rep.metadataLen = lmeta.metadata.size();
147
148 EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)),
Patrick Venture8bc11772019-06-04 07:20:24 -0700149 Matcher<BlobMeta*>(NotNull())))
150 .WillOnce(Invoke([&](const std::string& path, BlobMeta* meta) {
Patrick Ventureef3aead2018-09-12 08:53:29 -0700151 (*meta) = lmeta;
152 return true;
153 }));
154
155 EXPECT_EQ(IPMI_CC_OK, statBlob(&mgr, request, reply, &dataLen));
156
157 EXPECT_EQ(sizeof(rep) + lmeta.metadata.size(), dataLen);
158 EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep)));
159 EXPECT_EQ(0, std::memcmp(reply + sizeof(rep), lmeta.metadata.data(),
160 lmeta.metadata.size()));
161}
162} // namespace blobs