1 #include "dbus_environment.hpp"
2 #include "helpers.hpp"
3 #include "messages/collect_trigger_id.hpp"
4 #include "messages/trigger_presence_changed_ind.hpp"
5 #include "mocks/json_storage_mock.hpp"
6 #include "mocks/report_manager_mock.hpp"
7 #include "mocks/sensor_mock.hpp"
8 #include "mocks/threshold_mock.hpp"
9 #include "mocks/trigger_factory_mock.hpp"
10 #include "mocks/trigger_manager_mock.hpp"
11 #include "params/trigger_params.hpp"
12 #include "trigger.hpp"
13 #include "trigger_manager.hpp"
14 #include "utils/conversion_trigger.hpp"
15 #include "utils/dbus_path_utils.hpp"
16 #include "utils/messanger.hpp"
17 #include "utils/string_utils.hpp"
18 #include "utils/transform.hpp"
19 #include "utils/tstring.hpp"
20
21 #include <boost/range/combine.hpp>
22 #include <xyz/openbmc_project/Object/Delete/common.hpp>
23 #include <xyz/openbmc_project/Telemetry/Trigger/common.hpp>
24
25 using TelemetryTrigger =
26 sdbusplus::common::xyz::openbmc_project::telemetry::Trigger;
27 using ObjectDelete = sdbusplus::common::xyz::openbmc_project::object::Delete;
28
29 using namespace testing;
30 using namespace std::literals::string_literals;
31 using sdbusplus::message::object_path;
32
33 static constexpr size_t expectedTriggerVersion = 2;
34
35 class TestTrigger : public Test
36 {
37 public:
38 TriggerParams triggerParams;
39 TriggerParams triggerDiscreteParams =
40 TriggerParams()
41 .id("DiscreteTrigger")
42 .name("My Discrete Trigger")
43 .thresholdParams(std::vector<discrete::LabeledThresholdParam>{
44 discrete::LabeledThresholdParam{
45 "userId", discrete::Severity::warning,
46 Milliseconds(10).count(), "15.2"},
47 discrete::LabeledThresholdParam{
48 "userId_2", discrete::Severity::critical,
49 Milliseconds(5).count(), "32.7"},
50 });
51
52 std::unique_ptr<ReportManagerMock> reportManagerMockPtr =
53 std::make_unique<NiceMock<ReportManagerMock>>();
54 std::unique_ptr<TriggerManagerMock> triggerManagerMockPtr =
55 std::make_unique<NiceMock<TriggerManagerMock>>();
56 std::unique_ptr<TriggerFactoryMock> triggerFactoryMockPtr =
57 std::make_unique<NiceMock<TriggerFactoryMock>>();
58 testing::NiceMock<StorageMock> storageMock;
59 NiceMock<MockFunction<void(const messages::TriggerPresenceChangedInd)>>
60 triggerPresenceChanged;
61 std::vector<std::shared_ptr<interfaces::Threshold>> thresholdMocks;
62 utils::Messanger messanger;
63 std::unique_ptr<Trigger> sut;
64
TestTrigger()65 TestTrigger() : messanger(DbusEnvironment::getIoc())
66 {
67 messanger.on_receive<messages::TriggerPresenceChangedInd>(
68 [this](const auto& msg) { triggerPresenceChanged.Call(msg); });
69 }
70
SetUp()71 void SetUp() override
72 {
73 sut = makeTrigger(triggerParams);
74 }
75
convertToLabeledSensor(const SensorsInfo & sensorsInfo)76 static std::vector<LabeledSensorInfo> convertToLabeledSensor(
77 const SensorsInfo& sensorsInfo)
78 {
79 return utils::transform(sensorsInfo, [](const auto& sensorInfo) {
80 const auto& [sensorPath, sensorMetadata] = sensorInfo;
81 return LabeledSensorInfo("service1", sensorPath, sensorMetadata);
82 });
83 }
84
makeTrigger(const TriggerParams & params)85 std::unique_ptr<Trigger> makeTrigger(const TriggerParams& params)
86 {
87 thresholdMocks =
88 ThresholdMock::makeThresholds(params.thresholdParams());
89
90 auto id = std::make_unique<const std::string>(params.id());
91
92 return std::make_unique<Trigger>(
93 DbusEnvironment::getIoc(), DbusEnvironment::getObjServer(),
94 std::move(id), params.name(), params.triggerActions(),
95 std::make_shared<std::vector<std::string>>(
96 params.reportIds().begin(), params.reportIds().end()),
97 std::vector<std::shared_ptr<interfaces::Threshold>>(thresholdMocks),
98 *triggerManagerMockPtr, storageMock, *triggerFactoryMockPtr,
99 SensorMock::makeSensorMocks(params.sensors()));
100 }
101
to_file_path(std::string name)102 static interfaces::JsonStorage::FilePath to_file_path(std::string name)
103 {
104 return interfaces::JsonStorage::FilePath(
105 std::to_string(std::hash<std::string>{}(name)));
106 }
107
108 template <class T>
getProperty(const std::string & path,const std::string & property)109 static T getProperty(const std::string& path, const std::string& property)
110 {
111 return DbusEnvironment::getProperty<T>(
112 path, TelemetryTrigger::interface, property);
113 }
114
115 template <class T>
setProperty(const std::string & path,const std::string & property,const T & newValue)116 static boost::system::error_code setProperty(
117 const std::string& path, const std::string& property, const T& newValue)
118 {
119 return DbusEnvironment::setProperty<T>(
120 path, TelemetryTrigger::interface, property, newValue);
121 }
122
123 template <class T>
124 struct ChangePropertyParams
125 {
126 Matcher<T> valueBefore = _;
127 T newValue;
128 Matcher<boost::system::error_code> ec =
129 Eq(boost::system::errc::success);
130 Matcher<T> valueAfter = Eq(newValue);
131 };
132
133 template <class T>
changeProperty(const std::string & path,const std::string & property,ChangePropertyParams<T> p)134 static void changeProperty(const std::string& path,
135 const std::string& property,
136 ChangePropertyParams<T> p)
137 {
138 ASSERT_THAT(getProperty<T>(path, property), p.valueBefore);
139 ASSERT_THAT(setProperty<T>(path, property, p.newValue), p.ec);
140 EXPECT_THAT(getProperty<T>(path, property), p.valueAfter);
141 }
142
deleteTrigger(const std::string & path)143 boost::system::error_code deleteTrigger(const std::string& path)
144 {
145 std::promise<boost::system::error_code> methodPromise;
146 DbusEnvironment::getBus()->async_method_call(
147 [&methodPromise](boost::system::error_code ec) {
148 methodPromise.set_value(ec);
149 },
150 DbusEnvironment::serviceName(), path, ObjectDelete::interface,
151 ObjectDelete::method_names::delete_);
152 return DbusEnvironment::waitForFuture(methodPromise.get_future());
153 }
154 };
155
TEST_F(TestTrigger,checkIfPropertiesAreSet)156 TEST_F(TestTrigger, checkIfPropertiesAreSet)
157 {
158 EXPECT_THAT(getProperty<std::string>(
159 sut->getPath(), TelemetryTrigger::property_names::name),
160 Eq(triggerParams.name()));
161 EXPECT_THAT(getProperty<bool>(sut->getPath(),
162 TelemetryTrigger::property_names::persistent),
163 Eq(true));
164 EXPECT_THAT(
165 getProperty<std::vector<std::string>>(
166 sut->getPath(), TelemetryTrigger::property_names::trigger_actions),
167 Eq(utils::transform(
168 triggerParams.triggerActions(),
169 [](const auto& action) { return actionToString(action); })));
170 EXPECT_THAT((getProperty<SensorsInfo>(
171 sut->getPath(), TelemetryTrigger::property_names::sensors)),
172 Eq(utils::fromLabeledSensorsInfo(triggerParams.sensors())));
173 EXPECT_THAT(getProperty<std::vector<object_path>>(
174 sut->getPath(), TelemetryTrigger::property_names::reports),
175 Eq(triggerParams.reports()));
176 EXPECT_THAT(
177 getProperty<bool>(sut->getPath(),
178 TelemetryTrigger::property_names::discrete),
179 Eq(isTriggerThresholdDiscrete(triggerParams.thresholdParams())));
180
181 EXPECT_THAT(getProperty<std::vector<numeric::ThresholdParam>>(
182 sut->getPath(),
183 TelemetryTrigger::property_names::numeric_thresholds),
184 Eq(std::get<0>(utils::FromLabeledThresholdParamConversion()(
185 triggerParams.numericThresholdParams()))));
186
187 EXPECT_THAT(getProperty<std::vector<discrete::ThresholdParam>>(
188 sut->getPath(),
189 TelemetryTrigger::property_names::discrete_thresholds),
190 Eq(std::get<1>(utils::FromLabeledThresholdParamConversion()(
191 triggerParams.discreteThresholdParams()))));
192 }
193
TEST_F(TestTrigger,checkBasicGetters)194 TEST_F(TestTrigger, checkBasicGetters)
195 {
196 EXPECT_THAT(sut->getId(), Eq(triggerParams.id()));
197 EXPECT_THAT(sut->getPath(),
198 Eq(utils::constants::triggerDirPath.str + triggerParams.id()));
199 }
200
TEST_F(TestTrigger,setPropertyNameToCorrectValue)201 TEST_F(TestTrigger, setPropertyNameToCorrectValue)
202 {
203 std::string name = "custom name 1234 %^#5";
204 EXPECT_THAT(setProperty(sut->getPath(),
205 TelemetryTrigger::property_names::name, name),
206 Eq(boost::system::errc::success));
207 EXPECT_THAT(getProperty<std::string>(
208 sut->getPath(), TelemetryTrigger::property_names::name),
209 Eq(name));
210 }
211
TEST_F(TestTrigger,setPropertyReportNames)212 TEST_F(TestTrigger, setPropertyReportNames)
213 {
214 std::vector<object_path> newNames = {
215 utils::constants::reportDirPath / "abc",
216 utils::constants::reportDirPath / "one",
217 utils::constants::reportDirPath / "prefix" / "two"};
218 EXPECT_THAT(setProperty(sut->getPath(),
219 TelemetryTrigger::property_names::reports,
220 newNames),
221 Eq(boost::system::errc::success));
222 EXPECT_THAT(getProperty<std::vector<object_path>>(
223 sut->getPath(), TelemetryTrigger::property_names::reports),
224 Eq(newNames));
225 }
226
TEST_F(TestTrigger,sendsUpdateWhenReportNamesChanges)227 TEST_F(TestTrigger, sendsUpdateWhenReportNamesChanges)
228 {
229 std::vector<object_path> newPropertyVal = {
230 utils::constants::reportDirPath / "abc",
231 utils::constants::reportDirPath / "one",
232 utils::constants::reportDirPath / "two"};
233
234 EXPECT_CALL(triggerPresenceChanged,
235 Call(FieldsAre(messages::Presence::Exist, triggerParams.id(),
236 UnorderedElementsAre("abc", "one", "two"))));
237
238 EXPECT_THAT(setProperty(sut->getPath(),
239 TelemetryTrigger::property_names::reports,
240 newPropertyVal),
241 Eq(boost::system::errc::success));
242 }
243
TEST_F(TestTrigger,sendsUpdateWhenReportNamesChangesToSameValue)244 TEST_F(TestTrigger, sendsUpdateWhenReportNamesChangesToSameValue)
245 {
246 const std::vector<object_path> newPropertyVal = triggerParams.reports();
247
248 EXPECT_CALL(
249 triggerPresenceChanged,
250 Call(FieldsAre(messages::Presence::Exist, triggerParams.id(),
251 UnorderedElementsAreArray(triggerParams.reportIds()))));
252
253 EXPECT_THAT(setProperty(sut->getPath(),
254 TelemetryTrigger::property_names::reports,
255 newPropertyVal),
256 Eq(boost::system::errc::success));
257 }
258
TEST_F(TestTrigger,settingPropertyReportNamesThrowsExceptionWhenDuplicateReportIds)259 TEST_F(TestTrigger,
260 settingPropertyReportNamesThrowsExceptionWhenDuplicateReportIds)
261 {
262 std::vector<object_path> newPropertyVal{
263 utils::constants::reportDirPath / "report1",
264 utils::constants::reportDirPath / "report2",
265 utils::constants::reportDirPath / "report1"};
266
267 EXPECT_CALL(triggerPresenceChanged, Call(_)).Times(0);
268
269 EXPECT_THAT(setProperty(sut->getPath(),
270 TelemetryTrigger::property_names::reports,
271 newPropertyVal),
272 Eq(boost::system::errc::invalid_argument));
273 }
274
TEST_F(TestTrigger,settingPropertyReportNamesThrowsExceptionWhenReportWithTooManyPrefixes)275 TEST_F(TestTrigger,
276 settingPropertyReportNamesThrowsExceptionWhenReportWithTooManyPrefixes)
277 {
278 std::vector<object_path> newPropertyVal{
279 object_path("/xyz/openbmc_project/Telemetry/Reports/P1/P2/MyReport")};
280
281 EXPECT_CALL(triggerPresenceChanged, Call(_)).Times(0);
282
283 EXPECT_THAT(setProperty(sut->getPath(),
284 TelemetryTrigger::property_names::reports,
285 newPropertyVal),
286 Eq(boost::system::errc::invalid_argument));
287 }
288
TEST_F(TestTrigger,settingPropertyReportNamesThrowsExceptionWhenReportWithTooLongPrefix)289 TEST_F(TestTrigger,
290 settingPropertyReportNamesThrowsExceptionWhenReportWithTooLongPrefix)
291 {
292 std::vector<object_path> newPropertyVal{
293 object_path("/xyz/openbmc_project/Telemetry/Reports/" +
294 utils::string_utils::getTooLongPrefix() + "/MyReport")};
295
296 EXPECT_CALL(triggerPresenceChanged, Call(_)).Times(0);
297
298 EXPECT_THAT(setProperty(sut->getPath(),
299 TelemetryTrigger::property_names::reports,
300 newPropertyVal),
301 Eq(boost::system::errc::invalid_argument));
302 }
303
TEST_F(TestTrigger,settingPropertyReportNamesThrowsExceptionWhenReportWithTooLongId)304 TEST_F(TestTrigger,
305 settingPropertyReportNamesThrowsExceptionWhenReportWithTooLongId)
306 {
307 std::vector<object_path> newPropertyVal{
308 object_path("/xyz/openbmc_project/Telemetry/Reports/Prefix/" +
309 utils::string_utils::getTooLongId())};
310
311 EXPECT_CALL(triggerPresenceChanged, Call(_)).Times(0);
312
313 EXPECT_THAT(setProperty(sut->getPath(),
314 TelemetryTrigger::property_names::reports,
315 newPropertyVal),
316 Eq(boost::system::errc::invalid_argument));
317 }
318
TEST_F(TestTrigger,settingPropertyReportNamesThrowsExceptionWhenReportWithBadPath)319 TEST_F(TestTrigger,
320 settingPropertyReportNamesThrowsExceptionWhenReportWithBadPath)
321 {
322 std::vector<object_path> newPropertyVal{
323 object_path("/xyz/openbmc_project/Telemetry/NotReports/MyReport")};
324
325 EXPECT_CALL(triggerPresenceChanged, Call(_)).Times(0);
326
327 EXPECT_THAT(setProperty(sut->getPath(),
328 TelemetryTrigger::property_names::reports,
329 newPropertyVal),
330 Eq(boost::system::errc::invalid_argument));
331 }
332
TEST_F(TestTrigger,setPropertySensors)333 TEST_F(TestTrigger, setPropertySensors)
334 {
335 EXPECT_CALL(*triggerFactoryMockPtr, updateSensors(_, _));
336 for (const auto& threshold : thresholdMocks)
337 {
338 auto thresholdMockPtr =
339 std::dynamic_pointer_cast<NiceMock<ThresholdMock>>(threshold);
340 EXPECT_CALL(*thresholdMockPtr, updateSensors(_));
341 }
342 SensorsInfo newSensors(
343 {std::make_pair(object_path("/abc/def"), "metadata")});
344 EXPECT_THAT(setProperty(sut->getPath(),
345 TelemetryTrigger::property_names::sensors,
346 newSensors),
347 Eq(boost::system::errc::success));
348 }
349
TEST_F(TestTrigger,setPropertyNumericThresholds)350 TEST_F(TestTrigger, setPropertyNumericThresholds)
351 {
352 EXPECT_CALL(*triggerFactoryMockPtr, updateThresholds(_, _, _, _, _, _));
353 auto newThresholds = std::vector<numeric::ThresholdParam>({std::make_tuple(
354 numeric::typeToString(numeric::Type::upperWarning), 10,
355 numeric::directionToString(numeric::Direction::increasing), 12.3)});
356 EXPECT_THAT(
357 setProperty(sut->getPath(),
358 TelemetryTrigger::property_names::numeric_thresholds,
359 newThresholds),
360 Eq(boost::system::errc::success));
361 }
362
TEST_F(TestTrigger,setPropertyDiscreteThresholds)363 TEST_F(TestTrigger, setPropertyDiscreteThresholds)
364 {
365 EXPECT_CALL(*triggerFactoryMockPtr, updateThresholds(_, _, _, _, _, _));
366 auto newThresholds = std::vector<discrete::ThresholdParam>({std::make_tuple(
367 "discrete threshold", utils::enumToString(discrete::Severity::ok), 10,
368 "12.3")});
369 EXPECT_THAT(
370 setProperty(sut->getPath(),
371 TelemetryTrigger::property_names::discrete_thresholds,
372 newThresholds),
373 Eq(boost::system::errc::success));
374 }
375
TEST_F(TestTrigger,setThresholdParamsWithTooLongDiscreteName)376 TEST_F(TestTrigger, setThresholdParamsWithTooLongDiscreteName)
377 {
378 const std::vector<discrete::ThresholdParam> currentValue =
379 std::get<1>(utils::FromLabeledThresholdParamConversion()(
380 triggerParams.discreteThresholdParams()));
381
382 auto newThresholds = std::vector<discrete::ThresholdParam>({std::make_tuple(
383 utils::string_utils::getTooLongName(),
384 utils::enumToString(discrete::Severity::ok), 10, "12.3")});
385
386 changeProperty<std::vector<discrete::ThresholdParam>>(
387 sut->getPath(), TelemetryTrigger::property_names::discrete_thresholds,
388 {.valueBefore = Eq(currentValue),
389 .newValue = newThresholds,
390 .ec = Eq(boost::system::errc::invalid_argument),
391 .valueAfter = Eq(currentValue)});
392 }
393
TEST_F(TestTrigger,setNameTooLong)394 TEST_F(TestTrigger, setNameTooLong)
395 {
396 std::string currentValue = TriggerParams().name();
397
398 changeProperty<std::string>(
399 sut->getPath(), TelemetryTrigger::property_names::name,
400 {.valueBefore = Eq(currentValue),
401 .newValue = utils::string_utils::getTooLongName(),
402 .ec = Eq(boost::system::errc::invalid_argument),
403 .valueAfter = Eq(currentValue)});
404 }
405
TEST_F(TestTrigger,checkIfNumericCoversionsAreGood)406 TEST_F(TestTrigger, checkIfNumericCoversionsAreGood)
407 {
408 const auto& labeledParamsBase =
409 std::get<std::vector<numeric::LabeledThresholdParam>>(
410 triggerParams.thresholdParams());
411 const auto paramsToCheck =
412 std::visit(utils::FromLabeledThresholdParamConversion(),
413 triggerParams.thresholdParams());
414 const auto labeledParamsToCheck =
415 std::get<std::vector<numeric::LabeledThresholdParam>>(std::visit(
416 utils::ToLabeledThresholdParamConversion(), paramsToCheck));
417
418 for (const auto& [tocheck, base] :
419 boost::combine(labeledParamsToCheck, labeledParamsBase))
420 {
421 EXPECT_THAT(tocheck.at_label<utils::tstring::Type>(),
422 Eq(base.at_label<utils::tstring::Type>()));
423 EXPECT_THAT(tocheck.at_label<utils::tstring::Direction>(),
424 Eq(base.at_label<utils::tstring::Direction>()));
425 EXPECT_THAT(tocheck.at_label<utils::tstring::DwellTime>(),
426 Eq(base.at_label<utils::tstring::DwellTime>()));
427 EXPECT_THAT(tocheck.at_label<utils::tstring::ThresholdValue>(),
428 Eq(base.at_label<utils::tstring::ThresholdValue>()));
429 }
430 }
431
TEST_F(TestTrigger,checkIfDiscreteCoversionsAreGood)432 TEST_F(TestTrigger, checkIfDiscreteCoversionsAreGood)
433 {
434 const auto& labeledParamsBase =
435 std::get<std::vector<discrete::LabeledThresholdParam>>(
436 triggerDiscreteParams.thresholdParams());
437 const auto paramsToCheck =
438 std::visit(utils::FromLabeledThresholdParamConversion(),
439 triggerDiscreteParams.thresholdParams());
440 const auto labeledParamsToCheck =
441 std::get<std::vector<discrete::LabeledThresholdParam>>(std::visit(
442 utils::ToLabeledThresholdParamConversion(), paramsToCheck));
443
444 for (const auto& [tocheck, base] :
445 boost::combine(labeledParamsToCheck, labeledParamsBase))
446 {
447 EXPECT_THAT(tocheck.at_label<utils::tstring::UserId>(),
448 Eq(base.at_label<utils::tstring::UserId>()));
449 EXPECT_THAT(tocheck.at_label<utils::tstring::Severity>(),
450 Eq(base.at_label<utils::tstring::Severity>()));
451 EXPECT_THAT(tocheck.at_label<utils::tstring::DwellTime>(),
452 Eq(base.at_label<utils::tstring::DwellTime>()));
453 EXPECT_THAT(tocheck.at_label<utils::tstring::ThresholdValue>(),
454 Eq(base.at_label<utils::tstring::ThresholdValue>()));
455 }
456 }
457
TEST_F(TestTrigger,deleteTrigger)458 TEST_F(TestTrigger, deleteTrigger)
459 {
460 EXPECT_CALL(storageMock, remove(to_file_path(sut->getId())));
461 EXPECT_CALL(*triggerManagerMockPtr, removeTrigger(sut.get()));
462
463 auto ec = deleteTrigger(sut->getPath());
464 EXPECT_THAT(ec, Eq(boost::system::errc::success));
465 }
466
TEST_F(TestTrigger,sendUpdateWhenTriggerIsDeleted)467 TEST_F(TestTrigger, sendUpdateWhenTriggerIsDeleted)
468 {
469 EXPECT_CALL(triggerPresenceChanged,
470 Call(FieldsAre(messages::Presence::Removed, triggerParams.id(),
471 UnorderedElementsAre())));
472
473 auto ec = deleteTrigger(sut->getPath());
474 EXPECT_THAT(ec, Eq(boost::system::errc::success));
475 }
476
TEST_F(TestTrigger,deletingNonExistingTriggerReturnInvalidRequestDescriptor)477 TEST_F(TestTrigger, deletingNonExistingTriggerReturnInvalidRequestDescriptor)
478 {
479 auto ec =
480 deleteTrigger(utils::constants::triggerDirPath.str + "NonExisting"s);
481 EXPECT_THAT(ec.value(), Eq(EBADR));
482 }
483
TEST_F(TestTrigger,settingPersistencyToFalseRemovesTriggerFromStorage)484 TEST_F(TestTrigger, settingPersistencyToFalseRemovesTriggerFromStorage)
485 {
486 EXPECT_CALL(storageMock, remove(to_file_path(sut->getId())));
487
488 bool persistent = false;
489 EXPECT_THAT(setProperty(sut->getPath(),
490 TelemetryTrigger::property_names::persistent,
491 persistent),
492 Eq(boost::system::errc::success));
493 EXPECT_THAT(getProperty<bool>(sut->getPath(),
494 TelemetryTrigger::property_names::persistent),
495 Eq(persistent));
496 }
497
498 class TestOnChangeTrigger : public TestTrigger
499 {
500 public:
501 TriggerParams onChangeTriggerParams =
502 TriggerParams()
503 .id("DiscreteOnChangeTrigger")
504 .name("My Discrete On Change Trigger")
505 .thresholdParams(std::vector<numeric::LabeledThresholdParam>{});
506
SetUp()507 void SetUp() override
508 {
509 sut = makeTrigger(onChangeTriggerParams);
510 }
511 };
512
TEST_F(TestOnChangeTrigger,isDiscrete)513 TEST_F(TestOnChangeTrigger, isDiscrete)
514 {
515 EXPECT_THAT(getProperty<bool>(sut->getPath(),
516 TelemetryTrigger::property_names::discrete),
517 Eq(true));
518 }
519
520 class TestTriggerInitialization : public TestTrigger
521 {
522 public:
SetUp()523 void SetUp() override {}
524
525 nlohmann::json storedConfiguration;
526 };
527
TEST_F(TestTriggerInitialization,exceptionDuringTriggerStoreDisablesPersistency)528 TEST_F(TestTriggerInitialization,
529 exceptionDuringTriggerStoreDisablesPersistency)
530 {
531 EXPECT_CALL(storageMock, store(_, _))
532 .WillOnce(Throw(std::runtime_error("Generic error!")));
533
534 sut = makeTrigger(triggerParams);
535
536 EXPECT_THAT(getProperty<bool>(sut->getPath(),
537 TelemetryTrigger::property_names::persistent),
538 Eq(false));
539 }
540
TEST_F(TestTriggerInitialization,creatingTriggerThrowsExceptionWhenIdIsInvalid)541 TEST_F(TestTriggerInitialization, creatingTriggerThrowsExceptionWhenIdIsInvalid)
542 {
543 EXPECT_CALL(storageMock, store(_, _)).Times(0);
544
545 EXPECT_THROW(makeTrigger(triggerParams.id("inv?lidId")),
546 sdbusplus::exception::SdBusError);
547 }
548
TEST_F(TestTriggerInitialization,creatingTriggerUpdatesTriggersIdsInReports)549 TEST_F(TestTriggerInitialization, creatingTriggerUpdatesTriggersIdsInReports)
550 {
551 EXPECT_CALL(
552 triggerPresenceChanged,
553 Call(FieldsAre(messages::Presence::Exist, triggerParams.id(),
554 UnorderedElementsAreArray(triggerParams.reportIds()))));
555
556 sut = makeTrigger(triggerParams);
557 }
558
559 class TestTriggerStore : public TestTrigger
560 {
561 public:
562 nlohmann::json storedConfiguration;
563 nlohmann::json storedDiscreteConfiguration;
564 std::unique_ptr<Trigger> sutDiscrete;
565
SetUp()566 void SetUp() override
567 {
568 ON_CALL(storageMock, store(_, _))
569 .WillByDefault(SaveArg<1>(&storedConfiguration));
570 sut = makeTrigger(triggerParams);
571
572 ON_CALL(storageMock, store(_, _))
573 .WillByDefault(SaveArg<1>(&storedDiscreteConfiguration));
574 sutDiscrete = makeTrigger(triggerDiscreteParams);
575 }
576 };
577
TEST_F(TestTriggerStore,settingPersistencyToTrueStoresTriggerVersion)578 TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerVersion)
579 {
580 ASSERT_THAT(storedConfiguration.at("Version"), Eq(expectedTriggerVersion));
581 }
582
TEST_F(TestTriggerStore,settingPersistencyToTrueStoresTriggerId)583 TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerId)
584 {
585 ASSERT_THAT(storedConfiguration.at("Id"), Eq(triggerParams.id()));
586 }
587
TEST_F(TestTriggerStore,settingPersistencyToTrueStoresTriggerName)588 TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerName)
589 {
590 ASSERT_THAT(storedConfiguration.at("Name"), Eq(triggerParams.name()));
591 }
592
TEST_F(TestTriggerStore,settingPersistencyToTrueStoresTriggerTriggerActions)593 TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerTriggerActions)
594 {
595 ASSERT_THAT(storedConfiguration.at("TriggerActions"),
596 Eq(utils::transform(triggerParams.triggerActions(),
597 [](const auto& action) {
598 return actionToString(action);
599 })));
600 }
601
TEST_F(TestTriggerStore,settingPersistencyToTrueStoresTriggerReportIds)602 TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerReportIds)
603 {
604 ASSERT_THAT(storedConfiguration.at("ReportIds"),
605 Eq(triggerParams.reportIds()));
606 }
607
TEST_F(TestTriggerStore,settingPersistencyToTrueStoresTriggerSensors)608 TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerSensors)
609 {
610 nlohmann::json expectedItem;
611 expectedItem["service"] = "service1";
612 expectedItem["path"] = "/xyz/openbmc_project/sensors/temperature/BMC_Temp";
613 expectedItem["metadata"] = "metadata1";
614
615 ASSERT_THAT(storedConfiguration.at("Sensors"), ElementsAre(expectedItem));
616 }
617
TEST_F(TestTriggerStore,settingPersistencyToTrueStoresTriggerThresholdParams)618 TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerThresholdParams)
619 {
620 nlohmann::json expectedItem0;
621 expectedItem0["type"] = 0;
622 expectedItem0["dwellTime"] = 10;
623 expectedItem0["direction"] = 1;
624 expectedItem0["thresholdValue"] = 0.5;
625
626 nlohmann::json expectedItem1;
627 expectedItem1["type"] = 3;
628 expectedItem1["dwellTime"] = 10;
629 expectedItem1["direction"] = 2;
630 expectedItem1["thresholdValue"] = 90.2;
631
632 ASSERT_THAT(storedConfiguration.at("ThresholdParamsDiscriminator"), Eq(0));
633 ASSERT_THAT(storedConfiguration.at("ThresholdParams"),
634 ElementsAre(expectedItem0, expectedItem1));
635 }
636
TEST_F(TestTriggerStore,settingPersistencyToTrueStoresDiscreteTriggerThresholdParams)637 TEST_F(TestTriggerStore,
638 settingPersistencyToTrueStoresDiscreteTriggerThresholdParams)
639 {
640 nlohmann::json expectedItem0;
641 expectedItem0["userId"] = "userId";
642 expectedItem0["severity"] = discrete::Severity::warning;
643 expectedItem0["dwellTime"] = 10;
644 expectedItem0["thresholdValue"] = "15.2";
645
646 nlohmann::json expectedItem1;
647 expectedItem1["userId"] = "userId_2";
648 expectedItem1["severity"] = discrete::Severity::critical;
649 expectedItem1["dwellTime"] = 5;
650 expectedItem1["thresholdValue"] = "32.7";
651
652 ASSERT_THAT(storedDiscreteConfiguration.at("ThresholdParamsDiscriminator"),
653 Eq(1));
654 ASSERT_THAT(storedDiscreteConfiguration.at("ThresholdParams"),
655 ElementsAre(expectedItem0, expectedItem1));
656 }
657