xref: /openbmc/telemetry/tests/src/test_discrete_threshold.cpp (revision 583ba441654657bb4ba9d051b747144a7258c159)
1f763c9e3SSzymon Dompke #include "dbus_environment.hpp"
2f763c9e3SSzymon Dompke #include "discrete_threshold.hpp"
3f763c9e3SSzymon Dompke #include "helpers.hpp"
4b7b7e1b6SSzymon Dompke #include "mocks/clock_mock.hpp"
5f763c9e3SSzymon Dompke #include "mocks/sensor_mock.hpp"
6f763c9e3SSzymon Dompke #include "mocks/trigger_action_mock.hpp"
751f0fd50SKrzysztof Grobelny #include "types/duration_types.hpp"
8f763c9e3SSzymon Dompke #include "utils/conv_container.hpp"
9f763c9e3SSzymon Dompke 
10f763c9e3SSzymon Dompke #include <gmock/gmock.h>
11f763c9e3SSzymon Dompke 
12f763c9e3SSzymon Dompke using namespace testing;
13f763c9e3SSzymon Dompke using namespace std::chrono_literals;
14f763c9e3SSzymon Dompke 
15f763c9e3SSzymon Dompke class TestDiscreteThreshold : public Test
16f763c9e3SSzymon Dompke {
17f763c9e3SSzymon Dompke   public:
18f763c9e3SSzymon Dompke     std::vector<std::shared_ptr<SensorMock>> sensorMocks = {
19f763c9e3SSzymon Dompke         std::make_shared<NiceMock<SensorMock>>(),
20f763c9e3SSzymon Dompke         std::make_shared<NiceMock<SensorMock>>()};
21f763c9e3SSzymon Dompke     std::vector<std::string> sensorNames = {"Sensor1", "Sensor2"};
22f763c9e3SSzymon Dompke     std::unique_ptr<TriggerActionMock> actionMockPtr =
23f763c9e3SSzymon Dompke         std::make_unique<StrictMock<TriggerActionMock>>();
24f763c9e3SSzymon Dompke     TriggerActionMock& actionMock = *actionMockPtr;
25f763c9e3SSzymon Dompke     std::shared_ptr<DiscreteThreshold> sut;
26b7b7e1b6SSzymon Dompke     std::string triggerId = "MyTrigger";
27b7b7e1b6SSzymon Dompke     std::unique_ptr<NiceMock<ClockMock>> clockMockPtr =
28b7b7e1b6SSzymon Dompke         std::make_unique<NiceMock<ClockMock>>();
29f763c9e3SSzymon Dompke 
makeThreshold(Milliseconds dwellTime,std::string thresholdValue,discrete::Severity severity=discrete::Severity::ok,std::string thresholdName="treshold name")30*583ba441SPatrick Williams     std::shared_ptr<DiscreteThreshold> makeThreshold(
31*583ba441SPatrick Williams         Milliseconds dwellTime, std::string thresholdValue,
32b7b7e1b6SSzymon Dompke         discrete::Severity severity = discrete::Severity::ok,
33b7b7e1b6SSzymon Dompke         std::string thresholdName = "treshold name")
34f763c9e3SSzymon Dompke     {
35f763c9e3SSzymon Dompke         std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
36f763c9e3SSzymon Dompke         actions.push_back(std::move(actionMockPtr));
37f763c9e3SSzymon Dompke 
38f763c9e3SSzymon Dompke         return std::make_shared<DiscreteThreshold>(
39b7b7e1b6SSzymon Dompke             DbusEnvironment::getIoc(), triggerId,
40f763c9e3SSzymon Dompke             utils::convContainer<std::shared_ptr<interfaces::Sensor>>(
41f763c9e3SSzymon Dompke                 sensorMocks),
42b7b7e1b6SSzymon Dompke             std::move(actions), dwellTime, thresholdValue, thresholdName,
43b7b7e1b6SSzymon Dompke             severity, std::move(clockMockPtr));
44f763c9e3SSzymon Dompke     }
45f763c9e3SSzymon Dompke 
SetUp()46f763c9e3SSzymon Dompke     void SetUp() override
47f763c9e3SSzymon Dompke     {
4894f71c51SSzymon Dompke         for (size_t idx = 0; idx < sensorMocks.size(); idx++)
4994f71c51SSzymon Dompke         {
5094f71c51SSzymon Dompke             ON_CALL(*sensorMocks.at(idx), getName())
5194f71c51SSzymon Dompke                 .WillByDefault(Return(sensorNames[idx]));
5294f71c51SSzymon Dompke         }
5394f71c51SSzymon Dompke 
54aa572361SSzymon Dompke         sut = makeThreshold(0ms, "90.0", discrete::Severity::critical);
55f763c9e3SSzymon Dompke     }
56f763c9e3SSzymon Dompke };
57f763c9e3SSzymon Dompke 
TEST_F(TestDiscreteThreshold,initializeThresholdExpectAllSensorsAreRegistered)58f763c9e3SSzymon Dompke TEST_F(TestDiscreteThreshold, initializeThresholdExpectAllSensorsAreRegistered)
59f763c9e3SSzymon Dompke {
60f763c9e3SSzymon Dompke     for (auto& sensor : sensorMocks)
61f763c9e3SSzymon Dompke     {
62f763c9e3SSzymon Dompke         EXPECT_CALL(*sensor,
63f763c9e3SSzymon Dompke                     registerForUpdates(Truly([sut = sut.get()](const auto& x) {
64f763c9e3SSzymon Dompke                         return x.lock().get() == sut;
65f763c9e3SSzymon Dompke                     })));
66f763c9e3SSzymon Dompke     }
67f763c9e3SSzymon Dompke 
68f763c9e3SSzymon Dompke     sut->initialize();
69f763c9e3SSzymon Dompke }
70f763c9e3SSzymon Dompke 
TEST_F(TestDiscreteThreshold,thresholdIsNotInitializeExpectNoActionCommit)71f763c9e3SSzymon Dompke TEST_F(TestDiscreteThreshold, thresholdIsNotInitializeExpectNoActionCommit)
72f763c9e3SSzymon Dompke {
73b7b7e1b6SSzymon Dompke     EXPECT_CALL(actionMock, commit(_, _, _, _, _)).Times(0);
74f763c9e3SSzymon Dompke }
75f763c9e3SSzymon Dompke 
76aa572361SSzymon Dompke class TestDiscreteThresholdValues :
77aa572361SSzymon Dompke     public TestDiscreteThreshold,
78aa572361SSzymon Dompke     public WithParamInterface<std::string>
79aa572361SSzymon Dompke {};
80aa572361SSzymon Dompke 
81aa572361SSzymon Dompke INSTANTIATE_TEST_SUITE_P(_, TestDiscreteThresholdValues,
82aa572361SSzymon Dompke                          Values("90", ".90", "90.123", "0.0"));
83aa572361SSzymon Dompke 
TEST_P(TestDiscreteThresholdValues,thresholdValueIsNumericAndStoredCorrectly)84aa572361SSzymon Dompke TEST_P(TestDiscreteThresholdValues, thresholdValueIsNumericAndStoredCorrectly)
8594f71c51SSzymon Dompke {
86aa572361SSzymon Dompke     sut = makeThreshold(0ms, GetParam(), discrete::Severity::critical);
8794f71c51SSzymon Dompke     LabeledThresholdParam expected = discrete::LabeledThresholdParam(
88aa572361SSzymon Dompke         "treshold name", discrete::Severity::critical, 0, GetParam());
8994f71c51SSzymon Dompke     EXPECT_EQ(sut->getThresholdParam(), expected);
9094f71c51SSzymon Dompke }
9194f71c51SSzymon Dompke 
92aa572361SSzymon Dompke class TestBadDiscreteThresholdValues :
93aa572361SSzymon Dompke     public TestDiscreteThreshold,
94aa572361SSzymon Dompke     public WithParamInterface<std::string>
95aa572361SSzymon Dompke {};
96aa572361SSzymon Dompke 
97aa572361SSzymon Dompke INSTANTIATE_TEST_SUITE_P(_, TestBadDiscreteThresholdValues,
98aa572361SSzymon Dompke                          Values("90ad", "ab.90", "x90", "On", "Off", ""));
99aa572361SSzymon Dompke 
TEST_P(TestBadDiscreteThresholdValues,throwsWhenNotNumericValues)100aa572361SSzymon Dompke TEST_P(TestBadDiscreteThresholdValues, throwsWhenNotNumericValues)
101aa572361SSzymon Dompke {
102aa572361SSzymon Dompke     EXPECT_THROW(makeThreshold(0ms, GetParam()), std::invalid_argument);
103aa572361SSzymon Dompke }
104aa572361SSzymon Dompke 
105b7b7e1b6SSzymon Dompke class TestDiscreteThresholdInit : public TestDiscreteThreshold
106b7b7e1b6SSzymon Dompke {
SetUp()1073a1c297aSPatrick Williams     void SetUp() override {}
108b7b7e1b6SSzymon Dompke };
109b7b7e1b6SSzymon Dompke 
TEST_F(TestDiscreteThresholdInit,nonEmptyNameIsNotChanged)110b7b7e1b6SSzymon Dompke TEST_F(TestDiscreteThresholdInit, nonEmptyNameIsNotChanged)
111b7b7e1b6SSzymon Dompke {
112b7b7e1b6SSzymon Dompke     auto sut = makeThreshold(0ms, "12.3", discrete::Severity::ok, "non-empty");
113b7b7e1b6SSzymon Dompke     EXPECT_THAT(
114b7b7e1b6SSzymon Dompke         std::get<discrete::LabeledThresholdParam>(sut->getThresholdParam())
115b7b7e1b6SSzymon Dompke             .at_label<utils::tstring::UserId>(),
116b7b7e1b6SSzymon Dompke         Eq("non-empty"));
117b7b7e1b6SSzymon Dompke }
118b7b7e1b6SSzymon Dompke 
TEST_F(TestDiscreteThresholdInit,emptyNameIsChanged)119b7b7e1b6SSzymon Dompke TEST_F(TestDiscreteThresholdInit, emptyNameIsChanged)
120b7b7e1b6SSzymon Dompke {
121b7b7e1b6SSzymon Dompke     auto sut = makeThreshold(0ms, "12.3", discrete::Severity::ok, "");
122b7b7e1b6SSzymon Dompke     EXPECT_THAT(
123b7b7e1b6SSzymon Dompke         std::get<discrete::LabeledThresholdParam>(sut->getThresholdParam())
124b7b7e1b6SSzymon Dompke             .at_label<utils::tstring::UserId>(),
125b7b7e1b6SSzymon Dompke         Not(Eq("")));
126b7b7e1b6SSzymon Dompke }
127b7b7e1b6SSzymon Dompke 
128f763c9e3SSzymon Dompke struct DiscreteParams
129f763c9e3SSzymon Dompke {
130f763c9e3SSzymon Dompke     struct UpdateParams
131f763c9e3SSzymon Dompke     {
132f763c9e3SSzymon Dompke         size_t sensor;
133f763c9e3SSzymon Dompke         double value;
134dcc4e193SKrzysztof Grobelny         Milliseconds sleepAfter;
135f763c9e3SSzymon Dompke 
UpdateParamsDiscreteParams::UpdateParams136b7b7e1b6SSzymon Dompke         UpdateParams(size_t sensor, double value,
137dcc4e193SKrzysztof Grobelny                      Milliseconds sleepAfter = 0ms) :
138f535cad6SPatrick Williams             sensor(sensor), value(value), sleepAfter(sleepAfter)
139f763c9e3SSzymon Dompke         {}
140f763c9e3SSzymon Dompke     };
141f763c9e3SSzymon Dompke 
142f763c9e3SSzymon Dompke     struct ExpectedParams
143f763c9e3SSzymon Dompke     {
144f763c9e3SSzymon Dompke         size_t sensor;
145f763c9e3SSzymon Dompke         double value;
146dcc4e193SKrzysztof Grobelny         Milliseconds waitMin;
147f763c9e3SSzymon Dompke 
ExpectedParamsDiscreteParams::ExpectedParams148b7b7e1b6SSzymon Dompke         ExpectedParams(size_t sensor, double value,
149dcc4e193SKrzysztof Grobelny                        Milliseconds waitMin = 0ms) :
150f535cad6SPatrick Williams             sensor(sensor), value(value), waitMin(waitMin)
151f763c9e3SSzymon Dompke         {}
152f763c9e3SSzymon Dompke     };
153f763c9e3SSzymon Dompke 
UpdatesDiscreteParams154f763c9e3SSzymon Dompke     DiscreteParams& Updates(std::vector<UpdateParams> val)
155f763c9e3SSzymon Dompke     {
156f763c9e3SSzymon Dompke         updates = std::move(val);
157f763c9e3SSzymon Dompke         return *this;
158f763c9e3SSzymon Dompke     }
159f763c9e3SSzymon Dompke 
ExpectedDiscreteParams160f763c9e3SSzymon Dompke     DiscreteParams& Expected(std::vector<ExpectedParams> val)
161f763c9e3SSzymon Dompke     {
162f763c9e3SSzymon Dompke         expected = std::move(val);
163f763c9e3SSzymon Dompke         return *this;
164f763c9e3SSzymon Dompke     }
165f763c9e3SSzymon Dompke 
ThresholdValueDiscreteParams166aa572361SSzymon Dompke     DiscreteParams& ThresholdValue(std::string val)
167f763c9e3SSzymon Dompke     {
168aa572361SSzymon Dompke         thresholdValue = std::move(val);
169f763c9e3SSzymon Dompke         return *this;
170f763c9e3SSzymon Dompke     }
171f763c9e3SSzymon Dompke 
DwellTimeDiscreteParams172dcc4e193SKrzysztof Grobelny     DiscreteParams& DwellTime(Milliseconds val)
173f763c9e3SSzymon Dompke     {
174f763c9e3SSzymon Dompke         dwellTime = std::move(val);
175f763c9e3SSzymon Dompke         return *this;
176f763c9e3SSzymon Dompke     }
177f763c9e3SSzymon Dompke 
PrintTo(const DiscreteParams & o,std::ostream * os)178f763c9e3SSzymon Dompke     friend void PrintTo(const DiscreteParams& o, std::ostream* os)
179f763c9e3SSzymon Dompke     {
180f763c9e3SSzymon Dompke         *os << "{ DwellTime: " << o.dwellTime.count() << "ms ";
181f763c9e3SSzymon Dompke         *os << ", ThresholdValue: " << o.thresholdValue;
182b7b7e1b6SSzymon Dompke         *os << ", Updates: [ ";
183b7b7e1b6SSzymon Dompke         for (const auto& [index, value, sleepAfter] : o.updates)
184f763c9e3SSzymon Dompke         {
185b7b7e1b6SSzymon Dompke             *os << "{ SensorIndex: " << index << ", Value: " << value
186f763c9e3SSzymon Dompke                 << ", SleepAfter: " << sleepAfter.count() << "ms }, ";
187f763c9e3SSzymon Dompke         }
188b7b7e1b6SSzymon Dompke         *os << " ] Expected: [ ";
189b7b7e1b6SSzymon Dompke         for (const auto& [index, value, waitMin] : o.expected)
190f763c9e3SSzymon Dompke         {
191b7b7e1b6SSzymon Dompke             *os << "{ SensorIndex: " << index << ", Value: " << value
19251f0fd50SKrzysztof Grobelny                 << ", waitMin: " << waitMin.count() << "ms }, ";
193f763c9e3SSzymon Dompke         }
194b7b7e1b6SSzymon Dompke         *os << " ] }";
195f763c9e3SSzymon Dompke     }
196f763c9e3SSzymon Dompke 
197f763c9e3SSzymon Dompke     std::vector<UpdateParams> updates;
198f763c9e3SSzymon Dompke     std::vector<ExpectedParams> expected;
199aa572361SSzymon Dompke     std::string thresholdValue = "0.0";
200dcc4e193SKrzysztof Grobelny     Milliseconds dwellTime = 0ms;
201f763c9e3SSzymon Dompke };
202f763c9e3SSzymon Dompke 
203f763c9e3SSzymon Dompke class TestDiscreteThresholdCommon :
204f763c9e3SSzymon Dompke     public TestDiscreteThreshold,
205f763c9e3SSzymon Dompke     public WithParamInterface<DiscreteParams>
206f763c9e3SSzymon Dompke {
207f763c9e3SSzymon Dompke   public:
sleep(Milliseconds duration)208dcc4e193SKrzysztof Grobelny     void sleep(Milliseconds duration)
209f763c9e3SSzymon Dompke     {
210f763c9e3SSzymon Dompke         if (duration != 0ms)
211f763c9e3SSzymon Dompke         {
212f763c9e3SSzymon Dompke             DbusEnvironment::sleepFor(duration);
213f763c9e3SSzymon Dompke         }
214f763c9e3SSzymon Dompke     }
215f763c9e3SSzymon Dompke 
testBodySensorIsUpdatedMultipleTimes()216f763c9e3SSzymon Dompke     void testBodySensorIsUpdatedMultipleTimes()
217f763c9e3SSzymon Dompke     {
218f763c9e3SSzymon Dompke         std::vector<std::chrono::time_point<std::chrono::high_resolution_clock>>
219f763c9e3SSzymon Dompke             timestamps(sensorMocks.size());
220f763c9e3SSzymon Dompke 
221f763c9e3SSzymon Dompke         sut->initialize();
222f763c9e3SSzymon Dompke 
223f763c9e3SSzymon Dompke         InSequence seq;
224f763c9e3SSzymon Dompke 
225b7b7e1b6SSzymon Dompke         for (const auto& [index, value, waitMin] : GetParam().expected)
226f763c9e3SSzymon Dompke         {
227f763c9e3SSzymon Dompke             EXPECT_CALL(actionMock,
228b7b7e1b6SSzymon Dompke                         commit(triggerId, Optional(StrEq("treshold name")),
229b7b7e1b6SSzymon Dompke                                sensorNames[index], _,
230b7b7e1b6SSzymon Dompke                                TriggerValue(GetParam().thresholdValue)))
231f763c9e3SSzymon Dompke                 .WillOnce(DoAll(
232f763c9e3SSzymon Dompke                     InvokeWithoutArgs([idx = index, &timestamps] {
233*583ba441SPatrick Williams                         timestamps[idx] =
234*583ba441SPatrick Williams                             std::chrono::high_resolution_clock::now();
235f763c9e3SSzymon Dompke                     }),
236f763c9e3SSzymon Dompke                     InvokeWithoutArgs(DbusEnvironment::setPromise("commit"))));
237f763c9e3SSzymon Dompke         }
238f763c9e3SSzymon Dompke 
239f763c9e3SSzymon Dompke         auto start = std::chrono::high_resolution_clock::now();
240f763c9e3SSzymon Dompke 
241b7b7e1b6SSzymon Dompke         for (const auto& [index, value, sleepAfter] : GetParam().updates)
242f763c9e3SSzymon Dompke         {
243b7b7e1b6SSzymon Dompke             sut->sensorUpdated(*sensorMocks[index], 42ms, value);
244f763c9e3SSzymon Dompke             sleep(sleepAfter);
245f763c9e3SSzymon Dompke         }
246f763c9e3SSzymon Dompke 
247f763c9e3SSzymon Dompke         EXPECT_THAT(DbusEnvironment::waitForFutures("commit"), true);
248b7b7e1b6SSzymon Dompke         for (const auto& [index, value, waitMin] : GetParam().expected)
249f763c9e3SSzymon Dompke         {
250f763c9e3SSzymon Dompke             EXPECT_THAT(timestamps[index] - start, Ge(waitMin));
251f763c9e3SSzymon Dompke         }
252f763c9e3SSzymon Dompke     }
253f763c9e3SSzymon Dompke };
254f763c9e3SSzymon Dompke 
255f763c9e3SSzymon Dompke class TestDiscreteThresholdNoDwellTime : public TestDiscreteThresholdCommon
256f763c9e3SSzymon Dompke {
257f763c9e3SSzymon Dompke   public:
SetUp()258f763c9e3SSzymon Dompke     void SetUp() override
259f763c9e3SSzymon Dompke     {
26094f71c51SSzymon Dompke         for (size_t idx = 0; idx < sensorMocks.size(); idx++)
26194f71c51SSzymon Dompke         {
26294f71c51SSzymon Dompke             ON_CALL(*sensorMocks.at(idx), getName())
26394f71c51SSzymon Dompke                 .WillByDefault(Return(sensorNames[idx]));
26494f71c51SSzymon Dompke         }
26594f71c51SSzymon Dompke 
266f763c9e3SSzymon Dompke         sut = makeThreshold(0ms, GetParam().thresholdValue);
267f763c9e3SSzymon Dompke     }
268f763c9e3SSzymon Dompke };
269f763c9e3SSzymon Dompke 
270b7b7e1b6SSzymon Dompke INSTANTIATE_TEST_SUITE_P(
271b7b7e1b6SSzymon Dompke     _, TestDiscreteThresholdNoDwellTime,
27251f0fd50SKrzysztof Grobelny     Values(DiscreteParams()
273aa572361SSzymon Dompke                .ThresholdValue("90.0")
274b7b7e1b6SSzymon Dompke                .Updates({{0, 80.0}, {0, 89.0}})
275f763c9e3SSzymon Dompke                .Expected({}),
276f763c9e3SSzymon Dompke            DiscreteParams()
277aa572361SSzymon Dompke                .ThresholdValue("90.0")
278b7b7e1b6SSzymon Dompke                .Updates({{0, 80.0}, {0, 90.0}, {0, 80.0}, {0, 90.0}})
279b7b7e1b6SSzymon Dompke                .Expected({{0, 90.0}, {0, 90.0}}),
280f763c9e3SSzymon Dompke            DiscreteParams()
281aa572361SSzymon Dompke                .ThresholdValue("90.0")
282b7b7e1b6SSzymon Dompke                .Updates({{0, 90.0}, {0, 99.0}, {1, 100.0}, {1, 90.0}})
283b7b7e1b6SSzymon Dompke                .Expected({{0, 90.0}, {1, 90.0}})));
284f763c9e3SSzymon Dompke 
TEST_P(TestDiscreteThresholdNoDwellTime,senorsIsUpdatedMultipleTimes)285f763c9e3SSzymon Dompke TEST_P(TestDiscreteThresholdNoDwellTime, senorsIsUpdatedMultipleTimes)
286f763c9e3SSzymon Dompke {
287f763c9e3SSzymon Dompke     testBodySensorIsUpdatedMultipleTimes();
288f763c9e3SSzymon Dompke }
289f763c9e3SSzymon Dompke 
290f763c9e3SSzymon Dompke class TestDiscreteThresholdWithDwellTime : public TestDiscreteThresholdCommon
291f763c9e3SSzymon Dompke {
292f763c9e3SSzymon Dompke   public:
SetUp()293f763c9e3SSzymon Dompke     void SetUp() override
294f763c9e3SSzymon Dompke     {
29594f71c51SSzymon Dompke         for (size_t idx = 0; idx < sensorMocks.size(); idx++)
29694f71c51SSzymon Dompke         {
29794f71c51SSzymon Dompke             ON_CALL(*sensorMocks.at(idx), getName())
29894f71c51SSzymon Dompke                 .WillByDefault(Return(sensorNames[idx]));
29994f71c51SSzymon Dompke         }
30094f71c51SSzymon Dompke 
301f763c9e3SSzymon Dompke         sut = makeThreshold(GetParam().dwellTime, GetParam().thresholdValue);
302f763c9e3SSzymon Dompke     }
303f763c9e3SSzymon Dompke };
304f763c9e3SSzymon Dompke 
305f763c9e3SSzymon Dompke INSTANTIATE_TEST_SUITE_P(
306f763c9e3SSzymon Dompke     _, TestDiscreteThresholdWithDwellTime,
307f763c9e3SSzymon Dompke     Values(DiscreteParams()
308f763c9e3SSzymon Dompke                .DwellTime(200ms)
309aa572361SSzymon Dompke                .ThresholdValue("90.0")
310b7b7e1b6SSzymon Dompke                .Updates({{0, 90.0, 100ms}, {0, 91.0}, {0, 90.0}})
311b7b7e1b6SSzymon Dompke                .Expected({{0, 90.0, 300ms}}),
312f763c9e3SSzymon Dompke            DiscreteParams()
313f763c9e3SSzymon Dompke                .DwellTime(100ms)
314aa572361SSzymon Dompke                .ThresholdValue("90.0")
315b7b7e1b6SSzymon Dompke                .Updates({{0, 90.0, 100ms}})
316b7b7e1b6SSzymon Dompke                .Expected({{0, 90.0, 100ms}}),
317f763c9e3SSzymon Dompke            DiscreteParams()
318f763c9e3SSzymon Dompke                .DwellTime(1000ms)
319aa572361SSzymon Dompke                .ThresholdValue("90.0")
320b7b7e1b6SSzymon Dompke                .Updates({{0, 90.0, 700ms},
321b7b7e1b6SSzymon Dompke                          {0, 91.0, 100ms},
322b7b7e1b6SSzymon Dompke                          {0, 90.0, 300ms},
323b7b7e1b6SSzymon Dompke                          {0, 91.0, 100ms}})
324f763c9e3SSzymon Dompke                .Expected({}),
325f763c9e3SSzymon Dompke            DiscreteParams()
326f763c9e3SSzymon Dompke                .DwellTime(200ms)
327aa572361SSzymon Dompke                .ThresholdValue("90.0")
328b7b7e1b6SSzymon Dompke                .Updates({{0, 90.0},
329b7b7e1b6SSzymon Dompke                          {1, 89.0, 100ms},
330b7b7e1b6SSzymon Dompke                          {1, 90.0, 100ms},
331b7b7e1b6SSzymon Dompke                          {1, 89.0, 100ms},
332b7b7e1b6SSzymon Dompke                          {1, 90.0, 300ms},
333b7b7e1b6SSzymon Dompke                          {1, 89.0, 100ms}})
334b7b7e1b6SSzymon Dompke                .Expected({{0, 90, 200ms}, {1, 90, 500ms}})));
335f763c9e3SSzymon Dompke 
TEST_P(TestDiscreteThresholdWithDwellTime,senorsIsUpdatedMultipleTimes)336f763c9e3SSzymon Dompke TEST_P(TestDiscreteThresholdWithDwellTime, senorsIsUpdatedMultipleTimes)
337f763c9e3SSzymon Dompke {
338f763c9e3SSzymon Dompke     testBodySensorIsUpdatedMultipleTimes();
339f763c9e3SSzymon Dompke }
340