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