created AddReportFutureVersion dbus method

New method will support CollectionTimeScope, CollectionDuration

In order to make not breaking interface changes bmcweb will switch to
AddReportFutureVersion, then AddReport will be changed to match
AddReportFutureVersion, then redfish will switch back to use AddReport,
then AddReportFutureVersion will be removed.

Tested:
  - Verified that current version of bmcweb works fine with old API

Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
Change-Id: I51a9b7fb2f4da5b8d2f688ccd5e93710352b1ac7
diff --git a/tests/meson.build b/tests/meson.build
index e87a616..17cd369 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -25,6 +25,7 @@
             '../src/trigger_actions.cpp',
             '../src/trigger_factory.cpp',
             '../src/trigger_manager.cpp',
+            '../src/types/report_types.cpp',
             '../src/utils/conversion_trigger.cpp',
             'src/dbus_environment.cpp',
             'src/main.cpp',
diff --git a/tests/src/helpers.hpp b/tests/src/helpers.hpp
index 3cc6951..c12c610 100644
--- a/tests/src/helpers.hpp
+++ b/tests/src/helpers.hpp
@@ -1,7 +1,6 @@
 #pragma once
 
 #include "helpers/interfaces/json_storage_helpers.hpp"
-#include "helpers/interfaces/labeled_reading_parameter_helpers.hpp"
-#include "helpers/interfaces/labeled_sensor_parameter_helpers.hpp"
 #include "helpers/interfaces/sensor_id_helpers.hpp"
-#include "helpers/metric_value_helpers.hpp"
\ No newline at end of file
+#include "helpers/labeled_tuple_helpers.hpp"
+#include "helpers/metric_value_helpers.hpp"
diff --git a/tests/src/helpers/interfaces/labeled_reading_parameter_helpers.hpp b/tests/src/helpers/interfaces/labeled_reading_parameter_helpers.hpp
deleted file mode 100644
index 9a46d0c..0000000
--- a/tests/src/helpers/interfaces/labeled_reading_parameter_helpers.hpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#pragma once
-
-#include "helpers/interfaces/labeled_sensor_parameter_helpers.hpp"
-#include "interfaces/types.hpp"
-
-#include <ostream>
-
-#include <gmock/gmock.h>
-
-namespace utils
-{
-
-inline void PrintTo(const LabeledMetricParameters& o, std::ostream* os)
-{
-    using testing::PrintToString;
-
-    (*os) << "{ ";
-    (*os) << utils::tstring::SensorPath::str() << ": "
-          << PrintToString(o.at_label<utils::tstring::SensorPath>()) << ", ";
-    (*os) << utils::tstring::OperationType::str() << ": "
-          << PrintToString(o.at_label<utils::tstring::OperationType>()) << ", ";
-    (*os) << utils::tstring::Id::str() << ": "
-          << PrintToString(o.at_label<utils::tstring::Id>()) << ", ";
-    (*os) << utils::tstring::MetricMetadata::str() << ": "
-          << PrintToString(o.at_label<utils::tstring::MetricMetadata>());
-    (*os) << " }";
-}
-
-} // namespace utils
diff --git a/tests/src/helpers/interfaces/labeled_sensor_parameter_helpers.hpp b/tests/src/helpers/interfaces/labeled_sensor_parameter_helpers.hpp
deleted file mode 100644
index ef2eb6b..0000000
--- a/tests/src/helpers/interfaces/labeled_sensor_parameter_helpers.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-
-#include "interfaces/types.hpp"
-
-#include <ostream>
-
-#include <gmock/gmock.h>
-
-namespace utils
-{
-
-inline void PrintTo(const LabeledSensorParameters& o, std::ostream* os)
-{
-    using testing::PrintToString;
-
-    (*os) << "{ ";
-    (*os) << utils::tstring::Service::str() << ": "
-          << PrintToString(o.at_label<utils::tstring::Service>()) << ", ";
-    (*os) << utils::tstring::Path::str() << ": "
-          << PrintToString(o.at_label<utils::tstring::Path>());
-    (*os) << " }";
-}
-
-} // namespace utils
\ No newline at end of file
diff --git a/tests/src/helpers/labeled_tuple_helpers.hpp b/tests/src/helpers/labeled_tuple_helpers.hpp
new file mode 100644
index 0000000..4ee70c1
--- /dev/null
+++ b/tests/src/helpers/labeled_tuple_helpers.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "utils/labeled_tuple.hpp"
+
+#include <iomanip>
+
+namespace utils
+{
+
+template <class... Args, class... Labels>
+inline void
+    PrintTo(const LabeledTuple<std::tuple<Args...>, Labels...>& labeledTuple,
+            std::ostream* os)
+{
+    nlohmann::json json;
+    to_json(json, labeledTuple);
+
+    (*os) << std::setw(2) << json;
+}
+
+} // namespace utils
diff --git a/tests/src/mocks/metric_mock.hpp b/tests/src/mocks/metric_mock.hpp
index 2f31f1e..98bad87 100644
--- a/tests/src/mocks/metric_mock.hpp
+++ b/tests/src/mocks/metric_mock.hpp
@@ -11,12 +11,13 @@
     {
         using namespace testing;
 
-        ON_CALL(*this, getReading())
-            .WillByDefault(ReturnRefOfCopy(MetricValue()));
+        ON_CALL(*this, getReadings())
+            .WillByDefault(ReturnRefOfCopy(std::vector<MetricValue>()));
     }
 
     MOCK_METHOD(void, initialize, (), (override));
