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