1 #include "libpldm/base.h"
2 #include "libpldm/bios.h"
3 #include "libpldm/fru.h"
4 #include "libpldm/platform.h"
5 
6 #include "common/instance_id.hpp"
7 #include "common/types.hpp"
8 #include "mock_terminus_manager.hpp"
9 #include "platform-mc/terminus_manager.hpp"
10 #include "requester/handler.hpp"
11 #include "requester/mctp_endpoint_discovery.hpp"
12 #include "requester/request.hpp"
13 #include "test/test_instance_id.hpp"
14 
15 #include <sdbusplus/timer.hpp>
16 #include <sdeventplus/event.hpp>
17 
18 #include <gmock/gmock.h>
19 #include <gtest/gtest.h>
20 
21 using ::testing::AtLeast;
22 using ::testing::Between;
23 using ::testing::Exactly;
24 using ::testing::NiceMock;
25 using ::testing::Return;
26 
27 class TerminusManagerTest : public testing::Test
28 {
29   protected:
30     TerminusManagerTest() :
31         bus(pldm::utils::DBusHandler::getBus()),
32         event(sdeventplus::Event::get_default()), instanceIdDb(),
33         reqHandler(pldmTransport, event, instanceIdDb, false,
34                    std::chrono::seconds(1), 2, std::chrono::milliseconds(100)),
35         terminusManager(event, reqHandler, instanceIdDb, termini, nullptr,
36                         pldm::BmcMctpEid),
37         mockTerminusManager(event, reqHandler, instanceIdDb, termini, nullptr)
38     {}
39 
40     PldmTransport* pldmTransport = nullptr;
41     sdbusplus::bus_t& bus;
42     sdeventplus::Event event;
43     TestInstanceIdDb instanceIdDb;
44     pldm::requester::Handler<pldm::requester::Request> reqHandler;
45     pldm::platform_mc::TerminusManager terminusManager;
46     pldm::platform_mc::MockTerminusManager mockTerminusManager;
47     std::map<pldm_tid_t, std::shared_ptr<pldm::platform_mc::Terminus>> termini;
48 };
49 
50 TEST_F(TerminusManagerTest, mapTidTest)
51 {
52     pldm::MctpInfo mctpInfo1(8, "", "", 0);
53 
54     auto mappedTid1 = terminusManager.mapTid(mctpInfo1);
55     EXPECT_NE(mappedTid1, std::nullopt);
56 
57     auto tid1 = terminusManager.toTid(mctpInfo1);
58     EXPECT_NE(tid1, std::nullopt);
59 
60     auto mctpInfo2 = terminusManager.toMctpInfo(tid1.value());
61     EXPECT_EQ(mctpInfo1, mctpInfo2.value());
62 
63     auto ret = terminusManager.unmapTid(tid1.value());
64     EXPECT_EQ(ret, true);
65 
66     tid1 = terminusManager.toTid(mctpInfo1);
67     EXPECT_EQ(tid1, std::nullopt);
68 }
69 
70 TEST_F(TerminusManagerTest, negativeMapTidTest)
71 {
72     // map null EID(0) to TID
73     pldm::MctpInfo m0(0, "", "", 0);
74     auto mappedTid = terminusManager.mapTid(m0);
75     EXPECT_EQ(mappedTid, std::nullopt);
76 
77     // map broadcast EID(0xff) to TID
78     pldm::MctpInfo m1(0xff, "", "", 0);
79     mappedTid = terminusManager.mapTid(m1);
80     EXPECT_EQ(mappedTid, std::nullopt);
81 
82     // map EID to tid which has been assigned
83     pldm::MctpInfo m2(9, "", "", 1);
84     pldm::MctpInfo m3(10, "", "", 1);
85     auto mappedTid2 = terminusManager.mapTid(m2);
86     auto mappedTid3 = terminusManager.storeTerminusInfo(m3, mappedTid2.value());
87     EXPECT_NE(mappedTid2, std::nullopt);
88     EXPECT_EQ(mappedTid3, std::nullopt);
89 
90     // map two mctpInfo with same EID but different network Id
91     pldm::MctpInfo m4(12, "", "", 1);
92     pldm::MctpInfo m5(12, "", "", 2);
93     auto mappedTid4 = terminusManager.mapTid(m4);
94     auto mappedTid5 = terminusManager.mapTid(m5);
95     EXPECT_NE(mappedTid4.value(), mappedTid5.value());
96 
97     // map same mctpInfo twice
98     pldm::MctpInfo m6(12, "", "", 3);
99     auto mappedTid6 = terminusManager.mapTid(m6);
100     auto mappedTid6_1 = terminusManager.mapTid(m6);
101     EXPECT_EQ(mappedTid6.value(), mappedTid6_1.value());
102 
103     // look up an unmapped MctpInfo to TID
104     pldm::MctpInfo m7(1, "", "", 0);
105     auto mappedTid7 = terminusManager.toTid(m7);
106     EXPECT_EQ(mappedTid7, std::nullopt);
107 
108     // look up reserved TID(0)
109     auto mappedEid = terminusManager.toMctpInfo(0);
110     EXPECT_EQ(mappedEid, std::nullopt);
111 
112     // look up reserved TID(0xff)
113     mappedEid = terminusManager.toMctpInfo(0xff);
114     EXPECT_EQ(mappedEid, std::nullopt);
115 
116     // look up an unmapped TID
117     terminusManager.unmapTid(1);
118     mappedEid = terminusManager.toMctpInfo(1);
119     EXPECT_EQ(mappedEid, std::nullopt);
120 
121     // unmap reserved TID(0)
122     auto ret = terminusManager.unmapTid(0);
123     EXPECT_EQ(ret, false);
124 
125     // unmap reserved TID(0)
126     ret = terminusManager.unmapTid(0xff);
127     EXPECT_EQ(ret, false);
128 }
129 
130 TEST_F(TerminusManagerTest, discoverMctpTerminusTest)
131 {
132     const size_t getTidRespLen = PLDM_GET_TID_RESP_BYTES;
133     const size_t setTidRespLen = PLDM_SET_TID_RESP_BYTES;
134     const size_t getPldmTypesRespLen = PLDM_GET_TYPES_RESP_BYTES;
135 
136     // 0.discover a mctp list
137     auto rc = mockTerminusManager.clearQueuedResponses();
138     EXPECT_EQ(rc, PLDM_SUCCESS);
139 
140     std::array<uint8_t, sizeof(pldm_msg_hdr) + getTidRespLen> getTidResp0{
141         0x00, 0x02, 0x02, 0x00, 0x00};
142     rc = mockTerminusManager.enqueueResponse(
143         reinterpret_cast<pldm_msg*>(getTidResp0.data()), sizeof(getTidResp0));
144     EXPECT_EQ(rc, PLDM_SUCCESS);
145     std::array<uint8_t, sizeof(pldm_msg_hdr) + setTidRespLen> setTidResp0{
146         0x00, 0x02, 0x01, 0x00};
147     rc = mockTerminusManager.enqueueResponse(
148         reinterpret_cast<pldm_msg*>(setTidResp0.data()), sizeof(setTidResp0));
149     EXPECT_EQ(rc, PLDM_SUCCESS);
150     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmTypesRespLen>
151         getPldmTypesResp0{0x00, 0x02, 0x04, 0x00, 0x01, 0x00,
152                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
153     rc = mockTerminusManager.enqueueResponse(
154         reinterpret_cast<pldm_msg*>(getPldmTypesResp0.data()),
155         sizeof(getPldmTypesResp0));
156     EXPECT_EQ(rc, PLDM_SUCCESS);
157 
158     pldm::MctpInfos mctpInfos{};
159     mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1));
160     mockTerminusManager.discoverMctpTerminus(mctpInfos);
161     EXPECT_EQ(1, termini.size());
162 
163     // 1.discover the same mctp list again
164     rc = mockTerminusManager.clearQueuedResponses();
165     EXPECT_EQ(rc, PLDM_SUCCESS);
166 
167     std::array<uint8_t, sizeof(pldm_msg_hdr) + getTidRespLen> getTidResp1{
168         0x00, 0x02, 0x02, 0x00, 0x01};
169     rc = mockTerminusManager.enqueueResponse(
170         reinterpret_cast<pldm_msg*>(getTidResp1.data()), sizeof(getTidResp1));
171     EXPECT_EQ(rc, PLDM_SUCCESS);
172     rc = mockTerminusManager.enqueueResponse(
173         reinterpret_cast<pldm_msg*>(setTidResp0.data()), sizeof(setTidResp0));
174     EXPECT_EQ(rc, PLDM_SUCCESS);
175     rc = mockTerminusManager.enqueueResponse(
176         reinterpret_cast<pldm_msg*>(getPldmTypesResp0.data()),
177         sizeof(getPldmTypesResp0));
178     EXPECT_EQ(rc, PLDM_SUCCESS);
179 
180     mockTerminusManager.discoverMctpTerminus(mctpInfos);
181     EXPECT_EQ(1, termini.size());
182 
183     // 2.discover an empty mctp list
184     rc = mockTerminusManager.clearQueuedResponses();
185     EXPECT_EQ(rc, PLDM_SUCCESS);
186 
187     mockTerminusManager.removeMctpTerminus(mctpInfos);
188     EXPECT_EQ(0, termini.size());
189 }
190 
191 TEST_F(TerminusManagerTest, negativeDiscoverMctpTerminusTest)
192 {
193     const size_t getTidRespLen = PLDM_GET_TID_RESP_BYTES;
194     const size_t setTidRespLen = PLDM_SET_TID_RESP_BYTES;
195     const size_t getPldmTypesRespLen = PLDM_GET_TYPES_RESP_BYTES;
196 
197     // 0.terminus returns reserved tid
198     std::array<uint8_t, sizeof(pldm_msg_hdr) + getTidRespLen> getTidResp0{
199         0x00, 0x02, 0x02, 0x00, PLDM_TID_RESERVED};
200     auto rc = mockTerminusManager.enqueueResponse(
201         reinterpret_cast<pldm_msg*>(getTidResp0.data()), sizeof(getTidResp0));
202     EXPECT_EQ(rc, PLDM_SUCCESS);
203 
204     pldm::MctpInfos mctpInfos{};
205     mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1));
206     mockTerminusManager.discoverMctpTerminus(mctpInfos);
207     EXPECT_EQ(0, termini.size());
208 
209     // 1.terminus return cc=pldm_error for set tid
210     std::array<uint8_t, sizeof(pldm_msg_hdr) + getTidRespLen> getTidResp1{
211         0x00, 0x02, 0x02, 0x00, 0x00};
212     std::array<uint8_t, sizeof(pldm_msg_hdr) + setTidRespLen> setTidResp1{
213         0x00, 0x02, 0x01, PLDM_ERROR};
214 
215     rc = mockTerminusManager.enqueueResponse(
216         reinterpret_cast<pldm_msg*>(getTidResp1.data()), sizeof(getTidResp1));
217     EXPECT_EQ(rc, PLDM_SUCCESS);
218     rc = mockTerminusManager.enqueueResponse(
219         reinterpret_cast<pldm_msg*>(setTidResp1.data()), sizeof(setTidResp1));
220     EXPECT_EQ(rc, PLDM_SUCCESS);
221     mockTerminusManager.removeMctpTerminus(mctpInfos);
222     EXPECT_EQ(0, termini.size());
223 
224     // 2.terminus return cc=unsupported_pldm_cmd for set tid cmd and return
225     // cc=pldm_error for get pldm types cmd
226     std::array<uint8_t, sizeof(pldm_msg_hdr) + getTidRespLen> getTidResp2{
227         0x00, 0x02, 0x02, 0x00, 0x00};
228     std::array<uint8_t, sizeof(pldm_msg_hdr) + setTidRespLen> setTidResp2{
229         0x00, 0x02, 0x01, PLDM_ERROR_UNSUPPORTED_PLDM_CMD};
230     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmTypesRespLen>
231         getPldmTypesResp2{0x00, 0x02, 0x04, PLDM_ERROR, 0x01, 0x00,
232                           0x00, 0x00, 0x00, 0x00,       0x00, 0x00};
233     rc = mockTerminusManager.enqueueResponse(
234         reinterpret_cast<pldm_msg*>(getTidResp2.data()), sizeof(getTidResp2));
235     EXPECT_EQ(rc, PLDM_SUCCESS);
236     rc = mockTerminusManager.enqueueResponse(
237         reinterpret_cast<pldm_msg*>(setTidResp2.data()), sizeof(setTidResp2));
238     EXPECT_EQ(rc, PLDM_SUCCESS);
239 
240     rc = mockTerminusManager.enqueueResponse(
241         reinterpret_cast<pldm_msg*>(getPldmTypesResp2.data()),
242         sizeof(getPldmTypesResp2));
243     EXPECT_EQ(rc, PLDM_SUCCESS);
244     mockTerminusManager.removeMctpTerminus(mctpInfos);
245     EXPECT_EQ(0, termini.size());
246 }
247 
248 TEST_F(TerminusManagerTest, doesSupportTypeTest)
249 {
250     const size_t getTidRespLen = PLDM_GET_TID_RESP_BYTES;
251     const size_t setTidRespLen = PLDM_SET_TID_RESP_BYTES;
252     const size_t getPldmTypesRespLen = PLDM_GET_TYPES_RESP_BYTES;
253 
254     // 0.discover a mctp list
255     auto rc = mockTerminusManager.clearQueuedResponses();
256     EXPECT_EQ(rc, PLDM_SUCCESS);
257 
258     std::array<uint8_t, sizeof(pldm_msg_hdr) + getTidRespLen> getTidResp0{
259         0x00, 0x02, 0x02, 0x00, 0x00};
260     rc = mockTerminusManager.enqueueResponse(
261         reinterpret_cast<pldm_msg*>(getTidResp0.data()), sizeof(getTidResp0));
262     EXPECT_EQ(rc, PLDM_SUCCESS);
263 
264     std::array<uint8_t, sizeof(pldm_msg_hdr) + setTidRespLen> setTidResp0{
265         0x00, 0x02, 0x01, 0x00};
266     rc = mockTerminusManager.enqueueResponse(
267         reinterpret_cast<pldm_msg*>(setTidResp0.data()), sizeof(setTidResp0));
268     EXPECT_EQ(rc, PLDM_SUCCESS);
269 
270     uint8_t supportedType1Byte =
271         (1 << (PLDM_BASE % 8)) + (1 << (PLDM_PLATFORM % 8)) +
272         (1 << (PLDM_BIOS % 8)) + (1 << (PLDM_FRU % 8));
273     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmTypesRespLen>
274         getPldmTypesResp0{0x00, 0x02, 0x04, 0x00, supportedType1Byte,
275                           0x00, 0x00, 0x00, 0x00, 0x00,
276                           0x00, 0x00};
277     rc = mockTerminusManager.enqueueResponse(
278         reinterpret_cast<pldm_msg*>(getPldmTypesResp0.data()),
279         sizeof(getPldmTypesResp0));
280     EXPECT_EQ(rc, PLDM_SUCCESS);
281 
282     pldm::MctpInfos mctpInfos{};
283     mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1));
284     mockTerminusManager.discoverMctpTerminus(mctpInfos);
285     EXPECT_EQ(1, termini.size());
286 
287     EXPECT_EQ(true, termini.contains(1));
288     EXPECT_EQ(false, termini.contains(0));
289     EXPECT_EQ(false, termini.contains(2));
290 
291     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_BASE));
292     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_PLATFORM));
293     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_BIOS));
294     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_FRU));
295     EXPECT_EQ(false, termini[1]->doesSupportType(PLDM_FWUP));
296     EXPECT_EQ(false, termini[1]->doesSupportType(PLDM_OEM));
297 }
298 
299 TEST_F(TerminusManagerTest, doesSupportCommandTest)
300 {
301     const size_t getTidRespLen = PLDM_GET_TID_RESP_BYTES;
302     const size_t setTidRespLen = PLDM_SET_TID_RESP_BYTES;
303     const size_t getPldmTypesRespLen = PLDM_GET_TYPES_RESP_BYTES;
304     const size_t getPldmCommandRespLen = PLDM_GET_COMMANDS_RESP_BYTES;
305     /* PLDM_GET_VERSION_RESP_BYTES does not include 4 bytes check sum */
306     const size_t getPldmVersionRespLen =
307         PLDM_GET_VERSION_RESP_BYTES + sizeof(uint32_t);
308 
309     // 0.discover a mctp list
310     auto rc = mockTerminusManager.clearQueuedResponses();
311     EXPECT_EQ(rc, PLDM_SUCCESS);
312 
313     std::array<uint8_t, sizeof(pldm_msg_hdr) + getTidRespLen> getTidResp0{
314         0x00, 0x02, 0x02, 0x00, 0x00};
315     rc = mockTerminusManager.enqueueResponse(
316         reinterpret_cast<pldm_msg*>(getTidResp0.data()), sizeof(getTidResp0));
317     EXPECT_EQ(rc, PLDM_SUCCESS);
318 
319     std::array<uint8_t, sizeof(pldm_msg_hdr) + setTidRespLen> setTidResp0{
320         0x00, 0x02, 0x01, 0x00};
321     rc = mockTerminusManager.enqueueResponse(
322         reinterpret_cast<pldm_msg*>(setTidResp0.data()), sizeof(setTidResp0));
323     EXPECT_EQ(rc, PLDM_SUCCESS);
324 
325     uint8_t byte0 = (1 << (PLDM_BASE % 8)) + (1 << (PLDM_PLATFORM % 8)) +
326                     (1 << (PLDM_BIOS % 8)) + (1 << (PLDM_FRU % 8));
327     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmTypesRespLen>
328         getPldmTypesResp0{0x00, 0x02, 0x04, 0x00, byte0, 0x00,
329                           0x00, 0x00, 0x00, 0x00, 0x00,  0x00};
330     rc = mockTerminusManager.enqueueResponse(
331         reinterpret_cast<pldm_msg*>(getPldmTypesResp0.data()),
332         sizeof(getPldmTypesResp0));
333     EXPECT_EQ(rc, PLDM_SUCCESS);
334 
335     /* Response GetPLDMVersion BASE, CC=0 */
336     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmVersionRespLen>
337         getPldmVersionBaseResp0{0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
338                                 0x00, 0x00, 0x05, 0x00, 0xf0, 0xf1,
339                                 0xf1, 0xba, 0xbe, 0x9d, 0x53};
340 
341     rc = mockTerminusManager.enqueueResponse(
342         (pldm_msg*)getPldmVersionBaseResp0.data(),
343         sizeof(getPldmVersionBaseResp0));
344     EXPECT_EQ(rc, PLDM_SUCCESS);
345 
346     /* Response GetPLDMCommand BASE, CC=0,
347      * SetTID/GetTID/GetPLDMTypes/GetPLDMCommands */
348     byte0 = (1 << (PLDM_SET_TID % 8)) + (1 << (PLDM_GET_TID % 8)) +
349             (1 << (PLDM_GET_PLDM_TYPES % 8)) +
350             (1 << (PLDM_GET_PLDM_COMMANDS % 8));
351     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmCommandRespLen>
352         getPldmCommandBaseResp0{
353             0x00, 0x02, 0x05, 0x00, byte0, 0x00, 0x00, 0x00, 0x00,
354             0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
355             0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
356             0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00};
357     rc = mockTerminusManager.enqueueResponse(
358         reinterpret_cast<pldm_msg*>(getPldmCommandBaseResp0.data()),
359         sizeof(getPldmCommandBaseResp0));
360     EXPECT_EQ(rc, PLDM_SUCCESS);
361 
362     /* Response GetPLDMVersion PLATFORM, CC=0 */
363     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmVersionRespLen>
364         getPldmVersionPlatformResp0{0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
365                                     0x00, 0x00, 0x05, 0x00, 0xf1, 0xf2,
366                                     0xf1, 0x4e, 0x87, 0x72, 0x79};
367 
368     rc = mockTerminusManager.enqueueResponse(
369         (pldm_msg*)getPldmVersionPlatformResp0.data(),
370         sizeof(getPldmVersionPlatformResp0));
371     EXPECT_EQ(rc, PLDM_SUCCESS);
372     /* Response GetPLDMCommand PLATFORM, CC=0,
373      * SetEventReceiver/PlatformEventMessage/GetSensorReading/SetNumericEffecterValue/GetNumericEffecterValue/GetPDR
374      */
375     /* byte0 command from 0x00 to 0x07 */
376     byte0 = (1 << (PLDM_SET_EVENT_RECEIVER % 8)); // byte0 = 0x10
377     /* byte1 command from 0x08 to 0xf */
378     uint8_t byte1 = (1 << (PLDM_PLATFORM_EVENT_MESSAGE % 8)) +
379                     (1 << (PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE % 8)) +
380                     (1 << (PLDM_EVENT_MESSAGE_SUPPORTED % 8)) +
381                     (1 << (PLDM_EVENT_MESSAGE_BUFFER_SIZE % 8)); // byte1 = 0x3c
382     /* byte2 command from 0x10 to 0x17 */
383     uint8_t byte2 = (1 << (PLDM_GET_SENSOR_READING % 8)); // byte2 = 0x02
384     /* byte3 command from 0x18 to 0x1f */
385     /* byte4 command from 0x20 to 0x27 */
386     uint8_t byte4 = (1 << (PLDM_GET_STATE_SENSOR_READINGS % 8)); // byte4 = 0x02
387     /* byte5 command from 0x28 to 0x2f */
388     /* byte6 command from 0x30 to 0x37 */
389     uint8_t byte6 =
390         (1 << (PLDM_SET_NUMERIC_EFFECTER_VALUE % 8)) +
391         (1 << (PLDM_GET_NUMERIC_EFFECTER_VALUE % 8)); // byte6 = 0x06
392     /* byte7 command from 0x38 to 0x3f */
393     uint8_t byte7 = (0 << (PLDM_SET_STATE_EFFECTER_STATES % 8)); // byte7 = 0
394     /* byte8 command from 0x40 to 0x47 */
395     /* byte9 command from 0x48 to 0x4f */
396     /* byte10 command from 0x50 to 0x57 */
397     uint8_t byte10 = (1 << (PLDM_GET_PDR_REPOSITORY_INFO % 8)) +
398                      (1 << (PLDM_GET_PDR % 8)); // byte10 = 0x03
399     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmCommandRespLen>
400         getPldmCommandPlatResp0{
401             0x00, 0x02,  0x05,  0x00, byte0, byte1,  byte2, 0x00, byte4,
402             0x00, byte6, byte7, 0x00, 0x00,  byte10, 0x00,  0x00, 0x00,
403             0x00, 0x00,  0x00,  0x00, 0x00,  0x00,   0x00,  0x00, 0x00,
404             0x00, 0x00,  0x00,  0x00, 0x00,  0x00,   0x00,  0x00, 0x00};
405     rc = mockTerminusManager.enqueueResponse(
406         reinterpret_cast<pldm_msg*>(getPldmCommandPlatResp0.data()),
407         sizeof(getPldmCommandPlatResp0));
408     EXPECT_EQ(rc, PLDM_SUCCESS);
409 
410     /* Response GetPLDMVersion BIOS, CC=0 */
411     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmVersionRespLen>
412         getPldmVersionBiosResp0{0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
413                                 0x00, 0x00, 0x05, 0x00, 0xf0, 0xf0,
414                                 0xf1, 0xfb, 0x8f, 0x86, 0x4a};
415 
416     rc = mockTerminusManager.enqueueResponse(
417         (pldm_msg*)getPldmVersionBiosResp0.data(),
418         sizeof(getPldmVersionBiosResp0));
419     EXPECT_EQ(rc, PLDM_SUCCESS);
420     /* Response GetPLDMCommand BIOS, CC=0, GetDateTime/SetDateTime */
421     /* byte0 command from 1 to 7 */
422     byte0 = (0 << (PLDM_GET_BIOS_TABLE % 8)) +
423             (0 << (PLDM_SET_BIOS_TABLE % 8)) +
424             (0 << (PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE % 8));
425     /* byte1 command from 8 to 15 */
426     byte1 = (0 << (PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE % 8)) +
427             (1 << (PLDM_GET_DATE_TIME % 8)) + (1 << (PLDM_SET_DATE_TIME % 8));
428     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmCommandRespLen>
429         getPldmCommandBiosResp0{
430             0x00, 0x02, 0x05, 0x00, byte0, byte1, 0x00, 0x00, 0x00,
431             0x00, 0x00, 0x00, 0x00, 0x00,  0x00,  0x00, 0x00, 0x00,
432             0x00, 0x00, 0x00, 0x00, 0x00,  0x00,  0x00, 0x00, 0x00,
433             0x00, 0x00, 0x00, 0x00, 0x00,  0x00,  0x00, 0x00};
434     rc = mockTerminusManager.enqueueResponse(
435         reinterpret_cast<pldm_msg*>(getPldmCommandBiosResp0.data()),
436         sizeof(getPldmCommandBiosResp0));
437     EXPECT_EQ(rc, PLDM_SUCCESS);
438 
439     /* Response GetPLDMVersion FRU, CC=0 */
440     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmVersionRespLen>
441         getPldmVersionFruResp0{0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
442                                0x00, 0x00, 0x05, 0x00, 0xf1, 0xf0,
443                                0xf1, 0xcc, 0xe5, 0x44, 0x4b};
444 
445     rc = mockTerminusManager.enqueueResponse(
446         (pldm_msg*)getPldmVersionFruResp0.data(),
447         sizeof(getPldmVersionFruResp0));
448     EXPECT_EQ(rc, PLDM_SUCCESS);
449     /* Response GetPLDMCommand FRU, CC=0,
450      * GetFRURecordTableMetadata/GetFRURecordTable */
451     /* byte0 command from 1 to 7 */
452     byte0 = (1 << (PLDM_GET_FRU_RECORD_TABLE_METADATA % 8)) +
453             (1 << (PLDM_GET_FRU_RECORD_TABLE % 8)) +
454             (0 << (PLDM_SET_FRU_RECORD_TABLE % 8)) +
455             (0 << (PLDM_GET_FRU_RECORD_BY_OPTION % 8));
456     /* byte0 command from 8 to 15 */
457     byte1 = 0;
458     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmCommandRespLen>
459         getPldmCommandFruResp0{
460             0x00, 0x02, 0x05, 0x00, byte0, 0x00, 0x00, 0x00, 0x00,
461             0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
462             0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
463             0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00};
464     rc = mockTerminusManager.enqueueResponse(
465         reinterpret_cast<pldm_msg*>(getPldmCommandFruResp0.data()),
466         sizeof(getPldmCommandFruResp0));
467     EXPECT_EQ(rc, PLDM_SUCCESS);
468 
469     pldm::MctpInfos mctpInfos{};
470     mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1));
471     mockTerminusManager.discoverMctpTerminus(mctpInfos);
472     EXPECT_EQ(1, termini.size());
473     EXPECT_EQ(true, termini.contains(1));
474     EXPECT_EQ(false, termini.contains(0));
475     EXPECT_EQ(false, termini.contains(2));
476 
477     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_BASE));
478     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_PLATFORM));
479     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_BIOS));
480     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_FRU));
481     /* Check PLDM Base commands */
482     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_BASE, PLDM_SET_TID));
483     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_BASE, PLDM_GET_TID));
484     EXPECT_EQ(false,
485               termini[1]->doesSupportCommand(PLDM_BASE, PLDM_GET_PLDM_VERSION));
486     EXPECT_EQ(true,
487               termini[1]->doesSupportCommand(PLDM_BASE, PLDM_GET_PLDM_TYPES));
488 
489     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_BASE,
490                                                    PLDM_GET_PLDM_COMMANDS));
491     EXPECT_EQ(false, termini[1]->doesSupportCommand(PLDM_BASE,
492                                                     PLDM_MULTIPART_RECEIVE));
493 
494     /* Check PLDM Platform commands */
495     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_PLATFORM,
496                                                    PLDM_SET_EVENT_RECEIVER));
497     EXPECT_EQ(true, termini[1]->doesSupportCommand(
498                         PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE));
499     EXPECT_EQ(true, termini[1]->doesSupportCommand(
500                         PLDM_PLATFORM, PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE));
501     EXPECT_EQ(true, termini[1]->doesSupportCommand(
502                         PLDM_PLATFORM, PLDM_EVENT_MESSAGE_SUPPORTED));
503     EXPECT_EQ(true, termini[1]->doesSupportCommand(
504                         PLDM_PLATFORM, PLDM_EVENT_MESSAGE_BUFFER_SIZE));
505     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_PLATFORM,
506                                                    PLDM_GET_SENSOR_READING));
507     EXPECT_EQ(true, termini[1]->doesSupportCommand(
508                         PLDM_PLATFORM, PLDM_GET_STATE_SENSOR_READINGS));
509     EXPECT_EQ(true, termini[1]->doesSupportCommand(
510                         PLDM_PLATFORM, PLDM_SET_NUMERIC_EFFECTER_VALUE));
511     EXPECT_EQ(true, termini[1]->doesSupportCommand(
512                         PLDM_PLATFORM, PLDM_GET_NUMERIC_EFFECTER_VALUE));
513     EXPECT_EQ(false, termini[1]->doesSupportCommand(
514                          PLDM_PLATFORM, PLDM_SET_STATE_EFFECTER_STATES));
515     EXPECT_EQ(true, termini[1]->doesSupportCommand(
516                         PLDM_PLATFORM, PLDM_GET_PDR_REPOSITORY_INFO));
517     EXPECT_EQ(true,
518               termini[1]->doesSupportCommand(PLDM_PLATFORM, PLDM_GET_PDR));
519 
520     /* Check PLDM Bios commands */
521     EXPECT_EQ(false,
522               termini[1]->doesSupportCommand(PLDM_BIOS, PLDM_GET_BIOS_TABLE));
523     EXPECT_EQ(false,
524               termini[1]->doesSupportCommand(PLDM_BIOS, PLDM_SET_BIOS_TABLE));
525     EXPECT_EQ(false, termini[1]->doesSupportCommand(
526                          PLDM_BIOS, PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE));
527     EXPECT_EQ(false,
528               termini[1]->doesSupportCommand(
529                   PLDM_BIOS, PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE));
530     EXPECT_EQ(true,
531               termini[1]->doesSupportCommand(PLDM_BIOS, PLDM_GET_DATE_TIME));
532     EXPECT_EQ(true,
533               termini[1]->doesSupportCommand(PLDM_BIOS, PLDM_SET_DATE_TIME));
534 
535     /* Check PLDM Fru commands */
536     EXPECT_EQ(true, termini[1]->doesSupportCommand(
537                         PLDM_FRU, PLDM_GET_FRU_RECORD_TABLE_METADATA));
538     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_FRU,
539                                                    PLDM_GET_FRU_RECORD_TABLE));
540     EXPECT_EQ(false, termini[1]->doesSupportCommand(PLDM_FRU,
541                                                     PLDM_SET_FRU_RECORD_TABLE));
542     EXPECT_EQ(false, termini[1]->doesSupportCommand(
543                          PLDM_FRU, PLDM_GET_FRU_RECORD_BY_OPTION));
544 }
545