xref: /openbmc/telemetry/tests/src/test_trigger.cpp (revision b6171359492449e88734460ef00485f68f688ea2)
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