| #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 <sdbusplus/asio/property.hpp> |
| |
| #include <thread> |
| |
| #include <gmock/gmock.h> |
| |
| 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<interfaces::SensorListener> listener) |
| { |
| sut->registerForUpdates(listener); |
| DbusEnvironment::synchronizeIoc(); |
| } |
| |
| void unregisterFromUpdates( |
| std::shared_ptr<interfaces::SensorListener> listener) |
| { |
| sut->unregisterFromUpdates(listener); |
| DbusEnvironment::synchronizeIoc(); |
| } |
| |
| static std::unique_ptr<stubs::DbusSensorObject> makeSensorObject() |
| { |
| return std::make_unique<stubs::DbusSensorObject>( |
| DbusEnvironment::getIoc(), DbusEnvironment::getBus(), |
| DbusEnvironment::getObjServer()); |
| } |
| |
| std::unique_ptr<stubs::DbusSensorObject> sensorObject = makeSensorObject(); |
| |
| SensorCache sensorCache; |
| Milliseconds timestamp = Clock().steadyTimestamp(); |
| std::shared_ptr<Sensor> sut = sensorCache.makeSensor<Sensor>( |
| DbusEnvironment::serviceName(), sensorObject->path(), "metadata", |
| DbusEnvironment::getIoc(), DbusEnvironment::getBus()); |
| std::shared_ptr<SensorListenerMock> listenerMock = |
| std::make_shared<StrictMock<SensorListenerMock>>(); |
| std::shared_ptr<SensorListenerMock> listenerMock2 = |
| std::make_shared<StrictMock<SensorListenerMock>>(); |
| MockFunction<void()> 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<Sensor>(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<Sensor>(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"); |
| } |