1 #include "common/instance_id.hpp"
2 #include "common/types.hpp"
3 #include "mock_event_manager.hpp"
4 #include "mock_terminus_manager.hpp"
5 #include "platform-mc/platform_manager.hpp"
6 #include "platform-mc/terminus_manager.hpp"
7 #include "test/test_instance_id.hpp"
8 #include "utils_test.hpp"
9
10 #include <libpldm/base.h>
11 #include <libpldm/entity.h>
12 #include <libpldm/platform.h>
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 new (getPDRRepositoryInfoResp.data()) pldm_msg,
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(new (getPdrResp.data()) pldm_msg,
304 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 new (getPdrAuxNameResp.data()) pldm_msg, sizeof(getPdrAuxNameResp));
340 EXPECT_EQ(rc, PLDM_SUCCESS);
341
342 // queue eventMessageBufferSize response(bufferSize=32)
343 const size_t eventMessageBufferSizeRespLen = 3;
344 std::array<uint8_t, sizeof(pldm_msg_hdr) + eventMessageBufferSizeRespLen>
345 eventMessageBufferSizeResp{0x0, 0x02, 0x0d, PLDM_SUCCESS, 32, 0};
346 rc = terminusManager.enqueueResponse(
347 new (eventMessageBufferSizeResp.data()) pldm_msg,
348 sizeof(eventMessageBufferSizeResp));
349 EXPECT_EQ(rc, PLDM_SUCCESS);
350
351 // queue eventMessageSupported response
352 const size_t eventMessageSupportedLen = 7;
353 PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES;
354 std::array<uint8_t, sizeof(pldm_msg_hdr) + eventMessageSupportedLen>
355 eventMessageSupportedResp{0x0, 0x02, 0x0c, PLDM_SUCCESS,
356 0x0, // synchronyConfiguration
357 0x06, // synchronyConfigurationSupported
358 3, // numberEventClassReturned
359 0x0, 0x5, 0xfa};
360 rc = terminusManager.enqueueResponse(
361 new (eventMessageSupportedResp.data()) pldm_msg,
362 sizeof(eventMessageSupportedResp));
363 EXPECT_EQ(rc, PLDM_SUCCESS);
364
365 terminusManager.updateMctpEndpointAvailability(
366 pldm::MctpInfo(10, "", "", 1), true);
367
368 // queue SetEventReceiver response
369 const size_t SetEventReceiverLen = 1;
370 PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES;
371 std::array<uint8_t, sizeof(pldm_msg_hdr) + SetEventReceiverLen>
372 SetEventReceiverResp{0x0, 0x02, 0x04, PLDM_SUCCESS};
373 rc = terminusManager.enqueueResponse(
374 new (SetEventReceiverResp.data()) pldm_msg,
375 sizeof(SetEventReceiverResp));
376 EXPECT_EQ(rc, PLDM_SUCCESS);
377
378 // should finish immediately
379 stdexec::sync_wait(platformManager.initTerminus());
380 // Run event loop for a few seconds to let sensor creation
381 // defer tasks be run. May increase time when sensor num is large
382 utils::runEventLoopForSeconds(event, 1);
383 EXPECT_EQ(true, terminus->initialized);
384 EXPECT_EQ(32, terminus->maxBufferSize);
385 EXPECT_EQ(0x06, terminus->synchronyConfigurationSupported.byte);
386 EXPECT_EQ(2, terminus->pdrs.size());
387 EXPECT_EQ(1, terminus->numericSensors.size());
388 }
389
TEST_F(EventManagerTest,updateAvailableState)390 TEST_F(EventManagerTest, updateAvailableState)
391 {
392 pldm_tid_t tid = 1;
393 eventManager.updateAvailableState(tid, true);
394 EXPECT_EQ(true, eventManager.getAvailableState(tid));
395 eventManager.updateAvailableState(tid, false);
396 EXPECT_EQ(false, eventManager.getAvailableState(tid));
397 eventManager.updateAvailableState(2, false);
398 EXPECT_EQ(false, eventManager.getAvailableState(tid));
399 }
400
TEST_F(EventManagerTest,pollForPlatformEventTaskMultipartTransferTest)401 TEST_F(EventManagerTest, pollForPlatformEventTaskMultipartTransferTest)
402 {
403 // Add terminus
404 auto mappedTid = terminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
405 auto tid = mappedTid.value();
406 termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
407 tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM, event);
408 auto terminus = termini[tid];
409
410 // queue pollForPlatformEventMessage first part response
411 const size_t pollForPlatformEventMessage1Len = 22;
412 std::array<uint8_t, sizeof(pldm_msg_hdr) + pollForPlatformEventMessage1Len>
413 pollForPlatformEventMessage1Resp{
414 0x0,
415 0x02,
416 0x0d,
417 PLDM_SUCCESS,
418 tid, // TID
419 0x1,
420 0x0, // eventID
421 0x1,
422 0x0,
423 0x0,
424 0x0, // nextDataTransferHandle
425 PLDM_PLATFORM_TRANSFER_START, // transferFlag = start
426 PLDM_CPER_EVENT, // eventClass
427 8,
428 0,
429 0,
430 0, // eventDataSize
431 0x01, // CPER event formatVersion= 0x01
432 1, // formatType = single CPER section(0x01)
433 10,
434 0, // eventDataLength = 10
435 1,
436 2,
437 3,
438 4 // eventData first part
439 };
440 auto rc = terminusManager.enqueueResponse(
441 new (pollForPlatformEventMessage1Resp.data()) pldm_msg,
442 sizeof(pollForPlatformEventMessage1Resp));
443 EXPECT_EQ(rc, PLDM_SUCCESS);
444
445 // queue pollForPlatformEventMessage last part response
446 const size_t pollForPlatformEventMessage2Len = 24;
447 std::array<uint8_t, sizeof(pldm_msg_hdr) + pollForPlatformEventMessage2Len>
448 pollForPlatformEventMessage2Resp{
449 0x0,
450 0x02,
451 0x0d,
452 PLDM_SUCCESS,
453 tid, // TID
454 0x1,
455 0x0, // eventID
456 0x2,
457 0x0,
458 0x0,
459 0x0, // nextDataTransferHandle
460 PLDM_PLATFORM_TRANSFER_END, // transferFlag = end
461 PLDM_CPER_EVENT, // eventClass
462 6,
463 0,
464 0,
465 0, // eventDataSize
466 5,
467 6,
468 7,
469 8,
470 9,
471 0, // eventData last part
472 0x46,
473 0x7f,
474 0x6a,
475 0x5d // crc32
476 };
477 rc = terminusManager.enqueueResponse(
478 new (pollForPlatformEventMessage2Resp.data()) pldm_msg,
479 sizeof(pollForPlatformEventMessage2Resp));
480 EXPECT_EQ(rc, PLDM_SUCCESS);
481
482 // queue pollForPlatformEventMessage Ack response
483 const size_t pollForPlatformEventMessage3Len = 4;
484 std::array<uint8_t, sizeof(pldm_msg_hdr) + pollForPlatformEventMessage3Len>
485 pollForPlatformEventMessage3Resp{
486 0x0, 0x02, 0x0d, PLDM_SUCCESS,
487 tid, // TID
488 0x0, 0x0 // eventID
489 };
490 rc = terminusManager.enqueueResponse(
491 new (pollForPlatformEventMessage3Resp.data()) pldm_msg,
492 sizeof(pollForPlatformEventMessage3Resp));
493 EXPECT_EQ(rc, PLDM_SUCCESS);
494
495 terminusManager.updateMctpEndpointAvailability(
496 pldm::MctpInfo(10, "", "", 1), true);
497
498 EXPECT_CALL(eventManager, processCperEvent(_, _, _, _))
499 .Times(1)
500 .WillRepeatedly(Return(1));
501
502 // start task to poll event from terminus
503 // should finish immediately
504 stdexec::sync_wait(eventManager.pollForPlatformEventTask(tid, 0x0000));
505 }
506