Added support for Enabled property

Enabled property is added so that user can select via dbus interface if
Readings are updated and signal on Readings update is emitted, moreover
Metric calculation on received sensor data is active only when Enabled
is set to true

Tested:
- New unit tests were created, ran all new and previous UTs, all passed
- Tested under QEMU by adding reports for single and multiple sensors,
  changing Enabled property and emitting signal of value change for
  sensors added into the report, checking if Readings is accordingly
  updated or not updated
- Verified persistency, if Enabled property is successfully stored and
  restored after Telemetry service restart and also checked if after the
  restart dependencies of Enabled (Readings, Metric calculation) are
  properly initiated

Signed-off-by: Lukasz Kazmierczak <lukasz.kazmierczak@intel.com>
Change-Id: I29cf13693a48d15cb16d2ad6707f483f67f4879b
diff --git a/src/interfaces/metric.hpp b/src/interfaces/metric.hpp
index 62a8f44..57a2b68 100644
--- a/src/interfaces/metric.hpp
+++ b/src/interfaces/metric.hpp
@@ -16,6 +16,7 @@
     virtual ~Metric() = default;
 
     virtual void initialize() = 0;
+    virtual void deinitialize() = 0;
     virtual std::vector<MetricValue> getReadings() const = 0;
     virtual LabeledMetricParameters dumpConfiguration() const = 0;
 };
diff --git a/src/interfaces/report_factory.hpp b/src/interfaces/report_factory.hpp
index 182973d..970dd01 100644
--- a/src/interfaces/report_factory.hpp
+++ b/src/interfaces/report_factory.hpp
@@ -23,12 +23,13 @@
         convertMetricParams(boost::asio::yield_context& yield,
                             const ReadingParameters& metricParams) const = 0;
 
-    virtual std::unique_ptr<interfaces::Report> make(
-        const std::string& name, const std::string& reportingType,
-        bool emitsReadingsSignal, bool logToMetricReportsCollection,
-        Milliseconds period, ReportManager& reportManager,
-        JsonStorage& reportStorage,
-        std::vector<LabeledMetricParameters> labeledMetricParams) const = 0;
+    virtual std::unique_ptr<interfaces::Report>
+        make(const std::string& name, const std::string& reportingType,
+             bool emitsReadingsSignal, bool logToMetricReportsCollection,
+             Milliseconds period, ReportManager& reportManager,
+             JsonStorage& reportStorage,
+             std::vector<LabeledMetricParameters> labeledMetricParams,
+             bool enabled) const = 0;
 };
 
 } // namespace interfaces
diff --git a/src/interfaces/sensor.hpp b/src/interfaces/sensor.hpp
index 3e46317..65d3c21 100644
--- a/src/interfaces/sensor.hpp
+++ b/src/interfaces/sensor.hpp
@@ -44,6 +44,8 @@
 
     virtual Id id() const = 0;
     virtual void registerForUpdates(const std::weak_ptr<SensorListener>&) = 0;
+    virtual void
+        unregisterFromUpdates(const std::weak_ptr<SensorListener>&) = 0;
 };
 
 } // namespace interfaces
diff --git a/src/metric.cpp b/src/metric.cpp
index 04d3fe9..4290293 100644
--- a/src/metric.cpp
+++ b/src/metric.cpp
@@ -141,10 +141,17 @@
     }
 }
 
