Review fixes for 'Created metric class'

- Changed metric to_json to dumpConfiguration returning LabeledTuple
- LabeledTuple can be created and assigned directly to json
- LabeledTuple can be readed from json using json.get<LabeledTuple>
- Added PrintTo for LabeledMetricParams, LabeledSensorParams
- Added helper method expectMake to ReportFactoryMock
- sensorPaths are serialized to tuple<service, path> instead of single
  field with service and path separated via ':'
- Changed configuration version from 1 to 2

Change-Id: I7c45fb584687172f88fd549a93329264793b0b8e
Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
diff --git a/src/report_factory.cpp b/src/report_factory.cpp
index e4689aa..b8b5518 100644
--- a/src/report_factory.cpp
+++ b/src/report_factory.cpp
@@ -13,31 +13,35 @@
 {}
 
 std::unique_ptr<interfaces::Report> ReportFactory::make(
-    std::optional<std::reference_wrapper<boost::asio::yield_context>> yield,
+    boost::asio::yield_context& yield, const std::string& name,
+    const std::string& reportingType, bool emitsReadingsSignal,
+    bool logToMetricReportsCollection, std::chrono::milliseconds period,
+    const ReadingParameters& metricParams,
+    interfaces::ReportManager& reportManager,
+    interfaces::JsonStorage& reportStorage) const
+{
+    return make(name, reportingType, emitsReadingsSignal,
+                logToMetricReportsCollection, period, metricParams,
+                reportManager, reportStorage,
+                convertMetricParams(yield, metricParams));
+}
+
+std::unique_ptr<interfaces::Report> ReportFactory::make(
     const std::string& name, const std::string& reportingType,
     bool emitsReadingsSignal, bool logToMetricReportsCollection,
     std::chrono::milliseconds period, const ReadingParameters& metricParams,
     interfaces::ReportManager& reportManager,
-    interfaces::JsonStorage& reportStorage) const
+    interfaces::JsonStorage& reportStorage,
+    std::vector<LabeledMetricParameters> labeledMetricParams) const
 {
-    std::optional<std::vector<ReportFactory::SensorTree>> sensorTree;
-
-    std::vector<std::shared_ptr<interfaces::Metric>> metrics;
-    metrics.reserve(metricParams.size());
-
-    for (const auto& [sensorPaths, op, id, metadata] : metricParams)
-    {
-        if (!sensorTree && yield && sensorPaths.size() > 0)
-        {
-            sensorTree = getSensorTree(*yield);
-        }
-
-        std::vector<std::shared_ptr<interfaces::Sensor>> sensors =
-            getSensors(sensorTree, sensorPaths);
-
-        metrics.emplace_back(
-            std::make_shared<Metric>(std::move(sensors), op, id, metadata));
-    }
+    std::vector<std::shared_ptr<interfaces::Metric>> metrics = utils::transform(
+        labeledMetricParams,
+        [this](const LabeledMetricParameters& param)
+            -> std::shared_ptr<interfaces::Metric> {
+            return std::make_shared<Metric>(
+                getSensors(param.at_index<0>()), param.at_index<1>(),
+                param.at_index<2>(), param.at_index<3>());
+        });
 
     return std::make_unique<Report>(
         bus->get_io_context(), objServer, name, reportingType,
@@ -46,58 +50,57 @@
 }
 
 std::vector<std::shared_ptr<interfaces::Sensor>> ReportFactory::getSensors(
-    const std::optional<std::vector<ReportFactory::SensorTree>>& tree,
-    const std::vector<sdbusplus::message::object_path>& sensorPaths) const
+    const std::vector<LabeledSensorParameters>& sensorPaths) const
 {
-    if (tree)
-    {
-        std::vector<std::shared_ptr<interfaces::Sensor>> sensors;
+    return utils::transform(sensorPaths,
+                            [this](const LabeledSensorParameters& param)
+                                -> std::shared_ptr<interfaces::Sensor> {
+                                using namespace utils::tstring;
 
-        for (const auto& [sensor, ifacesMap] : *tree)
-        {
-            auto it = std::find(sensorPaths.begin(), sensorPaths.end(), sensor);
-            if (it != sensorPaths.end())
-            {
-                for (const auto& [service, ifaces] : ifacesMap)
-                {
-                    sensors.emplace_back(sensorCache.makeSensor<Sensor>(
-                        service, sensor, bus->get_io_context(), bus));
-                }
-            }
-        }
-
-        return sensors;
-    }
-    else
-    {
-        return utils::transform(
-            sensorPaths,
-            [this](const std::string& sensor)
-                -> std::shared_ptr<interfaces::Sensor> {
-                std::string::size_type pos = sensor.find_first_of(":");
-                auto service = sensor.substr(0, pos);
-                auto path = sensor.substr(pos + 1);
-                return sensorCache.makeSensor<Sensor>(
-                    service, path, bus->get_io_context(), bus);
-            });
-    }
+                                return sensorCache.makeSensor<Sensor>(
+                                    param.at_label<Service>(),
+                                    param.at_label<Path>(),
+                                    bus->get_io_context(), bus);
+                            });
 }
 
-std::vector<ReportFactory::SensorTree>
-    ReportFactory::getSensorTree(boost::asio::yield_context& yield) const
+std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
+    boost::asio::yield_context& yield,
+    const ReadingParameters& metricParams) const
 {
     std::array<const char*, 1> interfaces = {
         "xyz.openbmc_project.Sensor.Value"};
     boost::system::error_code ec;
 
-    auto result = bus->yield_method_call<std::vector<SensorTree>>(
+    auto tree = bus->yield_method_call<std::vector<SensorTree>>(
         yield, ec, "xyz.openbmc_project.ObjectMapper",
         "/xyz/openbmc_project/object_mapper",
         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
         "/xyz/openbmc_project/sensors", 2, interfaces);
     if (ec)
     {
-        throw std::runtime_error("failed");
+        throw std::runtime_error("Failed to query ObjectMapper!");
     }
-    return result;
+
+    return utils::transform(metricParams, [&tree](const auto& item) {
+        std::vector<LabeledSensorParameters> sensors;
+
+        for (const auto& sensorPath : std::get<0>(item))
+        {
+            auto it = std::find_if(
+                tree.begin(), tree.end(),
+                [&sensorPath](const auto& v) { return v.first == sensorPath; });
+
+            if (it != tree.end())
+            {
+                for (const auto& [service, ifaces] : it->second)
+                {
+                    sensors.emplace_back(service, sensorPath);
+                }
+            }
+        }
+
+        return LabeledMetricParameters(std::move(sensors), std::get<1>(item),
+                                       std::get<2>(item), std::get<3>(item));
+    });
 }