1 #include "dbus_environment.hpp" 2 #include "helpers.hpp" 3 #include "mocks/sensor_mock.hpp" 4 #include "mocks/trigger_action_mock.hpp" 5 #include "on_change_threshold.hpp" 6 #include "utils/conv_container.hpp" 7 8 #include <gmock/gmock.h> 9 10 using namespace testing; 11 using namespace std::chrono_literals; 12 13 class TestOnChangeThreshold : public Test 14 { 15 public: 16 std::vector<std::shared_ptr<SensorMock>> sensorMocks = { 17 std::make_shared<NiceMock<SensorMock>>(), 18 std::make_shared<NiceMock<SensorMock>>()}; 19 std::vector<std::string> sensorNames = {"Sensor1", "Sensor2"}; 20 std::unique_ptr<TriggerActionMock> actionMockPtr = 21 std::make_unique<StrictMock<TriggerActionMock>>(); 22 TriggerActionMock& actionMock = *actionMockPtr; 23 std::shared_ptr<OnChangeThreshold> sut; 24 25 void SetUp() override 26 { 27 std::vector<std::unique_ptr<interfaces::TriggerAction>> actions; 28 actions.push_back(std::move(actionMockPtr)); 29 30 for (size_t idx = 0; idx < sensorMocks.size(); idx++) 31 { 32 ON_CALL(*sensorMocks.at(idx), getName()) 33 .WillByDefault(Return(sensorNames[idx])); 34 } 35 36 sut = std::make_shared<OnChangeThreshold>( 37 utils::convContainer<std::shared_ptr<interfaces::Sensor>>( 38 sensorMocks), 39 std::move(actions)); 40 } 41 }; 42 43 TEST_F(TestOnChangeThreshold, initializeThresholdExpectAllSensorsAreRegistered) 44 { 45 for (auto& sensor : sensorMocks) 46 { 47 EXPECT_CALL(*sensor, 48 registerForUpdates(Truly([sut = sut.get()](const auto& x) { 49 return x.lock().get() == sut; 50 }))); 51 } 52 53 sut->initialize(); 54 } 55 56 TEST_F(TestOnChangeThreshold, thresholdIsNotInitializeExpectNoActionCommit) 57 { 58 EXPECT_CALL(actionMock, commit(_, _, _)).Times(0); 59 } 60 61 TEST_F(TestOnChangeThreshold, getLabeledParamsReturnsCorrectly) 62 { 63 LabeledThresholdParam expected = std::monostate(); 64 EXPECT_EQ(sut->getThresholdParam(), expected); 65 } 66 67 TEST_F(TestOnChangeThreshold, firstReadingDoesNoActionCommit) 68 { 69 EXPECT_CALL(actionMock, commit(_, _, _)).Times(0); 70 71 sut->initialize(); 72 sut->sensorUpdated(*sensorMocks.front(), 0ms, 42); 73 } 74 75 struct OnChangeParams 76 { 77 using UpdateParams = std::tuple<size_t, Milliseconds, double>; 78 using ExpectedParams = std::tuple<size_t, Milliseconds, double>; 79 80 OnChangeParams& Updates(std::vector<UpdateParams> val) 81 { 82 updates = std::move(val); 83 return *this; 84 } 85 86 OnChangeParams& Expected(std::vector<ExpectedParams> val) 87 { 88 expected = std::move(val); 89 return *this; 90 } 91 92 friend void PrintTo(const OnChangeParams& o, std::ostream* os) 93 { 94 *os << "{ Updates: "; 95 for (const auto& [index, timestamp, value] : o.updates) 96 { 97 *os << "{ SensorIndex: " << index 98 << ", Timestamp: " << timestamp.count() << ", Value: " << value 99 << " }, "; 100 } 101 *os << "Expected: "; 102 for (const auto& [index, timestamp, value] : o.expected) 103 { 104 *os << "{ SensorIndex: " << index 105 << ", Timestamp: " << timestamp.count() << ", Value: " << value 106 << " }, "; 107 } 108 *os << " }"; 109 } 110 111 std::vector<UpdateParams> updates; 112 std::vector<ExpectedParams> expected; 113 }; 114 115 class TestOnChangeThresholdUpdates : 116 public TestOnChangeThreshold, 117 public WithParamInterface<OnChangeParams> 118 {}; 119 120 INSTANTIATE_TEST_SUITE_P( 121 _, TestOnChangeThresholdUpdates, 122 Values( 123 OnChangeParams().Updates({{0, 1ms, 80.0}}).Expected({{0, 1ms, 80.0}}), 124 OnChangeParams() 125 .Updates({{0, 1ms, 80.0}, {1, 2ms, 81.0}}) 126 .Expected({{0, 1ms, 80.0}, {1, 2ms, 81.0}}), 127 OnChangeParams() 128 .Updates({{0, 1ms, 80.0}, {0, 2ms, 90.0}}) 129 .Expected({{0, 1ms, 80.0}, {0, 2ms, 90.0}}), 130 OnChangeParams() 131 .Updates({{0, 1ms, 80.0}, {1, 2ms, 90.0}, {0, 3ms, 90.0}}) 132 .Expected({{0, 1ms, 80.0}, {1, 2ms, 90.0}, {0, 3ms, 90.0}}), 133 OnChangeParams() 134 .Updates({{0, 1ms, 80.0}, 135 {1, 2ms, 80.0}, 136 {1, 3ms, 90.0}, 137 {0, 4ms, 90.0}}) 138 .Expected({{0, 1ms, 80.0}, 139 {1, 2ms, 80.0}, 140 {1, 3ms, 90.0}, 141 {0, 4ms, 90.0}}))); 142 143 TEST_P(TestOnChangeThresholdUpdates, senorsIsUpdatedMultipleTimes) 144 { 145 InSequence seq; 146 for (const auto& [index, timestamp, value] : GetParam().expected) 147 { 148 EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value)); 149 } 150 151 sut->initialize(); 152 153 // First reading will be skipped 154 sut->sensorUpdated(*sensorMocks.front(), 0ms, 42); 155 156 for (const auto& [index, timestamp, value] : GetParam().updates) 157 { 158 sut->sensorUpdated(*sensorMocks[index], timestamp, value); 159 } 160 } 161