-    MOCK_METHOD(const MetricValue&, getReading, (), (const, override));
+    MOCK_METHOD(const 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 0730d9e..a486e74 100644
--- a/tests/src/mocks/report_factory_mock.hpp
+++ b/tests/src/mocks/report_factory_mock.hpp
@@ -3,42 +3,56 @@
 #include "interfaces/report_factory.hpp"
 #include "mocks/report_mock.hpp"
 #include "params/report_params.hpp"
+#include "utils/transform.hpp"
 
 #include <gmock/gmock.h>
 
 class ReportFactoryMock : public interfaces::ReportFactory
 {
+    static std::vector<LabeledMetricParameters>
+        convertToLabeled(const ReadingParameters& readingParams)
+    {
+        return utils::transform(readingParams, [](const auto& params) {
+            return LabeledMetricParameters(
+                utils::transform(std::get<0>(params),
+                                 [](const auto& sensorPath) {
+                                     return LabeledSensorParameters("Service",
+                                                                    sensorPath);
+                                 }),
+                utils::stringToOperationType(std::get<1>(params)),
+                std::get<2>(params), std::get<3>(params),
+                utils::stringToCollectionTimeScope(std::get<4>(params)),
+                CollectionDuration(Milliseconds(std::get<5>(params))));
+        });
+    }
+
   public:
     ReportFactoryMock()
     {
         using namespace testing;
 
-        ON_CALL(*this,
-                make(A<boost::asio::yield_context&>(), _, _, _, _, _, _, _, _))
-            .WillByDefault(WithArgs<1>(Invoke([](const std::string& name) {
-                return std::make_unique<NiceMock<ReportMock>>(name);
-            })));
-        ON_CALL(*this, make(A<const std::string&>(), _, _, _, _, _, _, _, _))
+        ON_CALL(*this, convertMetricParams(_, _))
+            .WillByDefault(
+                WithArgs<1>(Invoke(&ReportFactoryMock::convertToLabeled)));
+
+        ON_CALL(*this, make(A<const std::string&>(), _, _, _, _, _, _, _))
             .WillByDefault(WithArgs<0>(Invoke([](const std::string& name) {
                 return std::make_unique<NiceMock<ReportMock>>(name);
             })));
     }
 
-    MOCK_METHOD(std::unique_ptr<interfaces::Report>, make,
-                (boost::asio::yield_context&, const std::string&,
-                 const std::string&, bool, bool, std::chrono::milliseconds,
-                 const ReadingParameters&, interfaces::ReportManager&,
-                 interfaces::JsonStorage&),
+    MOCK_METHOD(std::vector<LabeledMetricParameters>, convertMetricParams,
+                (boost::asio::yield_context&, const ReadingParameters&),
                 (const, override));
+
     MOCK_METHOD(std::unique_ptr<interfaces::Report>, make,
                 (const std::string&, const std::string&, bool, bool,
-                 std::chrono::milliseconds, const ReadingParameters&,
-                 interfaces::ReportManager&, interfaces::JsonStorage&,
+                 Milliseconds, interfaces::ReportManager&,
+                 interfaces::JsonStorage&,
                  std::vector<LabeledMetricParameters>),
                 (const, override));
 
     auto& expectMake(
-        const testing::Matcher<boost::asio::yield_context&>& yield,
         std::optional<std::reference_wrapper<const ReportParams>> paramsRef,
         const testing::Matcher<interfaces::ReportManager&>& rm,
         const testing::Matcher<interfaces::JsonStorage&>& js)
@@ -46,40 +60,17 @@
         if (paramsRef)
         {
             const ReportParams& params = *paramsRef;
-            return EXPECT_CALL(*this, make(yield, params.reportName(),
-                                           params.reportingType(),
-                                           params.emitReadingUpdate(),
-                                           params.logToMetricReportCollection(),
-                                           params.interval(),
-                                           params.readingParameters(), rm, js));
-        }
-        else
-        {
-            using testing::_;
-            return EXPECT_CALL(*this, make(yield, _, _, _, _, _, _, rm, js));
-        }
-    }
-
-    auto& expectMake(
-        std::optional<std::reference_wrapper<const ReportParams>> paramsRef,
-        const testing::Matcher<interfaces::ReportManager&>& rm,
-        const testing::Matcher<interfaces::JsonStorage&>& js,
-        const testing::Matcher<std::vector<LabeledMetricParameters>>& lrp)
-    {
-        if (paramsRef)
-        {
-            const ReportParams& params = *paramsRef;
             return EXPECT_CALL(*this,
                                make(params.reportName(), params.reportingType(),
                                     params.emitReadingUpdate(),
                                     params.logToMetricReportCollection(),
-                                    params.interval(),
-                                    params.readingParameters(), rm, js, lrp));
+                                    params.interval(), rm, js,
+                                    params.metricParameters()));
         }
         else
         {
             using testing::_;
-            return EXPECT_CALL(*this, make(_, _, _, _, _, _, rm, js, lrp));
+            return EXPECT_CALL(*this, make(_, _, _, _, _, rm, js, _));
         }
     }
 };
diff --git a/tests/src/params/metric_params.hpp b/tests/src/params/metric_params.hpp
new file mode 100644
index 0000000..f099472
--- /dev/null
+++ b/tests/src/params/metric_params.hpp
@@ -0,0 +1,74 @@
+#pragma once
+
+#include "types/collection_duration.hpp"
+#include "types/collection_time_scope.hpp"
+#include "types/operation_type.hpp"
+
+#include <string>
+
+class MetricParams final
+{
+  public:
+    MetricParams& operationType(OperationType val)
+    {
+        operationTypeProperty = val;
+        return *this;
+    }
+
+    const OperationType& operationType() const
+    {
+        return operationTypeProperty;
+    }
+
+    MetricParams& id(std::string val)
+    {
+        idProperty = std::move(val);
+        return *this;
+    }
+
+    const std::string& id() const
+    {
+        return idProperty;
+    }
+
+    MetricParams& metadata(std::string val)
+    {
+        metadataProperty = std::move(val);
+        return *this;
+    }
+
+    const std::string& metadata() const
+    {
+        return metadataProperty;
+    }
+
+    MetricParams& collectionTimeScope(CollectionTimeScope val)
+    {
+        collectionTimeScopeProperty = val;
+        return *this;
+    }
+
+    const CollectionTimeScope& collectionTimeScope() const
+    {
+        return collectionTimeScopeProperty;
+    }
+
+    MetricParams& collectionDuration(CollectionDuration val)
+    {
+        collectionDurationProperty = val;
+        return *this;
+    }
+
+    const CollectionDuration& collectionDuration() const
+    {
+        return collectionDurationProperty;
+    }
+
+  private:
+    OperationType operationTypeProperty = {};
+    std::string idProperty = "MetricId";
+    std::string metadataProperty = "MetricMetadata";
+    CollectionTimeScope collectionTimeScopeProperty = {};
+    CollectionDuration collectionDurationProperty =
+        CollectionDuration(Milliseconds(0u));
+};
diff --git a/tests/src/params/report_params.hpp b/tests/src/params/report_params.hpp
index 25422bc..3bfd308 100644
--- a/tests/src/params/report_params.hpp
+++ b/tests/src/params/report_params.hpp
@@ -1,7 +1,7 @@
 #pragma once
 
