Read persistent triggers from storage

Read json storage file for persistent triggers.
Add trigger to telemetry service.
Cover code with UTs.

Tested:
  - Passed unit tests
  - Tested on QEMU
    * starting app without configuration
    * restart app with configuration stored
    * restart app with configuration in incorrect version
    * restart app with configuration malformed

Change-Id: I2cb9324abdb8323be8a7f0c932ed7f70c5bc2891
Signed-off-by: Cezary Zwolak <cezary.zwolak@intel.com>
Signed-off-by: Lukasz Kazmierczak <lukasz.kazmierczak@intel.com>
diff --git a/tests/src/test_trigger.cpp b/tests/src/test_trigger.cpp
index f396589..cf7d96c 100644
--- a/tests/src/test_trigger.cpp
+++ b/tests/src/test_trigger.cpp
@@ -4,7 +4,12 @@
 #include "mocks/trigger_manager_mock.hpp"
 #include "params/trigger_params.hpp"
 #include "trigger.hpp"
+#include "utils/conversion_trigger.hpp"
 #include "utils/set_exception.hpp"
+#include "utils/transform.hpp"
+#include "utils/tstring.hpp"
+
+#include <boost/range/combine.hpp>
 
 using namespace testing;
 using namespace std::literals::string_literals;
@@ -15,6 +20,18 @@
 {
   public:
     TriggerParams triggerParams;
+    TriggerParams triggerDiscreteParams =
+        TriggerParams()
+            .name("Trigger2")
+            .isDiscrete(true)
+            .thresholdParams(std::vector<discrete::LabeledThresholdParam>{
+                discrete::LabeledThresholdParam{
+                    "userId", discrete::Severity::warning,
+                    std::chrono::milliseconds(10).count(), 15.2},
+                discrete::LabeledThresholdParam{
+                    "userId_2", discrete::Severity::critical,
+                    std::chrono::milliseconds(5).count(), 32.7},
+            });
 
     std::unique_ptr<TriggerManagerMock> triggerManagerMockPtr =
         std::make_unique<NiceMock<TriggerManagerMock>>();
@@ -26,13 +43,22 @@
         sut = makeTrigger(triggerParams);
     }
 
+    static std::vector<LabeledSensorInfo>
+        convertToLabeledSensor(const SensorsInfo& sensorsInfo)
+    {
+        return utils::transform(sensorsInfo, [](const auto& sensorInfo) {
+            const auto& [sensorPath, sensorMetadata] = sensorInfo;
+            return LabeledSensorInfo("service1", sensorPath, sensorMetadata);
+        });
+    }
+
     std::unique_ptr<Trigger> makeTrigger(const TriggerParams& params)
     {
         return std::make_unique<Trigger>(
             DbusEnvironment::getIoc(), DbusEnvironment::getObjServer(),
             params.name(), params.isDiscrete(), params.logToJournal(),
-            params.logToRedfish(), params.updateReport(), params.sensors(),
-            params.reportNames(), params.thresholdParams(),
+            params.logToRedfish(), params.updateReport(), params.reportNames(),
+            params.sensors(), params.thresholdParams(),
             std::vector<std::shared_ptr<interfaces::Threshold>>{},
             *triggerManagerMockPtr, storageMock);
     }
@@ -104,16 +130,67 @@
                 Eq(triggerParams.logToRedfish()));
     EXPECT_THAT(getProperty<bool>(sut->getPath(), "UpdateReport"),
                 Eq(triggerParams.updateReport()));
