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