+void Metric::deinitialize()
+{
+    for (const auto& sensor : sensors)
+    {
+        sensor->unregisterFromUpdates(weak_from_this());
+    }
+}
+
 std::vector<MetricValue> Metric::getReadings() const
 {
     const auto timestamp = clock->timestamp();
-
     auto resultReadings = readings;
 
     for (size_t i = 0; i < resultReadings.size(); ++i)
diff --git a/src/metric.hpp b/src/metric.hpp
index dfed383..f053691 100644
--- a/src/metric.hpp
+++ b/src/metric.hpp
@@ -17,6 +17,7 @@
     ~Metric();
 
     void initialize() override;
+    void deinitialize() override;
     std::vector<MetricValue> getReadings() const override;
     void sensorUpdated(interfaces::Sensor&, uint64_t) override;
     void sensorUpdated(interfaces::Sensor&, uint64_t, double value) override;
diff --git a/src/report.cpp b/src/report.cpp
index 8a7297e..af19a91 100644
--- a/src/report.cpp
+++ b/src/report.cpp
@@ -17,14 +17,15 @@
                const Milliseconds intervalIn,
                interfaces::ReportManager& reportManager,
                interfaces::JsonStorage& reportStorageIn,
-               std::vector<std::shared_ptr<interfaces::Metric>> metricsIn) :
+               std::vector<std::shared_ptr<interfaces::Metric>> metricsIn,
+               const bool enabledIn) :
     name(reportName),
     path(reportDir + name), reportingType(reportingTypeIn),
     interval(intervalIn), emitsReadingsUpdate(emitsReadingsUpdateIn),
     logToMetricReportsCollection(logToMetricReportsCollectionIn),
     objServer(objServer), metrics(std::move(metricsIn)), timer(ioc),
     fileName(std::to_string(std::hash<std::string>{}(name))),
