Changed dbus add report interface

- metric parameters now take single sensor instead of list
- added interface support for new operation types

Tested:
- All telemetry tests are passing.

Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
Change-Id: Id3a41c48e81a287e7d205ae1c747daa36d4cdb29
diff --git a/tests/src/helpers/interfaces/labeled_reading_parameter_helpers.hpp b/tests/src/helpers/interfaces/labeled_reading_parameter_helpers.hpp
index 3666a62..9a46d0c 100644
--- a/tests/src/helpers/interfaces/labeled_reading_parameter_helpers.hpp
+++ b/tests/src/helpers/interfaces/labeled_reading_parameter_helpers.hpp
@@ -15,8 +15,8 @@
     using testing::PrintToString;
 
     (*os) << "{ ";
-    (*os) << utils::tstring::SensorPaths::str() << ": "
-          << PrintToString(o.at_label<utils::tstring::SensorPaths>()) << ", ";
+    (*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() << ": "
@@ -26,4 +26,4 @@
     (*os) << " }";
 }
 
-} // namespace utils
\ No newline at end of file
+} // namespace utils
diff --git a/tests/src/mocks/metric_mock.hpp b/tests/src/mocks/metric_mock.hpp
index 98bad87..2f31f1e 100644
--- a/tests/src/mocks/metric_mock.hpp
+++ b/tests/src/mocks/metric_mock.hpp
@@ -11,13 +11,12 @@
     {
         using namespace testing;
 
-        ON_CALL(*this, getReadings())
-            .WillByDefault(ReturnRefOfCopy(std::vector<MetricValue>()));
+        ON_CALL(*this, getReading())
+            .WillByDefault(ReturnRefOfCopy(MetricValue()));
     }
 
     MOCK_METHOD(void, initialize, (), (override));
-    MOCK_METHOD(const std::vector<MetricValue>&, getReadings, (),
-                (const, override));
+    MOCK_METHOD(const MetricValue&, getReading, (), (const, override));
     MOCK_METHOD(LabeledMetricParameters, dumpConfiguration, (),
                 (const, override));
 };
diff --git a/tests/src/params/report_params.hpp b/tests/src/params/report_params.hpp
index fa1340c..25422bc 100644
--- a/tests/src/params/report_params.hpp
+++ b/tests/src/params/report_params.hpp
@@ -84,12 +84,12 @@
     ReadingParameters readingParametersProperty = {
         {{sdbusplus::message::object_path(
              "/xyz/openbmc_project/sensors/power/p1")},
-         "SINGLE",
+         utils::enumToString(OperationType::single),
          "MetricId1",
          "Metadata1"},
         {{sdbusplus::message::object_path(
              "/xyz/openbmc_project/sensors/power/p2")},
-         "SINGLE",
+         utils::enumToString(OperationType::single),
          "MetricId2",
          "Metadata2"}};
 };
diff --git a/tests/src/params/trigger_params.hpp b/tests/src/params/trigger_params.hpp
index 464c68b..9aed64d 100644
--- a/tests/src/params/trigger_params.hpp
+++ b/tests/src/params/trigger_params.hpp
@@ -2,6 +2,8 @@
 
 #include "interfaces/trigger_types.hpp"
 
+#include <sdbusplus/message.hpp>
+
 #include <chrono>
 #include <utility>
 
diff --git a/tests/src/test_conversion.cpp b/tests/src/test_conversion.cpp
index e3984ca..f24592f 100644
--- a/tests/src/test_conversion.cpp
+++ b/tests/src/test_conversion.cpp
@@ -4,7 +4,7 @@
 
 using namespace testing;
 
-class TestEnum : public Test
+class TestConversion : public Test
 {
   public:
     enum class Enum
@@ -18,16 +18,63 @@
     {
         return utils::toEnum<Enum, Enum::zero, Enum::two>(x);
     }
+
+    Enum stringToEnum(const std::string& value)
+    {
+        return utils::stringToEnum(convDataEnum, value);
+    }
+
+    std::string enumToString(Enum value)
+    {
+        return std::string(utils::enumToString(convDataEnum, value));
+    }
+
+    static constexpr std::array<std::pair<std::string_view, Enum>, 3>
+        convDataEnum = {
+            {std::make_pair<std::string_view, Enum>("zero", Enum::zero),
+             std::make_pair<std::string_view, Enum>("one", Enum::one),
+             std::make_pair<std::string_view, Enum>("two", Enum::two)}};
 };
 
