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 
30*94f71c51SSzymon Dompke         for (size_t idx = 0; idx < sensorMocks.size(); idx++)
31*94f71c51SSzymon Dompke         {
32*94f71c51SSzymon Dompke             ON_CALL(*sensorMocks.at(idx), getName())
33*94f71c51SSzymon Dompke                 .WillByDefault(Return(sensorNames[idx]));
34*94f71c51SSzymon Dompke         }
35*94f71c51SSzymon Dompke 
36f763c9e3SSzymon Dompke         sut = std::make_shared<OnChangeThreshold>(
37f763c9e3SSzymon Dompke             utils::convContainer<std::shared_ptr<interfaces::Sensor>>(
38f763c9e3SSzymon Dompke                 sensorMocks),
39*94f71c51SSzymon Dompke             std::move(actions));
40f763c9e3SSzymon Dompke     }
41f763c9e3SSzymon Dompke };
42f763c9e3SSzymon Dompke 
43f763c9e3SSzymon Dompke TEST_F(TestOnChangeThreshold, initializeThresholdExpectAllSensorsAreRegistered)
44f763c9e3SSzymon Dompke {
45f763c9e3SSzymon Dompke     for (auto& sensor : sensorMocks)
46f763c9e3SSzymon Dompke     {
47f763c9e3SSzymon Dompke         EXPECT_CALL(*sensor,
48f763c9e3SSzymon Dompke                     registerForUpdates(Truly([sut = sut.get()](const auto& x) {
49f763c9e3SSzymon Dompke                         return x.lock().get() == sut;
50f763c9e3SSzymon Dompke                     })));
51f763c9e3SSzymon Dompke     }
52f763c9e3SSzymon Dompke 
53f763c9e3SSzymon Dompke     sut->initialize();
54f763c9e3SSzymon Dompke }
55f763c9e3SSzymon Dompke 
56f763c9e3SSzymon Dompke TEST_F(TestOnChangeThreshold, thresholdIsNotInitializeExpectNoActionCommit)
57f763c9e3SSzymon Dompke {
58f763c9e3SSzymon Dompke     EXPECT_CALL(actionMock, commit(_, _, _)).Times(0);
59f763c9e3SSzymon Dompke }
60f763c9e3SSzymon Dompke 
61*94f71c51SSzymon Dompke TEST_F(TestOnChangeThreshold, getLabeledParamsReturnsCorrectly)
62*94f71c51SSzymon Dompke {
63*94f71c51SSzymon Dompke     LabeledThresholdParam expected = std::monostate();
64*94f71c51SSzymon Dompke     EXPECT_EQ(sut->getThresholdParam(), expected);
65*94f71c51SSzymon Dompke }
66*94f71c51SSzymon Dompke 
67f763c9e3SSzymon Dompke struct OnChangeParams
68f763c9e3SSzymon Dompke {
6951f0fd50SKrzysztof Grobelny     using UpdateParams = std::tuple<size_t, Milliseconds, double>;
7051f0fd50SKrzysztof Grobelny     using ExpectedParams = std::tuple<size_t, Milliseconds, double>;
71f763c9e3SSzymon Dompke 
72f763c9e3SSzymon Dompke     OnChangeParams& Updates(std::vector<UpdateParams> val)
73f763c9e3SSzymon Dompke     {
74f763c9e3SSzymon Dompke         updates = std::move(val);
75f763c9e3SSzymon Dompke         return *this;
76f763c9e3SSzymon Dompke     }
77f763c9e3SSzymon Dompke 
78f763c9e3SSzymon Dompke     OnChangeParams& Expected(std::vector<ExpectedParams> val)
79f763c9e3SSzymon Dompke     {
80f763c9e3SSzymon Dompke         expected = std::move(val);
81f763c9e3SSzymon Dompke         return *this;
82f763c9e3SSzymon Dompke     }
83f763c9e3SSzymon Dompke 
84f763c9e3SSzymon Dompke     friend void PrintTo(const OnChangeParams& o, std::ostream* os)
85f763c9e3SSzymon Dompke     {
86f763c9e3SSzymon Dompke         *os << "{ Updates: ";
87f763c9e3SSzymon Dompke         for (const auto& [index, timestamp, value] : o.updates)
88f763c9e3SSzymon Dompke         {
8951f0fd50SKrzysztof Grobelny             *os << "{ SensorIndex: " << index
9051f0fd50SKrzysztof Grobelny                 << ", Timestamp: " << timestamp.count() << ", Value: " << value
9151f0fd50SKrzysztof Grobelny                 << " }, ";
92f763c9e3SSzymon Dompke         }
93f763c9e3SSzymon Dompke         *os << "Expected: ";
94f763c9e3SSzymon Dompke         for (const auto& [index, timestamp, value] : o.expected)
95f763c9e3SSzymon Dompke         {
9651f0fd50SKrzysztof Grobelny             *os << "{ SensorIndex: " << index
9751f0fd50SKrzysztof Grobelny                 << ", Timestamp: " << timestamp.count() << ", Value: " << value
9851f0fd50SKrzysztof Grobelny                 << " }, ";
99f763c9e3SSzymon Dompke         }
100f763c9e3SSzymon Dompke         *os << " }";
101f763c9e3SSzymon Dompke     }
102f763c9e3SSzymon Dompke 
103f763c9e3SSzymon Dompke     std::vector<UpdateParams> updates;
104f763c9e3SSzymon Dompke     std::vector<ExpectedParams> expected;
105f763c9e3SSzymon Dompke };
106f763c9e3SSzymon Dompke 
107f763c9e3SSzymon Dompke class TestOnChangeThresholdUpdates :
108f763c9e3SSzymon Dompke     public TestOnChangeThreshold,
109f763c9e3SSzymon Dompke     public WithParamInterface<OnChangeParams>
110f763c9e3SSzymon Dompke {};
111f763c9e3SSzymon Dompke 
112f763c9e3SSzymon Dompke INSTANTIATE_TEST_SUITE_P(
113f763c9e3SSzymon Dompke     _, TestOnChangeThresholdUpdates,
114f763c9e3SSzymon Dompke     Values(
11551f0fd50SKrzysztof Grobelny         OnChangeParams().Updates({{0, 1ms, 80.0}}).Expected({{0, 1ms, 80.0}}),
116f763c9e3SSzymon Dompke         OnChangeParams()
11751f0fd50SKrzysztof Grobelny             .Updates({{0, 1ms, 80.0}, {1, 2ms, 81.0}})
11851f0fd50SKrzysztof Grobelny             .Expected({{0, 1ms, 80.0}, {1, 2ms, 81.0}}),
119f763c9e3SSzymon Dompke         OnChangeParams()
12051f0fd50SKrzysztof Grobelny             .Updates({{0, 1ms, 80.0}, {0, 2ms, 90.0}})
12151f0fd50SKrzysztof Grobelny             .Expected({{0, 1ms, 80.0}, {0, 2ms, 90.0}}),
122f763c9e3SSzymon Dompke         OnChangeParams()
12351f0fd50SKrzysztof Grobelny             .Updates({{0, 1ms, 80.0}, {1, 2ms, 90.0}, {0, 3ms, 90.0}})
12451f0fd50SKrzysztof Grobelny             .Expected({{0, 1ms, 80.0}, {1, 2ms, 90.0}, {0, 3ms, 90.0}}),
125f763c9e3SSzymon Dompke         OnChangeParams()
12651f0fd50SKrzysztof Grobelny             .Updates({{0, 1ms, 80.0},
12751f0fd50SKrzysztof Grobelny                       {1, 2ms, 80.0},
12851f0fd50SKrzysztof Grobelny                       {1, 3ms, 90.0},
12951f0fd50SKrzysztof Grobelny                       {0, 4ms, 90.0}})
13051f0fd50SKrzysztof Grobelny             .Expected({{0, 1ms, 80.0},
13151f0fd50SKrzysztof Grobelny                        {1, 2ms, 80.0},
13251f0fd50SKrzysztof Grobelny                        {1, 3ms, 90.0},
13351f0fd50SKrzysztof Grobelny                        {0, 4ms, 90.0}})));
134f763c9e3SSzymon Dompke 
135f763c9e3SSzymon Dompke TEST_P(TestOnChangeThresholdUpdates, senorsIsUpdatedMultipleTimes)
136f763c9e3SSzymon Dompke {
137f763c9e3SSzymon Dompke     InSequence seq;
138f763c9e3SSzymon Dompke     for (const auto& [index, timestamp, value] : GetParam().expected)
139f763c9e3SSzymon Dompke     {
140f763c9e3SSzymon Dompke         EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value));
141f763c9e3SSzymon Dompke     }
142f763c9e3SSzymon Dompke 
143f763c9e3SSzymon Dompke     sut->initialize();
144f763c9e3SSzymon Dompke     for (const auto& [index, timestamp, value] : GetParam().updates)
145f763c9e3SSzymon Dompke     {
146f763c9e3SSzymon Dompke         sut->sensorUpdated(*sensorMocks[index], timestamp, value);
147f763c9e3SSzymon Dompke     }
148f763c9e3SSzymon Dompke }
149