blob: 0bd6626ea12655b064411716b5376cc7863e228f [file] [log] [blame]
James Feist75eb7692019-02-25 12:50:02 -08001#include "conf.hpp"
Ed Tanousf8b6e552025-06-27 13:27:50 -07002#include "dbus/dbushelper_interface.hpp"
Patrick Venture0ef1faf2018-06-13 12:50:53 -07003#include "dbus/dbuspassive.hpp"
Ed Tanousf8b6e552025-06-27 13:27:50 -07004#include "interfaces.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07005#include "test/dbushelper_mock.hpp"
Patrick Venture0ef1faf2018-06-13 12:50:53 -07006
Ed Tanousf8b6e552025-06-27 13:27:50 -07007#include <systemd/sd-bus.h>
8
9#include <sdbusplus/bus.hpp>
10#include <sdbusplus/message.hpp>
Patrick Venture0ef1faf2018-06-13 12:50:53 -070011#include <sdbusplus/test/sdbus_mock.hpp>
Alexander Hansen207730b2025-10-28 12:24:05 +010012#include <xyz/openbmc_project/Sensor/Threshold/Critical/common.hpp>
13#include <xyz/openbmc_project/Sensor/Value/common.hpp>
14#include <xyz/openbmc_project/State/Decorator/Availability/common.hpp>
Patrick Venturea83a3ec2020-08-04 09:52:05 -070015
Ed Tanousf8b6e552025-06-27 13:27:50 -070016#include <cmath>
17#include <cstdint>
Patrick Venturea83a3ec2020-08-04 09:52:05 -070018#include <functional>
Patrick Venture8729eb92020-08-10 10:38:44 -070019#include <memory>
Patrick Venture0ef1faf2018-06-13 12:50:53 -070020#include <string>
Ed Tanousf8b6e552025-06-27 13:27:50 -070021#include <utility>
Patrick Venture0ef1faf2018-06-13 12:50:53 -070022
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070023#include <gmock/gmock.h>
24#include <gtest/gtest.h>
Patrick Venture0ef1faf2018-06-13 12:50:53 -070025
Patrick Venturea0764872020-08-08 07:48:43 -070026namespace pid_control
27{
28namespace
29{
30
Patrick Venture0ef1faf2018-06-13 12:50:53 -070031using ::testing::Invoke;
32using ::testing::IsNull;
33using ::testing::NotNull;
34using ::testing::Return;
35using ::testing::StrEq;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070036
Alexander Hansen207730b2025-10-28 12:24:05 +010037using SensorValue = sdbusplus::common::xyz::openbmc_project::sensor::Value;
38using ThresholdCritical =
39 sdbusplus::common::xyz::openbmc_project::sensor::threshold::Critical;
40using DecoratorAvailability =
41 sdbusplus::common::xyz::openbmc_project::state::decorator::Availability;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070042
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070043TEST(DbusPassiveTest, FactoryFailsWithInvalidType)
44{
Patrick Venture0ef1faf2018-06-13 12:50:53 -070045 // Verify the type is checked by the factory.
46
47 sdbusplus::SdBusMock sdbus_mock;
48 auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
49 std::string type = "invalid";
50 std::string id = "id";
51
Patrick Venture8729eb92020-08-10 10:38:44 -070052 auto helper = std::make_unique<DbusHelperMock>();
James Feistf81f2882019-02-26 11:26:36 -080053 auto info = conf::SensorConfig();
Patrick Venture0ef1faf2018-06-13 12:50:53 -070054
James Feist98b704e2019-06-03 16:24:53 -070055 std::unique_ptr<ReadInterface> ri = DbusPassive::createDbusPassive(
Patrick Venture8729eb92020-08-10 10:38:44 -070056 bus_mock, type, id, std::move(helper), &info, nullptr);
Patrick Venture0ef1faf2018-06-13 12:50:53 -070057
58 EXPECT_EQ(ri, nullptr);
59}
60
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070061TEST(DbusPassiveTest, BoringConstructorTest)
62{
Patrick Venturef8cb4642018-10-30 12:02:53 -070063 // Simply build the object, does no error checking.
Patrick Venture0ef1faf2018-06-13 12:50:53 -070064
65 sdbusplus::SdBusMock sdbus_mock;
66 auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
67 std::string type = "invalid";
68 std::string id = "id";
Alexander Hansen207730b2025-10-28 12:24:05 +010069 std::string path =
70 std::format("{}/unknown/id", SensorValue::namespace_path::value);
Patrick Venture0ef1faf2018-06-13 12:50:53 -070071
Patrick Venture8729eb92020-08-10 10:38:44 -070072 auto helper = std::make_unique<DbusHelperMock>();
Patrick Venture1df9e872020-10-08 15:35:01 -070073 SensorProperties properties;
Patrick Venture0ef1faf2018-06-13 12:50:53 -070074
Eric Yang3bfece82025-08-26 10:20:01 +000075 DbusPassive(bus_mock, type, id, std::move(helper), properties, false, false,
76 path, nullptr);
Patrick Venture0ef1faf2018-06-13 12:50:53 -070077 // Success
78}
79
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070080class DbusPassiveTestObj : public ::testing::Test
81{
82 protected:
83 DbusPassiveTestObj() :
Jayanth Othayoth2922eeb2024-12-08 07:47:37 -060084 sdbus_mock(), bus_mock(sdbusplus::get_mocked_new(&sdbus_mock)),
Patrick Venture8729eb92020-08-10 10:38:44 -070085 helper(std::make_unique<DbusHelperMock>())
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070086 {
Alexander Hansen207730b2025-10-28 12:24:05 +010087 EXPECT_CALL(*helper,
88 getService(StrEq(SensorValue::interface), StrEq(path)))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070089 .WillOnce(Return("asdf"));
Patrick Venture0ef1faf2018-06-13 12:50:53 -070090
Patrick Venture8729eb92020-08-10 10:38:44 -070091 EXPECT_CALL(*helper,
Patrick Venture9b936922020-08-10 11:28:39 -070092 getProperties(StrEq("asdf"), StrEq(path), NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +080093 .WillOnce(Invoke([&]([[maybe_unused]] const std::string& service,
94 [[maybe_unused]] const std::string& path,
95 SensorProperties* prop) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -040096 prop->scale = _scale;
97 prop->value = _value;
98 prop->unit = "x";
99 prop->min = 0;
100 prop->max = 0;
101 prop->available = true;
102 }));
Patrick Venture9b936922020-08-10 11:28:39 -0700103 EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
James Feist36b7d8e2018-10-05 15:39:01 -0700104 .WillOnce(Return(false));
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700105
James Feistf81f2882019-02-26 11:26:36 -0800106 auto info = conf::SensorConfig();
Alex.Song8f73ad72021-10-07 00:18:27 +0800107 info.unavailableAsFailed = true;
Patrick Venture8729eb92020-08-10 10:38:44 -0700108 ri = DbusPassive::createDbusPassive(bus_mock, type, id,
109 std::move(helper), &info, nullptr);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700110 passive = reinterpret_cast<DbusPassive*>(ri.get());
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700111 EXPECT_FALSE(passive == nullptr);
112 }
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700113
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700114 sdbusplus::SdBusMock sdbus_mock;
Patrick Williamsb228bc32022-07-22 19:26:56 -0500115 sdbusplus::bus_t bus_mock;
Patrick Venture8729eb92020-08-10 10:38:44 -0700116 std::unique_ptr<DbusHelperMock> helper;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700117 std::string type = "temp";
118 std::string id = "id";
Alexander Hansen207730b2025-10-28 12:24:05 +0100119 std::string path =
120 std::format("{}/{}/id", SensorValue::namespace_path::value,
121 SensorValue::namespace_path::temperature);
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700122 int64_t _scale = -3;
123 int64_t _value = 10;
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700124
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700125 std::unique_ptr<ReadInterface> ri;
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700126 DbusPassive* passive;
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700127};
128
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700129TEST_F(DbusPassiveTestObj, ReadReturnsExpectedValues)
130{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700131 // Verify read is returning the values.
132 ReadReturn v;
133 v.value = 0.01;
134 // TODO: updated is set when the value is created, so we can range check
135 // it.
136 ReadReturn r = passive->read();
137 EXPECT_EQ(v.value, r.value);
138}
139
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700140TEST_F(DbusPassiveTestObj, SetValueUpdatesValue)
141{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700142 // Verify setvalue does as advertised.
143
144 double value = 0.01;
145 passive->setValue(value);
146
147 // TODO: updated is set when the value is set, so we can range check it.
148 ReadReturn r = passive->read();
149 EXPECT_EQ(value, r.value);
150}
151
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700152TEST_F(DbusPassiveTestObj, GetScaleReturnsExpectedValue)
153{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700154 // Verify the scale is returned as expected.
155 EXPECT_EQ(_scale, passive->getScale());
156}
157
Patrick Venture563a3562018-10-30 09:31:26 -0700158TEST_F(DbusPassiveTestObj, getIDReturnsExpectedValue)
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700159{
Patrick Venture563a3562018-10-30 09:31:26 -0700160 // Verify getID returns the expected value.
161 EXPECT_EQ(id, passive->getID());
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700162}
163
Patrick Venture6b9f5992019-09-10 09:18:28 -0700164TEST_F(DbusPassiveTestObj, GetMinValueReturnsExpectedValue)
165{
166 EXPECT_DOUBLE_EQ(0, passive->getMin());
167}
168
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700169TEST_F(DbusPassiveTestObj, VerifyHandlesDbusSignal)
170{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700171 // The dbus passive sensor listens for updates and if it's the Value
172 // property, it needs to handle it.
173
174 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
175 .WillOnce(Return(nullptr));
Patrick Williamsb228bc32022-07-22 19:26:56 -0500176 sdbusplus::message_t msg(nullptr, &sdbus_mock);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700177
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700178 const char* Value = "Value";
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700179 int64_t xValue = 10000;
James Feist1f802f52019-02-08 13:51:43 -0800180 // string, std::map<std::string, std::variant<int64_t>>
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700181 // msg.read(msgSensor, msgData);
182
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700183 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800184 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
185 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400186 const char** s = static_cast<const char**>(p);
187 // Read the first parameter, the string.
Alexander Hansen207730b2025-10-28 12:24:05 +0100188 *s = SensorValue::interface;
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400189 return 0;
190 }))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800191 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
192 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400193 const char** s = static_cast<const char**>(p);
194 *s = Value;
195 // Read the string in the pair (dictionary).
196 return 0;
197 }));
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700198
199 // std::map
200 EXPECT_CALL(sdbus_mock,
201 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
202 .WillOnce(Return(0));
203
204 // while !at_end()
205 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
206 .WillOnce(Return(0))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700207 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700208
209 // std::pair
210 EXPECT_CALL(sdbus_mock,
211 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
212 .WillOnce(Return(0));
213
214 EXPECT_CALL(sdbus_mock,
215 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
216 .WillOnce(Return(1));
217 EXPECT_CALL(sdbus_mock,
218 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
219 .WillOnce(Return(0));
220
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700221 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800222 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
223 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400224 int64_t* s = static_cast<int64_t*>(p);
225 *s = xValue;
226 return 0;
227 }));
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700228
229 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
230 .WillOnce(Return(0)) /* variant. */
231 .WillOnce(Return(0)) /* std::pair */
232 .WillOnce(Return(0)); /* std::map */
233
Patrick Venture7af157b2018-10-30 11:24:40 -0700234 int rv = handleSensorValue(msg, passive);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700235 EXPECT_EQ(rv, 0); // It's always 0.
236
237 ReadReturn r = passive->read();
238 EXPECT_EQ(10, r.value);
239}
240
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700241TEST_F(DbusPassiveTestObj, VerifyIgnoresOtherPropertySignal)
242{
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700243 // The dbus passive sensor listens for updates and if it's the Value
244 // property, it needs to handle it. In this case, it won't be.
245
246 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
247 .WillOnce(Return(nullptr));
Patrick Williamsb228bc32022-07-22 19:26:56 -0500248 sdbusplus::message_t msg(nullptr, &sdbus_mock);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700249
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700250 const char* Scale = "Scale";
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700251 int64_t xScale = -6;
James Feist1f802f52019-02-08 13:51:43 -0800252 // string, std::map<std::string, std::variant<int64_t>>
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700253 // msg.read(msgSensor, msgData);
254
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700255 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800256 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
257 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400258 const char** s = static_cast<const char**>(p);
259 // Read the first parameter, the string.
Alexander Hansen207730b2025-10-28 12:24:05 +0100260 *s = SensorValue::interface;
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400261 return 0;
262 }))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800263 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
264 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400265 const char** s = static_cast<const char**>(p);
266 *s = Scale;
267 // Read the string in the pair (dictionary).
268 return 0;
269 }));
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700270
271 // std::map
272 EXPECT_CALL(sdbus_mock,
273 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
274 .WillOnce(Return(0));
275
276 // while !at_end()
277 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
278 .WillOnce(Return(0))
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700279 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700280
281 // std::pair
282 EXPECT_CALL(sdbus_mock,
283 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
284 .WillOnce(Return(0));
285
286 EXPECT_CALL(sdbus_mock,
287 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
288 .WillOnce(Return(1));
289 EXPECT_CALL(sdbus_mock,
290 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
291 .WillOnce(Return(0));
292
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700293 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800294 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
295 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400296 int64_t* s = static_cast<int64_t*>(p);
297 *s = xScale;
298 return 0;
299 }));
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700300
301 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
302 .WillOnce(Return(0)) /* variant. */
303 .WillOnce(Return(0)) /* std::pair */
304 .WillOnce(Return(0)); /* std::map */
305
Patrick Venture7af157b2018-10-30 11:24:40 -0700306 int rv = handleSensorValue(msg, passive);
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700307 EXPECT_EQ(rv, 0); // It's always 0.
308
309 ReadReturn r = passive->read();
310 EXPECT_EQ(0.01, r.value);
311}
Alex.Song8f73ad72021-10-07 00:18:27 +0800312
James Feist36b7d8e2018-10-05 15:39:01 -0700313TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdAssert)
314{
James Feist36b7d8e2018-10-05 15:39:01 -0700315 // Verifies when a threshold is crossed the sensor goes into error state
316 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
317 .WillOnce(Return(nullptr));
Patrick Williamsb228bc32022-07-22 19:26:56 -0500318 sdbusplus::message_t msg(nullptr, &sdbus_mock);
James Feist36b7d8e2018-10-05 15:39:01 -0700319
James Feist36b7d8e2018-10-05 15:39:01 -0700320 bool alarm = true;
James Feist36b7d8e2018-10-05 15:39:01 -0700321
322 passive->setFailed(false);
323
324 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800325 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
326 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400327 const char** s = static_cast<const char**>(p);
328 // Read the first parameter, the string.
Alexander Hansen207730b2025-10-28 12:24:05 +0100329 *s = ThresholdCritical::interface;
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400330 return 0;
331 }))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800332 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
333 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400334 const char** s = static_cast<const char**>(p);
Alexander Hansen207730b2025-10-28 12:24:05 +0100335 *s = ThresholdCritical::property_names::critical_alarm_high;
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400336 // Read the string in the pair (dictionary).
337 return 0;
338 }));
James Feist36b7d8e2018-10-05 15:39:01 -0700339
340 // std::map
341 EXPECT_CALL(sdbus_mock,
342 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
343 .WillOnce(Return(0));
344
345 // while !at_end()
346 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
347 .WillOnce(Return(0))
348 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
349
350 // std::pair
351 EXPECT_CALL(sdbus_mock,
352 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
353 .WillOnce(Return(0));
354
355 EXPECT_CALL(sdbus_mock,
356 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
357 .WillOnce(Return(0));
358 EXPECT_CALL(sdbus_mock,
359 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
360 .WillOnce(Return(0));
361 EXPECT_CALL(sdbus_mock,
362 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
363 .WillOnce(Return(1));
364 EXPECT_CALL(sdbus_mock,
365 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
366 .WillOnce(Return(0));
367
368 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800369 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
370 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400371 bool* s = static_cast<bool*>(p);
372 *s = alarm;
373 return 0;
374 }));
James Feist36b7d8e2018-10-05 15:39:01 -0700375
376 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
377 .WillOnce(Return(0)) /* variant. */
378 .WillOnce(Return(0)) /* std::pair */
379 .WillOnce(Return(0)); /* std::map */
380
Patrick Venture7af157b2018-10-30 11:24:40 -0700381 int rv = handleSensorValue(msg, passive);
James Feist36b7d8e2018-10-05 15:39:01 -0700382 EXPECT_EQ(rv, 0); // It's always 0.
383 bool failed = passive->getFailed();
384 EXPECT_EQ(failed, true);
385}
386
387TEST_F(DbusPassiveTestObj, VerifyCriticalThresholdDeassert)
388{
James Feist36b7d8e2018-10-05 15:39:01 -0700389 // Verifies when a threshold is deasserted a failed sensor goes back into
390 // the normal state
391 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
392 .WillOnce(Return(nullptr));
Patrick Williamsb228bc32022-07-22 19:26:56 -0500393 sdbusplus::message_t msg(nullptr, &sdbus_mock);
James Feist36b7d8e2018-10-05 15:39:01 -0700394
James Feist36b7d8e2018-10-05 15:39:01 -0700395 bool alarm = false;
James Feist36b7d8e2018-10-05 15:39:01 -0700396
397 passive->setFailed(true);
398
399 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800400 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
401 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400402 const char** s = static_cast<const char**>(p);
403 // Read the first parameter, the string.
Alexander Hansen207730b2025-10-28 12:24:05 +0100404 *s = ThresholdCritical::interface;
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400405 return 0;
406 }))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800407 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
408 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400409 const char** s = static_cast<const char**>(p);
Alexander Hansen207730b2025-10-28 12:24:05 +0100410 *s = ThresholdCritical::property_names::critical_alarm_high;
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400411 // Read the string in the pair (dictionary).
412 return 0;
413 }));
James Feist36b7d8e2018-10-05 15:39:01 -0700414
415 // std::map
416 EXPECT_CALL(sdbus_mock,
417 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
418 .WillOnce(Return(0));
419
420 // while !at_end()
421 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
422 .WillOnce(Return(0))
423 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
424
425 // std::pair
426 EXPECT_CALL(sdbus_mock,
427 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
428 .WillOnce(Return(0));
429
430 EXPECT_CALL(sdbus_mock,
431 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
432 .WillOnce(Return(0));
433 EXPECT_CALL(sdbus_mock,
434 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
435 .WillOnce(Return(0));
436 EXPECT_CALL(sdbus_mock,
437 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
438 .WillOnce(Return(1));
439 EXPECT_CALL(sdbus_mock,
440 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
441 .WillOnce(Return(0));
442
443 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800444 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
445 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400446 bool* s = static_cast<bool*>(p);
447 *s = alarm;
448 return 0;
449 }));
James Feist36b7d8e2018-10-05 15:39:01 -0700450
451 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
452 .WillOnce(Return(0)) /* variant. */
453 .WillOnce(Return(0)) /* std::pair */
454 .WillOnce(Return(0)); /* std::map */
455
Patrick Venture7af157b2018-10-30 11:24:40 -0700456 int rv = handleSensorValue(msg, passive);
James Feist36b7d8e2018-10-05 15:39:01 -0700457 EXPECT_EQ(rv, 0); // It's always 0.
458 bool failed = passive->getFailed();
459 EXPECT_EQ(failed, false);
Patrick Venture563a3562018-10-30 09:31:26 -0700460}
Patrick Venture6b9f5992019-09-10 09:18:28 -0700461
Alex.Song8f73ad72021-10-07 00:18:27 +0800462TEST_F(DbusPassiveTestObj, VerifyAvailableDeassert)
463{
Manojkiran Eda7ca88872024-06-17 11:55:48 +0530464 // Verifies when Available is deasserted && unavailableAsFailed == true,
Alex.Song8f73ad72021-10-07 00:18:27 +0800465 // the sensor goes into error state
466 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
467 .WillOnce(Return(nullptr));
Patrick Williamsb228bc32022-07-22 19:26:56 -0500468 sdbusplus::message_t msg(nullptr, &sdbus_mock);
Alex.Song8f73ad72021-10-07 00:18:27 +0800469
Alex.Song8f73ad72021-10-07 00:18:27 +0800470 bool asserted = false;
Alex.Song8f73ad72021-10-07 00:18:27 +0800471
472 passive->setAvailable(true);
473
474 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800475 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
476 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400477 const char** s = static_cast<const char**>(p);
478 // Read the first parameter, the string.
Alexander Hansen207730b2025-10-28 12:24:05 +0100479 *s = DecoratorAvailability::interface;
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400480 return 0;
481 }))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800482 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
483 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400484 const char** s = static_cast<const char**>(p);
Alexander Hansen207730b2025-10-28 12:24:05 +0100485 *s = DecoratorAvailability::property_names::available;
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400486 // Read the string in the pair (dictionary).
487 return 0;
488 }));
Alex.Song8f73ad72021-10-07 00:18:27 +0800489
490 // std::map
491 EXPECT_CALL(sdbus_mock,
492 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
493 .WillOnce(Return(0));
494
495 // while !at_end()
496 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
497 .WillOnce(Return(0))
498 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
499
500 // std::pair
501 EXPECT_CALL(sdbus_mock,
502 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
503 .WillOnce(Return(0));
504
505 EXPECT_CALL(sdbus_mock,
506 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
507 .WillOnce(Return(0));
508 EXPECT_CALL(sdbus_mock,
509 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
510 .WillOnce(Return(0));
511 EXPECT_CALL(sdbus_mock,
512 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
513 .WillOnce(Return(1));
514 EXPECT_CALL(sdbus_mock,
515 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
516 .WillOnce(Return(0));
517
518 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800519 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
520 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400521 bool* s = static_cast<bool*>(p);
522 *s = asserted;
523 return 0;
524 }));
Alex.Song8f73ad72021-10-07 00:18:27 +0800525
526 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
527 .WillOnce(Return(0)) /* variant. */
528 .WillOnce(Return(0)) /* std::pair */
529 .WillOnce(Return(0)); /* std::map */
530
531 int rv = handleSensorValue(msg, passive);
532 EXPECT_EQ(rv, 0); // It's always 0.
533 bool failed = passive->getFailed();
534 EXPECT_EQ(failed, true);
535}
536
537TEST_F(DbusPassiveTestObj, VerifyAvailableAssert)
538{
Manojkiran Eda7ca88872024-06-17 11:55:48 +0530539 // Verifies when Available is asserted && unavailableAsFailed == true,
Alex.Song8f73ad72021-10-07 00:18:27 +0800540 // an error sensor goes back to normal state
541 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
542 .WillOnce(Return(nullptr));
Patrick Williamsb228bc32022-07-22 19:26:56 -0500543 sdbusplus::message_t msg(nullptr, &sdbus_mock);
Alex.Song8f73ad72021-10-07 00:18:27 +0800544
Alex.Song8f73ad72021-10-07 00:18:27 +0800545 bool asserted = true;
Alex.Song8f73ad72021-10-07 00:18:27 +0800546
547 passive->setAvailable(false);
548 bool failed = passive->getFailed();
549 EXPECT_EQ(failed, true);
550
551 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800552 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
553 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400554 const char** s = static_cast<const char**>(p);
555 // Read the first parameter, the string.
Alexander Hansen207730b2025-10-28 12:24:05 +0100556 *s = DecoratorAvailability::interface;
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400557 return 0;
558 }))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800559 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
560 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400561 const char** s = static_cast<const char**>(p);
Alexander Hansen207730b2025-10-28 12:24:05 +0100562 *s = DecoratorAvailability::property_names::available;
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400563 // Read the string in the pair (dictionary).
564 return 0;
565 }));
Alex.Song8f73ad72021-10-07 00:18:27 +0800566
567 // std::map
568 EXPECT_CALL(sdbus_mock,
569 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
570 .WillOnce(Return(0));
571
572 // while !at_end()
573 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
574 .WillOnce(Return(0))
575 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
576
577 // std::pair
578 EXPECT_CALL(sdbus_mock,
579 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
580 .WillOnce(Return(0));
581
582 EXPECT_CALL(sdbus_mock,
583 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
584 .WillOnce(Return(0));
585 EXPECT_CALL(sdbus_mock,
586 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
587 .WillOnce(Return(0));
588 EXPECT_CALL(sdbus_mock,
589 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
590 .WillOnce(Return(1));
591 EXPECT_CALL(sdbus_mock,
592 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
593 .WillOnce(Return(0));
594
595 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800596 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
597 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400598 bool* s = static_cast<bool*>(p);
599 *s = asserted;
600 return 0;
601 }));
Alex.Song8f73ad72021-10-07 00:18:27 +0800602
603 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
604 .WillOnce(Return(0)) /* variant. */
605 .WillOnce(Return(0)) /* std::pair */
606 .WillOnce(Return(0)); /* std::map */
607
608 int rv = handleSensorValue(msg, passive);
609 EXPECT_EQ(rv, 0); // It's always 0.
610 failed = passive->getFailed();
611 EXPECT_EQ(failed, false);
612}
613
614class DbusPassiveTestUnaSensorNotAsFailedObj : public ::testing::Test
615{
616 protected:
617 DbusPassiveTestUnaSensorNotAsFailedObj() :
Jayanth Othayoth2922eeb2024-12-08 07:47:37 -0600618 sdbus_mock(), bus_mock(sdbusplus::get_mocked_new(&sdbus_mock)),
Alex.Song8f73ad72021-10-07 00:18:27 +0800619 helper(std::make_unique<DbusHelperMock>())
620 {
Alexander Hansen207730b2025-10-28 12:24:05 +0100621 EXPECT_CALL(*helper,
622 getService(StrEq(SensorValue::interface), StrEq(path)))
Alex.Song8f73ad72021-10-07 00:18:27 +0800623 .WillOnce(Return("asdf"));
624
625 EXPECT_CALL(*helper,
626 getProperties(StrEq("asdf"), StrEq(path), NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800627 .WillOnce(Invoke([&]([[maybe_unused]] const std::string& service,
628 [[maybe_unused]] const std::string& path,
629 SensorProperties* prop) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400630 prop->scale = _scale;
631 prop->value = _value;
632 prop->unit = "x";
633 prop->min = 0;
634 prop->max = 0;
635 prop->available = true;
636 }));
Alex.Song8f73ad72021-10-07 00:18:27 +0800637 EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
638 .WillOnce(Return(false));
639
640 auto info = conf::SensorConfig();
641 info.unavailableAsFailed = false;
642 ri = DbusPassive::createDbusPassive(bus_mock, type, id,
643 std::move(helper), &info, nullptr);
644 passive = reinterpret_cast<DbusPassive*>(ri.get());
645 EXPECT_FALSE(passive == nullptr);
646 }
647
648 sdbusplus::SdBusMock sdbus_mock;
Patrick Williamsb228bc32022-07-22 19:26:56 -0500649 sdbusplus::bus_t bus_mock;
Alex.Song8f73ad72021-10-07 00:18:27 +0800650 std::unique_ptr<DbusHelperMock> helper;
651 std::string type = "temp";
652 std::string id = "id";
Alexander Hansen207730b2025-10-28 12:24:05 +0100653 std::string path =
654 std::format("{}/{}/id", SensorValue::namespace_path::value,
655 SensorValue::namespace_path::temperature);
Alex.Song8f73ad72021-10-07 00:18:27 +0800656 int64_t _scale = -3;
657 int64_t _value = 10;
658
659 std::unique_ptr<ReadInterface> ri;
660 DbusPassive* passive;
661};
662
663TEST_F(DbusPassiveTestUnaSensorNotAsFailedObj, VerifyAvailableDeassert)
664{
Manojkiran Eda7ca88872024-06-17 11:55:48 +0530665 // Verifies when Available is deasserted && unavailableAsFailed == false,
Alex.Song8f73ad72021-10-07 00:18:27 +0800666 // the sensor remains at OK state but reading goes to NaN.
667 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
668 .WillOnce(Return(nullptr));
Patrick Williamsb228bc32022-07-22 19:26:56 -0500669 sdbusplus::message_t msg(nullptr, &sdbus_mock);
Alex.Song8f73ad72021-10-07 00:18:27 +0800670
Alex.Song8f73ad72021-10-07 00:18:27 +0800671 bool asserted = false;
Alex.Song8f73ad72021-10-07 00:18:27 +0800672
673 passive->setAvailable(true);
674
675 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800676 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
677 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400678 const char** s = static_cast<const char**>(p);
679 // Read the first parameter, the string.
Alexander Hansen207730b2025-10-28 12:24:05 +0100680 *s = DecoratorAvailability::interface;
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400681 return 0;
682 }))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800683 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
684 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400685 const char** s = static_cast<const char**>(p);
Alexander Hansen207730b2025-10-28 12:24:05 +0100686 *s = DecoratorAvailability::property_names::available;
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400687 // Read the string in the pair (dictionary).
688 return 0;
689 }));
Alex.Song8f73ad72021-10-07 00:18:27 +0800690
691 // std::map
692 EXPECT_CALL(sdbus_mock,
693 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
694 .WillOnce(Return(0));
695
696 // while !at_end()
697 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
698 .WillOnce(Return(0))
699 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
700
701 // std::pair
702 EXPECT_CALL(sdbus_mock,
703 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
704 .WillOnce(Return(0));
705
706 EXPECT_CALL(sdbus_mock,
707 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
708 .WillOnce(Return(0));
709 EXPECT_CALL(sdbus_mock,
710 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
711 .WillOnce(Return(0));
712 EXPECT_CALL(sdbus_mock,
713 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
714 .WillOnce(Return(1));
715 EXPECT_CALL(sdbus_mock,
716 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
717 .WillOnce(Return(0));
718
719 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800720 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
721 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400722 bool* s = static_cast<bool*>(p);
723 *s = asserted;
724 return 0;
725 }));
Alex.Song8f73ad72021-10-07 00:18:27 +0800726
727 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
728 .WillOnce(Return(0)) /* variant. */
729 .WillOnce(Return(0)) /* std::pair */
730 .WillOnce(Return(0)); /* std::map */
731
732 int rv = handleSensorValue(msg, passive);
733 EXPECT_EQ(rv, 0); // It's always 0.
734 bool failed = passive->getFailed();
735 EXPECT_EQ(failed, false);
736 ReadReturn r = passive->read();
737 EXPECT_FALSE(std::isfinite(r.value));
738}
739
740TEST_F(DbusPassiveTestUnaSensorNotAsFailedObj, VerifyAvailableAssert)
741{
Manojkiran Eda7ca88872024-06-17 11:55:48 +0530742 // Verifies when a sensor's state goes from unavailable to available
Alex.Song8f73ad72021-10-07 00:18:27 +0800743 // && unavailableAsFailed == false, this sensor remains at OK state.
744 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
745 .WillOnce(Return(nullptr));
Patrick Williamsb228bc32022-07-22 19:26:56 -0500746 sdbusplus::message_t msg(nullptr, &sdbus_mock);
Alex.Song8f73ad72021-10-07 00:18:27 +0800747
Alex.Song8f73ad72021-10-07 00:18:27 +0800748 bool asserted = true;
Alex.Song8f73ad72021-10-07 00:18:27 +0800749
750 passive->setAvailable(false);
751 bool failed = passive->getFailed();
752 EXPECT_EQ(failed, false);
753
754 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 's', NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800755 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
756 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400757 const char** s = static_cast<const char**>(p);
758 // Read the first parameter, the string.
Alexander Hansen207730b2025-10-28 12:24:05 +0100759 *s = DecoratorAvailability::interface;
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400760 return 0;
761 }))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800762 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
763 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400764 const char** s = static_cast<const char**>(p);
Alexander Hansen207730b2025-10-28 12:24:05 +0100765 *s = DecoratorAvailability::property_names::available;
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400766 // Read the string in the pair (dictionary).
767 return 0;
768 }));
Alex.Song8f73ad72021-10-07 00:18:27 +0800769
770 // std::map
771 EXPECT_CALL(sdbus_mock,
772 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
773 .WillOnce(Return(0));
774
775 // while !at_end()
776 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
777 .WillOnce(Return(0))
778 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
779
780 // std::pair
781 EXPECT_CALL(sdbus_mock,
782 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
783 .WillOnce(Return(0));
784
785 EXPECT_CALL(sdbus_mock,
786 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
787 .WillOnce(Return(0));
788 EXPECT_CALL(sdbus_mock,
789 sd_bus_message_verify_type(IsNull(), 'v', StrEq("d")))
790 .WillOnce(Return(0));
791 EXPECT_CALL(sdbus_mock,
792 sd_bus_message_verify_type(IsNull(), 'v', StrEq("b")))
793 .WillOnce(Return(1));
794 EXPECT_CALL(sdbus_mock,
795 sd_bus_message_enter_container(IsNull(), 'v', StrEq("b")))
796 .WillOnce(Return(0));
797
798 EXPECT_CALL(sdbus_mock, sd_bus_message_read_basic(IsNull(), 'b', NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800799 .WillOnce(Invoke([&]([[maybe_unused]] sd_bus_message* m,
800 [[maybe_unused]] char type, void* p) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400801 bool* s = static_cast<bool*>(p);
802 *s = asserted;
803 return 0;
804 }));
Alex.Song8f73ad72021-10-07 00:18:27 +0800805
806 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
807 .WillOnce(Return(0)) /* variant. */
808 .WillOnce(Return(0)) /* std::pair */
809 .WillOnce(Return(0)); /* std::map */
810
811 int rv = handleSensorValue(msg, passive);
812 EXPECT_EQ(rv, 0); // It's always 0.
813 failed = passive->getFailed();
814 EXPECT_EQ(failed, false);
815}
816
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800817void GetPropertiesMax3k([[maybe_unused]] const std::string& service,
818 [[maybe_unused]] const std::string& path,
Patrick Venture9b936922020-08-10 11:28:39 -0700819 SensorProperties* prop)
Patrick Venture6b9f5992019-09-10 09:18:28 -0700820{
821 prop->scale = -3;
822 prop->value = 10;
823 prop->unit = "x";
824 prop->min = 0;
825 prop->max = 3000;
826}
827
Patrick Venture9b936922020-08-10 11:28:39 -0700828using GetPropertiesFunction = std::function<void(
829 const std::string&, const std::string&, SensorProperties*)>;
Patrick Venture6b9f5992019-09-10 09:18:28 -0700830
831// TODO: There is definitely a cleaner way to do this.
832class DbusPassiveTest3kMaxObj : public ::testing::Test
833{
834 protected:
835 DbusPassiveTest3kMaxObj() :
Jayanth Othayoth2922eeb2024-12-08 07:47:37 -0600836 sdbus_mock(), bus_mock(sdbusplus::get_mocked_new(&sdbus_mock)),
Patrick Venture8729eb92020-08-10 10:38:44 -0700837 helper(std::make_unique<DbusHelperMock>())
Patrick Venture6b9f5992019-09-10 09:18:28 -0700838 {
Alexander Hansen207730b2025-10-28 12:24:05 +0100839 EXPECT_CALL(*helper,
840 getService(StrEq(SensorValue::interface), StrEq(path)))
Patrick Venture6b9f5992019-09-10 09:18:28 -0700841 .WillOnce(Return("asdf"));
842
Patrick Venture8729eb92020-08-10 10:38:44 -0700843 EXPECT_CALL(*helper,
Patrick Venture9b936922020-08-10 11:28:39 -0700844 getProperties(StrEq("asdf"), StrEq(path), NotNull()))
Patrick Venture6b9f5992019-09-10 09:18:28 -0700845 .WillOnce(_getProps);
Patrick Venture9b936922020-08-10 11:28:39 -0700846 EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
Patrick Venture6b9f5992019-09-10 09:18:28 -0700847 .WillOnce(Return(false));
848
849 auto info = conf::SensorConfig();
Patrick Venture8729eb92020-08-10 10:38:44 -0700850 ri = DbusPassive::createDbusPassive(bus_mock, type, id,
851 std::move(helper), &info, nullptr);
Patrick Venture6b9f5992019-09-10 09:18:28 -0700852 passive = reinterpret_cast<DbusPassive*>(ri.get());
853 EXPECT_FALSE(passive == nullptr);
854 }
855
856 sdbusplus::SdBusMock sdbus_mock;
Patrick Williamsb228bc32022-07-22 19:26:56 -0500857 sdbusplus::bus_t bus_mock;
Patrick Venture8729eb92020-08-10 10:38:44 -0700858 std::unique_ptr<DbusHelperMock> helper;
Patrick Venture6b9f5992019-09-10 09:18:28 -0700859 std::string type = "temp";
860 std::string id = "id";
Alexander Hansen207730b2025-10-28 12:24:05 +0100861 std::string path =
862 std::format("{}/{}/id", SensorValue::namespace_path::value,
863 SensorValue::namespace_path::temperature);
Patrick Venture6b9f5992019-09-10 09:18:28 -0700864 int64_t _scale = -3;
865 int64_t _value = 10;
866
867 std::unique_ptr<ReadInterface> ri;
868 DbusPassive* passive;
869 GetPropertiesFunction _getProps = &GetPropertiesMax3k;
870};
871
872TEST_F(DbusPassiveTest3kMaxObj, ReadMinAndMaxReturnsExpected)
873{
874 EXPECT_DOUBLE_EQ(0, passive->getMin());
875 EXPECT_DOUBLE_EQ(3, passive->getMax());
876}
877
878class DbusPassiveTest3kMaxIgnoredObj : public ::testing::Test
879{
880 protected:
881 DbusPassiveTest3kMaxIgnoredObj() :
Jayanth Othayoth2922eeb2024-12-08 07:47:37 -0600882 sdbus_mock(), bus_mock(sdbusplus::get_mocked_new(&sdbus_mock)),
Patrick Venture8729eb92020-08-10 10:38:44 -0700883 helper(std::make_unique<DbusHelperMock>())
Patrick Venture6b9f5992019-09-10 09:18:28 -0700884 {
Alexander Hansen207730b2025-10-28 12:24:05 +0100885 EXPECT_CALL(*helper,
886 getService(StrEq(SensorValue::interface), StrEq(path)))
Patrick Venture6b9f5992019-09-10 09:18:28 -0700887 .WillOnce(Return("asdf"));
888
Patrick Venture8729eb92020-08-10 10:38:44 -0700889 EXPECT_CALL(*helper,
Patrick Venture9b936922020-08-10 11:28:39 -0700890 getProperties(StrEq("asdf"), StrEq(path), NotNull()))
Patrick Venture6b9f5992019-09-10 09:18:28 -0700891 .WillOnce(_getProps);
Patrick Venture9b936922020-08-10 11:28:39 -0700892 EXPECT_CALL(*helper, thresholdsAsserted(StrEq("asdf"), StrEq(path)))
Patrick Venture6b9f5992019-09-10 09:18:28 -0700893 .WillOnce(Return(false));
894
895 auto info = conf::SensorConfig();
896 info.ignoreDbusMinMax = true;
Patrick Venture8729eb92020-08-10 10:38:44 -0700897 ri = DbusPassive::createDbusPassive(bus_mock, type, id,
898 std::move(helper), &info, nullptr);
Patrick Venture6b9f5992019-09-10 09:18:28 -0700899 passive = reinterpret_cast<DbusPassive*>(ri.get());
900 EXPECT_FALSE(passive == nullptr);
901 }
902
903 sdbusplus::SdBusMock sdbus_mock;
Patrick Williamsb228bc32022-07-22 19:26:56 -0500904 sdbusplus::bus_t bus_mock;
Patrick Venture8729eb92020-08-10 10:38:44 -0700905 std::unique_ptr<DbusHelperMock> helper;
Patrick Venture6b9f5992019-09-10 09:18:28 -0700906 std::string type = "temp";
907 std::string id = "id";
Alexander Hansen207730b2025-10-28 12:24:05 +0100908 std::string path =
909 std::format("{}/{}/id", SensorValue::namespace_path::value,
910 SensorValue::namespace_path::temperature);
Patrick Venture6b9f5992019-09-10 09:18:28 -0700911 int64_t _scale = -3;
912 int64_t _value = 10;
913
914 std::unique_ptr<ReadInterface> ri;
915 DbusPassive* passive;
916 GetPropertiesFunction _getProps = &GetPropertiesMax3k;
917};
918
919TEST_F(DbusPassiveTest3kMaxIgnoredObj, ReadMinAndMaxReturnsExpected)
920{
921 EXPECT_DOUBLE_EQ(0, passive->getMin());
922 EXPECT_DOUBLE_EQ(0, passive->getMax());
923}
Patrick Venturea0764872020-08-08 07:48:43 -0700924
925} // namespace
926} // namespace pid_control