-    EXPECT_THAT((getProperty<std::vector<
-                     std::pair<sdbusplus::message::object_path, std::string>>>(
-                    sut->getPath(), "Sensors")),
-                Eq(triggerParams.sensors()));
+    EXPECT_THAT((getProperty<SensorsInfo>(sut->getPath(), "Sensors")),
+                Eq(utils::fromLabeledSensorsInfo(triggerParams.sensors())));
     EXPECT_THAT(
         getProperty<std::vector<std::string>>(sut->getPath(), "ReportNames"),
         Eq(triggerParams.reportNames()));
     EXPECT_THAT(
         getProperty<TriggerThresholdParams>(sut->getPath(), "Thresholds"),
-        Eq(triggerParams.thresholdParams()));
+        Eq(std::visit(utils::FromLabeledThresholdParamConversion(),
+                      triggerParams.thresholdParams())));
+}
+
+TEST_F(TestTrigger, checkIfNumericCoversionsAreGood)
+{
+    const auto& labeledParamsBase =
+        std::get<std::vector<numeric::LabeledThresholdParam>>(
+            triggerParams.thresholdParams());
+    const auto paramsToCheck =
+        std::visit(utils::FromLabeledThresholdParamConversion(),
+                   triggerParams.thresholdParams());
+    const auto labeledParamsToCheck =
+        std::get<std::vector<numeric::LabeledThresholdParam>>(std::visit(
+            utils::ToLabeledThresholdParamConversion(), paramsToCheck));
+
+    for (const auto& [tocheck, base] :
+         boost::combine(labeledParamsToCheck, labeledParamsBase))
+    {
+        EXPECT_THAT(tocheck.at_label<utils::tstring::Type>(),
+                    Eq(base.at_label<utils::tstring::Type>()));
+        EXPECT_THAT(tocheck.at_label<utils::tstring::Direction>(),
+                    Eq(base.at_label<utils::tstring::Direction>()));
+        EXPECT_THAT(tocheck.at_label<utils::tstring::DwellTime>(),
+                    Eq(base.at_label<utils::tstring::DwellTime>()));
+        EXPECT_THAT(tocheck.at_label<utils::tstring::ThresholdValue>(),
+                    Eq(base.at_label<utils::tstring::ThresholdValue>()));
+    }
+}
+
+TEST_F(TestTrigger, checkIfDiscreteCoversionsAreGood)
+{
+    const auto& labeledParamsBase =
+        std::get<std::vector<discrete::LabeledThresholdParam>>(
+            triggerDiscreteParams.thresholdParams());
+    const auto paramsToCheck =
+        std::visit(utils::FromLabeledThresholdParamConversion(),
+                   triggerDiscreteParams.thresholdParams());
+    const auto labeledParamsToCheck =
+        std::get<std::vector<discrete::LabeledThresholdParam>>(std::visit(
+            utils::ToLabeledThresholdParamConversion(), paramsToCheck));
+
+    for (const auto& [tocheck, base] :
+         boost::combine(labeledParamsToCheck, labeledParamsBase))
+    {
+        EXPECT_THAT(tocheck.at_label<utils::tstring::UserId>(),
+                    Eq(base.at_label<utils::tstring::UserId>()));
+        EXPECT_THAT(tocheck.at_label<utils::tstring::Severity>(),
+                    Eq(base.at_label<utils::tstring::Severity>()));
+        EXPECT_THAT(tocheck.at_label<utils::tstring::DwellTime>(),
+                    Eq(base.at_label<utils::tstring::DwellTime>()));
+        EXPECT_THAT(tocheck.at_label<utils::tstring::ThresholdValue>(),
+                    Eq(base.at_label<utils::tstring::ThresholdValue>()));
+    }
 }
 
 TEST_F(TestTrigger, deleteTrigger)
@@ -130,12 +207,12 @@
     EXPECT_THAT(ec.value(), Eq(EBADR));
 }
 
-TEST_F(TestTrigger, settingPersistencyToFalseRemovesReportFromStorage)
+TEST_F(TestTrigger, settingPersistencyToFalseRemovesTriggerFromStorage)
 {
     EXPECT_CALL(storageMock, remove(to_file_path(sut->getName())));
 
     bool persistent = false;
-    EXPECT_THAT(setProperty(sut->getPath(), "Persistent", persistent).value(),
+    EXPECT_THAT(setProperty(sut->getPath(), "Persistent", persistent),
                 Eq(boost::system::errc::success));
     EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistent"),
                 Eq(persistent));
@@ -150,7 +227,7 @@
     nlohmann::json storedConfiguration;
 };
 
