#include "dbus_environment.hpp" #include "helpers.hpp" #include "mocks/sensor_mock.hpp" #include "mocks/trigger_action_mock.hpp" #include "numeric_threshold.hpp" #include "utils/conv_container.hpp" #include using namespace testing; using namespace std::chrono_literals; class TestNumericThreshold : public Test { public: std::vector> sensorMocks = { std::make_shared>(), std::make_shared>()}; std::vector sensorNames = {"Sensor1", "Sensor2"}; std::unique_ptr actionMockPtr = std::make_unique>(); TriggerActionMock& actionMock = *actionMockPtr; std::shared_ptr sut; void makeThreshold(Milliseconds dwellTime, numeric::Direction direction, double thresholdValue) { std::vector> actions; actions.push_back(std::move(actionMockPtr)); sut = std::make_shared( DbusEnvironment::getIoc(), utils::convContainer>( sensorMocks), sensorNames, std::move(actions), dwellTime, direction, thresholdValue); } void SetUp() override { makeThreshold(0ms, numeric::Direction::increasing, 90.0); } }; TEST_F(TestNumericThreshold, initializeThresholdExpectAllSensorsAreRegistered) { for (auto& sensor : sensorMocks) { EXPECT_CALL(*sensor, registerForUpdates(Truly([sut = sut.get()](const auto& x) { return x.lock().get() == sut; }))); } sut->initialize(); } TEST_F(TestNumericThreshold, thresholdIsNotInitializeExpectNoActionCommit) { EXPECT_CALL(actionMock, commit(_, _, _)).Times(0); } struct NumericParams { NumericParams& Direction(numeric::Direction val) { direction = val; return *this; } NumericParams& Updates(std::vector> val) { updates = std::move(val); return *this; } NumericParams& Expected(std::vector> val) { expected = std::move(val); return *this; } friend void PrintTo(const NumericParams& o, std::ostream* os) { *os << "{ Direction: " << static_cast(o.direction) << ", Updates: "; for (const auto& [index, timestamp, value] : o.updates) { *os << "{ SensorIndex: " << index << ", Timestamp: " << timestamp << ", Value: " << value << " }, "; } *os << "Expected: "; for (const auto& [index, timestamp, value] : o.expected) { *os << "{ SensorIndex: " << index << ", Timestamp: " << timestamp << ", Value: " << value << " }, "; } *os << " }"; } numeric::Direction direction; std::vector> updates; std::vector> expected; }; class TestNumericThresholdNoDwellTime : public TestNumericThreshold, public WithParamInterface { public: void SetUp() override { makeThreshold(0ms, GetParam().direction, 90.0); } }; INSTANTIATE_TEST_SUITE_P( _, TestNumericThresholdNoDwellTime, Values( NumericParams() .Direction(numeric::Direction::increasing) .Updates({{0, 1, 80.0}, {0, 2, 89.0}}) .Expected({}), NumericParams() .Direction(numeric::Direction::increasing) .Updates({{0, 1, 80.0}, {0, 2, 91.0}}) .Expected({{0, 2, 91.0}}), NumericParams() .Direction(numeric::Direction::increasing) .Updates({{0, 1, 80.0}, {0, 2, 99.0}, {0, 3, 80.0}, {0, 4, 98.0}}) .Expected({{0, 2, 99.0}, {0, 4, 98.0}}), NumericParams() .Direction(numeric::Direction::increasing) .Updates({{0, 1, 80.0}, {0, 2, 99.0}, {1, 3, 100.0}, {1, 4, 98.0}}) .Expected({{0, 2, 99.0}}), NumericParams() .Direction(numeric::Direction::decreasing) .Updates({{0, 1, 100.0}, {0, 2, 91.0}}) .Expected({}), NumericParams() .Direction(numeric::Direction::decreasing) .Updates({{0, 1, 100.0}, {0, 2, 80.0}}) .Expected({{0, 2, 80.0}}), NumericParams() .Direction(numeric::Direction::decreasing) .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {0, 3, 99.0}, {0, 4, 85.0}}) .Expected({{0, 2, 80.0}, {0, 4, 85.0}}), NumericParams() .Direction(numeric::Direction::decreasing) .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {1, 3, 99.0}, {1, 4, 88.0}}) .Expected({{0, 2, 80.0}, {1, 4, 88.0}}), NumericParams() .Direction(numeric::Direction::either) .Updates({{0, 1, 98.0}, {0, 2, 91.0}}) .Expected({}), NumericParams() .Direction(numeric::Direction::either) .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {0, 3, 85.0}, {0, 4, 91.0}}) .Expected({{0, 2, 80.0}, {0, 4, 91.0}}), NumericParams() .Direction(numeric::Direction::either) .Updates({{0, 1, 100.0}, {1, 2, 80.0}, {0, 3, 85.0}, {1, 4, 91.0}}) .Expected({{0, 3, 85.0}, {1, 4, 91.0}}))); TEST_P(TestNumericThresholdNoDwellTime, senorsIsUpdatedMultipleTimes) { InSequence seq; for (const auto& [index, timestamp, value] : GetParam().expected) { EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value)); } sut->initialize(); for (const auto& [index, timestamp, value] : GetParam().updates) { sut->sensorUpdated(*sensorMocks[index], timestamp, value); } } class TestNumericThresholdWithDwellTime : public TestNumericThreshold, public WithParamInterface { public: void SetUp() override { makeThreshold(2ms, GetParam().direction, 90.0); } void sleep() { DbusEnvironment::sleepFor(4ms); } }; INSTANTIATE_TEST_SUITE_P( _, TestNumericThresholdWithDwellTime, Values( NumericParams() .Direction(numeric::Direction::increasing) .Updates({{0, 1, 80.0}, {0, 2, 89.0}}) .Expected({}), NumericParams() .Direction(numeric::Direction::increasing) .Updates({{0, 1, 80.0}, {0, 2, 91.0}}) .Expected({{0, 2, 91.0}}), NumericParams() .Direction(numeric::Direction::increasing) .Updates({{0, 1, 80.0}, {0, 2, 99.0}, {0, 3, 80.0}, {0, 4, 98.0}}) .Expected({{0, 2, 99.0}, {0, 4, 98.0}}), NumericParams() .Direction(numeric::Direction::increasing) .Updates({{0, 1, 80.0}, {1, 2, 99.0}, {0, 3, 100.0}, {1, 4, 86.0}}) .Expected({{0, 3, 100.0}}), NumericParams() .Direction(numeric::Direction::decreasing) .Updates({{0, 1, 100.0}, {0, 2, 91.0}}) .Expected({}), NumericParams() .Direction(numeric::Direction::decreasing) .Updates({{0, 1, 100.0}, {0, 2, 80.0}}) .Expected({{0, 2, 80.0}}), NumericParams() .Direction(numeric::Direction::decreasing) .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {0, 3, 99.0}, {0, 4, 85.0}}) .Expected({{0, 2, 80.0}, {0, 4, 85.0}}), NumericParams() .Direction(numeric::Direction::decreasing) .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {1, 3, 99.0}, {1, 4, 88.0}}) .Expected({{0, 2, 80.0}, {1, 4, 88.0}}), NumericParams() .Direction(numeric::Direction::either) .Updates({{0, 1, 98.0}, {0, 2, 91.0}}) .Expected({}), NumericParams() .Direction(numeric::Direction::either) .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {0, 3, 85.0}, {0, 4, 91.0}}) .Expected({{0, 2, 80.0}, {0, 4, 91.0}}), NumericParams() .Direction(numeric::Direction::either) .Updates({{0, 1, 100.0}, {1, 2, 80.0}, {0, 3, 85.0}, {1, 4, 91.0}}) .Expected({{0, 3, 85.0}, {1, 4, 91.0}}))); TEST_P(TestNumericThresholdWithDwellTime, senorsIsUpdatedMultipleTimesSleepAfterEveryUpdate) { InSequence seq; for (const auto& [index, timestamp, value] : GetParam().expected) { EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value)); } sut->initialize(); for (const auto& [index, timestamp, value] : GetParam().updates) { sut->sensorUpdated(*sensorMocks[index], timestamp, value); sleep(); } } class TestNumericThresholdWithDwellTime2 : public TestNumericThreshold, public WithParamInterface { public: void SetUp() override { makeThreshold(2ms, GetParam().direction, 90.0); } void sleep() { DbusEnvironment::sleepFor(4ms); } }; INSTANTIATE_TEST_SUITE_P( _, TestNumericThresholdWithDwellTime2, Values( NumericParams() .Direction(numeric::Direction::increasing) .Updates({{0, 1, 80.0}, {0, 2, 89.0}}) .Expected({}), NumericParams() .Direction(numeric::Direction::increasing) .Updates({{0, 1, 80.0}, {0, 2, 91.0}}) .Expected({{0, 2, 91.0}}), NumericParams() .Direction(numeric::Direction::increasing) .Updates({{0, 1, 80.0}, {0, 2, 99.0}, {0, 3, 80.0}, {0, 4, 98.0}}) .Expected({{0, 4, 98.0}}), NumericParams() .Direction(numeric::Direction::increasing) .Updates({{0, 1, 80.0}, {1, 2, 99.0}, {0, 3, 100.0}, {1, 4, 98.0}}) .Expected({{0, 3, 100.0}}), NumericParams() .Direction(numeric::Direction::decreasing) .Updates({{0, 1, 100.0}, {0, 2, 91.0}}) .Expected({}), NumericParams() .Direction(numeric::Direction::decreasing) .Updates({{0, 1, 100.0}, {0, 2, 80.0}}) .Expected({{0, 2, 80.0}}), NumericParams() .Direction(numeric::Direction::decreasing) .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {0, 3, 99.0}, {0, 4, 85.0}}) .Expected({{0, 4, 85.0}}), NumericParams() .Direction(numeric::Direction::decreasing) .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {1, 3, 99.0}, {1, 4, 88.0}}) .Expected({{0, 2, 80.0}, {1, 4, 88.0}}), NumericParams() .Direction(numeric::Direction::either) .Updates({{0, 1, 98.0}, {0, 2, 91.0}}) .Expected({}), NumericParams() .Direction(numeric::Direction::either) .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {0, 3, 85.0}, {0, 4, 91.0}}) .Expected({{0, 4, 91.0}}), NumericParams() .Direction(numeric::Direction::either) .Updates({{0, 1, 100.0}, {1, 2, 80.0}, {0, 3, 85.0}, {1, 4, 91.0}}) .Expected({{0, 3, 85.0}, {1, 4, 91.0}}))); TEST_P(TestNumericThresholdWithDwellTime2, senorsIsUpdatedMultipleTimesSleepAfterLastUpdate) { InSequence seq; for (const auto& [index, timestamp, value] : GetParam().expected) { EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value)); } sut->initialize(); for (const auto& [index, timestamp, value] : GetParam().updates) { sut->sensorUpdated(*sensorMocks[index], timestamp, value); } sleep(); }