1 #include "dbus_environment.hpp" 2 #include "mocks/sensor_listener_mock.hpp" 3 #include "sensor.hpp" 4 #include "sensor_cache.hpp" 5 #include "stubs/dbus_sensor_object.hpp" 6 #include "utils/sensor_id_eq.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 DbusEnvironment::synchronizedPost( 34 [this, listener] { sut->registerForUpdates(listener); }); 35 } 36 37 std::chrono::milliseconds notifiesInGivenIntervalAfterSchedule( 38 std::chrono::milliseconds interval); 39 40 stubs::DbusSensorObject sensorObject{DbusEnvironment::getIoc(), 41 DbusEnvironment::getBus(), 42 DbusEnvironment::getObjServer()}; 43 44 SensorCache sensorCache; 45 uint64_t timestamp = std::time(0); 46 std::shared_ptr<Sensor> sut = sensorCache.makeSensor<Sensor>( 47 DbusEnvironment::serviceName(), sensorObject.path(), 48 DbusEnvironment::getIoc(), DbusEnvironment::getBus()); 49 std::shared_ptr<SensorListenerMock> listenerMock = 50 std::make_shared<StrictMock<SensorListenerMock>>(); 51 std::shared_ptr<SensorListenerMock> listenerMock2 = 52 std::make_shared<StrictMock<SensorListenerMock>>(); 53 }; 54 55 TEST_F(TestSensor, createsCorretlyViaSensorCache) 56 { 57 ASSERT_THAT(sut->id(), 58 sensorIdEq(Sensor::Id("Sensor", DbusEnvironment::serviceName(), 59 sensorObject.path()))); 60 } 61 62 TEST_F(TestSensor, notifiesWithValueAfterRegister) 63 { 64 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 65 .WillOnce(Invoke(DbusEnvironment::setPromise("async_read"))); 66 67 registerForUpdates(listenerMock); 68 69 ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read")); 70 } 71 72 TEST_F(TestSensor, notifiesOnceWithValueAfterRegister) 73 { 74 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 75 .WillOnce(Invoke(DbusEnvironment::setPromise("async_read"))); 76 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 77 .WillOnce(Invoke(DbusEnvironment::setPromise("async_read2"))); 78 79 DbusEnvironment::synchronizedPost([this] { 80 sut->registerForUpdates(listenerMock); 81 sut->registerForUpdates(listenerMock2); 82 }); 83 84 ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read")); 85 ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read2")); 86 } 87 88 class TestSensorNotification : public TestSensor 89 { 90 public: 91 void SetUp() override 92 { 93 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)) 94 .WillOnce(Invoke(DbusEnvironment::setPromise("async_read"))); 95 96 registerForUpdates(listenerMock); 97 98 ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read")); 99 } 100 101 std::shared_ptr<SensorListenerMock> listenerMock2 = 102 std::make_shared<StrictMock<SensorListenerMock>>(); 103 }; 104 105 TEST_F(TestSensorNotification, notifiesListenerWithValueWhenChangeOccurs) 106 { 107 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 108 .WillOnce(Invoke(DbusEnvironment::setPromise("notify"))); 109 110 sensorObject.setValue(42.7); 111 112 ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); 113 } 114 115 TEST_F(TestSensorNotification, notifiesListenerWithValueWhenNoChangeOccurs) 116 { 117 Sequence seq; 118 119 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 120 .InSequence(seq); 121 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp))) 122 .InSequence(seq) 123 .WillOnce(Invoke(DbusEnvironment::setPromise("notify"))); 124 125 sensorObject.setValue(42.7); 126 sensorObject.setValue(42.7); 127 128 ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); 129 } 130 131 TEST_F(TestSensorNotification, doesntNotifyExpiredListener) 132 { 133 Sequence seq; 134 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)) 135 .InSequence(seq); 136 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 137 .InSequence(seq) 138 .WillOnce(Invoke(DbusEnvironment::setPromise("notify"))); 139 140 registerForUpdates(listenerMock2); 141 listenerMock = nullptr; 142 143 sensorObject.setValue(42.7); 144 145 ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); 146 } 147 148 TEST_F(TestSensorNotification, notifiesWithValueDuringRegister) 149 { 150 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)); 151 152 registerForUpdates(listenerMock2); 153 } 154