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