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:
SetUp()21 void SetUp() override
22 {
23 sensorObject->setValue(42.7);
24 }
25
TearDown()26 void TearDown() override
27 {
28 DbusEnvironment::synchronizeIoc();
29 }
30
31 void
registerForUpdates(std::shared_ptr<interfaces::SensorListener> listener)32 registerForUpdates(std::shared_ptr<interfaces::SensorListener> listener)
33 {
34 sut->registerForUpdates(listener);
35 DbusEnvironment::synchronizeIoc();
36 }
37
unregisterFromUpdates(std::shared_ptr<interfaces::SensorListener> listener)38 void unregisterFromUpdates(
39 std::shared_ptr<interfaces::SensorListener> listener)
40 {
41 sut->unregisterFromUpdates(listener);
42 DbusEnvironment::synchronizeIoc();
43 }
44
makeSensorObject()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
TEST_F(TestSensor,createsCorretlyViaSensorCache)66 TEST_F(TestSensor, createsCorretlyViaSensorCache)
67 {
68 ASSERT_THAT(sut->id(),
69 Eq(Sensor::Id("Sensor", DbusEnvironment::serviceName(),
70 sensorObject->path())));
71 }
72
TEST_F(TestSensor,notifiesWithValueAfterRegister)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
TEST_F(TestSensor,notifiesOnceWithValueAfterRegister)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
TEST_F(TestSensor,getLabeledInfoReturnsCorrectly)100 TEST_F(TestSensor, getLabeledInfoReturnsCorrectly)
101 {
102 auto expected = LabeledSensorInfo(DbusEnvironment::serviceName(),
103 sensorObject->path(), "metadata");
104 EXPECT_EQ(sut->getLabeledSensorInfo(), expected);
105 }
106
TEST_F(TestSensor,getNameReturnsPathWhenMetadataIsNotSet)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
TEST_F(TestSensor,getNameReturnsMetadataWhenMetadataIsSet)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:
SetUp()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
TEST_F(TestSensorNotification,notifiesListenerWithValueWhenChangeOccurs)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
TEST_F(TestSensorNotification,doesntNotifyListenerWhenNoChangeOccurs)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
TEST_F(TestSensorNotification,doesntNotifyExpiredListener)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
TEST_F(TestSensorNotification,notifiesWithValueDuringRegister)176 TEST_F(TestSensorNotification, notifiesWithValueDuringRegister)
177 {
178 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.));
179
180 registerForUpdates(listenerMock2);
181 }
182
TEST_F(TestSensorNotification,notNotifiesWithValueWhenUnregistered)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
TEST_F(TestSensorNotification,dbusSensorIsAddedToSystemAfterSensorIsCreatedThenValueIsUpdated)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