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, notifiesListenerWithValueWhenNoChangeOccurs) 151 { 152 InSequence seq; 153 154 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)); 155 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp))) 156 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); 157 158 sensorObject->setValue(42.7); 159 sensorObject->setValue(42.7); 160 161 ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); 162 } 163 164 TEST_F(TestSensorNotification, doesntNotifyExpiredListener) 165 { 166 InSequence seq; 167 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)); 168 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 169 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); 170 171 registerForUpdates(listenerMock2); 172 listenerMock = nullptr; 173 174 sensorObject->setValue(42.7); 175 176 ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); 177 } 178 179 TEST_F(TestSensorNotification, notifiesWithValueDuringRegister) 180 { 181 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)); 182 183 registerForUpdates(listenerMock2); 184 } 185 186 TEST_F(TestSensorNotification, notNotifiesWithValueWhenUnregistered) 187 { 188 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)); 189 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 190 .Times(0); 191 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 192 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); 193 194 registerForUpdates(listenerMock2); 195 unregisterFromUpdates(listenerMock); 196 197 sensorObject->setValue(42.7); 198 199 ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); 200 } 201 202 TEST_F(TestSensorNotification, 203 dbusSensorIsAddedToSystemAfterSensorIsCreatedThenValueIsUpdated) 204 { 205 InSequence seq; 206 207 EXPECT_CALL(*listenerMock, 208 sensorUpdated(Ref(*sut), Ge(timestamp), DoubleEq(42.7))) 209 .WillOnce( 210 InvokeWithoutArgs(DbusEnvironment::setPromise("notify-change"))); 211 EXPECT_CALL(checkPoint, Call()); 212 EXPECT_CALL(*listenerMock, 213 sensorUpdated(Ref(*sut), Ge(timestamp), DoubleEq(0.))) 214 .WillOnce( 215 InvokeWithoutArgs(DbusEnvironment::setPromise("notify-create"))); 216 217 sensorObject->setValue(42.7); 218 DbusEnvironment::waitForFuture("notify-change"); 219 220 checkPoint.Call(); 221 222 sensorObject = nullptr; 223 sensorObject = makeSensorObject(); 224 DbusEnvironment::waitForFuture("notify-create"); 225 } 226