#include "dbus_environment.hpp" #include "helpers.hpp" #include "mocks/sensor_listener_mock.hpp" #include "sensor.hpp" #include "sensor_cache.hpp" #include "stubs/dbus_sensor_object.hpp" #include "utils/clock.hpp" #include #include #include using namespace testing; using namespace std::chrono_literals; class TestSensor : public Test { public: void SetUp() override { sensorObject->setValue(42.7); } void TearDown() override { DbusEnvironment::synchronizeIoc(); } void registerForUpdates(std::shared_ptr listener) { sut->registerForUpdates(listener); DbusEnvironment::synchronizeIoc(); } void unregisterFromUpdates( std::shared_ptr listener) { sut->unregisterFromUpdates(listener); DbusEnvironment::synchronizeIoc(); } static std::unique_ptr makeSensorObject() { return std::make_unique( DbusEnvironment::getIoc(), DbusEnvironment::getBus(), DbusEnvironment::getObjServer()); } std::unique_ptr sensorObject = makeSensorObject(); SensorCache sensorCache; Milliseconds timestamp = Clock().steadyTimestamp(); std::shared_ptr sut = sensorCache.makeSensor( DbusEnvironment::serviceName(), sensorObject->path(), "metadata", DbusEnvironment::getIoc(), DbusEnvironment::getBus()); std::shared_ptr listenerMock = std::make_shared>(); std::shared_ptr listenerMock2 = std::make_shared>(); MockFunction checkPoint; }; TEST_F(TestSensor, createsCorretlyViaSensorCache) { ASSERT_THAT(sut->id(), Eq(Sensor::Id("Sensor", DbusEnvironment::serviceName(), sensorObject->path()))); } TEST_F(TestSensor, notifiesWithValueAfterRegister) { EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("async_read"))); registerForUpdates(listenerMock); ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read")); } TEST_F(TestSensor, notifiesOnceWithValueAfterRegister) { EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("async_read"))); EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) .WillOnce( InvokeWithoutArgs(DbusEnvironment::setPromise("async_read2"))); DbusEnvironment::synchronizedPost([this] { sut->registerForUpdates(listenerMock); sut->registerForUpdates(listenerMock2); }); ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read")); ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read2")); } TEST_F(TestSensor, getLabeledInfoReturnsCorrectly) { auto expected = LabeledSensorInfo(DbusEnvironment::serviceName(), sensorObject->path(), "metadata"); EXPECT_EQ(sut->getLabeledSensorInfo(), expected); } TEST_F(TestSensor, getNameReturnsPathWhenMetadataIsNotSet) { static const char* path = "/telemetry/ut/DbusSensorObject2"; sut = sensorCache.makeSensor(DbusEnvironment::serviceName(), path, "", DbusEnvironment::getIoc(), DbusEnvironment::getBus()); EXPECT_EQ(sut->getName(), path); } TEST_F(TestSensor, getNameReturnsMetadataWhenMetadataIsSet) { static const char* path = "/telemetry/ut/DbusSensorObject2"; sut = sensorCache.makeSensor(DbusEnvironment::serviceName(), path, "metadata2", DbusEnvironment::getIoc(), DbusEnvironment::getBus()); EXPECT_EQ(sut->getName(), "metadata2"); } class TestSensorNotification : public TestSensor { public: void SetUp() override { EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)) .WillOnce( InvokeWithoutArgs(DbusEnvironment::setPromise("async_read"))); registerForUpdates(listenerMock); ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read")); } }; TEST_F(TestSensorNotification, notifiesListenerWithValueWhenChangeOccurs) { EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); sensorObject->setValue(42.7); ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); } TEST_F(TestSensorNotification, doesntNotifyListenerWhenNoChangeOccurs) { EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); sensorObject->setValue(42.7); sensorObject->setValue(42.7); ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); } TEST_F(TestSensorNotification, doesntNotifyExpiredListener) { InSequence seq; EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)); EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); registerForUpdates(listenerMock2); listenerMock = nullptr; sensorObject->setValue(42.7); ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); } TEST_F(TestSensorNotification, notifiesWithValueDuringRegister) { EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)); registerForUpdates(listenerMock2); } TEST_F(TestSensorNotification, notNotifiesWithValueWhenUnregistered) { EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.)); EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) .Times(0); EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7)) .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify"))); registerForUpdates(listenerMock2); unregisterFromUpdates(listenerMock); sensorObject->setValue(42.7); ASSERT_TRUE(DbusEnvironment::waitForFuture("notify")); } TEST_F(TestSensorNotification, dbusSensorIsAddedToSystemAfterSensorIsCreatedThenValueIsUpdated) { InSequence seq; EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), DoubleEq(42.7))) .WillOnce( InvokeWithoutArgs(DbusEnvironment::setPromise("notify-change"))); EXPECT_CALL(checkPoint, Call()); EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), DoubleEq(0.))) .WillOnce( InvokeWithoutArgs(DbusEnvironment::setPromise("notify-create"))); sensorObject->setValue(42.7); DbusEnvironment::waitForFuture("notify-change"); checkPoint.Call(); sensorObject = nullptr; sensorObject = makeSensorObject(); DbusEnvironment::waitForFuture("notify-create"); }