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