-#include "interfaces/types.hpp"
 #include "report_manager.hpp"
+#include "types/report_types.hpp"
 
 #include <chrono>
 #include <string>
@@ -53,26 +53,26 @@
         return logToMetricReportCollectionProperty;
     }
 
-    ReportParams& interval(std::chrono::milliseconds val)
+    ReportParams& interval(Milliseconds val)
     {
         intervalProperty = val;
         return *this;
     }
 
-    std::chrono::milliseconds interval() const
+    Milliseconds interval() const
     {
         return intervalProperty;
     }
 
-    ReportParams& readingParameters(ReadingParameters val)
+    ReportParams& metricParameters(std::vector<LabeledMetricParameters> val)
     {
-        readingParametersProperty = std::move(val);
+        metricParametersProperty = std::move(val);
         return *this;
     }
 
-    const ReadingParameters& readingParameters() const
+    const std::vector<LabeledMetricParameters>& metricParameters() const
     {
-        return readingParametersProperty;
+        return metricParametersProperty;
     }
 
   private:
@@ -80,16 +80,22 @@
     std::string reportingTypeProperty = "OnRequest";
     bool emitReadingUpdateProperty = true;
     bool logToMetricReportCollectionProperty = true;
-    std::chrono::milliseconds intervalProperty = ReportManager::minInterval;
-    ReadingParameters readingParametersProperty = {
-        {{sdbusplus::message::object_path(
-             "/xyz/openbmc_project/sensors/power/p1")},
-         utils::enumToString(OperationType::single),
-         "MetricId1",
-         "Metadata1"},
-        {{sdbusplus::message::object_path(
-             "/xyz/openbmc_project/sensors/power/p2")},
-         utils::enumToString(OperationType::single),
-         "MetricId2",
-         "Metadata2"}};
+    Milliseconds intervalProperty = ReportManager::minInterval;
+    std::vector<LabeledMetricParameters> metricParametersProperty{
+        {LabeledMetricParameters{
+             {LabeledSensorParameters{"Service",
+                                      "/xyz/openbmc_project/sensors/power/p1"}},
+             OperationType::single,
+             "MetricId1",
+             "Metadata1",
+             CollectionTimeScope::point,
+             CollectionDuration(Milliseconds(0u))},
+         LabeledMetricParameters{
+             {LabeledSensorParameters{"Service",
+                                      "/xyz/openbmc_project/sensors/power/p2"}},
+             OperationType::single,
+             "MetricId2",
+             "Metadata2",
+             CollectionTimeScope::point,
+             CollectionDuration(Milliseconds(0u))}}};
 };
diff --git a/tests/src/params/trigger_params.hpp b/tests/src/params/trigger_params.hpp
index 7e00157..ac8656a 100644
--- a/tests/src/params/trigger_params.hpp
+++ b/tests/src/params/trigger_params.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
-#include "interfaces/trigger_types.hpp"
+#include "types/milliseconds.hpp"
+#include "types/trigger_types.hpp"
 
 #include <sdbusplus/message.hpp>
 
@@ -88,12 +89,10 @@
 
     LabeledTriggerThresholdParams labeledThresholdsProperty =
         std::vector<numeric::LabeledThresholdParam>{
+            numeric::LabeledThresholdParam{numeric::Type::lowerCritical,
+                                           Milliseconds(10).count(),
+                                           numeric::Direction::decreasing, 0.5},
             numeric::LabeledThresholdParam{
-                numeric::Type::lowerCritical,
-                std::chrono::milliseconds(10).count(),
-                numeric::Direction::decreasing, 0.5},
-            numeric::LabeledThresholdParam{
-                numeric::Type::upperCritical,
-                std::chrono::milliseconds(10).count(),
+                numeric::Type::upperCritical, Milliseconds(10).count(),
                 numeric::Direction::increasing, 90.2}};
 };
diff --git a/tests/src/test_discrete_threshold.cpp b/tests/src/test_discrete_threshold.cpp
index 2b31767..47b6179 100644
--- a/tests/src/test_discrete_threshold.cpp
+++ b/tests/src/test_discrete_threshold.cpp
@@ -3,6 +3,7 @@
 #include "helpers.hpp"
 #include "mocks/sensor_mock.hpp"
 #include "mocks/trigger_action_mock.hpp"
+#include "types/milliseconds.hpp"
 #include "utils/conv_container.hpp"
 
 #include <gmock/gmock.h>
@@ -22,9 +23,8 @@
     TriggerActionMock& actionMock = *actionMockPtr;
     std::shared_ptr<DiscreteThreshold> sut;
 
-    std::shared_ptr<DiscreteThreshold>
-        makeThreshold(std::chrono::milliseconds dwellTime,
-                      double thresholdValue)
+    std::shared_ptr<DiscreteThreshold> makeThreshold(Milliseconds dwellTime,
+                                                     double thresholdValue)
     {
         std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
         actions.push_back(std::move(actionMockPtr));
@@ -68,10 +68,10 @@
         size_t sensor;
         uint64_t timestamp;
         double value;
-        std::chrono::milliseconds sleepAfter;
+        Milliseconds sleepAfter;
 
         UpdateParams(size_t sensor, uint64_t timestamp, double value,
-                     std::chrono::milliseconds sleepAfter = 0ms) :
+                     Milliseconds sleepAfter = 0ms) :
             sensor(sensor),
             timestamp(timestamp), value(value), sleepAfter(sleepAfter)
         {}
