xref: /openbmc/telemetry/tests/src/test_sensor.cpp (revision fbeb5bf4)
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 
115 TEST_F(TestSensorNotification, notifiesListenerWithValueWhenChangeOccurs)
116 {
117     EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
118         .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify")));
119 
120     sensorObject->setValue(42.7);
121 
122     ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
123 }
124 
125 TEST_F(TestSensorNotification, notifiesListenerWithValueWhenNoChangeOccurs)
126 {
127     InSequence seq;
128 
129     EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7));
130     EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp)))
131         .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify")));
132 
133     sensorObject->setValue(42.7);
134     sensorObject->setValue(42.7);
135 
136     ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
137 }
138 
139 TEST_F(TestSensorNotification, doesntNotifyExpiredListener)
140 {
141     InSequence seq;
142     EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.));
143     EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
144         .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify")));
145 
146     registerForUpdates(listenerMock2);
147     listenerMock = nullptr;
148 
149     sensorObject->setValue(42.7);
150 
151     ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
152 }
153 
154 TEST_F(TestSensorNotification, notifiesWithValueDuringRegister)
155 {
156     EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.));
157 
158     registerForUpdates(listenerMock2);
159 }
160 
161 TEST_F(TestSensorNotification, notNotifiesWithValueWhenUnregistered)
162 {
163     EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.));
164     EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
165         .Times(0);
166     EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
167         .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify")));
168 
169     registerForUpdates(listenerMock2);
170     unregisterFromUpdates(listenerMock);
171 
172     sensorObject->setValue(42.7);
173 
174     ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
175 }
176 
177 TEST_F(TestSensorNotification,
178        dbusSensorIsAddedToSystemAfterSensorIsCreatedThenValueIsUpdated)
179 {
180     InSequence seq;
181 
182     EXPECT_CALL(*listenerMock,
183                 sensorUpdated(Ref(*sut), Ge(timestamp), DoubleEq(42.7)))
184         .WillOnce(
185             InvokeWithoutArgs(DbusEnvironment::setPromise("notify-change")));
186     EXPECT_CALL(checkPoint, Call());
187     EXPECT_CALL(*listenerMock,
188                 sensorUpdated(Ref(*sut), Ge(timestamp), DoubleEq(0.)))
189         .WillOnce(
190             InvokeWithoutArgs(DbusEnvironment::setPromise("notify-create")));
191 
192     sensorObject->setValue(42.7);
193     DbusEnvironment::waitForFuture("notify-change");
194 
195     checkPoint.Call();
196 
197     sensorObject = nullptr;
198     sensorObject = makeSensorObject();
199     DbusEnvironment::waitForFuture("notify-create");
200 }
201