blob: 81238a5b5f5e4dd388d2b3647ef068bb2393c0d6 [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>
James Feist1f802f52019-02-08 13:51:43 -08006#include <variant>
Patrick Venture0ef1faf2018-06-13 12:50:53 -07007
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07008#include <gmock/gmock.h>
9#include <gtest/gtest.h>
Patrick Venture0ef1faf2018-06-13 12:50:53 -070010
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070011using ::testing::_;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070012using ::testing::InSequence;
13using ::testing::Invoke;
14using ::testing::IsNull;
15using ::testing::NotNull;
16using ::testing::Return;
17using ::testing::StrEq;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070018
19std::string SensorIntf = "xyz.openbmc_project.Sensor.Value";
20
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070021TEST(DbusPassiveTest, FactoryFailsWithInvalidType)
22{
Patrick Venture0ef1faf2018-06-13 12:50:53 -070023 // Verify the type is checked by the factory.
24
25 sdbusplus::SdBusMock sdbus_mock;
26 auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
27 std::string type = "invalid";
28 std::string id = "id";
29
30 DbusHelperMock helper;
31
32 std::unique_ptr<ReadInterface> ri =
Patrick Venture563a3562018-10-30 09:31:26 -070033 DbusPassive::createDbusPassive(bus_mock, type, id, &helper);
Patrick Venture0ef1faf2018-06-13 12:50:53 -070034
35 EXPECT_EQ(ri, nullptr);
36}
37
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070038TEST(DbusPassiveTest, BoringConstructorTest)
39{
Patrick Venturef8cb4642018-10-30 12:02:53 -070040 // Simply build the object, does no error checking.
Patrick Venture0ef1faf2018-06-13 12:50:53 -070041
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 Venturef8cb4642018-10-30 12:02:53 -070049 struct SensorProperties properties;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070050
Patrick Venturef8cb4642018-10-30 12:02:53 -070051 DbusPassive(bus_mock, type, id, &helper, properties, false);
Patrick Venture0ef1faf2018-06-13 12:50:53 -070052 // Success
53}
54
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070055class DbusPassiveTestObj : public ::testing::Test
56{
57 protected:
58 DbusPassiveTestObj() :
59 sdbus_mock(),
60 bus_mock(std::move(sdbusplus::get_mocked_new(&sdbus_mock))), helper()
61 {
Patrick Venture563a3562018-10-30 09:31:26 -070062 EXPECT_CALL(helper, getService(_, StrEq(SensorIntf), StrEq(path)))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070063 .WillOnce(Return("asdf"));
Patrick Venture0ef1faf2018-06-13 12:50:53 -070064
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070065 EXPECT_CALL(helper,
Patrick Venture563a3562018-10-30 09:31:26 -070066 getProperties(_, StrEq("asdf"), StrEq(path), NotNull()))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070067 .WillOnce(Invoke(
Patrick Venturee2ec0f62018-09-04 12:30:27 -070068 [&](sdbusplus::bus::bus& bus, const std::string& service,
69 const std::string& path, struct SensorProperties* prop) {
Patrick Venture0ef1faf2018-06-13 12:50:53 -070070 prop->scale = _scale;
71 prop->value = _value;
72 prop->unit = "x";
73 }));
Patrick Venture563a3562018-10-30 09:31:26 -070074 EXPECT_CALL(helper, thresholdsAsserted(_, StrEq("asdf"), StrEq(path)))
James Feist36b7d8e2018-10-05 15:39:01 -070075 .WillOnce(Return(false));
Patrick Venture0ef1faf2018-06-13 12:50:53 -070076
Patrick Venture563a3562018-10-30 09:31:26 -070077 ri = DbusPassive::createDbusPassive(bus_mock, type, id, &helper);
Patrick Venturee2ec0f62018-09-04 12:30:27 -070078 passive = reinterpret_cast<DbusPassive*>(ri.get());
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070079 EXPECT_FALSE(passive == nullptr);
80 }
Patrick Venture0ef1faf2018-06-13 12:50:53 -070081
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070082 sdbusplus::SdBusMock sdbus_mock;
83 sdbusplus::bus::bus bus_mock;
84 DbusHelperMock helper;
85 std::string type = "temp";
86 std::string id = "id";
87 std::string path = "/xyz/openbmc_project/sensors/temperature/id";
88 int64_t _scale = -3;
89 int64_t _value = 10;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070090
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070091 std::unique_ptr<ReadInterface> ri;
Patrick Venturee2ec0f62018-09-04 12:30:27 -070092 DbusPassive* passive;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070093};
94
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070095TEST_F(DbusPassiveTestObj, ReadReturnsExpectedValues)
96{
Patrick Venture0ef1faf2018-06-13 12:50:53 -070097 // Verify read is returning the values.
98 ReadReturn v;
99 v.value = 0.01;
100 // TODO: updated is set when the value is created, so we can range check
101 // it.
102 ReadReturn r = passive->read();
103 EXPECT_EQ(v.value, r.value);
104}
105
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700106TEST_F(DbusPassiveTestObj, SetValueUpdatesValue)
107{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700108 // Verify setvalue does as advertised.
109
110 double value = 0.01;
111 passive->setValue(value);
112
113 // TODO: updated is set when the value is set, so we can range check it.
114 ReadReturn r = passive->read();
115 EXPECT_EQ(value, r.value);
116}
117
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700118TEST_F(DbusPassiveTestObj, GetScaleReturnsExpectedValue)
119{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700120 // Verify the scale is returned as expected.
121 EXPECT_EQ(_scale, passive->getScale());
122}
123
Patrick Venture563a3562018-10-30 09:31:26 -0700124TEST_F(DbusPassiveTestObj, getIDReturnsExpectedValue)
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700125{
Patrick Venture563a3562018-10-30 09:31:26 -0700126 // Verify getID returns the expected value.
127 EXPECT_EQ(id, passive->getID());
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700128}
129
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700130TEST_F(DbusPassiveTestObj, VerifyHandlesDbusSignal)
131{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700132 // The dbus passive sensor listens for updates and if it's the Value
133 // property, it needs to handle it.
134
135 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
136 .WillOnce(Return(nullptr));
137 sdbusplus::message::message msg(nullptr, &sdbus_mock);
138
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700139 const char* Value = "Value";
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700140 int64_t xValue = 10000;
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700141 const char* intf = "xyz.openbmc_project.Sensor.Value";
James Feist1f802f52019-02-08 13:51:43 -0800142 // string, std::map<std::string, std::variant<int64_t>>
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700143 // msg.read(msgSensor, msgData);
144
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700145 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700146 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
147 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700148 // Read the first parameter, the string.
149 *s = intf;
150 return 0;
151 }))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700152 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
153 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700154 *s = Value;
155 // Read the string in the pair (dictionary).
156 return 0;
157 }));
158
159 // std::map
160 EXPECT_CALL(sdbus_mock,
161 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
162 .WillOnce(Return(0));
163
164 // while !at_end()
165 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
166 .WillOnce(Return(0))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700167 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700168
169 // std::pair
170 EXPECT_CALL(sdbus_mock,
171 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
172 .WillOnce(Return(0));
173
174 EXPECT_CALL(sdbus_mock,
175 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
176 .WillOnce(Return(1));
177 EXPECT_CALL(sdbus_mock,
178 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
179 .WillOnce(Return(0));
180
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700181 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700182 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
183 int64_t* s = static_cast<int64_t*>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700184 *s = xValue;
185 return 0;
186 }));
187
188 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
189 .WillOnce(Return(0)) /* variant. */
190 .WillOnce(Return(0)) /* std::pair */
191 .WillOnce(Return(0)); /* std::map */
192
Patrick Venture7af157b2018-10-30 11:24:40 -0700193 int rv = handleSensorValue(msg, passive);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700194 EXPECT_EQ(rv, 0); // It's always 0.
195
196 ReadReturn r = passive->read();
197 EXPECT_EQ(10, r.value);
198}
199
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700200TEST_F(DbusPassiveTestObj, VerifyIgnoresOtherPropertySignal)
201{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700202 // The dbus passive sensor listens for updates and if it's the Value
203 // property, it needs to handle it. In this case, it won't be.
204
205 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
206 .WillOnce(Return(nullptr));
207 sdbusplus::message::message msg(nullptr, &sdbus_mock);
208
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700209 const char* Scale = "Scale";
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700210 int64_t xScale = -6;
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700211 const char* intf = "xyz.openbmc_project.Sensor.Value";
James Feist1f802f52019-02-08 13:51:43 -0800212 // string, std::map<std::string, std::variant<int64_t>>
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700213 // msg.read(msgSensor, msgData);
214
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700215 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700216 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
217 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700218 // Read the first parameter, the string.
219 *s = intf;
220 return 0;
221 }))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700222 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
223 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700224 *s = Scale;
225 // Read the string in the pair (dictionary).
226 return 0;
227 }));
228
229 // std::map
230 EXPECT_CALL(sdbus_mock,
231 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
232 .WillOnce(Return(0));
233
234 // while !at_end()
235 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
236 .WillOnce(Return(0))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700237 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700238
239 // std::pair
240 EXPECT_CALL(sdbus_mock,
241 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
242 .WillOnce(Return(0));
243
244 EXPECT_CALL(sdbus_mock,
245 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
246 .WillOnce(Return(1));
247 EXPECT_CALL(sdbus_mock,
248 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
249 .WillOnce(Return(0));
250
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700251 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700252 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
253 int64_t* s = static_cast<int64_t*>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700254 *s = xScale;
255 return 0;
256 }));
257
258 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
259 .WillOnce(Return(0)) /* variant. */
260 .WillOnce(Return(0)) /* std::pair */
261 .WillOnce(Return(0)); /* std::map */
262
Patrick Venture7af157b2018-10-30 11:24:40 -0700263 int rv = handleSensorValue(msg, passive);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700264 EXPECT_EQ(rv, 0); // It's always 0.
265
266 ReadReturn r = passive->read();
267 EXPECT_EQ(0.01, r.value);
268}
James Feist36b7d8e2018-10-05 15:39:01 -0700269TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdAssert)
270{
271
272 // Verifies when a threshold is crossed the sensor goes into error state
273 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
274 .WillOnce(Return(nullptr));
275 sdbusplus::message::message msg(nullptr, &sdbus_mock);
276
277 const char* criticalAlarm = "CriticalAlarmHigh";
278 bool alarm = true;
279 const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
280
281 passive->setFailed(false);
282
283 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
284 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
285 const char** s = static_cast<const char**>(p);
286 // Read the first parameter, the string.
287 *s = intf;
288 return 0;
289 }))
290 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
291 const char** s = static_cast<const char**>(p);
292 *s = criticalAlarm;
293 // Read the string in the pair (dictionary).
294 return 0;
295 }));
296
297 // std::map
298 EXPECT_CALL(sdbus_mock,
299 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
300 .WillOnce(Return(0));
301
302 // while !at_end()
303 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
304 .WillOnce(Return(0))
305 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
306
307 // std::pair
308 EXPECT_CALL(sdbus_mock,
309 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
310 .WillOnce(Return(0));
311
312 EXPECT_CALL(sdbus_mock,
313 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
314 .WillOnce(Return(0));
315 EXPECT_CALL(sdbus_mock,
316 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
317 .WillOnce(Return(0));
318 EXPECT_CALL(sdbus_mock,
319 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
320 .WillOnce(Return(1));
321 EXPECT_CALL(sdbus_mock,
322 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
323 .WillOnce(Return(0));
324
325 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
326 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
327 bool* s = static_cast<bool*>(p);
328 *s = alarm;
329 return 0;
330 }));
331
332 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
333 .WillOnce(Return(0)) /* variant. */
334 .WillOnce(Return(0)) /* std::pair */
335 .WillOnce(Return(0)); /* std::map */
336
Patrick Venture7af157b2018-10-30 11:24:40 -0700337 int rv = handleSensorValue(msg, passive);
James Feist36b7d8e2018-10-05 15:39:01 -0700338 EXPECT_EQ(rv, 0); // It's always 0.
339 bool failed = passive->getFailed();
340 EXPECT_EQ(failed, true);
341}
342
343TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdDeassert)
344{
345
346 // Verifies when a threshold is deasserted a failed sensor goes back into
347 // the normal state
348 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
349 .WillOnce(Return(nullptr));
350 sdbusplus::message::message msg(nullptr, &sdbus_mock);
351
352 const char* criticalAlarm = "CriticalAlarmHigh";
353 bool alarm = false;
354 const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
355
356 passive->setFailed(true);
357
358 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
359 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
360 const char** s = static_cast<const char**>(p);
361 // Read the first parameter, the string.
362 *s = intf;
363 return 0;
364 }))
365 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
366 const char** s = static_cast<const char**>(p);
367 *s = criticalAlarm;
368 // Read the string in the pair (dictionary).
369 return 0;
370 }));
371
372 // std::map
373 EXPECT_CALL(sdbus_mock,
374 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
375 .WillOnce(Return(0));
376
377 // while !at_end()
378 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
379 .WillOnce(Return(0))
380 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
381
382 // std::pair
383 EXPECT_CALL(sdbus_mock,
384 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
385 .WillOnce(Return(0));
386
387 EXPECT_CALL(sdbus_mock,
388 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
389 .WillOnce(Return(0));
390 EXPECT_CALL(sdbus_mock,
391 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
392 .WillOnce(Return(0));
393 EXPECT_CALL(sdbus_mock,
394 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
395 .WillOnce(Return(1));
396 EXPECT_CALL(sdbus_mock,
397 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
398 .WillOnce(Return(0));
399
400 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
401 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
402 bool* s = static_cast<bool*>(p);
403 *s = alarm;
404 return 0;
405 }));
406
407 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
408 .WillOnce(Return(0)) /* variant. */
409 .WillOnce(Return(0)) /* std::pair */
410 .WillOnce(Return(0)); /* std::map */
411
Patrick Venture7af157b2018-10-30 11:24:40 -0700412 int rv = handleSensorValue(msg, passive);
James Feist36b7d8e2018-10-05 15:39:01 -0700413 EXPECT_EQ(rv, 0); // It's always 0.
414 bool failed = passive->getFailed();
415 EXPECT_EQ(failed, false);
Patrick Venture563a3562018-10-30 09:31:26 -0700416}