-TEST_F(TestEnum, passValueInRangeExpectToGetValidOutput)
+TEST_F(TestConversion, passValueInRangeExpectToGetValidOutput)
 {
     EXPECT_EQ(toEnum(0), Enum::zero);
     EXPECT_EQ(toEnum(2), Enum::two);
 }
 
-TEST_F(TestEnum, passInvalidValueExpectToThrowOutOfRangeException)
+TEST_F(TestConversion, passInvalidValueExpectToThrowOutOfRangeException)
 {
     EXPECT_THROW(toEnum(-1), std::out_of_range);
     EXPECT_THROW(toEnum(3), std::out_of_range);
 }
+
+TEST_F(TestConversion, convertsToUnderlyingType)
+{
+    EXPECT_THAT(utils::toUnderlying(Enum::one), Eq(1));
+    EXPECT_THAT(utils::toUnderlying(Enum::two), Eq(2));
+    EXPECT_THAT(utils::toUnderlying(Enum::zero), Eq(0));
+}
+
+TEST_F(TestConversion, convertsEnumToString)
+{
+    EXPECT_THAT(enumToString(Enum::one), Eq("one"));
+    EXPECT_THAT(enumToString(Enum::two), Eq("two"));
+    EXPECT_THAT(enumToString(Enum::zero), Eq("zero"));
+}
+
+TEST_F(TestConversion, convertsStringToEnum)
+{
+    EXPECT_THAT(stringToEnum("one"), Eq(Enum::one));
+    EXPECT_THAT(stringToEnum("two"), Eq(Enum::two));
+    EXPECT_THAT(stringToEnum("zero"), Eq(Enum::zero));
+}
+
+TEST_F(TestConversion, enumToStringThrowsWhenUknownEnumPassed)
+{
+    EXPECT_THROW(enumToString(static_cast<Enum>(77)), std::out_of_range);
+}
+
+TEST_F(TestConversion, stringToEnumThrowsWhenUknownStringPassed)
+{
+    EXPECT_THROW(stringToEnum("four"), std::out_of_range);
+}
diff --git a/tests/src/test_metric.cpp b/tests/src/test_metric.cpp
index 22fc97b..e91750d 100644
--- a/tests/src/test_metric.cpp
+++ b/tests/src/test_metric.cpp
@@ -2,130 +2,111 @@
 #include "metric.hpp"
 #include "mocks/sensor_mock.hpp"
 #include "utils/conv_container.hpp"
+#include "utils/conversion.hpp"
+#include "utils/tstring.hpp"
 
 #include <gmock/gmock.h>
 
 using namespace testing;
+namespace tstring = utils::tstring;
 
 using Timestamp = uint64_t;
 
 class TestMetric : public Test
 {
   public:
-    std::vector<std::shared_ptr<SensorMock>> sensorMocks = {
-        std::make_shared<NiceMock<SensorMock>>(),
-        std::make_shared<NiceMock<SensorMock>>(),
-        std::make_shared<NiceMock<SensorMock>>()};
+    std::shared_ptr<SensorMock> sensorMock =
+        std::make_shared<NiceMock<SensorMock>>();
 
     std::shared_ptr<Metric> sut = std::make_shared<Metric>(
-        utils::convContainer<std::shared_ptr<interfaces::Sensor>>(sensorMocks),
-        "op", "id", "metadata");
+        sensorMock, OperationType::avg, "id", "metadata");
 };
 
 TEST_F(TestMetric, subscribesForSensorDuringInitialization)
 {
-    for (auto& sensor : sensorMocks)
+    EXPECT_CALL(*sensorMock,
+                registerForUpdates(Truly([sut = sut.get()](const auto& a0) {
+                    return a0.lock().get() == sut;
+                })));
+
+    sut->initialize();
+}
+
+TEST_F(TestMetric, containsEmptyReadingAfterCreated)
+{
+    ASSERT_THAT(sut->getReading(), MetricValue({"id", "metadata", 0., 0u}));
+}
+
+class TestMetricAfterInitialization : public TestMetric
+{
+  public:
+    TestMetricAfterInitialization()
     {
-        EXPECT_CALL(*sensor,
-                    registerForUpdates(Truly([sut = sut.get()](const auto& a0) {
-                        return a0.lock().get() == sut;
-                    })));
+        sut->initialize();
     }
+};
 
-    sut->initialize();
+TEST_F(TestMetricAfterInitialization, containsEmptyReading)
+{
+    ASSERT_THAT(sut->getReading(), MetricValue({"id", "metadata", 0., 0u}));
 }
 
