1 #include "dbus/dbuspassive.hpp" 2 3 #include <gmock/gmock.h> 4 #include <gtest/gtest.h> 5 #include <sdbusplus/test/sdbus_mock.hpp> 6 #include <string> 7 8 #include "test/dbushelper_mock.hpp" 9 10 using ::testing::InSequence; 11 using ::testing::Invoke; 12 using ::testing::IsNull; 13 using ::testing::NotNull; 14 using ::testing::Return; 15 using ::testing::StrEq; 16 using ::testing::_; 17 18 std::string SensorIntf = "xyz.openbmc_project.Sensor.Value"; 19 20 TEST(DbusPassiveTest, FactoryFailsWithInvalidType) { 21 // Verify the type is checked by the factory. 22 23 sdbusplus::SdBusMock sdbus_mock; 24 auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock); 25 std::string type = "invalid"; 26 std::string id = "id"; 27 28 DbusHelperMock helper; 29 30 std::unique_ptr<ReadInterface> ri = 31 DbusPassive::CreateDbusPassive(bus_mock, type, id, &helper); 32 33 EXPECT_EQ(ri, nullptr); 34 } 35 36 TEST(DbusPassiveTest, BoringConstructorTest) { 37 // Just build the object, which should be avoided as this does no error 38 // checking at present. 39 40 sdbusplus::SdBusMock sdbus_mock; 41 auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock); 42 std::string type = "invalid"; 43 std::string id = "id"; 44 std::string path = "/xyz/openbmc_project/sensors/unknown/id"; 45 46 DbusHelperMock helper; 47 EXPECT_CALL(helper, GetService(_, StrEq(SensorIntf), StrEq(path))) 48 .WillOnce(Return("asdf")); 49 50 EXPECT_CALL(helper, GetProperties(_, StrEq("asdf"), StrEq(path), 51 NotNull())) 52 .WillOnce(Invoke([&](sdbusplus::bus::bus& bus, 53 const std::string& service, 54 const std::string& path, 55 struct SensorProperties* prop) { 56 prop->scale = -3; 57 prop->value = 10; 58 prop->unit = "x"; 59 })); 60 61 DbusPassive(bus_mock, type, id, &helper); 62 // Success 63 } 64 65 class DbusPassiveTestObj : public ::testing::Test { 66 protected: 67 DbusPassiveTestObj() 68 : sdbus_mock(), 69 bus_mock(std::move(sdbusplus::get_mocked_new(&sdbus_mock))), 70 helper() 71 { 72 EXPECT_CALL(helper, GetService(_, StrEq(SensorIntf), StrEq(path))) 73 .WillOnce(Return("asdf")); 74 75 EXPECT_CALL(helper, GetProperties(_, StrEq("asdf"), StrEq(path), 76 NotNull())) 77 .WillOnce(Invoke([&](sdbusplus::bus::bus& bus, 78 const std::string& service, 79 const std::string& path, 80 struct SensorProperties* prop) { 81 prop->scale = _scale; 82 prop->value = _value; 83 prop->unit = "x"; 84 })); 85 86 ri = DbusPassive::CreateDbusPassive(bus_mock, type, id, &helper); 87 passive = reinterpret_cast<DbusPassive*>(ri.get()); 88 EXPECT_FALSE(passive == nullptr); 89 } 90 91 sdbusplus::SdBusMock sdbus_mock; 92 sdbusplus::bus::bus bus_mock; 93 DbusHelperMock helper; 94 std::string type = "temp"; 95 std::string id = "id"; 96 std::string path = "/xyz/openbmc_project/sensors/temperature/id"; 97 int64_t _scale = -3; 98 int64_t _value = 10; 99 100 std::unique_ptr<ReadInterface> ri; 101 DbusPassive *passive; 102 }; 103 104 TEST_F(DbusPassiveTestObj, ReadReturnsExpectedValues) { 105 // Verify read is returning the values. 106 ReadReturn v; 107 v.value = 0.01; 108 // TODO: updated is set when the value is created, so we can range check 109 // it. 110 ReadReturn r = passive->read(); 111 EXPECT_EQ(v.value, r.value); 112 } 113 114 TEST_F(DbusPassiveTestObj, SetValueUpdatesValue) { 115 // Verify setvalue does as advertised. 116 117 double value = 0.01; 118 passive->setValue(value); 119 120 // TODO: updated is set when the value is set, so we can range check it. 121 ReadReturn r = passive->read(); 122 EXPECT_EQ(value, r.value); 123 } 124 125 TEST_F(DbusPassiveTestObj, GetScaleReturnsExpectedValue) { 126 // Verify the scale is returned as expected. 127 EXPECT_EQ(_scale, passive->getScale()); 128 } 129 130 TEST_F(DbusPassiveTestObj, GetIdReturnsExpectedValue) { 131 // Verify getId returns the expected value. 132 EXPECT_EQ(id, passive->getId()); 133 } 134 135 TEST_F(DbusPassiveTestObj, VerifyHandlesDbusSignal) { 136 // The dbus passive sensor listens for updates and if it's the Value 137 // property, it needs to handle it. 138 139 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull())) 140 .WillOnce(Return(nullptr)); 141 sdbusplus::message::message msg(nullptr, &sdbus_mock); 142 143 const char *Value = "Value"; 144 int64_t xValue = 10000; 145 const char *intf = "xyz.openbmc_project.Sensor.Value"; 146 // string, std::map<std::string, sdbusplus::message::variant<int64_t>> 147 // msg.read(msgSensor, msgData); 148 149 EXPECT_CALL(sdbus_mock, 150 sd_bus_message_read_basic(IsNull(), 's', NotNull())) 151 .WillOnce(Invoke([&](sd_bus_message *m, char type, void *p) { 152 const char **s = static_cast<const char **>(p); 153 // Read the first parameter, the string. 154 *s = intf; 155 return 0; 156 })) 157 .WillOnce(Invoke([&](sd_bus_message *m, char type, void *p) { 158 const char **s = static_cast<const char **>(p); 159 *s = Value; 160 // Read the string in the pair (dictionary). 161 return 0; 162 })); 163 164 // std::map 165 EXPECT_CALL(sdbus_mock, 166 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}"))) 167 .WillOnce(Return(0)); 168 169 // while !at_end() 170 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0)) 171 .WillOnce(Return(0)) 172 .WillOnce(Return(1)); // So it exits the loop after reading one pair. 173 174 // std::pair 175 EXPECT_CALL(sdbus_mock, 176 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv"))) 177 .WillOnce(Return(0)); 178 179 EXPECT_CALL(sdbus_mock, 180 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x"))) 181 .WillOnce(Return(1)); 182 EXPECT_CALL(sdbus_mock, 183 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x"))) 184 .WillOnce(Return(0)); 185 186 EXPECT_CALL(sdbus_mock, 187 sd_bus_message_read_basic(IsNull(), 'x', NotNull())) 188 .WillOnce(Invoke([&](sd_bus_message *m, char type, void *p) { 189 int64_t *s = static_cast<int64_t *>(p); 190 *s = xValue; 191 return 0; 192 })); 193 194 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull())) 195 .WillOnce(Return(0)) /* variant. */ 196 .WillOnce(Return(0)) /* std::pair */ 197 .WillOnce(Return(0)); /* std::map */ 198 199 int rv = HandleSensorValue(msg, passive); 200 EXPECT_EQ(rv, 0); // It's always 0. 201 202 ReadReturn r = passive->read(); 203 EXPECT_EQ(10, r.value); 204 } 205 206 TEST_F(DbusPassiveTestObj, VerifyIgnoresOtherPropertySignal) { 207 // The dbus passive sensor listens for updates and if it's the Value 208 // property, it needs to handle it. In this case, it won't be. 209 210 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull())) 211 .WillOnce(Return(nullptr)); 212 sdbusplus::message::message msg(nullptr, &sdbus_mock); 213 214 const char *Scale = "Scale"; 215 int64_t xScale = -6; 216 const char *intf = "xyz.openbmc_project.Sensor.Value"; 217 // string, std::map<std::string, sdbusplus::message::variant<int64_t>> 218 // msg.read(msgSensor, msgData); 219 220 EXPECT_CALL(sdbus_mock, 221 sd_bus_message_read_basic(IsNull(), 's', NotNull())) 222 .WillOnce(Invoke([&](sd_bus_message *m, char type, void *p) { 223 const char **s = static_cast<const char **>(p); 224 // Read the first parameter, the string. 225 *s = intf; 226 return 0; 227 })) 228 .WillOnce(Invoke([&](sd_bus_message *m, char type, void *p) { 229 const char **s = static_cast<const char **>(p); 230 *s = Scale; 231 // Read the string in the pair (dictionary). 232 return 0; 233 })); 234 235 // std::map 236 EXPECT_CALL(sdbus_mock, 237 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}"))) 238 .WillOnce(Return(0)); 239 240 // while !at_end() 241 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0)) 242 .WillOnce(Return(0)) 243 .WillOnce(Return(1)); // So it exits the loop after reading one pair. 244 245 // std::pair 246 EXPECT_CALL(sdbus_mock, 247 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv"))) 248 .WillOnce(Return(0)); 249 250 EXPECT_CALL(sdbus_mock, 251 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x"))) 252 .WillOnce(Return(1)); 253 EXPECT_CALL(sdbus_mock, 254 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x"))) 255 .WillOnce(Return(0)); 256 257 EXPECT_CALL(sdbus_mock, 258 sd_bus_message_read_basic(IsNull(), 'x', NotNull())) 259 .WillOnce(Invoke([&](sd_bus_message *m, char type, void *p) { 260 int64_t *s = static_cast<int64_t *>(p); 261 *s = xScale; 262 return 0; 263 })); 264 265 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull())) 266 .WillOnce(Return(0)) /* variant. */ 267 .WillOnce(Return(0)) /* std::pair */ 268 .WillOnce(Return(0)); /* std::map */ 269 270 int rv = HandleSensorValue(msg, passive); 271 EXPECT_EQ(rv, 0); // It's always 0. 272 273 ReadReturn r = passive->read(); 274 EXPECT_EQ(0.01, r.value); 275 } 276