blob: 2fc34713938f8f274cdc8fc02b2b24edc97fa964 [file] [log] [blame]
James Feist75eb7692019-02-25 12:50:02 -08001#include "conf.hpp"
Patrick Venture0ef1faf2018-06-13 12:50:53 -07002#include "dbus/dbuspassive.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07003#include "test/dbushelper_mock.hpp"
Patrick Venture0ef1faf2018-06-13 12:50:53 -07004
Patrick Venture0ef1faf2018-06-13 12:50:53 -07005#include <sdbusplus/test/sdbus_mock.hpp>
6#include <string>
James Feist1f802f52019-02-08 13:51:43 -08007#include <variant>
Patrick Venture0ef1faf2018-06-13 12:50:53 -07008
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07009#include <gmock/gmock.h>
10#include <gtest/gtest.h>
Patrick Venture0ef1faf2018-06-13 12:50:53 -070011
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070012using ::testing::_;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070013using ::testing::InSequence;
14using ::testing::Invoke;
15using ::testing::IsNull;
16using ::testing::NotNull;
17using ::testing::Return;
18using ::testing::StrEq;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070019
20std::string SensorIntf = "xyz.openbmc_project.Sensor.Value";
21
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070022TEST(DbusPassiveTest, FactoryFailsWithInvalidType)
23{
Patrick Venture0ef1faf2018-06-13 12:50:53 -070024 // Verify the type is checked by the factory.
25
26 sdbusplus::SdBusMock sdbus_mock;
27 auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
28 std::string type = "invalid";
29 std::string id = "id";
30
31 DbusHelperMock helper;
James Feistf81f2882019-02-26 11:26:36 -080032 auto info = conf::SensorConfig();
Patrick Venture0ef1faf2018-06-13 12:50:53 -070033
34 std::unique_ptr<ReadInterface> ri =
James Feist75eb7692019-02-25 12:50:02 -080035 DbusPassive::createDbusPassive(bus_mock, type, id, &helper, &info);
Patrick Venture0ef1faf2018-06-13 12:50:53 -070036
37 EXPECT_EQ(ri, nullptr);
38}
39
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070040TEST(DbusPassiveTest, BoringConstructorTest)
41{
Patrick Venturef8cb4642018-10-30 12:02:53 -070042 // Simply build the object, does no error checking.
Patrick Venture0ef1faf2018-06-13 12:50:53 -070043
44 sdbusplus::SdBusMock sdbus_mock;
45 auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
46 std::string type = "invalid";
47 std::string id = "id";
48 std::string path = "/xyz/openbmc_project/sensors/unknown/id";
49
50 DbusHelperMock helper;
Patrick Venturef8cb4642018-10-30 12:02:53 -070051 struct SensorProperties properties;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070052
Patrick Venturef8cb4642018-10-30 12:02:53 -070053 DbusPassive(bus_mock, type, id, &helper, properties, false);
Patrick Venture0ef1faf2018-06-13 12:50:53 -070054 // Success
55}
56
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070057class DbusPassiveTestObj : public ::testing::Test
58{
59 protected:
60 DbusPassiveTestObj() :
61 sdbus_mock(),
62 bus_mock(std::move(sdbusplus::get_mocked_new(&sdbus_mock))), helper()
63 {
Patrick Venture563a3562018-10-30 09:31:26 -070064 EXPECT_CALL(helper, getService(_, StrEq(SensorIntf), StrEq(path)))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070065 .WillOnce(Return("asdf"));
Patrick Venture0ef1faf2018-06-13 12:50:53 -070066
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070067 EXPECT_CALL(helper,
Patrick Venture563a3562018-10-30 09:31:26 -070068 getProperties(_, StrEq("asdf"), StrEq(path), NotNull()))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070069 .WillOnce(Invoke(
Patrick Venturee2ec0f62018-09-04 12:30:27 -070070 [&](sdbusplus::bus::bus& bus, const std::string& service,
71 const std::string& path, struct SensorProperties* prop) {
Patrick Venture0ef1faf2018-06-13 12:50:53 -070072 prop->scale = _scale;
73 prop->value = _value;
74 prop->unit = "x";
75 }));
Patrick Venture563a3562018-10-30 09:31:26 -070076 EXPECT_CALL(helper, thresholdsAsserted(_, StrEq("asdf"), StrEq(path)))
James Feist36b7d8e2018-10-05 15:39:01 -070077 .WillOnce(Return(false));
Patrick Venture0ef1faf2018-06-13 12:50:53 -070078
James Feistf81f2882019-02-26 11:26:36 -080079 auto info = conf::SensorConfig();
James Feist75eb7692019-02-25 12:50:02 -080080 ri = DbusPassive::createDbusPassive(bus_mock, type, id, &helper, &info);
Patrick Venturee2ec0f62018-09-04 12:30:27 -070081 passive = reinterpret_cast<DbusPassive*>(ri.get());
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070082 EXPECT_FALSE(passive == nullptr);
83 }
Patrick Venture0ef1faf2018-06-13 12:50:53 -070084
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070085 sdbusplus::SdBusMock sdbus_mock;
86 sdbusplus::bus::bus bus_mock;
87 DbusHelperMock helper;
88 std::string type = "temp";
89 std::string id = "id";
90 std::string path = "/xyz/openbmc_project/sensors/temperature/id";
91 int64_t _scale = -3;
92 int64_t _value = 10;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070093
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070094 std::unique_ptr<ReadInterface> ri;
Patrick Venturee2ec0f62018-09-04 12:30:27 -070095 DbusPassive* passive;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070096};
97
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070098TEST_F(DbusPassiveTestObj, ReadReturnsExpectedValues)
99{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700100 // Verify read is returning the values.
101 ReadReturn v;
102 v.value = 0.01;
103 // TODO: updated is set when the value is created, so we can range check
104 // it.
105 ReadReturn r = passive->read();
106 EXPECT_EQ(v.value, r.value);
107}
108
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700109TEST_F(DbusPassiveTestObj, SetValueUpdatesValue)
110{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700111 // Verify setvalue does as advertised.
112
113 double value = 0.01;
114 passive->setValue(value);
115
116 // TODO: updated is set when the value is set, so we can range check it.
117 ReadReturn r = passive->read();
118 EXPECT_EQ(value, r.value);
119}
120
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700121TEST_F(DbusPassiveTestObj, GetScaleReturnsExpectedValue)
122{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700123 // Verify the scale is returned as expected.
124 EXPECT_EQ(_scale, passive->getScale());
125}
126
Patrick Venture563a3562018-10-30 09:31:26 -0700127TEST_F(DbusPassiveTestObj, getIDReturnsExpectedValue)
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700128{
Patrick Venture563a3562018-10-30 09:31:26 -0700129 // Verify getID returns the expected value.
130 EXPECT_EQ(id, passive->getID());
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700131}
132
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700133TEST_F(DbusPassiveTestObj, VerifyHandlesDbusSignal)
134{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700135 // The dbus passive sensor listens for updates and if it's the Value
136 // property, it needs to handle it.
137
138 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
139 .WillOnce(Return(nullptr));
140 sdbusplus::message::message msg(nullptr, &sdbus_mock);
141
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700142 const char* Value = "Value";
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700143 int64_t xValue = 10000;
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700144 const char* intf = "xyz.openbmc_project.Sensor.Value";
James Feist1f802f52019-02-08 13:51:43 -0800145 // string, std::map<std::string, std::variant<int64_t>>
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700146 // msg.read(msgSensor, msgData);
147
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700148 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700149 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
150 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700151 // Read the first parameter, the string.
152 *s = intf;
153 return 0;
154 }))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700155 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
156 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700157 *s = Value;
158 // Read the string in the pair (dictionary).
159 return 0;
160 }));
161
162 // std::map
163 EXPECT_CALL(sdbus_mock,
164 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
165 .WillOnce(Return(0));
166
167 // while !at_end()
168 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
169 .WillOnce(Return(0))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700170 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700171
172 // std::pair
173 EXPECT_CALL(sdbus_mock,
174 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
175 .WillOnce(Return(0));
176
177 EXPECT_CALL(sdbus_mock,
178 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
179 .WillOnce(Return(1));
180 EXPECT_CALL(sdbus_mock,
181 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
182 .WillOnce(Return(0));
183
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700184 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700185 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
186 int64_t* s = static_cast<int64_t*>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700187 *s = xValue;
188 return 0;
189 }));
190
191 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
192 .WillOnce(Return(0)) /* variant. */
193 .WillOnce(Return(0)) /* std::pair */
194 .WillOnce(Return(0)); /* std::map */
195
Patrick Venture7af157b2018-10-30 11:24:40 -0700196 int rv = handleSensorValue(msg, passive);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700197 EXPECT_EQ(rv, 0); // It's always 0.
198
199 ReadReturn r = passive->read();
200 EXPECT_EQ(10, r.value);
201}
202
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700203TEST_F(DbusPassiveTestObj, VerifyIgnoresOtherPropertySignal)
204{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700205 // The dbus passive sensor listens for updates and if it's the Value
206 // property, it needs to handle it. In this case, it won't be.
207
208 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
209 .WillOnce(Return(nullptr));
210 sdbusplus::message::message msg(nullptr, &sdbus_mock);
211
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700212 const char* Scale = "Scale";
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700213 int64_t xScale = -6;
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700214 const char* intf = "xyz.openbmc_project.Sensor.Value";
James Feist1f802f52019-02-08 13:51:43 -0800215 // string, std::map<std::string, std::variant<int64_t>>
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700216 // msg.read(msgSensor, msgData);
217
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700218 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700219 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
220 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700221 // Read the first parameter, the string.
222 *s = intf;
223 return 0;
224 }))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700225 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
226 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700227 *s = Scale;
228 // Read the string in the pair (dictionary).
229 return 0;
230 }));
231
232 // std::map
233 EXPECT_CALL(sdbus_mock,
234 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
235 .WillOnce(Return(0));
236
237 // while !at_end()
238 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
239 .WillOnce(Return(0))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700240 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700241
242 // std::pair
243 EXPECT_CALL(sdbus_mock,
244 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
245 .WillOnce(Return(0));
246
247 EXPECT_CALL(sdbus_mock,
248 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
249 .WillOnce(Return(1));
250 EXPECT_CALL(sdbus_mock,
251 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
252 .WillOnce(Return(0));
253
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700254 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700255 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
256 int64_t* s = static_cast<int64_t*>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700257 *s = xScale;
258 return 0;
259 }));
260
261 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
262 .WillOnce(Return(0)) /* variant. */
263 .WillOnce(Return(0)) /* std::pair */
264 .WillOnce(Return(0)); /* std::map */
265
Patrick Venture7af157b2018-10-30 11:24:40 -0700266 int rv = handleSensorValue(msg, passive);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700267 EXPECT_EQ(rv, 0); // It's always 0.
268
269 ReadReturn r = passive->read();
270 EXPECT_EQ(0.01, r.value);
271}
James Feist36b7d8e2018-10-05 15:39:01 -0700272TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdAssert)
273{
274
275 // Verifies when a threshold is crossed the sensor goes into error state
276 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
277 .WillOnce(Return(nullptr));
278 sdbusplus::message::message msg(nullptr, &sdbus_mock);
279
280 const char* criticalAlarm = "CriticalAlarmHigh";
281 bool alarm = true;
282 const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
283
284 passive->setFailed(false);
285
286 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
287 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
288 const char** s = static_cast<const char**>(p);
289 // Read the first parameter, the string.
290 *s = intf;
291 return 0;
292 }))
293 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
294 const char** s = static_cast<const char**>(p);
295 *s = criticalAlarm;
296 // Read the string in the pair (dictionary).
297 return 0;
298 }));
299
300 // std::map
301 EXPECT_CALL(sdbus_mock,
302 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
303 .WillOnce(Return(0));
304
305 // while !at_end()
306 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
307 .WillOnce(Return(0))
308 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
309
310 // std::pair
311 EXPECT_CALL(sdbus_mock,
312 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
313 .WillOnce(Return(0));
314
315 EXPECT_CALL(sdbus_mock,
316 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
317 .WillOnce(Return(0));
318 EXPECT_CALL(sdbus_mock,
319 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
320 .WillOnce(Return(0));
321 EXPECT_CALL(sdbus_mock,
322 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
323 .WillOnce(Return(1));
324 EXPECT_CALL(sdbus_mock,
325 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
326 .WillOnce(Return(0));
327
328 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
329 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
330 bool* s = static_cast<bool*>(p);
331 *s = alarm;
332 return 0;
333 }));
334
335 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
336 .WillOnce(Return(0)) /* variant. */
337 .WillOnce(Return(0)) /* std::pair */
338 .WillOnce(Return(0)); /* std::map */
339
Patrick Venture7af157b2018-10-30 11:24:40 -0700340 int rv = handleSensorValue(msg, passive);
James Feist36b7d8e2018-10-05 15:39:01 -0700341 EXPECT_EQ(rv, 0); // It's always 0.
342 bool failed = passive->getFailed();
343 EXPECT_EQ(failed, true);
344}
345
346TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdDeassert)
347{
348
349 // Verifies when a threshold is deasserted a failed sensor goes back into
350 // the normal state
351 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
352 .WillOnce(Return(nullptr));
353 sdbusplus::message::message msg(nullptr, &sdbus_mock);
354
355 const char* criticalAlarm = "CriticalAlarmHigh";
356 bool alarm = false;
357 const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
358
359 passive->setFailed(true);
360
361 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
362 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
363 const char** s = static_cast<const char**>(p);
364 // Read the first parameter, the string.
365 *s = intf;
366 return 0;
367 }))
368 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
369 const char** s = static_cast<const char**>(p);
370 *s = criticalAlarm;
371 // Read the string in the pair (dictionary).
372 return 0;
373 }));
374
375 // std::map
376 EXPECT_CALL(sdbus_mock,
377 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
378 .WillOnce(Return(0));
379
380 // while !at_end()
381 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
382 .WillOnce(Return(0))
383 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
384
385 // std::pair
386 EXPECT_CALL(sdbus_mock,
387 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
388 .WillOnce(Return(0));
389
390 EXPECT_CALL(sdbus_mock,
391 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
392 .WillOnce(Return(0));
393 EXPECT_CALL(sdbus_mock,
394 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
395 .WillOnce(Return(0));
396 EXPECT_CALL(sdbus_mock,
397 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
398 .WillOnce(Return(1));
399 EXPECT_CALL(sdbus_mock,
400 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
401 .WillOnce(Return(0));
402
403 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
404 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
405 bool* s = static_cast<bool*>(p);
406 *s = alarm;
407 return 0;
408 }));
409
410 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
411 .WillOnce(Return(0)) /* variant. */
412 .WillOnce(Return(0)) /* std::pair */
413 .WillOnce(Return(0)); /* std::map */
414
Patrick Venture7af157b2018-10-30 11:24:40 -0700415 int rv = handleSensorValue(msg, passive);
James Feist36b7d8e2018-10-05 15:39:01 -0700416 EXPECT_EQ(rv, 0); // It's always 0.
417 bool failed = passive->getFailed();
418 EXPECT_EQ(failed, false);
Patrick Venture563a3562018-10-30 09:31:26 -0700419}