blob: c813e97ae9bbe94e26ad3f7533eebd2fc5d01fea [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_factory_mock.hpp"
5#include "mocks/trigger_mock.hpp"
6#include "params/trigger_params.hpp"
Cezary Zwolak4416fce2021-03-17 03:21:06 +01007#include "trigger.hpp"
Wludzik, Jozef76833cb2020-12-21 14:42:41 +01008#include "trigger_manager.hpp"
Cezary Zwolak4416fce2021-03-17 03:21:06 +01009#include "utils/conversion_trigger.hpp"
10#include "utils/transform.hpp"
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010011
12using namespace testing;
13
14class TestTriggerManager : public Test
15{
16 public:
17 std::pair<boost::system::error_code, std::string>
18 addTrigger(const TriggerParams& params)
19 {
Cezary Zwolak4416fce2021-03-17 03:21:06 +010020 const auto sensorInfos =
21 utils::fromLabeledSensorsInfo(params.sensors());
22
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010023 std::promise<std::pair<boost::system::error_code, std::string>>
24 addTriggerPromise;
25 DbusEnvironment::getBus()->async_method_call(
26 [&addTriggerPromise](boost::system::error_code ec,
27 const std::string& path) {
28 addTriggerPromise.set_value({ec, path});
29 },
30 DbusEnvironment::serviceName(), TriggerManager::triggerManagerPath,
Szymon Dompkee28aa532021-10-27 12:33:12 +020031 TriggerManager::triggerManagerIfaceName, "AddTrigger", params.id(),
Szymon Dompke20013012021-07-23 09:54:20 +020032 params.name(), params.triggerActions(), sensorInfos,
Cezary Zwolak4416fce2021-03-17 03:21:06 +010033 params.reportNames(),
34 std::visit(utils::FromLabeledThresholdParamConversion(),
35 params.thresholdParams()));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010036 return DbusEnvironment::waitForFuture(addTriggerPromise.get_future());
37 }
38
Cezary Zwolak4416fce2021-03-17 03:21:06 +010039 std::unique_ptr<TriggerManager> makeTriggerManager()
40 {
41 return std::make_unique<TriggerManager>(
42 std::move(triggerFactoryMockPtr), std::move(storageMockPtr),
43 DbusEnvironment::getObjServer());
44 }
45
46 void SetUp() override
47 {
48 sut = makeTriggerManager();
49 }
50
Cezary Zwolaka4e67612021-02-18 13:16:16 +010051 std::unique_ptr<StorageMock> storageMockPtr =
52 std::make_unique<NiceMock<StorageMock>>();
53 StorageMock& storageMock = *storageMockPtr;
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010054 std::unique_ptr<TriggerFactoryMock> triggerFactoryMockPtr =
55 std::make_unique<NiceMock<TriggerFactoryMock>>();
56 TriggerFactoryMock& triggerFactoryMock = *triggerFactoryMockPtr;
57 std::unique_ptr<TriggerMock> triggerMockPtr =
Szymon Dompkee28aa532021-10-27 12:33:12 +020058 std::make_unique<NiceMock<TriggerMock>>(TriggerParams().id());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010059 TriggerMock& triggerMock = *triggerMockPtr;
Cezary Zwolak4416fce2021-03-17 03:21:06 +010060 std::unique_ptr<TriggerManager> sut;
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010061 MockFunction<void(std::string)> checkPoint;
62};
63
64TEST_F(TestTriggerManager, addTrigger)
65{
Cezary Zwolak4416fce2021-03-17 03:21:06 +010066 triggerFactoryMock.expectMake(TriggerParams(), Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010067 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
68
Cezary Zwolak4416fce2021-03-17 03:21:06 +010069 auto [ec, path] = addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010070 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
71 EXPECT_THAT(path, Eq(triggerMock.getPath()));
72}
73
Szymon Dompkef763c9e2021-03-12 09:19:22 +010074TEST_F(TestTriggerManager, addTriggerWithDiscreteThresholds)
75{
76 TriggerParams triggerParamsDiscrete;
Cezary Zwolak4416fce2021-03-17 03:21:06 +010077 auto thresholds = std::vector<discrete::LabeledThresholdParam>{
Szymon Dompke9f346792021-07-14 21:07:11 +020078 {"discrete_threshold1", discrete::Severity::ok, 10, "11.0"},
79 {"discrete_threshold2", discrete::Severity::warning, 10, "12.0"},
80 {"discrete_threshold3", discrete::Severity::critical, 10, "13.0"}};
Szymon Dompkef763c9e2021-03-12 09:19:22 +010081
Szymon Dompke20013012021-07-23 09:54:20 +020082 triggerParamsDiscrete.thresholdParams(thresholds);
Szymon Dompkef763c9e2021-03-12 09:19:22 +010083
84 auto [ec, path] = addTrigger(triggerParamsDiscrete);
85 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
86 EXPECT_THAT(path, Eq(triggerMock.getPath()));
87}
88
89TEST_F(TestTriggerManager, addDiscreteTriggerWithoutThresholds)
90{
91 TriggerParams triggerParamsDiscrete;
Cezary Zwolak4416fce2021-03-17 03:21:06 +010092 auto thresholds = std::vector<discrete::LabeledThresholdParam>();
Szymon Dompkef763c9e2021-03-12 09:19:22 +010093
Szymon Dompke20013012021-07-23 09:54:20 +020094 triggerParamsDiscrete.thresholdParams(thresholds);
Szymon Dompkef763c9e2021-03-12 09:19:22 +010095
96 auto [ec, path] = addTrigger(triggerParamsDiscrete);
97 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
98 EXPECT_THAT(path, Eq(triggerMock.getPath()));
99}
100
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100101TEST_F(TestTriggerManager, DISABLED_failToAddTriggerTwice)
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100102{
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100103 triggerFactoryMock.expectMake(TriggerParams(), Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100104 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
105
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100106 addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100107
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100108 auto [ec, path] = addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100109 EXPECT_THAT(ec.value(), Eq(boost::system::errc::file_exists));
110 EXPECT_THAT(path, Eq(std::string()));
111}
112
Szymon Dompkee28aa532021-10-27 12:33:12 +0200113TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWithInvalidId)
114{
115 triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
116 .Times(0);
117
118 auto [ec, path] = addTrigger(TriggerParams().id("not valid?"));
119 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
120 EXPECT_THAT(path, Eq(std::string()));
121}
122
123TEST_F(TestTriggerManager, addTriggerWithoutIdAndName)
124{
125 triggerFactoryMock
126 .expectMake(TriggerParams()
127 .id(TriggerManager::triggerNameDefault)
128 .name(TriggerManager::triggerNameDefault),
129 Ref(*sut), Ref(storageMock))
130 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
131
132 auto [ec, path] = addTrigger(TriggerParams().id("").name(""));
133 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
134 EXPECT_THAT(path, Not(Eq("")));
135}
136
137TEST_F(TestTriggerManager, addTriggerWithPrefixId)
138{
139 triggerFactoryMock
140 .expectMake(TriggerParams()
141 .id("TelemetryService/HackyName")
142 .name("Hacky/Name!@#$"),
143 Ref(*sut), Ref(storageMock))
144 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
145
146 auto [ec, path] = addTrigger(
147 TriggerParams().id("TelemetryService/").name("Hacky/Name!@#$"));
148 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
149 EXPECT_THAT(path, Not(Eq("")));
150}
151
152TEST_F(TestTriggerManager, addTriggerWithoutIdTwice)
153{
154 addTrigger(TriggerParams().id(""));
155
156 auto [ec, path] = addTrigger(TriggerParams().id(""));
157 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
158 EXPECT_THAT(path, Not(Eq("")));
159}
160
161TEST_F(TestTriggerManager, addTriggerWithoutIdAndWithLongNameTwice)
162{
163 addTrigger(TriggerParams().id("").name(
164 std::string(2 * TriggerManager::maxTriggerIdLength, 'z')));
165
166 auto [ec, path] = addTrigger(TriggerParams().id("").name(
167 std::string(2 * TriggerManager::maxTriggerIdLength, 'z')));
168 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
169 EXPECT_THAT(path, Not(Eq("")));
170}
171
172TEST_F(TestTriggerManager, addTriggerWithMaxLengthId)
173{
174 auto triggerId = std::string(TriggerManager::maxTriggerIdLength, 'z');
175 auto triggerParams = TriggerParams().id(triggerId);
176
177 triggerFactoryMock.expectMake(triggerParams, Ref(*sut), Ref(storageMock))
178 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
179
180 auto [ec, path] = addTrigger(triggerParams);
181
182 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
183 EXPECT_THAT(path, Eq(triggerMock.getPath()));
184}
185
186TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWithTooLongId)
187{
188 auto triggerId = std::string(TriggerManager::maxTriggerIdLength + 1, 'z');
189 auto triggerParams = TriggerParams().id(triggerId);
190
191 triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
192 .Times(0);
193
194 auto [ec, path] = addTrigger(triggerParams);
195
196 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
197 EXPECT_THAT(path, Eq(std::string()));
198}
199
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100200TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWhenMaxTriggerIsReached)
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100201{
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100202 auto triggerParams = TriggerParams();
203
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100204 triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100205 .Times(TriggerManager::maxTriggers);
206
207 for (size_t i = 0; i < TriggerManager::maxTriggers; i++)
208 {
Szymon Dompkee28aa532021-10-27 12:33:12 +0200209 triggerParams.id(TriggerParams().id() + std::to_string(i));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100210
211 auto [ec, path] = addTrigger(triggerParams);
212 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
213 }
214
Szymon Dompkee28aa532021-10-27 12:33:12 +0200215 triggerParams.id(TriggerParams().id() +
216 std::to_string(TriggerManager::maxTriggers));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100217 auto [ec, path] = addTrigger(triggerParams);
218 EXPECT_THAT(ec.value(), Eq(boost::system::errc::too_many_files_open));
219 EXPECT_THAT(path, Eq(std::string()));
220}
221
222TEST_F(TestTriggerManager, removeTrigger)
223{
224 {
225 InSequence seq;
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100226 triggerFactoryMock
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100227 .expectMake(TriggerParams(), Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100228 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
229 EXPECT_CALL(triggerMock, Die());
230 EXPECT_CALL(checkPoint, Call("end"));
231 }
232
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100233 addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100234 sut->removeTrigger(&triggerMock);
235 checkPoint.Call("end");
236}
237
238TEST_F(TestTriggerManager, removingTriggerThatIsNotInContainerHasNoEffect)
239{
240 {
241 InSequence seq;
242 EXPECT_CALL(checkPoint, Call("end"));
243 EXPECT_CALL(triggerMock, Die());
244 }
245
246 sut->removeTrigger(&triggerMock);
247 checkPoint.Call("end");
248}
249
250TEST_F(TestTriggerManager, removingSameTriggerTwiceHasNoSideEffect)
251{
252 {
253 InSequence seq;
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100254 triggerFactoryMock
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100255 .expectMake(TriggerParams(), Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100256 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
257 EXPECT_CALL(triggerMock, Die());
258 EXPECT_CALL(checkPoint, Call("end"));
259 }
260
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100261 addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100262 sut->removeTrigger(&triggerMock);
263 sut->removeTrigger(&triggerMock);
264 checkPoint.Call("end");
265}
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100266
267class TestTriggerManagerStorage : public TestTriggerManager
268{
269 public:
270 using FilePath = interfaces::JsonStorage::FilePath;
271 using DirectoryPath = interfaces::JsonStorage::DirectoryPath;
272
273 void SetUp() override
274 {
275 ON_CALL(storageMock, list())
276 .WillByDefault(Return(std::vector<FilePath>{
277 {FilePath("trigger1")}, {FilePath("trigger2")}}));
278
279 ON_CALL(storageMock, load(FilePath("trigger1")))
280 .WillByDefault(InvokeWithoutArgs([this] { return data1; }));
281
Szymon Dompkee28aa532021-10-27 12:33:12 +0200282 data2["Id"] = "Trigger2";
283 data2["Name"] = "Second Trigger";
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100284 ON_CALL(storageMock, load(FilePath("trigger2")))
285 .WillByDefault(InvokeWithoutArgs([this] { return data2; }));
286 }
287
288 nlohmann::json data1 = nlohmann::json{
289 {"Version", Trigger::triggerVersion},
Szymon Dompkee28aa532021-10-27 12:33:12 +0200290 {"Id", TriggerParams().id()},
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100291 {"Name", TriggerParams().name()},
292 {"ThresholdParamsDiscriminator",
293 TriggerParams().thresholdParams().index()},
Szymon Dompke20013012021-07-23 09:54:20 +0200294 {"TriggerActions", TriggerParams().triggerActions()},
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100295 {"ThresholdParams", utils::labeledThresholdParamsToJson(
296 TriggerParams().thresholdParams())},
297 {"ReportNames", TriggerParams().reportNames()},
298 {"Sensors", TriggerParams().sensors()}};
299
300 nlohmann::json data2 = data1;
301};
302
303TEST_F(TestTriggerManagerStorage, triggerManagerCtorAddTriggerFromStorage)
304{
305 triggerFactoryMock.expectMake(TriggerParams(), _, Ref(storageMock));
Szymon Dompkee28aa532021-10-27 12:33:12 +0200306 triggerFactoryMock.expectMake(
307 TriggerParams().id("Trigger2").name("Second Trigger"), _,
308 Ref(storageMock));
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100309 EXPECT_CALL(storageMock, remove(_)).Times(0);
310
311 sut = makeTriggerManager();
312}
313
314TEST_F(TestTriggerManagerStorage,
315 triggerManagerCtorRemoveDiscreteTriggerFromStorage)
316{
317 LabeledTriggerThresholdParams thresholdParams =
318 std::vector<discrete::LabeledThresholdParam>{
Szymon Dompke9f346792021-07-14 21:07:11 +0200319 {"userId1", discrete::Severity::warning, 15, "10.0"},
320 {"userId2", discrete::Severity::critical, 5, "20.0"}};
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100321
322 data1["ThresholdParamsDiscriminator"] = thresholdParams.index();
323
324 data1["ThresholdParams"] =
325 utils::labeledThresholdParamsToJson(thresholdParams);
326
327 EXPECT_CALL(storageMock, remove(FilePath("trigger1"))).Times(0);
328
329 sut = makeTriggerManager();
330}
331
332TEST_F(TestTriggerManagerStorage,
333 triggerManagerCtorRemoveDiscreteTriggerFromStorage2)
334{
335 data1["IsDiscrete"] = true;
336
337 EXPECT_CALL(storageMock, remove(FilePath("trigger1"))).Times(0);
338
339 sut = makeTriggerManager();
340}
341
342TEST_F(TestTriggerManagerStorage,
343 triggerManagerCtorAddProperRemoveInvalidTriggerFromStorage)
344{
345 data1["Version"] = Trigger::triggerVersion - 1;
346
Szymon Dompkee28aa532021-10-27 12:33:12 +0200347 triggerFactoryMock.expectMake(
348 TriggerParams().id("Trigger2").name("Second Trigger"), _,
349 Ref(storageMock));
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100350 EXPECT_CALL(storageMock, remove(FilePath("trigger1")));
351
352 sut = makeTriggerManager();
353}