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         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 
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 
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 
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(
142         reinterpret_cast<pldm_msg*>(getTidResp0.data()), 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(
147         reinterpret_cast<pldm_msg*>(setTidResp0.data()), 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         reinterpret_cast<pldm_msg*>(getPldmTypesResp0.data()),
154         sizeof(getPldmTypesResp0));
155     EXPECT_EQ(rc, PLDM_SUCCESS);
156 
157     pldm::MctpInfos mctpInfos{};
158     mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1));
159     mockTerminusManager.discoverMctpTerminus(mctpInfos);
160     EXPECT_EQ(1, termini.size());
161 
162     // 1.discover the same mctp list again
163     rc = mockTerminusManager.clearQueuedResponses();
164     EXPECT_EQ(rc, PLDM_SUCCESS);
165 
166     std::array<uint8_t, sizeof(pldm_msg_hdr) + getTidRespLen> getTidResp1{
167         0x00, 0x02, 0x02, 0x00, 0x01};
168     rc = mockTerminusManager.enqueueResponse(
169         reinterpret_cast<pldm_msg*>(getTidResp1.data()), sizeof(getTidResp1));
170     EXPECT_EQ(rc, PLDM_SUCCESS);
171     rc = mockTerminusManager.enqueueResponse(
172         reinterpret_cast<pldm_msg*>(setTidResp0.data()), sizeof(setTidResp0));
173     EXPECT_EQ(rc, PLDM_SUCCESS);
174     rc = mockTerminusManager.enqueueResponse(
175         reinterpret_cast<pldm_msg*>(getPldmTypesResp0.data()),
176         sizeof(getPldmTypesResp0));
177     EXPECT_EQ(rc, PLDM_SUCCESS);
178 
179     mockTerminusManager.discoverMctpTerminus(mctpInfos);
180     EXPECT_EQ(1, termini.size());
181 
182     // 2.discover an empty mctp list
183     rc = mockTerminusManager.clearQueuedResponses();
184     EXPECT_EQ(rc, PLDM_SUCCESS);
185 
186     mockTerminusManager.removeMctpTerminus(mctpInfos);
187     EXPECT_EQ(0, termini.size());
188 }
189 
190 TEST_F(TerminusManagerTest, negativeDiscoverMctpTerminusTest)
191 {
192     const size_t getTidRespLen = PLDM_GET_TID_RESP_BYTES;
193     const size_t setTidRespLen = PLDM_SET_TID_RESP_BYTES;
194     const size_t getPldmTypesRespLen = PLDM_GET_TYPES_RESP_BYTES;
195 
196     // 0.terminus returns reserved tid
197     std::array<uint8_t, sizeof(pldm_msg_hdr) + getTidRespLen> getTidResp0{
198         0x00, 0x02, 0x02, 0x00, PLDM_TID_RESERVED};
199     auto rc = mockTerminusManager.enqueueResponse(
200         reinterpret_cast<pldm_msg*>(getTidResp0.data()), sizeof(getTidResp0));
201     EXPECT_EQ(rc, PLDM_SUCCESS);
202 
203     pldm::MctpInfos mctpInfos{};
204     mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1));
205     mockTerminusManager.discoverMctpTerminus(mctpInfos);
206     EXPECT_EQ(0, termini.size());
207 
208     // 1.terminus return cc=pldm_error for set tid
209     std::array<uint8_t, sizeof(pldm_msg_hdr) + getTidRespLen> getTidResp1{
210         0x00, 0x02, 0x02, 0x00, 0x00};
211     std::array<uint8_t, sizeof(pldm_msg_hdr) + setTidRespLen> setTidResp1{
212         0x00, 0x02, 0x01, PLDM_ERROR};
213 
214     rc = mockTerminusManager.enqueueResponse(
215         reinterpret_cast<pldm_msg*>(getTidResp1.data()), sizeof(getTidResp1));
216     EXPECT_EQ(rc, PLDM_SUCCESS);
217     rc = mockTerminusManager.enqueueResponse(
218         reinterpret_cast<pldm_msg*>(setTidResp1.data()), sizeof(setTidResp1));
219     EXPECT_EQ(rc, PLDM_SUCCESS);
220     mockTerminusManager.removeMctpTerminus(mctpInfos);
221     EXPECT_EQ(0, termini.size());
222 
223     // 2.terminus return cc=unsupported_pldm_cmd for set tid cmd and return
224     // cc=pldm_error for get pldm types cmd
225     std::array<uint8_t, sizeof(pldm_msg_hdr) + getTidRespLen> getTidResp2{
226         0x00, 0x02, 0x02, 0x00, 0x00};
227     std::array<uint8_t, sizeof(pldm_msg_hdr) + setTidRespLen> setTidResp2{
228         0x00, 0x02, 0x01, PLDM_ERROR_UNSUPPORTED_PLDM_CMD};
229     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmTypesRespLen>
230         getPldmTypesResp2{0x00, 0x02, 0x04, PLDM_ERROR, 0x01, 0x00,
231                           0x00, 0x00, 0x00, 0x00,       0x00, 0x00};
232     rc = mockTerminusManager.enqueueResponse(
233         reinterpret_cast<pldm_msg*>(getTidResp2.data()), sizeof(getTidResp2));
234     EXPECT_EQ(rc, PLDM_SUCCESS);
235     rc = mockTerminusManager.enqueueResponse(
236         reinterpret_cast<pldm_msg*>(setTidResp2.data()), sizeof(setTidResp2));
237     EXPECT_EQ(rc, PLDM_SUCCESS);
238 
239     rc = mockTerminusManager.enqueueResponse(
240         reinterpret_cast<pldm_msg*>(getPldmTypesResp2.data()),
241         sizeof(getPldmTypesResp2));
242     EXPECT_EQ(rc, PLDM_SUCCESS);
243     mockTerminusManager.removeMctpTerminus(mctpInfos);
244     EXPECT_EQ(0, termini.size());
245 }
246 
247 TEST_F(TerminusManagerTest, doesSupportTypeTest)
248 {
249     const size_t getTidRespLen = PLDM_GET_TID_RESP_BYTES;
250     const size_t setTidRespLen = PLDM_SET_TID_RESP_BYTES;
251     const size_t getPldmTypesRespLen = PLDM_GET_TYPES_RESP_BYTES;
252 
253     // 0.discover a mctp list
254     auto rc = mockTerminusManager.clearQueuedResponses();
255     EXPECT_EQ(rc, PLDM_SUCCESS);
256 
257     std::array<uint8_t, sizeof(pldm_msg_hdr) + getTidRespLen> getTidResp0{
258         0x00, 0x02, 0x02, 0x00, 0x00};
259     rc = mockTerminusManager.enqueueResponse(
260         reinterpret_cast<pldm_msg*>(getTidResp0.data()), sizeof(getTidResp0));
261     EXPECT_EQ(rc, PLDM_SUCCESS);
262 
263     std::array<uint8_t, sizeof(pldm_msg_hdr) + setTidRespLen> setTidResp0{
264         0x00, 0x02, 0x01, 0x00};
265     rc = mockTerminusManager.enqueueResponse(
266         reinterpret_cast<pldm_msg*>(setTidResp0.data()), sizeof(setTidResp0));
267     EXPECT_EQ(rc, PLDM_SUCCESS);
268 
269     uint8_t supportedType1Byte =
270         (1 << (PLDM_BASE % 8)) + (1 << (PLDM_PLATFORM % 8)) +
271         (1 << (PLDM_BIOS % 8)) + (1 << (PLDM_FRU % 8));
272     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmTypesRespLen>
273         getPldmTypesResp0{0x00, 0x02, 0x04, 0x00, supportedType1Byte,
274                           0x00, 0x00, 0x00, 0x00, 0x00,
275                           0x00, 0x00};
276     rc = mockTerminusManager.enqueueResponse(
277         reinterpret_cast<pldm_msg*>(getPldmTypesResp0.data()),
278         sizeof(getPldmTypesResp0));
279     EXPECT_EQ(rc, PLDM_SUCCESS);
280 
281     pldm::MctpInfos mctpInfos{};
282     mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1));
283     mockTerminusManager.discoverMctpTerminus(mctpInfos);
284     EXPECT_EQ(1, termini.size());
285 
286     EXPECT_EQ(true, termini.contains(1));
287     EXPECT_EQ(false, termini.contains(0));
288     EXPECT_EQ(false, termini.contains(2));
289 
290     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_BASE));
291     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_PLATFORM));
292     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_BIOS));
293     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_FRU));
294     EXPECT_EQ(false, termini[1]->doesSupportType(PLDM_FWUP));
295     EXPECT_EQ(false, termini[1]->doesSupportType(PLDM_OEM));
296 }
297 
298 TEST_F(TerminusManagerTest, doesSupportCommandTest)
299 {
300     const size_t getTidRespLen = PLDM_GET_TID_RESP_BYTES;
301     const size_t setTidRespLen = PLDM_SET_TID_RESP_BYTES;
302     const size_t getPldmTypesRespLen = PLDM_GET_TYPES_RESP_BYTES;
303     const size_t getPldmCommandRespLen = PLDM_GET_COMMANDS_RESP_BYTES;
304 
305     // 0.discover a mctp list
306     auto rc = mockTerminusManager.clearQueuedResponses();
307     EXPECT_EQ(rc, PLDM_SUCCESS);
308 
309     std::array<uint8_t, sizeof(pldm_msg_hdr) + getTidRespLen> getTidResp0{
310         0x00, 0x02, 0x02, 0x00, 0x00};
311     rc = mockTerminusManager.enqueueResponse(
312         reinterpret_cast<pldm_msg*>(getTidResp0.data()), sizeof(getTidResp0));
313     EXPECT_EQ(rc, PLDM_SUCCESS);
314 
315     std::array<uint8_t, sizeof(pldm_msg_hdr) + setTidRespLen> setTidResp0{
316         0x00, 0x02, 0x01, 0x00};
317     rc = mockTerminusManager.enqueueResponse(
318         reinterpret_cast<pldm_msg*>(setTidResp0.data()), sizeof(setTidResp0));
319     EXPECT_EQ(rc, PLDM_SUCCESS);
320 
321     uint8_t byte0 = (1 << (PLDM_BASE % 8)) + (1 << (PLDM_PLATFORM % 8)) +
322                     (1 << (PLDM_BIOS % 8)) + (1 << (PLDM_FRU % 8));
323     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmTypesRespLen>
324         getPldmTypesResp0{0x00, 0x02, 0x04, 0x00, byte0, 0x00,
325                           0x00, 0x00, 0x00, 0x00, 0x00,  0x00};
326     rc = mockTerminusManager.enqueueResponse(
327         reinterpret_cast<pldm_msg*>(getPldmTypesResp0.data()),
328         sizeof(getPldmTypesResp0));
329     EXPECT_EQ(rc, PLDM_SUCCESS);
330 
331     /* Response GetPLDMCommand BASE, CC=0,
332      * SetTID/GetTID/GetPLDMTypes/GetPLDMCommands */
333     byte0 = (1 << (PLDM_SET_TID % 8)) + (1 << (PLDM_GET_TID % 8)) +
334             (1 << (PLDM_GET_PLDM_TYPES % 8)) +
335             (1 << (PLDM_GET_PLDM_COMMANDS % 8));
336     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmCommandRespLen>
337         getPldmCommandBaseResp0{
338             0x00, 0x02, 0x05, 0x00, byte0, 0x00, 0x00, 0x00, 0x00,
339             0x00, 0x00, 0x00, 0x00, 0x00,  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     rc = mockTerminusManager.enqueueResponse(
343         reinterpret_cast<pldm_msg*>(getPldmCommandBaseResp0.data()),
344         sizeof(getPldmCommandBaseResp0));
345     EXPECT_EQ(rc, PLDM_SUCCESS);
346 
347     /* Response GetPLDMCommand PLATFORM, CC=0,
348      * SetEventReceiver/PlatformEventMessage/GetSensorReading/SetNumericEffecterValue/GetNumericEffecterValue/GetPDR
349      */
350     /* byte0 command from 0x00 to 0x07 */
351     byte0 = (1 << (PLDM_SET_EVENT_RECEIVER % 8)); // byte0 = 0x10
352     /* byte1 command from 0x08 to 0xf */
353     uint8_t byte1 = (1 << (PLDM_PLATFORM_EVENT_MESSAGE % 8)) +
354                     (1 << (PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE % 8)) +
355                     (1 << (PLDM_EVENT_MESSAGE_SUPPORTED % 8)) +
356                     (1 << (PLDM_EVENT_MESSAGE_BUFFER_SIZE % 8)); // byte1 = 0x3c
357     /* byte2 command from 0x10 to 0x17 */
358     uint8_t byte2 = (1 << (PLDM_GET_SENSOR_READING % 8)); // byte2 = 0x02
359     /* byte3 command from 0x18 to 0x1f */
360     /* byte4 command from 0x20 to 0x27 */
361     uint8_t byte4 = (1 << (PLDM_GET_STATE_SENSOR_READINGS % 8)); // byte4 = 0x02
362     /* byte5 command from 0x28 to 0x2f */
363     /* byte6 command from 0x30 to 0x37 */
364     uint8_t byte6 =
365         (1 << (PLDM_SET_NUMERIC_EFFECTER_VALUE % 8)) +
366         (1 << (PLDM_GET_NUMERIC_EFFECTER_VALUE % 8)); // byte6 = 0x06
367     /* byte7 command from 0x38 to 0x3f */
368     uint8_t byte7 = (0 << (PLDM_SET_STATE_EFFECTER_STATES % 8)); // byte7 = 0
369     /* byte8 command from 0x40 to 0x47 */
370     /* byte9 command from 0x48 to 0x4f */
371     /* byte10 command from 0x50 to 0x57 */
372     uint8_t byte10 = (1 << (PLDM_GET_PDR_REPOSITORY_INFO % 8)) +
373                      (1 << (PLDM_GET_PDR % 8)); // byte10 = 0x03
374     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmCommandRespLen>
375         getPldmCommandPlatResp0{
376             0x00, 0x02,  0x05,  0x00, byte0, byte1,  byte2, 0x00, byte4,
377             0x00, byte6, byte7, 0x00, 0x00,  byte10, 0x00,  0x00, 0x00,
378             0x00, 0x00,  0x00,  0x00, 0x00,  0x00,   0x00,  0x00, 0x00,
379             0x00, 0x00,  0x00,  0x00, 0x00,  0x00,   0x00,  0x00, 0x00};
380     rc = mockTerminusManager.enqueueResponse(
381         reinterpret_cast<pldm_msg*>(getPldmCommandPlatResp0.data()),
382         sizeof(getPldmCommandPlatResp0));
383     EXPECT_EQ(rc, PLDM_SUCCESS);
384 
385     /* Response GetPLDMCommand BIOS, CC=0, GetDateTime/SetDateTime */
386     /* byte0 command from 1 to 7 */
387     byte0 = (0 << (PLDM_GET_BIOS_TABLE % 8)) +
388             (0 << (PLDM_SET_BIOS_TABLE % 8)) +
389             (0 << (PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE % 8));
390     /* byte1 command from 8 to 15 */
391     byte1 = (0 << (PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE % 8)) +
392             (1 << (PLDM_GET_DATE_TIME % 8)) + (1 << (PLDM_SET_DATE_TIME % 8));
393     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmCommandRespLen>
394         getPldmCommandBiosResp0{
395             0x00, 0x02, 0x05, 0x00, byte0, byte1, 0x00, 0x00, 0x00,
396             0x00, 0x00, 0x00, 0x00, 0x00,  0x00,  0x00, 0x00, 0x00,
397             0x00, 0x00, 0x00, 0x00, 0x00,  0x00,  0x00, 0x00, 0x00,
398             0x00, 0x00, 0x00, 0x00, 0x00,  0x00,  0x00, 0x00};
399     rc = mockTerminusManager.enqueueResponse(
400         reinterpret_cast<pldm_msg*>(getPldmCommandBiosResp0.data()),
401         sizeof(getPldmCommandBiosResp0));
402     EXPECT_EQ(rc, PLDM_SUCCESS);
403 
404     /* Response GetPLDMCommand FRU, CC=0,
405      * GetFRURecordTableMetadata/GetFRURecordTable */
406     /* byte0 command from 1 to 7 */
407     byte0 = (1 << (PLDM_GET_FRU_RECORD_TABLE_METADATA % 8)) +
408             (1 << (PLDM_GET_FRU_RECORD_TABLE % 8)) +
409             (0 << (PLDM_SET_FRU_RECORD_TABLE % 8)) +
410             (0 << (PLDM_GET_FRU_RECORD_BY_OPTION % 8));
411     /* byte0 command from 8 to 15 */
412     byte1 = 0;
413     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmCommandRespLen>
414         getPldmCommandFruResp0{
415             0x00, 0x02, 0x05, 0x00, byte0, 0x00, 0x00, 0x00, 0x00,
416             0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
417             0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
418             0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00};
419     rc = mockTerminusManager.enqueueResponse(
420         reinterpret_cast<pldm_msg*>(getPldmCommandFruResp0.data()),
421         sizeof(getPldmCommandFruResp0));
422     EXPECT_EQ(rc, PLDM_SUCCESS);
423 
424     pldm::MctpInfos mctpInfos{};
425     mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1));
426     mockTerminusManager.discoverMctpTerminus(mctpInfos);
427     EXPECT_EQ(1, termini.size());
428     EXPECT_EQ(true, termini.contains(1));
429     EXPECT_EQ(false, termini.contains(0));
430     EXPECT_EQ(false, termini.contains(2));
431 
432     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_BASE));
433     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_PLATFORM));
434     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_BIOS));
435     EXPECT_EQ(true, termini[1]->doesSupportType(PLDM_FRU));
436     /* Check PLDM Base commands */
437     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_BASE, PLDM_SET_TID));
438     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_BASE, PLDM_GET_TID));
439     EXPECT_EQ(false,
440               termini[1]->doesSupportCommand(PLDM_BASE, PLDM_GET_PLDM_VERSION));
441     EXPECT_EQ(true,
442               termini[1]->doesSupportCommand(PLDM_BASE, PLDM_GET_PLDM_TYPES));
443 
444     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_BASE,
445                                                    PLDM_GET_PLDM_COMMANDS));
446     EXPECT_EQ(false, termini[1]->doesSupportCommand(PLDM_BASE,
447                                                     PLDM_MULTIPART_RECEIVE));
448 
449     /* Check PLDM Platform commands */
450     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_PLATFORM,
451                                                    PLDM_SET_EVENT_RECEIVER));
452     EXPECT_EQ(true, termini[1]->doesSupportCommand(
453                         PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE));
454     EXPECT_EQ(true, termini[1]->doesSupportCommand(
455                         PLDM_PLATFORM, PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE));
456     EXPECT_EQ(true, termini[1]->doesSupportCommand(
457                         PLDM_PLATFORM, PLDM_EVENT_MESSAGE_SUPPORTED));
458     EXPECT_EQ(true, termini[1]->doesSupportCommand(
459                         PLDM_PLATFORM, PLDM_EVENT_MESSAGE_BUFFER_SIZE));
460     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_PLATFORM,
461                                                    PLDM_GET_SENSOR_READING));
462     EXPECT_EQ(true, termini[1]->doesSupportCommand(
463                         PLDM_PLATFORM, PLDM_GET_STATE_SENSOR_READINGS));
464     EXPECT_EQ(true, termini[1]->doesSupportCommand(
465                         PLDM_PLATFORM, PLDM_SET_NUMERIC_EFFECTER_VALUE));
466     EXPECT_EQ(true, termini[1]->doesSupportCommand(
467                         PLDM_PLATFORM, PLDM_GET_NUMERIC_EFFECTER_VALUE));
468     EXPECT_EQ(false, termini[1]->doesSupportCommand(
469                          PLDM_PLATFORM, PLDM_SET_STATE_EFFECTER_STATES));
470     EXPECT_EQ(true, termini[1]->doesSupportCommand(
471                         PLDM_PLATFORM, PLDM_GET_PDR_REPOSITORY_INFO));
472     EXPECT_EQ(true,
473               termini[1]->doesSupportCommand(PLDM_PLATFORM, PLDM_GET_PDR));
474 
475     /* Check PLDM Bios commands */
476     EXPECT_EQ(false,
477               termini[1]->doesSupportCommand(PLDM_BIOS, PLDM_GET_BIOS_TABLE));
478     EXPECT_EQ(false,
479               termini[1]->doesSupportCommand(PLDM_BIOS, PLDM_SET_BIOS_TABLE));
480     EXPECT_EQ(false, termini[1]->doesSupportCommand(
481                          PLDM_BIOS, PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE));
482     EXPECT_EQ(false,
483               termini[1]->doesSupportCommand(
484                   PLDM_BIOS, PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE));
485     EXPECT_EQ(true,
486               termini[1]->doesSupportCommand(PLDM_BIOS, PLDM_GET_DATE_TIME));
487     EXPECT_EQ(true,
488               termini[1]->doesSupportCommand(PLDM_BIOS, PLDM_SET_DATE_TIME));
489 
490     /* Check PLDM Fru commands */
491     EXPECT_EQ(true, termini[1]->doesSupportCommand(
492                         PLDM_FRU, PLDM_GET_FRU_RECORD_TABLE_METADATA));
493     EXPECT_EQ(true, termini[1]->doesSupportCommand(PLDM_FRU,
494                                                    PLDM_GET_FRU_RECORD_TABLE));
495     EXPECT_EQ(false, termini[1]->doesSupportCommand(PLDM_FRU,
496                                                     PLDM_SET_FRU_RECORD_TABLE));
497     EXPECT_EQ(false, termini[1]->doesSupportCommand(
498                          PLDM_FRU, PLDM_GET_FRU_RECORD_BY_OPTION));
499 }
500