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(InvokeWithoutArgs(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(InvokeWithoutArgs(DbusEnvironment::setPromise("async_read"))); 76 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 77 .WillOnce( 78 InvokeWithoutArgs(DbusEnvironment::setPromise("async_read2"))); 79 80 DbusEnvironment::synchronizedPost([this] { 81 sut->registerForUpdates(listenerMock); 82 sut->registerForUpdates(listenerMock2); 83 }); 84 85 ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read")); 86 ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read2")); 87 } 88 89 class TestSensorNotification : public TestSensor 90 { 91 public: 92 void SetUp() override 93 { 94 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)) 95 .WillOnce( 96 InvokeWithoutArgs(DbusEnvironment::setPromise("async_read"))); 97 98 registerForUpdates(listenerMock); 99 100 ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read")); 101 } 102 103 std::shared_ptr<SensorListenerMock> listenerMock2 = 104 std::make_shared<StrictMock<SensorListenerMock>>(); 105 }; 106 107 TEST_F(TestSensorNotification, notifiesListenerWithValueWhenChangeOccurs) 108 { 109 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 110 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); 111 112 sensorObject.setValue(42.7); 113 114 ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); 115 } 116 117 TEST_F(TestSensorNotification, notifiesListenerWithValueWhenNoChangeOccurs) 118 { 119 Sequence seq; 120 121 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 122 .InSequence(seq); 123 EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp))) 124 .InSequence(seq) 125 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); 126 127 sensorObject.setValue(42.7); 128 sensorObject.setValue(42.7); 129 130 ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); 131 } 132 133 TEST_F(TestSensorNotification, doesntNotifyExpiredListener) 134 { 135 Sequence seq; 136 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)) 137 .InSequence(seq); 138 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) 139 .InSequence(seq) 140 .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); 141 142 registerForUpdates(listenerMock2); 143 listenerMock = nullptr; 144 145 sensorObject.setValue(42.7); 146 147 ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); 148 } 149 150 TEST_F(TestSensorNotification, notifiesWithValueDuringRegister) 151 { 152 EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)); 153 154 registerForUpdates(listenerMock2); 155 } 156