-TEST_F(TestMetric, containsNoReadingsWhenNotInitialized)
+TEST_F(TestMetricAfterInitialization, updatesMetricValuesOnSensorUpdate)
 {
-    ASSERT_THAT(sut->getReadings(), ElementsAre());
+    sut->sensorUpdated(*sensorMock, Timestamp{18}, 31.2);
+
+    ASSERT_THAT(sut->getReading(),
+                Eq(MetricValue{"id", "metadata", 31.2, 18u}));
 }
 
-TEST_F(TestMetric, containsEmptyReadingsAfterInitialize)
+TEST_F(TestMetricAfterInitialization,
+       throwsWhenUpdateIsPerformedOnUnknownSensor)
 {
-    sut->initialize();
-
-    ASSERT_THAT(sut->getReadings(),
-                ElementsAre(MetricValue{"id", "metadata", 0., 0u},
-                            MetricValue{"id", "metadata", 0., 0u},
-                            MetricValue{"id", "metadata", 0., 0u}));
-}
-
-TEST_F(TestMetric, throwsWhenUpdateIsPerformedWhenNotInitialized)
-{
-    EXPECT_THROW(sut->sensorUpdated(*sensorMocks[0], Timestamp{10}),
-                 std::out_of_range);
-    EXPECT_THROW(sut->sensorUpdated(*sensorMocks[1], Timestamp{10}, 20.0),
-                 std::out_of_range);
-}
-
-TEST_F(TestMetric, updatesMetricValuesOnSensorUpdate)
-{
-    sut->initialize();
-
-    sut->sensorUpdated(*sensorMocks[2], Timestamp{18}, 31.0);
-    sut->sensorUpdated(*sensorMocks[0], Timestamp{21});
-
-    ASSERT_THAT(sut->getReadings(),
-                ElementsAre(MetricValue{"id", "metadata", 0., 21u},
-                            MetricValue{"id", "metadata", 0., 0u},
-                            MetricValue{"id", "metadata", 31., 18u}));
-}
-
-TEST_F(TestMetric, throwsWhenUpdateIsPerformedOnUnknownSensor)
-{
-    sut->initialize();
-
     auto sensor = std::make_shared<StrictMock<SensorMock>>();
     EXPECT_THROW(sut->sensorUpdated(*sensor, Timestamp{10}), std::out_of_range);
     EXPECT_THROW(sut->sensorUpdated(*sensor, Timestamp{10}, 20.0),
                  std::out_of_range);
 }
 
-TEST_F(TestMetric, containsIdInConfigurationDump)
+TEST_F(TestMetricAfterInitialization, containsIdInConfigurationDump)
 {
     const auto conf = sut->dumpConfiguration();
 
     EXPECT_THAT(conf.at_label<utils::tstring::Id>(), Eq("id"));
-    EXPECT_THAT(conf.to_json().at("id"), Eq(nlohmann::json("id")));
+    EXPECT_THAT(conf.to_json().at(tstring::Id::str()),
+                Eq(nlohmann::json("id")));
 }
 
-TEST_F(TestMetric, containsOpInJsonDump)
+TEST_F(TestMetricAfterInitialization, containsOpInJsonDump)
 {
     const auto conf = sut->dumpConfiguration();
 
-    EXPECT_THAT(conf.at_label<utils::tstring::OperationType>(), Eq("op"));
-    EXPECT_THAT(conf.to_json().at("operationType"), Eq(nlohmann::json("op")));
+    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(TestMetric, containsMetadataInJsonDump)
+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("metricMetadata"),
+    EXPECT_THAT(conf.to_json().at(tstring::MetricMetadata::str()),
                 Eq(nlohmann::json("metadata")));
 }
 
-TEST_F(TestMetric, containsSensorPathsInJsonDump)
+TEST_F(TestMetricAfterInitialization, containsSensorPathInJsonDump)
 {
-    for (size_t i = 0; i < sensorMocks.size(); ++i)
-    {
-        const auto no = std::to_string(i);
-        ON_CALL(*sensorMocks[i], id())
-            .WillByDefault(
-                Return(SensorMock::makeId("service" + no, "path" + no)));
-    }
+    ON_CALL(*sensorMock, id())
+        .WillByDefault(Return(SensorMock::makeId("service1", "path1")));
 
     const auto conf = sut->dumpConfiguration();
 
-    EXPECT_THAT(conf.at_label<utils::tstring::SensorPaths>(),
-                ElementsAre(LabeledSensorParameters("service0", "path0"),
-                            LabeledSensorParameters("service1", "path1"),
-                            LabeledSensorParameters("service2", "path2")));
+    EXPECT_THAT(conf.at_label<utils::tstring::SensorPath>(),
+                Eq(LabeledSensorParameters("service1", "path1")));
     EXPECT_THAT(
-        conf.to_json().at("sensorPaths"),
-        Eq(nlohmann::json({{{"service", "service0"}, {"path", "path0"}},
-                           {{"service", "service1"}, {"path", "path1"}},
-                           {{"service", "service2"}, {"path", "path2"}}})));
+        conf.to_json().at(tstring::SensorPath::str()),
+        Eq(nlohmann::json({{"service", "service1"}, {"path", "path1"}})));
 }
