blob: 777a623c4a4b985b25177e98fa30cb358bf6ddaa [file] [log] [blame]
Patrick Venture0ef1faf2018-06-13 12:50:53 -07001#include "dbus/dbuspassive.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07002#include "test/dbushelper_mock.hpp"
Patrick Venture0ef1faf2018-06-13 12:50:53 -07003
Patrick Venture0ef1faf2018-06-13 12:50:53 -07004#include <sdbusplus/test/sdbus_mock.hpp>
5#include <string>
6
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07007#include <gmock/gmock.h>
8#include <gtest/gtest.h>
Patrick Venture0ef1faf2018-06-13 12:50:53 -07009
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070010using ::testing::_;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070011using ::testing::InSequence;
12using ::testing::Invoke;
13using ::testing::IsNull;
14using ::testing::NotNull;
15using ::testing::Return;
16using ::testing::StrEq;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070017
18std::string SensorIntf = "xyz.openbmc_project.Sensor.Value";
19
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070020TEST(DbusPassiveTest, FactoryFailsWithInvalidType)
21{
Patrick Venture0ef1faf2018-06-13 12:50:53 -070022 // Verify the type is checked by the factory.
23
24 sdbusplus::SdBusMock sdbus_mock;
25 auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
26 std::string type = "invalid";
27 std::string id = "id";
28
29 DbusHelperMock helper;
30
31 std::unique_ptr<ReadInterface> ri =
Patrick Venture563a3562018-10-30 09:31:26 -070032 DbusPassive::createDbusPassive(bus_mock, type, id, &helper);
Patrick Venture0ef1faf2018-06-13 12:50:53 -070033
34 EXPECT_EQ(ri, nullptr);
35}
36
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070037TEST(DbusPassiveTest, BoringConstructorTest)
38{
Patrick Venture0ef1faf2018-06-13 12:50:53 -070039 // Just build the object, which should be avoided as this does no error
40 // checking at present.
41
42 sdbusplus::SdBusMock sdbus_mock;
43 auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
44 std::string type = "invalid";
45 std::string id = "id";
46 std::string path = "/xyz/openbmc_project/sensors/unknown/id";
47
48 DbusHelperMock helper;
Patrick Venture563a3562018-10-30 09:31:26 -070049 EXPECT_CALL(helper, getService(_, StrEq(SensorIntf), StrEq(path)))
Patrick Venture0ef1faf2018-06-13 12:50:53 -070050 .WillOnce(Return("asdf"));
51
Patrick Venture563a3562018-10-30 09:31:26 -070052 EXPECT_CALL(helper, getProperties(_, StrEq("asdf"), StrEq(path), NotNull()))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070053 .WillOnce(
Patrick Venturee2ec0f62018-09-04 12:30:27 -070054 Invoke([&](sdbusplus::bus::bus& bus, const std::string& service,
55 const std::string& path, struct SensorProperties* prop) {
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070056 prop->scale = -3;
57 prop->value = 10;
58 prop->unit = "x";
59 }));
Patrick Venture563a3562018-10-30 09:31:26 -070060 EXPECT_CALL(helper, thresholdsAsserted(_, StrEq("asdf"), StrEq(path)))
James Feist36b7d8e2018-10-05 15:39:01 -070061 .WillOnce(Return(false));
Patrick Venture0ef1faf2018-06-13 12:50:53 -070062
63 DbusPassive(bus_mock, type, id, &helper);
64 // Success
65}
66
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070067class DbusPassiveTestObj : public ::testing::Test
68{
69 protected:
70 DbusPassiveTestObj() :
71 sdbus_mock(),
72 bus_mock(std::move(sdbusplus::get_mocked_new(&sdbus_mock))), helper()
73 {
Patrick Venture563a3562018-10-30 09:31:26 -070074 EXPECT_CALL(helper, getService(_, StrEq(SensorIntf), StrEq(path)))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070075 .WillOnce(Return("asdf"));
Patrick Venture0ef1faf2018-06-13 12:50:53 -070076
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070077 EXPECT_CALL(helper,
Patrick Venture563a3562018-10-30 09:31:26 -070078 getProperties(_, StrEq("asdf"), StrEq(path), NotNull()))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070079 .WillOnce(Invoke(
Patrick Venturee2ec0f62018-09-04 12:30:27 -070080 [&](sdbusplus::bus::bus& bus, const std::string& service,
81 const std::string& path, struct SensorProperties* prop) {
Patrick Venture0ef1faf2018-06-13 12:50:53 -070082 prop->scale = _scale;
83 prop->value = _value;
84 prop->unit = "x";
85 }));
Patrick Venture563a3562018-10-30 09:31:26 -070086 EXPECT_CALL(helper, thresholdsAsserted(_, StrEq("asdf"), StrEq(path)))
James Feist36b7d8e2018-10-05 15:39:01 -070087 .WillOnce(Return(false));
Patrick Venture0ef1faf2018-06-13 12:50:53 -070088
Patrick Venture563a3562018-10-30 09:31:26 -070089 ri = DbusPassive::createDbusPassive(bus_mock, type, id, &helper);
Patrick Venturee2ec0f62018-09-04 12:30:27 -070090 passive = reinterpret_cast<DbusPassive*>(ri.get());
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070091 EXPECT_FALSE(passive == nullptr);
92 }
Patrick Venture0ef1faf2018-06-13 12:50:53 -070093
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070094 sdbusplus::SdBusMock sdbus_mock;
95 sdbusplus::bus::bus bus_mock;
96 DbusHelperMock helper;
97 std::string type = "temp";
98 std::string id = "id";
99 std::string path = "/xyz/openbmc_project/sensors/temperature/id";
100 int64_t _scale = -3;
101 int64_t _value = 10;
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700102
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700103 std::unique_ptr<ReadInterface> ri;
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700104 DbusPassive* passive;
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700105};
106
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700107TEST_F(DbusPassiveTestObj, ReadReturnsExpectedValues)
108{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700109 // Verify read is returning the values.
110 ReadReturn v;
111 v.value = 0.01;
112 // TODO: updated is set when the value is created, so we can range check
113 // it.
114 ReadReturn r = passive->read();
115 EXPECT_EQ(v.value, r.value);
116}
117
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700118TEST_F(DbusPassiveTestObj, SetValueUpdatesValue)
119{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700120 // Verify setvalue does as advertised.
121
122 double value = 0.01;
123 passive->setValue(value);
124
125 // TODO: updated is set when the value is set, so we can range check it.
126 ReadReturn r = passive->read();
127 EXPECT_EQ(value, r.value);
128}
129
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700130TEST_F(DbusPassiveTestObj, GetScaleReturnsExpectedValue)
131{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700132 // Verify the scale is returned as expected.
133 EXPECT_EQ(_scale, passive->getScale());
134}
135
Patrick Venture563a3562018-10-30 09:31:26 -0700136TEST_F(DbusPassiveTestObj, getIDReturnsExpectedValue)
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700137{
Patrick Venture563a3562018-10-30 09:31:26 -0700138 // Verify getID returns the expected value.
139 EXPECT_EQ(id, passive->getID());
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700140}
141
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700142TEST_F(DbusPassiveTestObj, VerifyHandlesDbusSignal)
143{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700144 // The dbus passive sensor listens for updates and if it's the Value
145 // property, it needs to handle it.
146
147 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
148 .WillOnce(Return(nullptr));
149 sdbusplus::message::message msg(nullptr, &sdbus_mock);
150
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700151 const char* Value = "Value";
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700152 int64_t xValue = 10000;
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700153 const char* intf = "xyz.openbmc_project.Sensor.Value";
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700154 // string, std::map<std::string, sdbusplus::message::variant<int64_t>>
155 // msg.read(msgSensor, msgData);
156
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700157 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700158 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
159 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700160 // Read the first parameter, the string.
161 *s = intf;
162 return 0;
163 }))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700164 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
165 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700166 *s = Value;
167 // Read the string in the pair (dictionary).
168 return 0;
169 }));
170
171 // std::map
172 EXPECT_CALL(sdbus_mock,
173 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
174 .WillOnce(Return(0));
175
176 // while !at_end()
177 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
178 .WillOnce(Return(0))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700179 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700180
181 // std::pair
182 EXPECT_CALL(sdbus_mock,
183 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
184 .WillOnce(Return(0));
185
186 EXPECT_CALL(sdbus_mock,
187 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
188 .WillOnce(Return(1));
189 EXPECT_CALL(sdbus_mock,
190 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
191 .WillOnce(Return(0));
192
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700193 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700194 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
195 int64_t* s = static_cast<int64_t*>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700196 *s = xValue;
197 return 0;
198 }));
199
200 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
201 .WillOnce(Return(0)) /* variant. */
202 .WillOnce(Return(0)) /* std::pair */
203 .WillOnce(Return(0)); /* std::map */
204
205 int rv = HandleSensorValue(msg, passive);
206 EXPECT_EQ(rv, 0); // It's always 0.
207
208 ReadReturn r = passive->read();
209 EXPECT_EQ(10, r.value);
210}
211
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700212TEST_F(DbusPassiveTestObj, VerifyIgnoresOtherPropertySignal)
213{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700214 // The dbus passive sensor listens for updates and if it's the Value
215 // property, it needs to handle it. In this case, it won't be.
216
217 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
218 .WillOnce(Return(nullptr));
219 sdbusplus::message::message msg(nullptr, &sdbus_mock);
220
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700221 const char* Scale = "Scale";
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700222 int64_t xScale = -6;
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700223 const char* intf = "xyz.openbmc_project.Sensor.Value";
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700224 // string, std::map<std::string, sdbusplus::message::variant<int64_t>>
225 // msg.read(msgSensor, msgData);
226
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700227 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700228 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
229 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700230 // Read the first parameter, the string.
231 *s = intf;
232 return 0;
233 }))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700234 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
235 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700236 *s = Scale;
237 // Read the string in the pair (dictionary).
238 return 0;
239 }));
240
241 // std::map
242 EXPECT_CALL(sdbus_mock,
243 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
244 .WillOnce(Return(0));
245
246 // while !at_end()
247 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
248 .WillOnce(Return(0))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700249 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700250
251 // std::pair
252 EXPECT_CALL(sdbus_mock,
253 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
254 .WillOnce(Return(0));
255
256 EXPECT_CALL(sdbus_mock,
257 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
258 .WillOnce(Return(1));
259 EXPECT_CALL(sdbus_mock,
260 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
261 .WillOnce(Return(0));
262
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700263 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700264 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
265 int64_t* s = static_cast<int64_t*>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700266 *s = xScale;
267 return 0;
268 }));
269
270 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
271 .WillOnce(Return(0)) /* variant. */
272 .WillOnce(Return(0)) /* std::pair */
273 .WillOnce(Return(0)); /* std::map */
274
275 int rv = HandleSensorValue(msg, passive);
276 EXPECT_EQ(rv, 0); // It's always 0.
277
278 ReadReturn r = passive->read();
279 EXPECT_EQ(0.01, r.value);
280}
James Feist36b7d8e2018-10-05 15:39:01 -0700281TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdAssert)
282{
283
284 // Verifies when a threshold is crossed the sensor goes into error state
285 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
286 .WillOnce(Return(nullptr));
287 sdbusplus::message::message msg(nullptr, &sdbus_mock);
288
289 const char* criticalAlarm = "CriticalAlarmHigh";
290 bool alarm = true;
291 const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
292
293 passive->setFailed(false);
294
295 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
296 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
297 const char** s = static_cast<const char**>(p);
298 // Read the first parameter, the string.
299 *s = intf;
300 return 0;
301 }))
302 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
303 const char** s = static_cast<const char**>(p);
304 *s = criticalAlarm;
305 // Read the string in the pair (dictionary).
306 return 0;
307 }));
308
309 // std::map
310 EXPECT_CALL(sdbus_mock,
311 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
312 .WillOnce(Return(0));
313
314 // while !at_end()
315 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
316 .WillOnce(Return(0))
317 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
318
319 // std::pair
320 EXPECT_CALL(sdbus_mock,
321 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
322 .WillOnce(Return(0));
323
324 EXPECT_CALL(sdbus_mock,
325 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
326 .WillOnce(Return(0));
327 EXPECT_CALL(sdbus_mock,
328 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
329 .WillOnce(Return(0));
330 EXPECT_CALL(sdbus_mock,
331 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
332 .WillOnce(Return(1));
333 EXPECT_CALL(sdbus_mock,
334 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
335 .WillOnce(Return(0));
336
337 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
338 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
339 bool* s = static_cast<bool*>(p);
340 *s = alarm;
341 return 0;
342 }));
343
344 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
345 .WillOnce(Return(0)) /* variant. */
346 .WillOnce(Return(0)) /* std::pair */
347 .WillOnce(Return(0)); /* std::map */
348
349 int rv = HandleSensorValue(msg, passive);
350 EXPECT_EQ(rv, 0); // It's always 0.
351 bool failed = passive->getFailed();
352 EXPECT_EQ(failed, true);
353}
354
355TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdDeassert)
356{
357
358 // Verifies when a threshold is deasserted a failed sensor goes back into
359 // the normal state
360 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
361 .WillOnce(Return(nullptr));
362 sdbusplus::message::message msg(nullptr, &sdbus_mock);
363
364 const char* criticalAlarm = "CriticalAlarmHigh";
365 bool alarm = false;
366 const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
367
368 passive->setFailed(true);
369
370 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
371 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
372 const char** s = static_cast<const char**>(p);
373 // Read the first parameter, the string.
374 *s = intf;
375 return 0;
376 }))
377 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
378 const char** s = static_cast<const char**>(p);
379 *s = criticalAlarm;
380 // Read the string in the pair (dictionary).
381 return 0;
382 }));
383
384 // std::map
385 EXPECT_CALL(sdbus_mock,
386 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
387 .WillOnce(Return(0));
388
389 // while !at_end()
390 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
391 .WillOnce(Return(0))
392 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
393
394 // std::pair
395 EXPECT_CALL(sdbus_mock,
396 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
397 .WillOnce(Return(0));
398
399 EXPECT_CALL(sdbus_mock,
400 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
401 .WillOnce(Return(0));
402 EXPECT_CALL(sdbus_mock,
403 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
404 .WillOnce(Return(0));
405 EXPECT_CALL(sdbus_mock,
406 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
407 .WillOnce(Return(1));
408 EXPECT_CALL(sdbus_mock,
409 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
410 .WillOnce(Return(0));
411
412 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
413 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
414 bool* s = static_cast<bool*>(p);
415 *s = alarm;
416 return 0;
417 }));
418
419 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
420 .WillOnce(Return(0)) /* variant. */
421 .WillOnce(Return(0)) /* std::pair */
422 .WillOnce(Return(0)); /* std::map */
423
424 int rv = HandleSensorValue(msg, passive);
425 EXPECT_EQ(rv, 0); // It's always 0.
426 bool failed = passive->getFailed();
427 EXPECT_EQ(failed, false);
Patrick Venture563a3562018-10-30 09:31:26 -0700428}