Implemented sensor class
Sensor class was introduced, it monitors
xyz.openbmc_project.Sensor.Value, for change and notifies all
listeners.
Tested:
- Unit tested with service stub that provides dbus interface
xyz.openbmc_project.Sensor.Value
- All changes are delivered to listeners
- All other unit tests are passing
Change-Id: I8c9d58cc986c1fe2a4d2386815d559814016efa6
Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
diff --git a/tests/src/test_sensor.cpp b/tests/src/test_sensor.cpp
new file mode 100644
index 0000000..c650831
--- /dev/null
+++ b/tests/src/test_sensor.cpp
@@ -0,0 +1,153 @@
+#include "dbus_environment.hpp"
+#include "mocks/sensor_listener_mock.hpp"
+#include "sensor.hpp"
+#include "sensor_cache.hpp"
+#include "stubs/dbus_sensor_object.hpp"
+#include "utils/sensor_id_eq.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)
+ {
+ DbusEnvironment::synchronizedPost(
+ [this, listener] { sut->registerForUpdates(listener); });
+ }
+
+ std::chrono::milliseconds notifiesInGivenIntervalAfterSchedule(
+ std::chrono::milliseconds interval);
+
+ stubs::DbusSensorObject sensorObject{DbusEnvironment::getIoc(),
+ DbusEnvironment::getBus(),
+ DbusEnvironment::getObjServer()};
+
+ SensorCache sensorCache;
+ uint64_t timestamp = std::time(0);
+ std::shared_ptr<Sensor> sut = sensorCache.makeSensor<Sensor>(
+ DbusEnvironment::serviceName(), sensorObject.path(),
+ DbusEnvironment::getIoc(), DbusEnvironment::getBus());
+ std::shared_ptr<SensorListenerMock> listenerMock =
+ std::make_shared<StrictMock<SensorListenerMock>>();
+ std::shared_ptr<SensorListenerMock> listenerMock2 =
+ std::make_shared<StrictMock<SensorListenerMock>>();
+};
+
+TEST_F(TestSensor, createsCorretlyViaSensorCache)
+{
+ ASSERT_THAT(sut->id(),
+ sensorIdEq(Sensor::Id("Sensor", DbusEnvironment::serviceName(),
+ sensorObject.path())));
+}
+
+TEST_F(TestSensor, notifiesWithValueAfterRegister)
+{
+ EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
+ .WillOnce(Invoke(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(Invoke(DbusEnvironment::setPromise("async_read")));
+ EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
+ .WillOnce(Invoke(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"));
+}
+
+class TestSensorNotification : public TestSensor
+{
+ public:
+ void SetUp() override
+ {
+ EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 0.))
+ .WillOnce(Invoke(DbusEnvironment::setPromise("async_read")));
+
+ registerForUpdates(listenerMock);
+
+ ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read"));
+ }
+
+ std::shared_ptr<SensorListenerMock> listenerMock2 =
+ std::make_shared<StrictMock<SensorListenerMock>>();
+};
+
+TEST_F(TestSensorNotification, notifiesListenerWithValueWhenChangeOccurs)
+{
+ EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
+ .WillOnce(Invoke(DbusEnvironment::setPromise("notify")));
+
+ sensorObject.setValue(42.7);
+
+ ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
+}
+
+TEST_F(TestSensorNotification, notifiesListenerWithValueWhenNoChangeOccurs)
+{
+ Sequence seq;
+
+ EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
+ .InSequence(seq);
+ EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp)))
+ .InSequence(seq)
+ .WillOnce(Invoke(DbusEnvironment::setPromise("notify")));
+
+ sensorObject.setValue(42.7);
+ sensorObject.setValue(42.7);
+
+ ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
+}
+
+TEST_F(TestSensorNotification, doesntNotifyExpiredListener)
+{
+ Sequence seq;
+ EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.))
+ .InSequence(seq);
+ EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
+ .InSequence(seq)
+ .WillOnce(Invoke(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);
+}