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 
13 #include <gtest/gtest.h>
14 
15 using ::testing::_;
16 using ::testing::Return;
17 
18 class EventManagerTest : public testing::Test
19 {
20   protected:
21     EventManagerTest() :
22         bus(pldm::utils::DBusHandler::getBus()),
23         event(sdeventplus::Event::get_default()), instanceIdDb(),
24         reqHandler(pldmTransport, event, instanceIdDb, false,
25                    std::chrono::seconds(1), 2, std::chrono::milliseconds(100)),
26         terminusManager(event, reqHandler, instanceIdDb, termini, nullptr),
27         eventManager(terminusManager, termini),
28         platformManager(terminusManager, termini)
29     {}
30 
31     PldmTransport* pldmTransport = nullptr;
32     sdbusplus::bus::bus& bus;
33     sdeventplus::Event event;
34     TestInstanceIdDb instanceIdDb;
35     pldm::requester::Handler<pldm::requester::Request> reqHandler;
36     pldm::platform_mc::MockTerminusManager terminusManager;
37     pldm::platform_mc::MockEventManager eventManager;
38     pldm::platform_mc::PlatformManager platformManager;
39     pldm::platform_mc::TerminiMapper termini{};
40 };
41 
42 TEST_F(EventManagerTest, processNumericSensorEventTest)
43 {
44 #define SENSOR_READING 50
45 #define WARNING_HIGH 45
46     pldm_tid_t tid = 1;
47     termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
48         tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM);
49     std::vector<uint8_t> pdr1{
50         0x1,
51         0x0,
52         0x0,
53         0x0,                         // record handle
54         0x1,                         // PDRHeaderVersion
55         PLDM_NUMERIC_SENSOR_PDR,     // PDRType
56         0x0,
57         0x0,                         // recordChangeNumber
58         PLDM_PDR_NUMERIC_SENSOR_PDR_MIN_LENGTH,
59         0,                           // dataLength
60         0,
61         0,                           // PLDMTerminusHandle
62         0x1,
63         0x0,                         // sensorID=1
64         PLDM_ENTITY_POWER_SUPPLY,
65         0,                           // entityType=Power Supply(120)
66         1,
67         0,                           // entityInstanceNumber
68         1,
69         0,                           // containerID=1
70         PLDM_NO_INIT,                // sensorInit
71         false,                       // sensorAuxiliaryNamesPDR
72         PLDM_SENSOR_UNIT_DEGRESS_C,  // baseUint(2)=degrees C
73         0,                           // unitModifier = 0
74         0,                           // rateUnit
75         0,                           // baseOEMUnitHandle
76         0,                           // auxUnit
77         0,                           // auxUnitModifier
78         0,                           // auxRateUnit
79         0,                           // rel
80         0,                           // auxOEMUnitHandle
81         true,                        // isLinear
82         PLDM_SENSOR_DATA_SIZE_UINT8, // sensorDataSize
83         0,
84         0,
85         0x80,
86         0x3f, // resolution=1.0
87         0,
88         0,
89         0,
90         0,    // offset=0
91         0,
92         0,    // accuracy
93         0,    // plusTolerance
94         0,    // minusTolerance
95         2,    // hysteresis = 2
96         0x1b, // supportedThresholds
97         0,    // thresholdAndHysteresisVolatility
98         0,
99         0,
100         0x80,
101         0x3f, // stateTransistionInterval=1.0
102         0,
103         0,
104         0x80,
105         0x3f,                          // updateInverval=1.0
106         255,                           // maxReadable
107         0,                             // minReadable
108         PLDM_RANGE_FIELD_FORMAT_UINT8, // rangeFieldFormat
109         0x18,                          // rangeFieldsupport
110         0,                             // nominalValue
111         0,                             // normalMax
112         0,                             // normalMin
113         WARNING_HIGH,                  // warningHigh
114         20,                            // warningLow
115         60,                            // criticalHigh
116         10,                            // criticalLow
117         0,                             // fatalHigh
118         0                              // fatalLow
119     };
120 
121     std::vector<uint8_t> pdr2{
122         0x1, 0x0, 0x0,
123         0x0,                             // record handle
124         0x1,                             // PDRHeaderVersion
125         PLDM_ENTITY_AUXILIARY_NAMES_PDR, // PDRType
126         0x1,
127         0x0,                             // recordChangeNumber
128         0x11,
129         0,                               // dataLength
130         /* Entity Auxiliary Names PDR Data*/
131         3,
132         0x80, // entityType system software
133         0x1,
134         0x0,  // Entity instance number =1
135         0,
136         0,    // Overal system
137         0,    // shared Name Count one name only
138         01,   // nameStringCount
139         0x65, 0x6e, 0x00,
140         0x00, // Language Tag "en"
141         0x53, 0x00, 0x30, 0x00,
142         0x00  // Entity Name "S0"
143     };
144 
145     // add dummy numeric sensor
146     termini[tid]->pdrs.emplace_back(pdr1);
147     termini[tid]->pdrs.emplace_back(pdr2);
148     termini[tid]->parseTerminusPDRs();
149     EXPECT_EQ(1, termini[tid]->numericSensors.size());
150 
151     uint8_t platformEventStatus = 0;
152 
153     std::vector<uint8_t> eventData{
154         0x1,
155         0x0, // sensor id
156         PLDM_NUMERIC_SENSOR_STATE,
157         PLDM_SENSOR_UPPERWARNING,
158         PLDM_SENSOR_NORMAL,
159         PLDM_SENSOR_DATA_SIZE_UINT8,
160         SENSOR_READING};
161     auto rc = eventManager.handlePlatformEvent(
162         tid, 0x00, PLDM_SENSOR_EVENT, eventData.data(), eventData.size());
163     EXPECT_EQ(PLDM_SUCCESS, rc);
164     EXPECT_EQ(PLDM_EVENT_NO_LOGGING, platformEventStatus);
165 }
166 
167 TEST_F(EventManagerTest, SetEventReceiverTest)
168 {
169     // Add terminus
170     auto mappedTid = terminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
171     auto tid = mappedTid.value();
172     termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
173         tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM);
174     auto terminus = termini[tid];
175 
176     /* Set supported command by terminus */
177     auto size = PLDM_MAX_TYPES * (PLDM_MAX_CMDS_PER_TYPE / 8);
178     std::vector<uint8_t> pldmCmds(size);
179     uint8_t type = PLDM_PLATFORM;
180     uint8_t cmd = PLDM_GET_PDR_REPOSITORY_INFO;
181     auto idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
182     pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
183     cmd = PLDM_GET_PDR;
184     idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
185     pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
186     cmd = PLDM_EVENT_MESSAGE_SUPPORTED;
187     idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
188     pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
189     cmd = PLDM_EVENT_MESSAGE_BUFFER_SIZE;
190     idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
191     pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
192     cmd = PLDM_SET_EVENT_RECEIVER;
193     idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
194     pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
195     termini[tid]->setSupportedCommands(pldmCmds);
196 
197     EXPECT_EQ(true, termini[tid]->doesSupportCommand(PLDM_PLATFORM,
198                                                      PLDM_SET_EVENT_RECEIVER));
199     EXPECT_EQ(true, termini[tid]->doesSupportCommand(
200                         PLDM_PLATFORM, PLDM_EVENT_MESSAGE_BUFFER_SIZE));
201     EXPECT_EQ(true, termini[tid]->doesSupportCommand(
202                         PLDM_PLATFORM, PLDM_EVENT_MESSAGE_SUPPORTED));
203     EXPECT_EQ(true,
204               termini[tid]->doesSupportCommand(PLDM_PLATFORM, PLDM_GET_PDR));
205     EXPECT_EQ(true, termini[tid]->doesSupportCommand(
206                         PLDM_PLATFORM, PLDM_GET_PDR_REPOSITORY_INFO));
207 
208     // queue getPDRRepositoryInfo response
209     const size_t getPDRRepositoryInfoLen =
210         PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES;
211     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPDRRepositoryInfoLen>
212         getPDRRepositoryInfoResp{
213             0x0, 0x02, 0x50, PLDM_SUCCESS,
214             0x0,                                     // repositoryState
215             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, 0x0,
216             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, // updateTime
217             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, 0x0,
218             0x0, 0x0,  0x0,  0x0,          0x0, 0x0, // OEMUpdateTime
219             2,   0x0,  0x0,  0x0,                    // recordCount
220             0x0, 0x1,  0x0,  0x0,                    // repositorySize
221             59,  0x0,  0x0,  0x0,                    // largestRecordSize
222             0x0 // dataTransferHandleTimeout
223         };
224     auto rc = terminusManager.enqueueResponse(
225         reinterpret_cast<pldm_msg*>(getPDRRepositoryInfoResp.data()),
226         sizeof(getPDRRepositoryInfoResp));
227     EXPECT_EQ(rc, PLDM_SUCCESS);
228 
229     // queue getPDR responses
230     const size_t getPdrRespLen = 81;
231     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPdrRespLen> getPdrResp{
232         0x0, 0x02, 0x51, PLDM_SUCCESS, 0x1, 0x0, 0x0, 0x0, // nextRecordHandle
233         0x0, 0x0, 0x0, 0x0, // nextDataTransferHandle
234         0x5,                // transferFlag
235         69, 0x0,            // responseCount
236         // numeric Sensor PDR
237         0x0, 0x0, 0x0,
238         0x0,                     // record handle
239         0x1,                     // PDRHeaderVersion
240         PLDM_NUMERIC_SENSOR_PDR, // PDRType
241         0x0,
242         0x0,                     // recordChangeNumber
243         PLDM_PDR_NUMERIC_SENSOR_PDR_FIXED_LENGTH +
244             PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_SENSOR_DATA_SIZE_MIN_LENGTH +
245             PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_RANGE_FIELD_MIN_LENGTH,
246         0,                             // dataLength
247         0,
248         0,                             // PLDMTerminusHandle
249         0x1,
250         0x0,                           // sensorID=1
251         120,
252         0,                             // entityType=Power Supply(120)
253         1,
254         0,                             // entityInstanceNumber
255         0x1,
256         0x0,                           // containerID=1
257         PLDM_NO_INIT,                  // sensorInit
258         false,                         // sensorAuxiliaryNamesPDR
259         PLDM_SENSOR_UNIT_DEGRESS_C,    // baseUint(2)=degrees C
260         1,                             // unitModifier = 1
261         0,                             // rateUnit
262         0,                             // baseOEMUnitHandle
263         0,                             // auxUnit
264         0,                             // auxUnitModifier
265         0,                             // auxRateUnit
266         0,                             // rel
267         0,                             // auxOEMUnitHandle
268         true,                          // isLinear
269         PLDM_SENSOR_DATA_SIZE_UINT8,   // sensorDataSize
270         0, 0, 0xc0,
271         0x3f,                          // resolution=1.5
272         0, 0, 0x80,
273         0x3f,                          // offset=1.0
274         0,
275         0,                             // accuracy
276         0,                             // plusTolerance
277         0,                             // minusTolerance
278         2,                             // hysteresis
279         0,                             // supportedThresholds
280         0,                             // thresholdAndHysteresisVolatility
281         0, 0, 0x80,
282         0x3f,                          // stateTransistionInterval=1.0
283         0, 0, 0x80,
284         0x3f,                          // updateInverval=1.0
285         255,                           // maxReadable
286         0,                             // minReadable
287         PLDM_RANGE_FIELD_FORMAT_UINT8, // rangeFieldFormat
288         0,                             // rangeFieldsupport
289         0,                             // nominalValue
290         0,                             // normalMax
291         0,                             // normalMin
292         0,                             // warningHigh
293         0,                             // warningLow
294         0,                             // criticalHigh
295         0,                             // criticalLow
296         0,                             // fatalHigh
297         0                              // fatalLow
298     };
299     rc = terminusManager.enqueueResponse(
300         reinterpret_cast<pldm_msg*>(getPdrResp.data()), sizeof(getPdrResp));
301     EXPECT_EQ(rc, PLDM_SUCCESS);
302 
303     const size_t getPdrAuxNameRespLen = 39;
304     std::array<uint8_t, sizeof(pldm_msg_hdr) + getPdrAuxNameRespLen>
305         getPdrAuxNameResp{
306             0x0, 0x02, 0x51, PLDM_SUCCESS, 0x0, 0x0, 0x0,
307             0x0,                // nextRecordHandle
308             0x0, 0x0, 0x0, 0x0, // nextDataTransferHandle
309             0x5,                // transferFlag
310             0x1b, 0x0,          // responseCount
311             // Common PDR Header
312             0x1, 0x0, 0x0,
313             0x0,                             // record handle
314             0x1,                             // PDRHeaderVersion
315             PLDM_ENTITY_AUXILIARY_NAMES_PDR, // PDRType
316             0x1,
317             0x0,                             // recordChangeNumber
318             0x11,
319             0,                               // dataLength
320             /* Entity Auxiliary Names PDR Data*/
321             3,
322             0x80, // entityType system software
323             0x1,
324             0x0,  // Entity instance number =1
325             0,
326             0,    // Overal system
327             0,    // shared Name Count one name only
328             01,   // nameStringCount
329             0x65, 0x6e, 0x00,
330             0x00, // Language Tag "en"
331             0x53, 0x00, 0x30, 0x00,
332             0x00  // Entity Name "S0"
333         };
334     rc = terminusManager.enqueueResponse(
335         reinterpret_cast<pldm_msg*>(getPdrAuxNameResp.data()),
336         sizeof(getPdrAuxNameResp));
337     EXPECT_EQ(rc, PLDM_SUCCESS);
338 
339     // queue eventMessageBufferSize response(bufferSize=32)
340     const size_t eventMessageBufferSizeRespLen = 3;
341     std::array<uint8_t, sizeof(pldm_msg_hdr) + eventMessageBufferSizeRespLen>
342         eventMessageBufferSizeResp{0x0, 0x02, 0x0d, PLDM_SUCCESS, 32, 0};
343     rc = terminusManager.enqueueResponse(
344         reinterpret_cast<pldm_msg*>(eventMessageBufferSizeResp.data()),
345         sizeof(eventMessageBufferSizeResp));
346     EXPECT_EQ(rc, PLDM_SUCCESS);
347 
348     // queue eventMessageSupported response
349     const size_t eventMessageSupportedLen = 7;
350     PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES;
351     std::array<uint8_t, sizeof(pldm_msg_hdr) + eventMessageSupportedLen>
352         eventMessageSupportedResp{0x0,  0x02, 0x0c, PLDM_SUCCESS,
353                                   0x0,  // synchronyConfiguration
354                                   0x06, // synchronyConfigurationSupported
355                                   3,    // numberEventClassReturned
356                                   0x0,  0x5,  0xfa};
357     rc = terminusManager.enqueueResponse(
358         reinterpret_cast<pldm_msg*>(eventMessageSupportedResp.data()),
359         sizeof(eventMessageSupportedResp));
360     EXPECT_EQ(rc, PLDM_SUCCESS);
361 
362     // queue SetEventReceiver response
363     const size_t SetEventReceiverLen = 1;
364     PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES;
365     std::array<uint8_t, sizeof(pldm_msg_hdr) + SetEventReceiverLen>
366         SetEventReceiverResp{0x0, 0x02, 0x04, PLDM_SUCCESS};
367     rc = terminusManager.enqueueResponse(
368         reinterpret_cast<pldm_msg*>(SetEventReceiverResp.data()),
369         sizeof(SetEventReceiverResp));
370     EXPECT_EQ(rc, PLDM_SUCCESS);
371 
372     // should finish immediately
373     stdexec::sync_wait(platformManager.initTerminus());
374     EXPECT_EQ(true, terminus->initialized);
375     EXPECT_EQ(32, terminus->maxBufferSize);
376     EXPECT_EQ(0x06, terminus->synchronyConfigurationSupported.byte);
377     EXPECT_EQ(2, terminus->pdrs.size());
378     EXPECT_EQ(1, terminus->numericSensors.size());
379 }
380 
381 TEST_F(EventManagerTest, updateAvailableState)
382 {
383     pldm_tid_t tid = 1;
384     eventManager.updateAvailableState(tid, true);
385     EXPECT_EQ(true, eventManager.getAvailableState(tid));
386     eventManager.updateAvailableState(tid, false);
387     EXPECT_EQ(false, eventManager.getAvailableState(tid));
388     eventManager.updateAvailableState(2, false);
389     EXPECT_EQ(false, eventManager.getAvailableState(tid));
390 }
391