1 #include "common/instance_id.hpp"
2 #include "mock_terminus_manager.hpp"
3 #include "platform-mc/platform_manager.hpp"
4 #include "test/test_instance_id.hpp"
5 
6 #include <sdeventplus/event.hpp>
7 
8 #include <bitset>
9 
10 #include <gtest/gtest.h>
11 
12 class PlatformManagerTest : public testing::Test
13 {
14   protected:
15     PlatformManagerTest() :
16         bus(pldm::utils::DBusHandler::getBus()),
17         event(sdeventplus::Event::get_default()), instanceIdDb(),
18         reqHandler(pldmTransport, event, instanceIdDb, false,
19                    std::chrono::seconds(1), 2, std::chrono::milliseconds(100)),
20         mockTerminusManager(event, reqHandler, instanceIdDb, termini, nullptr),
21         platformManager(mockTerminusManager, termini)
22     {}
23 
24     PldmTransport* pldmTransport = nullptr;
25     sdbusplus::bus_t& bus;
26     sdeventplus::Event event;
27     TestInstanceIdDb instanceIdDb;
28     pldm::requester::Handler<pldm::requester::Request> reqHandler;
29     pldm::platform_mc::MockTerminusManager mockTerminusManager;
30     pldm::platform_mc::PlatformManager platformManager;
31     std::map<pldm_tid_t, std::shared_ptr<pldm::platform_mc::Terminus>> termini;
32 };
33 
34 TEST_F(PlatformManagerTest, initTerminusTest)
35 {
36     // Add terminus
37     auto mappedTid = mockTerminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
38     auto tid = mappedTid.value();
39     termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
40         tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM);
41     auto terminus = termini[tid];
42 
43     /* Set supported command by terminus */
44     auto size = PLDM_MAX_TYPES * (PLDM_MAX_CMDS_PER_TYPE / 8);
45     std::vector<uint8_t> pldmCmds(size);
46     uint8_t type = PLDM_PLATFORM;
47     uint8_t cmd = PLDM_GET_PDR;
48     auto idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
49     pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
50     cmd = PLDM_GET_PDR_REPOSITORY_INFO;
51     idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
52     pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
53     termini[tid]->setSupportedCommands(pldmCmds);
54 
55     // queue getPDRRepositoryInfo response
56     const size_t getPDRRepositoryInfoLen =
57         PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES;
58     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPDRRepositoryInfoLen>
59         getPDRRepositoryInfoResp{
60             0x0, 0x02, 0x50, PLDM_SUCCESS,
61             0x0,                                     // repositoryState
62             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, 0x0,
63             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, // updateTime
64             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, 0x0,
65             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, // OEMUpdateTime
66             1,   0x0,  0x0,  0x0,                    // recordCount
67             0x0, 0x1,  0x0,  0x0,                    // repositorySize
68             59,  0x0,  0x0,  0x0,                    // largestRecordSize
69             0x0 // dataTransferHandleTimeout
70         };
71     auto rc = mockTerminusManager.enqueueResponse(
72         reinterpret_cast<pldm_msg*>(getPDRRepositoryInfoResp.data()),
73         sizeof(getPDRRepositoryInfoResp));
74     EXPECT_EQ(rc, PLDM_SUCCESS);
75 
76     // queue getPDR responses
77     const size_t getPdrRespLen = 81;
78     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPdrRespLen> getPdrResp{
79         0x0, 0x02, 0x51, PLDM_SUCCESS, 0x0, 0x0, 0x0, 0x0, // nextRecordHandle
80         0x0, 0x0, 0x0, 0x0, // nextDataTransferHandle
81         0x5,                // transferFlag
82         69, 0x0,            // responseCount
83         // numeric Sensor PDR
84         0x1, 0x0, 0x0,
85         0x0,                     // record handle
86         0x1,                     // PDRHeaderVersion
87         PLDM_NUMERIC_SENSOR_PDR, // PDRType
88         0x0,
89         0x0,                     // recordChangeNumber
90         PLDM_PDR_NUMERIC_SENSOR_PDR_FIXED_LENGTH +
91             PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_SENSOR_DATA_SIZE_MIN_LENGTH +
92             PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_RANGE_FIELD_MIN_LENGTH,
93         0,                             // dataLength
94         0,
95         0,                             // PLDMTerminusHandle
96         0x1,
97         0x0,                           // sensorID=1
98         120,
99         0,                             // entityType=Power Supply(120)
100         1,
101         0,                             // entityInstanceNumber
102         0x1,
103         0x0,                           // containerID=1
104         PLDM_NO_INIT,                  // sensorInit
105         false,                         // sensorAuxiliaryNamesPDR
106         PLDM_SENSOR_UNIT_DEGRESS_C,    // baseUint(2)=degrees C
107         1,                             // unitModifier = 1
108         0,                             // rateUnit
109         0,                             // baseOEMUnitHandle
110         0,                             // auxUnit
111         0,                             // auxUnitModifier
112         0,                             // auxRateUnit
113         0,                             // rel
114         0,                             // auxOEMUnitHandle
115         true,                          // isLinear
116         PLDM_SENSOR_DATA_SIZE_UINT8,   // sensorDataSize
117         0, 0, 0xc0,
118         0x3f,                          // resolution=1.5
119         0, 0, 0x80,
120         0x3f,                          // offset=1.0
121         0,
122         0,                             // accuracy
123         0,                             // plusTolerance
124         0,                             // minusTolerance
125         2,                             // hysteresis
126         0,                             // supportedThresholds
127         0,                             // thresholdAndHysteresisVolatility
128         0, 0, 0x80,
129         0x3f,                          // stateTransistionInterval=1.0
130         0, 0, 0x80,
131         0x3f,                          // updateInverval=1.0
132         255,                           // maxReadable
133         0,                             // minReadable
134         PLDM_RANGE_FIELD_FORMAT_UINT8, // rangeFieldFormat
135         0,                             // rangeFieldsupport
136         0,                             // nominalValue
137         0,                             // normalMax
138         0,                             // normalMin
139         0,                             // warningHigh
140         0,                             // warningLow
141         0,                             // criticalHigh
142         0,                             // criticalLow
143         0,                             // fatalHigh
144         0                              // fatalLow
145     };
146     rc = mockTerminusManager.enqueueResponse(
147         reinterpret_cast<pldm_msg*>(getPdrResp.data()), sizeof(getPdrResp));
148     EXPECT_EQ(rc, PLDM_SUCCESS);
149 
150     stdexec::sync_wait(platformManager.initTerminus());
151     EXPECT_EQ(true, terminus->initialized);
152     EXPECT_EQ(1, terminus->pdrs.size());
153 }
154 
155 TEST_F(PlatformManagerTest, parseTerminusNameTest)
156 {
157     // Add terminus
158     auto mappedTid = mockTerminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
159     auto tid = mappedTid.value();
160     termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
161         tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM);
162     auto terminus = termini[tid];
163 
164     /* Set supported command by terminus */
165     auto size = PLDM_MAX_TYPES * (PLDM_MAX_CMDS_PER_TYPE / 8);
166     std::vector<uint8_t> pldmCmds(size);
167     uint8_t type = PLDM_PLATFORM;
168     uint8_t cmd = PLDM_GET_PDR;
169     auto idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
170     pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
171     cmd = PLDM_GET_PDR_REPOSITORY_INFO;
172     idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
173     pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
174     termini[tid]->setSupportedCommands(pldmCmds);
175 
176     // queue getPDRRepositoryInfo response
177     const size_t getPDRRepositoryInfoLen =
178         PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES;
179     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPDRRepositoryInfoLen>
180         getPDRRepositoryInfoResp{
181             0x0, 0x02, 0x50, PLDM_SUCCESS,
182             0x0,                                     // repositoryState
183             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, 0x0,
184             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, // updateTime
185             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, 0x0,
186             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, // OEMUpdateTime
187             2,   0x0,  0x0,  0x0,                    // recordCount
188             0x0, 0x1,  0x0,  0x0,                    // repositorySize
189             59,  0x0,  0x0,  0x0,                    // largestRecordSize
190             0x0 // dataTransferHandleTimeout
191         };
192     auto rc = mockTerminusManager.enqueueResponse(
193         reinterpret_cast<pldm_msg*>(getPDRRepositoryInfoResp.data()),
194         sizeof(getPDRRepositoryInfoResp));
195     EXPECT_EQ(rc, PLDM_SUCCESS);
196 
197     // queue getPDR responses
198     const size_t getPdrRespLen = 81;
199     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPdrRespLen> getPdrResp{
200         0x0, 0x02, 0x51, PLDM_SUCCESS, 0x1, 0x0, 0x0, 0x0, // nextRecordHandle
201         0x0, 0x0, 0x0, 0x0, // nextDataTransferHandle
202         0x5,                // transferFlag
203         69, 0x0,            // responseCount
204         // numeric Sensor PDR
205         0x0, 0x0, 0x0,
206         0x0,                     // record handle
207         0x1,                     // PDRHeaderVersion
208         PLDM_NUMERIC_SENSOR_PDR, // PDRType
209         0x0,
210         0x0,                     // recordChangeNumber
211         PLDM_PDR_NUMERIC_SENSOR_PDR_FIXED_LENGTH +
212             PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_SENSOR_DATA_SIZE_MIN_LENGTH +
213             PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_RANGE_FIELD_MIN_LENGTH,
214         0,                             // dataLength
215         0,
216         0,                             // PLDMTerminusHandle
217         0x1,
218         0x0,                           // sensorID=1
219         120,
220         0,                             // entityType=Power Supply(120)
221         1,
222         0,                             // entityInstanceNumber
223         0x1,
224         0x0,                           // containerID=1
225         PLDM_NO_INIT,                  // sensorInit
226         false,                         // sensorAuxiliaryNamesPDR
227         PLDM_SENSOR_UNIT_DEGRESS_C,    // baseUint(2)=degrees C
228         1,                             // unitModifier = 1
229         0,                             // rateUnit
230         0,                             // baseOEMUnitHandle
231         0,                             // auxUnit
232         0,                             // auxUnitModifier
233         0,                             // auxRateUnit
234         0,                             // rel
235         0,                             // auxOEMUnitHandle
236         true,                          // isLinear
237         PLDM_SENSOR_DATA_SIZE_UINT8,   // sensorDataSize
238         0, 0, 0xc0,
239         0x3f,                          // resolution=1.5
240         0, 0, 0x80,
241         0x3f,                          // offset=1.0
242         0,
243         0,                             // accuracy
244         0,                             // plusTolerance
245         0,                             // minusTolerance
246         2,                             // hysteresis
247         0,                             // supportedThresholds
248         0,                             // thresholdAndHysteresisVolatility
249         0, 0, 0x80,
250         0x3f,                          // stateTransistionInterval=1.0
251         0, 0, 0x80,
252         0x3f,                          // updateInverval=1.0
253         255,                           // maxReadable
254         0,                             // minReadable
255         PLDM_RANGE_FIELD_FORMAT_UINT8, // rangeFieldFormat
256         0,                             // rangeFieldsupport
257         0,                             // nominalValue
258         0,                             // normalMax
259         0,                             // normalMin
260         0,                             // warningHigh
261         0,                             // warningLow
262         0,                             // criticalHigh
263         0,                             // criticalLow
264         0,                             // fatalHigh
265         0                              // fatalLow
266     };
267     rc = mockTerminusManager.enqueueResponse(
268         reinterpret_cast<pldm_msg*>(getPdrResp.data()), sizeof(getPdrResp));
269     EXPECT_EQ(rc, PLDM_SUCCESS);
270 
271     const size_t getPdrAuxNameRespLen = 39;
272     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPdrAuxNameRespLen>
273         getPdrAuxNameResp{
274             0x0, 0x02, 0x51, PLDM_SUCCESS, 0x0, 0x0, 0x0,
275             0x0,                // nextRecordHandle
276             0x0, 0x0, 0x0, 0x0, // nextDataTransferHandle
277             0x5,                // transferFlag
278             0x1b, 0x0,          // responseCount
279             // Common PDR Header
280             0x1, 0x0, 0x0,
281             0x0,                             // record handle
282             0x1,                             // PDRHeaderVersion
283             PLDM_ENTITY_AUXILIARY_NAMES_PDR, // PDRType
284             0x1,
285             0x0,                             // recordChangeNumber
286             0x11,
287             0,                               // dataLength
288             /* Entity Auxiliary Names PDR Data*/
289             3,
290             0x80, // entityType system software
291             0x1,
292             0x0,  // Entity instance number =1
293             0,
294             0,    // Overal system
295             0,    // shared Name Count one name only
296             01,   // nameStringCount
297             0x65, 0x6e, 0x00,
298             0x00, // Language Tag "en"
299             0x53, 0x00, 0x30, 0x00,
300             0x00  // Entity Name "S0"
301         };
302     rc = mockTerminusManager.enqueueResponse(
303         reinterpret_cast<pldm_msg*>(getPdrAuxNameResp.data()),
304         sizeof(getPdrAuxNameResp));
305     EXPECT_EQ(rc, PLDM_SUCCESS);
306 
307     stdexec::sync_wait(platformManager.initTerminus());
308     EXPECT_EQ(true, terminus->initialized);
309     EXPECT_EQ(2, terminus->pdrs.size());
310     EXPECT_EQ("S0", terminus->getTerminusName());
311 }
312 
313 TEST_F(PlatformManagerTest, initTerminusDontSupportGetPDRTest)
314 {
315     // Add terminus
316     auto mappedTid = mockTerminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
317     auto tid = mappedTid.value();
318     termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
319         tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM);
320     auto terminus = termini[tid];
321 
322     /* Set supported command by terminus */
323     auto size = PLDM_MAX_TYPES * (PLDM_MAX_CMDS_PER_TYPE / 8);
324     std::vector<uint8_t> pldmCmds(size);
325     uint8_t type = PLDM_PLATFORM;
326     uint8_t cmd = PLDM_GET_PDR_REPOSITORY_INFO;
327     auto idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
328     pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
329     termini[tid]->setSupportedCommands(pldmCmds);
330 
331     // queue getPDRRepositoryInfo response
332     const size_t getPDRRepositoryInfoLen =
333         PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES;
334     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPDRRepositoryInfoLen>
335         getPDRRepositoryInfoResp{
336             0x0, 0x02, 0x50, PLDM_SUCCESS,
337             0x0,                                     // repositoryState
338             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, 0x0,
339             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, // updateTime
340             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, 0x0,
341             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, // OEMUpdateTime
342             1,   0x0,  0x0,  0x0,                    // recordCount
343             0x0, 0x1,  0x0,  0x0,                    // repositorySize
344             59,  0x0,  0x0,  0x0,                    // largestRecordSize
345             0x0 // dataTransferHandleTimeout
346         };
347     auto rc = mockTerminusManager.enqueueResponse(
348         reinterpret_cast<pldm_msg*>(getPDRRepositoryInfoResp.data()),
349         sizeof(getPDRRepositoryInfoResp));
350     EXPECT_EQ(rc, PLDM_SUCCESS);
351 
352     // queue getPDR responses
353     const size_t getPdrRespLen = 81;
354     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPdrRespLen> getPdrResp{
355         0x0, 0x02, 0x51, PLDM_SUCCESS, 0x0, 0x0, 0x0, 0x0, // nextRecordHandle
356         0x0, 0x0, 0x0, 0x0, // nextDataTransferHandle
357         0x5,                // transferFlag
358         69, 0x0,            // responseCount
359         // numeric Sensor PDR
360         0x1, 0x0, 0x0,
361         0x0,                     // record handle
362         0x1,                     // PDRHeaderVersion
363         PLDM_NUMERIC_SENSOR_PDR, // PDRType
364         0x0,
365         0x0,                     // recordChangeNumber
366         PLDM_PDR_NUMERIC_SENSOR_PDR_FIXED_LENGTH +
367             PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_SENSOR_DATA_SIZE_MIN_LENGTH +
368             PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_RANGE_FIELD_MIN_LENGTH,
369         0,                             // dataLength
370         0,
371         0,                             // PLDMTerminusHandle
372         0x1,
373         0x0,                           // sensorID=1
374         120,
375         0,                             // entityType=Power Supply(120)
376         1,
377         0,                             // entityInstanceNumber
378         0x1,
379         0x0,                           // containerID=1
380         PLDM_NO_INIT,                  // sensorInit
381         false,                         // sensorAuxiliaryNamesPDR
382         PLDM_SENSOR_UNIT_DEGRESS_C,    // baseUint(2)=degrees C
383         1,                             // unitModifier = 1
384         0,                             // rateUnit
385         0,                             // baseOEMUnitHandle
386         0,                             // auxUnit
387         0,                             // auxUnitModifier
388         0,                             // auxRateUnit
389         0,                             // rel
390         0,                             // auxOEMUnitHandle
391         true,                          // isLinear
392         PLDM_SENSOR_DATA_SIZE_UINT8,   // sensorDataSize
393         0, 0, 0xc0,
394         0x3f,                          // resolution=1.5
395         0, 0, 0x80,
396         0x3f,                          // offset=1.0
397         0,
398         0,                             // accuracy
399         0,                             // plusTolerance
400         0,                             // minusTolerance
401         2,                             // hysteresis
402         0,                             // supportedThresholds
403         0,                             // thresholdAndHysteresisVolatility
404         0, 0, 0x80,
405         0x3f,                          // stateTransistionInterval=1.0
406         0, 0, 0x80,
407         0x3f,                          // updateInverval=1.0
408         255,                           // maxReadable
409         0,                             // minReadable
410         PLDM_RANGE_FIELD_FORMAT_UINT8, // rangeFieldFormat
411         0,                             // rangeFieldsupport
412         0,                             // nominalValue
413         0,                             // normalMax
414         0,                             // normalMin
415         0,                             // warningHigh
416         0,                             // warningLow
417         0,                             // criticalHigh
418         0,                             // criticalLow
419         0,                             // fatalHigh
420         0                              // fatalLow
421     };
422     rc = mockTerminusManager.enqueueResponse(
423         reinterpret_cast<pldm_msg*>(getPdrResp.data()), sizeof(getPdrResp));
424     EXPECT_EQ(rc, PLDM_SUCCESS);
425 
426     stdexec::sync_wait(platformManager.initTerminus());
427     EXPECT_EQ(true, terminus->initialized);
428     EXPECT_EQ(0, terminus->pdrs.size());
429 }
430 
431 TEST_F(PlatformManagerTest, negativeInitTerminusTest1)
432 {
433     // terminus doesn't Type2 support
434     auto mappedTid = mockTerminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
435     auto tid = mappedTid.value();
436     termini[tid] =
437         std::make_shared<pldm::platform_mc::Terminus>(tid, 1 << PLDM_BASE);
438     auto terminus = termini[tid];
439 
440     stdexec::sync_wait(platformManager.initTerminus());
441     EXPECT_EQ(true, terminus->initialized);
442     EXPECT_EQ(0, terminus->pdrs.size());
443 }
444 
445 TEST_F(PlatformManagerTest, negativeInitTerminusTest2)
446 {
447     // terminus responses error
448     auto mappedTid = mockTerminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
449     auto tid = mappedTid.value();
450     termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
451         tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM);
452     auto terminus = termini[tid];
453 
454     // queue getPDRRepositoryInfo response cc=PLDM_ERROR
455     const size_t getPDRRepositoryInfoLen = 1;
456     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPDRRepositoryInfoLen>
457         getPDRRepositoryInfoResp{0x0, 0x02, 0x50, PLDM_ERROR};
458     auto rc = mockTerminusManager.enqueueResponse(
459         reinterpret_cast<pldm_msg*>(getPDRRepositoryInfoResp.data()),
460         sizeof(getPDRRepositoryInfoResp));
461     EXPECT_EQ(rc, PLDM_SUCCESS);
462 
463     // queue getPDR responses cc=PLDM_ERROR
464     const size_t getPdrRespLen = 1;
465     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPdrRespLen> getPdrResp{
466         0x0, 0x02, 0x51, PLDM_ERROR};
467     rc = mockTerminusManager.enqueueResponse(
468         reinterpret_cast<pldm_msg*>(getPdrResp.data()), sizeof(getPdrResp));
469     EXPECT_EQ(rc, PLDM_SUCCESS);
470 
471     stdexec::sync_wait(platformManager.initTerminus());
472     EXPECT_EQ(true, terminus->initialized);
473     EXPECT_EQ(0, terminus->pdrs.size());
474 }
475