diff --git a/tests/src/test_report.cpp b/tests/src/test_report.cpp
index f6c4ee7..5378f48 100644
--- a/tests/src/test_report.cpp
+++ b/tests/src/test_report.cpp
@@ -8,12 +8,14 @@
 #include "report_manager.hpp"
 #include "utils/conv_container.hpp"
 #include "utils/set_exception.hpp"
+#include "utils/tstring.hpp"
 
 #include <sdbusplus/exception.hpp>
 
 using namespace testing;
 using namespace std::literals::string_literals;
 using namespace std::chrono_literals;
+namespace tstring = utils::tstring;
 
 class TestReport : public Test
 {
@@ -33,13 +35,13 @@
 
     TestReport()
     {
-        ON_CALL(*metricMocks[0], getReadings())
-            .WillByDefault(ReturnRefOfCopy(std::vector<MetricValue>(
-                {MetricValue{"a", "b", 17.1, 114},
-                 MetricValue{"aaa", "bbb", 21.7, 100}})));
-        ON_CALL(*metricMocks[1], getReadings())
-            .WillByDefault(ReturnRefOfCopy(
-                std::vector<MetricValue>({MetricValue{"aa", "bb", 42.0, 74}})));
+        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)
         {
@@ -47,11 +49,11 @@
 
             auto id = std::to_string(i);
 
-            auto sensorParameters = std::vector<LabeledSensorParameters>(
-                {LabeledSensorParameters("service"s + id, "path"s + id)});
-            auto metricParameters =
-                LabeledMetricParameters(std::move(sensorParameters), "op"s + id,
-                                        "id"s + id, "metadata"s + id);
+            auto sensorParameters =
+                LabeledSensorParameters("service"s + id, "path"s + id);
+            auto metricParameters = LabeledMetricParameters(
+                std::move(sensorParameters), utils::toOperationType(i),
+                "id"s + id, "metadata"s + id);
 
             ON_CALL(*metricMocks[i], dumpConfiguration())
                 .WillByDefault(Return(std::move(metricParameters)));
@@ -241,35 +243,35 @@
 
 INSTANTIATE_TEST_SUITE_P(
     _, TestReportStore,
-    Values(
-        std::make_pair("Version"s, nlohmann::json(2)),
-        std::make_pair("Name"s, nlohmann::json(ReportParams().reportName())),
-        std::make_pair("ReportingType",
-                       nlohmann::json(ReportParams().reportingType())),
-        std::make_pair("EmitsReadingsUpdate",
-                       nlohmann::json(ReportParams().emitReadingUpdate())),
-        std::make_pair(
-            "LogToMetricReportsCollection",
-            nlohmann::json(ReportParams().logToMetricReportCollection())),
-        std::make_pair("Interval",
-                       nlohmann::json(ReportParams().interval().count())),
-        std::make_pair(
-            "ReadingParameters",
-            nlohmann::json({{{"sensorPaths",
-                              {{{"service", "service0"}, {"path", "path0"}}}},
-                             {"operationType", "op0"},
-                             {"id", "id0"},
-                             {"metricMetadata", "metadata0"}},
-                            {{"sensorPaths",
-                              {{{"service", "service1"}, {"path", "path1"}}}},
-                             {"operationType", "op1"},
-                             {"id", "id1"},
-                             {"metricMetadata", "metadata1"}},
-                            {{"sensorPaths",
-                              {{{"service", "service2"}, {"path", "path2"}}}},
-                             {"operationType", "op2"},
-                             {"id", "id2"},
-                             {"metricMetadata", "metadata2"}}}))));
+    Values(std::make_pair("Version"s, nlohmann::json(3)),
+           std::make_pair("Name"s, nlohmann::json(ReportParams().reportName())),
+           std::make_pair("ReportingType",
+                          nlohmann::json(ReportParams().reportingType())),
+           std::make_pair("EmitsReadingsUpdate",
+                          nlohmann::json(ReportParams().emitReadingUpdate())),
+           std::make_pair(
+               "LogToMetricReportsCollection",
+               nlohmann::json(ReportParams().logToMetricReportCollection())),
+           std::make_pair("Interval",
+                          nlohmann::json(ReportParams().interval().count())),
+           std::make_pair(
+               "ReadingParameters",
+               nlohmann::json(
+                   {{{tstring::SensorPath::str(),
+                      {{"service", "service0"}, {"path", "path0"}}},
+                     {tstring::OperationType::str(), OperationType::single},
+                     {tstring::Id::str(), "id0"},
+                     {tstring::MetricMetadata::str(), "metadata0"}},
+                    {{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"}}}))));
 
 TEST_P(TestReportStore, settingPersistencyToTrueStoresReport)
 {
@@ -416,8 +418,8 @@
 
     EXPECT_THAT(readings,
                 ElementsAre(std::make_tuple("a"s, "b"s, 17.1, 114u),
-                            std::make_tuple("aaa"s, "bbb"s, 21.7, 100u),
-                            std::make_tuple("aa"s, "bb"s, 42.0, 74u)));
+                            std::make_tuple("aa"s, "bb"s, 42.0, 74u),
+                            std::make_tuple("aaa"s, "bbb"s, 100.7, 21u)));
 }
 
 class TestReportNonOnRequestType :
@@ -493,8 +495,8 @@
 
     EXPECT_THAT(readings,
                 ElementsAre(std::make_tuple("a"s, "b"s, 17.1, 114u),
-                            std::make_tuple("aaa"s, "bbb"s, 21.7, 100u),
-                            std::make_tuple("aa"s, "bb"s, 42.0, 74u)));
+                            std::make_tuple("aa"s, "bb"s, 42.0, 74u),
+                            std::make_tuple("aaa"s, "bbb"s, 100.7, 21u)));
 }
 
 class TestReportInitialization : public TestReport
diff --git a/tests/src/test_report_manager.cpp b/tests/src/test_report_manager.cpp
index 30628d6..65e48f4 100644
--- a/tests/src/test_report_manager.cpp
+++ b/tests/src/test_report_manager.cpp
@@ -5,9 +5,11 @@
 #include "params/report_params.hpp"
 #include "report.hpp"
 #include "report_manager.hpp"
+#include "utils/conversion.hpp"
 #include "utils/transform.hpp"
 
 using namespace testing;
+using namespace std::string_literals;
 using namespace std::chrono_literals;
 
 class TestReportManager : public Test
@@ -246,6 +248,37 @@
     sut->updateReport("NotAReport");
 }
 
+class TestReportManagerWithAggregationOperationType :
+    public TestReportManager,
+    public WithParamInterface<OperationType>
+{
+  public:
+    OperationType operationType = GetParam();
+};
+
+INSTANTIATE_TEST_SUITE_P(_, TestReportManagerWithAggregationOperationType,
+                         Values(OperationType::single, OperationType::max,
+                                OperationType::min, OperationType::avg,
+                                OperationType::sum));
+
+TEST_P(TestReportManagerWithAggregationOperationType,
+       addReportWithDifferentOperationTypes)
+{
+    reportParams.readingParameters(
+        {{{sdbusplus::message::object_path(
+              "/xyz/openbmc_project/sensors/power/p1")},
+          utils::enumToString(operationType),
+          "MetricId1",
+          "Metadata1"}});
+
+    reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
+        .WillOnce(Return(ByMove(std::move(reportMockPtr))));
+
+    auto [ec, path] = addReport(reportParams);
+    EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
+    EXPECT_THAT(path, Eq("/"s + reportParams.reportName()));
+}
+
 class TestReportManagerStorage : public TestReportManager
 {
   public:
@@ -272,12 +305,9 @@
     {
         return utils::transform(params, [](const auto& item) {
             return LabeledMetricParameters(
-                utils::transform(std::get<0>(item),
-                                 [](const auto& elem) {
-                                     return LabeledSensorParameters("service",
-                                                                    elem);
-                                 }),
-                std::get<1>(item), std::get<2>(item), std::get<3>(item));
+                LabeledSensorParameters("service", std::get<0>(item)),
+                utils::stringToOperationType(std::get<1>(item)),
+                std::get<2>(item), std::get<3>(item));
         });
     }