blob: 1cffd2fac66cb6d474729bb977194ec3369e8f19 [file] [log] [blame]
#include "common/events.hpp"
#include <xyz/openbmc_project/Logging/Create/aserver.hpp>
#include <xyz/openbmc_project/Logging/Entry/aserver.hpp>
#include <xyz/openbmc_project/Sensor/Threshold/event.hpp>
#include <xyz/openbmc_project/Sensor/event.hpp>
#include <xyz/openbmc_project/State/Leak/Detector/event.hpp>
#include <xyz/openbmc_project/State/Power/event.hpp>
#include <xyz/openbmc_project/State/SMC/event.hpp>
#include <gtest/gtest.h>
class TestEventServer;
class TestEventEntry;
using namespace std::literals;
namespace EventIntf = phosphor::modbus::events;
using EventServerIntf =
sdbusplus::aserver::xyz::openbmc_project::logging::Create<TestEventServer>;
using EventEntryIntf =
sdbusplus::aserver::xyz::openbmc_project::logging::Entry<TestEventEntry>;
namespace SensorThresholdErrorIntf =
sdbusplus::error::xyz::openbmc_project::sensor::Threshold;
namespace SensorThresholdEventIntf =
sdbusplus::event::xyz::openbmc_project::sensor::Threshold;
namespace SensorErrorIntf = sdbusplus::error::xyz::openbmc_project::Sensor;
namespace SensorEventIntf = sdbusplus::event::xyz::openbmc_project::Sensor;
namespace ControllerErrorIntf =
sdbusplus::error::xyz::openbmc_project::state::SMC;
namespace ControllerEventIntf =
sdbusplus::event::xyz::openbmc_project::state::SMC;
namespace PowerErrorIntf = sdbusplus::error::xyz::openbmc_project::state::Power;
namespace PowerEventIntf = sdbusplus::event::xyz::openbmc_project::state::Power;
namespace LeakErrorIntf =
sdbusplus::error::xyz::openbmc_project::state::leak::Detector;
namespace LeakEventIntf =
sdbusplus::event::xyz::openbmc_project::state::leak::Detector;
// Test Event Class to mock the EventEntry
class TestEventEntry : public EventEntryIntf
{
public:
TestEventEntry(sdbusplus::async::context& ctx, const char* path) :
EventEntryIntf(ctx, path)
{}
auto method_call(get_entry_t)
-> sdbusplus::async::task<get_entry_t::return_type>
{
get_entry_t::return_type fd1 = 0;
co_return fd1;
}
};
// Test Event Server Class to mock the EventServer
class TestEventServer : public EventServerIntf
{
public:
TestEventServer(sdbusplus::async::context& ctx, const char* path) :
EventServerIntf(ctx, path), ctx(ctx)
{}
auto method_call(create_t, auto message, auto, auto)
-> sdbusplus::async::task<create_t::return_type>
{
static int cnt = 1;
cnt++;
// Append the count to the object path to make it unique for each event
std::string objectPath =
"/xyz/openbmc_project/logging/entry/TestEvent1" +
std::to_string(cnt);
EXPECT_EQ(message, expectedEvent) << "Event name mismatch";
eventEntries.emplace_back(
std::make_unique<TestEventEntry>(ctx, objectPath.c_str()));
co_return sdbusplus::message::object_path(objectPath);
}
auto method_call(create_with_ffdc_files_t, auto, auto, auto, auto)
-> sdbusplus::async::task<create_with_ffdc_files_t::return_type>
{
co_return;
}
std::string expectedEvent = "";
private:
sdbusplus::async::context& ctx;
std::vector<std::unique_ptr<TestEventEntry>> eventEntries;
};
class EventsTest : public ::testing::Test
{
public:
enum class EventTestType
{
sensorWarningEvent,
sensorCriticalEvent,
sensorFailureEvent,
controllerFailureEvent,
powerFailureEvent,
leakWarningEvent,
leakCriticalEvent,
};
static constexpr auto sensorObjectPath =
"/xyz/openbmc_project/sensors/OutletTemperature";
static constexpr auto serviceName = "xyz.openbmc_project.Logging";
static constexpr auto assert = true;
static constexpr auto deassert = false;
const char* objectPath = "/xyz/openbmc_project/logging";
sdbusplus::async::context ctx;
EventIntf::Events events;
TestEventServer eventServer;
sdbusplus::server::manager_t manager;
EventsTest() :
events(ctx), eventServer(ctx, objectPath), manager(ctx, objectPath)
{
ctx.request_name(serviceName);
}
~EventsTest() noexcept override {}
auto testAssertEvent(EventTestType eventType)
-> sdbusplus::async::task<void>
{
switch (eventType)
{
case EventTestType::sensorWarningEvent:
eventServer.expectedEvent =
SensorThresholdErrorIntf::ReadingWarning::errName;
co_await events.generateSensorReadingEvent(
sdbusplus::message::object_path(sensorObjectPath),
EventIntf::EventLevel::warning, 60,
EventIntf::SensorValueIntf::Unit::DegreesC, assert);
break;
case EventTestType::sensorCriticalEvent:
eventServer.expectedEvent =
SensorThresholdErrorIntf::ReadingCritical::errName;
co_await events.generateSensorReadingEvent(
sdbusplus::message::object_path(sensorObjectPath),
EventIntf::EventLevel::critical, 80,
EventIntf::SensorValueIntf::Unit::DegreesC, assert);
break;
case EventTestType::sensorFailureEvent:
eventServer.expectedEvent =
SensorErrorIntf::SensorFailure::errName;
co_await events.generateSensorFailureEvent(
sdbusplus::message::object_path(sensorObjectPath), assert);
break;
case EventTestType::controllerFailureEvent:
eventServer.expectedEvent =
ControllerErrorIntf::SMCFailed::errName;
co_await events.generateControllerFailureEvent(
sdbusplus::message::object_path(sensorObjectPath), "",
assert);
break;
case EventTestType::powerFailureEvent:
eventServer.expectedEvent =
PowerErrorIntf::PowerRailFault::errName;
co_await events.generatePowerFaultEvent(
sdbusplus::message::object_path(sensorObjectPath), "",
assert);
break;
case EventTestType::leakWarningEvent:
eventServer.expectedEvent =
LeakErrorIntf::LeakDetectedWarning::errName;
co_await events.generateLeakDetectedEvent(
sdbusplus::message::object_path(sensorObjectPath),
EventIntf::EventLevel::warning, assert);
break;
case EventTestType::leakCriticalEvent:
eventServer.expectedEvent =
LeakErrorIntf::LeakDetectedCritical::errName;
co_await events.generateLeakDetectedEvent(
sdbusplus::message::object_path(sensorObjectPath),
EventIntf::EventLevel::critical, assert);
break;
}
}
auto testDeassertEvent(EventTestType eventType)
-> sdbusplus::async::task<void>
{
switch (eventType)
{
case EventTestType::sensorWarningEvent:
eventServer.expectedEvent =
SensorThresholdEventIntf::SensorReadingNormalRange::errName;
co_await events.generateSensorReadingEvent(
sdbusplus::message::object_path(sensorObjectPath),
EventIntf::EventLevel::warning, 40,
EventIntf::SensorValueIntf::Unit::DegreesC, deassert);
break;
case EventTestType::sensorCriticalEvent:
eventServer.expectedEvent =
SensorThresholdEventIntf::SensorReadingNormalRange::errName;
co_await events.generateSensorReadingEvent(
sdbusplus::message::object_path(sensorObjectPath),
EventIntf::EventLevel::critical, 40,
EventIntf::SensorValueIntf::Unit::DegreesC, deassert);
break;
case EventTestType::sensorFailureEvent:
eventServer.expectedEvent =
SensorEventIntf::SensorRestored::errName;
co_await events.generateSensorFailureEvent(
sdbusplus::message::object_path(sensorObjectPath),
deassert);
break;
case EventTestType::controllerFailureEvent:
eventServer.expectedEvent =
ControllerEventIntf::SMCRestored::errName;
co_await events.generateControllerFailureEvent(
sdbusplus::message::object_path(sensorObjectPath), "",
deassert);
break;
case EventTestType::powerFailureEvent:
eventServer.expectedEvent =
PowerEventIntf::PowerRailFaultRecovered::errName;
co_await events.generatePowerFaultEvent(
sdbusplus::message::object_path(sensorObjectPath), "",
deassert);
break;
case EventTestType::leakWarningEvent:
eventServer.expectedEvent =
LeakEventIntf::LeakDetectedNormal::errName;
co_await events.generateLeakDetectedEvent(
sdbusplus::message::object_path(sensorObjectPath),
EventIntf::EventLevel::warning, deassert);
break;
case EventTestType::leakCriticalEvent:
eventServer.expectedEvent =
LeakEventIntf::LeakDetectedNormal::errName;
co_await events.generateLeakDetectedEvent(
sdbusplus::message::object_path(sensorObjectPath),
EventIntf::EventLevel::critical, deassert);
break;
}
}
auto testEvents(EventTestType eventType) -> sdbusplus::async::task<void>
{
co_await testAssertEvent(eventType);
co_await sdbusplus::async::sleep_for(ctx, 1s);
co_await testDeassertEvent(eventType);
ctx.request_stop();
}
};
TEST_F(EventsTest, TestEventsSensorWarning)
{
ctx.spawn(testEvents(EventTestType::sensorWarningEvent));
ctx.run();
}
TEST_F(EventsTest, TestEventsSensorCritical)
{
ctx.spawn(testEvents(EventTestType::sensorCriticalEvent));
ctx.run();
}
TEST_F(EventsTest, TestEventsSensorFailure)
{
ctx.spawn(testEvents(EventTestType::sensorFailureEvent));
ctx.run();
}
TEST_F(EventsTest, TestEventsControllerFailure)
{
ctx.spawn(testEvents(EventTestType::controllerFailureEvent));
ctx.run();
}
TEST_F(EventsTest, TestEventsPowerFailure)
{
ctx.spawn(testEvents(EventTestType::powerFailureEvent));
ctx.run();
}
TEST_F(EventsTest, TestEventsLeakWarning)
{
ctx.spawn(testEvents(EventTestType::leakWarningEvent));
ctx.run();
}
TEST_F(EventsTest, TestEventsLeakCritical)
{
ctx.spawn(testEvents(EventTestType::leakCriticalEvent));
ctx.run();
}