@@ -82,10 +82,10 @@
         size_t sensor;
         uint64_t timestamp;
         double value;
-        std::chrono::milliseconds waitMin;
+        Milliseconds waitMin;
 
         ExpectedParams(size_t sensor, uint64_t timestamp, double value,
-                       std::chrono::milliseconds waitMin = 0ms) :
+                       Milliseconds waitMin = 0ms) :
             sensor(sensor),
             timestamp(timestamp), value(value), waitMin(waitMin)
         {}
@@ -109,7 +109,7 @@
         return *this;
     }
 
-    DiscreteParams& DwellTime(std::chrono::milliseconds val)
+    DiscreteParams& DwellTime(Milliseconds val)
     {
         dwellTime = std::move(val);
         return *this;
@@ -139,7 +139,7 @@
     std::vector<UpdateParams> updates;
     std::vector<ExpectedParams> expected;
     double thresholdValue = 0.0;
-    std::chrono::milliseconds dwellTime = 0ms;
+    Milliseconds dwellTime = 0ms;
 };
 
 class TestDiscreteThresholdCommon :
@@ -147,7 +147,7 @@
     public WithParamInterface<DiscreteParams>
 {
   public:
-    void sleep(std::chrono::milliseconds duration)
+    void sleep(Milliseconds duration)
     {
         if (duration != 0ms)
         {
diff --git a/tests/src/test_metric.cpp b/tests/src/test_metric.cpp
index e91750d..9006962 100644
--- a/tests/src/test_metric.cpp
+++ b/tests/src/test_metric.cpp
@@ -1,6 +1,7 @@
 #include "helpers.hpp"
 #include "metric.hpp"
 #include "mocks/sensor_mock.hpp"
+#include "params/metric_params.hpp"
 #include "utils/conv_container.hpp"
 #include "utils/conversion.hpp"
 #include "utils/tstring.hpp"
@@ -8,6 +9,8 @@
 #include <gmock/gmock.h>
 
 using namespace testing;
+using namespace std::chrono_literals;
+
 namespace tstring = utils::tstring;
 
 using Timestamp = uint64_t;
@@ -15,16 +18,42 @@
 class TestMetric : public Test
 {
   public:
-    std::shared_ptr<SensorMock> sensorMock =
-        std::make_shared<NiceMock<SensorMock>>();
+    static std::vector<std::shared_ptr<SensorMock>>
+        makeSensorMocks(size_t amount)
+    {
+        std::vector<std::shared_ptr<SensorMock>> result;
+        for (size_t i = 0; i < amount; ++i)
+        {
+            result.emplace_back(std::make_shared<NiceMock<SensorMock>>());
+        }
+        return result;
+    }
 
-    std::shared_ptr<Metric> sut = std::make_shared<Metric>(
-        sensorMock, OperationType::avg, "id", "metadata");
+    std::shared_ptr<Metric> makeSut(const MetricParams& p)
+    {
+        return std::make_shared<Metric>(
+            utils::convContainer<std::shared_ptr<interfaces::Sensor>>(
+                sensorMocks),
+            p.operationType(), p.id(), p.metadata(), p.collectionTimeScope(),
+            p.collectionDuration());
+    }
+
+    MetricParams params =
+        MetricParams()
+            .id("id")
+            .metadata("metadata")
+            .operationType(OperationType::avg)
+            .collectionTimeScope(CollectionTimeScope::interval)
+            .collectionDuration(CollectionDuration(42ms));
+    std::vector<std::shared_ptr<SensorMock>> sensorMocks = makeSensorMocks(1u);
+    std::shared_ptr<Metric> sut;
 };
 
 TEST_F(TestMetric, subscribesForSensorDuringInitialization)
 {
-    EXPECT_CALL(*sensorMock,
+    sut = makeSut(params);
+
+    EXPECT_CALL(*sensorMocks.front(),
                 registerForUpdates(Truly([sut = sut.get()](const auto& a0) {
                     return a0.lock().get() == sut;
                 })));
@@ -34,29 +63,72 @@
 
 TEST_F(TestMetric, containsEmptyReadingAfterCreated)
 {
-    ASSERT_THAT(sut->getReading(), MetricValue({"id", "metadata", 0., 0u}));
+    sut = makeSut(params);
+
+    ASSERT_THAT(sut->getReadings(),
+                ElementsAre(MetricValue({"id", "metadata", 0., 0u})));
+}
+
+TEST_F(TestMetric, parsesSensorMetadata)
+{
+    nlohmann::json metadata;
+    metadata["MetricProperties"] = {"sensor1", "sensor2"};
+
+    sensorMocks = makeSensorMocks(2);
+    sut = makeSut(params.metadata(metadata.dump()));
+
+    EXPECT_THAT(sut->getReadings(),
+                ElementsAre(MetricValue{"id", "sensor1", 0., 0u},
+                            MetricValue{"id", "sensor2", 0., 0u}));
+}
+
+TEST_F(TestMetric, parsesSensorMetadataWhenMoreMetadataThanSensors)
+{
+    nlohmann::json metadata;
+    metadata["MetricProperties"] = {"sensor1", "sensor2"};
+
+    sensorMocks = makeSensorMocks(1);
+    sut = makeSut(params.metadata(metadata.dump()));
+
+    EXPECT_THAT(sut->getReadings(),
+                ElementsAre(MetricValue{"id", metadata.dump(), 0., 0u}));
+}
+
+TEST_F(TestMetric, parsesSensorMetadataWhenMoreSensorsThanMetadata)
+{
+    nlohmann::json metadata;
+    metadata["MetricProperties"] = {"sensor1"};
+
+    sensorMocks = makeSensorMocks(2);
+    sut = makeSut(params.metadata(metadata.dump()));
+
+    EXPECT_THAT(sut->getReadings(),
+                ElementsAre(MetricValue{"id", metadata.dump(), 0., 0u},
+                            MetricValue{"id", metadata.dump(), 0., 0u}));
 }
 
 class TestMetricAfterInitialization : public TestMetric
 {
   public:
-    TestMetricAfterInitialization()
+    void SetUp() override
     {
+        sut = makeSut(params);
         sut->initialize();
     }
 };
 
 TEST_F(TestMetricAfterInitialization, containsEmptyReading)
 {
-    ASSERT_THAT(sut->getReading(), MetricValue({"id", "metadata", 0., 0u}));
+    ASSERT_THAT(sut->getReadings(),
+                ElementsAre(MetricValue({"id", "metadata", 0., 0u})));
 }
 
 TEST_F(TestMetricAfterInitialization, updatesMetricValuesOnSensorUpdate)
 {
-    sut->sensorUpdated(*sensorMock, Timestamp{18}, 31.2);
+    sut->sensorUpdated(*sensorMocks.front(), Timestamp{18}, 31.2);
 
-    ASSERT_THAT(sut->getReading(),
-                Eq(MetricValue{"id", "metadata", 31.2, 18u}));
+    ASSERT_THAT(sut->getReadings(),
+                ElementsAre(MetricValue{"id", "metadata", 31.2, 18u}));
 }
 
 TEST_F(TestMetricAfterInitialization,
@@ -68,45 +140,24 @@
                  std::out_of_range);
 }
 
-TEST_F(TestMetricAfterInitialization, containsIdInConfigurationDump)
+TEST_F(TestMetricAfterInitialization, dumpsConfiguration)
 {
-    const auto conf = sut->dumpConfiguration();
+    namespace ts = utils::tstring;
 
-    EXPECT_THAT(conf.at_label<utils::tstring::Id>(), Eq("id"));
-    EXPECT_THAT(conf.to_json().at(tstring::Id::str()),
-                Eq(nlohmann::json("id")));
-}
-
-TEST_F(TestMetricAfterInitialization, containsOpInJsonDump)
-{
-    const auto conf = sut->dumpConfiguration();
-
-    EXPECT_THAT(conf.at_label<utils::tstring::OperationType>(),
-                Eq(OperationType::avg));
-    EXPECT_THAT(conf.to_json().at(tstring::OperationType::str()),
-                Eq(nlohmann::json(utils::toUnderlying(OperationType::avg))));
-}
-
-TEST_F(TestMetricAfterInitialization, containsMetadataInJsonDump)
-{
-    const auto conf = sut->dumpConfiguration();
-
-    EXPECT_THAT(conf.at_label<utils::tstring::MetricMetadata>(),
-                Eq("metadata"));
-    EXPECT_THAT(conf.to_json().at(tstring::MetricMetadata::str()),
-                Eq(nlohmann::json("metadata")));
-}
-
-TEST_F(TestMetricAfterInitialization, containsSensorPathInJsonDump)
-{
-    ON_CALL(*sensorMock, id())
+    ON_CALL(*sensorMocks.front(), id())
         .WillByDefault(Return(SensorMock::makeId("service1", "path1")));
 
     const auto conf = sut->dumpConfiguration();
 
-    EXPECT_THAT(conf.at_label<utils::tstring::SensorPath>(),
-                Eq(LabeledSensorParameters("service1", "path1")));
-    EXPECT_THAT(
-        conf.to_json().at(tstring::SensorPath::str()),
-        Eq(nlohmann::json({{"service", "service1"}, {"path", "path1"}})));
+    LabeledMetricParameters expected = {};
+    expected.at_label<ts::Id>() = "id";
+    expected.at_label<ts::MetricMetadata>() = "metadata";
+    expected.at_label<ts::OperationType>() = OperationType::avg;
+    expected.at_label<ts::CollectionTimeScope>() =
+        CollectionTimeScope::interval;
+    expected.at_label<ts::CollectionDuration>() = CollectionDuration(42ms);
+    expected.at_label<ts::SensorPath>() = {
+        LabeledSensorParameters("service1", "path1")};
+
+    EXPECT_THAT(conf, Eq(expected));
 }
diff --git a/tests/src/test_numeric_threshold.cpp b/tests/src/test_numeric_threshold.cpp
index 0f1d145..bda31a0 100644
--- a/tests/src/test_numeric_threshold.cpp
+++ b/tests/src/test_numeric_threshold.cpp
@@ -22,8 +22,8 @@
     TriggerActionMock& actionMock = *actionMockPtr;
     std::shared_ptr<NumericThreshold> sut;
 
-    void makeThreshold(std::chrono::milliseconds dwellTime,
-                       numeric::Direction direction, double thresholdValue)
+    void makeThreshold(Milliseconds dwellTime, numeric::Direction direction,
+                       double thresholdValue)
     {
         std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
         actions.push_back(std::move(actionMockPtr));
diff --git a/tests/src/test_report.cpp b/tests/src/test_report.cpp
index 80c0a9c..96f74f0 100644
--- a/tests/src/test_report.cpp
+++ b/tests/src/test_report.cpp
@@ -25,38 +25,30 @@
     std::unique_ptr<ReportManagerMock> reportManagerMock =
         std::make_unique<NiceMock<ReportManagerMock>>();
     testing::NiceMock<StorageMock> storageMock;
-    std::vector<std::shared_ptr<MetricMock>> metricMocks = {
-        std::make_shared<NiceMock<MetricMock>>(),
-        std::make_shared<NiceMock<MetricMock>>(),
-        std::make_shared<NiceMock<MetricMock>>()};
+    std::vector<std::shared_ptr<MetricMock>> metricMocks;
     std::unique_ptr<Report> sut;
 
     MockFunction<void()> checkPoint;
 
-    TestReport()
+    void initMetricMocks(
+        const std::vector<LabeledMetricParameters>& metricParameters)
     {
-        ON_CALL(*metricMocks[0], getReading())
-            .WillByDefault(ReturnRefOfCopy(MetricValue{"a", "b", 17.1, 114}));
-        ON_CALL(*metricMocks[1], getReading())
-            .WillByDefault(ReturnRefOfCopy(MetricValue{"aa", "bb", 42.0, 74}));
-        ON_CALL(*metricMocks[2], getReading())
-            .WillByDefault(
-                ReturnRefOfCopy(MetricValue{"aaa", "bbb", 100.7, 21}));
-
-        for (size_t i = 0; i < metricMocks.size(); ++i)
+        for (auto i = metricMocks.size(); i < metricParameters.size(); ++i)
         {
-            using namespace std::string_literals;
+            metricMocks.emplace_back(std::make_shared<NiceMock<MetricMock>>());
+        }
+        metricMocks.resize(metricParameters.size());
 
-            auto id = std::to_string(i);
+        std::vector<MetricValue> readings{{MetricValue{"a", "b", 17.1, 114},
+                                           MetricValue{"aa", "bb", 42.0, 74}}};
+        readings.resize(metricParameters.size());
 
-            auto sensorParameters =
-                LabeledSensorParameters("service"s + id, "path"s + id);
-            auto metricParameters = LabeledMetricParameters(
-                std::move(sensorParameters), utils::toOperationType(i),
-                "id"s + id, "metadata"s + id);
-
+        for (size_t i = 0; i < metricParameters.size(); ++i)
+        {
+            ON_CALL(*metricMocks[i], getReadings())
+                .WillByDefault(ReturnRefOfCopy(std::vector({readings[i]})));
             ON_CALL(*metricMocks[i], dumpConfiguration())
-                .WillByDefault(Return(std::move(metricParameters)));
+                .WillByDefault(Return(metricParameters[i]));
         }
     }
 
@@ -73,12 +65,13 @@
 
     std::unique_ptr<Report> makeReport(const ReportParams& params)
     {
+        initMetricMocks(params.metricParameters());
+
         return std::make_unique<Report>(
             DbusEnvironment::getIoc(), DbusEnvironment::getObjServer(),
             params.reportName(), params.reportingType(),
             params.emitReadingUpdate(), params.logToMetricReportCollection(),
-            params.interval(), params.readingParameters(), *reportManagerMock,
-            storageMock,
+            params.interval(), *reportManagerMock, storageMock,
             utils::convContainer<std::shared_ptr<interfaces::Metric>>(
                 metricMocks));
     }
@@ -126,7 +119,7 @@
                                                  const T& newValue)
     {
         auto setPromise = std::promise<boost::system::error_code>();
-        auto setFuture = setPromise.get_future();
+        auto future = setPromise.get_future();
         sdbusplus::asio::setProperty(
             *DbusEnvironment::getBus(), DbusEnvironment::serviceName(), path,
             Report::reportIfaceName, property, std::move(newValue),
@@ -134,7 +127,7 @@
                  std::move(setPromise)](boost::system::error_code ec) mutable {
                 setPromise.set_value(ec);
             });
-        return DbusEnvironment::waitForFuture(std::move(setFuture));
+        return DbusEnvironment::waitForFuture(std::move(future));
     }
 
     boost::system::error_code deleteReport(const std::string& path)
@@ -153,9 +146,9 @@
     EXPECT_THAT(
         getProperty<bool>(sut->getPath(), "LogToMetricReportsCollection"),
         Eq(defaultParams.logToMetricReportCollection()));
-    EXPECT_THAT(
-        getProperty<ReadingParameters>(sut->getPath(), "ReadingParameters"),
-        Eq(defaultParams.readingParameters()));
+    EXPECT_THAT(getProperty<ReadingParameters>(
+                    sut->getPath(), "ReadingParametersFutureVersion"),
+                Eq(toReadingParameters(defaultParams.metricParameters())));
 }
 
 TEST_F(TestReport, readingsAreInitialyEmpty)
@@ -247,7 +240,7 @@
 
 INSTANTIATE_TEST_SUITE_P(
     _, TestReportStore,
-    Values(std::make_pair("Version"s, nlohmann::json(3)),
+    Values(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())),
@@ -262,20 +255,25 @@
                "ReadingParameters",
                nlohmann::json(
                    {{{tstring::SensorPath::str(),
-                      {{"service", "service0"}, {"path", "path0"}}},
+                      {{{tstring::Service::str(), "Service"},
+                        {tstring::Path::str(),
+                         "/xyz/openbmc_project/sensors/power/p1"}}}},
                      {tstring::OperationType::str(), OperationType::single},
-                     {tstring::Id::str(), "id0"},
-                     {tstring::MetricMetadata::str(), "metadata0"}},
+                     {tstring::Id::str(), "MetricId1"},
+                     {tstring::MetricMetadata::str(), "Metadata1"},
+                     {tstring::CollectionTimeScope::str(),
+                      CollectionTimeScope::point},
+                     {tstring::CollectionDuration::str(), 0}},
                     {{tstring::SensorPath::str(),
-                      {{"service", "service1"}, {"path", "path1"}}},
-                     {tstring::OperationType::str(), OperationType::max},
-                     {tstring::Id::str(), "id1"},
-                     {tstring::MetricMetadata::str(), "metadata1"}},
-                    {{tstring::SensorPath::str(),
-                      {{"service", "service2"}, {"path", "path2"}}},
-                     {tstring::OperationType::str(), OperationType::min},
-                     {tstring::Id::str(), "id2"},
-                     {tstring::MetricMetadata::str(), "metadata2"}}}))));
+                      {{{tstring::Service::str(), "Service"},
+                        {tstring::Path::str(),
+                         "/xyz/openbmc_project/sensors/power/p2"}}}},
+                     {tstring::OperationType::str(), OperationType::single},
+                     {tstring::Id::str(), "MetricId2"},
+                     {tstring::MetricMetadata::str(), "Metadata2"},
+                     {tstring::CollectionTimeScope::str(),
+                      CollectionTimeScope::point},
+                     {tstring::CollectionDuration::str(), 0}}}))));
 
 TEST_P(TestReportStore, settingPersistencyToTrueStoresReport)
 {
@@ -422,8 +420,7 @@
 
     EXPECT_THAT(readings,
                 ElementsAre(std::make_tuple("a"s, "b"s, 17.1, 114u),
-                            std::make_tuple("aa"s, "bb"s, 42.0, 74u),
-                            std::make_tuple("aaa"s, "bbb"s, 100.7, 21u)));
+                            std::make_tuple("aa"s, "bb"s, 42.0, 74u)));
 }
 
 class TestReportNonOnRequestType :
