xref: /openbmc/telemetry/tests/src/test_sensor.cpp (revision 51f0fd501f4b772533271d15cb27d396186a7192)
1 #include "dbus_environment.hpp"
2 #include "helpers.hpp"
3 #include "mocks/sensor_listener_mock.hpp"
4 #include "sensor.hpp"
5 #include "sensor_cache.hpp"
6 #include "stubs/dbus_sensor_object.hpp"
7 #include "utils/clock.hpp"
8 
9 #include <sdbusplus/asio/property.hpp>
10 
11 #include <thread>
12 
13 #include <gmock/gmock.h>
14 
15 using namespace testing;
16 using namespace std::chrono_literals;
17 
18 class TestSensor : public Test
19 {
20   public:
21     void SetUp() override
22     {
23         sensorObject->setValue(42.7);
24     }
25 
26     void TearDown() override
27     {
28         DbusEnvironment::synchronizeIoc();
29     }
30 
31     void
32         registerForUpdates(std::shared_ptr<interfaces::SensorListener> listener)
33     {
34         sut->registerForUpdates(listener);
35         DbusEnvironment::synchronizeIoc();
36     }
37 
38     void unregisterFromUpdates(
39         std::shared_ptr<interfaces::SensorListener> listener)
40     {
41         sut->unregisterFromUpdates(listener);
42         DbusEnvironment::synchronizeIoc();
43     }
44 
45     static std::unique_ptr<stubs::DbusSensorObject> makeSensorObject()
46     {
47         return std::make_unique<stubs::DbusSensorObject>(
48             DbusEnvironment::getIoc(), DbusEnvironment::getBus(),
49             DbusEnvironment::getObjServer());
50     }
51 
52     std::unique_ptr<stubs::DbusSensorObject> sensorObject = makeSensorObject();
53 
54     SensorCache sensorCache;
55     Milliseconds timestamp = Clock().steadyTimestamp();
56     std::shared_ptr<Sensor> sut = sensorCache.makeSensor<Sensor>(
57         DbusEnvironment::serviceName(), sensorObject->path(), "metadata",
58         DbusEnvironment::getIoc(), DbusEnvironment::getBus());
59     std::shared_ptr<SensorListenerMock> listenerMock =
60         std::make_shared<StrictMock<SensorListenerMock>>();
61     std::shared_ptr<SensorListenerMock> listenerMock2 =
62         std::make_shared<StrictMock<SensorListenerMock>>();
63     MockFunction<void()> checkPoint;
64 };
65 
66 TEST_F(TestSensor, createsCorretlyViaSensorCache)
67 {
68     ASSERT_THAT(sut->id(),
69                 Eq(Sensor::Id("Sensor", DbusEnvironment::serviceName(),
70                               sensorObject->path())));
71 }
72 
73 TEST_F(TestSensor, notifiesWithValueAfterRegister)
74 {
75     EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
76         .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("async_read")));
77 
78     registerForUpdates(listenerMock);
79 
80     ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read"));
81 }
82 
83 TEST_F(TestSensor, notifiesOnceWithValueAfterRegister)
84 {
85     EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
86         .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("async_read")));
87     EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
88         .WillOnce(
89             InvokeWithoutArgs(DbusEnvironment::setPromise("async_read2")));
90 
91     DbusEnvironment::synchronizedPost([this] {
92         sut->registerForUpdates(listenerMock);
93         sut->registerForUpdates(listenerMock2);
94     });
95 
96     ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read"));
97     ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read2"));
98 }
99 
100 class TestSensorNotification : public TestSensor
101 {
102   public:
103     void SetUp() override
104     {
105         EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 0.))
106             .WillOnce(
107                 InvokeWithoutArgs(DbusEnvironment::setPromise("async_read")));
108 
109         registerForUpdates(listenerMock);
110 
111         ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read"));
112     }
113 
114     std::shared_ptr<SensorListenerMock> listenerMock2 =
115         std::make_shared<StrictMock<SensorListenerMock>>();
116 };
117 
118 TEST_F(TestSensorNotification, notifiesListenerWithValueWhenChangeOccurs)
119 {
120     EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
121         .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify")));
122 
123     sensorObject->setValue(42.7);
124 
125     ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
126 }
127 
128 TEST_F(TestSensorNotification, notifiesListenerWithValueWhenNoChangeOccurs)
129 {
130     InSequence seq;
131 
132     EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7));
133     EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp)))
134         .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify")));
135 
136     sensorObject->setValue(42.7);
137     sensorObject->setValue(42.7);
138 
139     ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
140 }
141 
142 TEST_F(TestSensorNotification, doesntNotifyExpiredListener)
143 {
144     InSequence seq;
145     EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.));
146     EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
147         .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify")));
148 
149     registerForUpdates(listenerMock2);
150     listenerMock = nullptr;
151 
152     sensorObject->setValue(42.7);
153 
154     ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
155 }
156 
157 TEST_F(TestSensorNotification, notifiesWithValueDuringRegister)
158 {
159     EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.));
160 
161     registerForUpdates(listenerMock2);
162 }
163 
164 TEST_F(TestSensorNotification, notNotifiesWithValueWhenUnregistered)
165 {
166     EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.));
167     EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
168         .Times(0);
169     EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
170         .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify")));
171 
172     registerForUpdates(listenerMock2);
173     unregisterFromUpdates(listenerMock);
174 
175     sensorObject->setValue(42.7);
176 
177     ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
178 }
179 
180 TEST_F(TestSensorNotification,
181        dbusSensorIsAddedToSystemAfterSensorIsCreatedThenValueIsUpdated)
182 {
183     InSequence seq;
184 
185     EXPECT_CALL(*listenerMock,
186                 sensorUpdated(Ref(*sut), Ge(timestamp), DoubleEq(42.7)))
187         .WillOnce(
188             InvokeWithoutArgs(DbusEnvironment::setPromise("notify-change")));
189     EXPECT_CALL(checkPoint, Call());
190     EXPECT_CALL(*listenerMock,
191                 sensorUpdated(Ref(*sut), Ge(timestamp), DoubleEq(0.)))
192         .WillOnce(
193             InvokeWithoutArgs(DbusEnvironment::setPromise("notify-create")));
194 
195     sensorObject->setValue(42.7);
196     DbusEnvironment::waitForFuture("notify-change");
197 
198     checkPoint.Call();
199 
200     sensorObject = nullptr;
201     sensorObject = makeSensorObject();
202     DbusEnvironment::waitForFuture("notify-create");
203 }
204