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 
306     // 0.discover a mctp list
307     auto rc = mockTerminusManager.clearQueuedResponses();
308     EXPECT_EQ(rc, PLDM_SUCCESS);
309 
310     std::array<uint8_t, sizeof(pldm_msg_hdr) + getTidRespLen> getTidResp0{
311         0x00, 0x02, 0x02, 0x00, 0x00};
312     rc = mockTerminusManager.enqueueResponse(
313         reinterpret_cast<pldm_msg*>(getTidResp0.data()), sizeof(getTidResp0));
314     EXPECT_EQ(rc, PLDM_SUCCESS);
315 
316     std::array<uint8_t, sizeof(pldm_msg_hdr) + setTidRespLen> setTidResp0{
317         0x00, 0x02, 0x01, 0x00};
318     rc = mockTerminusManager.enqueueResponse(
319         reinterpret_cast<pldm_msg*>(setTidResp0.data()), sizeof(setTidResp0));
320     EXPECT_EQ(rc, PLDM_SUCCESS);
321 
322     uint8_t byte0 = (1 << (PLDM_BASE % 8)) + (1 << (PLDM_PLATFORM % 8)) +
323                     (1 << (PLDM_BIOS % 8)) + (1 << (PLDM_FRU % 8));
324     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmTypesRespLen>
325         getPldmTypesResp0{0x00, 0x02, 0x04, 0x00, byte0, 0x00,
326                           0x00, 0x00, 0x00, 0x00, 0x00,  0x00};
327     rc = mockTerminusManager.enqueueResponse(
328         reinterpret_cast<pldm_msg*>(getPldmTypesResp0.data()),
329         sizeof(getPldmTypesResp0));
330     EXPECT_EQ(rc, PLDM_SUCCESS);
331 
332     /* Response GetPLDMCommand BASE, CC=0,
333      * SetTID/GetTID/GetPLDMTypes/GetPLDMCommands */
334     byte0 = (1 << (PLDM_SET_TID % 8)) + (1 << (PLDM_GET_TID % 8)) +
335             (1 << (PLDM_GET_PLDM_TYPES % 8)) +
336             (1 << (PLDM_GET_PLDM_COMMANDS % 8));
337     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmCommandRespLen>
338         getPldmCommandBaseResp0{
339             0x00, 0x02, 0x05, 0x00, byte0, 0x00, 0x00, 0x00, 0x00,
340             0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
341             0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
342             0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00};
343     rc = mockTerminusManager.enqueueResponse(
344         reinterpret_cast<pldm_msg*>(getPldmCommandBaseResp0.data()),
345         sizeof(getPldmCommandBaseResp0));
346     EXPECT_EQ(rc, PLDM_SUCCESS);
347 
348     /* Response GetPLDMCommand PLATFORM, CC=0,
349      * SetEventReceiver/PlatformEventMessage/GetSensorReading/SetNumericEffecterValue/GetNumericEffecterValue/GetPDR
350      */
351     /* byte0 command from 0x00 to 0x07 */
352     byte0 = (1 << (PLDM_SET_EVENT_RECEIVER % 8)); // byte0 = 0x10
353     /* byte1 command from 0x08 to 0xf */
354     uint8_t byte1 = (1 << (PLDM_PLATFORM_EVENT_MESSAGE % 8)) +
355                     (1 << (PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE % 8)) +
356                     (1 << (PLDM_EVENT_MESSAGE_SUPPORTED % 8)) +
357                     (1 << (PLDM_EVENT_MESSAGE_BUFFER_SIZE % 8)); // byte1 = 0x3c
358     /* byte2 command from 0x10 to 0x17 */
359     uint8_t byte2 = (1 << (PLDM_GET_SENSOR_READING % 8)); // byte2 = 0x02
360     /* byte3 command from 0x18 to 0x1f */
361     /* byte4 command from 0x20 to 0x27 */
362     uint8_t byte4 = (1 << (PLDM_GET_STATE_SENSOR_READINGS % 8)); // byte4 = 0x02
363     /* byte5 command from 0x28 to 0x2f */
364     /* byte6 command from 0x30 to 0x37 */
365     uint8_t byte6 =
366         (1 << (PLDM_SET_NUMERIC_EFFECTER_VALUE % 8)) +
367         (1 << (PLDM_GET_NUMERIC_EFFECTER_VALUE % 8)); // byte6 = 0x06
368     /* byte7 command from 0x38 to 0x3f */
369     uint8_t byte7 = (0 << (PLDM_SET_STATE_EFFECTER_STATES % 8)); // byte7 = 0
370     /* byte8 command from 0x40 to 0x47 */
371     /* byte9 command from 0x48 to 0x4f */
372     /* byte10 command from 0x50 to 0x57 */
373     uint8_t byte10 = (1 << (PLDM_GET_PDR_REPOSITORY_INFO % 8)) +
374                      (1 << (PLDM_GET_PDR % 8)); // byte10 = 0x03
375     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmCommandRespLen>
376         getPldmCommandPlatResp0{
377             0x00, 0x02,  0x05,  0x00, byte0, byte1,  byte2, 0x00, byte4,
378             0x00, byte6, byte7, 0x00, 0x00,  byte10, 0x00,  0x00, 0x00,
379             0x00, 0x00,  0x00,  0x00, 0x00,  0x00,   0x00,  0x00, 0x00,
380             0x00, 0x00,  0x00,  0x00, 0x00,  0x00,   0x00,  0x00, 0x00};
381     rc = mockTerminusManager.enqueueResponse(
382         reinterpret_cast<pldm_msg*>(getPldmCommandPlatResp0.data()),
383         sizeof(getPldmCommandPlatResp0));
384     EXPECT_EQ(rc, PLDM_SUCCESS);
385 
386     /* Response GetPLDMCommand BIOS, CC=0, GetDateTime/SetDateTime */
387     /* byte0 command from 1 to 7 */
388     byte0 = (0 << (PLDM_GET_BIOS_TABLE % 8)) +
389             (0 << (PLDM_SET_BIOS_TABLE % 8)) +
390             (0 << (PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE % 8));
391     /* byte1 command from 8 to 15 */
392     byte1 = (0 << (PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE % 8)) +
393             (1 << (PLDM_GET_DATE_TIME % 8)) + (1 << (PLDM_SET_DATE_TIME % 8));
394     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmCommandRespLen>
395         getPldmCommandBiosResp0{
396             0x00, 0x02, 0x05, 0x00, byte0, byte1, 0x00, 0x00, 0x00,
397             0x00, 0x00, 0x00, 0x00, 0x00,  0x00,  0x00, 0x00, 0x00,
398             0x00, 0x00, 0x00, 0x00, 0x00,  0x00,  0x00, 0x00, 0x00,
399             0x00, 0x00, 0x00, 0x00, 0x00,  0x00,  0x00, 0x00};
400     rc = mockTerminusManager.enqueueResponse(
401         reinterpret_cast<pldm_msg*>(getPldmCommandBiosResp0.data()),
402         sizeof(getPldmCommandBiosResp0));
403     EXPECT_EQ(rc, PLDM_SUCCESS);
404 
405     /* Response GetPLDMCommand FRU, CC=0,
406      * GetFRURecordTableMetadata/GetFRURecordTable */
407     /* byte0 command from 1 to 7 */
408     byte0 = (1 << (PLDM_GET_FRU_RECORD_TABLE_METADATA % 8)) +
409             (1 << (PLDM_GET_FRU_RECORD_TABLE % 8)) +
410             (0 << (PLDM_SET_FRU_RECORD_TABLE % 8)) +
411             (0 << (PLDM_GET_FRU_RECORD_BY_OPTION % 8));
412     /* byte0 command from 8 to 15 */
413     byte1 = 0;
414     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmCommandRespLen>
415         getPldmCommandFruResp0{
416             0x00, 0x02, 0x05, 0x00, byte0, 0x00, 0x00, 0x00, 0x00,
417             0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
418             0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
419             0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00};
420     rc = mockTerminusManager.enqueueResponse(
421         reinterpret_cast<pldm_msg*>(getPldmCommandFruResp0.data()),
422         sizeof(getPldmCommandFruResp0));
423     EXPECT_EQ(rc, PLDM_SUCCESS);
424 
425     pldm::MctpInfos mctpInfos{};
426     mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1));
427     mockTerminusManager.discoverMctpTerminus(mctpInfos);
428     EXPECT_EQ(1, termini.size());
429     EXPECT_EQ(true, termini.contains(1));
430     EXPECT_EQ(false, termini.contains(0));
431     EXPECT_EQ(false, termini.contains(2));
432 
433     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_BASE));
434     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_PLATFORM));
435     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_BIOS));
436     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_FRU));
437     /* Check PLDM Base commands */
438     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_BASE, PLDM_SET_TID));
439     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_BASE, PLDM_GET_TID));
440     EXPECT_EQ(false,
441               termini[1]->doesSupportCommand(PLDM_BASE, PLDM_GET_PLDM_VERSION));
442     EXPECT_EQ(true,
443               termini[1]->doesSupportCommand(PLDM_BASE, PLDM_GET_PLDM_TYPES));
444 
445     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_BASE,
446                                                    PLDM_GET_PLDM_COMMANDS));
447     EXPECT_EQ(false, termini[1]->doesSupportCommand(PLDM_BASE,
448                                                     PLDM_MULTIPART_RECEIVE));
449 
450     /* Check PLDM Platform commands */
451     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_PLATFORM,
452                                                    PLDM_SET_EVENT_RECEIVER));
453     EXPECT_EQ(true, termini[1]->doesSupportCommand(
454                         PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE));
455     EXPECT_EQ(true, termini[1]->doesSupportCommand(
456                         PLDM_PLATFORM, PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE));
457     EXPECT_EQ(true, termini[1]->doesSupportCommand(
458                         PLDM_PLATFORM, PLDM_EVENT_MESSAGE_SUPPORTED));
459     EXPECT_EQ(true, termini[1]->doesSupportCommand(
460                         PLDM_PLATFORM, PLDM_EVENT_MESSAGE_BUFFER_SIZE));
461     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_PLATFORM,
462                                                    PLDM_GET_SENSOR_READING));
463     EXPECT_EQ(true, termini[1]->doesSupportCommand(
464                         PLDM_PLATFORM, PLDM_GET_STATE_SENSOR_READINGS));
465     EXPECT_EQ(true, termini[1]->doesSupportCommand(
466                         PLDM_PLATFORM, PLDM_SET_NUMERIC_EFFECTER_VALUE));
467     EXPECT_EQ(true, termini[1]->doesSupportCommand(
468                         PLDM_PLATFORM, PLDM_GET_NUMERIC_EFFECTER_VALUE));
469     EXPECT_EQ(false, termini[1]->doesSupportCommand(
470                          PLDM_PLATFORM, PLDM_SET_STATE_EFFECTER_STATES));
471     EXPECT_EQ(true, termini[1]->doesSupportCommand(
472                         PLDM_PLATFORM, PLDM_GET_PDR_REPOSITORY_INFO));
473     EXPECT_EQ(true,
474               termini[1]->doesSupportCommand(PLDM_PLATFORM, PLDM_GET_PDR));
475 
476     /* Check PLDM Bios commands */
477     EXPECT_EQ(false,
478               termini[1]->doesSupportCommand(PLDM_BIOS, PLDM_GET_BIOS_TABLE));
479     EXPECT_EQ(false,
480               termini[1]->doesSupportCommand(PLDM_BIOS, PLDM_SET_BIOS_TABLE));
481     EXPECT_EQ(false, termini[1]->doesSupportCommand(
482                          PLDM_BIOS, PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE));
483     EXPECT_EQ(false,
484               termini[1]->doesSupportCommand(
485                   PLDM_BIOS, PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE));
486     EXPECT_EQ(true,
487               termini[1]->doesSupportCommand(PLDM_BIOS, PLDM_GET_DATE_TIME));
488     EXPECT_EQ(true,
489               termini[1]->doesSupportCommand(PLDM_BIOS, PLDM_SET_DATE_TIME));
490 
491     /* Check PLDM Fru commands */
492     EXPECT_EQ(true, termini[1]->doesSupportCommand(
493                         PLDM_FRU, PLDM_GET_FRU_RECORD_TABLE_METADATA));
494     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_FRU,
495                                                    PLDM_GET_FRU_RECORD_TABLE));
496     EXPECT_EQ(false, termini[1]->doesSupportCommand(PLDM_FRU,
497                                                     PLDM_SET_FRU_RECORD_TABLE));
498     EXPECT_EQ(false, termini[1]->doesSupportCommand(
499                          PLDM_FRU, PLDM_GET_FRU_RECORD_BY_OPTION));
500 }
501