-    reportStorage(reportStorageIn)
+    reportStorage(reportStorageIn), enabled(enabledIn)
 {
     readingParameters =
         toReadingParameters(utils::transform(metrics, [](const auto& metric) {
@@ -59,9 +60,12 @@
         scheduleTimer(interval);
     }
 
-    for (auto& metric : this->metrics)
+    if (enabled)
     {
-        metric->initialize();
+        for (auto& metric : this->metrics)
+        {
+            metric->initialize();
+        }
     }
 }
 
@@ -69,16 +73,50 @@
 {
     auto dbusIface = objServer->add_unique_interface(path, reportIfaceName);
     dbusIface->register_property_rw(
+        "Enabled", enabled, sdbusplus::vtable::property_::emits_change,
+        [this](bool newVal, const auto&) {
+            if (newVal != enabled)
+            {
+                if (true == newVal && "Periodic" == reportingType)
+                {
+                    scheduleTimer(interval);
+                }
+                if (newVal)
+                {
+                    for (auto& metric : metrics)
+                    {
+                        metric->initialize();
+                    }
+                }
+                else
+                {
+                    for (auto& metric : metrics)
+                    {
+                        metric->deinitialize();
+                    }
+                }
+
+                enabled = newVal;
+                persistency = storeConfiguration();
+            }
+            return true;
+        },
+        [this](const auto&) { return enabled; });
+    dbusIface->register_property_rw(
         "Interval", interval.count(),
         sdbusplus::vtable::property_::emits_change,
         [this](uint64_t newVal, auto&) {
-            Milliseconds newValT(newVal);
-            if (newValT < ReportManager::minInterval)
+            if (Milliseconds newValT{newVal};
+                newValT >= ReportManager::minInterval)
             {
-                return false;
+                if (newValT != interval)
+                {
+                    interval = newValT;
+                    persistency = storeConfiguration();
+                }
+                return true;
             }
-            interval = newValT;
-            return true;
+            return false;
         },
         [this](const auto&) { return interval.count(); });
     dbusIface->register_property_rw(
@@ -158,22 +196,24 @@
 
 void Report::updateReadings()
 {
-    using ReadingsValue = std::tuple_element_t<1, Readings>;
-    std::get<ReadingsValue>(cachedReadings).clear();
-
-    for (const auto& metric : metrics)
+    if (!enabled)
     {
-        for (const auto& reading : metric->getReadings())
-        {
-            std::get<1>(cachedReadings)
-                .emplace_back(reading.id, reading.metadata, reading.value,
-                              reading.timestamp);
-        }
+        return;
     }
 
     using ReadingsTimestamp = std::tuple_element_t<0, Readings>;
-    std::get<ReadingsTimestamp>(cachedReadings) = std::time(0);
+    using ReadingsValue = std::tuple_element_t<1, Readings>;
 
+    std::get<ReadingsValue>(cachedReadings).clear();
+    for (const auto& metric : metrics)
+    {
+        for (const auto& [id, meta, val, timestamp] : metric->getReadings())
+        {
+            std::get<ReadingsValue>(cachedReadings)
+                .emplace_back(id, meta, val, timestamp);
+        }
+    }
+    std::get<ReadingsTimestamp>(cachedReadings) = std::time(0);
     std::swap(readings, cachedReadings);
 
     reportIface->signal_property("Readings");
@@ -185,6 +225,7 @@
     {
         nlohmann::json data;
 
+        data["Enabled"] = enabled;
         data["Version"] = reportVersion;
         data["Name"] = name;
         data["ReportingType"] = reportingType;
diff --git a/src/report.hpp b/src/report.hpp
index 92293a0..26cc130 100644
--- a/src/report.hpp
+++ b/src/report.hpp
@@ -23,7 +23,8 @@
            const bool logToMetricReportsCollection, const Milliseconds period,
            interfaces::ReportManager& reportManager,
            interfaces::JsonStorage& reportStorage,
-           std::vector<std::shared_ptr<interfaces::Metric>> metrics);
+           std::vector<std::shared_ptr<interfaces::Metric>> metrics,
+           const bool enabled);
     ~Report() = default;
 
     Report(const Report&) = delete;
@@ -68,6 +69,7 @@
 
     interfaces::JsonStorage::FilePath fileName;
     interfaces::JsonStorage& reportStorage;
+    bool enabled;
 
   public:
     static constexpr const char* reportIfaceName =
diff --git a/src/report_factory.cpp b/src/report_factory.cpp
index 091739c..3d86521 100644
--- a/src/report_factory.cpp
+++ b/src/report_factory.cpp
@@ -21,7 +21,8 @@
     bool emitsReadingsSignal, bool logToMetricReportsCollection,
     Milliseconds period, interfaces::ReportManager& reportManager,
     interfaces::JsonStorage& reportStorage,
-    std::vector<LabeledMetricParameters> labeledMetricParams) const
+    std::vector<LabeledMetricParameters> labeledMetricParams,
+    bool enabled) const
 {
     std::vector<std::shared_ptr<interfaces::Metric>> metrics = utils::transform(
         labeledMetricParams,
@@ -41,7 +42,7 @@
     return std::make_unique<Report>(
         bus->get_io_context(), objServer, name, reportingType,
         emitsReadingsSignal, logToMetricReportsCollection, period,
-        reportManager, reportStorage, std::move(metrics));
+        reportManager, reportStorage, std::move(metrics), enabled);
 }
 
 Sensors ReportFactory::getSensors(
diff --git a/src/report_factory.hpp b/src/report_factory.hpp
index 1160a6f..69f6349 100644
--- a/src/report_factory.hpp
+++ b/src/report_factory.hpp
@@ -24,8 +24,8 @@
              bool emitsReadingsSignal, bool logToMetricReportsCollection,
              Milliseconds period, interfaces::ReportManager& reportManager,
              interfaces::JsonStorage& reportStorage,
-             std::vector<LabeledMetricParameters> labeledMetricParams)
-            const override;
+             std::vector<LabeledMetricParameters> labeledMetricParams,
+             bool enabled) const override;
 
   private:
     Sensors getSensors(
diff --git a/src/report_manager.cpp b/src/report_manager.cpp
index e40d9a4..c8103a6 100644
--- a/src/report_manager.cpp
+++ b/src/report_manager.cpp
@@ -56,12 +56,14 @@
                                     const bool logToMetricReportsCollection,
                                     const uint64_t interval,
                                     ReadingParametersPastVersion metricParams) {
+                    constexpr auto enabledDefault = true;
                     return addReport(yield, reportName, reportingType,
                                      emitsReadingsUpdate,
                                      logToMetricReportsCollection,
                                      Milliseconds(interval),
                                      convertToReadingParameters(
-                                         std::move(metricParams)))
+                                         std::move(metricParams)),
+                                     enabledDefault)
                         .getPath();
                 });
 
@@ -74,11 +76,12 @@
                        const bool logToMetricReportsCollection,
                        const uint64_t interval,
                        ReadingParameters metricParams) {
+                    constexpr auto enabledDefault = true;
                     return addReport(yield, reportName, reportingType,
                                      emitsReadingsUpdate,
                                      logToMetricReportsCollection,
                                      Milliseconds(interval),
-                                     std::move(metricParams))
+                                     std::move(metricParams), enabledDefault)
                         .getPath();
                 });
         });
