blob: a6f1dfe302fa0ded7cc6ed50be43d84b160a6f36 [file] [log] [blame]
Patrick Ventureef3aead2018-09-12 08:53:29 -07001#include "ipmi.hpp"
2#include "manager_mock.hpp"
3
4#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
35 req->cmd = BlobOEMCommands::bmcBlobStat;
36 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
42 EXPECT_EQ(IPMI_CC_INVALID, statBlob(&mgr, request, reply, &dataLen));
43}
44
45TEST(BlobStatTest, 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 BmcBlobStatTx*>(request);
54 std::string blobId = "a";
55
56 req->cmd = BlobOEMCommands::bmcBlobStat;
57 req->crc = 0;
58 // length() doesn't include the nul-terminator, request buff is initialized
59 // to 0s
60 std::memcpy(req->blobId, blobId.c_str(), blobId.length());
61
62 dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1;
63
64 EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)),
65 Matcher<struct BlobMeta*>(_)))
66 .WillOnce(Return(false));
67
68 EXPECT_EQ(IPMI_CC_INVALID, statBlob(&mgr, request, reply, &dataLen));
69}
70
71TEST(BlobStatTest, RequestSucceedsNoMetadata)
72{
73 // Stat request succeeeds but there were no metadata bytes.
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 BmcBlobStatTx*>(request);
80 std::string blobId = "a";
81
82 req->cmd = BlobOEMCommands::bmcBlobStat;
83 req->crc = 0;
84 // length() doesn't include the nul-terminator, request buff is initialized
85 // to 0s
86 std::memcpy(req->blobId, blobId.c_str(), blobId.length());
87
88 dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1;
89
90 struct BmcBlobStatRx rep;
91 rep.crc = 0x00;
92 rep.blobState = 0x01;
93 rep.size = 0x100;
94 rep.metadataLen = 0x00;
95
96 EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)),
97 Matcher<struct BlobMeta*>(NotNull())))
98 .WillOnce(Invoke([&](const std::string& path, struct BlobMeta* meta) {
99 meta->blobState = rep.blobState;
100 meta->size = rep.size;
101 return true;
102 }));
103
104 EXPECT_EQ(IPMI_CC_OK, statBlob(&mgr, request, reply, &dataLen));
105
106 EXPECT_EQ(sizeof(rep), dataLen);
107 EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep)));
108}
109
110TEST(BlobStatTest, RequestSucceedsWithMetadata)
111{
112 // Stat request succeeds and there were metadata bytes.
113
114 ManagerMock mgr;
115 size_t dataLen;
116 uint8_t request[MAX_IPMI_BUFFER] = {0};
117 uint8_t reply[MAX_IPMI_BUFFER] = {0};
118 auto req = reinterpret_cast<struct BmcBlobStatTx*>(request);
119 std::string blobId = "a";
120
121 req->cmd = BlobOEMCommands::bmcBlobStat;
122 req->crc = 0;
123 // length() doesn't include the nul-terminator, request buff is initialized
124 // to 0s
125 std::memcpy(req->blobId, blobId.c_str(), blobId.length());
126
127 dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1;
128
129 struct BlobMeta lmeta;
130 lmeta.blobState = 0x01;
131 lmeta.size = 0x100;
132 lmeta.metadata.push_back(0x01);
133 lmeta.metadata.push_back(0x02);
134 lmeta.metadata.push_back(0x03);
135 lmeta.metadata.push_back(0x04);
136
137 struct BmcBlobStatRx rep;
138 rep.crc = 0x00;
139 rep.blobState = lmeta.blobState;
140 rep.size = lmeta.size;
141 rep.metadataLen = lmeta.metadata.size();
142
143 EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)),
144 Matcher<struct BlobMeta*>(NotNull())))
145 .WillOnce(Invoke([&](const std::string& path, struct BlobMeta* meta) {
146 (*meta) = lmeta;
147 return true;
148 }));
149
150 EXPECT_EQ(IPMI_CC_OK, statBlob(&mgr, request, reply, &dataLen));
151
152 EXPECT_EQ(sizeof(rep) + lmeta.metadata.size(), dataLen);
153 EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep)));
154 EXPECT_EQ(0, std::memcmp(reply + sizeof(rep), lmeta.metadata.data(),
155 lmeta.metadata.size()));
156}
157} // namespace blobs