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 8 #include <sdbusplus/asio/property.hpp> 9 10 #include <thread> 11 12 #include <gmock/gmock.h> 13 14 using namespace testing; 15 using namespace std::chrono_literals; 16 17 class TestSensor : public Test 18 { 19 public: 20 void SetUp() override 21 { 22 sensorObject->setValue(42.7); 23 } 24 25 void TearDown() override 26 { 27 DbusEnvironment::synchronizeIoc(); 28 } 29 30 void 31 registerForUpdates(std::shared_ptr<interfaces::SensorListener> listener) 32 { 33 sut->registerForUpdates(listener); 34 DbusEnvironment::synchronizeIoc(); 35 } 36 37 void unregisterFromUpdates( 38 std::shared_ptr<interfaces::SensorListener> listener) 39 { 40 sut->unregisterFromUpdates(listener); 41 DbusEnvironment::synchronizeIoc(); 42 } 43 44 static std::unique_ptr<stubs::DbusSensorObject> makeSensorObject() 45 { 46 return std::make_unique<stubs::DbusSensorObject>( 47 DbusEnvironment::getIoc(), DbusEnvironment::getBus(), 48 DbusEnvironment::getObjServer()); 49 } 50 51 std::unique_ptr<stubs::DbusSensorObject> sensorObject = makeSensorObject(); 52 53 SensorCache sensorCache; 54 uint64_t timestamp = std::time(0); 55 std::shared_ptr<Sensor> sut = sensorCache.makeSensor<Sensor>( 56 DbusEnvironment::serviceName(), sensorObject->path(), 57 DbusEnvironment::getIoc(), DbusEnvironment::getBus()); 58 std::shared_ptr<SensorListenerMock> listenerMock = 59 std::make_shared<StrictMock<SensorListenerMock>>(); 60 std::shared_ptr<SensorListenerMock> listenerMock2 = 61 std::make_shared<StrictMock<SensorListenerMock>>(); 62 MockFunction<void()> checkPoint; 63 }; 64 65 TEST_F(TestSensor, createsCorretlyViaSensorCache) 66 { 67 ASSERT_THAT(sut->id(), 68 Eq(Sensor::Id("Sensor", DbusEnvironment::serviceName(), 69 sensorObject->path()))); 70 } 71 72 TEST_F(TestSensor, notifiesWithValueAfterRegister) 73 { 74 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 75 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("async_read"))); 76 77 registerForUpdates(listenerMock); 78 79 ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read")); 80 } 81 82 TEST_F(TestSensor, notifiesOnceWithValueAfterRegister) 83 { 84 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 85 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("async_read"))); 86 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 87 .WillOnce( 88 InvokeWithoutArgs(DbusEnvironment::setPromise("async_read2"))); 89 90 DbusEnvironment::synchronizedPost([this] { 91 sut->registerForUpdates(listenerMock); 92 sut->registerForUpdates(listenerMock2); 93 }); 94 95 ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read")); 96 ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read2")); 97 } 98 99 class TestSensorNotification : public TestSensor 100 { 101 public: 102 void SetUp() override 103 { 104 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)) 105 .WillOnce( 106 InvokeWithoutArgs(DbusEnvironment::setPromise("async_read"))); 107 108 registerForUpdates(listenerMock); 109 110 ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read")); 111 } 112 113 std::shared_ptr<SensorListenerMock> listenerMock2 = 114 std::make_shared<StrictMock<SensorListenerMock>>(); 115 }; 116 117 TEST_F(TestSensorNotification, notifiesListenerWithValueWhenChangeOccurs) 118 { 119 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 120 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); 121 122 sensorObject->setValue(42.7); 123 124 ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); 125 } 126 127 TEST_F(TestSensorNotification, notifiesListenerWithValueWhenNoChangeOccurs) 128 { 129 InSequence seq; 130 131 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)); 132 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp))) 133 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); 134 135 sensorObject->setValue(42.7); 136 sensorObject->setValue(42.7); 137 138 ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); 139 } 140 141 TEST_F(TestSensorNotification, doesntNotifyExpiredListener) 142 { 143 InSequence seq; 144 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)); 145 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 146 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); 147 148 registerForUpdates(listenerMock2); 149 listenerMock = nullptr; 150 151 sensorObject->setValue(42.7); 152 153 ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); 154 } 155 156 TEST_F(TestSensorNotification, notifiesWithValueDuringRegister) 157 { 158 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)); 159 160 registerForUpdates(listenerMock2); 161 } 162 163 TEST_F(TestSensorNotification, notNotifiesWithValueWhenUnregistered) 164 { 165 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)); 166 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 167 .Times(0); 168 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 169 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); 170 171 registerForUpdates(listenerMock2); 172 unregisterFromUpdates(listenerMock); 173 174 sensorObject->setValue(42.7); 175 176 ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); 177 } 178 179 TEST_F(TestSensorNotification, 180 dbusSensorIsAddedToSystemAfterSensorIsCreatedThenValueIsUpdated) 181 { 182 InSequence seq; 183 184 EXPECT_CALL(*listenerMock, 185 sensorUpdated(Ref(*sut), Ge(timestamp), DoubleEq(42.7))) 186 .WillOnce( 187 InvokeWithoutArgs(DbusEnvironment::setPromise("notify-change"))); 188 EXPECT_CALL(checkPoint, Call()); 189 EXPECT_CALL(*listenerMock, 190 sensorUpdated(Ref(*sut), Ge(timestamp), DoubleEq(0.))) 191 .WillOnce( 192 InvokeWithoutArgs(DbusEnvironment::setPromise("notify-create"))); 193 194 sensorObject->setValue(42.7); 195 DbusEnvironment::waitForFuture("notify-change"); 196 197 checkPoint.Call(); 198 199 sensorObject = nullptr; 200 sensorObject = makeSensorObject(); 201 DbusEnvironment::waitForFuture("notify-create"); 202 } 203