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