@@ -499,8 +496,7 @@
 
     EXPECT_THAT(readings,
                 ElementsAre(std::make_tuple("a"s, "b"s, 17.1, 114u),
-                            std::make_tuple("aa"s, "bb"s, 42.0, 74u),
-                            std::make_tuple("aaa"s, "bbb"s, 100.7, 21u)));
+                            std::make_tuple("aa"s, "bb"s, 42.0, 74u)));
 }
 
 class TestReportInitialization : public TestReport
diff --git a/tests/src/test_report_manager.cpp b/tests/src/test_report_manager.cpp
index 4ad5479..2287707 100644
--- a/tests/src/test_report_manager.cpp
+++ b/tests/src/test_report_manager.cpp
@@ -36,6 +36,9 @@
 
     void SetUp() override
     {
+        EXPECT_CALL(reportFactoryMock, convertMetricParams(_, _))
+            .Times(AnyNumber());
+
         sut = std::make_unique<ReportManager>(std::move(reportFactoryMockPtr),
                                               std::move(storageMockPtr),
                                               DbusEnvironment::getObjServer());
@@ -57,11 +60,11 @@
                 addReportPromise.set_value({ec, path});
             },
             DbusEnvironment::serviceName(), ReportManager::reportManagerPath,
-            ReportManager::reportManagerIfaceName, "AddReport",
+            ReportManager::reportManagerIfaceName, "AddReportFutureVersion",
             params.reportName(), params.reportingType(),
             params.emitReadingUpdate(), params.logToMetricReportCollection(),
