18#include <gtest/gtest.h>
28using namespace std::chrono_literals;
40 trigger_ = std::make_shared<threshold_trigger>(80.0, comparison_operator::greater_than);
41 EXPECT_TRUE(trigger_->evaluate(81.0));
42 EXPECT_FALSE(trigger_->evaluate(80.0));
43 EXPECT_FALSE(trigger_->evaluate(79.0));
47 trigger_ = std::make_shared<threshold_trigger>(80.0, comparison_operator::greater_or_equal);
48 EXPECT_TRUE(trigger_->evaluate(81.0));
49 EXPECT_TRUE(trigger_->evaluate(80.0));
50 EXPECT_FALSE(trigger_->evaluate(79.0));
54 trigger_ = std::make_shared<threshold_trigger>(20.0, comparison_operator::less_than);
55 EXPECT_TRUE(trigger_->evaluate(19.0));
56 EXPECT_FALSE(trigger_->evaluate(20.0));
57 EXPECT_FALSE(trigger_->evaluate(21.0));
61 trigger_ = std::make_shared<threshold_trigger>(20.0, comparison_operator::less_or_equal);
62 EXPECT_TRUE(trigger_->evaluate(19.0));
63 EXPECT_TRUE(trigger_->evaluate(20.0));
64 EXPECT_FALSE(trigger_->evaluate(21.0));
68 trigger_ = std::make_shared<threshold_trigger>(50.0, comparison_operator::equal);
69 EXPECT_TRUE(trigger_->evaluate(50.0));
70 EXPECT_TRUE(trigger_->evaluate(50.0 + 1e-10));
71 EXPECT_FALSE(trigger_->evaluate(50.1));
75 trigger_ = std::make_shared<threshold_trigger>(50.0, comparison_operator::not_equal);
76 EXPECT_FALSE(trigger_->evaluate(50.0));
77 EXPECT_TRUE(trigger_->evaluate(50.1));
78 EXPECT_TRUE(trigger_->evaluate(49.9));
83 EXPECT_TRUE(t->evaluate(81.0));
84 EXPECT_FALSE(t->evaluate(80.0));
85 EXPECT_EQ(t->threshold(), 80.0);
86 EXPECT_EQ(t->op(), comparison_operator::greater_than);
91 EXPECT_TRUE(t->evaluate(19.0));
92 EXPECT_FALSE(t->evaluate(20.0));
97 EXPECT_TRUE(t->evaluate(80.0));
98 EXPECT_FALSE(t->evaluate(79.9));
103 EXPECT_TRUE(t->evaluate(20.0));
104 EXPECT_FALSE(t->evaluate(20.1));
109 EXPECT_EQ(trigger_->type_name(),
"threshold");
114 auto desc = trigger_->description();
115 EXPECT_FALSE(desc.empty());
116 EXPECT_NE(desc.find(
">"), std::string::npos);
121 EXPECT_TRUE(trigger_->evaluate(-11.0));
122 EXPECT_FALSE(trigger_->evaluate(-9.0));
127 EXPECT_TRUE(trigger_->evaluate(0.001));
128 EXPECT_FALSE(trigger_->evaluate(0.0));
129 EXPECT_FALSE(trigger_->evaluate(-1.0));
139 auto trigger = std::make_shared<range_trigger>(10.0, 90.0,
true);
140 EXPECT_TRUE(trigger->evaluate(50.0));
141 EXPECT_TRUE(trigger->evaluate(10.0));
142 EXPECT_TRUE(trigger->evaluate(90.0));
143 EXPECT_FALSE(trigger->evaluate(9.9));
144 EXPECT_FALSE(trigger->evaluate(90.1));
148 auto trigger = std::make_shared<range_trigger>(10.0, 90.0,
false);
149 EXPECT_TRUE(trigger->evaluate(5.0));
150 EXPECT_TRUE(trigger->evaluate(95.0));
151 EXPECT_FALSE(trigger->evaluate(50.0));
152 EXPECT_FALSE(trigger->evaluate(10.0));
153 EXPECT_FALSE(trigger->evaluate(90.0));
158 EXPECT_TRUE(trigger->evaluate(50.0));
159 EXPECT_FALSE(trigger->evaluate(10.0));
164 EXPECT_TRUE(trigger->evaluate(10.0));
165 EXPECT_TRUE(trigger->evaluate(90.0));
166 EXPECT_FALSE(trigger->evaluate(50.0));
170 auto trigger = std::make_shared<range_trigger>(10.0, 90.0,
true);
171 EXPECT_EQ(trigger->type_name(),
"range");
172 auto desc = trigger->description();
173 EXPECT_NE(desc.find(
"in"), std::string::npos);
177 auto trigger = std::make_shared<range_trigger>(10.0, 90.0,
false);
178 auto desc = trigger->description();
179 EXPECT_NE(desc.find(
"outside"), std::string::npos);
189 auto trigger = std::make_shared<rate_of_change_trigger>(
190 10.0, 1000ms, rate_of_change_trigger::rate_direction::either, 3);
192 EXPECT_FALSE(trigger->evaluate(50.0));
194 EXPECT_FALSE(trigger->evaluate(60.0));
198 auto trigger = std::make_shared<rate_of_change_trigger>(
199 5.0, 1000ms, rate_of_change_trigger::rate_direction::increasing, 2);
201 trigger->evaluate(0.0);
202 std::this_thread::sleep_for(10ms);
204 bool fired = trigger->evaluate(100.0);
211 auto trigger = std::make_shared<rate_of_change_trigger>(
212 5.0, 1000ms, rate_of_change_trigger::rate_direction::decreasing, 2);
214 trigger->evaluate(100.0);
215 std::this_thread::sleep_for(10ms);
216 bool fired = trigger->evaluate(0.0);
221 auto trigger = std::make_shared<rate_of_change_trigger>(
222 5.0, 1000ms, rate_of_change_trigger::rate_direction::either, 2);
224 trigger->evaluate(50.0);
225 std::this_thread::sleep_for(10ms);
227 EXPECT_TRUE(trigger->evaluate(200.0));
231 auto trigger = std::make_shared<rate_of_change_trigger>(
232 5.0, 1000ms, rate_of_change_trigger::rate_direction::either, 2);
234 trigger->evaluate(0.0);
235 trigger->evaluate(100.0);
239 EXPECT_FALSE(trigger->evaluate(50.0));
243 auto trigger = std::make_shared<rate_of_change_trigger>(
244 10.0, 1000ms, rate_of_change_trigger::rate_direction::increasing);
245 EXPECT_EQ(trigger->type_name(),
"rate_of_change");
246 EXPECT_FALSE(trigger->description().empty());
256 auto trigger = std::make_shared<anomaly_trigger>(3.0, 100, 10);
258 for (
int i = 0; i < 9; ++i) {
259 EXPECT_FALSE(trigger->evaluate(50.0));
264 auto trigger = std::make_shared<anomaly_trigger>(3.0, 100, 10);
266 for (
int i = 0; i < 50; ++i) {
267 EXPECT_FALSE(trigger->evaluate(50.0 + (i % 3) * 0.1));
272 auto trigger = std::make_shared<anomaly_trigger>(2.0, 100, 10);
274 for (
int i = 0; i < 20; ++i) {
275 trigger->evaluate(50.0 + (i % 2 == 0 ? 0.5 : -0.5));
278 bool fired = trigger->evaluate(200.0);
283 auto trigger = std::make_shared<anomaly_trigger>(3.0, 100, 5);
284 for (
int i = 0; i < 10; ++i) {
285 trigger->evaluate(10.0);
287 EXPECT_NEAR(trigger->current_mean(), 10.0, 0.01);
288 EXPECT_NEAR(trigger->current_stddev(), 0.0, 0.01);
292 auto trigger = std::make_shared<anomaly_trigger>(3.0, 100, 10);
293 for (
int i = 0; i < 20; ++i) {
294 trigger->evaluate(50.0);
298 EXPECT_FALSE(trigger->evaluate(200.0));
303 auto trigger = std::make_shared<anomaly_trigger>(3.0, 100, 5);
304 for (
int i = 0; i < 10; ++i) {
305 trigger->evaluate(50.0);
308 EXPECT_FALSE(trigger->evaluate(50.0));
312 auto trigger = std::make_shared<anomaly_trigger>(3.0);
313 EXPECT_EQ(trigger->type_name(),
"anomaly");
314 EXPECT_NE(trigger->description().find(
"std devs"), std::string::npos);
330 EXPECT_FALSE(composite->evaluate(90.0));
336 EXPECT_TRUE(composite->evaluate_multi({90.0, 10.0}));
338 EXPECT_FALSE(composite->evaluate_multi({90.0, 30.0}));
344 EXPECT_TRUE(composite->evaluate(90.0));
346 EXPECT_TRUE(composite->evaluate(10.0));
348 EXPECT_FALSE(composite->evaluate(50.0));
352 auto composite = std::make_shared<composite_trigger>(
353 composite_operation::XOR,
354 std::vector<std::shared_ptr<alert_trigger>>{high_, low_});
357 EXPECT_TRUE(composite->evaluate(90.0));
359 EXPECT_FALSE(composite->evaluate(50.0));
363 auto composite = std::make_shared<composite_trigger>(
364 composite_operation::XOR,
365 std::vector<std::shared_ptr<alert_trigger>>{high_, low_});
368 EXPECT_FALSE(composite->evaluate_multi({90.0, 10.0}));
374 EXPECT_FALSE(composite->evaluate(90.0));
376 EXPECT_TRUE(composite->evaluate(50.0));
380 auto composite = std::make_shared<composite_trigger>(
381 composite_operation::AND,
382 std::vector<std::shared_ptr<alert_trigger>>{});
383 EXPECT_FALSE(composite->evaluate(50.0));
390 EXPECT_FALSE(composite->evaluate_multi({90.0}));
395 EXPECT_EQ(composite->triggers().size(), 2u);
400 EXPECT_EQ(composite->type_name(),
"composite");
401 auto desc = composite->description();
402 EXPECT_NE(desc.find(
"AND"), std::string::npos);
407 auto desc = composite->description();
408 EXPECT_NE(desc.find(
"NOT"), std::string::npos);
418 auto trigger = std::make_shared<absent_trigger>(100ms);
419 EXPECT_FALSE(trigger->evaluate(1.0));
423 auto trigger = std::make_shared<absent_trigger>(100ms);
424 trigger->evaluate(1.0);
426 EXPECT_FALSE(trigger->evaluate(2.0));
430 auto trigger = std::make_shared<absent_trigger>(50ms);
431 trigger->evaluate(1.0);
432 std::this_thread::sleep_for(60ms);
433 EXPECT_TRUE(trigger->evaluate(2.0));
437 auto trigger = std::make_shared<absent_trigger>(50ms);
438 trigger->evaluate(1.0);
441 EXPECT_FALSE(trigger->evaluate(2.0));
445 auto trigger = std::make_shared<absent_trigger>(5000ms);
446 EXPECT_EQ(trigger->type_name(),
"absent");
447 auto desc = trigger->description();
448 EXPECT_NE(desc.find(
"no data"), std::string::npos);
458 auto trigger = std::make_shared<delta_trigger>(10.0);
459 EXPECT_FALSE(trigger->evaluate(50.0));
463 auto trigger = std::make_shared<delta_trigger>(10.0,
true);
464 trigger->evaluate(50.0);
465 EXPECT_FALSE(trigger->evaluate(55.0));
469 auto trigger = std::make_shared<delta_trigger>(10.0,
true);
470 trigger->evaluate(50.0);
471 EXPECT_TRUE(trigger->evaluate(70.0));
475 auto trigger = std::make_shared<delta_trigger>(10.0,
true);
476 trigger->evaluate(50.0);
477 EXPECT_TRUE(trigger->evaluate(30.0));
481 auto trigger = std::make_shared<delta_trigger>(10.0,
false);
482 trigger->evaluate(50.0);
484 EXPECT_FALSE(trigger->evaluate(30.0));
486 EXPECT_TRUE(trigger->evaluate(70.0));
490 auto trigger = std::make_shared<delta_trigger>(5.0,
true);
491 trigger->evaluate(10.0);
492 trigger->evaluate(12.0);
493 EXPECT_FALSE(trigger->evaluate(14.0));
494 EXPECT_TRUE(trigger->evaluate(25.0));
495 EXPECT_FALSE(trigger->evaluate(27.0));
499 auto trigger = std::make_shared<delta_trigger>(5.0,
true);
500 trigger->evaluate(10.0);
501 trigger->evaluate(20.0);
504 EXPECT_FALSE(trigger->evaluate(100.0));
508 auto trigger = std::make_shared<delta_trigger>(10.0,
true);
509 EXPECT_EQ(trigger->type_name(),
"delta");
510 auto desc = trigger->description();
511 EXPECT_NE(desc.find(
"delta"), std::string::npos);
515 auto trigger = std::make_shared<delta_trigger>(10.0,
false);
516 auto desc = trigger->description();
518 EXPECT_EQ(desc.find(
"|delta|"), std::string::npos);
525TEST(ComparisonOperatorTest, AllOperatorsHaveStrings) {
Alert trigger implementations for various condition types.
std::shared_ptr< threshold_trigger > high_
std::shared_ptr< threshold_trigger > low_
std::shared_ptr< threshold_trigger > trigger_
static std::shared_ptr< composite_trigger > all_of(std::vector< std::shared_ptr< alert_trigger > > triggers)
Create AND composite.
static std::shared_ptr< composite_trigger > any_of(std::vector< std::shared_ptr< alert_trigger > > triggers)
Create OR composite.
static std::shared_ptr< composite_trigger > invert(std::shared_ptr< alert_trigger > trigger)
Create NOT composite.
static std::shared_ptr< threshold_trigger > below_or_equal(double threshold)
Create trigger for value <= threshold.
static std::shared_ptr< threshold_trigger > below(double threshold)
Create trigger for value < threshold.
static std::shared_ptr< class range_trigger > in_range(double min_val, double max_val)
Create trigger for value within range (inclusive)
static std::shared_ptr< threshold_trigger > above_or_equal(double threshold)
Create trigger for value >= threshold.
static std::shared_ptr< class range_trigger > out_of_range(double min_val, double max_val)
Create trigger for value outside range (exclusive)
static std::shared_ptr< threshold_trigger > above(double threshold)
Create trigger for value > threshold.
constexpr const char * comparison_operator_to_string(comparison_operator op) noexcept
Convert comparison operator to string.
TEST(ComparisonOperatorTest, AllOperatorsHaveStrings)
TEST_F(ThresholdTriggerTest, GreaterThan)