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