@@ -169,28 +172,29 @@
     boost::asio::yield_context& yield, const std::string& reportName,
     const std::string& reportingType, const bool emitsReadingsUpdate,
     const bool logToMetricReportsCollection, Milliseconds interval,
-    ReadingParameters metricParams)
+    ReadingParameters metricParams, const bool enabled)
 {
     auto labeledMetricParams =
         reportFactory->convertMetricParams(yield, metricParams);
 
     return addReport(reportName, reportingType, emitsReadingsUpdate,
                      logToMetricReportsCollection, interval,
-                     std::move(labeledMetricParams));
+                     std::move(labeledMetricParams), enabled);
 }
 
 interfaces::Report& ReportManager::addReport(
     const std::string& reportName, const std::string& reportingType,
     const bool emitsReadingsUpdate, const bool logToMetricReportsCollection,
     Milliseconds interval,
-    std::vector<LabeledMetricParameters> labeledMetricParams)
+    std::vector<LabeledMetricParameters> labeledMetricParams,
+    const bool enabled)
 {
     verifyAddReport(reportName, reportingType, interval, labeledMetricParams);
 
     reports.emplace_back(
         reportFactory->make(reportName, reportingType, emitsReadingsUpdate,
                             logToMetricReportsCollection, interval, *this,
-                            *reportStorage, labeledMetricParams));
+                            *reportStorage, labeledMetricParams, enabled));
     return *reports.back();
 }
 
@@ -204,6 +208,7 @@
         std::optional<nlohmann::json> data = reportStorage->load(path);
         try
         {
+            bool enabled = data->at("Enabled").get<bool>();
             size_t version = data->at("Version").get<size_t>();
             if (version != Report::reportVersion)
             {
@@ -223,7 +228,7 @@
 
             addReport(name, reportingType, emitsReadingsSignal,
                       logToMetricReportsCollection, Milliseconds(interval),
-                      std::move(readingParameters));
+                      std::move(readingParameters), enabled);
         }
         catch (const std::exception& e)
         {
diff --git a/src/report_manager.hpp b/src/report_manager.hpp
index 1e6e15d..f056f78 100644
--- a/src/report_manager.hpp
+++ b/src/report_manager.hpp
@@ -43,18 +43,16 @@
         const std::string& reportName, const std::string& reportingType,
         Milliseconds interval,
         const std::vector<LabeledMetricParameters>& readingParams);
-    interfaces::Report& addReport(boost::asio::yield_context& yield,
-                                  const std::string& reportName,
-                                  const std::string& reportingType,
-                                  const bool emitsReadingsUpdate,
-                                  const bool logToMetricReportsCollection,
-                                  Milliseconds interval,
-                                  ReadingParameters metricParams);
+    interfaces::Report& addReport(
+        boost::asio::yield_context& yield, const std::string& reportName,
+        const std::string& reportingType, const bool emitsReadingsUpdate,
+        const bool logToMetricReportsCollection, Milliseconds interval,
+        ReadingParameters metricParams, const bool enabled);
     interfaces::Report& addReport(
         const std::string& reportName, const std::string& reportingType,
         const bool emitsReadingsUpdate, const bool logToMetricReportsCollection,
         Milliseconds interval,
-        std::vector<LabeledMetricParameters> metricParams);
+        std::vector<LabeledMetricParameters> metricParams, const bool enabled);
     void loadFromPersistent();
 
   public:
diff --git a/src/sensor.cpp b/src/sensor.cpp
index 26cadb7..f26a964 100644
--- a/src/sensor.cpp
+++ b/src/sensor.cpp
@@ -75,6 +75,22 @@
     }
 }
 
