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 static std::unique_ptr<stubs::DbusSensorObject> makeSensorObject() 38 { 39 return std::make_unique<stubs::DbusSensorObject>( 40 DbusEnvironment::getIoc(), DbusEnvironment::getBus(), 41 DbusEnvironment::getObjServer()); 42 } 43 44 std::unique_ptr<stubs::DbusSensorObject> sensorObject = makeSensorObject(); 45 46 SensorCache sensorCache; 47 uint64_t timestamp = std::time(0); 48 std::shared_ptr<Sensor> sut = sensorCache.makeSensor<Sensor>( 49 DbusEnvironment::serviceName(), sensorObject->path(), 50 DbusEnvironment::getIoc(), DbusEnvironment::getBus()); 51 std::shared_ptr<SensorListenerMock> listenerMock = 52 std::make_shared<StrictMock<SensorListenerMock>>(); 53 std::shared_ptr<SensorListenerMock> listenerMock2 = 54 std::make_shared<StrictMock<SensorListenerMock>>(); 55 MockFunction<void()> checkPoint; 56 }; 57 58 TEST_F(TestSensor, createsCorretlyViaSensorCache) 59 { 60 ASSERT_THAT(sut->id(), 61 Eq(Sensor::Id("Sensor", DbusEnvironment::serviceName(), 62 sensorObject->path()))); 63 } 64 65 TEST_F(TestSensor, notifiesWithValueAfterRegister) 66 { 67 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 68 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("async_read"))); 69 70 registerForUpdates(listenerMock); 71 72 ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read")); 73 } 74 75 TEST_F(TestSensor, notifiesOnceWithValueAfterRegister) 76 { 77 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 78 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("async_read"))); 79 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 80 .WillOnce( 81 InvokeWithoutArgs(DbusEnvironment::setPromise("async_read2"))); 82 83 DbusEnvironment::synchronizedPost([this] { 84 sut->registerForUpdates(listenerMock); 85 sut->registerForUpdates(listenerMock2); 86 }); 87 88 ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read")); 89 ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read2")); 90 } 91 92 class TestSensorNotification : public TestSensor 93 { 94 public: 95 void SetUp() override 96 { 97 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)) 98 .WillOnce( 99 InvokeWithoutArgs(DbusEnvironment::setPromise("async_read"))); 100 101 registerForUpdates(listenerMock); 102 103 ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read")); 104 } 105 106 std::shared_ptr<SensorListenerMock> listenerMock2 = 107 std::make_shared<StrictMock<SensorListenerMock>>(); 108 }; 109 110 TEST_F(TestSensorNotification, notifiesListenerWithValueWhenChangeOccurs) 111 { 112 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 113 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); 114 115 sensorObject->setValue(42.7); 116 117 ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); 118 } 119 120 TEST_F(TestSensorNotification, notifiesListenerWithValueWhenNoChangeOccurs) 121 { 122 InSequence seq; 123 124 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)); 125 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp))) 126 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); 127 128 sensorObject->setValue(42.7); 129 sensorObject->setValue(42.7); 130 131 ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); 132 } 133 134 TEST_F(TestSensorNotification, doesntNotifyExpiredListener) 135 { 136 InSequence seq; 137 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)); 138 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 139 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); 140 141 registerForUpdates(listenerMock2); 142 listenerMock = nullptr; 143 144 sensorObject->setValue(42.7); 145 146 ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); 147 } 148 149 TEST_F(TestSensorNotification, notifiesWithValueDuringRegister) 150 { 151 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)); 152 153 registerForUpdates(listenerMock2); 154 } 155 156 TEST_F(TestSensorNotification, 157 dbusSensorIsAddedToSystemAfterSensorIsCreatedThenValueIsUpdated) 158 { 159 InSequence seq; 160 161 EXPECT_CALL(*listenerMock, 162 sensorUpdated(Ref(*sut), Ge(timestamp), DoubleEq(42.7))) 163 .WillOnce( 164 InvokeWithoutArgs(DbusEnvironment::setPromise("notify-change"))); 165 EXPECT_CALL(checkPoint, Call()); 166 EXPECT_CALL(*listenerMock, 167 sensorUpdated(Ref(*sut), Ge(timestamp), DoubleEq(0.))) 168 .WillOnce( 169 InvokeWithoutArgs(DbusEnvironment::setPromise("notify-create"))); 170 171 sensorObject->setValue(42.7); 172 DbusEnvironment::waitForFuture("notify-change"); 173 174 checkPoint.Call(); 175 176 sensorObject = nullptr; 177 sensorObject = makeSensorObject(); 178 DbusEnvironment::waitForFuture("notify-create"); 179 } 180