blob: 7764c8da3c2c25511a1443513ceb9a28df8bf5e0 [file] [log] [blame]
Wludzik, Jozef76833cb2020-12-21 14:42:41 +01001#include "dbus_environment.hpp"
2#include "helpers.hpp"
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +01003#include "messages/collect_trigger_id.hpp"
4#include "messages/trigger_presence_changed_ind.hpp"
Cezary Zwolaka4e67612021-02-18 13:16:16 +01005#include "mocks/json_storage_mock.hpp"
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +01006#include "mocks/report_manager_mock.hpp"
Szymon Dompke94f71c52021-12-10 07:16:33 +01007#include "mocks/sensor_mock.hpp"
8#include "mocks/threshold_mock.hpp"
9#include "mocks/trigger_factory_mock.hpp"
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010010#include "mocks/trigger_manager_mock.hpp"
11#include "params/trigger_params.hpp"
12#include "trigger.hpp"
Szymon Dompkee28aa532021-10-27 12:33:12 +020013#include "trigger_manager.hpp"
Cezary Zwolak4416fce2021-03-17 03:21:06 +010014#include "utils/conversion_trigger.hpp"
Szymon Dompke32305f12022-07-05 15:37:21 +020015#include "utils/dbus_path_utils.hpp"
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +010016#include "utils/messanger.hpp"
Szymon Dompke32305f12022-07-05 15:37:21 +020017#include "utils/string_utils.hpp"
Cezary Zwolak4416fce2021-03-17 03:21:06 +010018#include "utils/transform.hpp"
19#include "utils/tstring.hpp"
20
21#include <boost/range/combine.hpp>
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010022
23using namespace testing;
24using namespace std::literals::string_literals;
Szymon Dompke1cdd7e42022-06-08 14:43:13 +020025using sdbusplus::message::object_path;
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010026
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +020027static constexpr size_t expectedTriggerVersion = 2;
Cezary Zwolaka4e67612021-02-18 13:16:16 +010028
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010029class TestTrigger : public Test
30{
31 public:
32 TriggerParams triggerParams;
Cezary Zwolak4416fce2021-03-17 03:21:06 +010033 TriggerParams triggerDiscreteParams =
34 TriggerParams()
Szymon Dompkee28aa532021-10-27 12:33:12 +020035 .id("DiscreteTrigger")
36 .name("My Discrete Trigger")
Cezary Zwolak4416fce2021-03-17 03:21:06 +010037 .thresholdParams(std::vector<discrete::LabeledThresholdParam>{
38 discrete::LabeledThresholdParam{
39 "userId", discrete::Severity::warning,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000040 Milliseconds(10).count(), "15.2"},
Cezary Zwolak4416fce2021-03-17 03:21:06 +010041 discrete::LabeledThresholdParam{
42 "userId_2", discrete::Severity::critical,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000043 Milliseconds(5).count(), "32.7"},
Cezary Zwolak4416fce2021-03-17 03:21:06 +010044 });
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010045
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +010046 std::unique_ptr<ReportManagerMock> reportManagerMockPtr =
47 std::make_unique<NiceMock<ReportManagerMock>>();
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010048 std::unique_ptr<TriggerManagerMock> triggerManagerMockPtr =
49 std::make_unique<NiceMock<TriggerManagerMock>>();
Szymon Dompke94f71c52021-12-10 07:16:33 +010050 std::unique_ptr<TriggerFactoryMock> triggerFactoryMockPtr =
51 std::make_unique<NiceMock<TriggerFactoryMock>>();
Cezary Zwolaka4e67612021-02-18 13:16:16 +010052 testing::NiceMock<StorageMock> storageMock;
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +010053 NiceMock<MockFunction<void(const messages::TriggerPresenceChangedInd)>>
54 triggerPresenceChanged;
Szymon Dompke94f71c52021-12-10 07:16:33 +010055 std::vector<std::shared_ptr<interfaces::Threshold>> thresholdMocks;
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +010056 utils::Messanger messanger;
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010057 std::unique_ptr<Trigger> sut;
58
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +010059 TestTrigger() : messanger(DbusEnvironment::getIoc())
60 {
61 messanger.on_receive<messages::TriggerPresenceChangedInd>(
62 [this](const auto& msg) { triggerPresenceChanged.Call(msg); });
63 }
64
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010065 void SetUp() override
66 {
Cezary Zwolaka4e67612021-02-18 13:16:16 +010067 sut = makeTrigger(triggerParams);
68 }
69
Patrick Williams583ba442025-02-03 14:28:19 -050070 static std::vector<LabeledSensorInfo> convertToLabeledSensor(
71 const SensorsInfo& sensorsInfo)
Cezary Zwolak4416fce2021-03-17 03:21:06 +010072 {
73 return utils::transform(sensorsInfo, [](const auto& sensorInfo) {
74 const auto& [sensorPath, sensorMetadata] = sensorInfo;
75 return LabeledSensorInfo("service1", sensorPath, sensorMetadata);
76 });
77 }
78
Cezary Zwolaka4e67612021-02-18 13:16:16 +010079 std::unique_ptr<Trigger> makeTrigger(const TriggerParams& params)
80 {
Szymon Dompke94f71c52021-12-10 07:16:33 +010081 thresholdMocks =
82 ThresholdMock::makeThresholds(params.thresholdParams());
83
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +020084 auto id = std::make_unique<const std::string>(params.id());
85
Cezary Zwolaka4e67612021-02-18 13:16:16 +010086 return std::make_unique<Trigger>(
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010087 DbusEnvironment::getIoc(), DbusEnvironment::getObjServer(),
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +020088 std::move(id), params.name(), params.triggerActions(),
Szymon Dompke94f71c52021-12-10 07:16:33 +010089 std::make_shared<std::vector<std::string>>(
90 params.reportIds().begin(), params.reportIds().end()),
91 std::vector<std::shared_ptr<interfaces::Threshold>>(thresholdMocks),
92 *triggerManagerMockPtr, storageMock, *triggerFactoryMockPtr,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +010093 SensorMock::makeSensorMocks(params.sensors()));
Cezary Zwolaka4e67612021-02-18 13:16:16 +010094 }
95
96 static interfaces::JsonStorage::FilePath to_file_path(std::string name)
97 {
98 return interfaces::JsonStorage::FilePath(
99 std::to_string(std::hash<std::string>{}(name)));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100100 }
101
102 template <class T>
103 static T getProperty(const std::string& path, const std::string& property)
104 {
Szymon Dompkee28aa532021-10-27 12:33:12 +0200105 return DbusEnvironment::getProperty<T>(path, Trigger::triggerIfaceName,
106 property);
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100107 }
108
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100109 template <class T>
Patrick Williams583ba442025-02-03 14:28:19 -0500110 static boost::system::error_code setProperty(
111 const std::string& path, const std::string& property, const T& newValue)
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100112 {
Szymon Dompkee28aa532021-10-27 12:33:12 +0200113 return DbusEnvironment::setProperty<T>(path, Trigger::triggerIfaceName,
114 property, newValue);
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100115 }
116
Szymon Dompke32305f12022-07-05 15:37:21 +0200117 template <class T>
118 struct ChangePropertyParams
119 {
120 Matcher<T> valueBefore = _;
121 T newValue;
122 Matcher<boost::system::error_code> ec =
123 Eq(boost::system::errc::success);
124 Matcher<T> valueAfter = Eq(newValue);
125 };
126
127 template <class T>
128 static void changeProperty(const std::string& path,
129 const std::string& property,
130 ChangePropertyParams<T> p)
131 {
132 ASSERT_THAT(getProperty<T>(path, property), p.valueBefore);
133 ASSERT_THAT(setProperty<T>(path, property, p.newValue), p.ec);
134 EXPECT_THAT(getProperty<T>(path, property), p.valueAfter);
135 }
136
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100137 boost::system::error_code deleteTrigger(const std::string& path)
138 {
139 std::promise<boost::system::error_code> methodPromise;
140 DbusEnvironment::getBus()->async_method_call(
141 [&methodPromise](boost::system::error_code ec) {
Patrick Williams583ba442025-02-03 14:28:19 -0500142 methodPromise.set_value(ec);
143 },
144 DbusEnvironment::serviceName(), path, Trigger::deleteIfaceName,
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100145 "Delete");
146 return DbusEnvironment::waitForFuture(methodPromise.get_future());
147 }
148};
149
150TEST_F(TestTrigger, checkIfPropertiesAreSet)
151{
Szymon Dompkee28aa532021-10-27 12:33:12 +0200152 EXPECT_THAT(getProperty<std::string>(sut->getPath(), "Name"),
153 Eq(triggerParams.name()));
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100154 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistent"), Eq(true));
Szymon Dompke20013012021-07-23 09:54:20 +0200155 EXPECT_THAT(
156 getProperty<std::vector<std::string>>(sut->getPath(), "TriggerActions"),
Patrick Williamsc7935fa2023-10-20 11:19:30 -0500157 Eq(utils::transform(
158 triggerParams.triggerActions(),
159 [](const auto& action) { return actionToString(action); })));
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100160 EXPECT_THAT((getProperty<SensorsInfo>(sut->getPath(), "Sensors")),
161 Eq(utils::fromLabeledSensorsInfo(triggerParams.sensors())));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100162 EXPECT_THAT(
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200163 getProperty<std::vector<object_path>>(sut->getPath(), "Reports"),
164 Eq(triggerParams.reports()));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100165 EXPECT_THAT(
Szymon Dompke94f71c52021-12-10 07:16:33 +0100166 getProperty<bool>(sut->getPath(), "Discrete"),
167 Eq(isTriggerThresholdDiscrete(triggerParams.thresholdParams())));
Ed Tanous2efa95d2024-10-19 11:36:53 -0700168
169 EXPECT_THAT(getProperty<std::vector<numeric::ThresholdParam>>(
170 sut->getPath(), "NumericThresholds"),
171 Eq(std::get<0>(utils::FromLabeledThresholdParamConversion()(
172 triggerParams.numericThresholdParams()))));
173
174 EXPECT_THAT(getProperty<std::vector<discrete::ThresholdParam>>(
175 sut->getPath(), "DiscreteThresholds"),
176 Eq(std::get<1>(utils::FromLabeledThresholdParamConversion()(
177 triggerParams.discreteThresholdParams()))));
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100178}
179
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100180TEST_F(TestTrigger, checkBasicGetters)
181{
182 EXPECT_THAT(sut->getId(), Eq(triggerParams.id()));
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200183 EXPECT_THAT(sut->getPath(),
184 Eq(utils::constants::triggerDirPath.str + triggerParams.id()));
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100185}
186
Szymon Dompkee28aa532021-10-27 12:33:12 +0200187TEST_F(TestTrigger, setPropertyNameToCorrectValue)
188{
189 std::string name = "custom name 1234 %^#5";
190 EXPECT_THAT(setProperty(sut->getPath(), "Name", name),
191 Eq(boost::system::errc::success));
192 EXPECT_THAT(getProperty<std::string>(sut->getPath(), "Name"), Eq(name));
193}
194
Szymon Dompke94f71c52021-12-10 07:16:33 +0100195TEST_F(TestTrigger, setPropertyReportNames)
196{
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200197 std::vector<object_path> newNames = {
198 utils::constants::reportDirPath / "abc",
199 utils::constants::reportDirPath / "one",
200 utils::constants::reportDirPath / "prefix" / "two"};
201 EXPECT_THAT(setProperty(sut->getPath(), "Reports", newNames),
Szymon Dompke94f71c52021-12-10 07:16:33 +0100202 Eq(boost::system::errc::success));
203 EXPECT_THAT(
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200204 getProperty<std::vector<object_path>>(sut->getPath(), "Reports"),
Szymon Dompke94f71c52021-12-10 07:16:33 +0100205 Eq(newNames));
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100206}
207
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100208TEST_F(TestTrigger, sendsUpdateWhenReportNamesChanges)
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100209{
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200210 std::vector<object_path> newPropertyVal = {
211 utils::constants::reportDirPath / "abc",
212 utils::constants::reportDirPath / "one",
213 utils::constants::reportDirPath / "two"};
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100214
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100215 EXPECT_CALL(triggerPresenceChanged,
216 Call(FieldsAre(messages::Presence::Exist, triggerParams.id(),
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200217 UnorderedElementsAre("abc", "one", "two"))));
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100218
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200219 EXPECT_THAT(setProperty(sut->getPath(), "Reports", newPropertyVal),
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100220 Eq(boost::system::errc::success));
221}
222
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100223TEST_F(TestTrigger, sendsUpdateWhenReportNamesChangesToSameValue)
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100224{
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200225 const std::vector<object_path> newPropertyVal = triggerParams.reports();
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100226
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100227 EXPECT_CALL(
228 triggerPresenceChanged,
229 Call(FieldsAre(messages::Presence::Exist, triggerParams.id(),
230 UnorderedElementsAreArray(triggerParams.reportIds()))));
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100231
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200232 EXPECT_THAT(setProperty(sut->getPath(), "Reports", newPropertyVal),
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100233 Eq(boost::system::errc::success));
234}
235
236TEST_F(TestTrigger,
Michal Orzelb47b7db2024-09-16 10:02:29 +0200237 settingPropertyReportNamesThrowsExceptionWhenDuplicateReportIds)
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100238{
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200239 std::vector<object_path> newPropertyVal{
240 utils::constants::reportDirPath / "report1",
241 utils::constants::reportDirPath / "report2",
242 utils::constants::reportDirPath / "report1"};
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100243
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100244 EXPECT_CALL(triggerPresenceChanged, Call(_)).Times(0);
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100245
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200246 EXPECT_THAT(setProperty(sut->getPath(), "Reports", newPropertyVal),
247 Eq(boost::system::errc::invalid_argument));
248}
249
Michal Orzelb47b7db2024-09-16 10:02:29 +0200250TEST_F(TestTrigger,
251 settingPropertyReportNamesThrowsExceptionWhenReportWithTooManyPrefixes)
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200252{
253 std::vector<object_path> newPropertyVal{
254 object_path("/xyz/openbmc_project/Telemetry/Reports/P1/P2/MyReport")};
255
256 EXPECT_CALL(triggerPresenceChanged, Call(_)).Times(0);
257
258 EXPECT_THAT(setProperty(sut->getPath(), "Reports", newPropertyVal),
259 Eq(boost::system::errc::invalid_argument));
260}
261
Michal Orzelb47b7db2024-09-16 10:02:29 +0200262TEST_F(TestTrigger,
263 settingPropertyReportNamesThrowsExceptionWhenReportWithTooLongPrefix)
Szymon Dompke32305f12022-07-05 15:37:21 +0200264{
265 std::vector<object_path> newPropertyVal{
266 object_path("/xyz/openbmc_project/Telemetry/Reports/" +
267 utils::string_utils::getTooLongPrefix() + "/MyReport")};
268
269 EXPECT_CALL(triggerPresenceChanged, Call(_)).Times(0);
270
271 EXPECT_THAT(setProperty(sut->getPath(), "Reports", newPropertyVal),
272 Eq(boost::system::errc::invalid_argument));
273}
274
Michal Orzelb47b7db2024-09-16 10:02:29 +0200275TEST_F(TestTrigger,
276 settingPropertyReportNamesThrowsExceptionWhenReportWithTooLongId)
Szymon Dompke32305f12022-07-05 15:37:21 +0200277{
278 std::vector<object_path> newPropertyVal{
279 object_path("/xyz/openbmc_project/Telemetry/Reports/Prefix/" +
280 utils::string_utils::getTooLongId())};
281
282 EXPECT_CALL(triggerPresenceChanged, Call(_)).Times(0);
283
284 EXPECT_THAT(setProperty(sut->getPath(), "Reports", newPropertyVal),
285 Eq(boost::system::errc::invalid_argument));
286}
287
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200288TEST_F(TestTrigger,
Michal Orzelb47b7db2024-09-16 10:02:29 +0200289 settingPropertyReportNamesThrowsExceptionWhenReportWithBadPath)
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200290{
291 std::vector<object_path> newPropertyVal{
292 object_path("/xyz/openbmc_project/Telemetry/NotReports/MyReport")};
293
294 EXPECT_CALL(triggerPresenceChanged, Call(_)).Times(0);
295
296 EXPECT_THAT(setProperty(sut->getPath(), "Reports", newPropertyVal),
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100297 Eq(boost::system::errc::invalid_argument));
Szymon Dompke94f71c52021-12-10 07:16:33 +0100298}
299
300TEST_F(TestTrigger, setPropertySensors)
301{
302 EXPECT_CALL(*triggerFactoryMockPtr, updateSensors(_, _));
303 for (const auto& threshold : thresholdMocks)
304 {
305 auto thresholdMockPtr =
306 std::dynamic_pointer_cast<NiceMock<ThresholdMock>>(threshold);
307 EXPECT_CALL(*thresholdMockPtr, updateSensors(_));
308 }
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200309 SensorsInfo newSensors(
310 {std::make_pair(object_path("/abc/def"), "metadata")});
Szymon Dompke94f71c52021-12-10 07:16:33 +0100311 EXPECT_THAT(setProperty(sut->getPath(), "Sensors", newSensors),
312 Eq(boost::system::errc::success));
313}
314
315TEST_F(TestTrigger, setPropertyThresholds)
316{
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200317 EXPECT_CALL(*triggerFactoryMockPtr, updateThresholds(_, _, _, _, _, _));
Szymon Dompke94f71c52021-12-10 07:16:33 +0100318 TriggerThresholdParams newThresholds =
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +0000319 std::vector<discrete::ThresholdParam>({std::make_tuple(
320 "discrete threshold", utils::enumToString(discrete::Severity::ok),
321 10, "12.3")});
Szymon Dompke94f71c52021-12-10 07:16:33 +0100322 EXPECT_THAT(setProperty(sut->getPath(), "Thresholds", newThresholds),
323 Eq(boost::system::errc::success));
324}
325
Szymon Dompke32305f12022-07-05 15:37:21 +0200326TEST_F(TestTrigger, setThresholdParamsWithTooLongDiscreteName)
327{
328 const TriggerThresholdParams currentValue =
329 std::visit(utils::FromLabeledThresholdParamConversion(),
330 triggerParams.thresholdParams());
331
332 TriggerThresholdParams newThresholds =
333 std::vector<discrete::ThresholdParam>({std::make_tuple(
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +0000334 utils::string_utils::getTooLongName(),
335 utils::enumToString(discrete::Severity::ok), 10, "12.3")});
Szymon Dompke32305f12022-07-05 15:37:21 +0200336
337 changeProperty<TriggerThresholdParams>(
338 sut->getPath(), "Thresholds",
339 {.valueBefore = Eq(currentValue),
340 .newValue = newThresholds,
341 .ec = Eq(boost::system::errc::invalid_argument),
342 .valueAfter = Eq(currentValue)});
343}
344
345TEST_F(TestTrigger, setNameTooLong)
346{
347 std::string currentValue = TriggerParams().name();
348
349 changeProperty<std::string>(
350 sut->getPath(), "Name",
351 {.valueBefore = Eq(currentValue),
352 .newValue = utils::string_utils::getTooLongName(),
353 .ec = Eq(boost::system::errc::invalid_argument),
354 .valueAfter = Eq(currentValue)});
355}
356
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100357TEST_F(TestTrigger, checkIfNumericCoversionsAreGood)
358{
359 const auto& labeledParamsBase =
360 std::get<std::vector<numeric::LabeledThresholdParam>>(
361 triggerParams.thresholdParams());
362 const auto paramsToCheck =
363 std::visit(utils::FromLabeledThresholdParamConversion(),
364 triggerParams.thresholdParams());
365 const auto labeledParamsToCheck =
366 std::get<std::vector<numeric::LabeledThresholdParam>>(std::visit(
367 utils::ToLabeledThresholdParamConversion(), paramsToCheck));
368
369 for (const auto& [tocheck, base] :
370 boost::combine(labeledParamsToCheck, labeledParamsBase))
371 {
372 EXPECT_THAT(tocheck.at_label<utils::tstring::Type>(),
373 Eq(base.at_label<utils::tstring::Type>()));
374 EXPECT_THAT(tocheck.at_label<utils::tstring::Direction>(),
375 Eq(base.at_label<utils::tstring::Direction>()));
376 EXPECT_THAT(tocheck.at_label<utils::tstring::DwellTime>(),
377 Eq(base.at_label<utils::tstring::DwellTime>()));
378 EXPECT_THAT(tocheck.at_label<utils::tstring::ThresholdValue>(),
379 Eq(base.at_label<utils::tstring::ThresholdValue>()));
380 }
381}
382
383TEST_F(TestTrigger, checkIfDiscreteCoversionsAreGood)
384{
385 const auto& labeledParamsBase =
386 std::get<std::vector<discrete::LabeledThresholdParam>>(
387 triggerDiscreteParams.thresholdParams());
388 const auto paramsToCheck =
389 std::visit(utils::FromLabeledThresholdParamConversion(),
390 triggerDiscreteParams.thresholdParams());
391 const auto labeledParamsToCheck =
392 std::get<std::vector<discrete::LabeledThresholdParam>>(std::visit(
393 utils::ToLabeledThresholdParamConversion(), paramsToCheck));
394
395 for (const auto& [tocheck, base] :
396 boost::combine(labeledParamsToCheck, labeledParamsBase))
397 {
398 EXPECT_THAT(tocheck.at_label<utils::tstring::UserId>(),
399 Eq(base.at_label<utils::tstring::UserId>()));
400 EXPECT_THAT(tocheck.at_label<utils::tstring::Severity>(),
401 Eq(base.at_label<utils::tstring::Severity>()));
402 EXPECT_THAT(tocheck.at_label<utils::tstring::DwellTime>(),
403 Eq(base.at_label<utils::tstring::DwellTime>()));
404 EXPECT_THAT(tocheck.at_label<utils::tstring::ThresholdValue>(),
405 Eq(base.at_label<utils::tstring::ThresholdValue>()));
406 }
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100407}
408
409TEST_F(TestTrigger, deleteTrigger)
410{
Szymon Dompkee28aa532021-10-27 12:33:12 +0200411 EXPECT_CALL(storageMock, remove(to_file_path(sut->getId())));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100412 EXPECT_CALL(*triggerManagerMockPtr, removeTrigger(sut.get()));
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100413
414 auto ec = deleteTrigger(sut->getPath());
415 EXPECT_THAT(ec, Eq(boost::system::errc::success));
416}
417
418TEST_F(TestTrigger, sendUpdateWhenTriggerIsDeleted)
419{
420 EXPECT_CALL(triggerPresenceChanged,
421 Call(FieldsAre(messages::Presence::Removed, triggerParams.id(),
422 UnorderedElementsAre())));
423
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100424 auto ec = deleteTrigger(sut->getPath());
425 EXPECT_THAT(ec, Eq(boost::system::errc::success));
426}
427
428TEST_F(TestTrigger, deletingNonExistingTriggerReturnInvalidRequestDescriptor)
429{
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200430 auto ec =
431 deleteTrigger(utils::constants::triggerDirPath.str + "NonExisting"s);
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100432 EXPECT_THAT(ec.value(), Eq(EBADR));
433}
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100434
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100435TEST_F(TestTrigger, settingPersistencyToFalseRemovesTriggerFromStorage)
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100436{
Szymon Dompkee28aa532021-10-27 12:33:12 +0200437 EXPECT_CALL(storageMock, remove(to_file_path(sut->getId())));
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100438
439 bool persistent = false;
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100440 EXPECT_THAT(setProperty(sut->getPath(), "Persistent", persistent),
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100441 Eq(boost::system::errc::success));
442 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistent"),
443 Eq(persistent));
444}
445
Michal Orzel6f56d262025-07-25 11:19:13 +0200446class TestOnChangeTrigger : public TestTrigger
447{
448 public:
449 TriggerParams onChangeTriggerParams =
450 TriggerParams()
451 .id("DiscreteOnChangeTrigger")
452 .name("My Discrete On Change Trigger")
453 .thresholdParams(std::vector<numeric::LabeledThresholdParam>{});
454
455 void SetUp() override
456 {
457 sut = makeTrigger(onChangeTriggerParams);
458 }
459};
460
461TEST_F(TestOnChangeTrigger, isDiscrete)
462{
463 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Discrete"), Eq(true));
464}
465
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100466class TestTriggerInitialization : public TestTrigger
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100467{
468 public:
Patrick Williams3a1c2972023-05-10 07:51:04 -0500469 void SetUp() override {}
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100470
471 nlohmann::json storedConfiguration;
472};
473
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100474TEST_F(TestTriggerInitialization,
475 exceptionDuringTriggerStoreDisablesPersistency)
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100476{
477 EXPECT_CALL(storageMock, store(_, _))
478 .WillOnce(Throw(std::runtime_error("Generic error!")));
479
480 sut = makeTrigger(triggerParams);
481
482 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistent"), Eq(false));
483}
484
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100485TEST_F(TestTriggerInitialization, creatingTriggerThrowsExceptionWhenIdIsInvalid)
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100486{
487 EXPECT_CALL(storageMock, store(_, _)).Times(0);
488
Szymon Dompkee28aa532021-10-27 12:33:12 +0200489 EXPECT_THROW(makeTrigger(triggerParams.id("inv?lidId")),
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100490 sdbusplus::exception::SdBusError);
491}
492
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100493TEST_F(TestTriggerInitialization, creatingTriggerUpdatesTriggersIdsInReports)
494{
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100495 EXPECT_CALL(
496 triggerPresenceChanged,
497 Call(FieldsAre(messages::Presence::Exist, triggerParams.id(),
498 UnorderedElementsAreArray(triggerParams.reportIds()))));
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100499
500 sut = makeTrigger(triggerParams);
501}
502
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100503class TestTriggerStore : public TestTrigger
504{
505 public:
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100506 nlohmann::json storedConfiguration;
507 nlohmann::json storedDiscreteConfiguration;
508 std::unique_ptr<Trigger> sutDiscrete;
509
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100510 void SetUp() override
511 {
512 ON_CALL(storageMock, store(_, _))
513 .WillByDefault(SaveArg<1>(&storedConfiguration));
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100514 sut = makeTrigger(triggerParams);
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100515
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100516 ON_CALL(storageMock, store(_, _))
517 .WillByDefault(SaveArg<1>(&storedDiscreteConfiguration));
518 sutDiscrete = makeTrigger(triggerDiscreteParams);
519 }
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100520};
521
522TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerVersion)
523{
524 ASSERT_THAT(storedConfiguration.at("Version"), Eq(expectedTriggerVersion));
525}
526
Szymon Dompkee28aa532021-10-27 12:33:12 +0200527TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerId)
528{
529 ASSERT_THAT(storedConfiguration.at("Id"), Eq(triggerParams.id()));
530}
531
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100532TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerName)
533{
534 ASSERT_THAT(storedConfiguration.at("Name"), Eq(triggerParams.name()));
535}
536
Szymon Dompke20013012021-07-23 09:54:20 +0200537TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerTriggerActions)
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100538{
Szymon Dompke20013012021-07-23 09:54:20 +0200539 ASSERT_THAT(storedConfiguration.at("TriggerActions"),
Szymon Dompke94f71c52021-12-10 07:16:33 +0100540 Eq(utils::transform(triggerParams.triggerActions(),
541 [](const auto& action) {
Patrick Williams583ba442025-02-03 14:28:19 -0500542 return actionToString(action);
543 })));
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100544}
545
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100546TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerReportIds)
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100547{
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100548 ASSERT_THAT(storedConfiguration.at("ReportIds"),
549 Eq(triggerParams.reportIds()));
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100550}
551
552TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerSensors)
553{
554 nlohmann::json expectedItem;
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100555 expectedItem["service"] = "service1";
Szymon Dompke94f71c52021-12-10 07:16:33 +0100556 expectedItem["path"] = "/xyz/openbmc_project/sensors/temperature/BMC_Temp";
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100557 expectedItem["metadata"] = "metadata1";
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100558
559 ASSERT_THAT(storedConfiguration.at("Sensors"), ElementsAre(expectedItem));
560}
561
562TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerThresholdParams)
563{
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100564 nlohmann::json expectedItem0;
565 expectedItem0["type"] = 0;
566 expectedItem0["dwellTime"] = 10;
567 expectedItem0["direction"] = 1;
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100568 expectedItem0["thresholdValue"] = 0.5;
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100569
570 nlohmann::json expectedItem1;
571 expectedItem1["type"] = 3;
572 expectedItem1["dwellTime"] = 10;
573 expectedItem1["direction"] = 2;
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100574 expectedItem1["thresholdValue"] = 90.2;
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100575
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100576 ASSERT_THAT(storedConfiguration.at("ThresholdParamsDiscriminator"), Eq(0));
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100577 ASSERT_THAT(storedConfiguration.at("ThresholdParams"),
578 ElementsAre(expectedItem0, expectedItem1));
579}
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100580
581TEST_F(TestTriggerStore,
582 settingPersistencyToTrueStoresDiscreteTriggerThresholdParams)
583{
584 nlohmann::json expectedItem0;
585 expectedItem0["userId"] = "userId";
586 expectedItem0["severity"] = discrete::Severity::warning;
587 expectedItem0["dwellTime"] = 10;
Szymon Dompke9f346792021-07-14 21:07:11 +0200588 expectedItem0["thresholdValue"] = "15.2";
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100589
590 nlohmann::json expectedItem1;
591 expectedItem1["userId"] = "userId_2";
592 expectedItem1["severity"] = discrete::Severity::critical;
593 expectedItem1["dwellTime"] = 5;
Szymon Dompke9f346792021-07-14 21:07:11 +0200594 expectedItem1["thresholdValue"] = "32.7";
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100595
596 ASSERT_THAT(storedDiscreteConfiguration.at("ThresholdParamsDiscriminator"),
597 Eq(1));
598 ASSERT_THAT(storedDiscreteConfiguration.at("ThresholdParams"),
599 ElementsAre(expectedItem0, expectedItem1));
600}