1 #include "helper.hpp"
2 #include "ipmi.hpp"
3 #include "manager_mock.hpp"
4 
5 #include <cstring>
6 #include <string>
7 
8 #include <gtest/gtest.h>
9 
10 namespace blobs
11 {
12 
13 using ::testing::_;
14 using ::testing::Invoke;
15 using ::testing::Matcher;
16 using ::testing::NotNull;
17 using ::testing::Return;
18 using ::testing::StrEq;
19 
20 // ipmid.hpp isn't installed where we can grab it and this value is per BMC
21 // SoC.
22 #define MAX_IPMI_BUFFER 64
23 
24 TEST(BlobStatTest, InvalidRequestLengthReturnsFailure)
25 {
26     // There is a minimum blobId length of one character, this test verifies
27     // we check that.
28     ManagerMock mgr;
29     std::vector<uint8_t> request;
30     struct BmcBlobStatTx req;
31     std::string blobId = "abc";
32 
33     req.crc = 0;
34     request.resize(sizeof(struct BmcBlobStatTx));
35     std::memcpy(request.data(), &req, sizeof(struct BmcBlobStatTx));
36     // Do not include the nul-terminator
37     request.insert(request.end(), blobId.begin(), blobId.end());
38 
39     EXPECT_EQ(ipmi::responseReqDataLenInvalid(), statBlob(&mgr, request));
40 }
41 
42 TEST(BlobStatTest, RequestRejectedReturnsFailure)
43 {
44     // The blobId is rejected for any reason.
45 
46     ManagerMock mgr;
47     std::vector<uint8_t> request;
48     struct BmcBlobStatTx req;
49     std::string blobId = "a";
50 
51     req.crc = 0;
52     request.resize(sizeof(struct BmcBlobStatTx));
53     std::memcpy(request.data(), &req, sizeof(struct BmcBlobStatTx));
54     request.insert(request.end(), blobId.begin(), blobId.end());
55     request.emplace_back('\0');
56 
57     EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)),
58                           Matcher<BlobMeta*>(_)))
59         .WillOnce(Return(false));
60 
61     EXPECT_EQ(ipmi::responseUnspecifiedError(), statBlob(&mgr, request));
62 }
63 
64 TEST(BlobStatTest, RequestSucceedsNoMetadata)
65 {
66     // Stat request succeeeds but there were no metadata bytes.
67 
68     ManagerMock mgr;
69     std::vector<uint8_t> request;
70     struct BmcBlobStatTx req;
71     std::string blobId = "a";
72 
73     req.crc = 0;
74     request.resize(sizeof(struct BmcBlobStatTx));
75     std::memcpy(request.data(), &req, sizeof(struct BmcBlobStatTx));
76     request.insert(request.end(), blobId.begin(), blobId.end());
77     request.emplace_back('\0');
78 
79     struct BmcBlobStatRx rep;
80     rep.crc = 0x00;
81     rep.blobState = 0x01;
82     rep.size = 0x100;
83     rep.metadataLen = 0x00;
84 
85     uint16_t blobState = rep.blobState;
86     uint32_t size = rep.size;
87 
88     EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)),
89                           Matcher<BlobMeta*>(NotNull())))
90         .WillOnce(Invoke([&](const std::string&, BlobMeta* meta) {
91             meta->blobState = blobState;
92             meta->size = size;
93             return true;
94         }));
95 
96     auto result = validateReply(statBlob(&mgr, request));
97 
98     EXPECT_EQ(sizeof(rep), result.size());
99     EXPECT_EQ(0, std::memcmp(result.data(), &rep, sizeof(rep)));
100 }
101 
102 TEST(BlobStatTest, RequestSucceedsWithMetadata)
103 {
104     // Stat request succeeds and there were metadata bytes.
105 
106     ManagerMock mgr;
107     std::vector<uint8_t> request;
108     struct BmcBlobStatTx req;
109     std::string blobId = "a";
110 
111     req.crc = 0;
112     request.resize(sizeof(struct BmcBlobStatTx));
113     std::memcpy(request.data(), &req, sizeof(struct BmcBlobStatTx));
114     request.insert(request.end(), blobId.begin(), blobId.end());
115     request.emplace_back('\0');
116 
117     BlobMeta lmeta;
118     lmeta.blobState = 0x01;
119     lmeta.size = 0x100;
120     lmeta.metadata.push_back(0x01);
121     lmeta.metadata.push_back(0x02);
122     lmeta.metadata.push_back(0x03);
123     lmeta.metadata.push_back(0x04);
124 
125     struct BmcBlobStatRx rep;
126     rep.crc = 0x00;
127     rep.blobState = lmeta.blobState;
128     rep.size = lmeta.size;
129     rep.metadataLen = lmeta.metadata.size();
130 
131     EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)),
132                           Matcher<BlobMeta*>(NotNull())))
133         .WillOnce(Invoke([&](const std::string&, BlobMeta* meta) {
134             (*meta) = lmeta;
135             return true;
136         }));
137 
138     auto result = validateReply(statBlob(&mgr, request));
139 
140     EXPECT_EQ(sizeof(rep) + lmeta.metadata.size(), result.size());
141     EXPECT_EQ(0, std::memcmp(result.data(), &rep, sizeof(rep)));
142     EXPECT_EQ(0, std::memcmp(result.data() + sizeof(rep), lmeta.metadata.data(),
143                              lmeta.metadata.size()));
144 }
145 } // namespace blobs
146