blob: a074e7a29308dac3ef94e14fd313760fc32cfe0a [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"
Szymon Dompkee28aa532021-10-27 12:33:12 +02007#include "trigger_manager.hpp"
Cezary Zwolak4416fce2021-03-17 03:21:06 +01008#include "utils/conversion_trigger.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()
Szymon Dompkee28aa532021-10-27 12:33:12 +020025 .id("DiscreteTrigger")
26 .name("My Discrete Trigger")
Cezary Zwolak4416fce2021-03-17 03:21:06 +010027 .thresholdParams(std::vector<discrete::LabeledThresholdParam>{
28 discrete::LabeledThresholdParam{
29 "userId", discrete::Severity::warning,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000030 Milliseconds(10).count(), "15.2"},
Cezary Zwolak4416fce2021-03-17 03:21:06 +010031 discrete::LabeledThresholdParam{
32 "userId_2", discrete::Severity::critical,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000033 Milliseconds(5).count(), "32.7"},
Cezary Zwolak4416fce2021-03-17 03:21:06 +010034 });
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(),
Szymon Dompkee28aa532021-10-27 12:33:12 +020059 params.id(), params.name(), params.triggerActions(),
60 params.reportNames(), params.sensors(), params.thresholdParams(),
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010061 std::vector<std::shared_ptr<interfaces::Threshold>>{},
Cezary Zwolaka4e67612021-02-18 13:16:16 +010062 *triggerManagerMockPtr, storageMock);
63 }
64
65 static interfaces::JsonStorage::FilePath to_file_path(std::string name)
66 {
67 return interfaces::JsonStorage::FilePath(
68 std::to_string(std::hash<std::string>{}(name)));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010069 }
70
71 template <class T>
72 static T getProperty(const std::string& path, const std::string& property)
73 {
Szymon Dompkee28aa532021-10-27 12:33:12 +020074 return DbusEnvironment::getProperty<T>(path, Trigger::triggerIfaceName,
75 property);
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010076 }
77
Cezary Zwolaka4e67612021-02-18 13:16:16 +010078 template <class T>
79 static boost::system::error_code setProperty(const std::string& path,
80 const std::string& property,
81 const T& newValue)
82 {
Szymon Dompkee28aa532021-10-27 12:33:12 +020083 return DbusEnvironment::setProperty<T>(path, Trigger::triggerIfaceName,
84 property, newValue);
Cezary Zwolaka4e67612021-02-18 13:16:16 +010085 }
86
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010087 boost::system::error_code deleteTrigger(const std::string& path)
88 {
89 std::promise<boost::system::error_code> methodPromise;
90 DbusEnvironment::getBus()->async_method_call(
91 [&methodPromise](boost::system::error_code ec) {
92 methodPromise.set_value(ec);
93 },
94 DbusEnvironment::serviceName(), path, Trigger::deleteIfaceName,
95 "Delete");
96 return DbusEnvironment::waitForFuture(methodPromise.get_future());
97 }
98};
99
100TEST_F(TestTrigger, checkIfPropertiesAreSet)
101{
Szymon Dompkee28aa532021-10-27 12:33:12 +0200102 EXPECT_THAT(getProperty<std::string>(sut->getPath(), "Name"),
103 Eq(triggerParams.name()));
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100104 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistent"), Eq(true));
Szymon Dompke20013012021-07-23 09:54:20 +0200105 EXPECT_THAT(
106 getProperty<std::vector<std::string>>(sut->getPath(), "TriggerActions"),
107 Eq(triggerParams.triggerActions()));
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100108 EXPECT_THAT((getProperty<SensorsInfo>(sut->getPath(), "Sensors")),
109 Eq(utils::fromLabeledSensorsInfo(triggerParams.sensors())));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100110 EXPECT_THAT(
111 getProperty<std::vector<std::string>>(sut->getPath(), "ReportNames"),
112 Eq(triggerParams.reportNames()));
113 EXPECT_THAT(
114 getProperty<TriggerThresholdParams>(sut->getPath(), "Thresholds"),
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100115 Eq(std::visit(utils::FromLabeledThresholdParamConversion(),
116 triggerParams.thresholdParams())));
117}
118
Szymon Dompkee28aa532021-10-27 12:33:12 +0200119TEST_F(TestTrigger, setPropertyNameToCorrectValue)
120{
121 std::string name = "custom name 1234 %^#5";
122 EXPECT_THAT(setProperty(sut->getPath(), "Name", name),
123 Eq(boost::system::errc::success));
124 EXPECT_THAT(getProperty<std::string>(sut->getPath(), "Name"), Eq(name));
125}
126
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100127TEST_F(TestTrigger, checkIfNumericCoversionsAreGood)
128{
129 const auto& labeledParamsBase =
130 std::get<std::vector<numeric::LabeledThresholdParam>>(
131 triggerParams.thresholdParams());
132 const auto paramsToCheck =
133 std::visit(utils::FromLabeledThresholdParamConversion(),
134 triggerParams.thresholdParams());
135 const auto labeledParamsToCheck =
136 std::get<std::vector<numeric::LabeledThresholdParam>>(std::visit(
137 utils::ToLabeledThresholdParamConversion(), paramsToCheck));
138
139 for (const auto& [tocheck, base] :
140 boost::combine(labeledParamsToCheck, labeledParamsBase))
141 {
142 EXPECT_THAT(tocheck.at_label<utils::tstring::Type>(),
143 Eq(base.at_label<utils::tstring::Type>()));
144 EXPECT_THAT(tocheck.at_label<utils::tstring::Direction>(),
145 Eq(base.at_label<utils::tstring::Direction>()));
146 EXPECT_THAT(tocheck.at_label<utils::tstring::DwellTime>(),
147 Eq(base.at_label<utils::tstring::DwellTime>()));
148 EXPECT_THAT(tocheck.at_label<utils::tstring::ThresholdValue>(),
149 Eq(base.at_label<utils::tstring::ThresholdValue>()));
150 }
151}
152
153TEST_F(TestTrigger, checkIfDiscreteCoversionsAreGood)
154{
155 const auto& labeledParamsBase =
156 std::get<std::vector<discrete::LabeledThresholdParam>>(
157 triggerDiscreteParams.thresholdParams());
158 const auto paramsToCheck =
159 std::visit(utils::FromLabeledThresholdParamConversion(),
160 triggerDiscreteParams.thresholdParams());
161 const auto labeledParamsToCheck =
162 std::get<std::vector<discrete::LabeledThresholdParam>>(std::visit(
163 utils::ToLabeledThresholdParamConversion(), paramsToCheck));
164
165 for (const auto& [tocheck, base] :
166 boost::combine(labeledParamsToCheck, labeledParamsBase))
167 {
168 EXPECT_THAT(tocheck.at_label<utils::tstring::UserId>(),
169 Eq(base.at_label<utils::tstring::UserId>()));
170 EXPECT_THAT(tocheck.at_label<utils::tstring::Severity>(),
171 Eq(base.at_label<utils::tstring::Severity>()));
172 EXPECT_THAT(tocheck.at_label<utils::tstring::DwellTime>(),
173 Eq(base.at_label<utils::tstring::DwellTime>()));
174 EXPECT_THAT(tocheck.at_label<utils::tstring::ThresholdValue>(),
175 Eq(base.at_label<utils::tstring::ThresholdValue>()));
176 }
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100177}
178
179TEST_F(TestTrigger, deleteTrigger)
180{
Szymon Dompkee28aa532021-10-27 12:33:12 +0200181 EXPECT_CALL(storageMock, remove(to_file_path(sut->getId())));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100182 EXPECT_CALL(*triggerManagerMockPtr, removeTrigger(sut.get()));
183 auto ec = deleteTrigger(sut->getPath());
184 EXPECT_THAT(ec, Eq(boost::system::errc::success));
185}
186
187TEST_F(TestTrigger, deletingNonExistingTriggerReturnInvalidRequestDescriptor)
188{
189 auto ec = deleteTrigger(Trigger::triggerDir + "NonExisting"s);
190 EXPECT_THAT(ec.value(), Eq(EBADR));
191}
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100192
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100193TEST_F(TestTrigger, settingPersistencyToFalseRemovesTriggerFromStorage)
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100194{
Szymon Dompkee28aa532021-10-27 12:33:12 +0200195 EXPECT_CALL(storageMock, remove(to_file_path(sut->getId())));
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100196
197 bool persistent = false;
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100198 EXPECT_THAT(setProperty(sut->getPath(), "Persistent", persistent),
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100199 Eq(boost::system::errc::success));
200 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistent"),
201 Eq(persistent));
202}
203
204class TestTriggerErrors : public TestTrigger
205{
206 public:
207 void SetUp() override
208 {}
209
210 nlohmann::json storedConfiguration;
211};
212
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100213TEST_F(TestTriggerErrors, exceptionDuringTriggerStoreDisablesPersistency)
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100214{
215 EXPECT_CALL(storageMock, store(_, _))
216 .WillOnce(Throw(std::runtime_error("Generic error!")));
217
218 sut = makeTrigger(triggerParams);
219
220 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistent"), Eq(false));
221}
222
Szymon Dompkee28aa532021-10-27 12:33:12 +0200223TEST_F(TestTriggerErrors, creatingTriggerThrowsExceptionWhenIdIsInvalid)
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100224{
225 EXPECT_CALL(storageMock, store(_, _)).Times(0);
226
Szymon Dompkee28aa532021-10-27 12:33:12 +0200227 EXPECT_THROW(makeTrigger(triggerParams.id("inv?lidId")),
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100228 sdbusplus::exception::SdBusError);
229}
230
231class TestTriggerStore : public TestTrigger
232{
233 public:
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100234 nlohmann::json storedConfiguration;
235 nlohmann::json storedDiscreteConfiguration;
236 std::unique_ptr<Trigger> sutDiscrete;
237
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100238 void SetUp() override
239 {
240 ON_CALL(storageMock, store(_, _))
241 .WillByDefault(SaveArg<1>(&storedConfiguration));
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100242 sut = makeTrigger(triggerParams);
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100243
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100244 ON_CALL(storageMock, store(_, _))
245 .WillByDefault(SaveArg<1>(&storedDiscreteConfiguration));
246 sutDiscrete = makeTrigger(triggerDiscreteParams);
247 }
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100248};
249
250TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerVersion)
251{
252 ASSERT_THAT(storedConfiguration.at("Version"), Eq(expectedTriggerVersion));
253}
254
Szymon Dompkee28aa532021-10-27 12:33:12 +0200255TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerId)
256{
257 ASSERT_THAT(storedConfiguration.at("Id"), Eq(triggerParams.id()));
258}
259
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100260TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerName)
261{
262 ASSERT_THAT(storedConfiguration.at("Name"), Eq(triggerParams.name()));
263}
264
Szymon Dompke20013012021-07-23 09:54:20 +0200265TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerTriggerActions)
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100266{
Szymon Dompke20013012021-07-23 09:54:20 +0200267 ASSERT_THAT(storedConfiguration.at("TriggerActions"),
268 Eq(triggerParams.triggerActions()));
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100269}
270
271TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerReportNames)
272{
273 ASSERT_THAT(storedConfiguration.at("ReportNames"),
274 Eq(triggerParams.reportNames()));
275}
276
277TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerSensors)
278{
279 nlohmann::json expectedItem;
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100280 expectedItem["service"] = "service1";
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100281 expectedItem["sensorPath"] =
282 "/xyz/openbmc_project/sensors/temperature/BMC_Temp";
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100283 expectedItem["sensorMetadata"] = "metadata1";
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100284
285 ASSERT_THAT(storedConfiguration.at("Sensors"), ElementsAre(expectedItem));
286}
287
288TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerThresholdParams)
289{
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100290 nlohmann::json expectedItem0;
291 expectedItem0["type"] = 0;
292 expectedItem0["dwellTime"] = 10;
293 expectedItem0["direction"] = 1;
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100294 expectedItem0["thresholdValue"] = 0.5;
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100295
296 nlohmann::json expectedItem1;
297 expectedItem1["type"] = 3;
298 expectedItem1["dwellTime"] = 10;
299 expectedItem1["direction"] = 2;
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100300 expectedItem1["thresholdValue"] = 90.2;
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100301
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100302 ASSERT_THAT(storedConfiguration.at("ThresholdParamsDiscriminator"), Eq(0));
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100303 ASSERT_THAT(storedConfiguration.at("ThresholdParams"),
304 ElementsAre(expectedItem0, expectedItem1));
305}
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100306
307TEST_F(TestTriggerStore,
308 settingPersistencyToTrueStoresDiscreteTriggerThresholdParams)
309{
310 nlohmann::json expectedItem0;
311 expectedItem0["userId"] = "userId";
312 expectedItem0["severity"] = discrete::Severity::warning;
313 expectedItem0["dwellTime"] = 10;
Szymon Dompke9f346792021-07-14 21:07:11 +0200314 expectedItem0["thresholdValue"] = "15.2";
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100315
316 nlohmann::json expectedItem1;
317 expectedItem1["userId"] = "userId_2";
318 expectedItem1["severity"] = discrete::Severity::critical;
319 expectedItem1["dwellTime"] = 5;
Szymon Dompke9f346792021-07-14 21:07:11 +0200320 expectedItem1["thresholdValue"] = "32.7";
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100321
322 ASSERT_THAT(storedDiscreteConfiguration.at("ThresholdParamsDiscriminator"),
323 Eq(1));
324 ASSERT_THAT(storedDiscreteConfiguration.at("ThresholdParams"),
325 ElementsAre(expectedItem0, expectedItem1));
326}