xref: /openbmc/telemetry/tests/src/test_on_change_threshold.cpp (revision 36de0563f9f05dd325cf626ac18d0af1437fbab4)
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