1*acfdd55fSJagpal Singh Gill #include "common/events.hpp"
2*acfdd55fSJagpal Singh Gill #include "device/device_factory.hpp"
3*acfdd55fSJagpal Singh Gill #include "modbus_server_tester.hpp"
4*acfdd55fSJagpal Singh Gill #include "port/base_port.hpp"
5*acfdd55fSJagpal Singh Gill #include "test_base.hpp"
6*acfdd55fSJagpal Singh Gill
7*acfdd55fSJagpal Singh Gill #include <xyz/openbmc_project/Logging/Create/aserver.hpp>
8*acfdd55fSJagpal Singh Gill #include <xyz/openbmc_project/Logging/Entry/aserver.hpp>
9*acfdd55fSJagpal Singh Gill #include <xyz/openbmc_project/Sensor/Threshold/Critical/client.hpp>
10*acfdd55fSJagpal Singh Gill #include <xyz/openbmc_project/Sensor/Value/client.hpp>
11*acfdd55fSJagpal Singh Gill #include <xyz/openbmc_project/State/Decorator/Availability/client.hpp>
12*acfdd55fSJagpal Singh Gill #include <xyz/openbmc_project/State/Decorator/OperationalStatus/client.hpp>
13*acfdd55fSJagpal Singh Gill
14*acfdd55fSJagpal Singh Gill #include <cmath>
15*acfdd55fSJagpal Singh Gill #include <string>
16*acfdd55fSJagpal Singh Gill
17*acfdd55fSJagpal Singh Gill #include <gtest/gtest.h>
18*acfdd55fSJagpal Singh Gill
19*acfdd55fSJagpal Singh Gill using namespace std::literals;
20*acfdd55fSJagpal Singh Gill using namespace testing;
21*acfdd55fSJagpal Singh Gill using SensorValueIntf =
22*acfdd55fSJagpal Singh Gill sdbusplus::client::xyz::openbmc_project::sensor::Value<>;
23*acfdd55fSJagpal Singh Gill using OperationalStatusIntf = sdbusplus::client::xyz::openbmc_project::state::
24*acfdd55fSJagpal Singh Gill decorator::OperationalStatus<>;
25*acfdd55fSJagpal Singh Gill using AvailabilityIntf =
26*acfdd55fSJagpal Singh Gill sdbusplus::client::xyz::openbmc_project::state::decorator::Availability<>;
27*acfdd55fSJagpal Singh Gill using ThresholdCriticalIntf =
28*acfdd55fSJagpal Singh Gill sdbusplus::client::xyz::openbmc_project::sensor::threshold::Critical<>;
29*acfdd55fSJagpal Singh Gill
30*acfdd55fSJagpal Singh Gill class TestEventServer;
31*acfdd55fSJagpal Singh Gill class TestEventEntry;
32*acfdd55fSJagpal Singh Gill
33*acfdd55fSJagpal Singh Gill using EventServerIntf =
34*acfdd55fSJagpal Singh Gill sdbusplus::aserver::xyz::openbmc_project::logging::Create<TestEventServer>;
35*acfdd55fSJagpal Singh Gill using EventEntryIntf =
36*acfdd55fSJagpal Singh Gill sdbusplus::aserver::xyz::openbmc_project::logging::Entry<TestEventEntry>;
37*acfdd55fSJagpal Singh Gill
38*acfdd55fSJagpal Singh Gill namespace ModbusIntf = phosphor::modbus::rtu;
39*acfdd55fSJagpal Singh Gill namespace PortIntf = phosphor::modbus::rtu::port;
40*acfdd55fSJagpal Singh Gill namespace PortConfigIntf = PortIntf::config;
41*acfdd55fSJagpal Singh Gill namespace DeviceIntf = phosphor::modbus::rtu::device;
42*acfdd55fSJagpal Singh Gill namespace DeviceConfigIntf = DeviceIntf::config;
43*acfdd55fSJagpal Singh Gill namespace EventIntf = phosphor::modbus::events;
44*acfdd55fSJagpal Singh Gill
45*acfdd55fSJagpal Singh Gill class MockPort : public PortIntf::BasePort
46*acfdd55fSJagpal Singh Gill {
47*acfdd55fSJagpal Singh Gill public:
MockPort(sdbusplus::async::context & ctx,const PortConfigIntf::Config & config,const std::string & devicePath)48*acfdd55fSJagpal Singh Gill MockPort(sdbusplus::async::context& ctx,
49*acfdd55fSJagpal Singh Gill const PortConfigIntf::Config& config,
50*acfdd55fSJagpal Singh Gill const std::string& devicePath) : BasePort(ctx, config, devicePath)
51*acfdd55fSJagpal Singh Gill {}
52*acfdd55fSJagpal Singh Gill };
53*acfdd55fSJagpal Singh Gill
54*acfdd55fSJagpal Singh Gill // Test Event Class to mock the EventEntry
55*acfdd55fSJagpal Singh Gill class TestEventEntry : public EventEntryIntf
56*acfdd55fSJagpal Singh Gill {
57*acfdd55fSJagpal Singh Gill public:
TestEventEntry(sdbusplus::async::context & ctx,const char * path)58*acfdd55fSJagpal Singh Gill TestEventEntry(sdbusplus::async::context& ctx, const char* path) :
59*acfdd55fSJagpal Singh Gill EventEntryIntf(ctx, path)
60*acfdd55fSJagpal Singh Gill {}
61*acfdd55fSJagpal Singh Gill
method_call(get_entry_t)62*acfdd55fSJagpal Singh Gill auto method_call(get_entry_t)
63*acfdd55fSJagpal Singh Gill -> sdbusplus::async::task<get_entry_t::return_type>
64*acfdd55fSJagpal Singh Gill {
65*acfdd55fSJagpal Singh Gill get_entry_t::return_type fd1 = 0;
66*acfdd55fSJagpal Singh Gill co_return fd1;
67*acfdd55fSJagpal Singh Gill }
68*acfdd55fSJagpal Singh Gill };
69*acfdd55fSJagpal Singh Gill
70*acfdd55fSJagpal Singh Gill // Test Event Server Class to mock the EventServer
71*acfdd55fSJagpal Singh Gill class TestEventServer : public EventServerIntf
72*acfdd55fSJagpal Singh Gill {
73*acfdd55fSJagpal Singh Gill public:
TestEventServer(sdbusplus::async::context & ctx,const char * path)74*acfdd55fSJagpal Singh Gill TestEventServer(sdbusplus::async::context& ctx, const char* path) :
75*acfdd55fSJagpal Singh Gill EventServerIntf(ctx, path), ctx(ctx)
76*acfdd55fSJagpal Singh Gill {}
77*acfdd55fSJagpal Singh Gill
method_call(create_t,auto message,auto,auto)78*acfdd55fSJagpal Singh Gill auto method_call(create_t, auto message, auto, auto)
79*acfdd55fSJagpal Singh Gill -> sdbusplus::async::task<create_t::return_type>
80*acfdd55fSJagpal Singh Gill
81*acfdd55fSJagpal Singh Gill {
82*acfdd55fSJagpal Singh Gill static int cnt = 100;
83*acfdd55fSJagpal Singh Gill cnt++;
84*acfdd55fSJagpal Singh Gill
85*acfdd55fSJagpal Singh Gill // Append the count to the object path to make it unique for each event
86*acfdd55fSJagpal Singh Gill std::string objectPath =
87*acfdd55fSJagpal Singh Gill "/xyz/openbmc_project/logging/entry/TestEvent" +
88*acfdd55fSJagpal Singh Gill std::to_string(cnt);
89*acfdd55fSJagpal Singh Gill EXPECT_EQ(message, expectedEvent) << "Event name mismatch";
90*acfdd55fSJagpal Singh Gill
91*acfdd55fSJagpal Singh Gill eventEntries.emplace_back(
92*acfdd55fSJagpal Singh Gill std::make_unique<TestEventEntry>(ctx, objectPath.c_str()));
93*acfdd55fSJagpal Singh Gill
94*acfdd55fSJagpal Singh Gill co_return sdbusplus::message::object_path(objectPath);
95*acfdd55fSJagpal Singh Gill }
96*acfdd55fSJagpal Singh Gill
method_call(create_with_ffdc_files_t,auto,auto,auto,auto)97*acfdd55fSJagpal Singh Gill auto method_call(create_with_ffdc_files_t, auto, auto, auto, auto)
98*acfdd55fSJagpal Singh Gill -> sdbusplus::async::task<create_with_ffdc_files_t::return_type>
99*acfdd55fSJagpal Singh Gill
100*acfdd55fSJagpal Singh Gill {
101*acfdd55fSJagpal Singh Gill co_return;
102*acfdd55fSJagpal Singh Gill }
103*acfdd55fSJagpal Singh Gill
104*acfdd55fSJagpal Singh Gill std::string expectedEvent;
105*acfdd55fSJagpal Singh Gill
106*acfdd55fSJagpal Singh Gill private:
107*acfdd55fSJagpal Singh Gill sdbusplus::async::context& ctx;
108*acfdd55fSJagpal Singh Gill std::vector<std::unique_ptr<TestEventEntry>> eventEntries;
109*acfdd55fSJagpal Singh Gill };
110*acfdd55fSJagpal Singh Gill
111*acfdd55fSJagpal Singh Gill class DeviceEventsTest : public BaseTest
112*acfdd55fSJagpal Singh Gill {
113*acfdd55fSJagpal Singh Gill public:
114*acfdd55fSJagpal Singh Gill PortConfigIntf::Config portConfig;
115*acfdd55fSJagpal Singh Gill static constexpr const char* clientDevicePath =
116*acfdd55fSJagpal Singh Gill "/tmp/ttyDeviceEventsTestPort0";
117*acfdd55fSJagpal Singh Gill static constexpr const char* serverDevicePath =
118*acfdd55fSJagpal Singh Gill "/tmp/ttyDeviceEventsTestPort1";
119*acfdd55fSJagpal Singh Gill static constexpr auto portName = "TestPort0";
120*acfdd55fSJagpal Singh Gill std::string deviceName;
121*acfdd55fSJagpal Singh Gill std::string fullSensorName;
122*acfdd55fSJagpal Singh Gill std::string objectPath;
123*acfdd55fSJagpal Singh Gill const char* loggingObjectPath = "/xyz/openbmc_project/logging";
124*acfdd55fSJagpal Singh Gill static constexpr auto serviceName = "xyz.openbmc_project.Logging";
125*acfdd55fSJagpal Singh Gill static constexpr auto sensorName = "OutletTemperature";
126*acfdd55fSJagpal Singh Gill TestEventServer eventServer;
127*acfdd55fSJagpal Singh Gill sdbusplus::server::manager_t manager;
128*acfdd55fSJagpal Singh Gill
DeviceEventsTest()129*acfdd55fSJagpal Singh Gill DeviceEventsTest() :
130*acfdd55fSJagpal Singh Gill BaseTest(clientDevicePath, serverDevicePath, serviceName),
131*acfdd55fSJagpal Singh Gill eventServer(ctx, loggingObjectPath), manager(ctx, loggingObjectPath)
132*acfdd55fSJagpal Singh Gill {
133*acfdd55fSJagpal Singh Gill portConfig.name = portName;
134*acfdd55fSJagpal Singh Gill portConfig.portMode = PortConfigIntf::PortMode::rs485;
135*acfdd55fSJagpal Singh Gill portConfig.baudRate = baudRate;
136*acfdd55fSJagpal Singh Gill portConfig.rtsDelay = 1;
137*acfdd55fSJagpal Singh Gill
138*acfdd55fSJagpal Singh Gill deviceName = std::format("ResorviorPumpUnit_{}_{}",
139*acfdd55fSJagpal Singh Gill TestIntf::testDeviceAddress, portName);
140*acfdd55fSJagpal Singh Gill
141*acfdd55fSJagpal Singh Gill fullSensorName = std::format("{}_{}", deviceName, sensorName);
142*acfdd55fSJagpal Singh Gill
143*acfdd55fSJagpal Singh Gill objectPath = std::format(
144*acfdd55fSJagpal Singh Gill "{}/{}/{}", SensorValueIntf::namespace_path::value,
145*acfdd55fSJagpal Singh Gill SensorValueIntf::namespace_path::temperature, fullSensorName);
146*acfdd55fSJagpal Singh Gill }
147*acfdd55fSJagpal Singh Gill
verifyValue(bool currentValue,bool expectedValue,const std::string & failureStr)148*acfdd55fSJagpal Singh Gill auto verifyValue(bool currentValue, bool expectedValue,
149*acfdd55fSJagpal Singh Gill const std::string& failureStr) -> void
150*acfdd55fSJagpal Singh Gill {
151*acfdd55fSJagpal Singh Gill EXPECT_EQ(currentValue, expectedValue) << failureStr;
152*acfdd55fSJagpal Singh Gill }
153*acfdd55fSJagpal Singh Gill
verifyValue(double currentValue,double expectedValue,const std::string & failureStr)154*acfdd55fSJagpal Singh Gill auto verifyValue(double currentValue, double expectedValue,
155*acfdd55fSJagpal Singh Gill const std::string& failureStr) -> void
156*acfdd55fSJagpal Singh Gill {
157*acfdd55fSJagpal Singh Gill EXPECT_EQ(currentValue, expectedValue) << failureStr;
158*acfdd55fSJagpal Singh Gill }
159*acfdd55fSJagpal Singh Gill
verifyResult(SensorValueIntf::properties_t & properties,OperationalStatusIntf::properties_t & operationalProperties,AvailabilityIntf::properties_t & availabilityProperties,ThresholdCriticalIntf::properties_t & thresholdProperties,double expectedValue,SensorValueIntf::Unit expectedUnit)160*acfdd55fSJagpal Singh Gill auto verifyResult(
161*acfdd55fSJagpal Singh Gill SensorValueIntf::properties_t& properties,
162*acfdd55fSJagpal Singh Gill OperationalStatusIntf::properties_t& operationalProperties,
163*acfdd55fSJagpal Singh Gill AvailabilityIntf::properties_t& availabilityProperties,
164*acfdd55fSJagpal Singh Gill ThresholdCriticalIntf::properties_t& thresholdProperties,
165*acfdd55fSJagpal Singh Gill double expectedValue, SensorValueIntf::Unit expectedUnit) -> void
166*acfdd55fSJagpal Singh Gill {
167*acfdd55fSJagpal Singh Gill if (std::isnan(expectedValue))
168*acfdd55fSJagpal Singh Gill {
169*acfdd55fSJagpal Singh Gill EXPECT_TRUE(std::isnan(properties.value))
170*acfdd55fSJagpal Singh Gill << "Sensor value should be Nan";
171*acfdd55fSJagpal Singh Gill verifyValue(operationalProperties.functional, false,
172*acfdd55fSJagpal Singh Gill "Operational status mismatch");
173*acfdd55fSJagpal Singh Gill verifyValue(availabilityProperties.available, false,
174*acfdd55fSJagpal Singh Gill "Availability mismatch");
175*acfdd55fSJagpal Singh Gill verifyValue(thresholdProperties.critical_alarm_high, false,
176*acfdd55fSJagpal Singh Gill "Critical Alarm mismatch");
177*acfdd55fSJagpal Singh Gill }
178*acfdd55fSJagpal Singh Gill else
179*acfdd55fSJagpal Singh Gill {
180*acfdd55fSJagpal Singh Gill verifyValue(properties.value, expectedValue,
181*acfdd55fSJagpal Singh Gill "Sensor value mismatch");
182*acfdd55fSJagpal Singh Gill verifyValue(operationalProperties.functional, true,
183*acfdd55fSJagpal Singh Gill "Operational status mismatch");
184*acfdd55fSJagpal Singh Gill verifyValue(availabilityProperties.available, true,
185*acfdd55fSJagpal Singh Gill "Availability mismatch");
186*acfdd55fSJagpal Singh Gill verifyValue(thresholdProperties.critical_alarm_high, true,
187*acfdd55fSJagpal Singh Gill "Critical Alarm mismatch");
188*acfdd55fSJagpal Singh Gill }
189*acfdd55fSJagpal Singh Gill
190*acfdd55fSJagpal Singh Gill EXPECT_EQ(properties.unit, expectedUnit) << "Sensor unit mismatch";
191*acfdd55fSJagpal Singh Gill EXPECT_TRUE(std::isnan(properties.min_value)) << "Min value mismatch";
192*acfdd55fSJagpal Singh Gill EXPECT_TRUE(std::isnan(properties.max_value)) << "Max value mismatch";
193*acfdd55fSJagpal Singh Gill }
194*acfdd55fSJagpal Singh Gill
testSensorCreation(std::string objectPath,DeviceConfigIntf::StatusType statusType,double expectedValue)195*acfdd55fSJagpal Singh Gill auto testSensorCreation(std::string objectPath,
196*acfdd55fSJagpal Singh Gill DeviceConfigIntf::StatusType statusType,
197*acfdd55fSJagpal Singh Gill double expectedValue)
198*acfdd55fSJagpal Singh Gill -> sdbusplus::async::task<void>
199*acfdd55fSJagpal Singh Gill {
200*acfdd55fSJagpal Singh Gill DeviceConfigIntf::StatusBit statusBit = {
201*acfdd55fSJagpal Singh Gill .name = sensorName,
202*acfdd55fSJagpal Singh Gill .type = statusType,
203*acfdd55fSJagpal Singh Gill .bitPosition = 0,
204*acfdd55fSJagpal Singh Gill .value = true};
205*acfdd55fSJagpal Singh Gill DeviceConfigIntf::Config::status_registers_t statusRegisters = {
206*acfdd55fSJagpal Singh Gill {TestIntf::testReadHoldingRegisterEventOffset, {statusBit}}};
207*acfdd55fSJagpal Singh Gill DeviceConfigIntf::Config::sensor_registers_t sensorRegisters = {{
208*acfdd55fSJagpal Singh Gill .name = sensorName,
209*acfdd55fSJagpal Singh Gill .pathSuffix = SensorValueIntf::namespace_path::temperature,
210*acfdd55fSJagpal Singh Gill .unit = SensorValueIntf::Unit::DegreesC,
211*acfdd55fSJagpal Singh Gill .offset = TestIntf::testReadHoldingRegisterTempUnsignedOffset,
212*acfdd55fSJagpal Singh Gill .size = TestIntf::testReadHoldingRegisterTempCount,
213*acfdd55fSJagpal Singh Gill .format = DeviceConfigIntf::SensorFormat::floatingPoint,
214*acfdd55fSJagpal Singh Gill }};
215*acfdd55fSJagpal Singh Gill DeviceConfigIntf::DeviceFactoryConfig deviceFactoryConfig = {
216*acfdd55fSJagpal Singh Gill {
217*acfdd55fSJagpal Singh Gill .address = TestIntf::testDeviceAddress,
218*acfdd55fSJagpal Singh Gill .parity = ModbusIntf::Parity::none,
219*acfdd55fSJagpal Singh Gill .baudRate = baudRate,
220*acfdd55fSJagpal Singh Gill .name = deviceName,
221*acfdd55fSJagpal Singh Gill .portName = portConfig.name,
222*acfdd55fSJagpal Singh Gill .inventoryPath = sdbusplus::message::object_path(
223*acfdd55fSJagpal Singh Gill "xyz/openbmc_project/Inventory/ResorviorPumpUnit"),
224*acfdd55fSJagpal Singh Gill .sensorRegisters = sensorRegisters,
225*acfdd55fSJagpal Singh Gill .statusRegisters = statusRegisters,
226*acfdd55fSJagpal Singh Gill .firmwareRegisters = {},
227*acfdd55fSJagpal Singh Gill },
228*acfdd55fSJagpal Singh Gill DeviceConfigIntf::DeviceType::reservoirPumpUnit,
229*acfdd55fSJagpal Singh Gill DeviceConfigIntf::DeviceModel::RDF040DSS5193E0,
230*acfdd55fSJagpal Singh Gill };
231*acfdd55fSJagpal Singh Gill EventIntf::Events events{ctx};
232*acfdd55fSJagpal Singh Gill MockPort mockPort(ctx, portConfig, clientDevicePath);
233*acfdd55fSJagpal Singh Gill auto device = DeviceIntf::DeviceFactory::create(
234*acfdd55fSJagpal Singh Gill ctx, deviceFactoryConfig, mockPort, events);
235*acfdd55fSJagpal Singh Gill co_await device->readSensorRegisters();
236*acfdd55fSJagpal Singh Gill auto properties = co_await SensorValueIntf(ctx)
237*acfdd55fSJagpal Singh Gill .service(serviceName)
238*acfdd55fSJagpal Singh Gill .path(objectPath)
239*acfdd55fSJagpal Singh Gill .properties();
240*acfdd55fSJagpal Singh Gill auto operationalProperties =
241*acfdd55fSJagpal Singh Gill co_await OperationalStatusIntf(ctx)
242*acfdd55fSJagpal Singh Gill .service(serviceName)
243*acfdd55fSJagpal Singh Gill .path(objectPath)
244*acfdd55fSJagpal Singh Gill .properties();
245*acfdd55fSJagpal Singh Gill auto availabilityProperties =
246*acfdd55fSJagpal Singh Gill co_await AvailabilityIntf(ctx)
247*acfdd55fSJagpal Singh Gill .service(serviceName)
248*acfdd55fSJagpal Singh Gill .path(objectPath)
249*acfdd55fSJagpal Singh Gill .properties();
250*acfdd55fSJagpal Singh Gill auto thresholdProperties =
251*acfdd55fSJagpal Singh Gill co_await ThresholdCriticalIntf(ctx)
252*acfdd55fSJagpal Singh Gill .service(serviceName)
253*acfdd55fSJagpal Singh Gill .path(objectPath)
254*acfdd55fSJagpal Singh Gill .properties();
255*acfdd55fSJagpal Singh Gill verifyResult(properties, operationalProperties, availabilityProperties,
256*acfdd55fSJagpal Singh Gill thresholdProperties, expectedValue,
257*acfdd55fSJagpal Singh Gill sensorRegisters[0].unit);
258*acfdd55fSJagpal Singh Gill co_return;
259*acfdd55fSJagpal Singh Gill }
260*acfdd55fSJagpal Singh Gill };
261*acfdd55fSJagpal Singh Gill
TEST_F(DeviceEventsTest,TestSensorReadingCritical)262*acfdd55fSJagpal Singh Gill TEST_F(DeviceEventsTest, TestSensorReadingCritical)
263*acfdd55fSJagpal Singh Gill {
264*acfdd55fSJagpal Singh Gill eventServer.expectedEvent =
265*acfdd55fSJagpal Singh Gill "xyz.openbmc_project.Sensor.Threshold.ReadingCritical";
266*acfdd55fSJagpal Singh Gill
267*acfdd55fSJagpal Singh Gill ctx.spawn(testSensorCreation(
268*acfdd55fSJagpal Singh Gill objectPath, DeviceConfigIntf::StatusType::sensorReadingCritical,
269*acfdd55fSJagpal Singh Gill TestIntf::testReadHoldingRegisterTempUnsigned[0]));
270*acfdd55fSJagpal Singh Gill
271*acfdd55fSJagpal Singh Gill ctx.spawn(sdbusplus::async::sleep_for(ctx, 1s) |
272*acfdd55fSJagpal Singh Gill sdbusplus::async::execution::then([&]() { ctx.request_stop(); }));
273*acfdd55fSJagpal Singh Gill
274*acfdd55fSJagpal Singh Gill ctx.run();
275*acfdd55fSJagpal Singh Gill }
276*acfdd55fSJagpal Singh Gill
TEST_F(DeviceEventsTest,TestSensorFailure)277*acfdd55fSJagpal Singh Gill TEST_F(DeviceEventsTest, TestSensorFailure)
278*acfdd55fSJagpal Singh Gill {
279*acfdd55fSJagpal Singh Gill eventServer.expectedEvent = "xyz.openbmc_project.Sensor.SensorFailure";
280*acfdd55fSJagpal Singh Gill
281*acfdd55fSJagpal Singh Gill ctx.spawn(testSensorCreation(objectPath,
282*acfdd55fSJagpal Singh Gill DeviceConfigIntf::StatusType::sensorFailure,
283*acfdd55fSJagpal Singh Gill std::numeric_limits<double>::quiet_NaN()));
284*acfdd55fSJagpal Singh Gill
285*acfdd55fSJagpal Singh Gill ctx.spawn(sdbusplus::async::sleep_for(ctx, 1s) |
286*acfdd55fSJagpal Singh Gill sdbusplus::async::execution::then([&]() { ctx.request_stop(); }));
287*acfdd55fSJagpal Singh Gill
288*acfdd55fSJagpal Singh Gill ctx.run();
289*acfdd55fSJagpal Singh Gill }
290