blob: cf7d96c613607e0c42f278bb4d452437c84b2aa8 [file] [log] [blame]
Wludzik, Jozef76833cb2020-12-21 14:42:41 +01001#include "dbus_environment.hpp"
2#include "helpers.hpp"
Cezary Zwolaka4e67612021-02-18 13:16:16 +01003#include "mocks/json_storage_mock.hpp"
Wludzik, Jozef76833cb2020-12-21 14:42:41 +01004#include "mocks/trigger_manager_mock.hpp"
5#include "params/trigger_params.hpp"
6#include "trigger.hpp"
Cezary Zwolak4416fce2021-03-17 03:21:06 +01007#include "utils/conversion_trigger.hpp"
Wludzik, Jozef76833cb2020-12-21 14:42:41 +01008#include "utils/set_exception.hpp"
Cezary Zwolak4416fce2021-03-17 03:21:06 +01009#include "utils/transform.hpp"
10#include "utils/tstring.hpp"
11
12#include <boost/range/combine.hpp>
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010013
14using namespace testing;
15using namespace std::literals::string_literals;
16
Cezary Zwolaka4e67612021-02-18 13:16:16 +010017static constexpr size_t expectedTriggerVersion = 0;
18
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010019class TestTrigger : public Test
20{
21 public:
22 TriggerParams triggerParams;
Cezary Zwolak4416fce2021-03-17 03:21:06 +010023 TriggerParams triggerDiscreteParams =
24 TriggerParams()
25 .name("Trigger2")
26 .isDiscrete(true)
27 .thresholdParams(std::vector<discrete::LabeledThresholdParam>{
28 discrete::LabeledThresholdParam{
29 "userId", discrete::Severity::warning,
30 std::chrono::milliseconds(10).count(), 15.2},
31 discrete::LabeledThresholdParam{
32 "userId_2", discrete::Severity::critical,
33 std::chrono::milliseconds(5).count(), 32.7},
34 });
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010035
36 std::unique_ptr<TriggerManagerMock> triggerManagerMockPtr =
37 std::make_unique<NiceMock<TriggerManagerMock>>();
Cezary Zwolaka4e67612021-02-18 13:16:16 +010038 testing::NiceMock<StorageMock> storageMock;
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010039 std::unique_ptr<Trigger> sut;
40
41 void SetUp() override
42 {
Cezary Zwolaka4e67612021-02-18 13:16:16 +010043 sut = makeTrigger(triggerParams);
44 }
45
Cezary Zwolak4416fce2021-03-17 03:21:06 +010046 static std::vector<LabeledSensorInfo>
47 convertToLabeledSensor(const SensorsInfo& sensorsInfo)
48 {
49 return utils::transform(sensorsInfo, [](const auto& sensorInfo) {
50 const auto& [sensorPath, sensorMetadata] = sensorInfo;
51 return LabeledSensorInfo("service1", sensorPath, sensorMetadata);
52 });
53 }
54
Cezary Zwolaka4e67612021-02-18 13:16:16 +010055 std::unique_ptr<Trigger> makeTrigger(const TriggerParams& params)
56 {
57 return std::make_unique<Trigger>(
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010058 DbusEnvironment::getIoc(), DbusEnvironment::getObjServer(),
Cezary Zwolaka4e67612021-02-18 13:16:16 +010059 params.name(), params.isDiscrete(), params.logToJournal(),
Cezary Zwolak4416fce2021-03-17 03:21:06 +010060 params.logToRedfish(), params.updateReport(), params.reportNames(),
61 params.sensors(), params.thresholdParams(),
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010062 std::vector<std::shared_ptr<interfaces::Threshold>>{},
Cezary Zwolaka4e67612021-02-18 13:16:16 +010063 *triggerManagerMockPtr, storageMock);
64 }
65
66 static interfaces::JsonStorage::FilePath to_file_path(std::string name)
67 {
68 return interfaces::JsonStorage::FilePath(
69 std::to_string(std::hash<std::string>{}(name)));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010070 }
71
72 template <class T>
73 static T getProperty(const std::string& path, const std::string& property)
74 {
Ed Tanous0e7ae5d2021-02-23 14:06:49 -080075 auto propertyPromise = std::promise<T>();
76 auto propertyFuture = propertyPromise.get_future();
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010077 sdbusplus::asio::getProperty<T>(
78 *DbusEnvironment::getBus(), DbusEnvironment::serviceName(), path,
79 Trigger::triggerIfaceName, property,
Ed Tanous0e7ae5d2021-02-23 14:06:49 -080080 [&propertyPromise](const boost::system::error_code& ec, T t) {
81 if (ec)
82 {
83 utils::setException(propertyPromise, "GetProperty failed");
84 return;
85 }
86 propertyPromise.set_value(t);
87 });
88 return DbusEnvironment::waitForFuture(std::move(propertyFuture));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010089 }
90
Cezary Zwolaka4e67612021-02-18 13:16:16 +010091 template <class T>
92 static boost::system::error_code setProperty(const std::string& path,
93 const std::string& property,
94 const T& newValue)
95 {
96 auto setPromise = std::promise<boost::system::error_code>();
97 auto setFuture = setPromise.get_future();
98
99 sdbusplus::asio::setProperty(
100 *DbusEnvironment::getBus(), DbusEnvironment::serviceName(), path,
101 Trigger::triggerIfaceName, property, std::move(newValue),
102 [setPromise =
103 std::move(setPromise)](boost::system::error_code ec) mutable {
104 setPromise.set_value(ec);
105 });
106 return DbusEnvironment::waitForFuture(std::move(setFuture));
107 }
108
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100109 boost::system::error_code deleteTrigger(const std::string& path)
110 {
111 std::promise<boost::system::error_code> methodPromise;
112 DbusEnvironment::getBus()->async_method_call(
113 [&methodPromise](boost::system::error_code ec) {
114 methodPromise.set_value(ec);
115 },
116 DbusEnvironment::serviceName(), path, Trigger::deleteIfaceName,
117 "Delete");
118 return DbusEnvironment::waitForFuture(methodPromise.get_future());
119 }
120};
121
122TEST_F(TestTrigger, checkIfPropertiesAreSet)
123{
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100124 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistent"), Eq(true));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100125 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Discrete"),
126 Eq(triggerParams.isDiscrete()));
127 EXPECT_THAT(getProperty<bool>(sut->getPath(), "LogToJournal"),
128 Eq(triggerParams.logToJournal()));
129 EXPECT_THAT(getProperty<bool>(sut->getPath(), "LogToRedfish"),
130 Eq(triggerParams.logToRedfish()));
131 EXPECT_THAT(getProperty<bool>(sut->getPath(), "UpdateReport"),
132 Eq(triggerParams.updateReport()));
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100133 EXPECT_THAT((getProperty<SensorsInfo>(sut->getPath(), "Sensors")),
134 Eq(utils::fromLabeledSensorsInfo(triggerParams.sensors())));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100135 EXPECT_THAT(
136 getProperty<std::vector<std::string>>(sut->getPath(), "ReportNames"),
137 Eq(triggerParams.reportNames()));
138 EXPECT_THAT(
139 getProperty<TriggerThresholdParams>(sut->getPath(), "Thresholds"),
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100140 Eq(std::visit(utils::FromLabeledThresholdParamConversion(),
141 triggerParams.thresholdParams())));
142}
143
144TEST_F(TestTrigger, checkIfNumericCoversionsAreGood)
145{
146 const auto& labeledParamsBase =
147 std::get<std::vector<numeric::LabeledThresholdParam>>(
148 triggerParams.thresholdParams());
149 const auto paramsToCheck =
150 std::visit(utils::FromLabeledThresholdParamConversion(),
151 triggerParams.thresholdParams());
152 const auto labeledParamsToCheck =
153 std::get<std::vector<numeric::LabeledThresholdParam>>(std::visit(
154 utils::ToLabeledThresholdParamConversion(), paramsToCheck));
155
156 for (const auto& [tocheck, base] :
157 boost::combine(labeledParamsToCheck, labeledParamsBase))
158 {
159 EXPECT_THAT(tocheck.at_label<utils::tstring::Type>(),
160 Eq(base.at_label<utils::tstring::Type>()));
161 EXPECT_THAT(tocheck.at_label<utils::tstring::Direction>(),
162 Eq(base.at_label<utils::tstring::Direction>()));
163 EXPECT_THAT(tocheck.at_label<utils::tstring::DwellTime>(),
164 Eq(base.at_label<utils::tstring::DwellTime>()));
165 EXPECT_THAT(tocheck.at_label<utils::tstring::ThresholdValue>(),
166 Eq(base.at_label<utils::tstring::ThresholdValue>()));
167 }
168}
169
170TEST_F(TestTrigger, checkIfDiscreteCoversionsAreGood)
171{
172 const auto& labeledParamsBase =
173 std::get<std::vector<discrete::LabeledThresholdParam>>(
174 triggerDiscreteParams.thresholdParams());
175 const auto paramsToCheck =
176 std::visit(utils::FromLabeledThresholdParamConversion(),
177 triggerDiscreteParams.thresholdParams());
178 const auto labeledParamsToCheck =
179 std::get<std::vector<discrete::LabeledThresholdParam>>(std::visit(
180 utils::ToLabeledThresholdParamConversion(), paramsToCheck));
181
182 for (const auto& [tocheck, base] :
183 boost::combine(labeledParamsToCheck, labeledParamsBase))
184 {
185 EXPECT_THAT(tocheck.at_label<utils::tstring::UserId>(),
186 Eq(base.at_label<utils::tstring::UserId>()));
187 EXPECT_THAT(tocheck.at_label<utils::tstring::Severity>(),
188 Eq(base.at_label<utils::tstring::Severity>()));
189 EXPECT_THAT(tocheck.at_label<utils::tstring::DwellTime>(),
190 Eq(base.at_label<utils::tstring::DwellTime>()));
191 EXPECT_THAT(tocheck.at_label<utils::tstring::ThresholdValue>(),
192 Eq(base.at_label<utils::tstring::ThresholdValue>()));
193 }
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100194}
195
196TEST_F(TestTrigger, deleteTrigger)
197{
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100198 EXPECT_CALL(storageMock, remove(to_file_path(sut->getName())));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100199 EXPECT_CALL(*triggerManagerMockPtr, removeTrigger(sut.get()));
200 auto ec = deleteTrigger(sut->getPath());
201 EXPECT_THAT(ec, Eq(boost::system::errc::success));
202}
203
204TEST_F(TestTrigger, deletingNonExistingTriggerReturnInvalidRequestDescriptor)
205{
206 auto ec = deleteTrigger(Trigger::triggerDir + "NonExisting"s);
207 EXPECT_THAT(ec.value(), Eq(EBADR));
208}
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100209
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100210TEST_F(TestTrigger, settingPersistencyToFalseRemovesTriggerFromStorage)
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100211{
212 EXPECT_CALL(storageMock, remove(to_file_path(sut->getName())));
213
214 bool persistent = false;
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100215 EXPECT_THAT(setProperty(sut->getPath(), "Persistent", persistent),
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100216 Eq(boost::system::errc::success));
217 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistent"),
218 Eq(persistent));
219}
220
221class TestTriggerErrors : public TestTrigger
222{
223 public:
224 void SetUp() override
225 {}
226
227 nlohmann::json storedConfiguration;
228};
229
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100230TEST_F(TestTriggerErrors, exceptionDuringTriggerStoreDisablesPersistency)
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100231{
232 EXPECT_CALL(storageMock, store(_, _))
233 .WillOnce(Throw(std::runtime_error("Generic error!")));
234
235 sut = makeTrigger(triggerParams);
236
237 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistent"), Eq(false));
238}
239
240TEST_F(TestTriggerErrors, creatingTriggerThrowsExceptionWhenNameIsInvalid)
241{
242 EXPECT_CALL(storageMock, store(_, _)).Times(0);
243
244 EXPECT_THROW(makeTrigger(triggerParams.name("inv?lidName")),
245 sdbusplus::exception::SdBusError);
246}
247
248class TestTriggerStore : public TestTrigger
249{
250 public:
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100251 nlohmann::json storedConfiguration;
252 nlohmann::json storedDiscreteConfiguration;
253 std::unique_ptr<Trigger> sutDiscrete;
254
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100255 void SetUp() override
256 {
257 ON_CALL(storageMock, store(_, _))
258 .WillByDefault(SaveArg<1>(&storedConfiguration));
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100259 sut = makeTrigger(triggerParams);
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100260
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100261 ON_CALL(storageMock, store(_, _))
262 .WillByDefault(SaveArg<1>(&storedDiscreteConfiguration));
263 sutDiscrete = makeTrigger(triggerDiscreteParams);
264 }
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100265};
266
267TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerVersion)
268{
269 ASSERT_THAT(storedConfiguration.at("Version"), Eq(expectedTriggerVersion));
270}
271
272TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerName)
273{
274 ASSERT_THAT(storedConfiguration.at("Name"), Eq(triggerParams.name()));
275}
276
277TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerIsDiscrete)
278{
279 ASSERT_THAT(storedConfiguration.at("IsDiscrete"),
280 Eq(triggerParams.isDiscrete()));
281}
282
283TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerLogToJournal)
284{
285 ASSERT_THAT(storedConfiguration.at("LogToJournal"),
286 Eq(triggerParams.logToRedfish()));
287}
288
289TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerLogToRedfish)
290{
291 ASSERT_THAT(storedConfiguration.at("LogToRedfish"),
292 Eq(triggerParams.logToRedfish()));
293}
294
295TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerUpdateReport)
296{
297 ASSERT_THAT(storedConfiguration.at("UpdateReport"),
298 Eq(triggerParams.updateReport()));
299}
300
301TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerReportNames)
302{
303 ASSERT_THAT(storedConfiguration.at("ReportNames"),
304 Eq(triggerParams.reportNames()));
305}
306
307TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerSensors)
308{
309 nlohmann::json expectedItem;
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100310 expectedItem["service"] = "service1";
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100311 expectedItem["sensorPath"] =
312 "/xyz/openbmc_project/sensors/temperature/BMC_Temp";
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100313 expectedItem["sensorMetadata"] = "metadata1";
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100314
315 ASSERT_THAT(storedConfiguration.at("Sensors"), ElementsAre(expectedItem));
316}
317
318TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerThresholdParams)
319{
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100320 nlohmann::json expectedItem0;
321 expectedItem0["type"] = 0;
322 expectedItem0["dwellTime"] = 10;
323 expectedItem0["direction"] = 1;
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100324 expectedItem0["thresholdValue"] = 0.5;
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100325
326 nlohmann::json expectedItem1;
327 expectedItem1["type"] = 3;
328 expectedItem1["dwellTime"] = 10;
329 expectedItem1["direction"] = 2;
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100330 expectedItem1["thresholdValue"] = 90.2;
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100331
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100332 ASSERT_THAT(storedConfiguration.at("ThresholdParamsDiscriminator"), Eq(0));
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100333 ASSERT_THAT(storedConfiguration.at("ThresholdParams"),
334 ElementsAre(expectedItem0, expectedItem1));
335}
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100336
337TEST_F(TestTriggerStore,
338 settingPersistencyToTrueStoresDiscreteTriggerThresholdParams)
339{
340 nlohmann::json expectedItem0;
341 expectedItem0["userId"] = "userId";
342 expectedItem0["severity"] = discrete::Severity::warning;
343 expectedItem0["dwellTime"] = 10;
344 expectedItem0["thresholdValue"] = 15.2;
345
346 nlohmann::json expectedItem1;
347 expectedItem1["userId"] = "userId_2";
348 expectedItem1["severity"] = discrete::Severity::critical;
349 expectedItem1["dwellTime"] = 5;
350 expectedItem1["thresholdValue"] = 32.7;
351
352 ASSERT_THAT(storedDiscreteConfiguration.at("ThresholdParamsDiscriminator"),
353 Eq(1));
354 ASSERT_THAT(storedDiscreteConfiguration.at("ThresholdParams"),
355 ElementsAre(expectedItem0, expectedItem1));
356}