xref: /openbmc/phosphor-modbus/tests/test_events.cpp (revision 7184805ae4ede906935133e3e0f8ee2468bc781b)
1 #include "common/events.hpp"
2 
3 #include <xyz/openbmc_project/Logging/Create/aserver.hpp>
4 #include <xyz/openbmc_project/Logging/Entry/aserver.hpp>
5 #include <xyz/openbmc_project/Sensor/Threshold/event.hpp>
6 #include <xyz/openbmc_project/Sensor/event.hpp>
7 #include <xyz/openbmc_project/State/Leak/Detector/event.hpp>
8 #include <xyz/openbmc_project/State/Power/event.hpp>
9 #include <xyz/openbmc_project/State/SMC/event.hpp>
10 
11 #include <gtest/gtest.h>
12 
13 class TestEventServer;
14 class TestEventEntry;
15 
16 using namespace std::literals;
17 namespace EventIntf = phosphor::modbus::events;
18 using EventServerIntf =
19     sdbusplus::aserver::xyz::openbmc_project::logging::Create<TestEventServer>;
20 using EventEntryIntf =
21     sdbusplus::aserver::xyz::openbmc_project::logging::Entry<TestEventEntry>;
22 
23 namespace SensorThresholdErrorIntf =
24     sdbusplus::error::xyz::openbmc_project::sensor::Threshold;
25 namespace SensorThresholdEventIntf =
26     sdbusplus::event::xyz::openbmc_project::sensor::Threshold;
27 namespace SensorErrorIntf = sdbusplus::error::xyz::openbmc_project::Sensor;
28 namespace SensorEventIntf = sdbusplus::event::xyz::openbmc_project::Sensor;
29 namespace ControllerErrorIntf =
30     sdbusplus::error::xyz::openbmc_project::state::SMC;
31 namespace ControllerEventIntf =
32     sdbusplus::event::xyz::openbmc_project::state::SMC;
33 namespace PowerErrorIntf = sdbusplus::error::xyz::openbmc_project::state::Power;
34 namespace PowerEventIntf = sdbusplus::event::xyz::openbmc_project::state::Power;
35 namespace LeakErrorIntf =
36     sdbusplus::error::xyz::openbmc_project::state::leak::Detector;
37 namespace LeakEventIntf =
38     sdbusplus::event::xyz::openbmc_project::state::leak::Detector;
39 
40 // Test Event Class to mock the EventEntry
41 class TestEventEntry : public EventEntryIntf
42 {
43   public:
TestEventEntry(sdbusplus::async::context & ctx,const char * path)44     TestEventEntry(sdbusplus::async::context& ctx, const char* path) :
45         EventEntryIntf(ctx, path)
46     {}
47 
method_call(get_entry_t)48     auto method_call(get_entry_t)
49         -> sdbusplus::async::task<get_entry_t::return_type>
50     {
51         get_entry_t::return_type fd1 = 0;
52         co_return fd1;
53     }
54 };
55 
56 // Test Event Server Class to mock the EventServer
57 class TestEventServer : public EventServerIntf
58 {
59   public:
TestEventServer(sdbusplus::async::context & ctx,const char * path)60     TestEventServer(sdbusplus::async::context& ctx, const char* path) :
61         EventServerIntf(ctx, path), ctx(ctx)
62     {}
63 
method_call(create_t,auto message,auto,auto)64     auto method_call(create_t, auto message, auto, auto)
65         -> sdbusplus::async::task<create_t::return_type>
66 
67     {
68         static int cnt = 1;
69         cnt++;
70 
71         // Append the count to the object path to make it unique for each event
72         std::string objectPath =
73             "/xyz/openbmc_project/logging/entry/TestEvent1" +
74             std::to_string(cnt);
75         EXPECT_EQ(message, expectedEvent) << "Event name mismatch";
76 
77         eventEntries.emplace_back(
78             std::make_unique<TestEventEntry>(ctx, objectPath.c_str()));
79 
80         co_return sdbusplus::message::object_path(objectPath);
81     }
82 
method_call(create_with_ffdc_files_t,auto,auto,auto,auto)83     auto method_call(create_with_ffdc_files_t, auto, auto, auto, auto)
84         -> sdbusplus::async::task<create_with_ffdc_files_t::return_type>
85 
86     {
87         co_return;
88     }
89 
90     std::string expectedEvent = "";
91 
92   private:
93     sdbusplus::async::context& ctx;
94     std::vector<std::unique_ptr<TestEventEntry>> eventEntries;
95 };
96 
97 class EventsTest : public ::testing::Test
98 {
99   public:
100     enum class EventTestType
101     {
102         sensorWarningEvent,
103         sensorCriticalEvent,
104         sensorFailureEvent,
105         controllerFailureEvent,
106         powerFailureEvent,
107         leakWarningEvent,
108         leakCriticalEvent,
109     };
110 
111     static constexpr auto sensorObjectPath =
112         "/xyz/openbmc_project/sensors/OutletTemperature";
113     static constexpr auto serviceName = "xyz.openbmc_project.Logging";
114     static constexpr auto assert = true;
115     static constexpr auto deassert = false;
116     const char* objectPath = "/xyz/openbmc_project/logging";
117     sdbusplus::async::context ctx;
118     EventIntf::Events events;
119     TestEventServer eventServer;
120     sdbusplus::server::manager_t manager;
121 
EventsTest()122     EventsTest() :
123         events(ctx), eventServer(ctx, objectPath), manager(ctx, objectPath)
124     {
125         ctx.request_name(serviceName);
126     }
127 
~EventsTest()128     ~EventsTest() noexcept override {}
129 
testAssertEvent(EventTestType eventType)130     auto testAssertEvent(EventTestType eventType)
131         -> sdbusplus::async::task<void>
132     {
133         switch (eventType)
134         {
135             case EventTestType::sensorWarningEvent:
136                 eventServer.expectedEvent =
137                     SensorThresholdErrorIntf::ReadingWarning::errName;
138                 co_await events.generateSensorReadingEvent(
139                     sdbusplus::message::object_path(sensorObjectPath),
140                     EventIntf::EventLevel::warning, 60,
141                     EventIntf::SensorValueIntf::Unit::DegreesC, assert);
142                 break;
143             case EventTestType::sensorCriticalEvent:
144                 eventServer.expectedEvent =
145                     SensorThresholdErrorIntf::ReadingCritical::errName;
146                 co_await events.generateSensorReadingEvent(
147                     sdbusplus::message::object_path(sensorObjectPath),
148                     EventIntf::EventLevel::critical, 80,
149                     EventIntf::SensorValueIntf::Unit::DegreesC, assert);
150                 break;
151             case EventTestType::sensorFailureEvent:
152                 eventServer.expectedEvent =
153                     SensorErrorIntf::SensorFailure::errName;
154                 co_await events.generateSensorFailureEvent(
155                     sdbusplus::message::object_path(sensorObjectPath), assert);
156                 break;
157             case EventTestType::controllerFailureEvent:
158                 eventServer.expectedEvent =
159                     ControllerErrorIntf::SMCFailed::errName;
160                 co_await events.generateControllerFailureEvent(
161                     sdbusplus::message::object_path(sensorObjectPath), "",
162                     assert);
163                 break;
164             case EventTestType::powerFailureEvent:
165                 eventServer.expectedEvent =
166                     PowerErrorIntf::PowerRailFault::errName;
167                 co_await events.generatePowerFaultEvent(
168                     sdbusplus::message::object_path(sensorObjectPath), "",
169                     assert);
170                 break;
171             case EventTestType::leakWarningEvent:
172                 eventServer.expectedEvent =
173                     LeakErrorIntf::LeakDetectedWarning::errName;
174                 co_await events.generateLeakDetectedEvent(
175                     sdbusplus::message::object_path(sensorObjectPath),
176                     EventIntf::EventLevel::warning, assert);
177                 break;
178             case EventTestType::leakCriticalEvent:
179                 eventServer.expectedEvent =
180                     LeakErrorIntf::LeakDetectedCritical::errName;
181                 co_await events.generateLeakDetectedEvent(
182                     sdbusplus::message::object_path(sensorObjectPath),
183                     EventIntf::EventLevel::critical, assert);
184                 break;
185         }
186     }
187 
testDeassertEvent(EventTestType eventType)188     auto testDeassertEvent(EventTestType eventType)
189         -> sdbusplus::async::task<void>
190     {
191         switch (eventType)
192         {
193             case EventTestType::sensorWarningEvent:
194                 eventServer.expectedEvent =
195                     SensorThresholdEventIntf::SensorReadingNormalRange::errName;
196                 co_await events.generateSensorReadingEvent(
197                     sdbusplus::message::object_path(sensorObjectPath),
198                     EventIntf::EventLevel::warning, 40,
199                     EventIntf::SensorValueIntf::Unit::DegreesC, deassert);
200                 break;
201             case EventTestType::sensorCriticalEvent:
202                 eventServer.expectedEvent =
203                     SensorThresholdEventIntf::SensorReadingNormalRange::errName;
204                 co_await events.generateSensorReadingEvent(
205                     sdbusplus::message::object_path(sensorObjectPath),
206                     EventIntf::EventLevel::critical, 40,
207                     EventIntf::SensorValueIntf::Unit::DegreesC, deassert);
208                 break;
209             case EventTestType::sensorFailureEvent:
210                 eventServer.expectedEvent =
211                     SensorEventIntf::SensorRestored::errName;
212                 co_await events.generateSensorFailureEvent(
213                     sdbusplus::message::object_path(sensorObjectPath),
214                     deassert);
215                 break;
216             case EventTestType::controllerFailureEvent:
217                 eventServer.expectedEvent =
218                     ControllerEventIntf::SMCRestored::errName;
219                 co_await events.generateControllerFailureEvent(
220                     sdbusplus::message::object_path(sensorObjectPath), "",
221                     deassert);
222                 break;
223             case EventTestType::powerFailureEvent:
224                 eventServer.expectedEvent =
225                     PowerEventIntf::PowerRailFaultRecovered::errName;
226                 co_await events.generatePowerFaultEvent(
227                     sdbusplus::message::object_path(sensorObjectPath), "",
228                     deassert);
229                 break;
230             case EventTestType::leakWarningEvent:
231                 eventServer.expectedEvent =
232                     LeakEventIntf::LeakDetectedNormal::errName;
233                 co_await events.generateLeakDetectedEvent(
234                     sdbusplus::message::object_path(sensorObjectPath),
235                     EventIntf::EventLevel::warning, deassert);
236                 break;
237             case EventTestType::leakCriticalEvent:
238                 eventServer.expectedEvent =
239                     LeakEventIntf::LeakDetectedNormal::errName;
240                 co_await events.generateLeakDetectedEvent(
241                     sdbusplus::message::object_path(sensorObjectPath),
242                     EventIntf::EventLevel::critical, deassert);
243                 break;
244         }
245     }
246 
testEvents(EventTestType eventType)247     auto testEvents(EventTestType eventType) -> sdbusplus::async::task<void>
248     {
249         co_await testAssertEvent(eventType);
250 
251         co_await sdbusplus::async::sleep_for(ctx, 1s);
252 
253         co_await testDeassertEvent(eventType);
254 
255         ctx.request_stop();
256     }
257 };
258 
TEST_F(EventsTest,TestEventsSensorWarning)259 TEST_F(EventsTest, TestEventsSensorWarning)
260 {
261     ctx.spawn(testEvents(EventTestType::sensorWarningEvent));
262     ctx.run();
263 }
264 
TEST_F(EventsTest,TestEventsSensorCritical)265 TEST_F(EventsTest, TestEventsSensorCritical)
266 {
267     ctx.spawn(testEvents(EventTestType::sensorCriticalEvent));
268     ctx.run();
269 }
270 
TEST_F(EventsTest,TestEventsSensorFailure)271 TEST_F(EventsTest, TestEventsSensorFailure)
272 {
273     ctx.spawn(testEvents(EventTestType::sensorFailureEvent));
274     ctx.run();
275 }
276 
TEST_F(EventsTest,TestEventsControllerFailure)277 TEST_F(EventsTest, TestEventsControllerFailure)
278 {
279     ctx.spawn(testEvents(EventTestType::controllerFailureEvent));
280     ctx.run();
281 }
282 
TEST_F(EventsTest,TestEventsPowerFailure)283 TEST_F(EventsTest, TestEventsPowerFailure)
284 {
285     ctx.spawn(testEvents(EventTestType::powerFailureEvent));
286     ctx.run();
287 }
288 
TEST_F(EventsTest,TestEventsLeakWarning)289 TEST_F(EventsTest, TestEventsLeakWarning)
290 {
291     ctx.spawn(testEvents(EventTestType::leakWarningEvent));
292     ctx.run();
293 }
294 
TEST_F(EventsTest,TestEventsLeakCritical)295 TEST_F(EventsTest, TestEventsLeakCritical)
296 {
297     ctx.spawn(testEvents(EventTestType::leakCriticalEvent));
298     ctx.run();
299 }
300