-TEST_F(TestTriggerErrors, throwingExceptionDoesNotStoreTriggerReportNames)
+TEST_F(TestTriggerErrors, exceptionDuringTriggerStoreDisablesPersistency)
 {
     EXPECT_CALL(storageMock, store(_, _))
         .WillOnce(Throw(std::runtime_error("Generic error!")));
@@ -171,15 +248,20 @@
 class TestTriggerStore : public TestTrigger
 {
   public:
+    nlohmann::json storedConfiguration;
+    nlohmann::json storedDiscreteConfiguration;
+    std::unique_ptr<Trigger> sutDiscrete;
+
     void SetUp() override
     {
         ON_CALL(storageMock, store(_, _))
             .WillByDefault(SaveArg<1>(&storedConfiguration));
-
         sut = makeTrigger(triggerParams);
-    }
 
-    nlohmann::json storedConfiguration;
+        ON_CALL(storageMock, store(_, _))
+            .WillByDefault(SaveArg<1>(&storedDiscreteConfiguration));
+        sutDiscrete = makeTrigger(triggerDiscreteParams);
+    }
 };
 
 TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerVersion)
@@ -225,29 +307,50 @@
 TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerSensors)
 {
     nlohmann::json expectedItem;
+    expectedItem["service"] = "service1";
     expectedItem["sensorPath"] =
         "/xyz/openbmc_project/sensors/temperature/BMC_Temp";
-    expectedItem["sensorMetadata"] = "";
+    expectedItem["sensorMetadata"] = "metadata1";
 
     ASSERT_THAT(storedConfiguration.at("Sensors"), ElementsAre(expectedItem));
 }
 
 TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerThresholdParams)
 {
-    ASSERT_THAT(storedConfiguration.at("ThresholdParamsDiscriminator"), Eq(0));
-
     nlohmann::json expectedItem0;
     expectedItem0["type"] = 0;
     expectedItem0["dwellTime"] = 10;
     expectedItem0["direction"] = 1;
-    expectedItem0["thresholdValue"] = 0.0;
+    expectedItem0["thresholdValue"] = 0.5;
 
     nlohmann::json expectedItem1;
     expectedItem1["type"] = 3;
     expectedItem1["dwellTime"] = 10;
     expectedItem1["direction"] = 2;
-    expectedItem1["thresholdValue"] = 90.0;
+    expectedItem1["thresholdValue"] = 90.2;
 
+    ASSERT_THAT(storedConfiguration.at("ThresholdParamsDiscriminator"), Eq(0));
     ASSERT_THAT(storedConfiguration.at("ThresholdParams"),
                 ElementsAre(expectedItem0, expectedItem1));
 }
+
+TEST_F(TestTriggerStore,
+       settingPersistencyToTrueStoresDiscreteTriggerThresholdParams)
+{
+    nlohmann::json expectedItem0;
+    expectedItem0["userId"] = "userId";
+    expectedItem0["severity"] = discrete::Severity::warning;
+    expectedItem0["dwellTime"] = 10;
+    expectedItem0["thresholdValue"] = 15.2;
+
+    nlohmann::json expectedItem1;
+    expectedItem1["userId"] = "userId_2";
+    expectedItem1["severity"] = discrete::Severity::critical;
+    expectedItem1["dwellTime"] = 5;
+    expectedItem1["thresholdValue"] = 32.7;
+
+    ASSERT_THAT(storedDiscreteConfiguration.at("ThresholdParamsDiscriminator"),
+                Eq(1));
+    ASSERT_THAT(storedDiscreteConfiguration.at("ThresholdParams"),
+                ElementsAre(expectedItem0, expectedItem1));
+}