-            static_cast<uint64_t>(params.interval().count()),
-            params.readingParameters());
+            params.interval().count(),
+            toReadingParameters(params.metricParameters()));
         return DbusEnvironment::waitForFuture(addReportPromise.get_future());
     }
 
@@ -74,10 +77,10 @@
             *DbusEnvironment::getBus(), DbusEnvironment::serviceName(),
             ReportManager::reportManagerPath,
             ReportManager::reportManagerIfaceName, property,
-            [&propertyPromise](boost::system::error_code ec, T t) {
+            [&propertyPromise](const boost::system::error_code& ec, T t) {
                 if (ec)
                 {
-                    utils::setException(propertyPromise, "GetProperty failed");
+                    utils::setException(propertyPromise, "Get property failed");
                     return;
                 }
                 propertyPromise.set_value(t);
@@ -99,7 +102,7 @@
 TEST_F(TestReportManager, minInterval)
 {
     EXPECT_THAT(getProperty<uint64_t>("MinInterval"),
-                Eq(static_cast<uint64_t>(ReportManager::minInterval.count())));
+                Eq(ReportManager::minInterval.count()));
 }
 
 TEST_F(TestReportManager, maxReports)
@@ -110,7 +113,8 @@
 
 TEST_F(TestReportManager, addReport)
 {
-    reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
+    EXPECT_CALL(reportFactoryMock, convertMetricParams(_, _));
+    reportFactoryMock.expectMake(reportParams, Ref(*sut), Ref(storageMock))
         .WillOnce(Return(ByMove(std::move(reportMockPtr))));
 
     auto [ec, path] = addReport(reportParams);
@@ -123,7 +127,7 @@
     std::string reportName =
         prepareReportNameWithLength(ReportManager::maxReportNameLength);
     reportParams.reportName(reportName);
-    reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock));
+    reportFactoryMock.expectMake(reportParams, Ref(*sut), Ref(storageMock));
 
     auto [ec, path] = addReport(reportParams);
 
