blob: 52126cf8644e5f466212fc090d7925e30361c582 [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 Venturef8cb4642018-10-30 12:02:53 -070039 // Simply build the object, does no error checking.
Patrick Venture0ef1faf2018-06-13 12:50:53 -070040
41 sdbusplus::SdBusMock sdbus_mock;
42 auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
43 std::string type = "invalid";
44 std::string id = "id";
45 std::string path = "/xyz/openbmc_project/sensors/unknown/id";
46
47 DbusHelperMock helper;
Patrick Venturef8cb4642018-10-30 12:02:53 -070048 struct SensorProperties properties;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070049
Patrick Venturef8cb4642018-10-30 12:02:53 -070050 DbusPassive(bus_mock, type, id, &helper, properties, false);
Patrick Venture0ef1faf2018-06-13 12:50:53 -070051 // Success
52}
53
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070054class DbusPassiveTestObj : public ::testing::Test
55{
56 protected:
57 DbusPassiveTestObj() :
58 sdbus_mock(),
59 bus_mock(std::move(sdbusplus::get_mocked_new(&sdbus_mock))), helper()
60 {
Patrick Venture563a3562018-10-30 09:31:26 -070061 EXPECT_CALL(helper, getService(_, StrEq(SensorIntf), StrEq(path)))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070062 .WillOnce(Return("asdf"));
Patrick Venture0ef1faf2018-06-13 12:50:53 -070063
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070064 EXPECT_CALL(helper,
Patrick Venture563a3562018-10-30 09:31:26 -070065 getProperties(_, StrEq("asdf"), StrEq(path), NotNull()))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070066 .WillOnce(Invoke(
Patrick Venturee2ec0f62018-09-04 12:30:27 -070067 [&](sdbusplus::bus::bus& bus, const std::string& service,
68 const std::string& path, struct SensorProperties* prop) {
Patrick Venture0ef1faf2018-06-13 12:50:53 -070069 prop->scale = _scale;
70 prop->value = _value;
71 prop->unit = "x";
72 }));
Patrick Venture563a3562018-10-30 09:31:26 -070073 EXPECT_CALL(helper, thresholdsAsserted(_, StrEq("asdf"), StrEq(path)))
James Feist36b7d8e2018-10-05 15:39:01 -070074 .WillOnce(Return(false));
Patrick Venture0ef1faf2018-06-13 12:50:53 -070075
Patrick Venture563a3562018-10-30 09:31:26 -070076 ri = DbusPassive::createDbusPassive(bus_mock, type, id, &helper);
Patrick Venturee2ec0f62018-09-04 12:30:27 -070077 passive = reinterpret_cast<DbusPassive*>(ri.get());
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070078 EXPECT_FALSE(passive == nullptr);
79 }
Patrick Venture0ef1faf2018-06-13 12:50:53 -070080
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070081 sdbusplus::SdBusMock sdbus_mock;
82 sdbusplus::bus::bus bus_mock;
83 DbusHelperMock helper;
84 std::string type = "temp";
85 std::string id = "id";
86 std::string path = "/xyz/openbmc_project/sensors/temperature/id";
87 int64_t _scale = -3;
88 int64_t _value = 10;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070089
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070090 std::unique_ptr<ReadInterface> ri;
Patrick Venturee2ec0f62018-09-04 12:30:27 -070091 DbusPassive* passive;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070092};
93
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070094TEST_F(DbusPassiveTestObj, ReadReturnsExpectedValues)
95{
Patrick Venture0ef1faf2018-06-13 12:50:53 -070096 // Verify read is returning the values.
97 ReadReturn v;
98 v.value = 0.01;
99 // TODO: updated is set when the value is created, so we can range check
100 // it.
101 ReadReturn r = passive->read();
102 EXPECT_EQ(v.value, r.value);
103}
104
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700105TEST_F(DbusPassiveTestObj, SetValueUpdatesValue)
106{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700107 // Verify setvalue does as advertised.
108
109 double value = 0.01;
110 passive->setValue(value);
111
112 // TODO: updated is set when the value is set, so we can range check it.
113 ReadReturn r = passive->read();
114 EXPECT_EQ(value, r.value);
115}
116
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700117TEST_F(DbusPassiveTestObj, GetScaleReturnsExpectedValue)
118{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700119 // Verify the scale is returned as expected.
120 EXPECT_EQ(_scale, passive->getScale());
121}
122
Patrick Venture563a3562018-10-30 09:31:26 -0700123TEST_F(DbusPassiveTestObj, getIDReturnsExpectedValue)
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700124{
Patrick Venture563a3562018-10-30 09:31:26 -0700125 // Verify getID returns the expected value.
126 EXPECT_EQ(id, passive->getID());
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700127}
128
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700129TEST_F(DbusPassiveTestObj, VerifyHandlesDbusSignal)
130{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700131 // The dbus passive sensor listens for updates and if it's the Value
132 // property, it needs to handle it.
133
134 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
135 .WillOnce(Return(nullptr));
136 sdbusplus::message::message msg(nullptr, &sdbus_mock);
137
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700138 const char* Value = "Value";
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700139 int64_t xValue = 10000;
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700140 const char* intf = "xyz.openbmc_project.Sensor.Value";
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700141 // string, std::map<std::string, sdbusplus::message::variant<int64_t>>
142 // msg.read(msgSensor, msgData);
143
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700144 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700145 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
146 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700147 // Read the first parameter, the string.
148 *s = intf;
149 return 0;
150 }))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700151 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
152 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700153 *s = Value;
154 // Read the string in the pair (dictionary).
155 return 0;
156 }));
157
158 // std::map
159 EXPECT_CALL(sdbus_mock,
160 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
161 .WillOnce(Return(0));
162
163 // while !at_end()
164 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
165 .WillOnce(Return(0))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700166 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700167
168 // std::pair
169 EXPECT_CALL(sdbus_mock,
170 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
171 .WillOnce(Return(0));
172
173 EXPECT_CALL(sdbus_mock,
174 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
175 .WillOnce(Return(1));
176 EXPECT_CALL(sdbus_mock,
177 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
178 .WillOnce(Return(0));
179
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700180 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700181 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
182 int64_t* s = static_cast<int64_t*>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700183 *s = xValue;
184 return 0;
185 }));
186
187 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
188 .WillOnce(Return(0)) /* variant. */
189 .WillOnce(Return(0)) /* std::pair */
190 .WillOnce(Return(0)); /* std::map */
191
Patrick Venture7af157b2018-10-30 11:24:40 -0700192 int rv = handleSensorValue(msg, passive);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700193 EXPECT_EQ(rv, 0); // It's always 0.
194
195 ReadReturn r = passive->read();
196 EXPECT_EQ(10, r.value);
197}
198
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700199TEST_F(DbusPassiveTestObj, VerifyIgnoresOtherPropertySignal)
200{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700201 // The dbus passive sensor listens for updates and if it's the Value
202 // property, it needs to handle it. In this case, it won't be.
203
204 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
205 .WillOnce(Return(nullptr));
206 sdbusplus::message::message msg(nullptr, &sdbus_mock);
207
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700208 const char* Scale = "Scale";
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700209 int64_t xScale = -6;
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700210 const char* intf = "xyz.openbmc_project.Sensor.Value";
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700211 // string, std::map<std::string, sdbusplus::message::variant<int64_t>>
212 // msg.read(msgSensor, msgData);
213
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700214 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700215 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
216 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700217 // Read the first parameter, the string.
218 *s = intf;
219 return 0;
220 }))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700221 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
222 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700223 *s = Scale;
224 // Read the string in the pair (dictionary).
225 return 0;
226 }));
227
228 // std::map
229 EXPECT_CALL(sdbus_mock,
230 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
231 .WillOnce(Return(0));
232
233 // while !at_end()
234 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
235 .WillOnce(Return(0))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700236 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700237
238 // std::pair
239 EXPECT_CALL(sdbus_mock,
240 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
241 .WillOnce(Return(0));
242
243 EXPECT_CALL(sdbus_mock,
244 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
245 .WillOnce(Return(1));
246 EXPECT_CALL(sdbus_mock,
247 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
248 .WillOnce(Return(0));
249
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700250 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700251 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
252 int64_t* s = static_cast<int64_t*>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700253 *s = xScale;
254 return 0;
255 }));
256
257 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
258 .WillOnce(Return(0)) /* variant. */
259 .WillOnce(Return(0)) /* std::pair */
260 .WillOnce(Return(0)); /* std::map */
261
Patrick Venture7af157b2018-10-30 11:24:40 -0700262 int rv = handleSensorValue(msg, passive);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700263 EXPECT_EQ(rv, 0); // It's always 0.
264
265 ReadReturn r = passive->read();
266 EXPECT_EQ(0.01, r.value);
267}
James Feist36b7d8e2018-10-05 15:39:01 -0700268TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdAssert)
269{
270
271 // Verifies when a threshold is crossed the sensor goes into error state
272 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
273 .WillOnce(Return(nullptr));
274 sdbusplus::message::message msg(nullptr, &sdbus_mock);
275
276 const char* criticalAlarm = "CriticalAlarmHigh";
277 bool alarm = true;
278 const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
279
280 passive->setFailed(false);
281
282 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
283 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
284 const char** s = static_cast<const char**>(p);
285 // Read the first parameter, the string.
286 *s = intf;
287 return 0;
288 }))
289 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
290 const char** s = static_cast<const char**>(p);
291 *s = criticalAlarm;
292 // Read the string in the pair (dictionary).
293 return 0;
294 }));
295
296 // std::map
297 EXPECT_CALL(sdbus_mock,
298 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
299 .WillOnce(Return(0));
300
301 // while !at_end()
302 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
303 .WillOnce(Return(0))
304 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
305
306 // std::pair
307 EXPECT_CALL(sdbus_mock,
308 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
309 .WillOnce(Return(0));
310
311 EXPECT_CALL(sdbus_mock,
312 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
313 .WillOnce(Return(0));
314 EXPECT_CALL(sdbus_mock,
315 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
316 .WillOnce(Return(0));
317 EXPECT_CALL(sdbus_mock,
318 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
319 .WillOnce(Return(1));
320 EXPECT_CALL(sdbus_mock,
321 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
322 .WillOnce(Return(0));
323
324 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
325 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
326 bool* s = static_cast<bool*>(p);
327 *s = alarm;
328 return 0;
329 }));
330
331 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
332 .WillOnce(Return(0)) /* variant. */
333 .WillOnce(Return(0)) /* std::pair */
334 .WillOnce(Return(0)); /* std::map */
335
Patrick Venture7af157b2018-10-30 11:24:40 -0700336 int rv = handleSensorValue(msg, passive);
James Feist36b7d8e2018-10-05 15:39:01 -0700337 EXPECT_EQ(rv, 0); // It's always 0.
338 bool failed = passive->getFailed();
339 EXPECT_EQ(failed, true);
340}
341
342TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdDeassert)
343{
344
345 // Verifies when a threshold is deasserted a failed sensor goes back into
346 // the normal state
347 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
348 .WillOnce(Return(nullptr));
349 sdbusplus::message::message msg(nullptr, &sdbus_mock);
350
351 const char* criticalAlarm = "CriticalAlarmHigh";
352 bool alarm = false;
353 const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
354
355 passive->setFailed(true);
356
357 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
358 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
359 const char** s = static_cast<const char**>(p);
360 // Read the first parameter, the string.
361 *s = intf;
362 return 0;
363 }))
364 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
365 const char** s = static_cast<const char**>(p);
366 *s = criticalAlarm;
367 // Read the string in the pair (dictionary).
368 return 0;
369 }));
370
371 // std::map
372 EXPECT_CALL(sdbus_mock,
373 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
374 .WillOnce(Return(0));
375
376 // while !at_end()
377 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
378 .WillOnce(Return(0))
379 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
380
381 // std::pair
382 EXPECT_CALL(sdbus_mock,
383 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
384 .WillOnce(Return(0));
385
386 EXPECT_CALL(sdbus_mock,
387 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
388 .WillOnce(Return(0));
389 EXPECT_CALL(sdbus_mock,
390 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
391 .WillOnce(Return(0));
392 EXPECT_CALL(sdbus_mock,
393 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
394 .WillOnce(Return(1));
395 EXPECT_CALL(sdbus_mock,
396 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
397 .WillOnce(Return(0));
398
399 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
400 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
401 bool* s = static_cast<bool*>(p);
402 *s = alarm;
403 return 0;
404 }));
405
406 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
407 .WillOnce(Return(0)) /* variant. */
408 .WillOnce(Return(0)) /* std::pair */
409 .WillOnce(Return(0)); /* std::map */
410
Patrick Venture7af157b2018-10-30 11:24:40 -0700411 int rv = handleSensorValue(msg, passive);
James Feist36b7d8e2018-10-05 15:39:01 -0700412 EXPECT_EQ(rv, 0); // It's always 0.
413 bool failed = passive->getFailed();
414 EXPECT_EQ(failed, false);
Patrick Venture563a3562018-10-30 09:31:26 -0700415}