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