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