@@ -133,9 +137,7 @@
 
 TEST_F(TestReportManager, DISABLED_failToAddReportWithTooLongName)
 {
-    reportFactoryMock.expectMake(_, std::nullopt, Ref(*sut), Ref(storageMock))
-        .Times(0);
-    reportFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock), _)
+    reportFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
         .Times(0);
 
     reportParams.reportName(
@@ -149,7 +151,7 @@
 
 TEST_F(TestReportManager, DISABLED_failToAddReportTwice)
 {
-    reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
+    reportFactoryMock.expectMake(reportParams, Ref(*sut), Ref(storageMock))
         .WillOnce(Return(ByMove(std::move(reportMockPtr))));
 
     addReport(reportParams);
@@ -162,9 +164,7 @@
 
 TEST_F(TestReportManager, DISABLED_failToAddReportWithInvalidInterval)
 {
-    reportFactoryMock.expectMake(_, std::nullopt, Ref(*sut), Ref(storageMock))
-        .Times(0);
-    reportFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock), _)
+    reportFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
         .Times(0);
 
     reportParams.reportingType("Periodic");
@@ -178,9 +178,7 @@
 
 TEST_F(TestReportManager, DISABLED_failToAddReportWithInvalidReportingType)
 {
-    reportFactoryMock.expectMake(_, std::nullopt, Ref(*sut), Ref(storageMock))
-        .Times(0);
-    reportFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock), _)
+    reportFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
         .Times(0);
 
     reportParams.reportingType("Invalid");
@@ -193,17 +191,15 @@
 
 TEST_F(TestReportManager, DISABLED_failToAddReportWithMoreSensorsThanExpected)
 {
-    reportFactoryMock.expectMake(_, std::nullopt, Ref(*sut), Ref(storageMock))
-        .Times(0);
-    reportFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock), _)
+    reportFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
         .Times(0);
 
-    auto readingParams = reportParams.readingParameters();
+    auto metricParams = reportParams.metricParameters();
     for (size_t i = 0; i < ReportManager::maxReadingParams + 1; i++)
     {
-        readingParams.push_back(readingParams.front());
+        metricParams.push_back(metricParams.front());
     }
