xref: /openbmc/phosphor-pid-control/test/dbus_passive_unittest.cpp (revision 2922eebe4ddc565062eef84082519c094cb99f6e)
175eb769dSJames Feist #include "conf.hpp"
20ef1faf7SPatrick Venture #include "dbus/dbuspassive.hpp"
3da4a5dd1SPatrick Venture #include "test/dbushelper_mock.hpp"
40ef1faf7SPatrick Venture 
50ef1faf7SPatrick Venture #include <sdbusplus/test/sdbus_mock.hpp>
6a83a3eccSPatrick Venture 
7a83a3eccSPatrick Venture #include <functional>
88729eb98SPatrick Venture #include <memory>
90ef1faf7SPatrick Venture #include <string>
101f802f5eSJames Feist #include <variant>
110ef1faf7SPatrick Venture 
12da4a5dd1SPatrick Venture #include <gmock/gmock.h>
13da4a5dd1SPatrick Venture #include <gtest/gtest.h>
140ef1faf7SPatrick Venture 
15a076487aSPatrick Venture namespace pid_control
16a076487aSPatrick Venture {
17a076487aSPatrick Venture namespace
18a076487aSPatrick Venture {
19a076487aSPatrick Venture 
20da4a5dd1SPatrick Venture using ::testing::_;
210ef1faf7SPatrick Venture using ::testing::InSequence;
220ef1faf7SPatrick Venture using ::testing::Invoke;
230ef1faf7SPatrick Venture using ::testing::IsNull;
240ef1faf7SPatrick Venture using ::testing::NotNull;
250ef1faf7SPatrick Venture using ::testing::Return;
260ef1faf7SPatrick Venture using ::testing::StrEq;
270ef1faf7SPatrick Venture 
280ef1faf7SPatrick Venture std::string SensorIntf = "xyz.openbmc_project.Sensor.Value";
290ef1faf7SPatrick Venture 
TEST(DbusPassiveTest,FactoryFailsWithInvalidType)30da4a5dd1SPatrick Venture TEST(DbusPassiveTest, FactoryFailsWithInvalidType)
31da4a5dd1SPatrick Venture {
320ef1faf7SPatrick Venture     // Verify the type is checked by the factory.
330ef1faf7SPatrick Venture 
340ef1faf7SPatrick Venture     sdbusplus::SdBusMock sdbus_mock;
350ef1faf7SPatrick Venture     auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
360ef1faf7SPatrick Venture     std::string type = "invalid";
370ef1faf7SPatrick Venture     std::string id = "id";
380ef1faf7SPatrick Venture 
398729eb98SPatrick Venture     auto helper = std::make_unique<DbusHelperMock>();
40f81f2886SJames Feist     auto info = conf::SensorConfig();
410ef1faf7SPatrick Venture 
4298b704e1SJames Feist     std::unique_ptr<ReadInterface> ri = DbusPassive::createDbusPassive(
438729eb98SPatrick Venture         bus_mock, type, id, std::move(helper), &info, nullptr);
440ef1faf7SPatrick Venture 
450ef1faf7SPatrick Venture     EXPECT_EQ(ri, nullptr);
460ef1faf7SPatrick Venture }
470ef1faf7SPatrick Venture 
TEST(DbusPassiveTest,BoringConstructorTest)48da4a5dd1SPatrick Venture TEST(DbusPassiveTest, BoringConstructorTest)
49da4a5dd1SPatrick Venture {
50f8cb4644SPatrick Venture     // Simply build the object, does no error checking.
510ef1faf7SPatrick Venture 
520ef1faf7SPatrick Venture     sdbusplus::SdBusMock sdbus_mock;
530ef1faf7SPatrick Venture     auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
540ef1faf7SPatrick Venture     std::string type = "invalid";
550ef1faf7SPatrick Venture     std::string id = "id";
560ef1faf7SPatrick Venture     std::string path = "/xyz/openbmc_project/sensors/unknown/id";
570ef1faf7SPatrick Venture 
588729eb98SPatrick Venture     auto helper = std::make_unique<DbusHelperMock>();
591df9e879SPatrick Venture     SensorProperties properties;
600ef1faf7SPatrick Venture 
618729eb98SPatrick Venture     DbusPassive(bus_mock, type, id, std::move(helper), properties, false, path,
628729eb98SPatrick Venture                 nullptr);
630ef1faf7SPatrick Venture     // Success
640ef1faf7SPatrick Venture }
650ef1faf7SPatrick Venture 
66da4a5dd1SPatrick Venture class DbusPassiveTestObj : public ::testing::Test
67da4a5dd1SPatrick Venture {
680ef1faf7SPatrick Venture   protected:
DbusPassiveTestObj()69da4a5dd1SPatrick Venture     DbusPassiveTestObj() :
70*2922eebeSJayanth Othayoth         sdbus_mock(), bus_mock(sdbusplus::get_mocked_new(&sdbus_mock)),
718729eb98SPatrick Venture         helper(std::make_unique<DbusHelperMock>())
720ef1faf7SPatrick Venture     {
739b93692dSPatrick Venture         EXPECT_CALL(*helper, getService(StrEq(SensorIntf), StrEq(path)))
740ef1faf7SPatrick Venture             .WillOnce(Return("asdf"));
750ef1faf7SPatrick Venture 
768729eb98SPatrick Venture         EXPECT_CALL(*helper,
779b93692dSPatrick Venture                     getProperties(StrEq("asdf"), StrEq(path), NotNull()))
78a1ae4fa1SHarvey.Wu             .WillOnce(Invoke([&]([[maybe_unused]] const std::string& service,
79a1ae4fa1SHarvey.Wu                                  [[maybe_unused]] const std::string& path,
801df9e879SPatrick Venture                                  SensorProperties* prop) {
810ef1faf7SPatrick Venture                 prop->scale = _scale;
820ef1faf7SPatrick Venture                 prop->value = _value;
830ef1faf7SPatrick Venture                 prop->unit = "x";
846b9f5999SPatrick Venture                 prop->min = 0;
856b9f5999SPatrick Venture                 prop->max = 0;
868f73ad76SAlex.Song                 prop->available = true;
870ef1faf7SPatrick Venture             }));
889b93692dSPatrick Venture         EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
8936b7d8ebSJames Feist             .WillOnce(Return(false));
900ef1faf7SPatrick Venture 
91f81f2886SJames Feist         auto info = conf::SensorConfig();
928f73ad76SAlex.Song         info.unavailableAsFailed = true;
938729eb98SPatrick Venture         ri = DbusPassive::createDbusPassive(bus_mock, type, id,
948729eb98SPatrick Venture                                             std::move(helper), &info, nullptr);
950ef1faf7SPatrick Venture         passive = reinterpret_cast<DbusPassive*>(ri.get());
960ef1faf7SPatrick Venture         EXPECT_FALSE(passive == nullptr);
970ef1faf7SPatrick Venture     }
980ef1faf7SPatrick Venture 
990ef1faf7SPatrick Venture     sdbusplus::SdBusMock sdbus_mock;
100b228bc30SPatrick Williams     sdbusplus::bus_t bus_mock;
1018729eb98SPatrick Venture     std::unique_ptr<DbusHelperMock> helper;
1020ef1faf7SPatrick Venture     std::string type = "temp";
1030ef1faf7SPatrick Venture     std::string id = "id";
1040ef1faf7SPatrick Venture     std::string path = "/xyz/openbmc_project/sensors/temperature/id";
1050ef1faf7SPatrick Venture     int64_t _scale = -3;
1060ef1faf7SPatrick Venture     int64_t _value = 10;
1070ef1faf7SPatrick Venture 
1080ef1faf7SPatrick Venture     std::unique_ptr<ReadInterface> ri;
1090ef1faf7SPatrick Venture     DbusPassive* passive;
1100ef1faf7SPatrick Venture };
1110ef1faf7SPatrick Venture 
TEST_F(DbusPassiveTestObj,ReadReturnsExpectedValues)112da4a5dd1SPatrick Venture TEST_F(DbusPassiveTestObj, ReadReturnsExpectedValues)
113da4a5dd1SPatrick Venture {
1140ef1faf7SPatrick Venture     // Verify read is returning the values.
1150ef1faf7SPatrick Venture     ReadReturn v;
1160ef1faf7SPatrick Venture     v.value = 0.01;
1170ef1faf7SPatrick Venture     // TODO: updated is set when the value is created, so we can range check
1180ef1faf7SPatrick Venture     // it.
1190ef1faf7SPatrick Venture     ReadReturn r = passive->read();
1200ef1faf7SPatrick Venture     EXPECT_EQ(v.value, r.value);
1210ef1faf7SPatrick Venture }
1220ef1faf7SPatrick Venture 
TEST_F(DbusPassiveTestObj,SetValueUpdatesValue)123da4a5dd1SPatrick Venture TEST_F(DbusPassiveTestObj, SetValueUpdatesValue)
124da4a5dd1SPatrick Venture {
1250ef1faf7SPatrick Venture     // Verify setvalue does as advertised.
1260ef1faf7SPatrick Venture 
1270ef1faf7SPatrick Venture     double value = 0.01;
1280ef1faf7SPatrick Venture     passive->setValue(value);
1290ef1faf7SPatrick Venture 
1300ef1faf7SPatrick Venture     // TODO: updated is set when the value is set, so we can range check it.
1310ef1faf7SPatrick Venture     ReadReturn r = passive->read();
1320ef1faf7SPatrick Venture     EXPECT_EQ(value, r.value);
1330ef1faf7SPatrick Venture }
1340ef1faf7SPatrick Venture 
TEST_F(DbusPassiveTestObj,GetScaleReturnsExpectedValue)135da4a5dd1SPatrick Venture TEST_F(DbusPassiveTestObj, GetScaleReturnsExpectedValue)
136da4a5dd1SPatrick Venture {
1370ef1faf7SPatrick Venture     // Verify the scale is returned as expected.
1380ef1faf7SPatrick Venture     EXPECT_EQ(_scale, passive->getScale());
1390ef1faf7SPatrick Venture }
1400ef1faf7SPatrick Venture 
TEST_F(DbusPassiveTestObj,getIDReturnsExpectedValue)141563a356fSPatrick Venture TEST_F(DbusPassiveTestObj, getIDReturnsExpectedValue)
142da4a5dd1SPatrick Venture {
143563a356fSPatrick Venture     // Verify getID returns the expected value.
144563a356fSPatrick Venture     EXPECT_EQ(id, passive->getID());
1450ef1faf7SPatrick Venture }
1460ef1faf7SPatrick Venture 
TEST_F(DbusPassiveTestObj,GetMinValueReturnsExpectedValue)1476b9f5999SPatrick Venture TEST_F(DbusPassiveTestObj, GetMinValueReturnsExpectedValue)
1486b9f5999SPatrick Venture {
1496b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(0, passive->getMin());
1506b9f5999SPatrick Venture }
1516b9f5999SPatrick Venture 
TEST_F(DbusPassiveTestObj,VerifyHandlesDbusSignal)152da4a5dd1SPatrick Venture TEST_F(DbusPassiveTestObj, VerifyHandlesDbusSignal)
153da4a5dd1SPatrick Venture {
1540ef1faf7SPatrick Venture     // The dbus passive sensor listens for updates and if it's the Value
1550ef1faf7SPatrick Venture     // property, it needs to handle it.
1560ef1faf7SPatrick Venture 
1570ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
1580ef1faf7SPatrick Venture         .WillOnce(Return(nullptr));
159b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
1600ef1faf7SPatrick Venture 
1610ef1faf7SPatrick Venture     const char* Value = "Value";
1620ef1faf7SPatrick Venture     int64_t xValue = 10000;
1630ef1faf7SPatrick Venture     const char* intf = "xyz.openbmc_project.Sensor.Value";
1641f802f5eSJames Feist     // string, std::map<std::string, std::variant<int64_t>>
1650ef1faf7SPatrick Venture     // msg.read(msgSensor, msgData);
1660ef1faf7SPatrick Venture 
167da4a5dd1SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
168a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
169a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
1700ef1faf7SPatrick Venture             const char** s = static_cast<const char**>(p);
1710ef1faf7SPatrick Venture             // Read the first parameter, the string.
1720ef1faf7SPatrick Venture             *s = intf;
1730ef1faf7SPatrick Venture             return 0;
1740ef1faf7SPatrick Venture         }))
175a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
176a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
1770ef1faf7SPatrick Venture             const char** s = static_cast<const char**>(p);
1780ef1faf7SPatrick Venture             *s = Value;
1790ef1faf7SPatrick Venture             // Read the string in the pair (dictionary).
1800ef1faf7SPatrick Venture             return 0;
1810ef1faf7SPatrick Venture         }));
1820ef1faf7SPatrick Venture 
1830ef1faf7SPatrick Venture     // std::map
1840ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
1850ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
1860ef1faf7SPatrick Venture         .WillOnce(Return(0));
1870ef1faf7SPatrick Venture 
1880ef1faf7SPatrick Venture     // while !at_end()
1890ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
1900ef1faf7SPatrick Venture         .WillOnce(Return(0))
1910ef1faf7SPatrick Venture         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
1920ef1faf7SPatrick Venture 
1930ef1faf7SPatrick Venture     // std::pair
1940ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
1950ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
1960ef1faf7SPatrick Venture         .WillOnce(Return(0));
1970ef1faf7SPatrick Venture 
1980ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
1990ef1faf7SPatrick Venture                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
2000ef1faf7SPatrick Venture         .WillOnce(Return(1));
2010ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
2020ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
2030ef1faf7SPatrick Venture         .WillOnce(Return(0));
2040ef1faf7SPatrick Venture 
205da4a5dd1SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
206a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
207a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
2080ef1faf7SPatrick Venture             int64_t* s = static_cast<int64_t*>(p);
2090ef1faf7SPatrick Venture             *s = xValue;
2100ef1faf7SPatrick Venture             return 0;
2110ef1faf7SPatrick Venture         }));
2120ef1faf7SPatrick Venture 
2130ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
2140ef1faf7SPatrick Venture         .WillOnce(Return(0))  /* variant. */
2150ef1faf7SPatrick Venture         .WillOnce(Return(0))  /* std::pair */
2160ef1faf7SPatrick Venture         .WillOnce(Return(0)); /* std::map */
2170ef1faf7SPatrick Venture 
2187af157b1SPatrick Venture     int rv = handleSensorValue(msg, passive);
2190ef1faf7SPatrick Venture     EXPECT_EQ(rv, 0); // It's always 0.
2200ef1faf7SPatrick Venture 
2210ef1faf7SPatrick Venture     ReadReturn r = passive->read();
2220ef1faf7SPatrick Venture     EXPECT_EQ(10, r.value);
2230ef1faf7SPatrick Venture }
2240ef1faf7SPatrick Venture 
TEST_F(DbusPassiveTestObj,VerifyIgnoresOtherPropertySignal)225da4a5dd1SPatrick Venture TEST_F(DbusPassiveTestObj, VerifyIgnoresOtherPropertySignal)
226da4a5dd1SPatrick Venture {
2270ef1faf7SPatrick Venture     // The dbus passive sensor listens for updates and if it's the Value
2280ef1faf7SPatrick Venture     // property, it needs to handle it.  In this case, it won't be.
2290ef1faf7SPatrick Venture 
2300ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
2310ef1faf7SPatrick Venture         .WillOnce(Return(nullptr));
232b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
2330ef1faf7SPatrick Venture 
2340ef1faf7SPatrick Venture     const char* Scale = "Scale";
2350ef1faf7SPatrick Venture     int64_t xScale = -6;
2360ef1faf7SPatrick Venture     const char* intf = "xyz.openbmc_project.Sensor.Value";
2371f802f5eSJames Feist     // string, std::map<std::string, std::variant<int64_t>>
2380ef1faf7SPatrick Venture     // msg.read(msgSensor, msgData);
2390ef1faf7SPatrick Venture 
240da4a5dd1SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
241a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
242a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
2430ef1faf7SPatrick Venture             const char** s = static_cast<const char**>(p);
2440ef1faf7SPatrick Venture             // Read the first parameter, the string.
2450ef1faf7SPatrick Venture             *s = intf;
2460ef1faf7SPatrick Venture             return 0;
2470ef1faf7SPatrick Venture         }))
248a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
249a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
2500ef1faf7SPatrick Venture             const char** s = static_cast<const char**>(p);
2510ef1faf7SPatrick Venture             *s = Scale;
2520ef1faf7SPatrick Venture             // Read the string in the pair (dictionary).
2530ef1faf7SPatrick Venture             return 0;
2540ef1faf7SPatrick Venture         }));
2550ef1faf7SPatrick Venture 
2560ef1faf7SPatrick Venture     // std::map
2570ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
2580ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
2590ef1faf7SPatrick Venture         .WillOnce(Return(0));
2600ef1faf7SPatrick Venture 
2610ef1faf7SPatrick Venture     // while !at_end()
2620ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
2630ef1faf7SPatrick Venture         .WillOnce(Return(0))
2640ef1faf7SPatrick Venture         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
2650ef1faf7SPatrick Venture 
2660ef1faf7SPatrick Venture     // std::pair
2670ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
2680ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
2690ef1faf7SPatrick Venture         .WillOnce(Return(0));
2700ef1faf7SPatrick Venture 
2710ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
2720ef1faf7SPatrick Venture                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
2730ef1faf7SPatrick Venture         .WillOnce(Return(1));
2740ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
2750ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
2760ef1faf7SPatrick Venture         .WillOnce(Return(0));
2770ef1faf7SPatrick Venture 
278da4a5dd1SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
279a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
280a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
2810ef1faf7SPatrick Venture             int64_t* s = static_cast<int64_t*>(p);
2820ef1faf7SPatrick Venture             *s = xScale;
2830ef1faf7SPatrick Venture             return 0;
2840ef1faf7SPatrick Venture         }));
2850ef1faf7SPatrick Venture 
2860ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
2870ef1faf7SPatrick Venture         .WillOnce(Return(0))  /* variant. */
2880ef1faf7SPatrick Venture         .WillOnce(Return(0))  /* std::pair */
2890ef1faf7SPatrick Venture         .WillOnce(Return(0)); /* std::map */
2900ef1faf7SPatrick Venture 
2917af157b1SPatrick Venture     int rv = handleSensorValue(msg, passive);
2920ef1faf7SPatrick Venture     EXPECT_EQ(rv, 0); // It's always 0.
2930ef1faf7SPatrick Venture 
2940ef1faf7SPatrick Venture     ReadReturn r = passive->read();
2950ef1faf7SPatrick Venture     EXPECT_EQ(0.01, r.value);
2960ef1faf7SPatrick Venture }
2978f73ad76SAlex.Song 
TEST_F(DbusPassiveTestObj,VerifyCriticalThresholdAssert)29836b7d8ebSJames Feist TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdAssert)
29936b7d8ebSJames Feist {
30036b7d8ebSJames Feist     // Verifies when a threshold is crossed the sensor goes into error state
30136b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
30236b7d8ebSJames Feist         .WillOnce(Return(nullptr));
303b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
30436b7d8ebSJames Feist 
30536b7d8ebSJames Feist     const char* criticalAlarm = "CriticalAlarmHigh";
30636b7d8ebSJames Feist     bool alarm = true;
30736b7d8ebSJames Feist     const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
30836b7d8ebSJames Feist 
30936b7d8ebSJames Feist     passive->setFailed(false);
31036b7d8ebSJames Feist 
31136b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
312a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
313a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
31436b7d8ebSJames Feist             const char** s = static_cast<const char**>(p);
31536b7d8ebSJames Feist             // Read the first parameter, the string.
31636b7d8ebSJames Feist             *s = intf;
31736b7d8ebSJames Feist             return 0;
31836b7d8ebSJames Feist         }))
319a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
320a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
32136b7d8ebSJames Feist             const char** s = static_cast<const char**>(p);
32236b7d8ebSJames Feist             *s = criticalAlarm;
32336b7d8ebSJames Feist             // Read the string in the pair (dictionary).
32436b7d8ebSJames Feist             return 0;
32536b7d8ebSJames Feist         }));
32636b7d8ebSJames Feist 
32736b7d8ebSJames Feist     // std::map
32836b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
32936b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
33036b7d8ebSJames Feist         .WillOnce(Return(0));
33136b7d8ebSJames Feist 
33236b7d8ebSJames Feist     // while !at_end()
33336b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
33436b7d8ebSJames Feist         .WillOnce(Return(0))
33536b7d8ebSJames Feist         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
33636b7d8ebSJames Feist 
33736b7d8ebSJames Feist     // std::pair
33836b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
33936b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
34036b7d8ebSJames Feist         .WillOnce(Return(0));
34136b7d8ebSJames Feist 
34236b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
34336b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
34436b7d8ebSJames Feist         .WillOnce(Return(0));
34536b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
34636b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
34736b7d8ebSJames Feist         .WillOnce(Return(0));
34836b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
34936b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
35036b7d8ebSJames Feist         .WillOnce(Return(1));
35136b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
35236b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
35336b7d8ebSJames Feist         .WillOnce(Return(0));
35436b7d8ebSJames Feist 
35536b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
356a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
357a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
35836b7d8ebSJames Feist             bool* s = static_cast<bool*>(p);
35936b7d8ebSJames Feist             *s = alarm;
36036b7d8ebSJames Feist             return 0;
36136b7d8ebSJames Feist         }));
36236b7d8ebSJames Feist 
36336b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
36436b7d8ebSJames Feist         .WillOnce(Return(0))  /* variant. */
36536b7d8ebSJames Feist         .WillOnce(Return(0))  /* std::pair */
36636b7d8ebSJames Feist         .WillOnce(Return(0)); /* std::map */
36736b7d8ebSJames Feist 
3687af157b1SPatrick Venture     int rv = handleSensorValue(msg, passive);
36936b7d8ebSJames Feist     EXPECT_EQ(rv, 0); // It's always 0.
37036b7d8ebSJames Feist     bool failed = passive->getFailed();
37136b7d8ebSJames Feist     EXPECT_EQ(failed, true);
37236b7d8ebSJames Feist }
37336b7d8ebSJames Feist 
TEST_F(DbusPassiveTestObj,VerifyCriticalThresholdDeassert)37436b7d8ebSJames Feist TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdDeassert)
37536b7d8ebSJames Feist {
37636b7d8ebSJames Feist     // Verifies when a threshold is deasserted a failed sensor goes back into
37736b7d8ebSJames Feist     // the normal state
37836b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
37936b7d8ebSJames Feist         .WillOnce(Return(nullptr));
380b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
38136b7d8ebSJames Feist 
38236b7d8ebSJames Feist     const char* criticalAlarm = "CriticalAlarmHigh";
38336b7d8ebSJames Feist     bool alarm = false;
38436b7d8ebSJames Feist     const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
38536b7d8ebSJames Feist 
38636b7d8ebSJames Feist     passive->setFailed(true);
38736b7d8ebSJames Feist 
38836b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
389a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
390a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
39136b7d8ebSJames Feist             const char** s = static_cast<const char**>(p);
39236b7d8ebSJames Feist             // Read the first parameter, the string.
39336b7d8ebSJames Feist             *s = intf;
39436b7d8ebSJames Feist             return 0;
39536b7d8ebSJames Feist         }))
396a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
397a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
39836b7d8ebSJames Feist             const char** s = static_cast<const char**>(p);
39936b7d8ebSJames Feist             *s = criticalAlarm;
40036b7d8ebSJames Feist             // Read the string in the pair (dictionary).
40136b7d8ebSJames Feist             return 0;
40236b7d8ebSJames Feist         }));
40336b7d8ebSJames Feist 
40436b7d8ebSJames Feist     // std::map
40536b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
40636b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
40736b7d8ebSJames Feist         .WillOnce(Return(0));
40836b7d8ebSJames Feist 
40936b7d8ebSJames Feist     // while !at_end()
41036b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
41136b7d8ebSJames Feist         .WillOnce(Return(0))
41236b7d8ebSJames Feist         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
41336b7d8ebSJames Feist 
41436b7d8ebSJames Feist     // std::pair
41536b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
41636b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
41736b7d8ebSJames Feist         .WillOnce(Return(0));
41836b7d8ebSJames Feist 
41936b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
42036b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
42136b7d8ebSJames Feist         .WillOnce(Return(0));
42236b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
42336b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
42436b7d8ebSJames Feist         .WillOnce(Return(0));
42536b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
42636b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
42736b7d8ebSJames Feist         .WillOnce(Return(1));
42836b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
42936b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
43036b7d8ebSJames Feist         .WillOnce(Return(0));
43136b7d8ebSJames Feist 
43236b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
433a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
434a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
43536b7d8ebSJames Feist             bool* s = static_cast<bool*>(p);
43636b7d8ebSJames Feist             *s = alarm;
43736b7d8ebSJames Feist             return 0;
43836b7d8ebSJames Feist         }));
43936b7d8ebSJames Feist 
44036b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
44136b7d8ebSJames Feist         .WillOnce(Return(0))  /* variant. */
44236b7d8ebSJames Feist         .WillOnce(Return(0))  /* std::pair */
44336b7d8ebSJames Feist         .WillOnce(Return(0)); /* std::map */
44436b7d8ebSJames Feist 
4457af157b1SPatrick Venture     int rv = handleSensorValue(msg, passive);
44636b7d8ebSJames Feist     EXPECT_EQ(rv, 0); // It's always 0.
44736b7d8ebSJames Feist     bool failed = passive->getFailed();
44836b7d8ebSJames Feist     EXPECT_EQ(failed, false);
44936b7d8ebSJames Feist }
4506b9f5999SPatrick Venture 
TEST_F(DbusPassiveTestObj,VerifyAvailableDeassert)4518f73ad76SAlex.Song TEST_F(DbusPassiveTestObj, VerifyAvailableDeassert)
4528f73ad76SAlex.Song {
4538f73ad76SAlex.Song     // Verifies when Availble is deasserted && unavailableAsFailed == true,
4548f73ad76SAlex.Song     // the sensor goes into error state
4558f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
4568f73ad76SAlex.Song         .WillOnce(Return(nullptr));
457b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
4588f73ad76SAlex.Song 
4598f73ad76SAlex.Song     const char* property = "Available";
4608f73ad76SAlex.Song     bool asserted = false;
4618f73ad76SAlex.Song     const char* intf = "xyz.openbmc_project.State.Decorator.Availability";
4628f73ad76SAlex.Song 
4638f73ad76SAlex.Song     passive->setAvailable(true);
4648f73ad76SAlex.Song 
4658f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
466a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
467a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
4688f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
4698f73ad76SAlex.Song             // Read the first parameter, the string.
4708f73ad76SAlex.Song             *s = intf;
4718f73ad76SAlex.Song             return 0;
4728f73ad76SAlex.Song         }))
473a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
474a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
4758f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
4768f73ad76SAlex.Song             *s = property;
4778f73ad76SAlex.Song             // Read the string in the pair (dictionary).
4788f73ad76SAlex.Song             return 0;
4798f73ad76SAlex.Song         }));
4808f73ad76SAlex.Song 
4818f73ad76SAlex.Song     // std::map
4828f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
4838f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
4848f73ad76SAlex.Song         .WillOnce(Return(0));
4858f73ad76SAlex.Song 
4868f73ad76SAlex.Song     // while !at_end()
4878f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
4888f73ad76SAlex.Song         .WillOnce(Return(0))
4898f73ad76SAlex.Song         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
4908f73ad76SAlex.Song 
4918f73ad76SAlex.Song     // std::pair
4928f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
4938f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
4948f73ad76SAlex.Song         .WillOnce(Return(0));
4958f73ad76SAlex.Song 
4968f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
4978f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
4988f73ad76SAlex.Song         .WillOnce(Return(0));
4998f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5008f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
5018f73ad76SAlex.Song         .WillOnce(Return(0));
5028f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5038f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
5048f73ad76SAlex.Song         .WillOnce(Return(1));
5058f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5068f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
5078f73ad76SAlex.Song         .WillOnce(Return(0));
5088f73ad76SAlex.Song 
5098f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
510a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
511a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
5128f73ad76SAlex.Song             bool* s = static_cast<bool*>(p);
5138f73ad76SAlex.Song             *s = asserted;
5148f73ad76SAlex.Song             return 0;
5158f73ad76SAlex.Song         }));
5168f73ad76SAlex.Song 
5178f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
5188f73ad76SAlex.Song         .WillOnce(Return(0))  /* variant. */
5198f73ad76SAlex.Song         .WillOnce(Return(0))  /* std::pair */
5208f73ad76SAlex.Song         .WillOnce(Return(0)); /* std::map */
5218f73ad76SAlex.Song 
5228f73ad76SAlex.Song     int rv = handleSensorValue(msg, passive);
5238f73ad76SAlex.Song     EXPECT_EQ(rv, 0); // It's always 0.
5248f73ad76SAlex.Song     bool failed = passive->getFailed();
5258f73ad76SAlex.Song     EXPECT_EQ(failed, true);
5268f73ad76SAlex.Song }
5278f73ad76SAlex.Song 
TEST_F(DbusPassiveTestObj,VerifyAvailableAssert)5288f73ad76SAlex.Song TEST_F(DbusPassiveTestObj, VerifyAvailableAssert)
5298f73ad76SAlex.Song {
5308f73ad76SAlex.Song     // Verifies when Availble is asserted && unavailableAsFailed == true,
5318f73ad76SAlex.Song     // an error sensor goes back to normal state
5328f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
5338f73ad76SAlex.Song         .WillOnce(Return(nullptr));
534b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
5358f73ad76SAlex.Song 
5368f73ad76SAlex.Song     const char* property = "Available";
5378f73ad76SAlex.Song     bool asserted = true;
5388f73ad76SAlex.Song     const char* intf = "xyz.openbmc_project.State.Decorator.Availability";
5398f73ad76SAlex.Song 
5408f73ad76SAlex.Song     passive->setAvailable(false);
5418f73ad76SAlex.Song     bool failed = passive->getFailed();
5428f73ad76SAlex.Song     EXPECT_EQ(failed, true);
5438f73ad76SAlex.Song 
5448f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
545a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
546a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
5478f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
5488f73ad76SAlex.Song             // Read the first parameter, the string.
5498f73ad76SAlex.Song             *s = intf;
5508f73ad76SAlex.Song             return 0;
5518f73ad76SAlex.Song         }))
552a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
553a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
5548f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
5558f73ad76SAlex.Song             *s = property;
5568f73ad76SAlex.Song             // Read the string in the pair (dictionary).
5578f73ad76SAlex.Song             return 0;
5588f73ad76SAlex.Song         }));
5598f73ad76SAlex.Song 
5608f73ad76SAlex.Song     // std::map
5618f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5628f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
5638f73ad76SAlex.Song         .WillOnce(Return(0));
5648f73ad76SAlex.Song 
5658f73ad76SAlex.Song     // while !at_end()
5668f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
5678f73ad76SAlex.Song         .WillOnce(Return(0))
5688f73ad76SAlex.Song         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
5698f73ad76SAlex.Song 
5708f73ad76SAlex.Song     // std::pair
5718f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5728f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
5738f73ad76SAlex.Song         .WillOnce(Return(0));
5748f73ad76SAlex.Song 
5758f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5768f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
5778f73ad76SAlex.Song         .WillOnce(Return(0));
5788f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5798f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
5808f73ad76SAlex.Song         .WillOnce(Return(0));
5818f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5828f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
5838f73ad76SAlex.Song         .WillOnce(Return(1));
5848f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5858f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
5868f73ad76SAlex.Song         .WillOnce(Return(0));
5878f73ad76SAlex.Song 
5888f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
589a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
590a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
5918f73ad76SAlex.Song             bool* s = static_cast<bool*>(p);
5928f73ad76SAlex.Song             *s = asserted;
5938f73ad76SAlex.Song             return 0;
5948f73ad76SAlex.Song         }));
5958f73ad76SAlex.Song 
5968f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
5978f73ad76SAlex.Song         .WillOnce(Return(0))  /* variant. */
5988f73ad76SAlex.Song         .WillOnce(Return(0))  /* std::pair */
5998f73ad76SAlex.Song         .WillOnce(Return(0)); /* std::map */
6008f73ad76SAlex.Song 
6018f73ad76SAlex.Song     int rv = handleSensorValue(msg, passive);
6028f73ad76SAlex.Song     EXPECT_EQ(rv, 0); // It's always 0.
6038f73ad76SAlex.Song     failed = passive->getFailed();
6048f73ad76SAlex.Song     EXPECT_EQ(failed, false);
6058f73ad76SAlex.Song }
6068f73ad76SAlex.Song 
6078f73ad76SAlex.Song class DbusPassiveTestUnaSensorNotAsFailedObj : public ::testing::Test
6088f73ad76SAlex.Song {
6098f73ad76SAlex.Song   protected:
DbusPassiveTestUnaSensorNotAsFailedObj()6108f73ad76SAlex.Song     DbusPassiveTestUnaSensorNotAsFailedObj() :
611*2922eebeSJayanth Othayoth         sdbus_mock(), bus_mock(sdbusplus::get_mocked_new(&sdbus_mock)),
6128f73ad76SAlex.Song         helper(std::make_unique<DbusHelperMock>())
6138f73ad76SAlex.Song     {
6148f73ad76SAlex.Song         EXPECT_CALL(*helper, getService(StrEq(SensorIntf), StrEq(path)))
6158f73ad76SAlex.Song             .WillOnce(Return("asdf"));
6168f73ad76SAlex.Song 
6178f73ad76SAlex.Song         EXPECT_CALL(*helper,
6188f73ad76SAlex.Song                     getProperties(StrEq("asdf"), StrEq(path), NotNull()))
619a1ae4fa1SHarvey.Wu             .WillOnce(Invoke([&]([[maybe_unused]] const std::string& service,
620a1ae4fa1SHarvey.Wu                                  [[maybe_unused]] const std::string& path,
6218f73ad76SAlex.Song                                  SensorProperties* prop) {
6228f73ad76SAlex.Song                 prop->scale = _scale;
6238f73ad76SAlex.Song                 prop->value = _value;
6248f73ad76SAlex.Song                 prop->unit = "x";
6258f73ad76SAlex.Song                 prop->min = 0;
6268f73ad76SAlex.Song                 prop->max = 0;
6278f73ad76SAlex.Song                 prop->available = true;
6288f73ad76SAlex.Song             }));
6298f73ad76SAlex.Song         EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
6308f73ad76SAlex.Song             .WillOnce(Return(false));
6318f73ad76SAlex.Song 
6328f73ad76SAlex.Song         auto info = conf::SensorConfig();
6338f73ad76SAlex.Song         info.unavailableAsFailed = false;
6348f73ad76SAlex.Song         ri = DbusPassive::createDbusPassive(bus_mock, type, id,
6358f73ad76SAlex.Song                                             std::move(helper), &info, nullptr);
6368f73ad76SAlex.Song         passive = reinterpret_cast<DbusPassive*>(ri.get());
6378f73ad76SAlex.Song         EXPECT_FALSE(passive == nullptr);
6388f73ad76SAlex.Song     }
6398f73ad76SAlex.Song 
6408f73ad76SAlex.Song     sdbusplus::SdBusMock sdbus_mock;
641b228bc30SPatrick Williams     sdbusplus::bus_t bus_mock;
6428f73ad76SAlex.Song     std::unique_ptr<DbusHelperMock> helper;
6438f73ad76SAlex.Song     std::string type = "temp";
6448f73ad76SAlex.Song     std::string id = "id";
6458f73ad76SAlex.Song     std::string path = "/xyz/openbmc_project/sensors/temperature/id";
6468f73ad76SAlex.Song     int64_t _scale = -3;
6478f73ad76SAlex.Song     int64_t _value = 10;
6488f73ad76SAlex.Song 
6498f73ad76SAlex.Song     std::unique_ptr<ReadInterface> ri;
6508f73ad76SAlex.Song     DbusPassive* passive;
6518f73ad76SAlex.Song };
6528f73ad76SAlex.Song 
TEST_F(DbusPassiveTestUnaSensorNotAsFailedObj,VerifyAvailableDeassert)6538f73ad76SAlex.Song TEST_F(DbusPassiveTestUnaSensorNotAsFailedObj, VerifyAvailableDeassert)
6548f73ad76SAlex.Song {
6558f73ad76SAlex.Song     // Verifies when Availble is deasserted && unavailableAsFailed == false,
6568f73ad76SAlex.Song     // the sensor remains at OK state but reading goes to NaN.
6578f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
6588f73ad76SAlex.Song         .WillOnce(Return(nullptr));
659b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
6608f73ad76SAlex.Song 
6618f73ad76SAlex.Song     const char* property = "Available";
6628f73ad76SAlex.Song     bool asserted = false;
6638f73ad76SAlex.Song     const char* intf = "xyz.openbmc_project.State.Decorator.Availability";
6648f73ad76SAlex.Song 
6658f73ad76SAlex.Song     passive->setAvailable(true);
6668f73ad76SAlex.Song 
6678f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
668a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
669a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
6708f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
6718f73ad76SAlex.Song             // Read the first parameter, the string.
6728f73ad76SAlex.Song             *s = intf;
6738f73ad76SAlex.Song             return 0;
6748f73ad76SAlex.Song         }))
675a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
676a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
6778f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
6788f73ad76SAlex.Song             *s = property;
6798f73ad76SAlex.Song             // Read the string in the pair (dictionary).
6808f73ad76SAlex.Song             return 0;
6818f73ad76SAlex.Song         }));
6828f73ad76SAlex.Song 
6838f73ad76SAlex.Song     // std::map
6848f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
6858f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
6868f73ad76SAlex.Song         .WillOnce(Return(0));
6878f73ad76SAlex.Song 
6888f73ad76SAlex.Song     // while !at_end()
6898f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
6908f73ad76SAlex.Song         .WillOnce(Return(0))
6918f73ad76SAlex.Song         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
6928f73ad76SAlex.Song 
6938f73ad76SAlex.Song     // std::pair
6948f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
6958f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
6968f73ad76SAlex.Song         .WillOnce(Return(0));
6978f73ad76SAlex.Song 
6988f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
6998f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
7008f73ad76SAlex.Song         .WillOnce(Return(0));
7018f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7028f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
7038f73ad76SAlex.Song         .WillOnce(Return(0));
7048f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7058f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
7068f73ad76SAlex.Song         .WillOnce(Return(1));
7078f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7088f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
7098f73ad76SAlex.Song         .WillOnce(Return(0));
7108f73ad76SAlex.Song 
7118f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
712a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
713a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
7148f73ad76SAlex.Song             bool* s = static_cast<bool*>(p);
7158f73ad76SAlex.Song             *s = asserted;
7168f73ad76SAlex.Song             return 0;
7178f73ad76SAlex.Song         }));
7188f73ad76SAlex.Song 
7198f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
7208f73ad76SAlex.Song         .WillOnce(Return(0))  /* variant. */
7218f73ad76SAlex.Song         .WillOnce(Return(0))  /* std::pair */
7228f73ad76SAlex.Song         .WillOnce(Return(0)); /* std::map */
7238f73ad76SAlex.Song 
7248f73ad76SAlex.Song     int rv = handleSensorValue(msg, passive);
7258f73ad76SAlex.Song     EXPECT_EQ(rv, 0); // It's always 0.
7268f73ad76SAlex.Song     bool failed = passive->getFailed();
7278f73ad76SAlex.Song     EXPECT_EQ(failed, false);
7288f73ad76SAlex.Song     ReadReturn r = passive->read();
7298f73ad76SAlex.Song     EXPECT_FALSE(std::isfinite(r.value));
7308f73ad76SAlex.Song }
7318f73ad76SAlex.Song 
TEST_F(DbusPassiveTestUnaSensorNotAsFailedObj,VerifyAvailableAssert)7328f73ad76SAlex.Song TEST_F(DbusPassiveTestUnaSensorNotAsFailedObj, VerifyAvailableAssert)
7338f73ad76SAlex.Song {
7348f73ad76SAlex.Song     // Verifies when a sensor's state goes from unavailble to available
7358f73ad76SAlex.Song     // && unavailableAsFailed == false, this sensor remains at OK state.
7368f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
7378f73ad76SAlex.Song         .WillOnce(Return(nullptr));
738b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
7398f73ad76SAlex.Song 
7408f73ad76SAlex.Song     const char* property = "Available";
7418f73ad76SAlex.Song     bool asserted = true;
7428f73ad76SAlex.Song     const char* intf = "xyz.openbmc_project.State.Decorator.Availability";
7438f73ad76SAlex.Song 
7448f73ad76SAlex.Song     passive->setAvailable(false);
7458f73ad76SAlex.Song     bool failed = passive->getFailed();
7468f73ad76SAlex.Song     EXPECT_EQ(failed, false);
7478f73ad76SAlex.Song 
7488f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
749a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
750a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
7518f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
7528f73ad76SAlex.Song             // Read the first parameter, the string.
7538f73ad76SAlex.Song             *s = intf;
7548f73ad76SAlex.Song             return 0;
7558f73ad76SAlex.Song         }))
756a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
757a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
7588f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
7598f73ad76SAlex.Song             *s = property;
7608f73ad76SAlex.Song             // Read the string in the pair (dictionary).
7618f73ad76SAlex.Song             return 0;
7628f73ad76SAlex.Song         }));
7638f73ad76SAlex.Song 
7648f73ad76SAlex.Song     // std::map
7658f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7668f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
7678f73ad76SAlex.Song         .WillOnce(Return(0));
7688f73ad76SAlex.Song 
7698f73ad76SAlex.Song     // while !at_end()
7708f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
7718f73ad76SAlex.Song         .WillOnce(Return(0))
7728f73ad76SAlex.Song         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
7738f73ad76SAlex.Song 
7748f73ad76SAlex.Song     // std::pair
7758f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7768f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
7778f73ad76SAlex.Song         .WillOnce(Return(0));
7788f73ad76SAlex.Song 
7798f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7808f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
7818f73ad76SAlex.Song         .WillOnce(Return(0));
7828f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7838f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
7848f73ad76SAlex.Song         .WillOnce(Return(0));
7858f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7868f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
7878f73ad76SAlex.Song         .WillOnce(Return(1));
7888f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7898f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
7908f73ad76SAlex.Song         .WillOnce(Return(0));
7918f73ad76SAlex.Song 
7928f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
793a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
794a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
7958f73ad76SAlex.Song             bool* s = static_cast<bool*>(p);
7968f73ad76SAlex.Song             *s = asserted;
7978f73ad76SAlex.Song             return 0;
7988f73ad76SAlex.Song         }));
7998f73ad76SAlex.Song 
8008f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
8018f73ad76SAlex.Song         .WillOnce(Return(0))  /* variant. */
8028f73ad76SAlex.Song         .WillOnce(Return(0))  /* std::pair */
8038f73ad76SAlex.Song         .WillOnce(Return(0)); /* std::map */
8048f73ad76SAlex.Song 
8058f73ad76SAlex.Song     int rv = handleSensorValue(msg, passive);
8068f73ad76SAlex.Song     EXPECT_EQ(rv, 0); // It's always 0.
8078f73ad76SAlex.Song     failed = passive->getFailed();
8088f73ad76SAlex.Song     EXPECT_EQ(failed, false);
8098f73ad76SAlex.Song }
8108f73ad76SAlex.Song 
GetPropertiesMax3k(const std::string & service,const std::string & path,SensorProperties * prop)811a1ae4fa1SHarvey.Wu void GetPropertiesMax3k([[maybe_unused]] const std::string& service,
812a1ae4fa1SHarvey.Wu                         [[maybe_unused]] const std::string& path,
8139b93692dSPatrick Venture                         SensorProperties* prop)
8146b9f5999SPatrick Venture {
8156b9f5999SPatrick Venture     prop->scale = -3;
8166b9f5999SPatrick Venture     prop->value = 10;
8176b9f5999SPatrick Venture     prop->unit = "x";
8186b9f5999SPatrick Venture     prop->min = 0;
8196b9f5999SPatrick Venture     prop->max = 3000;
8206b9f5999SPatrick Venture }
8216b9f5999SPatrick Venture 
8229b93692dSPatrick Venture using GetPropertiesFunction = std::function<void(
8239b93692dSPatrick Venture     const std::string&, const std::string&, SensorProperties*)>;
8246b9f5999SPatrick Venture 
8256b9f5999SPatrick Venture // TODO: There is definitely a cleaner way to do this.
8266b9f5999SPatrick Venture class DbusPassiveTest3kMaxObj : public ::testing::Test
8276b9f5999SPatrick Venture {
8286b9f5999SPatrick Venture   protected:
DbusPassiveTest3kMaxObj()8296b9f5999SPatrick Venture     DbusPassiveTest3kMaxObj() :
830*2922eebeSJayanth Othayoth         sdbus_mock(), bus_mock(sdbusplus::get_mocked_new(&sdbus_mock)),
8318729eb98SPatrick Venture         helper(std::make_unique<DbusHelperMock>())
8326b9f5999SPatrick Venture     {
8339b93692dSPatrick Venture         EXPECT_CALL(*helper, getService(StrEq(SensorIntf), StrEq(path)))
8346b9f5999SPatrick Venture             .WillOnce(Return("asdf"));
8356b9f5999SPatrick Venture 
8368729eb98SPatrick Venture         EXPECT_CALL(*helper,
8379b93692dSPatrick Venture                     getProperties(StrEq("asdf"), StrEq(path), NotNull()))
8386b9f5999SPatrick Venture             .WillOnce(_getProps);
8399b93692dSPatrick Venture         EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
8406b9f5999SPatrick Venture             .WillOnce(Return(false));
8416b9f5999SPatrick Venture 
8426b9f5999SPatrick Venture         auto info = conf::SensorConfig();
8438729eb98SPatrick Venture         ri = DbusPassive::createDbusPassive(bus_mock, type, id,
8448729eb98SPatrick Venture                                             std::move(helper), &info, nullptr);
8456b9f5999SPatrick Venture         passive = reinterpret_cast<DbusPassive*>(ri.get());
8466b9f5999SPatrick Venture         EXPECT_FALSE(passive == nullptr);
8476b9f5999SPatrick Venture     }
8486b9f5999SPatrick Venture 
8496b9f5999SPatrick Venture     sdbusplus::SdBusMock sdbus_mock;
850b228bc30SPatrick Williams     sdbusplus::bus_t bus_mock;
8518729eb98SPatrick Venture     std::unique_ptr<DbusHelperMock> helper;
8526b9f5999SPatrick Venture     std::string type = "temp";
8536b9f5999SPatrick Venture     std::string id = "id";
8546b9f5999SPatrick Venture     std::string path = "/xyz/openbmc_project/sensors/temperature/id";
8556b9f5999SPatrick Venture     int64_t _scale = -3;
8566b9f5999SPatrick Venture     int64_t _value = 10;
8576b9f5999SPatrick Venture 
8586b9f5999SPatrick Venture     std::unique_ptr<ReadInterface> ri;
8596b9f5999SPatrick Venture     DbusPassive* passive;
8606b9f5999SPatrick Venture     GetPropertiesFunction _getProps = &GetPropertiesMax3k;
8616b9f5999SPatrick Venture };
8626b9f5999SPatrick Venture 
TEST_F(DbusPassiveTest3kMaxObj,ReadMinAndMaxReturnsExpected)8636b9f5999SPatrick Venture TEST_F(DbusPassiveTest3kMaxObj, ReadMinAndMaxReturnsExpected)
8646b9f5999SPatrick Venture {
8656b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(0, passive->getMin());
8666b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(3, passive->getMax());
8676b9f5999SPatrick Venture }
8686b9f5999SPatrick Venture 
8696b9f5999SPatrick Venture class DbusPassiveTest3kMaxIgnoredObj : public ::testing::Test
8706b9f5999SPatrick Venture {
8716b9f5999SPatrick Venture   protected:
DbusPassiveTest3kMaxIgnoredObj()8726b9f5999SPatrick Venture     DbusPassiveTest3kMaxIgnoredObj() :
873*2922eebeSJayanth Othayoth         sdbus_mock(), bus_mock(sdbusplus::get_mocked_new(&sdbus_mock)),
8748729eb98SPatrick Venture         helper(std::make_unique<DbusHelperMock>())
8756b9f5999SPatrick Venture     {
8769b93692dSPatrick Venture         EXPECT_CALL(*helper, getService(StrEq(SensorIntf), StrEq(path)))
8776b9f5999SPatrick Venture             .WillOnce(Return("asdf"));
8786b9f5999SPatrick Venture 
8798729eb98SPatrick Venture         EXPECT_CALL(*helper,
8809b93692dSPatrick Venture                     getProperties(StrEq("asdf"), StrEq(path), NotNull()))
8816b9f5999SPatrick Venture             .WillOnce(_getProps);
8829b93692dSPatrick Venture         EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
8836b9f5999SPatrick Venture             .WillOnce(Return(false));
8846b9f5999SPatrick Venture 
8856b9f5999SPatrick Venture         auto info = conf::SensorConfig();
8866b9f5999SPatrick Venture         info.ignoreDbusMinMax = true;
8878729eb98SPatrick Venture         ri = DbusPassive::createDbusPassive(bus_mock, type, id,
8888729eb98SPatrick Venture                                             std::move(helper), &info, nullptr);
8896b9f5999SPatrick Venture         passive = reinterpret_cast<DbusPassive*>(ri.get());
8906b9f5999SPatrick Venture         EXPECT_FALSE(passive == nullptr);
8916b9f5999SPatrick Venture     }
8926b9f5999SPatrick Venture 
8936b9f5999SPatrick Venture     sdbusplus::SdBusMock sdbus_mock;
894b228bc30SPatrick Williams     sdbusplus::bus_t bus_mock;
8958729eb98SPatrick Venture     std::unique_ptr<DbusHelperMock> helper;
8966b9f5999SPatrick Venture     std::string type = "temp";
8976b9f5999SPatrick Venture     std::string id = "id";
8986b9f5999SPatrick Venture     std::string path = "/xyz/openbmc_project/sensors/temperature/id";
8996b9f5999SPatrick Venture     int64_t _scale = -3;
9006b9f5999SPatrick Venture     int64_t _value = 10;
9016b9f5999SPatrick Venture 
9026b9f5999SPatrick Venture     std::unique_ptr<ReadInterface> ri;
9036b9f5999SPatrick Venture     DbusPassive* passive;
9046b9f5999SPatrick Venture     GetPropertiesFunction _getProps = &GetPropertiesMax3k;
9056b9f5999SPatrick Venture };
9066b9f5999SPatrick Venture 
TEST_F(DbusPassiveTest3kMaxIgnoredObj,ReadMinAndMaxReturnsExpected)9076b9f5999SPatrick Venture TEST_F(DbusPassiveTest3kMaxIgnoredObj, ReadMinAndMaxReturnsExpected)
9086b9f5999SPatrick Venture {
9096b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(0, passive->getMin());
9106b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(0, passive->getMax());
9116b9f5999SPatrick Venture }
912a076487aSPatrick Venture 
913a076487aSPatrick Venture } // namespace
914a076487aSPatrick Venture } // namespace pid_control
915