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