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>();
59f8cb4644SPatrick Venture     struct 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     {
74*9b93692dSPatrick Venture         EXPECT_CALL(*helper, getService(StrEq(SensorIntf), StrEq(path)))
750ef1faf7SPatrick Venture             .WillOnce(Return("asdf"));
760ef1faf7SPatrick Venture 
778729eb98SPatrick Venture         EXPECT_CALL(*helper,
78*9b93692dSPatrick Venture                     getProperties(StrEq("asdf"), StrEq(path), NotNull()))
79*9b93692dSPatrick Venture             .WillOnce(
80*9b93692dSPatrick Venture                 Invoke([&](const std::string& service, const std::string& path,
81*9b93692dSPatrick Venture                            struct 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;
870ef1faf7SPatrick Venture                 }));
88*9b93692dSPatrick Venture         EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
8936b7d8ebSJames Feist             .WillOnce(Return(false));
900ef1faf7SPatrick Venture 
91f81f2886SJames Feist         auto info = conf::SensorConfig();
928729eb98SPatrick Venture         ri = DbusPassive::createDbusPassive(bus_mock, type, id,
938729eb98SPatrick Venture                                             std::move(helper), &info, nullptr);
940ef1faf7SPatrick Venture         passive = reinterpret_cast<DbusPassive*>(ri.get());
950ef1faf7SPatrick Venture         EXPECT_FALSE(passive == nullptr);
960ef1faf7SPatrick Venture     }
970ef1faf7SPatrick Venture 
980ef1faf7SPatrick Venture     sdbusplus::SdBusMock sdbus_mock;
990ef1faf7SPatrick Venture     sdbusplus::bus::bus bus_mock;
1008729eb98SPatrick Venture     std::unique_ptr<DbusHelperMock> helper;
1010ef1faf7SPatrick Venture     std::string type = "temp";
1020ef1faf7SPatrick Venture     std::string id = "id";
1030ef1faf7SPatrick Venture     std::string path = "/xyz/openbmc_project/sensors/temperature/id";
1040ef1faf7SPatrick Venture     int64_t _scale = -3;
1050ef1faf7SPatrick Venture     int64_t _value = 10;
1060ef1faf7SPatrick Venture 
1070ef1faf7SPatrick Venture     std::unique_ptr<ReadInterface> ri;
1080ef1faf7SPatrick Venture     DbusPassive* passive;
1090ef1faf7SPatrick Venture };
1100ef1faf7SPatrick Venture 
111da4a5dd1SPatrick Venture TEST_F(DbusPassiveTestObj, ReadReturnsExpectedValues)
112da4a5dd1SPatrick Venture {
1130ef1faf7SPatrick Venture     // Verify read is returning the values.
1140ef1faf7SPatrick Venture     ReadReturn v;
1150ef1faf7SPatrick Venture     v.value = 0.01;
1160ef1faf7SPatrick Venture     // TODO: updated is set when the value is created, so we can range check
1170ef1faf7SPatrick Venture     // it.
1180ef1faf7SPatrick Venture     ReadReturn r = passive->read();
1190ef1faf7SPatrick Venture     EXPECT_EQ(v.value, r.value);
1200ef1faf7SPatrick Venture }
1210ef1faf7SPatrick Venture 
122da4a5dd1SPatrick Venture TEST_F(DbusPassiveTestObj, SetValueUpdatesValue)
123da4a5dd1SPatrick Venture {
1240ef1faf7SPatrick Venture     // Verify setvalue does as advertised.
1250ef1faf7SPatrick Venture 
1260ef1faf7SPatrick Venture     double value = 0.01;
1270ef1faf7SPatrick Venture     passive->setValue(value);
1280ef1faf7SPatrick Venture 
1290ef1faf7SPatrick Venture     // TODO: updated is set when the value is set, so we can range check it.
1300ef1faf7SPatrick Venture     ReadReturn r = passive->read();
1310ef1faf7SPatrick Venture     EXPECT_EQ(value, r.value);
1320ef1faf7SPatrick Venture }
1330ef1faf7SPatrick Venture 
134da4a5dd1SPatrick Venture TEST_F(DbusPassiveTestObj, GetScaleReturnsExpectedValue)
135da4a5dd1SPatrick Venture {
1360ef1faf7SPatrick Venture     // Verify the scale is returned as expected.
1370ef1faf7SPatrick Venture     EXPECT_EQ(_scale, passive->getScale());
1380ef1faf7SPatrick Venture }
1390ef1faf7SPatrick Venture 
140563a356fSPatrick Venture TEST_F(DbusPassiveTestObj, getIDReturnsExpectedValue)
141da4a5dd1SPatrick Venture {
142563a356fSPatrick Venture     // Verify getID returns the expected value.
143563a356fSPatrick Venture     EXPECT_EQ(id, passive->getID());
1440ef1faf7SPatrick Venture }
1450ef1faf7SPatrick Venture 
1466b9f5999SPatrick Venture TEST_F(DbusPassiveTestObj, GetMinValueReturnsExpectedValue)
1476b9f5999SPatrick Venture {
1486b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(0, passive->getMin());
1496b9f5999SPatrick Venture }
1506b9f5999SPatrick Venture 
151da4a5dd1SPatrick Venture TEST_F(DbusPassiveTestObj, VerifyHandlesDbusSignal)
152da4a5dd1SPatrick Venture {
1530ef1faf7SPatrick Venture     // The dbus passive sensor listens for updates and if it's the Value
1540ef1faf7SPatrick Venture     // property, it needs to handle it.
1550ef1faf7SPatrick Venture 
1560ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
1570ef1faf7SPatrick Venture         .WillOnce(Return(nullptr));
1580ef1faf7SPatrick Venture     sdbusplus::message::message msg(nullptr, &sdbus_mock);
1590ef1faf7SPatrick Venture 
1600ef1faf7SPatrick Venture     const char* Value = "Value";
1610ef1faf7SPatrick Venture     int64_t xValue = 10000;
1620ef1faf7SPatrick Venture     const char* intf = "xyz.openbmc_project.Sensor.Value";
1631f802f5eSJames Feist     // string, std::map<std::string, std::variant<int64_t>>
1640ef1faf7SPatrick Venture     // msg.read(msgSensor, msgData);
1650ef1faf7SPatrick Venture 
166da4a5dd1SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
1670ef1faf7SPatrick Venture         .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
1680ef1faf7SPatrick Venture             const char** s = static_cast<const char**>(p);
1690ef1faf7SPatrick Venture             // Read the first parameter, the string.
1700ef1faf7SPatrick Venture             *s = intf;
1710ef1faf7SPatrick Venture             return 0;
1720ef1faf7SPatrick Venture         }))
1730ef1faf7SPatrick Venture         .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
1740ef1faf7SPatrick Venture             const char** s = static_cast<const char**>(p);
1750ef1faf7SPatrick Venture             *s = Value;
1760ef1faf7SPatrick Venture             // Read the string in the pair (dictionary).
1770ef1faf7SPatrick Venture             return 0;
1780ef1faf7SPatrick Venture         }));
1790ef1faf7SPatrick Venture 
1800ef1faf7SPatrick Venture     // std::map
1810ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
1820ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
1830ef1faf7SPatrick Venture         .WillOnce(Return(0));
1840ef1faf7SPatrick Venture 
1850ef1faf7SPatrick Venture     // while !at_end()
1860ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
1870ef1faf7SPatrick Venture         .WillOnce(Return(0))
1880ef1faf7SPatrick Venture         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
1890ef1faf7SPatrick Venture 
1900ef1faf7SPatrick Venture     // std::pair
1910ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
1920ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
1930ef1faf7SPatrick Venture         .WillOnce(Return(0));
1940ef1faf7SPatrick Venture 
1950ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
1960ef1faf7SPatrick Venture                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
1970ef1faf7SPatrick Venture         .WillOnce(Return(1));
1980ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
1990ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
2000ef1faf7SPatrick Venture         .WillOnce(Return(0));
2010ef1faf7SPatrick Venture 
202da4a5dd1SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
2030ef1faf7SPatrick Venture         .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
2040ef1faf7SPatrick Venture             int64_t* s = static_cast<int64_t*>(p);
2050ef1faf7SPatrick Venture             *s = xValue;
2060ef1faf7SPatrick Venture             return 0;
2070ef1faf7SPatrick Venture         }));
2080ef1faf7SPatrick Venture 
2090ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
2100ef1faf7SPatrick Venture         .WillOnce(Return(0))  /* variant. */
2110ef1faf7SPatrick Venture         .WillOnce(Return(0))  /* std::pair */
2120ef1faf7SPatrick Venture         .WillOnce(Return(0)); /* std::map */
2130ef1faf7SPatrick Venture 
2147af157b1SPatrick Venture     int rv = handleSensorValue(msg, passive);
2150ef1faf7SPatrick Venture     EXPECT_EQ(rv, 0); // It's always 0.
2160ef1faf7SPatrick Venture 
2170ef1faf7SPatrick Venture     ReadReturn r = passive->read();
2180ef1faf7SPatrick Venture     EXPECT_EQ(10, r.value);
2190ef1faf7SPatrick Venture }
2200ef1faf7SPatrick Venture 
221da4a5dd1SPatrick Venture TEST_F(DbusPassiveTestObj, VerifyIgnoresOtherPropertySignal)
222da4a5dd1SPatrick Venture {
2230ef1faf7SPatrick Venture     // The dbus passive sensor listens for updates and if it's the Value
2240ef1faf7SPatrick Venture     // property, it needs to handle it.  In this case, it won't be.
2250ef1faf7SPatrick Venture 
2260ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
2270ef1faf7SPatrick Venture         .WillOnce(Return(nullptr));
2280ef1faf7SPatrick Venture     sdbusplus::message::message msg(nullptr, &sdbus_mock);
2290ef1faf7SPatrick Venture 
2300ef1faf7SPatrick Venture     const char* Scale = "Scale";
2310ef1faf7SPatrick Venture     int64_t xScale = -6;
2320ef1faf7SPatrick Venture     const char* intf = "xyz.openbmc_project.Sensor.Value";
2331f802f5eSJames Feist     // string, std::map<std::string, std::variant<int64_t>>
2340ef1faf7SPatrick Venture     // msg.read(msgSensor, msgData);
2350ef1faf7SPatrick Venture 
236da4a5dd1SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
2370ef1faf7SPatrick Venture         .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
2380ef1faf7SPatrick Venture             const char** s = static_cast<const char**>(p);
2390ef1faf7SPatrick Venture             // Read the first parameter, the string.
2400ef1faf7SPatrick Venture             *s = intf;
2410ef1faf7SPatrick Venture             return 0;
2420ef1faf7SPatrick Venture         }))
2430ef1faf7SPatrick Venture         .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
2440ef1faf7SPatrick Venture             const char** s = static_cast<const char**>(p);
2450ef1faf7SPatrick Venture             *s = Scale;
2460ef1faf7SPatrick Venture             // Read the string in the pair (dictionary).
2470ef1faf7SPatrick Venture             return 0;
2480ef1faf7SPatrick Venture         }));
2490ef1faf7SPatrick Venture 
2500ef1faf7SPatrick Venture     // std::map
2510ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
2520ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
2530ef1faf7SPatrick Venture         .WillOnce(Return(0));
2540ef1faf7SPatrick Venture 
2550ef1faf7SPatrick Venture     // while !at_end()
2560ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
2570ef1faf7SPatrick Venture         .WillOnce(Return(0))
2580ef1faf7SPatrick Venture         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
2590ef1faf7SPatrick Venture 
2600ef1faf7SPatrick Venture     // std::pair
2610ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
2620ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
2630ef1faf7SPatrick Venture         .WillOnce(Return(0));
2640ef1faf7SPatrick Venture 
2650ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
2660ef1faf7SPatrick Venture                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
2670ef1faf7SPatrick Venture         .WillOnce(Return(1));
2680ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock,
2690ef1faf7SPatrick Venture                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
2700ef1faf7SPatrick Venture         .WillOnce(Return(0));
2710ef1faf7SPatrick Venture 
272da4a5dd1SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
2730ef1faf7SPatrick Venture         .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
2740ef1faf7SPatrick Venture             int64_t* s = static_cast<int64_t*>(p);
2750ef1faf7SPatrick Venture             *s = xScale;
2760ef1faf7SPatrick Venture             return 0;
2770ef1faf7SPatrick Venture         }));
2780ef1faf7SPatrick Venture 
2790ef1faf7SPatrick Venture     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
2800ef1faf7SPatrick Venture         .WillOnce(Return(0))  /* variant. */
2810ef1faf7SPatrick Venture         .WillOnce(Return(0))  /* std::pair */
2820ef1faf7SPatrick Venture         .WillOnce(Return(0)); /* std::map */
2830ef1faf7SPatrick Venture 
2847af157b1SPatrick Venture     int rv = handleSensorValue(msg, passive);
2850ef1faf7SPatrick Venture     EXPECT_EQ(rv, 0); // It's always 0.
2860ef1faf7SPatrick Venture 
2870ef1faf7SPatrick Venture     ReadReturn r = passive->read();
2880ef1faf7SPatrick Venture     EXPECT_EQ(0.01, r.value);
2890ef1faf7SPatrick Venture }
29036b7d8ebSJames Feist TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdAssert)
29136b7d8ebSJames Feist {
29236b7d8ebSJames Feist 
29336b7d8ebSJames Feist     // Verifies when a threshold is crossed the sensor goes into error state
29436b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
29536b7d8ebSJames Feist         .WillOnce(Return(nullptr));
29636b7d8ebSJames Feist     sdbusplus::message::message msg(nullptr, &sdbus_mock);
29736b7d8ebSJames Feist 
29836b7d8ebSJames Feist     const char* criticalAlarm = "CriticalAlarmHigh";
29936b7d8ebSJames Feist     bool alarm = true;
30036b7d8ebSJames Feist     const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
30136b7d8ebSJames Feist 
30236b7d8ebSJames Feist     passive->setFailed(false);
30336b7d8ebSJames Feist 
30436b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
30536b7d8ebSJames Feist         .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
30636b7d8ebSJames Feist             const char** s = static_cast<const char**>(p);
30736b7d8ebSJames Feist             // Read the first parameter, the string.
30836b7d8ebSJames Feist             *s = intf;
30936b7d8ebSJames Feist             return 0;
31036b7d8ebSJames Feist         }))
31136b7d8ebSJames Feist         .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
31236b7d8ebSJames Feist             const char** s = static_cast<const char**>(p);
31336b7d8ebSJames Feist             *s = criticalAlarm;
31436b7d8ebSJames Feist             // Read the string in the pair (dictionary).
31536b7d8ebSJames Feist             return 0;
31636b7d8ebSJames Feist         }));
31736b7d8ebSJames Feist 
31836b7d8ebSJames Feist     // std::map
31936b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
32036b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
32136b7d8ebSJames Feist         .WillOnce(Return(0));
32236b7d8ebSJames Feist 
32336b7d8ebSJames Feist     // while !at_end()
32436b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
32536b7d8ebSJames Feist         .WillOnce(Return(0))
32636b7d8ebSJames Feist         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
32736b7d8ebSJames Feist 
32836b7d8ebSJames Feist     // std::pair
32936b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
33036b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
33136b7d8ebSJames Feist         .WillOnce(Return(0));
33236b7d8ebSJames Feist 
33336b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
33436b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
33536b7d8ebSJames Feist         .WillOnce(Return(0));
33636b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
33736b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
33836b7d8ebSJames Feist         .WillOnce(Return(0));
33936b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
34036b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
34136b7d8ebSJames Feist         .WillOnce(Return(1));
34236b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
34336b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
34436b7d8ebSJames Feist         .WillOnce(Return(0));
34536b7d8ebSJames Feist 
34636b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
34736b7d8ebSJames Feist         .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
34836b7d8ebSJames Feist             bool* s = static_cast<bool*>(p);
34936b7d8ebSJames Feist             *s = alarm;
35036b7d8ebSJames Feist             return 0;
35136b7d8ebSJames Feist         }));
35236b7d8ebSJames Feist 
35336b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
35436b7d8ebSJames Feist         .WillOnce(Return(0))  /* variant. */
35536b7d8ebSJames Feist         .WillOnce(Return(0))  /* std::pair */
35636b7d8ebSJames Feist         .WillOnce(Return(0)); /* std::map */
35736b7d8ebSJames Feist 
3587af157b1SPatrick Venture     int rv = handleSensorValue(msg, passive);
35936b7d8ebSJames Feist     EXPECT_EQ(rv, 0); // It's always 0.
36036b7d8ebSJames Feist     bool failed = passive->getFailed();
36136b7d8ebSJames Feist     EXPECT_EQ(failed, true);
36236b7d8ebSJames Feist }
36336b7d8ebSJames Feist 
36436b7d8ebSJames Feist TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdDeassert)
36536b7d8ebSJames Feist {
36636b7d8ebSJames Feist 
36736b7d8ebSJames Feist     // Verifies when a threshold is deasserted a failed sensor goes back into
36836b7d8ebSJames Feist     // the normal state
36936b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
37036b7d8ebSJames Feist         .WillOnce(Return(nullptr));
37136b7d8ebSJames Feist     sdbusplus::message::message msg(nullptr, &sdbus_mock);
37236b7d8ebSJames Feist 
37336b7d8ebSJames Feist     const char* criticalAlarm = "CriticalAlarmHigh";
37436b7d8ebSJames Feist     bool alarm = false;
37536b7d8ebSJames Feist     const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
37636b7d8ebSJames Feist 
37736b7d8ebSJames Feist     passive->setFailed(true);
37836b7d8ebSJames Feist 
37936b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
38036b7d8ebSJames Feist         .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
38136b7d8ebSJames Feist             const char** s = static_cast<const char**>(p);
38236b7d8ebSJames Feist             // Read the first parameter, the string.
38336b7d8ebSJames Feist             *s = intf;
38436b7d8ebSJames Feist             return 0;
38536b7d8ebSJames Feist         }))
38636b7d8ebSJames Feist         .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
38736b7d8ebSJames Feist             const char** s = static_cast<const char**>(p);
38836b7d8ebSJames Feist             *s = criticalAlarm;
38936b7d8ebSJames Feist             // Read the string in the pair (dictionary).
39036b7d8ebSJames Feist             return 0;
39136b7d8ebSJames Feist         }));
39236b7d8ebSJames Feist 
39336b7d8ebSJames Feist     // std::map
39436b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
39536b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
39636b7d8ebSJames Feist         .WillOnce(Return(0));
39736b7d8ebSJames Feist 
39836b7d8ebSJames Feist     // while !at_end()
39936b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
40036b7d8ebSJames Feist         .WillOnce(Return(0))
40136b7d8ebSJames Feist         .WillOnce(Return(1)); // So it exits the loop after reading one pair.
40236b7d8ebSJames Feist 
40336b7d8ebSJames Feist     // std::pair
40436b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
40536b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
40636b7d8ebSJames Feist         .WillOnce(Return(0));
40736b7d8ebSJames Feist 
40836b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
40936b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
41036b7d8ebSJames Feist         .WillOnce(Return(0));
41136b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
41236b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
41336b7d8ebSJames Feist         .WillOnce(Return(0));
41436b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
41536b7d8ebSJames Feist                 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
41636b7d8ebSJames Feist         .WillOnce(Return(1));
41736b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock,
41836b7d8ebSJames Feist                 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
41936b7d8ebSJames Feist         .WillOnce(Return(0));
42036b7d8ebSJames Feist 
42136b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
42236b7d8ebSJames Feist         .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
42336b7d8ebSJames Feist             bool* s = static_cast<bool*>(p);
42436b7d8ebSJames Feist             *s = alarm;
42536b7d8ebSJames Feist             return 0;
42636b7d8ebSJames Feist         }));
42736b7d8ebSJames Feist 
42836b7d8ebSJames Feist     EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
42936b7d8ebSJames Feist         .WillOnce(Return(0))  /* variant. */
43036b7d8ebSJames Feist         .WillOnce(Return(0))  /* std::pair */
43136b7d8ebSJames Feist         .WillOnce(Return(0)); /* std::map */
43236b7d8ebSJames Feist 
4337af157b1SPatrick Venture     int rv = handleSensorValue(msg, passive);
43436b7d8ebSJames Feist     EXPECT_EQ(rv, 0); // It's always 0.
43536b7d8ebSJames Feist     bool failed = passive->getFailed();
43636b7d8ebSJames Feist     EXPECT_EQ(failed, false);
43736b7d8ebSJames Feist }
4386b9f5999SPatrick Venture 
439*9b93692dSPatrick Venture void GetPropertiesMax3k(const std::string& service, const std::string& path,
440*9b93692dSPatrick Venture                         SensorProperties* prop)
4416b9f5999SPatrick Venture {
4426b9f5999SPatrick Venture     prop->scale = -3;
4436b9f5999SPatrick Venture     prop->value = 10;
4446b9f5999SPatrick Venture     prop->unit = "x";
4456b9f5999SPatrick Venture     prop->min = 0;
4466b9f5999SPatrick Venture     prop->max = 3000;
4476b9f5999SPatrick Venture }
4486b9f5999SPatrick Venture 
449*9b93692dSPatrick Venture using GetPropertiesFunction = std::function<void(
450*9b93692dSPatrick Venture     const std::string&, const std::string&, SensorProperties*)>;
4516b9f5999SPatrick Venture 
4526b9f5999SPatrick Venture // TODO: There is definitely a cleaner way to do this.
4536b9f5999SPatrick Venture class DbusPassiveTest3kMaxObj : public ::testing::Test
4546b9f5999SPatrick Venture {
4556b9f5999SPatrick Venture   protected:
4566b9f5999SPatrick Venture     DbusPassiveTest3kMaxObj() :
4576b9f5999SPatrick Venture         sdbus_mock(),
4588729eb98SPatrick Venture         bus_mock(std::move(sdbusplus::get_mocked_new(&sdbus_mock))),
4598729eb98SPatrick Venture         helper(std::make_unique<DbusHelperMock>())
4606b9f5999SPatrick Venture     {
461*9b93692dSPatrick Venture         EXPECT_CALL(*helper, getService(StrEq(SensorIntf), StrEq(path)))
4626b9f5999SPatrick Venture             .WillOnce(Return("asdf"));
4636b9f5999SPatrick Venture 
4648729eb98SPatrick Venture         EXPECT_CALL(*helper,
465*9b93692dSPatrick Venture                     getProperties(StrEq("asdf"), StrEq(path), NotNull()))
4666b9f5999SPatrick Venture             .WillOnce(_getProps);
467*9b93692dSPatrick Venture         EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
4686b9f5999SPatrick Venture             .WillOnce(Return(false));
4696b9f5999SPatrick Venture 
4706b9f5999SPatrick Venture         auto info = conf::SensorConfig();
4718729eb98SPatrick Venture         ri = DbusPassive::createDbusPassive(bus_mock, type, id,
4728729eb98SPatrick Venture                                             std::move(helper), &info, nullptr);
4736b9f5999SPatrick Venture         passive = reinterpret_cast<DbusPassive*>(ri.get());
4746b9f5999SPatrick Venture         EXPECT_FALSE(passive == nullptr);
4756b9f5999SPatrick Venture     }
4766b9f5999SPatrick Venture 
4776b9f5999SPatrick Venture     sdbusplus::SdBusMock sdbus_mock;
4786b9f5999SPatrick Venture     sdbusplus::bus::bus bus_mock;
4798729eb98SPatrick Venture     std::unique_ptr<DbusHelperMock> helper;
4806b9f5999SPatrick Venture     std::string type = "temp";
4816b9f5999SPatrick Venture     std::string id = "id";
4826b9f5999SPatrick Venture     std::string path = "/xyz/openbmc_project/sensors/temperature/id";
4836b9f5999SPatrick Venture     int64_t _scale = -3;
4846b9f5999SPatrick Venture     int64_t _value = 10;
4856b9f5999SPatrick Venture 
4866b9f5999SPatrick Venture     std::unique_ptr<ReadInterface> ri;
4876b9f5999SPatrick Venture     DbusPassive* passive;
4886b9f5999SPatrick Venture     GetPropertiesFunction _getProps = &GetPropertiesMax3k;
4896b9f5999SPatrick Venture };
4906b9f5999SPatrick Venture 
4916b9f5999SPatrick Venture TEST_F(DbusPassiveTest3kMaxObj, ReadMinAndMaxReturnsExpected)
4926b9f5999SPatrick Venture {
4936b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(0, passive->getMin());
4946b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(3, passive->getMax());
4956b9f5999SPatrick Venture }
4966b9f5999SPatrick Venture 
4976b9f5999SPatrick Venture class DbusPassiveTest3kMaxIgnoredObj : public ::testing::Test
4986b9f5999SPatrick Venture {
4996b9f5999SPatrick Venture   protected:
5006b9f5999SPatrick Venture     DbusPassiveTest3kMaxIgnoredObj() :
5016b9f5999SPatrick Venture         sdbus_mock(),
5028729eb98SPatrick Venture         bus_mock(std::move(sdbusplus::get_mocked_new(&sdbus_mock))),
5038729eb98SPatrick Venture         helper(std::make_unique<DbusHelperMock>())
5046b9f5999SPatrick Venture     {
505*9b93692dSPatrick Venture         EXPECT_CALL(*helper, getService(StrEq(SensorIntf), StrEq(path)))
5066b9f5999SPatrick Venture             .WillOnce(Return("asdf"));
5076b9f5999SPatrick Venture 
5088729eb98SPatrick Venture         EXPECT_CALL(*helper,
509*9b93692dSPatrick Venture                     getProperties(StrEq("asdf"), StrEq(path), NotNull()))
5106b9f5999SPatrick Venture             .WillOnce(_getProps);
511*9b93692dSPatrick Venture         EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
5126b9f5999SPatrick Venture             .WillOnce(Return(false));
5136b9f5999SPatrick Venture 
5146b9f5999SPatrick Venture         auto info = conf::SensorConfig();
5156b9f5999SPatrick Venture         info.ignoreDbusMinMax = true;
5168729eb98SPatrick Venture         ri = DbusPassive::createDbusPassive(bus_mock, type, id,
5178729eb98SPatrick Venture                                             std::move(helper), &info, nullptr);
5186b9f5999SPatrick Venture         passive = reinterpret_cast<DbusPassive*>(ri.get());
5196b9f5999SPatrick Venture         EXPECT_FALSE(passive == nullptr);
5206b9f5999SPatrick Venture     }
5216b9f5999SPatrick Venture 
5226b9f5999SPatrick Venture     sdbusplus::SdBusMock sdbus_mock;
5236b9f5999SPatrick Venture     sdbusplus::bus::bus bus_mock;
5248729eb98SPatrick Venture     std::unique_ptr<DbusHelperMock> helper;
5256b9f5999SPatrick Venture     std::string type = "temp";
5266b9f5999SPatrick Venture     std::string id = "id";
5276b9f5999SPatrick Venture     std::string path = "/xyz/openbmc_project/sensors/temperature/id";
5286b9f5999SPatrick Venture     int64_t _scale = -3;
5296b9f5999SPatrick Venture     int64_t _value = 10;
5306b9f5999SPatrick Venture 
5316b9f5999SPatrick Venture     std::unique_ptr<ReadInterface> ri;
5326b9f5999SPatrick Venture     DbusPassive* passive;
5336b9f5999SPatrick Venture     GetPropertiesFunction _getProps = &GetPropertiesMax3k;
5346b9f5999SPatrick Venture };
5356b9f5999SPatrick Venture 
5366b9f5999SPatrick Venture TEST_F(DbusPassiveTest3kMaxIgnoredObj, ReadMinAndMaxReturnsExpected)
5376b9f5999SPatrick Venture {
5386b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(0, passive->getMin());
5396b9f5999SPatrick Venture     EXPECT_DOUBLE_EQ(0, passive->getMax());
5406b9f5999SPatrick Venture }
541a076487aSPatrick Venture 
542a076487aSPatrick Venture } // namespace
543a076487aSPatrick Venture } // namespace pid_control
544