+void Sensor::unregisterFromUpdates(
+    const std::weak_ptr<interfaces::SensorListener>& weakListener)
+{
+    if (auto listener = weakListener.lock())
+    {
+        listeners.erase(
+            std::remove_if(
+                listeners.begin(), listeners.end(),
+                [listenerToUnregister = listener.get()](const auto& listener) {
+                    return (listener.expired() ||
+                            listener.lock().get() == listenerToUnregister);
+                }),
+            listeners.end());
+    }
+}
+
 void Sensor::updateValue(double newValue)
 {
     timestamp = std::time(0);
diff --git a/src/sensor.hpp b/src/sensor.hpp
index e3334a0..23c3d5c 100644
--- a/src/sensor.hpp
+++ b/src/sensor.hpp
@@ -28,6 +28,8 @@
     Id id() const override;
     void registerForUpdates(
         const std::weak_ptr<interfaces::SensorListener>& weakListener) override;
+    void unregisterFromUpdates(
+        const std::weak_ptr<interfaces::SensorListener>& weakListener) override;
 
   private:
     static std::optional<double> readValue(const ValueVariant& v);
diff --git a/tests/src/fakes/clock_fake.hpp b/tests/src/fakes/clock_fake.hpp
index 28c2940..3871a3b 100644
--- a/tests/src/fakes/clock_fake.hpp
+++ b/tests/src/fakes/clock_fake.hpp
@@ -27,6 +27,11 @@
         timePoint = time_point{timeSinceEpoch};
     }
 
+    void reset(void) noexcept
+    {
+        set(Milliseconds(0));
+    }
+
     static uint64_t toTimestamp(Milliseconds time)
     {
         return time.count();
diff --git a/tests/src/mocks/metric_mock.hpp b/tests/src/mocks/metric_mock.hpp
index f66f38d..a105aa0 100644
--- a/tests/src/mocks/metric_mock.hpp
+++ b/tests/src/mocks/metric_mock.hpp
@@ -16,6 +16,7 @@
     }
 
     MOCK_METHOD(void, initialize, (), (override));
+    MOCK_METHOD(void, deinitialize, (), (override));
     MOCK_METHOD(std::vector<MetricValue>, getReadings, (), (const, override));
     MOCK_METHOD(LabeledMetricParameters, dumpConfiguration, (),
                 (const, override));
diff --git a/tests/src/mocks/report_factory_mock.hpp b/tests/src/mocks/report_factory_mock.hpp
index a486e74..e456429 100644
--- a/tests/src/mocks/report_factory_mock.hpp
+++ b/tests/src/mocks/report_factory_mock.hpp
@@ -35,7 +35,7 @@
             .WillByDefault(
                 WithArgs<1>(Invoke(&ReportFactoryMock::convertToLabeled)));
 
-        ON_CALL(*this, make(A<const std::string&>(), _, _, _, _, _, _, _))
+        ON_CALL(*this, make(A<const std::string&>(), _, _, _, _, _, _, _, _))
             .WillByDefault(WithArgs<0>(Invoke([](const std::string& name) {
                 return std::make_unique<NiceMock<ReportMock>>(name);
             })));
@@ -48,8 +48,8 @@
     MOCK_METHOD(std::unique_ptr<interfaces::Report>, make,
                 (const std::string&, const std::string&, bool, bool,
                  Milliseconds, interfaces::ReportManager&,
-                 interfaces::JsonStorage&,
-                 std::vector<LabeledMetricParameters>),
+                 interfaces::JsonStorage&, std::vector<LabeledMetricParameters>,
+                 bool),
                 (const, override));
 
     auto& expectMake(
@@ -60,17 +60,17 @@
         if (paramsRef)
         {
             const ReportParams& params = *paramsRef;
-            return EXPECT_CALL(*this,
-                               make(params.reportName(), params.reportingType(),
-                                    params.emitReadingUpdate(),
-                                    params.logToMetricReportCollection(),
-                                    params.interval(), rm, js,
-                                    params.metricParameters()));
+            return EXPECT_CALL(
+                *this,
+                make(params.reportName(), params.reportingType(),
+                     params.emitReadingUpdate(),
+                     params.logToMetricReportCollection(), params.interval(),
+                     rm, js, params.metricParameters(), params.enabled()));
         }
         else
         {
             using testing::_;
-            return EXPECT_CALL(*this, make(_, _, _, _, _, rm, js, _));
+            return EXPECT_CALL(*this, make(_, _, _, _, _, rm, js, _, _));
         }
     }
 };
