xref: /openbmc/telemetry/tests/src/test_sensor.cpp (revision 1cdd7e4f)
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 TEST_F(TestSensor, getLabeledInfoReturnsCorrectly)
101 {
102     auto expected = LabeledSensorInfo(DbusEnvironment::serviceName(),
103                                       sensorObject->path(), "metadata");
104     EXPECT_EQ(sut->getLabeledSensorInfo(), expected);
105 }
106 
107 TEST_F(TestSensor, getNameReturnsPathWhenMetadataIsNotSet)
108 {
109     static const char* path = "/telemetry/ut/DbusSensorObject2";
110     sut = sensorCache.makeSensor<Sensor>(DbusEnvironment::serviceName(), path,
111                                          "", DbusEnvironment::getIoc(),
112                                          DbusEnvironment::getBus());
113     EXPECT_EQ(sut->getName(), path);
114 }
115 
116 TEST_F(TestSensor, getNameReturnsMetadataWhenMetadataIsSet)
117 {
118     static const char* path = "/telemetry/ut/DbusSensorObject2";
119     sut = sensorCache.makeSensor<Sensor>(DbusEnvironment::serviceName(), path,
120                                          "metadata2", DbusEnvironment::getIoc(),
121                                          DbusEnvironment::getBus());
122     EXPECT_EQ(sut->getName(), "metadata2");
123 }
124 
125 class TestSensorNotification : public TestSensor
126 {
127   public:
128     void SetUp() override
129     {
130         EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 0.))
131             .WillOnce(
132                 InvokeWithoutArgs(DbusEnvironment::setPromise("async_read")));
133 
134         registerForUpdates(listenerMock);
135 
136         ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read"));
137     }
138 };
139 
140 TEST_F(TestSensorNotification, notifiesListenerWithValueWhenChangeOccurs)
141 {
142     EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
143         .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify")));
144 
145     sensorObject->setValue(42.7);
146 
147     ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
148 }
149 
150 TEST_F(TestSensorNotification, doesntNotifyListenerWhenNoChangeOccurs)
151 {
152     EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
153         .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify")));
154 
155     sensorObject->setValue(42.7);
156     sensorObject->setValue(42.7);
157 
158     ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
159 }
160 
161 TEST_F(TestSensorNotification, doesntNotifyExpiredListener)
162 {
163     InSequence seq;
164     EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.));
165     EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
166         .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify")));
167 
168     registerForUpdates(listenerMock2);
169     listenerMock = nullptr;
170 
171     sensorObject->setValue(42.7);
172 
173     ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
174 }
175 
176 TEST_F(TestSensorNotification, notifiesWithValueDuringRegister)
177 {
178     EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.));
179 
180     registerForUpdates(listenerMock2);
181 }
182 
183 TEST_F(TestSensorNotification, notNotifiesWithValueWhenUnregistered)
184 {
185     EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.));
186     EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
187         .Times(0);
188     EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
189         .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify")));
190 
191     registerForUpdates(listenerMock2);
192     unregisterFromUpdates(listenerMock);
193 
194     sensorObject->setValue(42.7);
195 
196     ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
197 }
198 
199 TEST_F(TestSensorNotification,
200        dbusSensorIsAddedToSystemAfterSensorIsCreatedThenValueIsUpdated)
201 {
202     InSequence seq;
203 
204     EXPECT_CALL(*listenerMock,
205                 sensorUpdated(Ref(*sut), Ge(timestamp), DoubleEq(42.7)))
206         .WillOnce(
207             InvokeWithoutArgs(DbusEnvironment::setPromise("notify-change")));
208     EXPECT_CALL(checkPoint, Call());
209     EXPECT_CALL(*listenerMock,
210                 sensorUpdated(Ref(*sut), Ge(timestamp), DoubleEq(0.)))
211         .WillOnce(
212             InvokeWithoutArgs(DbusEnvironment::setPromise("notify-create")));
213 
214     sensorObject->setValue(42.7);
215     DbusEnvironment::waitForFuture("notify-change");
216 
217     checkPoint.Call();
218 
219     sensorObject = nullptr;
220     sensorObject = makeSensorObject();
221     DbusEnvironment::waitForFuture("notify-create");
222 }
223