blob: 84557ee6b4ddcfac08bbf1ab92af36da4980df5d [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
James Feist98b704e2019-06-03 16:24:53 -070034 std::unique_ptr<ReadInterface> ri = DbusPassive::createDbusPassive(
35 bus_mock, type, id, &helper, &info, nullptr);
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
James Feist98b704e2019-06-03 16:24:53 -070053 DbusPassive(bus_mock, type, id, &helper, properties, false, path, nullptr);
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 Feist98b704e2019-06-03 16:24:53 -070080 ri = DbusPassive::createDbusPassive(bus_mock, type, id, &helper, &info,
81 nullptr);
Patrick Venturee2ec0f62018-09-04 12:30:27 -070082 passive = reinterpret_cast<DbusPassive*>(ri.get());
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070083 EXPECT_FALSE(passive == nullptr);
84 }
Patrick Venture0ef1faf2018-06-13 12:50:53 -070085
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070086 sdbusplus::SdBusMock sdbus_mock;
87 sdbusplus::bus::bus bus_mock;
88 DbusHelperMock helper;
89 std::string type = "temp";
90 std::string id = "id";
91 std::string path = "/xyz/openbmc_project/sensors/temperature/id";
92 int64_t _scale = -3;
93 int64_t _value = 10;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070094
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070095 std::unique_ptr<ReadInterface> ri;
Patrick Venturee2ec0f62018-09-04 12:30:27 -070096 DbusPassive* passive;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070097};
98
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070099TEST_F(DbusPassiveTestObj, ReadReturnsExpectedValues)
100{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700101 // Verify read is returning the values.
102 ReadReturn v;
103 v.value = 0.01;
104 // TODO: updated is set when the value is created, so we can range check
105 // it.
106 ReadReturn r = passive->read();
107 EXPECT_EQ(v.value, r.value);
108}
109
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700110TEST_F(DbusPassiveTestObj, SetValueUpdatesValue)
111{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700112 // Verify setvalue does as advertised.
113
114 double value = 0.01;
115 passive->setValue(value);
116
117 // TODO: updated is set when the value is set, so we can range check it.
118 ReadReturn r = passive->read();
119 EXPECT_EQ(value, r.value);
120}
121
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700122TEST_F(DbusPassiveTestObj, GetScaleReturnsExpectedValue)
123{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700124 // Verify the scale is returned as expected.
125 EXPECT_EQ(_scale, passive->getScale());
126}
127
Patrick Venture563a3562018-10-30 09:31:26 -0700128TEST_F(DbusPassiveTestObj, getIDReturnsExpectedValue)
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700129{
Patrick Venture563a3562018-10-30 09:31:26 -0700130 // Verify getID returns the expected value.
131 EXPECT_EQ(id, passive->getID());
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700132}
133
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700134TEST_F(DbusPassiveTestObj, VerifyHandlesDbusSignal)
135{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700136 // 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
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700143 const char* Value = "Value";
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700144 int64_t xValue = 10000;
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700145 const char* intf = "xyz.openbmc_project.Sensor.Value";
James Feist1f802f52019-02-08 13:51:43 -0800146 // string, std::map<std::string, std::variant<int64_t>>
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700147 // msg.read(msgSensor, msgData);
148
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700149 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700150 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
151 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700152 // Read the first parameter, the string.
153 *s = intf;
154 return 0;
155 }))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700156 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
157 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700158 *s = Value;
159 // Read the string in the pair (dictionary).
160 return 0;
161 }));
162
163 // std::map
164 EXPECT_CALL(sdbus_mock,
165 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
166 .WillOnce(Return(0));
167
168 // while !at_end()
169 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
170 .WillOnce(Return(0))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700171 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700172
173 // std::pair
174 EXPECT_CALL(sdbus_mock,
175 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
176 .WillOnce(Return(0));
177
178 EXPECT_CALL(sdbus_mock,
179 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
180 .WillOnce(Return(1));
181 EXPECT_CALL(sdbus_mock,
182 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
183 .WillOnce(Return(0));
184
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700185 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700186 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
187 int64_t* s = static_cast<int64_t*>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700188 *s = xValue;
189 return 0;
190 }));
191
192 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
193 .WillOnce(Return(0)) /* variant. */
194 .WillOnce(Return(0)) /* std::pair */
195 .WillOnce(Return(0)); /* std::map */
196
Patrick Venture7af157b2018-10-30 11:24:40 -0700197 int rv = handleSensorValue(msg, passive);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700198 EXPECT_EQ(rv, 0); // It's always 0.
199
200 ReadReturn r = passive->read();
201 EXPECT_EQ(10, r.value);
202}
203
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700204TEST_F(DbusPassiveTestObj, VerifyIgnoresOtherPropertySignal)
205{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700206 // The dbus passive sensor listens for updates and if it's the Value
207 // property, it needs to handle it. In this case, it won't be.
208
209 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
210 .WillOnce(Return(nullptr));
211 sdbusplus::message::message msg(nullptr, &sdbus_mock);
212
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700213 const char* Scale = "Scale";
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700214 int64_t xScale = -6;
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700215 const char* intf = "xyz.openbmc_project.Sensor.Value";
James Feist1f802f52019-02-08 13:51:43 -0800216 // string, std::map<std::string, std::variant<int64_t>>
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700217 // msg.read(msgSensor, msgData);
218
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700219 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700220 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
221 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700222 // Read the first parameter, the string.
223 *s = intf;
224 return 0;
225 }))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700226 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
227 const char** s = static_cast<const char**>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700228 *s = Scale;
229 // Read the string in the pair (dictionary).
230 return 0;
231 }));
232
233 // std::map
234 EXPECT_CALL(sdbus_mock,
235 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
236 .WillOnce(Return(0));
237
238 // while !at_end()
239 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
240 .WillOnce(Return(0))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700241 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700242
243 // std::pair
244 EXPECT_CALL(sdbus_mock,
245 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
246 .WillOnce(Return(0));
247
248 EXPECT_CALL(sdbus_mock,
249 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
250 .WillOnce(Return(1));
251 EXPECT_CALL(sdbus_mock,
252 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
253 .WillOnce(Return(0));
254
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700255 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700256 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
257 int64_t* s = static_cast<int64_t*>(p);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700258 *s = xScale;
259 return 0;
260 }));
261
262 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
263 .WillOnce(Return(0)) /* variant. */
264 .WillOnce(Return(0)) /* std::pair */
265 .WillOnce(Return(0)); /* std::map */
266
Patrick Venture7af157b2018-10-30 11:24:40 -0700267 int rv = handleSensorValue(msg, passive);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700268 EXPECT_EQ(rv, 0); // It's always 0.
269
270 ReadReturn r = passive->read();
271 EXPECT_EQ(0.01, r.value);
272}
James Feist36b7d8e2018-10-05 15:39:01 -0700273TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdAssert)
274{
275
276 // Verifies when a threshold is crossed the sensor goes into error state
277 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
278 .WillOnce(Return(nullptr));
279 sdbusplus::message::message msg(nullptr, &sdbus_mock);
280
281 const char* criticalAlarm = "CriticalAlarmHigh";
282 bool alarm = true;
283 const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
284
285 passive->setFailed(false);
286
287 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
288 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
289 const char** s = static_cast<const char**>(p);
290 // Read the first parameter, the string.
291 *s = intf;
292 return 0;
293 }))
294 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
295 const char** s = static_cast<const char**>(p);
296 *s = criticalAlarm;
297 // Read the string in the pair (dictionary).
298 return 0;
299 }));
300
301 // std::map
302 EXPECT_CALL(sdbus_mock,
303 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
304 .WillOnce(Return(0));
305
306 // while !at_end()
307 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
308 .WillOnce(Return(0))
309 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
310
311 // std::pair
312 EXPECT_CALL(sdbus_mock,
313 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
314 .WillOnce(Return(0));
315
316 EXPECT_CALL(sdbus_mock,
317 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
318 .WillOnce(Return(0));
319 EXPECT_CALL(sdbus_mock,
320 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
321 .WillOnce(Return(0));
322 EXPECT_CALL(sdbus_mock,
323 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
324 .WillOnce(Return(1));
325 EXPECT_CALL(sdbus_mock,
326 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
327 .WillOnce(Return(0));
328
329 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
330 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
331 bool* s = static_cast<bool*>(p);
332 *s = alarm;
333 return 0;
334 }));
335
336 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
337 .WillOnce(Return(0)) /* variant. */
338 .WillOnce(Return(0)) /* std::pair */
339 .WillOnce(Return(0)); /* std::map */
340
Patrick Venture7af157b2018-10-30 11:24:40 -0700341 int rv = handleSensorValue(msg, passive);
James Feist36b7d8e2018-10-05 15:39:01 -0700342 EXPECT_EQ(rv, 0); // It's always 0.
343 bool failed = passive->getFailed();
344 EXPECT_EQ(failed, true);
345}
346
347TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdDeassert)
348{
349
350 // Verifies when a threshold is deasserted a failed sensor goes back into
351 // the normal state
352 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
353 .WillOnce(Return(nullptr));
354 sdbusplus::message::message msg(nullptr, &sdbus_mock);
355
356 const char* criticalAlarm = "CriticalAlarmHigh";
357 bool alarm = false;
358 const char* intf = "xyz.openbmc_project.Sensor.Threshold.Critical";
359
360 passive->setFailed(true);
361
362 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
363 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
364 const char** s = static_cast<const char**>(p);
365 // Read the first parameter, the string.
366 *s = intf;
367 return 0;
368 }))
369 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
370 const char** s = static_cast<const char**>(p);
371 *s = criticalAlarm;
372 // Read the string in the pair (dictionary).
373 return 0;
374 }));
375
376 // std::map
377 EXPECT_CALL(sdbus_mock,
378 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
379 .WillOnce(Return(0));
380
381 // while !at_end()
382 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
383 .WillOnce(Return(0))
384 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
385
386 // std::pair
387 EXPECT_CALL(sdbus_mock,
388 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
389 .WillOnce(Return(0));
390
391 EXPECT_CALL(sdbus_mock,
392 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
393 .WillOnce(Return(0));
394 EXPECT_CALL(sdbus_mock,
395 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
396 .WillOnce(Return(0));
397 EXPECT_CALL(sdbus_mock,
398 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
399 .WillOnce(Return(1));
400 EXPECT_CALL(sdbus_mock,
401 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
402 .WillOnce(Return(0));
403
404 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
405 .WillOnce(Invoke([&](sd_bus_message* m, char type, void* p) {
406 bool* s = static_cast<bool*>(p);
407 *s = alarm;
408 return 0;
409 }));
410
411 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
412 .WillOnce(Return(0)) /* variant. */
413 .WillOnce(Return(0)) /* std::pair */
414 .WillOnce(Return(0)); /* std::map */
415
Patrick Venture7af157b2018-10-30 11:24:40 -0700416 int rv = handleSensorValue(msg, passive);
James Feist36b7d8e2018-10-05 15:39:01 -0700417 EXPECT_EQ(rv, 0); // It's always 0.
418 bool failed = passive->getFailed();
419 EXPECT_EQ(failed, false);
Patrick Venture563a3562018-10-30 09:31:26 -0700420}