diff --git a/tests/src/mocks/sensor_mock.hpp b/tests/src/mocks/sensor_mock.hpp
index d71d77e..b86a26e 100644
--- a/tests/src/mocks/sensor_mock.hpp
+++ b/tests/src/mocks/sensor_mock.hpp
@@ -26,6 +26,8 @@
     MOCK_METHOD(Id, id, (), (const, override));
     MOCK_METHOD(void, registerForUpdates,
                 (const std::weak_ptr<interfaces::SensorListener>&), (override));
+    MOCK_METHOD(void, unregisterFromUpdates,
+                (const std::weak_ptr<interfaces::SensorListener>&), (override));
 
     const uint64_t mockId = generateUniqueMockId();
 
diff --git a/tests/src/params/report_params.hpp b/tests/src/params/report_params.hpp
index 3bfd308..cc71ce3 100644
--- a/tests/src/params/report_params.hpp
+++ b/tests/src/params/report_params.hpp
@@ -64,6 +64,17 @@
         return intervalProperty;
     }
 
+    ReportParams& enabled(bool val)
+    {
+        enabledProperty = val;
+        return *this;
+    }
+
+    bool enabled() const
+    {
+        return enabledProperty;
+    }
+
     ReportParams& metricParameters(std::vector<LabeledMetricParameters> val)
     {
         metricParametersProperty = std::move(val);
@@ -98,4 +109,5 @@
              "Metadata2",
              CollectionTimeScope::point,
              CollectionDuration(Milliseconds(0u))}}};
+    bool enabledProperty = true;
 };
diff --git a/tests/src/test_metric.cpp b/tests/src/test_metric.cpp
index 87e32f9..a8c3d86 100644
--- a/tests/src/test_metric.cpp
+++ b/tests/src/test_metric.cpp
@@ -63,6 +63,18 @@
     sut->initialize();
 }
 
+TEST_F(TestMetric, unsubscribesForSensorDuringDeinitialization)
+{
+    sut = makeSut(params);
+
+    EXPECT_CALL(*sensorMocks.front(),
+                unregisterFromUpdates(Truly([sut = sut.get()](const auto& a0) {
+                    return a0.lock().get() == sut;
+                })));
+
+    sut->deinitialize();
+}
+
 TEST_F(TestMetric, containsEmptyReadingAfterCreated)
 {
     sut = makeSut(params);
@@ -177,8 +189,7 @@
   public:
     void SetUp() override
     {
-        clockFakePtr->set(0ms);
-
+        clockFake.reset();
         sut = makeSut(params.operationType(GetParam().operationType())
                           .collectionTimeScope(GetParam().collectionTimeScope())
                           .collectionDuration(GetParam().collectionDuration()));
diff --git a/tests/src/test_report.cpp b/tests/src/test_report.cpp
index 441ebd9..79e66ff 100644
--- a/tests/src/test_report.cpp
+++ b/tests/src/test_report.cpp
@@ -73,7 +73,8 @@
             params.emitReadingUpdate(), params.logToMetricReportCollection(),
             params.interval(), *reportManagerMock, storageMock,
             utils::convContainer<std::shared_ptr<interfaces::Metric>>(
-                metricMocks));
+                metricMocks),
+            params.enabled());
     }
 
     template <class T>
@@ -138,6 +139,8 @@
 
 TEST_F(TestReport, verifyIfPropertiesHaveValidValue)
 {
+    EXPECT_THAT(getProperty<bool>(sut->getPath(), "Enabled"),
+                Eq(defaultParams.enabled()));
     EXPECT_THAT(getProperty<uint64_t>(sut->getPath(), "Interval"),
                 Eq(defaultParams.interval().count()));
     EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistency"), Eq(true));
@@ -157,6 +160,14 @@
                 Eq(Readings{}));
 }
 