-    reportParams.readingParameters(std::move(readingParams));
+    reportParams.metricParameters(std::move(metricParams));
 
     auto [ec, path] = addReport(reportParams);
 
@@ -213,7 +209,7 @@
 
 TEST_F(TestReportManager, DISABLED_failToAddReportWhenMaxReportIsReached)
 {
-    reportFactoryMock.expectMake(_, std::nullopt, Ref(*sut), Ref(storageMock))
+    reportFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
         .Times(ReportManager::maxReports);
 
     for (size_t i = 0; i < ReportManager::maxReports; i++)
@@ -236,8 +232,8 @@
 {
     {
         InSequence seq;
-        reportFactoryMock
-            .expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
+        EXPECT_CALL(reportFactoryMock, convertMetricParams(_, _));
+        reportFactoryMock.expectMake(reportParams, Ref(*sut), Ref(storageMock))
             .WillOnce(Return(ByMove(std::move(reportMockPtr))));
         EXPECT_CALL(reportMock, Die());
         EXPECT_CALL(checkPoint, Call("end"));
@@ -264,8 +260,8 @@
 {
     {
         InSequence seq;
-        reportFactoryMock
-            .expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
+        EXPECT_CALL(reportFactoryMock, convertMetricParams(_, _));
+        reportFactoryMock.expectMake(reportParams, Ref(*sut), Ref(storageMock))
             .WillOnce(Return(ByMove(std::move(reportMockPtr))));
         EXPECT_CALL(reportMock, Die());
         EXPECT_CALL(checkPoint, Call("end"));
@@ -279,7 +275,7 @@
 
 TEST_F(TestReportManager, updateReportCallsUpdateReadingsForExistReport)
 {
-    reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
+    reportFactoryMock.expectMake(reportParams, Ref(*sut), Ref(storageMock))
         .WillOnce(Return(ByMove(std::move(reportMockPtr))));
     EXPECT_CALL(reportMock, updateReadings());
 
@@ -289,7 +285,7 @@
 
 TEST_F(TestReportManager, updateReportDoNothingIfReportDoesNotExist)
 {
-    reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
+    reportFactoryMock.expectMake(reportParams, Ref(*sut), Ref(storageMock))
         .WillOnce(Return(ByMove(std::move(reportMockPtr))));
     EXPECT_CALL(reportMock, updateReadings()).Times(0);
 
@@ -313,14 +309,17 @@
 TEST_P(TestReportManagerWithAggregationOperationType,
        addReportWithDifferentOperationTypes)
 {
-    reportParams.readingParameters(
-        {{{sdbusplus::message::object_path(
-              "/xyz/openbmc_project/sensors/power/p1")},
-          utils::enumToString(operationType),
-          "MetricId1",
-          "Metadata1"}});
+    reportParams.metricParameters(
+        std::vector<LabeledMetricParameters>{{LabeledMetricParameters{
+            {LabeledSensorParameters{"Service",
+                                     "/xyz/openbmc_project/sensors/power/p1"}},
+            operationType,
+            "MetricId1",
+            "Metadata1",
+            CollectionTimeScope::point,
+            CollectionDuration(Milliseconds(0u))}}});
 
-    reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
+    reportFactoryMock.expectMake(reportParams, Ref(*sut), Ref(storageMock))
         .WillOnce(Return(ByMove(std::move(reportMockPtr))));
 
     auto [ec, path] = addReport(reportParams);
@@ -337,6 +336,8 @@
 
     void SetUp() override
     {
+        EXPECT_CALL(reportFactoryMock, convertMetricParams(_, _)).Times(0);
+
         ON_CALL(storageMock, list())
             .WillByDefault(Return(std::vector<FilePath>{FilePath("report1")}));
         ON_CALL(storageMock, load(FilePath("report1")))
@@ -350,17 +351,6 @@
                                               DbusEnvironment::getObjServer());
     }
 
-    static std::vector<LabeledMetricParameters>
-        convertToLabeled(const ReadingParameters& params)
-    {
-        return utils::transform(params, [](const auto& item) {
-            return LabeledMetricParameters(
-                LabeledSensorParameters("service", std::get<0>(item)),
-                utils::stringToOperationType(std::get<1>(item)),
-                std::get<2>(item), std::get<3>(item));
-        });
-    }
-
     nlohmann::json data = nlohmann::json{
         {"Version", Report::reportVersion},
         {"Name", reportParams.reportName()},
@@ -369,15 +359,12 @@
         {"LogToMetricReportsCollection",
          reportParams.logToMetricReportCollection()},
         {"Interval", reportParams.interval().count()},
-        {"ReadingParameters",
-         convertToLabeled(reportParams.readingParameters())}};
+        {"ReadingParameters", reportParams.metricParameters()}};
 };
 
 TEST_F(TestReportManagerStorage, reportManagerCtorAddReportFromStorage)
 {
-    reportFactoryMock.expectMake(
-        reportParams, _, Ref(storageMock),
-        ElementsAreArray(convertToLabeled(reportParams.readingParameters())));
+    reportFactoryMock.expectMake(reportParams, _, Ref(storageMock));
 
     makeReportManager();
 }
diff --git a/tests/src/test_trigger.cpp b/tests/src/test_trigger.cpp
index 2336267..7529017 100644
--- a/tests/src/test_trigger.cpp
+++ b/tests/src/test_trigger.cpp
@@ -27,10 +27,10 @@
             .thresholdParams(std::vector<discrete::LabeledThresholdParam>{
                 discrete::LabeledThresholdParam{
                     "userId", discrete::Severity::warning,
-                    std::chrono::milliseconds(10).count(), "15.2"},
+                    Milliseconds(10).count(), "15.2"},
                 discrete::LabeledThresholdParam{
                     "userId_2", discrete::Severity::critical,
-                    std::chrono::milliseconds(5).count(), "32.7"},
+                    Milliseconds(5).count(), "32.7"},
             });
 
     std::unique_ptr<TriggerManagerMock> triggerManagerMockPtr =