xref: /openbmc/pldm/platform-mc/test/event_manager_test.cpp (revision fdf61cc310dfe7bb56d007bf1026635081f44aca)
1 #include "libpldm/base.h"
2 #include "libpldm/entity.h"
3 #include "libpldm/platform.h"
4 
5 #include "common/instance_id.hpp"
6 #include "common/types.hpp"
7 #include "mock_event_manager.hpp"
8 #include "mock_terminus_manager.hpp"
9 #include "platform-mc/platform_manager.hpp"
10 #include "platform-mc/terminus_manager.hpp"
11 #include "test/test_instance_id.hpp"
12 #include "utils_test.hpp"
13 
14 #include <gtest/gtest.h>
15 
16 using ::testing::_;
17 using ::testing::Return;
18 
19 class EventManagerTest : public testing::Test
20 {
21   protected:
EventManagerTest()22     EventManagerTest() :
23         bus(pldm::utils::DBusHandler::getBus()),
24         event(sdeventplus::Event::get_default()), instanceIdDb(),
25         reqHandler(pldmTransport, event, instanceIdDb, false,
26                    std::chrono::seconds(1), 2, std::chrono::milliseconds(100)),
27         terminusManager(event, reqHandler, instanceIdDb, termini, nullptr),
28         eventManager(terminusManager, termini),
29         platformManager(terminusManager, termini, nullptr)
30     {}
31 
32     PldmTransport* pldmTransport = nullptr;
33     sdbusplus::bus_t& bus;
34     sdeventplus::Event event;
35     TestInstanceIdDb instanceIdDb;
36     pldm::requester::Handler<pldm::requester::Request> reqHandler;
37     pldm::platform_mc::MockTerminusManager terminusManager;
38     pldm::platform_mc::MockEventManager eventManager;
39     pldm::platform_mc::PlatformManager platformManager;
40     pldm::platform_mc::TerminiMapper termini{};
41 };
42 
TEST_F(EventManagerTest,processNumericSensorEventTest)43 TEST_F(EventManagerTest, processNumericSensorEventTest)
44 {
45 #define SENSOR_READING 50
46 #define WARNING_HIGH 45
47     pldm_tid_t tid = 1;
48     termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
49         tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM, event);
50     std::vector<uint8_t> pdr1{
51         0x1,
52         0x0,
53         0x0,
54         0x0,                         // record handle
55         0x1,                         // PDRHeaderVersion
56         PLDM_NUMERIC_SENSOR_PDR,     // PDRType
57         0x0,
58         0x0,                         // recordChangeNumber
59         PLDM_PDR_NUMERIC_SENSOR_PDR_MIN_LENGTH,
60         0,                           // dataLength
61         0,
62         0,                           // PLDMTerminusHandle
63         0x1,
64         0x0,                         // sensorID=1
65         PLDM_ENTITY_POWER_SUPPLY,
66         0,                           // entityType=Power Supply(120)
67         1,
68         0,                           // entityInstanceNumber
69         1,
70         0,                           // containerID=1
71         PLDM_NO_INIT,                // sensorInit
72         false,                       // sensorAuxiliaryNamesPDR
73         PLDM_SENSOR_UNIT_DEGRESS_C,  // baseUint(2)=degrees C
74         0,                           // unitModifier = 0
75         0,                           // rateUnit
76         0,                           // baseOEMUnitHandle
77         0,                           // auxUnit
78         0,                           // auxUnitModifier
79         0,                           // auxRateUnit
80         0,                           // rel
81         0,                           // auxOEMUnitHandle
82         true,                        // isLinear
83         PLDM_SENSOR_DATA_SIZE_UINT8, // sensorDataSize
84         0,
85         0,
86         0x80,
87         0x3f, // resolution=1.0
88         0,
89         0,
90         0,
91         0,    // offset=0
92         0,
93         0,    // accuracy
94         0,    // plusTolerance
95         0,    // minusTolerance
96         2,    // hysteresis = 2
97         0x1b, // supportedThresholds
98         0,    // thresholdAndHysteresisVolatility
99         0,
100         0,
101         0x80,
102         0x3f, // stateTransistionInterval=1.0
103         0,
104         0,
105         0x80,
106         0x3f,                          // updateInverval=1.0
107         255,                           // maxReadable
108         0,                             // minReadable
109         PLDM_RANGE_FIELD_FORMAT_UINT8, // rangeFieldFormat
110         0x18,                          // rangeFieldsupport
111         0,                             // nominalValue
112         0,                             // normalMax
113         0,                             // normalMin
114         WARNING_HIGH,                  // warningHigh
115         20,                            // warningLow
116         60,                            // criticalHigh
117         10,                            // criticalLow
118         0,                             // fatalHigh
119         0                              // fatalLow
120     };
121 
122     std::vector<uint8_t> pdr2{
123         0x1, 0x0, 0x0,
124         0x0,                             // record handle
125         0x1,                             // PDRHeaderVersion
126         PLDM_ENTITY_AUXILIARY_NAMES_PDR, // PDRType
127         0x1,
128         0x0,                             // recordChangeNumber
129         0x11,
130         0,                               // dataLength
131         /* Entity Auxiliary Names PDR Data*/
132         3,
133         0x80, // entityType system software
134         0x1,
135         0x0,  // Entity instance number =1
136         0,
137         0,    // Overal system
138         0,    // shared Name Count one name only
139         01,   // nameStringCount
140         0x65, 0x6e, 0x00,
141         0x00, // Language Tag "en"
142         0x53, 0x00, 0x30, 0x00,
143         0x00  // Entity Name "S0"
144     };
145 
146     // add dummy numeric sensor
147     termini[tid]->pdrs.emplace_back(pdr1);
148     termini[tid]->pdrs.emplace_back(pdr2);
149     termini[tid]->parseTerminusPDRs();
150     // Run event loop for a few seconds to let sensor creation
151     // defer tasks be run. May increase time when sensor num is large
152     utils::runEventLoopForSeconds(event, 1);
153     EXPECT_EQ(1, termini[tid]->numericSensors.size());
154 
155     uint8_t platformEventStatus = 0;
156 
157     std::vector<uint8_t> eventData{
158         0x1,
159         0x0, // sensor id
160         PLDM_NUMERIC_SENSOR_STATE,
161         PLDM_SENSOR_UPPERWARNING,
162         PLDM_SENSOR_NORMAL,
163         PLDM_SENSOR_DATA_SIZE_UINT8,
164         SENSOR_READING};
165     auto rc = eventManager.handlePlatformEvent(
166         tid, 0x00, PLDM_SENSOR_EVENT, eventData.data(), eventData.size());
167     EXPECT_EQ(PLDM_SUCCESS, rc);
168     EXPECT_EQ(PLDM_EVENT_NO_LOGGING, platformEventStatus);
169 }
170 
TEST_F(EventManagerTest,SetEventReceiverTest)171 TEST_F(EventManagerTest, SetEventReceiverTest)
172 {
173     // Add terminus
174     auto mappedTid = terminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
175     auto tid = mappedTid.value();
176     termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
177         tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM, event);
178     auto terminus = termini[tid];
179 
180     /* Set supported command by terminus */
181     auto size = PLDM_MAX_TYPES * (PLDM_MAX_CMDS_PER_TYPE / 8);
182     std::vector<uint8_t> pldmCmds(size);
183     uint8_t type = PLDM_PLATFORM;
184     uint8_t cmd = PLDM_GET_PDR_REPOSITORY_INFO;
185     auto idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
186     pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
187     cmd = PLDM_GET_PDR;
188     idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
189     pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
190     cmd = PLDM_EVENT_MESSAGE_SUPPORTED;
191     idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
192     pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
193     cmd = PLDM_EVENT_MESSAGE_BUFFER_SIZE;
194     idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
195     pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
196     cmd = PLDM_SET_EVENT_RECEIVER;
197     idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
198     pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
199     termini[tid]->setSupportedCommands(pldmCmds);
200 
201     EXPECT_EQ(true, termini[tid]->doesSupportCommand(PLDM_PLATFORM,
202                                                      PLDM_SET_EVENT_RECEIVER));
203     EXPECT_EQ(true, termini[tid]->doesSupportCommand(
204                         PLDM_PLATFORM, PLDM_EVENT_MESSAGE_BUFFER_SIZE));
205     EXPECT_EQ(true, termini[tid]->doesSupportCommand(
206                         PLDM_PLATFORM, PLDM_EVENT_MESSAGE_SUPPORTED));
207     EXPECT_EQ(true,
208               termini[tid]->doesSupportCommand(PLDM_PLATFORM, PLDM_GET_PDR));
209     EXPECT_EQ(true, termini[tid]->doesSupportCommand(
210                         PLDM_PLATFORM, PLDM_GET_PDR_REPOSITORY_INFO));
211 
212     // queue getPDRRepositoryInfo response
213     const size_t getPDRRepositoryInfoLen =
214         PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES;
215     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPDRRepositoryInfoLen>
216         getPDRRepositoryInfoResp{
217             0x0, 0x02, 0x50, PLDM_SUCCESS,
218             0x0,                                     // repositoryState
219             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, 0x0,
220             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, // updateTime
221             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, 0x0,
222             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, // OEMUpdateTime
223             2,   0x0,  0x0,  0x0,                    // recordCount
224             0x0, 0x1,  0x0,  0x0,                    // repositorySize
225             59,  0x0,  0x0,  0x0,                    // largestRecordSize
226             0x0 // dataTransferHandleTimeout
227         };
228     auto rc = terminusManager.enqueueResponse(
229         reinterpret_cast<pldm_msg*>(getPDRRepositoryInfoResp.data()),
230         sizeof(getPDRRepositoryInfoResp));
231     EXPECT_EQ(rc, PLDM_SUCCESS);
232 
233     // queue getPDR responses
234     const size_t getPdrRespLen = 81;
235     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPdrRespLen> getPdrResp{
236         0x0, 0x02, 0x51, PLDM_SUCCESS, 0x1, 0x0, 0x0, 0x0, // nextRecordHandle
237         0x0, 0x0, 0x0, 0x0, // nextDataTransferHandle
238         0x5,                // transferFlag
239         69, 0x0,            // responseCount
240         // numeric Sensor PDR
241         0x0, 0x0, 0x0,
242         0x0,                     // record handle
243         0x1,                     // PDRHeaderVersion
244         PLDM_NUMERIC_SENSOR_PDR, // PDRType
245         0x0,
246         0x0,                     // recordChangeNumber
247         PLDM_PDR_NUMERIC_SENSOR_PDR_FIXED_LENGTH +
248             PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_SENSOR_DATA_SIZE_MIN_LENGTH +
249             PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_RANGE_FIELD_MIN_LENGTH,
250         0,                             // dataLength
251         0,
252         0,                             // PLDMTerminusHandle
253         0x1,
254         0x0,                           // sensorID=1
255         120,
256         0,                             // entityType=Power Supply(120)
257         1,
258         0,                             // entityInstanceNumber
259         0x1,
260         0x0,                           // containerID=1
261         PLDM_NO_INIT,                  // sensorInit
262         false,                         // sensorAuxiliaryNamesPDR
263         PLDM_SENSOR_UNIT_DEGRESS_C,    // baseUint(2)=degrees C
264         1,                             // unitModifier = 1
265         0,                             // rateUnit
266         0,                             // baseOEMUnitHandle
267         0,                             // auxUnit
268         0,                             // auxUnitModifier
269         0,                             // auxRateUnit
270         0,                             // rel
271         0,                             // auxOEMUnitHandle
272         true,                          // isLinear
273         PLDM_SENSOR_DATA_SIZE_UINT8,   // sensorDataSize
274         0, 0, 0xc0,
275         0x3f,                          // resolution=1.5
276         0, 0, 0x80,
277         0x3f,                          // offset=1.0
278         0,
279         0,                             // accuracy
280         0,                             // plusTolerance
281         0,                             // minusTolerance
282         2,                             // hysteresis
283         0,                             // supportedThresholds
284         0,                             // thresholdAndHysteresisVolatility
285         0, 0, 0x80,
286         0x3f,                          // stateTransistionInterval=1.0
287         0, 0, 0x80,
288         0x3f,                          // updateInverval=1.0
289         255,                           // maxReadable
290         0,                             // minReadable
291         PLDM_RANGE_FIELD_FORMAT_UINT8, // rangeFieldFormat
292         0,                             // rangeFieldsupport
293         0,                             // nominalValue
294         0,                             // normalMax
295         0,                             // normalMin
296         0,                             // warningHigh
297         0,                             // warningLow
298         0,                             // criticalHigh
299         0,                             // criticalLow
300         0,                             // fatalHigh
301         0                              // fatalLow
302     };
303     rc = terminusManager.enqueueResponse(
304         reinterpret_cast<pldm_msg*>(getPdrResp.data()), sizeof(getPdrResp));
305     EXPECT_EQ(rc, PLDM_SUCCESS);
306 
307     const size_t getPdrAuxNameRespLen = 39;
308     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPdrAuxNameRespLen>
309         getPdrAuxNameResp{
310             0x0, 0x02, 0x51, PLDM_SUCCESS, 0x0, 0x0, 0x0,
311             0x0,                // nextRecordHandle
312             0x0, 0x0, 0x0, 0x0, // nextDataTransferHandle
313             0x5,                // transferFlag
314             0x1b, 0x0,          // responseCount
315             // Common PDR Header
316             0x1, 0x0, 0x0,
317             0x0,                             // record handle
318             0x1,                             // PDRHeaderVersion
319             PLDM_ENTITY_AUXILIARY_NAMES_PDR, // PDRType
320             0x1,
321             0x0,                             // recordChangeNumber
322             0x11,
323             0,                               // dataLength
324             /* Entity Auxiliary Names PDR Data*/
325             3,
326             0x80, // entityType system software
327             0x1,
328             0x0,  // Entity instance number =1
329             0,
330             0,    // Overal system
331             0,    // shared Name Count one name only
332             01,   // nameStringCount
333             0x65, 0x6e, 0x00,
334             0x00, // Language Tag "en"
335             0x53, 0x00, 0x30, 0x00,
336             0x00  // Entity Name "S0"
337         };
338     rc = terminusManager.enqueueResponse(
339         reinterpret_cast<pldm_msg*>(getPdrAuxNameResp.data()),
340         sizeof(getPdrAuxNameResp));
341     EXPECT_EQ(rc, PLDM_SUCCESS);
342 
343     // queue eventMessageBufferSize response(bufferSize=32)
344     const size_t eventMessageBufferSizeRespLen = 3;
345     std::array<uint8_t, sizeof(pldm_msg_hdr) + eventMessageBufferSizeRespLen>
346         eventMessageBufferSizeResp{0x0, 0x02, 0x0d, PLDM_SUCCESS, 32, 0};
347     rc = terminusManager.enqueueResponse(
348         reinterpret_cast<pldm_msg*>(eventMessageBufferSizeResp.data()),
349         sizeof(eventMessageBufferSizeResp));
350     EXPECT_EQ(rc, PLDM_SUCCESS);
351 
352     // queue eventMessageSupported response
353     const size_t eventMessageSupportedLen = 7;
354     PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES;
355     std::array<uint8_t, sizeof(pldm_msg_hdr) + eventMessageSupportedLen>
356         eventMessageSupportedResp{0x0,  0x02, 0x0c, PLDM_SUCCESS,
357                                   0x0,  // synchronyConfiguration
358                                   0x06, // synchronyConfigurationSupported
359                                   3,    // numberEventClassReturned
360                                   0x0,  0x5,  0xfa};
361     rc = terminusManager.enqueueResponse(
362         reinterpret_cast<pldm_msg*>(eventMessageSupportedResp.data()),
363         sizeof(eventMessageSupportedResp));
364     EXPECT_EQ(rc, PLDM_SUCCESS);
365 
366     terminusManager.updateMctpEndpointAvailability(
367         pldm::MctpInfo(10, "", "", 1), true);
368 
369     // queue SetEventReceiver response
370     const size_t SetEventReceiverLen = 1;
371     PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES;
372     std::array<uint8_t, sizeof(pldm_msg_hdr) + SetEventReceiverLen>
373         SetEventReceiverResp{0x0, 0x02, 0x04, PLDM_SUCCESS};
374     rc = terminusManager.enqueueResponse(
375         reinterpret_cast<pldm_msg*>(SetEventReceiverResp.data()),
376         sizeof(SetEventReceiverResp));
377     EXPECT_EQ(rc, PLDM_SUCCESS);
378 
379     // should finish immediately
380     stdexec::sync_wait(platformManager.initTerminus());
381     // Run event loop for a few seconds to let sensor creation
382     // defer tasks be run. May increase time when sensor num is large
383     utils::runEventLoopForSeconds(event, 1);
384     EXPECT_EQ(true, terminus->initialized);
385     EXPECT_EQ(32, terminus->maxBufferSize);
386     EXPECT_EQ(0x06, terminus->synchronyConfigurationSupported.byte);
387     EXPECT_EQ(2, terminus->pdrs.size());
388     EXPECT_EQ(1, terminus->numericSensors.size());
389 }
390 
TEST_F(EventManagerTest,updateAvailableState)391 TEST_F(EventManagerTest, updateAvailableState)
392 {
393     pldm_tid_t tid = 1;
394     eventManager.updateAvailableState(tid, true);
395     EXPECT_EQ(true, eventManager.getAvailableState(tid));
396     eventManager.updateAvailableState(tid, false);
397     EXPECT_EQ(false, eventManager.getAvailableState(tid));
398     eventManager.updateAvailableState(2, false);
399     EXPECT_EQ(false, eventManager.getAvailableState(tid));
400 }
401 
TEST_F(EventManagerTest,pollForPlatformEventTaskMultipartTransferTest)402 TEST_F(EventManagerTest, pollForPlatformEventTaskMultipartTransferTest)
403 {
404     // Add terminus
405     auto mappedTid = terminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
406     auto tid = mappedTid.value();
407     termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
408         tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM, event);
409     auto terminus = termini[tid];
410 
411     // queue pollForPlatformEventMessage first part response
412     const size_t pollForPlatformEventMessage1Len = 22;
413     std::array<uint8_t, sizeof(pldm_msg_hdr) + pollForPlatformEventMessage1Len>
414         pollForPlatformEventMessage1Resp{
415             0x0,
416             0x02,
417             0x0d,
418             PLDM_SUCCESS,
419             tid, // TID
420             0x1,
421             0x0, // eventID
422             0x1,
423             0x0,
424             0x0,
425             0x0,                          // nextDataTransferHandle
426             PLDM_PLATFORM_TRANSFER_START, // transferFlag = start
427             PLDM_CPER_EVENT,              // eventClass
428             8,
429             0,
430             0,
431             0,    // eventDataSize
432             0x01, // CPER event formatVersion= 0x01
433             1,    // formatType = single CPER section(0x01)
434             10,
435             0,    // eventDataLength = 10
436             1,
437             2,
438             3,
439             4 // eventData first part
440         };
441     auto rc = terminusManager.enqueueResponse(
442         reinterpret_cast<pldm_msg*>(pollForPlatformEventMessage1Resp.data()),
443         sizeof(pollForPlatformEventMessage1Resp));
444     EXPECT_EQ(rc, PLDM_SUCCESS);
445 
446     // queue pollForPlatformEventMessage last part response
447     const size_t pollForPlatformEventMessage2Len = 24;
448     std::array<uint8_t, sizeof(pldm_msg_hdr) + pollForPlatformEventMessage2Len>
449         pollForPlatformEventMessage2Resp{
450             0x0,
451             0x02,
452             0x0d,
453             PLDM_SUCCESS,
454             tid, // TID
455             0x1,
456             0x0, // eventID
457             0x2,
458             0x0,
459             0x0,
460             0x0,                        // nextDataTransferHandle
461             PLDM_PLATFORM_TRANSFER_END, // transferFlag = end
462             PLDM_CPER_EVENT,            // eventClass
463             6,
464             0,
465             0,
466             0, // eventDataSize
467             5,
468             6,
469             7,
470             8,
471             9,
472             0, // eventData last part
473             0x46,
474             0x7f,
475             0x6a,
476             0x5d // crc32
477         };
478     rc = terminusManager.enqueueResponse(
479         reinterpret_cast<pldm_msg*>(pollForPlatformEventMessage2Resp.data()),
480         sizeof(pollForPlatformEventMessage2Resp));
481     EXPECT_EQ(rc, PLDM_SUCCESS);
482 
483     // queue pollForPlatformEventMessage Ack response
484     const size_t pollForPlatformEventMessage3Len = 4;
485     std::array<uint8_t, sizeof(pldm_msg_hdr) + pollForPlatformEventMessage3Len>
486         pollForPlatformEventMessage3Resp{
487             0x0, 0x02, 0x0d, PLDM_SUCCESS,
488             tid,     // TID
489             0x0, 0x0 // eventID
490         };
491     rc = terminusManager.enqueueResponse(
492         reinterpret_cast<pldm_msg*>(pollForPlatformEventMessage3Resp.data()),
493         sizeof(pollForPlatformEventMessage3Resp));
494     EXPECT_EQ(rc, PLDM_SUCCESS);
495 
496     terminusManager.updateMctpEndpointAvailability(
497         pldm::MctpInfo(10, "", "", 1), true);
498 
499     EXPECT_CALL(eventManager, processCperEvent(_, _, _, _))
500         .Times(1)
501         .WillRepeatedly(Return(1));
502 
503     // start task to poll event from terminus
504     // should finish immediately
505     stdexec::sync_wait(eventManager.pollForPlatformEventTask(tid, 0x0000));
506 }
507