+TEST_F(TestReport, setEnabledWithNewValue)
+{
+    bool newValue = !defaultParams.enabled();
+    EXPECT_THAT(setProperty(sut->getPath(), "Enabled", newValue).value(),
+                Eq(boost::system::errc::success));
+    EXPECT_THAT(getProperty<bool>(sut->getPath(), "Enabled"), Eq(newValue));
+}
+
 TEST_F(TestReport, setIntervalWithValidValue)
 {
     uint64_t newValue = defaultParams.interval().count() + 1;
@@ -240,7 +251,8 @@
 
 INSTANTIATE_TEST_SUITE_P(
     _, TestReportStore,
-    Values(std::make_pair("Version"s, nlohmann::json(4)),
+    Values(std::make_pair("Enabled"s, nlohmann::json(ReportParams().enabled())),
+           std::make_pair("Version"s, nlohmann::json(4)),
            std::make_pair("Name"s, nlohmann::json(ReportParams().reportName())),
            std::make_pair("ReportingType",
                           nlohmann::json(ReportParams().reportingType())),
@@ -379,15 +391,28 @@
                 Eq(GetParam().reportingType()));
 }
 
-TEST_P(TestReportAllReportTypes, updateReadingsCallUpdateReadingsProperty)
+TEST_P(TestReportAllReportTypes, updateReadingsCallEnabledPropertyOff)
+{
+    const uint64_t expectedTime = std::time(0);
+
+    setProperty(sut->getPath(), "Enabled", false);
+    sut->updateReadings();
+    const auto [timestamp, readings] =
+        getProperty<Readings>(sut->getPath(), "Readings");
+
+    EXPECT_THAT(getProperty<bool>(sut->getPath(), "Enabled"), Eq(false));
+    EXPECT_THAT(timestamp, Lt(expectedTime));
+}
+
+TEST_P(TestReportAllReportTypes, updateReadingsCallEnabledPropertyOn)
 {
     const uint64_t expectedTime = std::time(0);
 
     sut->updateReadings();
-
     const auto [timestamp, readings] =
         getProperty<Readings>(sut->getPath(), "Readings");
 
+    EXPECT_THAT(getProperty<bool>(sut->getPath(), "Enabled"), Eq(true));
     EXPECT_THAT(timestamp, Ge(expectedTime));
 }
 
@@ -539,14 +564,26 @@
     MockFunction<void()> readingsUpdated;
 };
 
-TEST_F(TestReportInitialization, metricsAreInitializedWhenConstructed)
+TEST_F(TestReportInitialization,
+       metricsAreInitializedWhenEnabledReportConstructed)
 {
+    initMetricMocks(defaultParams.metricParameters());
     for (auto& metric : metricMocks)
     {
-        EXPECT_CALL(*metric, initialize());
+        EXPECT_CALL(*metric, initialize()).Times(1);
     }
+    sut = makeReport(defaultParams.enabled(true));
+}
 
-    sut = makeReport(ReportParams());
+TEST_F(TestReportInitialization,
+       metricsAreNotInitializedWhenDisabledReportConstructed)
+{
+    initMetricMocks(defaultParams.metricParameters());
+    for (auto& metric : metricMocks)
+    {
+        EXPECT_CALL(*metric, initialize()).Times(0);
+    }
+    sut = makeReport(defaultParams.enabled(false));
 }
 
 TEST_F(TestReportInitialization,
diff --git a/tests/src/test_report_manager.cpp b/tests/src/test_report_manager.cpp
index 2287707..e0705ca 100644
--- a/tests/src/test_report_manager.cpp
+++ b/tests/src/test_report_manager.cpp
@@ -352,6 +352,7 @@
     }
 
     nlohmann::json data = nlohmann::json{
+        {"Enabled", reportParams.enabled()},
         {"Version", Report::reportVersion},
         {"Name", reportParams.reportName()},
         {"ReportingType", reportParams.reportingType()},
diff --git a/tests/src/test_sensor.cpp b/tests/src/test_sensor.cpp
index 820602c..5547cf0 100644
--- a/tests/src/test_sensor.cpp
+++ b/tests/src/test_sensor.cpp
@@ -34,6 +34,13 @@
         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>(
@@ -153,6 +160,22 @@
     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)
 {