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() :
70da4a5dd1SPatrick Venture         sdbus_mock(),
718729eb98SPatrick Venture         bus_mock(std::move(sdbusplus::get_mocked_new(&sdbus_mock))),
728729eb98SPatrick Venture         helper(std::make_unique<DbusHelperMock>())
730ef1faf7SPatrick Venture     {
749b93692dSPatrick Venture         EXPECT_CALL(*helper, getService(StrEq(SensorIntf), StrEq(path)))
750ef1faf7SPatrick Venture             .WillOnce(Return("asdf"));
760ef1faf7SPatrick Venture 
778729eb98SPatrick Venture         EXPECT_CALL(*helper,
789b93692dSPatrick Venture                     getProperties(StrEq("asdf"), StrEq(path), NotNull()))
79*a1ae4fa1SHarvey.Wu             .WillOnce(Invoke([&]([[maybe_unused]] const std::string& service,
80*a1ae4fa1SHarvey.Wu                                  [[maybe_unused]] const std::string& path,
811df9e879SPatrick Venture                                  SensorProperties* prop) {
820ef1faf7SPatrick Venture                 prop->scale = _scale;
830ef1faf7SPatrick Venture                 prop->value = _value;
840ef1faf7SPatrick Venture                 prop->unit = "x";
856b9f5999SPatrick Venture                 prop->min = 0;
866b9f5999SPatrick Venture                 prop->max = 0;
878f73ad76SAlex.Song                 prop->available = true;
880ef1faf7SPatrick Venture             }));
899b93692dSPatrick Venture         EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
9036b7d8ebSJames Feist             .WillOnce(Return(false));
910ef1faf7SPatrick Venture 
92f81f2886SJames Feist         auto info = conf::SensorConfig();
938f73ad76SAlex.Song         info.unavailableAsFailed = true;
948729eb98SPatrick Venture         ri = DbusPassive::createDbusPassive(bus_mock, type, id,
958729eb98SPatrick Venture                                             std::move(helper), &info, nullptr);
960ef1faf7SPatrick Venture         passive = reinterpret_cast<DbusPassive*>(ri.get());
970ef1faf7SPatrick Venture         EXPECT_FALSE(passive == nullptr);
980ef1faf7SPatrick Venture     }
990ef1faf7SPatrick Venture 
1000ef1faf7SPatrick Venture     sdbusplus::SdBusMock sdbus_mock;
101b228bc30SPatrick Williams     sdbusplus::bus_t bus_mock;
1028729eb98SPatrick Venture     std::unique_ptr<DbusHelperMock> helper;
1030ef1faf7SPatrick Venture     std::string type = "temp";
1040ef1faf7SPatrick Venture     std::string id = "id";
1050ef1faf7SPatrick Venture     std::string path = "/xyz/openbmc_project/sensors/temperature/id";
1060ef1faf7SPatrick Venture     int64_t _scale = -3;
1070ef1faf7SPatrick Venture     int64_t _value = 10;
1080ef1faf7SPatrick Venture 
1090ef1faf7SPatrick Venture     std::unique_ptr<ReadInterface> ri;
1100ef1faf7SPatrick Venture     DbusPassive* passive;
1110ef1faf7SPatrick Venture };
1120ef1faf7SPatrick Venture 
TEST_F(DbusPassiveTestObj,ReadReturnsExpectedValues)113da4a5dd1SPatrick Venture TEST_F(DbusPassiveTestObj, ReadReturnsExpectedValues)
114da4a5dd1SPatrick Venture {
1150ef1faf7SPatrick Venture     // Verify read is returning the values.
1160ef1faf7SPatrick Venture     ReadReturn v;
1170ef1faf7SPatrick Venture     v.value = 0.01;
1180ef1faf7SPatrick Venture     // TODO: updated is set when the value is created, so we can range check
1190ef1faf7SPatrick Venture     // it.
1200ef1faf7SPatrick Venture     ReadReturn r = passive->read();
1210ef1faf7SPatrick Venture     EXPECT_EQ(v.value, r.value);
1220ef1faf7SPatrick Venture }
1230ef1faf7SPatrick Venture 
TEST_F(DbusPassiveTestObj,SetValueUpdatesValue)124da4a5dd1SPatrick Venture TEST_F(DbusPassiveTestObj, SetValueUpdatesValue)
125da4a5dd1SPatrick Venture {
1260ef1faf7SPatrick Venture     // Verify setvalue does as advertised.
1270ef1faf7SPatrick Venture 
1280ef1faf7SPatrick Venture     double value = 0.01;
1290ef1faf7SPatrick Venture     passive->setValue(value);
1300ef1faf7SPatrick Venture 
1310ef1faf7SPatrick Venture     // TODO: updated is set when the value is set, so we can range check it.
1320ef1faf7SPatrick Venture     ReadReturn r = passive->read();
1330ef1faf7SPatrick Venture     EXPECT_EQ(value, r.value);
1340ef1faf7SPatrick Venture }
1350ef1faf7SPatrick Venture 
TEST_F(DbusPassiveTestObj,GetScaleReturnsExpectedValue)136da4a5dd1SPatrick Venture TEST_F(DbusPassiveTestObj, GetScaleReturnsExpectedValue)
137da4a5dd1SPatrick Venture {
1380ef1faf7SPatrick Venture     // Verify the scale is returned as expected.
1390ef1faf7SPatrick Venture     EXPECT_EQ(_scale, passive->getScale());
1400ef1faf7SPatrick Venture }
1410ef1faf7SPatrick Venture 
TEST_F(DbusPassiveTestObj,getIDReturnsExpectedValue)142563a356fSPatrick Venture TEST_F(DbusPassiveTestObj, getIDReturnsExpectedValue)
143da4a5dd1SPatrick Venture {
144563a356fSPatrick Venture     // Verify getID returns the expected value.
145563a356fSPatrick Venture     EXPECT_EQ(id, passive->getID());
1460ef1faf7SPatrick Venture }
1470ef1faf7SPatrick Venture 
TEST_F(DbusPassiveTestObj,GetMinValueReturnsExpectedValue)1486b9f5999SPatrick Venture TEST_F(DbusPassiveTestObj, GetMinValueReturnsExpectedValue)
1496b9f5999SPatrick Venture {
1506b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(0, passive->getMin());
1516b9f5999SPatrick Venture }
1526b9f5999SPatrick Venture 
TEST_F(DbusPassiveTestObj,VerifyHandlesDbusSignal)153da4a5dd1SPatrick Venture TEST_F(DbusPassiveTestObj, VerifyHandlesDbusSignal)
154da4a5dd1SPatrick Venture {
1550ef1faf7SPatrick Venture     // The dbus passive sensor listens for updates and if it's the Value
1560ef1faf7SPatrick Venture     // property, it needs to handle it.
1570ef1faf7SPatrick Venture 
1580ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
1590ef1faf7SPatrick Venture         .WillOnce(Return(nullptr));
160b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
1610ef1faf7SPatrick Venture 
1620ef1faf7SPatrick Venture     const char* Value = "Value";
1630ef1faf7SPatrick Venture     int64_t xValue = 10000;
1640ef1faf7SPatrick Venture     const char* intf = "xyz.openbmc_project.Sensor.Value";
1651f802f5eSJames Feist     // string, std::map<std::string, std::variant<int64_t>>
1660ef1faf7SPatrick Venture     // msg.read(msgSensor, msgData);
1670ef1faf7SPatrick Venture 
168da4a5dd1SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
169*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
170*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
1710ef1faf7SPatrick Venture             const char** s = static_cast<const char**>(p);
1720ef1faf7SPatrick Venture             // Read the first parameter, the string.
1730ef1faf7SPatrick Venture             *s = intf;
1740ef1faf7SPatrick Venture             return 0;
1750ef1faf7SPatrick Venture         }))
176*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
177*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
1780ef1faf7SPatrick Venture             const char** s = static_cast<const char**>(p);
1790ef1faf7SPatrick Venture             *s = Value;
1800ef1faf7SPatrick Venture             // Read the string in the pair (dictionary).
1810ef1faf7SPatrick Venture             return 0;
1820ef1faf7SPatrick Venture         }));
1830ef1faf7SPatrick Venture 
1840ef1faf7SPatrick Venture     // std::map
1850ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
1860ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
1870ef1faf7SPatrick Venture         .WillOnce(Return(0));
1880ef1faf7SPatrick Venture 
1890ef1faf7SPatrick Venture     // while !at_end()
1900ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
1910ef1faf7SPatrick Venture         .WillOnce(Return(0))
1920ef1faf7SPatrick Venture         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
1930ef1faf7SPatrick Venture 
1940ef1faf7SPatrick Venture     // std::pair
1950ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
1960ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
1970ef1faf7SPatrick Venture         .WillOnce(Return(0));
1980ef1faf7SPatrick Venture 
1990ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
2000ef1faf7SPatrick Venture                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
2010ef1faf7SPatrick Venture         .WillOnce(Return(1));
2020ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
2030ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
2040ef1faf7SPatrick Venture         .WillOnce(Return(0));
2050ef1faf7SPatrick Venture 
206da4a5dd1SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
207*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
208*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
2090ef1faf7SPatrick Venture             int64_t* s = static_cast<int64_t*>(p);
2100ef1faf7SPatrick Venture             *s = xValue;
2110ef1faf7SPatrick Venture             return 0;
2120ef1faf7SPatrick Venture         }));
2130ef1faf7SPatrick Venture 
2140ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
2150ef1faf7SPatrick Venture         .WillOnce(Return(0))  /* variant. */
2160ef1faf7SPatrick Venture         .WillOnce(Return(0))  /* std::pair */
2170ef1faf7SPatrick Venture         .WillOnce(Return(0)); /* std::map */
2180ef1faf7SPatrick Venture 
2197af157b1SPatrick Venture     int rv = handleSensorValue(msg, passive);
2200ef1faf7SPatrick Venture     EXPECT_EQ(rv, 0); // It's always 0.
2210ef1faf7SPatrick Venture 
2220ef1faf7SPatrick Venture     ReadReturn r = passive->read();
2230ef1faf7SPatrick Venture     EXPECT_EQ(10, r.value);
2240ef1faf7SPatrick Venture }
2250ef1faf7SPatrick Venture 
TEST_F(DbusPassiveTestObj,VerifyIgnoresOtherPropertySignal)226da4a5dd1SPatrick Venture TEST_F(DbusPassiveTestObj, VerifyIgnoresOtherPropertySignal)
227da4a5dd1SPatrick Venture {
2280ef1faf7SPatrick Venture     // The dbus passive sensor listens for updates and if it's the Value
2290ef1faf7SPatrick Venture     // property, it needs to handle it.  In this case, it won't be.
2300ef1faf7SPatrick Venture 
2310ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
2320ef1faf7SPatrick Venture         .WillOnce(Return(nullptr));
233b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
2340ef1faf7SPatrick Venture 
2350ef1faf7SPatrick Venture     const char* Scale = "Scale";
2360ef1faf7SPatrick Venture     int64_t xScale = -6;
2370ef1faf7SPatrick Venture     const char* intf = "xyz.openbmc_project.Sensor.Value";
2381f802f5eSJames Feist     // string, std::map<std::string, std::variant<int64_t>>
2390ef1faf7SPatrick Venture     // msg.read(msgSensor, msgData);
2400ef1faf7SPatrick Venture 
241da4a5dd1SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
242*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
243*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
2440ef1faf7SPatrick Venture             const char** s = static_cast<const char**>(p);
2450ef1faf7SPatrick Venture             // Read the first parameter, the string.
2460ef1faf7SPatrick Venture             *s = intf;
2470ef1faf7SPatrick Venture             return 0;
2480ef1faf7SPatrick Venture         }))
249*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
250*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
2510ef1faf7SPatrick Venture             const char** s = static_cast<const char**>(p);
2520ef1faf7SPatrick Venture             *s = Scale;
2530ef1faf7SPatrick Venture             // Read the string in the pair (dictionary).
2540ef1faf7SPatrick Venture             return 0;
2550ef1faf7SPatrick Venture         }));
2560ef1faf7SPatrick Venture 
2570ef1faf7SPatrick Venture     // std::map
2580ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
2590ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
2600ef1faf7SPatrick Venture         .WillOnce(Return(0));
2610ef1faf7SPatrick Venture 
2620ef1faf7SPatrick Venture     // while !at_end()
2630ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
2640ef1faf7SPatrick Venture         .WillOnce(Return(0))
2650ef1faf7SPatrick Venture         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
2660ef1faf7SPatrick Venture 
2670ef1faf7SPatrick Venture     // std::pair
2680ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
2690ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
2700ef1faf7SPatrick Venture         .WillOnce(Return(0));
2710ef1faf7SPatrick Venture 
2720ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
2730ef1faf7SPatrick Venture                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
2740ef1faf7SPatrick Venture         .WillOnce(Return(1));
2750ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
2760ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
2770ef1faf7SPatrick Venture         .WillOnce(Return(0));
2780ef1faf7SPatrick Venture 
279da4a5dd1SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
280*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
281*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
2820ef1faf7SPatrick Venture             int64_t* s = static_cast<int64_t*>(p);
2830ef1faf7SPatrick Venture             *s = xScale;
2840ef1faf7SPatrick Venture             return 0;
2850ef1faf7SPatrick Venture         }));
2860ef1faf7SPatrick Venture 
2870ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
2880ef1faf7SPatrick Venture         .WillOnce(Return(0))  /* variant. */
2890ef1faf7SPatrick Venture         .WillOnce(Return(0))  /* std::pair */
2900ef1faf7SPatrick Venture         .WillOnce(Return(0)); /* std::map */
2910ef1faf7SPatrick Venture 
2927af157b1SPatrick Venture     int rv = handleSensorValue(msg, passive);
2930ef1faf7SPatrick Venture     EXPECT_EQ(rv, 0); // It's always 0.
2940ef1faf7SPatrick Venture 
2950ef1faf7SPatrick Venture     ReadReturn r = passive->read();
2960ef1faf7SPatrick Venture     EXPECT_EQ(0.01, r.value);
2970ef1faf7SPatrick Venture }
2988f73ad76SAlex.Song 
TEST_F(DbusPassiveTestObj,VerifyCriticalThresholdAssert)29936b7d8ebSJames Feist TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdAssert)
30036b7d8ebSJames Feist {
30136b7d8ebSJames Feist     // Verifies when a threshold is crossed the sensor goes into error state
30236b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
30336b7d8ebSJames Feist         .WillOnce(Return(nullptr));
304b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
30536b7d8ebSJames Feist 
30636b7d8ebSJames Feist     const char* criticalAlarm = "CriticalAlarmHigh";
30736b7d8ebSJames Feist     bool alarm = true;
30836b7d8ebSJames Feist     const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
30936b7d8ebSJames Feist 
31036b7d8ebSJames Feist     passive->setFailed(false);
31136b7d8ebSJames Feist 
31236b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
313*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
314*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
31536b7d8ebSJames Feist             const char** s = static_cast<const char**>(p);
31636b7d8ebSJames Feist             // Read the first parameter, the string.
31736b7d8ebSJames Feist             *s = intf;
31836b7d8ebSJames Feist             return 0;
31936b7d8ebSJames Feist         }))
320*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
321*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
32236b7d8ebSJames Feist             const char** s = static_cast<const char**>(p);
32336b7d8ebSJames Feist             *s = criticalAlarm;
32436b7d8ebSJames Feist             // Read the string in the pair (dictionary).
32536b7d8ebSJames Feist             return 0;
32636b7d8ebSJames Feist         }));
32736b7d8ebSJames Feist 
32836b7d8ebSJames Feist     // std::map
32936b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
33036b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
33136b7d8ebSJames Feist         .WillOnce(Return(0));
33236b7d8ebSJames Feist 
33336b7d8ebSJames Feist     // while !at_end()
33436b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
33536b7d8ebSJames Feist         .WillOnce(Return(0))
33636b7d8ebSJames Feist         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
33736b7d8ebSJames Feist 
33836b7d8ebSJames Feist     // std::pair
33936b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
34036b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
34136b7d8ebSJames Feist         .WillOnce(Return(0));
34236b7d8ebSJames Feist 
34336b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
34436b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
34536b7d8ebSJames Feist         .WillOnce(Return(0));
34636b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
34736b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
34836b7d8ebSJames Feist         .WillOnce(Return(0));
34936b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
35036b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
35136b7d8ebSJames Feist         .WillOnce(Return(1));
35236b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
35336b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
35436b7d8ebSJames Feist         .WillOnce(Return(0));
35536b7d8ebSJames Feist 
35636b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
357*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
358*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
35936b7d8ebSJames Feist             bool* s = static_cast<bool*>(p);
36036b7d8ebSJames Feist             *s = alarm;
36136b7d8ebSJames Feist             return 0;
36236b7d8ebSJames Feist         }));
36336b7d8ebSJames Feist 
36436b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
36536b7d8ebSJames Feist         .WillOnce(Return(0))  /* variant. */
36636b7d8ebSJames Feist         .WillOnce(Return(0))  /* std::pair */
36736b7d8ebSJames Feist         .WillOnce(Return(0)); /* std::map */
36836b7d8ebSJames Feist 
3697af157b1SPatrick Venture     int rv = handleSensorValue(msg, passive);
37036b7d8ebSJames Feist     EXPECT_EQ(rv, 0); // It's always 0.
37136b7d8ebSJames Feist     bool failed = passive->getFailed();
37236b7d8ebSJames Feist     EXPECT_EQ(failed, true);
37336b7d8ebSJames Feist }
37436b7d8ebSJames Feist 
TEST_F(DbusPassiveTestObj,VerifyCriticalThresholdDeassert)37536b7d8ebSJames Feist TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdDeassert)
37636b7d8ebSJames Feist {
37736b7d8ebSJames Feist     // Verifies when a threshold is deasserted a failed sensor goes back into
37836b7d8ebSJames Feist     // the normal state
37936b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
38036b7d8ebSJames Feist         .WillOnce(Return(nullptr));
381b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
38236b7d8ebSJames Feist 
38336b7d8ebSJames Feist     const char* criticalAlarm = "CriticalAlarmHigh";
38436b7d8ebSJames Feist     bool alarm = false;
38536b7d8ebSJames Feist     const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
38636b7d8ebSJames Feist 
38736b7d8ebSJames Feist     passive->setFailed(true);
38836b7d8ebSJames Feist 
38936b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
390*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
391*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
39236b7d8ebSJames Feist             const char** s = static_cast<const char**>(p);
39336b7d8ebSJames Feist             // Read the first parameter, the string.
39436b7d8ebSJames Feist             *s = intf;
39536b7d8ebSJames Feist             return 0;
39636b7d8ebSJames Feist         }))
397*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
398*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
39936b7d8ebSJames Feist             const char** s = static_cast<const char**>(p);
40036b7d8ebSJames Feist             *s = criticalAlarm;
40136b7d8ebSJames Feist             // Read the string in the pair (dictionary).
40236b7d8ebSJames Feist             return 0;
40336b7d8ebSJames Feist         }));
40436b7d8ebSJames Feist 
40536b7d8ebSJames Feist     // std::map
40636b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
40736b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
40836b7d8ebSJames Feist         .WillOnce(Return(0));
40936b7d8ebSJames Feist 
41036b7d8ebSJames Feist     // while !at_end()
41136b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
41236b7d8ebSJames Feist         .WillOnce(Return(0))
41336b7d8ebSJames Feist         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
41436b7d8ebSJames Feist 
41536b7d8ebSJames Feist     // std::pair
41636b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
41736b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
41836b7d8ebSJames Feist         .WillOnce(Return(0));
41936b7d8ebSJames Feist 
42036b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
42136b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
42236b7d8ebSJames Feist         .WillOnce(Return(0));
42336b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
42436b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
42536b7d8ebSJames Feist         .WillOnce(Return(0));
42636b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
42736b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
42836b7d8ebSJames Feist         .WillOnce(Return(1));
42936b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
43036b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
43136b7d8ebSJames Feist         .WillOnce(Return(0));
43236b7d8ebSJames Feist 
43336b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
434*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
435*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
43636b7d8ebSJames Feist             bool* s = static_cast<bool*>(p);
43736b7d8ebSJames Feist             *s = alarm;
43836b7d8ebSJames Feist             return 0;
43936b7d8ebSJames Feist         }));
44036b7d8ebSJames Feist 
44136b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
44236b7d8ebSJames Feist         .WillOnce(Return(0))  /* variant. */
44336b7d8ebSJames Feist         .WillOnce(Return(0))  /* std::pair */
44436b7d8ebSJames Feist         .WillOnce(Return(0)); /* std::map */
44536b7d8ebSJames Feist 
4467af157b1SPatrick Venture     int rv = handleSensorValue(msg, passive);
44736b7d8ebSJames Feist     EXPECT_EQ(rv, 0); // It's always 0.
44836b7d8ebSJames Feist     bool failed = passive->getFailed();
44936b7d8ebSJames Feist     EXPECT_EQ(failed, false);
45036b7d8ebSJames Feist }
4516b9f5999SPatrick Venture 
TEST_F(DbusPassiveTestObj,VerifyAvailableDeassert)4528f73ad76SAlex.Song TEST_F(DbusPassiveTestObj, VerifyAvailableDeassert)
4538f73ad76SAlex.Song {
4548f73ad76SAlex.Song     // Verifies when Availble is deasserted && unavailableAsFailed == true,
4558f73ad76SAlex.Song     // the sensor goes into error state
4568f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
4578f73ad76SAlex.Song         .WillOnce(Return(nullptr));
458b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
4598f73ad76SAlex.Song 
4608f73ad76SAlex.Song     const char* property = "Available";
4618f73ad76SAlex.Song     bool asserted = false;
4628f73ad76SAlex.Song     const char* intf = "xyz.openbmc_project.State.Decorator.Availability";
4638f73ad76SAlex.Song 
4648f73ad76SAlex.Song     passive->setAvailable(true);
4658f73ad76SAlex.Song 
4668f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
467*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
468*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
4698f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
4708f73ad76SAlex.Song             // Read the first parameter, the string.
4718f73ad76SAlex.Song             *s = intf;
4728f73ad76SAlex.Song             return 0;
4738f73ad76SAlex.Song         }))
474*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
475*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
4768f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
4778f73ad76SAlex.Song             *s = property;
4788f73ad76SAlex.Song             // Read the string in the pair (dictionary).
4798f73ad76SAlex.Song             return 0;
4808f73ad76SAlex.Song         }));
4818f73ad76SAlex.Song 
4828f73ad76SAlex.Song     // std::map
4838f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
4848f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
4858f73ad76SAlex.Song         .WillOnce(Return(0));
4868f73ad76SAlex.Song 
4878f73ad76SAlex.Song     // while !at_end()
4888f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
4898f73ad76SAlex.Song         .WillOnce(Return(0))
4908f73ad76SAlex.Song         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
4918f73ad76SAlex.Song 
4928f73ad76SAlex.Song     // std::pair
4938f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
4948f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
4958f73ad76SAlex.Song         .WillOnce(Return(0));
4968f73ad76SAlex.Song 
4978f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
4988f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
4998f73ad76SAlex.Song         .WillOnce(Return(0));
5008f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5018f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
5028f73ad76SAlex.Song         .WillOnce(Return(0));
5038f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5048f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
5058f73ad76SAlex.Song         .WillOnce(Return(1));
5068f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5078f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
5088f73ad76SAlex.Song         .WillOnce(Return(0));
5098f73ad76SAlex.Song 
5108f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
511*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
512*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
5138f73ad76SAlex.Song             bool* s = static_cast<bool*>(p);
5148f73ad76SAlex.Song             *s = asserted;
5158f73ad76SAlex.Song             return 0;
5168f73ad76SAlex.Song         }));
5178f73ad76SAlex.Song 
5188f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
5198f73ad76SAlex.Song         .WillOnce(Return(0))  /* variant. */
5208f73ad76SAlex.Song         .WillOnce(Return(0))  /* std::pair */
5218f73ad76SAlex.Song         .WillOnce(Return(0)); /* std::map */
5228f73ad76SAlex.Song 
5238f73ad76SAlex.Song     int rv = handleSensorValue(msg, passive);
5248f73ad76SAlex.Song     EXPECT_EQ(rv, 0); // It's always 0.
5258f73ad76SAlex.Song     bool failed = passive->getFailed();
5268f73ad76SAlex.Song     EXPECT_EQ(failed, true);
5278f73ad76SAlex.Song }
5288f73ad76SAlex.Song 
TEST_F(DbusPassiveTestObj,VerifyAvailableAssert)5298f73ad76SAlex.Song TEST_F(DbusPassiveTestObj, VerifyAvailableAssert)
5308f73ad76SAlex.Song {
5318f73ad76SAlex.Song     // Verifies when Availble is asserted && unavailableAsFailed == true,
5328f73ad76SAlex.Song     // an error sensor goes back to normal state
5338f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
5348f73ad76SAlex.Song         .WillOnce(Return(nullptr));
535b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
5368f73ad76SAlex.Song 
5378f73ad76SAlex.Song     const char* property = "Available";
5388f73ad76SAlex.Song     bool asserted = true;
5398f73ad76SAlex.Song     const char* intf = "xyz.openbmc_project.State.Decorator.Availability";
5408f73ad76SAlex.Song 
5418f73ad76SAlex.Song     passive->setAvailable(false);
5428f73ad76SAlex.Song     bool failed = passive->getFailed();
5438f73ad76SAlex.Song     EXPECT_EQ(failed, true);
5448f73ad76SAlex.Song 
5458f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
546*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
547*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
5488f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
5498f73ad76SAlex.Song             // Read the first parameter, the string.
5508f73ad76SAlex.Song             *s = intf;
5518f73ad76SAlex.Song             return 0;
5528f73ad76SAlex.Song         }))
553*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
554*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
5558f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
5568f73ad76SAlex.Song             *s = property;
5578f73ad76SAlex.Song             // Read the string in the pair (dictionary).
5588f73ad76SAlex.Song             return 0;
5598f73ad76SAlex.Song         }));
5608f73ad76SAlex.Song 
5618f73ad76SAlex.Song     // std::map
5628f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5638f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
5648f73ad76SAlex.Song         .WillOnce(Return(0));
5658f73ad76SAlex.Song 
5668f73ad76SAlex.Song     // while !at_end()
5678f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
5688f73ad76SAlex.Song         .WillOnce(Return(0))
5698f73ad76SAlex.Song         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
5708f73ad76SAlex.Song 
5718f73ad76SAlex.Song     // std::pair
5728f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5738f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
5748f73ad76SAlex.Song         .WillOnce(Return(0));
5758f73ad76SAlex.Song 
5768f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5778f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
5788f73ad76SAlex.Song         .WillOnce(Return(0));
5798f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5808f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
5818f73ad76SAlex.Song         .WillOnce(Return(0));
5828f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5838f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
5848f73ad76SAlex.Song         .WillOnce(Return(1));
5858f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5868f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
5878f73ad76SAlex.Song         .WillOnce(Return(0));
5888f73ad76SAlex.Song 
5898f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
590*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
591*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
5928f73ad76SAlex.Song             bool* s = static_cast<bool*>(p);
5938f73ad76SAlex.Song             *s = asserted;
5948f73ad76SAlex.Song             return 0;
5958f73ad76SAlex.Song         }));
5968f73ad76SAlex.Song 
5978f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
5988f73ad76SAlex.Song         .WillOnce(Return(0))  /* variant. */
5998f73ad76SAlex.Song         .WillOnce(Return(0))  /* std::pair */
6008f73ad76SAlex.Song         .WillOnce(Return(0)); /* std::map */
6018f73ad76SAlex.Song 
6028f73ad76SAlex.Song     int rv = handleSensorValue(msg, passive);
6038f73ad76SAlex.Song     EXPECT_EQ(rv, 0); // It's always 0.
6048f73ad76SAlex.Song     failed = passive->getFailed();
6058f73ad76SAlex.Song     EXPECT_EQ(failed, false);
6068f73ad76SAlex.Song }
6078f73ad76SAlex.Song 
6088f73ad76SAlex.Song class DbusPassiveTestUnaSensorNotAsFailedObj : public ::testing::Test
6098f73ad76SAlex.Song {
6108f73ad76SAlex.Song   protected:
DbusPassiveTestUnaSensorNotAsFailedObj()6118f73ad76SAlex.Song     DbusPassiveTestUnaSensorNotAsFailedObj() :
6128f73ad76SAlex.Song         sdbus_mock(),
6138f73ad76SAlex.Song         bus_mock(std::move(sdbusplus::get_mocked_new(&sdbus_mock))),
6148f73ad76SAlex.Song         helper(std::make_unique<DbusHelperMock>())
6158f73ad76SAlex.Song     {
6168f73ad76SAlex.Song         EXPECT_CALL(*helper, getService(StrEq(SensorIntf), StrEq(path)))
6178f73ad76SAlex.Song             .WillOnce(Return("asdf"));
6188f73ad76SAlex.Song 
6198f73ad76SAlex.Song         EXPECT_CALL(*helper,
6208f73ad76SAlex.Song                     getProperties(StrEq("asdf"), StrEq(path), NotNull()))
621*a1ae4fa1SHarvey.Wu             .WillOnce(Invoke([&]([[maybe_unused]] const std::string& service,
622*a1ae4fa1SHarvey.Wu                                  [[maybe_unused]] const std::string& path,
6238f73ad76SAlex.Song                                  SensorProperties* prop) {
6248f73ad76SAlex.Song                 prop->scale = _scale;
6258f73ad76SAlex.Song                 prop->value = _value;
6268f73ad76SAlex.Song                 prop->unit = "x";
6278f73ad76SAlex.Song                 prop->min = 0;
6288f73ad76SAlex.Song                 prop->max = 0;
6298f73ad76SAlex.Song                 prop->available = true;
6308f73ad76SAlex.Song             }));
6318f73ad76SAlex.Song         EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
6328f73ad76SAlex.Song             .WillOnce(Return(false));
6338f73ad76SAlex.Song 
6348f73ad76SAlex.Song         auto info = conf::SensorConfig();
6358f73ad76SAlex.Song         info.unavailableAsFailed = false;
6368f73ad76SAlex.Song         ri = DbusPassive::createDbusPassive(bus_mock, type, id,
6378f73ad76SAlex.Song                                             std::move(helper), &info, nullptr);
6388f73ad76SAlex.Song         passive = reinterpret_cast<DbusPassive*>(ri.get());
6398f73ad76SAlex.Song         EXPECT_FALSE(passive == nullptr);
6408f73ad76SAlex.Song     }
6418f73ad76SAlex.Song 
6428f73ad76SAlex.Song     sdbusplus::SdBusMock sdbus_mock;
643b228bc30SPatrick Williams     sdbusplus::bus_t bus_mock;
6448f73ad76SAlex.Song     std::unique_ptr<DbusHelperMock> helper;
6458f73ad76SAlex.Song     std::string type = "temp";
6468f73ad76SAlex.Song     std::string id = "id";
6478f73ad76SAlex.Song     std::string path = "/xyz/openbmc_project/sensors/temperature/id";
6488f73ad76SAlex.Song     int64_t _scale = -3;
6498f73ad76SAlex.Song     int64_t _value = 10;
6508f73ad76SAlex.Song 
6518f73ad76SAlex.Song     std::unique_ptr<ReadInterface> ri;
6528f73ad76SAlex.Song     DbusPassive* passive;
6538f73ad76SAlex.Song };
6548f73ad76SAlex.Song 
TEST_F(DbusPassiveTestUnaSensorNotAsFailedObj,VerifyAvailableDeassert)6558f73ad76SAlex.Song TEST_F(DbusPassiveTestUnaSensorNotAsFailedObj, VerifyAvailableDeassert)
6568f73ad76SAlex.Song {
6578f73ad76SAlex.Song     // Verifies when Availble is deasserted && unavailableAsFailed == false,
6588f73ad76SAlex.Song     // the sensor remains at OK state but reading goes to NaN.
6598f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
6608f73ad76SAlex.Song         .WillOnce(Return(nullptr));
661b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
6628f73ad76SAlex.Song 
6638f73ad76SAlex.Song     const char* property = "Available";
6648f73ad76SAlex.Song     bool asserted = false;
6658f73ad76SAlex.Song     const char* intf = "xyz.openbmc_project.State.Decorator.Availability";
6668f73ad76SAlex.Song 
6678f73ad76SAlex.Song     passive->setAvailable(true);
6688f73ad76SAlex.Song 
6698f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
670*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
671*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
6728f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
6738f73ad76SAlex.Song             // Read the first parameter, the string.
6748f73ad76SAlex.Song             *s = intf;
6758f73ad76SAlex.Song             return 0;
6768f73ad76SAlex.Song         }))
677*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
678*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
6798f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
6808f73ad76SAlex.Song             *s = property;
6818f73ad76SAlex.Song             // Read the string in the pair (dictionary).
6828f73ad76SAlex.Song             return 0;
6838f73ad76SAlex.Song         }));
6848f73ad76SAlex.Song 
6858f73ad76SAlex.Song     // std::map
6868f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
6878f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
6888f73ad76SAlex.Song         .WillOnce(Return(0));
6898f73ad76SAlex.Song 
6908f73ad76SAlex.Song     // while !at_end()
6918f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
6928f73ad76SAlex.Song         .WillOnce(Return(0))
6938f73ad76SAlex.Song         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
6948f73ad76SAlex.Song 
6958f73ad76SAlex.Song     // std::pair
6968f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
6978f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
6988f73ad76SAlex.Song         .WillOnce(Return(0));
6998f73ad76SAlex.Song 
7008f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7018f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
7028f73ad76SAlex.Song         .WillOnce(Return(0));
7038f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7048f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
7058f73ad76SAlex.Song         .WillOnce(Return(0));
7068f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7078f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
7088f73ad76SAlex.Song         .WillOnce(Return(1));
7098f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7108f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
7118f73ad76SAlex.Song         .WillOnce(Return(0));
7128f73ad76SAlex.Song 
7138f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
714*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
715*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
7168f73ad76SAlex.Song             bool* s = static_cast<bool*>(p);
7178f73ad76SAlex.Song             *s = asserted;
7188f73ad76SAlex.Song             return 0;
7198f73ad76SAlex.Song         }));
7208f73ad76SAlex.Song 
7218f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
7228f73ad76SAlex.Song         .WillOnce(Return(0))  /* variant. */
7238f73ad76SAlex.Song         .WillOnce(Return(0))  /* std::pair */
7248f73ad76SAlex.Song         .WillOnce(Return(0)); /* std::map */
7258f73ad76SAlex.Song 
7268f73ad76SAlex.Song     int rv = handleSensorValue(msg, passive);
7278f73ad76SAlex.Song     EXPECT_EQ(rv, 0); // It's always 0.
7288f73ad76SAlex.Song     bool failed = passive->getFailed();
7298f73ad76SAlex.Song     EXPECT_EQ(failed, false);
7308f73ad76SAlex.Song     ReadReturn r = passive->read();
7318f73ad76SAlex.Song     EXPECT_FALSE(std::isfinite(r.value));
7328f73ad76SAlex.Song }
7338f73ad76SAlex.Song 
TEST_F(DbusPassiveTestUnaSensorNotAsFailedObj,VerifyAvailableAssert)7348f73ad76SAlex.Song TEST_F(DbusPassiveTestUnaSensorNotAsFailedObj, VerifyAvailableAssert)
7358f73ad76SAlex.Song {
7368f73ad76SAlex.Song     // Verifies when a sensor's state goes from unavailble to available
7378f73ad76SAlex.Song     // && unavailableAsFailed == false, this sensor remains at OK state.
7388f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
7398f73ad76SAlex.Song         .WillOnce(Return(nullptr));
740b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
7418f73ad76SAlex.Song 
7428f73ad76SAlex.Song     const char* property = "Available";
7438f73ad76SAlex.Song     bool asserted = true;
7448f73ad76SAlex.Song     const char* intf = "xyz.openbmc_project.State.Decorator.Availability";
7458f73ad76SAlex.Song 
7468f73ad76SAlex.Song     passive->setAvailable(false);
7478f73ad76SAlex.Song     bool failed = passive->getFailed();
7488f73ad76SAlex.Song     EXPECT_EQ(failed, false);
7498f73ad76SAlex.Song 
7508f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
751*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
752*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
7538f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
7548f73ad76SAlex.Song             // Read the first parameter, the string.
7558f73ad76SAlex.Song             *s = intf;
7568f73ad76SAlex.Song             return 0;
7578f73ad76SAlex.Song         }))
758*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
759*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
7608f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
7618f73ad76SAlex.Song             *s = property;
7628f73ad76SAlex.Song             // Read the string in the pair (dictionary).
7638f73ad76SAlex.Song             return 0;
7648f73ad76SAlex.Song         }));
7658f73ad76SAlex.Song 
7668f73ad76SAlex.Song     // std::map
7678f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7688f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
7698f73ad76SAlex.Song         .WillOnce(Return(0));
7708f73ad76SAlex.Song 
7718f73ad76SAlex.Song     // while !at_end()
7728f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
7738f73ad76SAlex.Song         .WillOnce(Return(0))
7748f73ad76SAlex.Song         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
7758f73ad76SAlex.Song 
7768f73ad76SAlex.Song     // std::pair
7778f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7788f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
7798f73ad76SAlex.Song         .WillOnce(Return(0));
7808f73ad76SAlex.Song 
7818f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7828f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
7838f73ad76SAlex.Song         .WillOnce(Return(0));
7848f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7858f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
7868f73ad76SAlex.Song         .WillOnce(Return(0));
7878f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7888f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
7898f73ad76SAlex.Song         .WillOnce(Return(1));
7908f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7918f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
7928f73ad76SAlex.Song         .WillOnce(Return(0));
7938f73ad76SAlex.Song 
7948f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
795*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
796*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
7978f73ad76SAlex.Song             bool* s = static_cast<bool*>(p);
7988f73ad76SAlex.Song             *s = asserted;
7998f73ad76SAlex.Song             return 0;
8008f73ad76SAlex.Song         }));
8018f73ad76SAlex.Song 
8028f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
8038f73ad76SAlex.Song         .WillOnce(Return(0))  /* variant. */
8048f73ad76SAlex.Song         .WillOnce(Return(0))  /* std::pair */
8058f73ad76SAlex.Song         .WillOnce(Return(0)); /* std::map */
8068f73ad76SAlex.Song 
8078f73ad76SAlex.Song     int rv = handleSensorValue(msg, passive);
8088f73ad76SAlex.Song     EXPECT_EQ(rv, 0); // It's always 0.
8098f73ad76SAlex.Song     failed = passive->getFailed();
8108f73ad76SAlex.Song     EXPECT_EQ(failed, false);
8118f73ad76SAlex.Song }
8128f73ad76SAlex.Song 
GetPropertiesMax3k(const std::string & service,const std::string & path,SensorProperties * prop)813*a1ae4fa1SHarvey.Wu void GetPropertiesMax3k([[maybe_unused]] const std::string& service,
814*a1ae4fa1SHarvey.Wu                         [[maybe_unused]] const std::string& path,
8159b93692dSPatrick Venture                         SensorProperties* prop)
8166b9f5999SPatrick Venture {
8176b9f5999SPatrick Venture     prop->scale = -3;
8186b9f5999SPatrick Venture     prop->value = 10;
8196b9f5999SPatrick Venture     prop->unit = "x";
8206b9f5999SPatrick Venture     prop->min = 0;
8216b9f5999SPatrick Venture     prop->max = 3000;
8226b9f5999SPatrick Venture }
8236b9f5999SPatrick Venture 
8249b93692dSPatrick Venture using GetPropertiesFunction = std::function<void(
8259b93692dSPatrick Venture     const std::string&, const std::string&, SensorProperties*)>;
8266b9f5999SPatrick Venture 
8276b9f5999SPatrick Venture // TODO: There is definitely a cleaner way to do this.
8286b9f5999SPatrick Venture class DbusPassiveTest3kMaxObj : public ::testing::Test
8296b9f5999SPatrick Venture {
8306b9f5999SPatrick Venture   protected:
DbusPassiveTest3kMaxObj()8316b9f5999SPatrick Venture     DbusPassiveTest3kMaxObj() :
8326b9f5999SPatrick Venture         sdbus_mock(),
8338729eb98SPatrick Venture         bus_mock(std::move(sdbusplus::get_mocked_new(&sdbus_mock))),
8348729eb98SPatrick Venture         helper(std::make_unique<DbusHelperMock>())
8356b9f5999SPatrick Venture     {
8369b93692dSPatrick Venture         EXPECT_CALL(*helper, getService(StrEq(SensorIntf), StrEq(path)))
8376b9f5999SPatrick Venture             .WillOnce(Return("asdf"));
8386b9f5999SPatrick Venture 
8398729eb98SPatrick Venture         EXPECT_CALL(*helper,
8409b93692dSPatrick Venture                     getProperties(StrEq("asdf"), StrEq(path), NotNull()))
8416b9f5999SPatrick Venture             .WillOnce(_getProps);
8429b93692dSPatrick Venture         EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
8436b9f5999SPatrick Venture             .WillOnce(Return(false));
8446b9f5999SPatrick Venture 
8456b9f5999SPatrick Venture         auto info = conf::SensorConfig();
8468729eb98SPatrick Venture         ri = DbusPassive::createDbusPassive(bus_mock, type, id,
8478729eb98SPatrick Venture                                             std::move(helper), &info, nullptr);
8486b9f5999SPatrick Venture         passive = reinterpret_cast<DbusPassive*>(ri.get());
8496b9f5999SPatrick Venture         EXPECT_FALSE(passive == nullptr);
8506b9f5999SPatrick Venture     }
8516b9f5999SPatrick Venture 
8526b9f5999SPatrick Venture     sdbusplus::SdBusMock sdbus_mock;
853b228bc30SPatrick Williams     sdbusplus::bus_t bus_mock;
8548729eb98SPatrick Venture     std::unique_ptr<DbusHelperMock> helper;
8556b9f5999SPatrick Venture     std::string type = "temp";
8566b9f5999SPatrick Venture     std::string id = "id";
8576b9f5999SPatrick Venture     std::string path = "/xyz/openbmc_project/sensors/temperature/id";
8586b9f5999SPatrick Venture     int64_t _scale = -3;
8596b9f5999SPatrick Venture     int64_t _value = 10;
8606b9f5999SPatrick Venture 
8616b9f5999SPatrick Venture     std::unique_ptr<ReadInterface> ri;
8626b9f5999SPatrick Venture     DbusPassive* passive;
8636b9f5999SPatrick Venture     GetPropertiesFunction _getProps = &GetPropertiesMax3k;
8646b9f5999SPatrick Venture };
8656b9f5999SPatrick Venture 
TEST_F(DbusPassiveTest3kMaxObj,ReadMinAndMaxReturnsExpected)8666b9f5999SPatrick Venture TEST_F(DbusPassiveTest3kMaxObj, ReadMinAndMaxReturnsExpected)
8676b9f5999SPatrick Venture {
8686b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(0, passive->getMin());
8696b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(3, passive->getMax());
8706b9f5999SPatrick Venture }
8716b9f5999SPatrick Venture 
8726b9f5999SPatrick Venture class DbusPassiveTest3kMaxIgnoredObj : public ::testing::Test
8736b9f5999SPatrick Venture {
8746b9f5999SPatrick Venture   protected:
DbusPassiveTest3kMaxIgnoredObj()8756b9f5999SPatrick Venture     DbusPassiveTest3kMaxIgnoredObj() :
8766b9f5999SPatrick Venture         sdbus_mock(),
8778729eb98SPatrick Venture         bus_mock(std::move(sdbusplus::get_mocked_new(&sdbus_mock))),
8788729eb98SPatrick Venture         helper(std::make_unique<DbusHelperMock>())
8796b9f5999SPatrick Venture     {
8809b93692dSPatrick Venture         EXPECT_CALL(*helper, getService(StrEq(SensorIntf), StrEq(path)))
8816b9f5999SPatrick Venture             .WillOnce(Return("asdf"));
8826b9f5999SPatrick Venture 
8838729eb98SPatrick Venture         EXPECT_CALL(*helper,
8849b93692dSPatrick Venture                     getProperties(StrEq("asdf"), StrEq(path), NotNull()))
8856b9f5999SPatrick Venture             .WillOnce(_getProps);
8869b93692dSPatrick Venture         EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
8876b9f5999SPatrick Venture             .WillOnce(Return(false));
8886b9f5999SPatrick Venture 
8896b9f5999SPatrick Venture         auto info = conf::SensorConfig();
8906b9f5999SPatrick Venture         info.ignoreDbusMinMax = true;
8918729eb98SPatrick Venture         ri = DbusPassive::createDbusPassive(bus_mock, type, id,
8928729eb98SPatrick Venture                                             std::move(helper), &info, nullptr);
8936b9f5999SPatrick Venture         passive = reinterpret_cast<DbusPassive*>(ri.get());
8946b9f5999SPatrick Venture         EXPECT_FALSE(passive == nullptr);
8956b9f5999SPatrick Venture     }
8966b9f5999SPatrick Venture 
8976b9f5999SPatrick Venture     sdbusplus::SdBusMock sdbus_mock;
898b228bc30SPatrick Williams     sdbusplus::bus_t bus_mock;
8998729eb98SPatrick Venture     std::unique_ptr<DbusHelperMock> helper;
9006b9f5999SPatrick Venture     std::string type = "temp";
9016b9f5999SPatrick Venture     std::string id = "id";
9026b9f5999SPatrick Venture     std::string path = "/xyz/openbmc_project/sensors/temperature/id";
9036b9f5999SPatrick Venture     int64_t _scale = -3;
9046b9f5999SPatrick Venture     int64_t _value = 10;
9056b9f5999SPatrick Venture 
9066b9f5999SPatrick Venture     std::unique_ptr<ReadInterface> ri;
9076b9f5999SPatrick Venture     DbusPassive* passive;
9086b9f5999SPatrick Venture     GetPropertiesFunction _getProps = &GetPropertiesMax3k;
9096b9f5999SPatrick Venture };
9106b9f5999SPatrick Venture 
TEST_F(DbusPassiveTest3kMaxIgnoredObj,ReadMinAndMaxReturnsExpected)9116b9f5999SPatrick Venture TEST_F(DbusPassiveTest3kMaxIgnoredObj, ReadMinAndMaxReturnsExpected)
9126b9f5999SPatrick Venture {
9136b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(0, passive->getMin());
9146b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(0, passive->getMax());
9156b9f5999SPatrick Venture }
916a076487aSPatrick Venture 
917a076487aSPatrick Venture } // namespace
918a076487aSPatrick Venture } // namespace pid_control
919