xref: /openbmc/phosphor-pid-control/test/dbus_passive_unittest.cpp (revision a1ae4fa1fdd5ab7b83b89fb6372fbfc16290c07c)
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 
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 
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:
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 
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 
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 
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 
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 
1486b9f5999SPatrick Venture TEST_F(DbusPassiveTestObj, GetMinValueReturnsExpectedValue)
1496b9f5999SPatrick Venture {
1506b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(0, passive->getMin());
1516b9f5999SPatrick Venture }
1526b9f5999SPatrick Venture 
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 
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 
29936b7d8ebSJames Feist TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdAssert)
30036b7d8ebSJames Feist {
30136b7d8ebSJames Feist 
30236b7d8ebSJames Feist     // Verifies when a threshold is crossed the sensor goes into error state
30336b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
30436b7d8ebSJames Feist         .WillOnce(Return(nullptr));
305b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
30636b7d8ebSJames Feist 
30736b7d8ebSJames Feist     const char* criticalAlarm = "CriticalAlarmHigh";
30836b7d8ebSJames Feist     bool alarm = true;
30936b7d8ebSJames Feist     const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
31036b7d8ebSJames Feist 
31136b7d8ebSJames Feist     passive->setFailed(false);
31236b7d8ebSJames Feist 
31336b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
314*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
315*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
31636b7d8ebSJames Feist             const char** s = static_cast<const char**>(p);
31736b7d8ebSJames Feist             // Read the first parameter, the string.
31836b7d8ebSJames Feist             *s = intf;
31936b7d8ebSJames Feist             return 0;
32036b7d8ebSJames Feist         }))
321*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
322*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
32336b7d8ebSJames Feist             const char** s = static_cast<const char**>(p);
32436b7d8ebSJames Feist             *s = criticalAlarm;
32536b7d8ebSJames Feist             // Read the string in the pair (dictionary).
32636b7d8ebSJames Feist             return 0;
32736b7d8ebSJames Feist         }));
32836b7d8ebSJames Feist 
32936b7d8ebSJames Feist     // std::map
33036b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
33136b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
33236b7d8ebSJames Feist         .WillOnce(Return(0));
33336b7d8ebSJames Feist 
33436b7d8ebSJames Feist     // while !at_end()
33536b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
33636b7d8ebSJames Feist         .WillOnce(Return(0))
33736b7d8ebSJames Feist         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
33836b7d8ebSJames Feist 
33936b7d8ebSJames Feist     // std::pair
34036b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
34136b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
34236b7d8ebSJames Feist         .WillOnce(Return(0));
34336b7d8ebSJames Feist 
34436b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
34536b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
34636b7d8ebSJames Feist         .WillOnce(Return(0));
34736b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
34836b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
34936b7d8ebSJames Feist         .WillOnce(Return(0));
35036b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
35136b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
35236b7d8ebSJames Feist         .WillOnce(Return(1));
35336b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
35436b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
35536b7d8ebSJames Feist         .WillOnce(Return(0));
35636b7d8ebSJames Feist 
35736b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
358*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
359*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
36036b7d8ebSJames Feist             bool* s = static_cast<bool*>(p);
36136b7d8ebSJames Feist             *s = alarm;
36236b7d8ebSJames Feist             return 0;
36336b7d8ebSJames Feist         }));
36436b7d8ebSJames Feist 
36536b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
36636b7d8ebSJames Feist         .WillOnce(Return(0))  /* variant. */
36736b7d8ebSJames Feist         .WillOnce(Return(0))  /* std::pair */
36836b7d8ebSJames Feist         .WillOnce(Return(0)); /* std::map */
36936b7d8ebSJames Feist 
3707af157b1SPatrick Venture     int rv = handleSensorValue(msg, passive);
37136b7d8ebSJames Feist     EXPECT_EQ(rv, 0); // It's always 0.
37236b7d8ebSJames Feist     bool failed = passive->getFailed();
37336b7d8ebSJames Feist     EXPECT_EQ(failed, true);
37436b7d8ebSJames Feist }
37536b7d8ebSJames Feist 
37636b7d8ebSJames Feist TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdDeassert)
37736b7d8ebSJames Feist {
37836b7d8ebSJames Feist 
37936b7d8ebSJames Feist     // Verifies when a threshold is deasserted a failed sensor goes back into
38036b7d8ebSJames Feist     // the normal state
38136b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
38236b7d8ebSJames Feist         .WillOnce(Return(nullptr));
383b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
38436b7d8ebSJames Feist 
38536b7d8ebSJames Feist     const char* criticalAlarm = "CriticalAlarmHigh";
38636b7d8ebSJames Feist     bool alarm = false;
38736b7d8ebSJames Feist     const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
38836b7d8ebSJames Feist 
38936b7d8ebSJames Feist     passive->setFailed(true);
39036b7d8ebSJames Feist 
39136b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
392*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
393*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
39436b7d8ebSJames Feist             const char** s = static_cast<const char**>(p);
39536b7d8ebSJames Feist             // Read the first parameter, the string.
39636b7d8ebSJames Feist             *s = intf;
39736b7d8ebSJames Feist             return 0;
39836b7d8ebSJames Feist         }))
399*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
400*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
40136b7d8ebSJames Feist             const char** s = static_cast<const char**>(p);
40236b7d8ebSJames Feist             *s = criticalAlarm;
40336b7d8ebSJames Feist             // Read the string in the pair (dictionary).
40436b7d8ebSJames Feist             return 0;
40536b7d8ebSJames Feist         }));
40636b7d8ebSJames Feist 
40736b7d8ebSJames Feist     // std::map
40836b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
40936b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
41036b7d8ebSJames Feist         .WillOnce(Return(0));
41136b7d8ebSJames Feist 
41236b7d8ebSJames Feist     // while !at_end()
41336b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
41436b7d8ebSJames Feist         .WillOnce(Return(0))
41536b7d8ebSJames Feist         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
41636b7d8ebSJames Feist 
41736b7d8ebSJames Feist     // std::pair
41836b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
41936b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
42036b7d8ebSJames Feist         .WillOnce(Return(0));
42136b7d8ebSJames Feist 
42236b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
42336b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
42436b7d8ebSJames Feist         .WillOnce(Return(0));
42536b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
42636b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
42736b7d8ebSJames Feist         .WillOnce(Return(0));
42836b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
42936b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
43036b7d8ebSJames Feist         .WillOnce(Return(1));
43136b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
43236b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
43336b7d8ebSJames Feist         .WillOnce(Return(0));
43436b7d8ebSJames Feist 
43536b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
436*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
437*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
43836b7d8ebSJames Feist             bool* s = static_cast<bool*>(p);
43936b7d8ebSJames Feist             *s = alarm;
44036b7d8ebSJames Feist             return 0;
44136b7d8ebSJames Feist         }));
44236b7d8ebSJames Feist 
44336b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
44436b7d8ebSJames Feist         .WillOnce(Return(0))  /* variant. */
44536b7d8ebSJames Feist         .WillOnce(Return(0))  /* std::pair */
44636b7d8ebSJames Feist         .WillOnce(Return(0)); /* std::map */
44736b7d8ebSJames Feist 
4487af157b1SPatrick Venture     int rv = handleSensorValue(msg, passive);
44936b7d8ebSJames Feist     EXPECT_EQ(rv, 0); // It's always 0.
45036b7d8ebSJames Feist     bool failed = passive->getFailed();
45136b7d8ebSJames Feist     EXPECT_EQ(failed, false);
45236b7d8ebSJames Feist }
4536b9f5999SPatrick Venture 
4548f73ad76SAlex.Song TEST_F(DbusPassiveTestObj, VerifyAvailableDeassert)
4558f73ad76SAlex.Song {
4568f73ad76SAlex.Song 
4578f73ad76SAlex.Song     // Verifies when Availble is deasserted && unavailableAsFailed == true,
4588f73ad76SAlex.Song     // the sensor goes into error state
4598f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
4608f73ad76SAlex.Song         .WillOnce(Return(nullptr));
461b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
4628f73ad76SAlex.Song 
4638f73ad76SAlex.Song     const char* property = "Available";
4648f73ad76SAlex.Song     bool asserted = false;
4658f73ad76SAlex.Song     const char* intf = "xyz.openbmc_project.State.Decorator.Availability";
4668f73ad76SAlex.Song 
4678f73ad76SAlex.Song     passive->setAvailable(true);
4688f73ad76SAlex.Song 
4698f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
470*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
471*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
4728f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
4738f73ad76SAlex.Song             // Read the first parameter, the string.
4748f73ad76SAlex.Song             *s = intf;
4758f73ad76SAlex.Song             return 0;
4768f73ad76SAlex.Song         }))
477*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
478*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
4798f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
4808f73ad76SAlex.Song             *s = property;
4818f73ad76SAlex.Song             // Read the string in the pair (dictionary).
4828f73ad76SAlex.Song             return 0;
4838f73ad76SAlex.Song         }));
4848f73ad76SAlex.Song 
4858f73ad76SAlex.Song     // std::map
4868f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
4878f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
4888f73ad76SAlex.Song         .WillOnce(Return(0));
4898f73ad76SAlex.Song 
4908f73ad76SAlex.Song     // while !at_end()
4918f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
4928f73ad76SAlex.Song         .WillOnce(Return(0))
4938f73ad76SAlex.Song         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
4948f73ad76SAlex.Song 
4958f73ad76SAlex.Song     // std::pair
4968f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
4978f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
4988f73ad76SAlex.Song         .WillOnce(Return(0));
4998f73ad76SAlex.Song 
5008f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5018f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
5028f73ad76SAlex.Song         .WillOnce(Return(0));
5038f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5048f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
5058f73ad76SAlex.Song         .WillOnce(Return(0));
5068f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5078f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
5088f73ad76SAlex.Song         .WillOnce(Return(1));
5098f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5108f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
5118f73ad76SAlex.Song         .WillOnce(Return(0));
5128f73ad76SAlex.Song 
5138f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
514*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
515*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
5168f73ad76SAlex.Song             bool* s = static_cast<bool*>(p);
5178f73ad76SAlex.Song             *s = asserted;
5188f73ad76SAlex.Song             return 0;
5198f73ad76SAlex.Song         }));
5208f73ad76SAlex.Song 
5218f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
5228f73ad76SAlex.Song         .WillOnce(Return(0))  /* variant. */
5238f73ad76SAlex.Song         .WillOnce(Return(0))  /* std::pair */
5248f73ad76SAlex.Song         .WillOnce(Return(0)); /* std::map */
5258f73ad76SAlex.Song 
5268f73ad76SAlex.Song     int rv = handleSensorValue(msg, passive);
5278f73ad76SAlex.Song     EXPECT_EQ(rv, 0); // It's always 0.
5288f73ad76SAlex.Song     bool failed = passive->getFailed();
5298f73ad76SAlex.Song     EXPECT_EQ(failed, true);
5308f73ad76SAlex.Song }
5318f73ad76SAlex.Song 
5328f73ad76SAlex.Song TEST_F(DbusPassiveTestObj, VerifyAvailableAssert)
5338f73ad76SAlex.Song {
5348f73ad76SAlex.Song 
5358f73ad76SAlex.Song     // Verifies when Availble is asserted && unavailableAsFailed == true,
5368f73ad76SAlex.Song     // an error sensor goes back to normal state
5378f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
5388f73ad76SAlex.Song         .WillOnce(Return(nullptr));
539b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
5408f73ad76SAlex.Song 
5418f73ad76SAlex.Song     const char* property = "Available";
5428f73ad76SAlex.Song     bool asserted = true;
5438f73ad76SAlex.Song     const char* intf = "xyz.openbmc_project.State.Decorator.Availability";
5448f73ad76SAlex.Song 
5458f73ad76SAlex.Song     passive->setAvailable(false);
5468f73ad76SAlex.Song     bool failed = passive->getFailed();
5478f73ad76SAlex.Song     EXPECT_EQ(failed, true);
5488f73ad76SAlex.Song 
5498f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
550*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
551*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
5528f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
5538f73ad76SAlex.Song             // Read the first parameter, the string.
5548f73ad76SAlex.Song             *s = intf;
5558f73ad76SAlex.Song             return 0;
5568f73ad76SAlex.Song         }))
557*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
558*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
5598f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
5608f73ad76SAlex.Song             *s = property;
5618f73ad76SAlex.Song             // Read the string in the pair (dictionary).
5628f73ad76SAlex.Song             return 0;
5638f73ad76SAlex.Song         }));
5648f73ad76SAlex.Song 
5658f73ad76SAlex.Song     // std::map
5668f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5678f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
5688f73ad76SAlex.Song         .WillOnce(Return(0));
5698f73ad76SAlex.Song 
5708f73ad76SAlex.Song     // while !at_end()
5718f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
5728f73ad76SAlex.Song         .WillOnce(Return(0))
5738f73ad76SAlex.Song         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
5748f73ad76SAlex.Song 
5758f73ad76SAlex.Song     // std::pair
5768f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5778f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
5788f73ad76SAlex.Song         .WillOnce(Return(0));
5798f73ad76SAlex.Song 
5808f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5818f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
5828f73ad76SAlex.Song         .WillOnce(Return(0));
5838f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5848f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
5858f73ad76SAlex.Song         .WillOnce(Return(0));
5868f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5878f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
5888f73ad76SAlex.Song         .WillOnce(Return(1));
5898f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
5908f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
5918f73ad76SAlex.Song         .WillOnce(Return(0));
5928f73ad76SAlex.Song 
5938f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
594*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
595*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
5968f73ad76SAlex.Song             bool* s = static_cast<bool*>(p);
5978f73ad76SAlex.Song             *s = asserted;
5988f73ad76SAlex.Song             return 0;
5998f73ad76SAlex.Song         }));
6008f73ad76SAlex.Song 
6018f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
6028f73ad76SAlex.Song         .WillOnce(Return(0))  /* variant. */
6038f73ad76SAlex.Song         .WillOnce(Return(0))  /* std::pair */
6048f73ad76SAlex.Song         .WillOnce(Return(0)); /* std::map */
6058f73ad76SAlex.Song 
6068f73ad76SAlex.Song     int rv = handleSensorValue(msg, passive);
6078f73ad76SAlex.Song     EXPECT_EQ(rv, 0); // It's always 0.
6088f73ad76SAlex.Song     failed = passive->getFailed();
6098f73ad76SAlex.Song     EXPECT_EQ(failed, false);
6108f73ad76SAlex.Song }
6118f73ad76SAlex.Song 
6128f73ad76SAlex.Song class DbusPassiveTestUnaSensorNotAsFailedObj : public ::testing::Test
6138f73ad76SAlex.Song {
6148f73ad76SAlex.Song   protected:
6158f73ad76SAlex.Song     DbusPassiveTestUnaSensorNotAsFailedObj() :
6168f73ad76SAlex.Song         sdbus_mock(),
6178f73ad76SAlex.Song         bus_mock(std::move(sdbusplus::get_mocked_new(&sdbus_mock))),
6188f73ad76SAlex.Song         helper(std::make_unique<DbusHelperMock>())
6198f73ad76SAlex.Song     {
6208f73ad76SAlex.Song         EXPECT_CALL(*helper, getService(StrEq(SensorIntf), StrEq(path)))
6218f73ad76SAlex.Song             .WillOnce(Return("asdf"));
6228f73ad76SAlex.Song 
6238f73ad76SAlex.Song         EXPECT_CALL(*helper,
6248f73ad76SAlex.Song                     getProperties(StrEq("asdf"), StrEq(path), NotNull()))
625*a1ae4fa1SHarvey.Wu             .WillOnce(Invoke([&]([[maybe_unused]] const std::string& service,
626*a1ae4fa1SHarvey.Wu                                  [[maybe_unused]] const std::string& path,
6278f73ad76SAlex.Song                                  SensorProperties* prop) {
6288f73ad76SAlex.Song                 prop->scale = _scale;
6298f73ad76SAlex.Song                 prop->value = _value;
6308f73ad76SAlex.Song                 prop->unit = "x";
6318f73ad76SAlex.Song                 prop->min = 0;
6328f73ad76SAlex.Song                 prop->max = 0;
6338f73ad76SAlex.Song                 prop->available = true;
6348f73ad76SAlex.Song             }));
6358f73ad76SAlex.Song         EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
6368f73ad76SAlex.Song             .WillOnce(Return(false));
6378f73ad76SAlex.Song 
6388f73ad76SAlex.Song         auto info = conf::SensorConfig();
6398f73ad76SAlex.Song         info.unavailableAsFailed = false;
6408f73ad76SAlex.Song         ri = DbusPassive::createDbusPassive(bus_mock, type, id,
6418f73ad76SAlex.Song                                             std::move(helper), &info, nullptr);
6428f73ad76SAlex.Song         passive = reinterpret_cast<DbusPassive*>(ri.get());
6438f73ad76SAlex.Song         EXPECT_FALSE(passive == nullptr);
6448f73ad76SAlex.Song     }
6458f73ad76SAlex.Song 
6468f73ad76SAlex.Song     sdbusplus::SdBusMock sdbus_mock;
647b228bc30SPatrick Williams     sdbusplus::bus_t bus_mock;
6488f73ad76SAlex.Song     std::unique_ptr<DbusHelperMock> helper;
6498f73ad76SAlex.Song     std::string type = "temp";
6508f73ad76SAlex.Song     std::string id = "id";
6518f73ad76SAlex.Song     std::string path = "/xyz/openbmc_project/sensors/temperature/id";
6528f73ad76SAlex.Song     int64_t _scale = -3;
6538f73ad76SAlex.Song     int64_t _value = 10;
6548f73ad76SAlex.Song 
6558f73ad76SAlex.Song     std::unique_ptr<ReadInterface> ri;
6568f73ad76SAlex.Song     DbusPassive* passive;
6578f73ad76SAlex.Song };
6588f73ad76SAlex.Song 
6598f73ad76SAlex.Song TEST_F(DbusPassiveTestUnaSensorNotAsFailedObj, VerifyAvailableDeassert)
6608f73ad76SAlex.Song {
6618f73ad76SAlex.Song 
6628f73ad76SAlex.Song     // Verifies when Availble is deasserted && unavailableAsFailed == false,
6638f73ad76SAlex.Song     // the sensor remains at OK state but reading goes to NaN.
6648f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
6658f73ad76SAlex.Song         .WillOnce(Return(nullptr));
666b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
6678f73ad76SAlex.Song 
6688f73ad76SAlex.Song     const char* property = "Available";
6698f73ad76SAlex.Song     bool asserted = false;
6708f73ad76SAlex.Song     const char* intf = "xyz.openbmc_project.State.Decorator.Availability";
6718f73ad76SAlex.Song 
6728f73ad76SAlex.Song     passive->setAvailable(true);
6738f73ad76SAlex.Song 
6748f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
675*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
676*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
6778f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
6788f73ad76SAlex.Song             // Read the first parameter, the string.
6798f73ad76SAlex.Song             *s = intf;
6808f73ad76SAlex.Song             return 0;
6818f73ad76SAlex.Song         }))
682*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
683*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
6848f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
6858f73ad76SAlex.Song             *s = property;
6868f73ad76SAlex.Song             // Read the string in the pair (dictionary).
6878f73ad76SAlex.Song             return 0;
6888f73ad76SAlex.Song         }));
6898f73ad76SAlex.Song 
6908f73ad76SAlex.Song     // std::map
6918f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
6928f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
6938f73ad76SAlex.Song         .WillOnce(Return(0));
6948f73ad76SAlex.Song 
6958f73ad76SAlex.Song     // while !at_end()
6968f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
6978f73ad76SAlex.Song         .WillOnce(Return(0))
6988f73ad76SAlex.Song         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
6998f73ad76SAlex.Song 
7008f73ad76SAlex.Song     // std::pair
7018f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7028f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
7038f73ad76SAlex.Song         .WillOnce(Return(0));
7048f73ad76SAlex.Song 
7058f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7068f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
7078f73ad76SAlex.Song         .WillOnce(Return(0));
7088f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7098f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
7108f73ad76SAlex.Song         .WillOnce(Return(0));
7118f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7128f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
7138f73ad76SAlex.Song         .WillOnce(Return(1));
7148f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7158f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
7168f73ad76SAlex.Song         .WillOnce(Return(0));
7178f73ad76SAlex.Song 
7188f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
719*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
720*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
7218f73ad76SAlex.Song             bool* s = static_cast<bool*>(p);
7228f73ad76SAlex.Song             *s = asserted;
7238f73ad76SAlex.Song             return 0;
7248f73ad76SAlex.Song         }));
7258f73ad76SAlex.Song 
7268f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
7278f73ad76SAlex.Song         .WillOnce(Return(0))  /* variant. */
7288f73ad76SAlex.Song         .WillOnce(Return(0))  /* std::pair */
7298f73ad76SAlex.Song         .WillOnce(Return(0)); /* std::map */
7308f73ad76SAlex.Song 
7318f73ad76SAlex.Song     int rv = handleSensorValue(msg, passive);
7328f73ad76SAlex.Song     EXPECT_EQ(rv, 0); // It's always 0.
7338f73ad76SAlex.Song     bool failed = passive->getFailed();
7348f73ad76SAlex.Song     EXPECT_EQ(failed, false);
7358f73ad76SAlex.Song     ReadReturn r = passive->read();
7368f73ad76SAlex.Song     EXPECT_FALSE(std::isfinite(r.value));
7378f73ad76SAlex.Song }
7388f73ad76SAlex.Song 
7398f73ad76SAlex.Song TEST_F(DbusPassiveTestUnaSensorNotAsFailedObj, VerifyAvailableAssert)
7408f73ad76SAlex.Song {
7418f73ad76SAlex.Song 
7428f73ad76SAlex.Song     // Verifies when a sensor's state goes from unavailble to available
7438f73ad76SAlex.Song     // && unavailableAsFailed == false, this sensor remains at OK state.
7448f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
7458f73ad76SAlex.Song         .WillOnce(Return(nullptr));
746b228bc30SPatrick Williams     sdbusplus::message_t msg(nullptr, &sdbus_mock);
7478f73ad76SAlex.Song 
7488f73ad76SAlex.Song     const char* property = "Available";
7498f73ad76SAlex.Song     bool asserted = true;
7508f73ad76SAlex.Song     const char* intf = "xyz.openbmc_project.State.Decorator.Availability";
7518f73ad76SAlex.Song 
7528f73ad76SAlex.Song     passive->setAvailable(false);
7538f73ad76SAlex.Song     bool failed = passive->getFailed();
7548f73ad76SAlex.Song     EXPECT_EQ(failed, false);
7558f73ad76SAlex.Song 
7568f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
757*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
758*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
7598f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
7608f73ad76SAlex.Song             // Read the first parameter, the string.
7618f73ad76SAlex.Song             *s = intf;
7628f73ad76SAlex.Song             return 0;
7638f73ad76SAlex.Song         }))
764*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
765*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
7668f73ad76SAlex.Song             const char** s = static_cast<const char**>(p);
7678f73ad76SAlex.Song             *s = property;
7688f73ad76SAlex.Song             // Read the string in the pair (dictionary).
7698f73ad76SAlex.Song             return 0;
7708f73ad76SAlex.Song         }));
7718f73ad76SAlex.Song 
7728f73ad76SAlex.Song     // std::map
7738f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7748f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
7758f73ad76SAlex.Song         .WillOnce(Return(0));
7768f73ad76SAlex.Song 
7778f73ad76SAlex.Song     // while !at_end()
7788f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
7798f73ad76SAlex.Song         .WillOnce(Return(0))
7808f73ad76SAlex.Song         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
7818f73ad76SAlex.Song 
7828f73ad76SAlex.Song     // std::pair
7838f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7848f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
7858f73ad76SAlex.Song         .WillOnce(Return(0));
7868f73ad76SAlex.Song 
7878f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7888f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
7898f73ad76SAlex.Song         .WillOnce(Return(0));
7908f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7918f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
7928f73ad76SAlex.Song         .WillOnce(Return(0));
7938f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7948f73ad76SAlex.Song                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
7958f73ad76SAlex.Song         .WillOnce(Return(1));
7968f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock,
7978f73ad76SAlex.Song                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
7988f73ad76SAlex.Song         .WillOnce(Return(0));
7998f73ad76SAlex.Song 
8008f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
801*a1ae4fa1SHarvey.Wu         .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
802*a1ae4fa1SHarvey.Wu                              [[maybe_unused]] char type, void* p) {
8038f73ad76SAlex.Song             bool* s = static_cast<bool*>(p);
8048f73ad76SAlex.Song             *s = asserted;
8058f73ad76SAlex.Song             return 0;
8068f73ad76SAlex.Song         }));
8078f73ad76SAlex.Song 
8088f73ad76SAlex.Song     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
8098f73ad76SAlex.Song         .WillOnce(Return(0))  /* variant. */
8108f73ad76SAlex.Song         .WillOnce(Return(0))  /* std::pair */
8118f73ad76SAlex.Song         .WillOnce(Return(0)); /* std::map */
8128f73ad76SAlex.Song 
8138f73ad76SAlex.Song     int rv = handleSensorValue(msg, passive);
8148f73ad76SAlex.Song     EXPECT_EQ(rv, 0); // It's always 0.
8158f73ad76SAlex.Song     failed = passive->getFailed();
8168f73ad76SAlex.Song     EXPECT_EQ(failed, false);
8178f73ad76SAlex.Song }
8188f73ad76SAlex.Song 
819*a1ae4fa1SHarvey.Wu void GetPropertiesMax3k([[maybe_unused]] const std::string& service,
820*a1ae4fa1SHarvey.Wu                         [[maybe_unused]] const std::string& path,
8219b93692dSPatrick Venture                         SensorProperties* prop)
8226b9f5999SPatrick Venture {
8236b9f5999SPatrick Venture     prop->scale = -3;
8246b9f5999SPatrick Venture     prop->value = 10;
8256b9f5999SPatrick Venture     prop->unit = "x";
8266b9f5999SPatrick Venture     prop->min = 0;
8276b9f5999SPatrick Venture     prop->max = 3000;
8286b9f5999SPatrick Venture }
8296b9f5999SPatrick Venture 
8309b93692dSPatrick Venture using GetPropertiesFunction = std::function<void(
8319b93692dSPatrick Venture     const std::string&, const std::string&, SensorProperties*)>;
8326b9f5999SPatrick Venture 
8336b9f5999SPatrick Venture // TODO: There is definitely a cleaner way to do this.
8346b9f5999SPatrick Venture class DbusPassiveTest3kMaxObj : public ::testing::Test
8356b9f5999SPatrick Venture {
8366b9f5999SPatrick Venture   protected:
8376b9f5999SPatrick Venture     DbusPassiveTest3kMaxObj() :
8386b9f5999SPatrick Venture         sdbus_mock(),
8398729eb98SPatrick Venture         bus_mock(std::move(sdbusplus::get_mocked_new(&sdbus_mock))),
8408729eb98SPatrick Venture         helper(std::make_unique<DbusHelperMock>())
8416b9f5999SPatrick Venture     {
8429b93692dSPatrick Venture         EXPECT_CALL(*helper, getService(StrEq(SensorIntf), StrEq(path)))
8436b9f5999SPatrick Venture             .WillOnce(Return("asdf"));
8446b9f5999SPatrick Venture 
8458729eb98SPatrick Venture         EXPECT_CALL(*helper,
8469b93692dSPatrick Venture                     getProperties(StrEq("asdf"), StrEq(path), NotNull()))
8476b9f5999SPatrick Venture             .WillOnce(_getProps);
8489b93692dSPatrick Venture         EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
8496b9f5999SPatrick Venture             .WillOnce(Return(false));
8506b9f5999SPatrick Venture 
8516b9f5999SPatrick Venture         auto info = conf::SensorConfig();
8528729eb98SPatrick Venture         ri = DbusPassive::createDbusPassive(bus_mock, type, id,
8538729eb98SPatrick Venture                                             std::move(helper), &info, nullptr);
8546b9f5999SPatrick Venture         passive = reinterpret_cast<DbusPassive*>(ri.get());
8556b9f5999SPatrick Venture         EXPECT_FALSE(passive == nullptr);
8566b9f5999SPatrick Venture     }
8576b9f5999SPatrick Venture 
8586b9f5999SPatrick Venture     sdbusplus::SdBusMock sdbus_mock;
859b228bc30SPatrick Williams     sdbusplus::bus_t bus_mock;
8608729eb98SPatrick Venture     std::unique_ptr<DbusHelperMock> helper;
8616b9f5999SPatrick Venture     std::string type = "temp";
8626b9f5999SPatrick Venture     std::string id = "id";
8636b9f5999SPatrick Venture     std::string path = "/xyz/openbmc_project/sensors/temperature/id";
8646b9f5999SPatrick Venture     int64_t _scale = -3;
8656b9f5999SPatrick Venture     int64_t _value = 10;
8666b9f5999SPatrick Venture 
8676b9f5999SPatrick Venture     std::unique_ptr<ReadInterface> ri;
8686b9f5999SPatrick Venture     DbusPassive* passive;
8696b9f5999SPatrick Venture     GetPropertiesFunction _getProps = &GetPropertiesMax3k;
8706b9f5999SPatrick Venture };
8716b9f5999SPatrick Venture 
8726b9f5999SPatrick Venture TEST_F(DbusPassiveTest3kMaxObj, ReadMinAndMaxReturnsExpected)
8736b9f5999SPatrick Venture {
8746b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(0, passive->getMin());
8756b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(3, passive->getMax());
8766b9f5999SPatrick Venture }
8776b9f5999SPatrick Venture 
8786b9f5999SPatrick Venture class DbusPassiveTest3kMaxIgnoredObj : public ::testing::Test
8796b9f5999SPatrick Venture {
8806b9f5999SPatrick Venture   protected:
8816b9f5999SPatrick Venture     DbusPassiveTest3kMaxIgnoredObj() :
8826b9f5999SPatrick Venture         sdbus_mock(),
8838729eb98SPatrick Venture         bus_mock(std::move(sdbusplus::get_mocked_new(&sdbus_mock))),
8848729eb98SPatrick Venture         helper(std::make_unique<DbusHelperMock>())
8856b9f5999SPatrick Venture     {
8869b93692dSPatrick Venture         EXPECT_CALL(*helper, getService(StrEq(SensorIntf), StrEq(path)))
8876b9f5999SPatrick Venture             .WillOnce(Return("asdf"));
8886b9f5999SPatrick Venture 
8898729eb98SPatrick Venture         EXPECT_CALL(*helper,
8909b93692dSPatrick Venture                     getProperties(StrEq("asdf"), StrEq(path), NotNull()))
8916b9f5999SPatrick Venture             .WillOnce(_getProps);
8929b93692dSPatrick Venture         EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
8936b9f5999SPatrick Venture             .WillOnce(Return(false));
8946b9f5999SPatrick Venture 
8956b9f5999SPatrick Venture         auto info = conf::SensorConfig();
8966b9f5999SPatrick Venture         info.ignoreDbusMinMax = true;
8978729eb98SPatrick Venture         ri = DbusPassive::createDbusPassive(bus_mock, type, id,
8988729eb98SPatrick Venture                                             std::move(helper), &info, nullptr);
8996b9f5999SPatrick Venture         passive = reinterpret_cast<DbusPassive*>(ri.get());
9006b9f5999SPatrick Venture         EXPECT_FALSE(passive == nullptr);
9016b9f5999SPatrick Venture     }
9026b9f5999SPatrick Venture 
9036b9f5999SPatrick Venture     sdbusplus::SdBusMock sdbus_mock;
904b228bc30SPatrick Williams     sdbusplus::bus_t bus_mock;
9058729eb98SPatrick Venture     std::unique_ptr<DbusHelperMock> helper;
9066b9f5999SPatrick Venture     std::string type = "temp";
9076b9f5999SPatrick Venture     std::string id = "id";
9086b9f5999SPatrick Venture     std::string path = "/xyz/openbmc_project/sensors/temperature/id";
9096b9f5999SPatrick Venture     int64_t _scale = -3;
9106b9f5999SPatrick Venture     int64_t _value = 10;
9116b9f5999SPatrick Venture 
9126b9f5999SPatrick Venture     std::unique_ptr<ReadInterface> ri;
9136b9f5999SPatrick Venture     DbusPassive* passive;
9146b9f5999SPatrick Venture     GetPropertiesFunction _getProps = &GetPropertiesMax3k;
9156b9f5999SPatrick Venture };
9166b9f5999SPatrick Venture 
9176b9f5999SPatrick Venture TEST_F(DbusPassiveTest3kMaxIgnoredObj, ReadMinAndMaxReturnsExpected)
9186b9f5999SPatrick Venture {
9196b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(0, passive->getMin());
9206b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(0, passive->getMax());
9216b9f5999SPatrick Venture }
922a076487aSPatrick Venture 
923a076487aSPatrick Venture } // namespace
924a076487aSPatrick Venture } // namespace pid_control
925