Update Trigger Actions implementation

Dbus trigger action names were modified to reflect separation of
Telemetry Service from Redfish:
- LogToLogService is renamed to LogToJournal,
- RedfishEvent was renamed to LogToRedfishEventLog

Both of those logging actions, now also include trigger id and threshold
name. Threshold naming logic:
- For discrete triggers, it can be specified by user, if left empty it
  will be changed to "{Severity} condition".
- Numeric triggers have no way of naming threshold, instead its type
  will be converted to string, example "UpperWarning"
- Discrete OnChange threshold will always be named "OnChange"

Additionally, defect was found with timestamp attached to Trigger Logs:
it was a steady_clock timestamp instead of system_clock. The function
which was supposed to format it was also working incorrectly, and was
improved to work with milliseconds. This change required major refactor
of unit tests, especially for numeric threshold.

Testing done:
- LogToJournal action is working properly,
- LogToRedfishEventLog action is working properly,
- UTs are passing.

Signed-off-by: Szymon Dompke <szymon.dompke@intel.com>
Change-Id: Iae2490682f0e9e2a610b45fd8af5cc5e21e66f35
diff --git a/tests/src/mocks/clock_mock.hpp b/tests/src/mocks/clock_mock.hpp
new file mode 100644
index 0000000..2008e7e
--- /dev/null
+++ b/tests/src/mocks/clock_mock.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "interfaces/clock.hpp"
+#include "types/duration_types.hpp"
+
+#include <gmock/gmock.h>
+
+class ClockMock : public interfaces::Clock
+{
+  public:
+    MOCK_METHOD(Milliseconds, steadyTimestamp, (), (const, noexcept, override));
+    MOCK_METHOD(Milliseconds, systemTimestamp, (), (const, noexcept, override));
+};
diff --git a/tests/src/mocks/trigger_action_mock.hpp b/tests/src/mocks/trigger_action_mock.hpp
index 65585d8..cbf5bf3 100644
--- a/tests/src/mocks/trigger_action_mock.hpp
+++ b/tests/src/mocks/trigger_action_mock.hpp
@@ -7,6 +7,8 @@
 class TriggerActionMock : public interfaces::TriggerAction
 {
   public:
-    MOCK_METHOD(void, commit, (const std::string&, Milliseconds, double),
+    MOCK_METHOD(void, commit,
+                (const std::string&, const ThresholdName, const std::string&,
+                 const Milliseconds, const TriggerValue),
                 (override));
 };
diff --git a/tests/src/mocks/trigger_factory_mock.hpp b/tests/src/mocks/trigger_factory_mock.hpp
index 80a62a1..d3d83e5 100644
--- a/tests/src/mocks/trigger_factory_mock.hpp
+++ b/tests/src/mocks/trigger_factory_mock.hpp
@@ -42,6 +42,7 @@
     MOCK_METHOD(void, updateThresholds,
                 (std::vector<std::shared_ptr<interfaces::Threshold>> &
                      currentThresholds,
+                 const std::string& triggerId,
                  const std::vector<TriggerAction>& triggerActions,
                  const std::shared_ptr<std::vector<std::string>>& reportIds,
                  const Sensors& sensors,
diff --git a/tests/src/test_discrete_threshold.cpp b/tests/src/test_discrete_threshold.cpp
index b68d1c3..953ddd5 100644
--- a/tests/src/test_discrete_threshold.cpp
+++ b/tests/src/test_discrete_threshold.cpp
@@ -1,6 +1,7 @@
 #include "dbus_environment.hpp"
 #include "discrete_threshold.hpp"
 #include "helpers.hpp"
+#include "mocks/clock_mock.hpp"
 #include "mocks/sensor_mock.hpp"
 #include "mocks/trigger_action_mock.hpp"
 #include "types/duration_types.hpp"
@@ -22,20 +23,24 @@
         std::make_unique<StrictMock<TriggerActionMock>>();
     TriggerActionMock& actionMock = *actionMockPtr;
     std::shared_ptr<DiscreteThreshold> sut;
+    std::string triggerId = "MyTrigger";
+    std::unique_ptr<NiceMock<ClockMock>> clockMockPtr =
+        std::make_unique<NiceMock<ClockMock>>();
 
     std::shared_ptr<DiscreteThreshold>
         makeThreshold(Milliseconds dwellTime, std::string thresholdValue,
-                      discrete::Severity severity = discrete::Severity::ok)
+                      discrete::Severity severity = discrete::Severity::ok,
+                      std::string thresholdName = "treshold name")
     {
         std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
         actions.push_back(std::move(actionMockPtr));
 
         return std::make_shared<DiscreteThreshold>(
-            DbusEnvironment::getIoc(),
+            DbusEnvironment::getIoc(), triggerId,
             utils::convContainer<std::shared_ptr<interfaces::Sensor>>(
                 sensorMocks),
-            std::move(actions), dwellTime, thresholdValue, "treshold name",
-            severity);
+            std::move(actions), dwellTime, thresholdValue, thresholdName,
+            severity, std::move(clockMockPtr));
     }
 
     void SetUp() override
@@ -65,7 +70,7 @@
 
 TEST_F(TestDiscreteThreshold, thresholdIsNotInitializeExpectNoActionCommit)
 {
-    EXPECT_CALL(actionMock, commit(_, _, _)).Times(0);
+    EXPECT_CALL(actionMock, commit(_, _, _, _, _)).Times(0);
 }
 
 class TestDiscreteThresholdValues :
@@ -97,33 +102,55 @@
     EXPECT_THROW(makeThreshold(0ms, GetParam()), std::invalid_argument);
 }
 
+class TestDiscreteThresholdInit : public TestDiscreteThreshold
+{
+    void SetUp() override
+    {}
+};
+
+TEST_F(TestDiscreteThresholdInit, nonEmptyNameIsNotChanged)
+{
+    auto sut = makeThreshold(0ms, "12.3", discrete::Severity::ok, "non-empty");
+    EXPECT_THAT(
+        std::get<discrete::LabeledThresholdParam>(sut->getThresholdParam())
+            .at_label<utils::tstring::UserId>(),
+        Eq("non-empty"));
+}
+
+TEST_F(TestDiscreteThresholdInit, emptyNameIsChanged)
+{
+    auto sut = makeThreshold(0ms, "12.3", discrete::Severity::ok, "");
+    EXPECT_THAT(
+        std::get<discrete::LabeledThresholdParam>(sut->getThresholdParam())
+            .at_label<utils::tstring::UserId>(),
+        Not(Eq("")));
+}
+
 struct DiscreteParams
 {
     struct UpdateParams
     {
         size_t sensor;
-        Milliseconds timestamp;
         double value;
         Milliseconds sleepAfter;
 
-        UpdateParams(size_t sensor, Milliseconds timestamp, double value,
+        UpdateParams(size_t sensor, double value,
                      Milliseconds sleepAfter = 0ms) :
             sensor(sensor),
-            timestamp(timestamp), value(value), sleepAfter(sleepAfter)
+            value(value), sleepAfter(sleepAfter)
         {}
     };
 
     struct ExpectedParams
     {
         size_t sensor;
-        Milliseconds timestamp;
         double value;
         Milliseconds waitMin;
 
-        ExpectedParams(size_t sensor, Milliseconds timestamp, double value,
+        ExpectedParams(size_t sensor, double value,
                        Milliseconds waitMin = 0ms) :
             sensor(sensor),
-            timestamp(timestamp), value(value), waitMin(waitMin)
+            value(value), waitMin(waitMin)
         {}
     };
 
@@ -155,21 +182,19 @@
     {
         *os << "{ DwellTime: " << o.dwellTime.count() << "ms ";
         *os << ", ThresholdValue: " << o.thresholdValue;
-        *os << ", Updates: ";
-        for (const auto& [index, timestamp, value, sleepAfter] : o.updates)
+        *os << ", Updates: [ ";
+        for (const auto& [index, value, sleepAfter] : o.updates)
         {
-            *os << "{ SensorIndex: " << index
-                << ", Timestamp: " << timestamp.count() << ", Value: " << value
+            *os << "{ SensorIndex: " << index << ", Value: " << value
                 << ", SleepAfter: " << sleepAfter.count() << "ms }, ";
         }
-        *os << "Expected: ";
-        for (const auto& [index, timestamp, value, waitMin] : o.expected)
+        *os << " ] Expected: [ ";
+        for (const auto& [index, value, waitMin] : o.expected)
         {
-            *os << "{ SensorIndex: " << index
-                << ", Timestamp: " << timestamp.count() << ", Value: " << value
+            *os << "{ SensorIndex: " << index << ", Value: " << value
                 << ", waitMin: " << waitMin.count() << "ms }, ";
         }
-        *os << " }";
+        *os << " ] }";
     }
 
     std::vector<UpdateParams> updates;
@@ -200,11 +225,12 @@
 
         InSequence seq;
 
-        for (const auto& [index, timestamp, value, waitMin] :
-             GetParam().expected)
+        for (const auto& [index, value, waitMin] : GetParam().expected)
         {
             EXPECT_CALL(actionMock,
-                        commit(sensorNames[index], timestamp, value))
+                        commit(triggerId, Optional(StrEq("treshold name")),
+                               sensorNames[index], _,
+                               TriggerValue(GetParam().thresholdValue)))
                 .WillOnce(DoAll(
                     InvokeWithoutArgs([idx = index, &timestamps] {
                         timestamps[idx] =
@@ -215,16 +241,14 @@
 
         auto start = std::chrono::high_resolution_clock::now();
 
-        for (const auto& [index, timestamp, value, sleepAfter] :
-             GetParam().updates)
+        for (const auto& [index, value, sleepAfter] : GetParam().updates)
         {
-            sut->sensorUpdated(*sensorMocks[index], timestamp, value);
+            sut->sensorUpdated(*sensorMocks[index], 42ms, value);
             sleep(sleepAfter);
         }
 
         EXPECT_THAT(DbusEnvironment::waitForFutures("commit"), true);
-        for (const auto& [index, timestamp, value, waitMin] :
-             GetParam().expected)
+        for (const auto& [index, value, waitMin] : GetParam().expected)
         {
             EXPECT_THAT(timestamps[index] - start, Ge(waitMin));
         }
@@ -236,7 +260,6 @@
   public:
     void SetUp() override
     {
-
         for (size_t idx = 0; idx < sensorMocks.size(); idx++)
         {
             ON_CALL(*sensorMocks.at(idx), getName())
@@ -247,26 +270,20 @@
     }
 };
 
-INSTANTIATE_TEST_SUITE_P(_, TestDiscreteThresholdNoDwellTime,
-                         Values(DiscreteParams()
-                                    .ThresholdValue("90.0")
-                                    .Updates({{0, 1ms, 80.0}, {0, 2ms, 89.0}})
-                                    .Expected({}),
-                                DiscreteParams()
-                                    .ThresholdValue("90.0")
-                                    .Updates({{0, 1ms, 80.0},
-                                              {0, 2ms, 90.0},
-                                              {0, 3ms, 80.0},
-                                              {0, 4ms, 90.0}})
-                                    .Expected({{0, 2ms, 90.0}, {0, 4ms, 90.0}}),
-                                DiscreteParams()
-                                    .ThresholdValue("90.0")
-                                    .Updates({{0, 1ms, 90.0},
-                                              {0, 2ms, 99.0},
-                                              {1, 3ms, 100.0},
-                                              {1, 4ms, 90.0}})
-                                    .Expected({{0, 1ms, 90.0},
-                                               {1, 4ms, 90.0}})));
+INSTANTIATE_TEST_SUITE_P(
+    _, TestDiscreteThresholdNoDwellTime,
+    Values(DiscreteParams()
+               .ThresholdValue("90.0")
+               .Updates({{0, 80.0}, {0, 89.0}})
+               .Expected({}),
+           DiscreteParams()
+               .ThresholdValue("90.0")
+               .Updates({{0, 80.0}, {0, 90.0}, {0, 80.0}, {0, 90.0}})
+               .Expected({{0, 90.0}, {0, 90.0}}),
+           DiscreteParams()
+               .ThresholdValue("90.0")
+               .Updates({{0, 90.0}, {0, 99.0}, {1, 100.0}, {1, 90.0}})
+               .Expected({{0, 90.0}, {1, 90.0}})));
 
 TEST_P(TestDiscreteThresholdNoDwellTime, senorsIsUpdatedMultipleTimes)
 {
@@ -293,31 +310,31 @@
     Values(DiscreteParams()
                .DwellTime(200ms)
                .ThresholdValue("90.0")
-               .Updates({{0, 1ms, 90.0, 100ms}, {0, 2ms, 91.0}, {0, 3ms, 90.0}})
-               .Expected({{0, 3ms, 90.0, 300ms}}),
+               .Updates({{0, 90.0, 100ms}, {0, 91.0}, {0, 90.0}})
+               .Expected({{0, 90.0, 300ms}}),
            DiscreteParams()
                .DwellTime(100ms)
                .ThresholdValue("90.0")
-               .Updates({{0, 1ms, 90.0, 100ms}})
-               .Expected({{0, 1ms, 90.0, 100ms}}),
+               .Updates({{0, 90.0, 100ms}})
+               .Expected({{0, 90.0, 100ms}}),
            DiscreteParams()
                .DwellTime(1000ms)
                .ThresholdValue("90.0")
-               .Updates({{0, 1ms, 90.0, 700ms},
-                         {0, 1ms, 91.0, 100ms},
-                         {0, 1ms, 90.0, 300ms},
-                         {0, 1ms, 91.0, 100ms}})
+               .Updates({{0, 90.0, 700ms},
+                         {0, 91.0, 100ms},
+                         {0, 90.0, 300ms},
+                         {0, 91.0, 100ms}})
                .Expected({}),
            DiscreteParams()
                .DwellTime(200ms)
                .ThresholdValue("90.0")
-               .Updates({{0, 1ms, 90.0},
-                         {1, 2ms, 89.0, 100ms},
-                         {1, 3ms, 90.0, 100ms},
-                         {1, 4ms, 89.0, 100ms},
-                         {1, 5ms, 90.0, 300ms},
-                         {1, 6ms, 89.0, 100ms}})
-               .Expected({{0, 1ms, 90, 200ms}, {1, 5ms, 90, 500ms}})));
+               .Updates({{0, 90.0},
+                         {1, 89.0, 100ms},
+                         {1, 90.0, 100ms},
+                         {1, 89.0, 100ms},
+                         {1, 90.0, 300ms},
+                         {1, 89.0, 100ms}})
+               .Expected({{0, 90, 200ms}, {1, 90, 500ms}})));
 
 TEST_P(TestDiscreteThresholdWithDwellTime, senorsIsUpdatedMultipleTimes)
 {
diff --git a/tests/src/test_numeric_threshold.cpp b/tests/src/test_numeric_threshold.cpp
index 65c976c..69ad0de 100644
--- a/tests/src/test_numeric_threshold.cpp
+++ b/tests/src/test_numeric_threshold.cpp
@@ -1,5 +1,6 @@
 #include "dbus_environment.hpp"
 #include "helpers.hpp"
+#include "mocks/clock_mock.hpp"
 #include "mocks/sensor_mock.hpp"
 #include "mocks/trigger_action_mock.hpp"
 #include "numeric_threshold.hpp"
@@ -21,6 +22,9 @@
         std::make_unique<StrictMock<TriggerActionMock>>();
     TriggerActionMock& actionMock = *actionMockPtr;
     std::shared_ptr<NumericThreshold> sut;
+    std::string triggerId = "MyTrigger";
+    std::unique_ptr<NiceMock<ClockMock>> clockMockPtr =
+        std::make_unique<NiceMock<ClockMock>>();
 
     void makeThreshold(Milliseconds dwellTime, numeric::Direction direction,
                        double thresholdValue,
@@ -30,10 +34,11 @@
         actions.push_back(std::move(actionMockPtr));
 
         sut = std::make_shared<NumericThreshold>(
-            DbusEnvironment::getIoc(),
+            DbusEnvironment::getIoc(), triggerId,
             utils::convContainer<std::shared_ptr<interfaces::Sensor>>(
                 sensorMocks),
-            std::move(actions), dwellTime, direction, thresholdValue, type);
+            std::move(actions), dwellTime, direction, thresholdValue, type,
+            std::move(clockMockPtr));
     }
 
     void SetUp() override
@@ -64,7 +69,7 @@
 
 TEST_F(TestNumericThreshold, thresholdIsNotInitializeExpectNoActionCommit)
 {
-    EXPECT_CALL(actionMock, commit(_, _, _)).Times(0);
+    EXPECT_CALL(actionMock, commit(_, _, _, _, _)).Times(0);
 }
 
 TEST_F(TestNumericThreshold, getLabeledParamsReturnsCorrectly)
@@ -76,56 +81,167 @@
 
 struct NumericParams
 {
+    struct UpdateParams
+    {
+        size_t sensor;
+        double value;
+        Milliseconds sleepAfter;
+
+        UpdateParams(size_t sensor, double value,
+                     Milliseconds sleepAfter = 0ms) :
+            sensor(sensor),
+            value(value), sleepAfter(sleepAfter)
+        {}
+    };
+
+    struct ExpectedParams
+    {
+        size_t sensor;
+        double value;
+        Milliseconds waitMin;
+
+        ExpectedParams(size_t sensor, double value,
+                       Milliseconds waitMin = 0ms) :
+            sensor(sensor),
+            value(value), waitMin(waitMin)
+        {}
+    };
+
     NumericParams& Direction(numeric::Direction val)
     {
         direction = val;
         return *this;
     }
 
-    NumericParams&
-        Updates(std::vector<std::tuple<size_t, Milliseconds, double>> val)
+    NumericParams& Updates(std::vector<UpdateParams> val)
     {
         updates = std::move(val);
         return *this;
     }
 
-    NumericParams&
-        Expected(std::vector<std::tuple<size_t, Milliseconds, double>> val)
+    NumericParams& Expected(std::vector<ExpectedParams> val)
     {
         expected = std::move(val);
         return *this;
     }
 
+    NumericParams& ThresholdValue(double val)
+    {
+        thresholdValue = val;
+        return *this;
+    }
+
+    NumericParams& DwellTime(Milliseconds val)
+    {
+        dwellTime = std::move(val);
+        return *this;
+    }
+
+    NumericParams& InitialValues(std::vector<double> val)
+    {
+        initialValues = std::move(val);
+        return *this;
+    }
+
     friend void PrintTo(const NumericParams& o, std::ostream* os)
     {
-        *os << "{ Direction: " << static_cast<int>(o.direction)
-            << ", Updates: ";
-        for (const auto& [index, timestamp, value] : o.updates)
+        *os << "{ DwellTime: " << o.dwellTime.count() << "ms ";
+        *os << ", ThresholdValue: " << o.thresholdValue;
+        *os << ", Direction: " << static_cast<int>(o.direction);
+        *os << ", InitialValues: [ ";
+        size_t idx = 0;
+        for (const double value : o.initialValues)
         {
-            *os << "{ SensorIndex: " << index
-                << ", Timestamp: " << timestamp.count() << ", Value: " << value
-                << " }, ";
+            *os << "{ SensorIndex: " << idx << ", Value: " << value << " }, ";
+            idx++;
         }
-        *os << "Expected: ";
-        for (const auto& [index, timestamp, value] : o.expected)
+        *os << " ], Updates: [ ";
+        for (const auto& [index, value, sleepAfter] : o.updates)
         {
-            *os << "{ SensorIndex: " << index
-                << ", Timestamp: " << timestamp.count() << ", Value: " << value
-                << " }, ";
+            *os << "{ SensorIndex: " << index << ", Value: " << value
+                << ", SleepAfter: " << sleepAfter.count() << "ms }, ";
         }
-        *os << " }";
+        *os << " ], Expected: [ ";
+        for (const auto& [index, value, waitMin] : o.expected)
+        {
+            *os << "{ SensorIndex: " << index << ", Value: " << value
+                << ", waitMin: " << waitMin.count() << "ms }, ";
+        }
+        *os << " ] }";
     }
 
     numeric::Direction direction;
-    std::vector<std::tuple<size_t, Milliseconds, double>> updates;
-    std::vector<std::tuple<size_t, Milliseconds, double>> expected;
+    double thresholdValue = 0.0;
+    Milliseconds dwellTime = 0ms;
+    std::vector<UpdateParams> updates;
+    std::vector<ExpectedParams> expected;
+    std::vector<double> initialValues;
 };
 
-class TestNumericThresholdNoDwellTime :
+class TestNumericThresholdCommon :
     public TestNumericThreshold,
     public WithParamInterface<NumericParams>
 {
   public:
+    void sleep(Milliseconds duration)
+    {
+        if (duration != 0ms)
+        {
+            DbusEnvironment::sleepFor(duration);
+        }
+    }
+
+    void testBodySensorIsUpdatedMultipleTimes()
+    {
+        std::vector<std::chrono::time_point<std::chrono::high_resolution_clock>>
+            timestamps(sensorMocks.size());
+
+        sut->initialize();
+
+        InSequence seq;
+
+        for (const auto& [index, value, waitMin] : GetParam().expected)
+        {
+            EXPECT_CALL(actionMock,
+                        commit(triggerId, Eq(std::nullopt), sensorNames[index],
+                               _, TriggerValue(value)))
+                .WillOnce(DoAll(
+                    InvokeWithoutArgs([idx = index, &timestamps] {
+                        timestamps[idx] =
+                            std::chrono::high_resolution_clock::now();
+                    }),
+                    InvokeWithoutArgs(DbusEnvironment::setPromise("commit"))));
+        }
+
+        auto start = std::chrono::high_resolution_clock::now();
+
+        size_t idx = 0;
+        for (const double value : GetParam().initialValues)
+        {
+            sut->sensorUpdated(*sensorMocks[idx], 0ms, value);
+            idx++;
+        }
+
+        for (const auto& [index, value, sleepAfter] : GetParam().updates)
+        {
+            ASSERT_LT(index, GetParam().initialValues.size())
+                << "Initial value was not specified for sensor with index: "
+                << index;
+            sut->sensorUpdated(*sensorMocks[index], 42ms, value);
+            sleep(sleepAfter);
+        }
+
+        EXPECT_THAT(DbusEnvironment::waitForFutures("commit"), true);
+        for (const auto& [index, value, waitMin] : GetParam().expected)
+        {
+            EXPECT_THAT(timestamps[index] - start, Ge(waitMin));
+        }
+    }
+};
+
+class TestNumericThresholdNoDwellTime : public TestNumericThresholdCommon
+{
+  public:
     void SetUp() override
     {
         for (size_t idx = 0; idx < sensorMocks.size(); idx++)
@@ -134,93 +250,84 @@
                 .WillByDefault(Return(sensorNames[idx]));
         }
 
-        makeThreshold(0ms, GetParam().direction, 90.0);
+        makeThreshold(0ms, GetParam().direction, GetParam().thresholdValue);
     }
 };
 
 INSTANTIATE_TEST_SUITE_P(_, TestNumericThresholdNoDwellTime,
                          Values(NumericParams()
+                                    .ThresholdValue(90.0)
                                     .Direction(numeric::Direction::increasing)
-                                    .Updates({{0, 1ms, 80.0}, {0, 2ms, 89.0}})
+                                    .InitialValues({80.0})
+                                    .Updates({{0, 89.0}})
                                     .Expected({}),
                                 NumericParams()
+                                    .ThresholdValue(90.0)
                                     .Direction(numeric::Direction::increasing)
-                                    .Updates({{0, 1ms, 80.0}, {0, 2ms, 91.0}})
-                                    .Expected({{0, 2ms, 91.0}}),
+                                    .InitialValues({80.0})
+                                    .Updates({{0, 91.0}})
+                                    .Expected({{0, 91.0}}),
                                 NumericParams()
+                                    .ThresholdValue(90.0)
                                     .Direction(numeric::Direction::increasing)
-                                    .Updates({{0, 1ms, 80.0},
-                                              {0, 2ms, 99.0},
-                                              {0, 3ms, 80.0},
-                                              {0, 4ms, 98.0}})
-                                    .Expected({{0, 2ms, 99.0}, {0, 4ms, 98.0}}),
+                                    .InitialValues({80.0})
+                                    .Updates({{0, 99.0}, {0, 80.0}, {0, 98.0}})
+                                    .Expected({{0, 99.0}, {0, 98.0}}),
                                 NumericParams()
+                                    .ThresholdValue(90.0)
                                     .Direction(numeric::Direction::increasing)
-                                    .Updates({{0, 1ms, 80.0},
-                                              {0, 2ms, 99.0},
-                                              {1, 3ms, 100.0},
-                                              {1, 4ms, 98.0}})
-                                    .Expected({{0, 2ms, 99.0}}),
+                                    .InitialValues({80.0, 100.0})
+                                    .Updates({{0, 99.0}, {1, 98.0}})
+                                    .Expected({{0, 99.0}}),
                                 NumericParams()
+                                    .ThresholdValue(90.0)
                                     .Direction(numeric::Direction::decreasing)
-                                    .Updates({{0, 1ms, 100.0}, {0, 2ms, 91.0}})
+                                    .InitialValues({100.0})
+                                    .Updates({{0, 91.0}})
                                     .Expected({}),
                                 NumericParams()
+                                    .ThresholdValue(90.0)
                                     .Direction(numeric::Direction::decreasing)
-                                    .Updates({{0, 1ms, 100.0}, {0, 2ms, 80.0}})
-                                    .Expected({{0, 2ms, 80.0}}),
+                                    .InitialValues({100.0})
+                                    .Updates({{0, 80.0}})
+                                    .Expected({{0, 80.0}}),
                                 NumericParams()
+                                    .ThresholdValue(90.0)
                                     .Direction(numeric::Direction::decreasing)
-                                    .Updates({{0, 1ms, 100.0},
-                                              {0, 2ms, 80.0},
-                                              {0, 3ms, 99.0},
-                                              {0, 4ms, 85.0}})
-                                    .Expected({{0, 2ms, 80.0}, {0, 4ms, 85.0}}),
+                                    .InitialValues({100.0})
+                                    .Updates({{0, 80.0}, {0, 99.0}, {0, 85.0}})
+                                    .Expected({{0, 80.0}, {0, 85.0}}),
                                 NumericParams()
+                                    .ThresholdValue(90.0)
                                     .Direction(numeric::Direction::decreasing)
-                                    .Updates({{0, 1ms, 100.0},
-                                              {0, 2ms, 80.0},
-                                              {1, 3ms, 99.0},
-                                              {1, 4ms, 88.0}})
-                                    .Expected({{0, 2ms, 80.0}, {1, 4ms, 88.0}}),
+                                    .InitialValues({100.0, 99.0})
+                                    .Updates({{0, 80.0}, {1, 88.0}})
+                                    .Expected({{0, 80.0}, {1, 88.0}}),
                                 NumericParams()
+                                    .ThresholdValue(90.0)
                                     .Direction(numeric::Direction::either)
-                                    .Updates({{0, 1ms, 98.0}, {0, 2ms, 91.0}})
+                                    .InitialValues({98.0})
+                                    .Updates({{0, 91.0}})
                                     .Expected({}),
                                 NumericParams()
+                                    .ThresholdValue(90.0)
                                     .Direction(numeric::Direction::either)
-                                    .Updates({{0, 1ms, 100.0},
-                                              {0, 2ms, 80.0},
-                                              {0, 3ms, 85.0},
-                                              {0, 4ms, 91.0}})
-                                    .Expected({{0, 2ms, 80.0}, {0, 4ms, 91.0}}),
+                                    .InitialValues({100.0})
+                                    .Updates({{0, 80.0}, {0, 85.0}, {0, 91.0}})
+                                    .Expected({{0, 80.0}, {0, 91.0}}),
                                 NumericParams()
+                                    .ThresholdValue(90.0)
                                     .Direction(numeric::Direction::either)
-                                    .Updates({{0, 1ms, 100.0},
-                                              {1, 2ms, 80.0},
-                                              {0, 3ms, 85.0},
-                                              {1, 4ms, 91.0}})
-                                    .Expected({{0, 3ms, 85.0},
-                                               {1, 4ms, 91.0}})));
+                                    .InitialValues({100.0, 80.0})
+                                    .Updates({{0, 85.0}, {1, 91.0}})
+                                    .Expected({{0, 85.0}, {1, 91.0}})));
 
 TEST_P(TestNumericThresholdNoDwellTime, senorsIsUpdatedMultipleTimes)
 {
-    InSequence seq;
-    for (const auto& [index, timestamp, value] : GetParam().expected)
-    {
-        EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value));
-    }
-
-    sut->initialize();
-    for (const auto& [index, timestamp, value] : GetParam().updates)
-    {
-        sut->sensorUpdated(*sensorMocks[index], timestamp, value);
-    }
+    testBodySensorIsUpdatedMultipleTimes();
 }
 
-class TestNumericThresholdWithDwellTime :
-    public TestNumericThreshold,
-    public WithParamInterface<NumericParams>
+class TestNumericThresholdWithDwellTime : public TestNumericThresholdCommon
 {
   public:
     void SetUp() override
@@ -231,197 +338,172 @@
                 .WillByDefault(Return(sensorNames[idx]));
         }
 
-        makeThreshold(2ms, GetParam().direction, 90.0);
-    }
-
-    void sleep()
-    {
-        DbusEnvironment::sleepFor(4ms);
+        makeThreshold(GetParam().dwellTime, GetParam().direction,
+                      GetParam().thresholdValue);
     }
 };
 
-INSTANTIATE_TEST_SUITE_P(_, TestNumericThresholdWithDwellTime,
-                         Values(NumericParams()
-                                    .Direction(numeric::Direction::increasing)
-                                    .Updates({{0, 1ms, 80.0}, {0, 2ms, 89.0}})
-                                    .Expected({}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::increasing)
-                                    .Updates({{0, 1ms, 80.0}, {0, 2ms, 91.0}})
-                                    .Expected({{0, 2ms, 91.0}}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::increasing)
-                                    .Updates({{0, 1ms, 80.0},
-                                              {0, 2ms, 99.0},
-                                              {0, 3ms, 80.0},
-                                              {0, 4ms, 98.0}})
-                                    .Expected({{0, 2ms, 99.0}, {0, 4ms, 98.0}}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::increasing)
-                                    .Updates({{0, 1ms, 80.0},
-                                              {1, 2ms, 99.0},
-                                              {0, 3ms, 100.0},
-                                              {1, 4ms, 86.0}})
-                                    .Expected({{0, 3ms, 100.0}}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::decreasing)
-                                    .Updates({{0, 1ms, 100.0}, {0, 2ms, 91.0}})
-                                    .Expected({}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::decreasing)
-                                    .Updates({{0, 1ms, 100.0}, {0, 2ms, 80.0}})
-                                    .Expected({{0, 2ms, 80.0}}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::decreasing)
-                                    .Updates({{0, 1ms, 100.0},
-                                              {0, 2ms, 80.0},
-                                              {0, 3ms, 99.0},
-                                              {0, 4ms, 85.0}})
-                                    .Expected({{0, 2ms, 80.0}, {0, 4ms, 85.0}}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::decreasing)
-                                    .Updates({{0, 1ms, 100.0},
-                                              {0, 2ms, 80.0},
-                                              {1, 3ms, 99.0},
-                                              {1, 4ms, 88.0}})
-                                    .Expected({{0, 2ms, 80.0}, {1, 4ms, 88.0}}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::either)
-                                    .Updates({{0, 1ms, 98.0}, {0, 2ms, 91.0}})
-                                    .Expected({}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::either)
-                                    .Updates({{0, 1ms, 100.0},
-                                              {0, 2ms, 80.0},
-                                              {0, 3ms, 85.0},
-                                              {0, 4ms, 91.0}})
-                                    .Expected({{0, 2ms, 80.0}, {0, 4ms, 91.0}}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::either)
-                                    .Updates({{0, 1ms, 100.0},
-                                              {1, 2ms, 80.0},
-                                              {0, 3ms, 85.0},
-                                              {1, 4ms, 91.0}})
-                                    .Expected({{0, 3ms, 85.0},
-                                               {1, 4ms, 91.0}})));
+INSTANTIATE_TEST_SUITE_P(
+    SleepAfterEveryUpdate, TestNumericThresholdWithDwellTime,
+    Values(NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::increasing)
+               .InitialValues({80.0})
+               .Updates({{0, 89.0, 200ms}})
+               .Expected({}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::increasing)
+               .InitialValues({80.0})
+               .Updates({{0, 91.0, 200ms}})
+               .Expected({{0, 91.0, 200ms}}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::increasing)
+               .InitialValues({80.0})
+               .Updates({{0, 99.0, 200ms}, {0, 80.0, 100ms}, {0, 98.0, 200ms}})
+               .Expected({{0, 99.0, 200ms}, {0, 98.0, 500ms}}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::increasing)
+               .InitialValues({80.0, 99.0})
+               .Updates({{0, 100.0, 100ms}, {1, 86.0, 100ms}})
+               .Expected({{0, 100.0, 200ms}}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::decreasing)
+               .InitialValues({100.0})
+               .Updates({{0, 91.0, 200ms}})
+               .Expected({}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::decreasing)
+               .InitialValues({100.0})
+               .Updates({{0, 80.0, 200ms}})
+               .Expected({{0, 80.0, 200ms}}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::decreasing)
+               .InitialValues({100.0})
+               .Updates({{0, 80.0, 200ms}, {0, 99.0, 100ms}, {0, 85.0, 200ms}})
+               .Expected({{0, 80.0, 200ms}, {0, 85.0, 500ms}}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::decreasing)
+               .InitialValues({100.0, 99.0})
+               .Updates({{0, 80.0, 200ms}, {1, 88.0, 200ms}})
+               .Expected({{0, 80.0, 200ms}, {1, 88.0, 400ms}}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::either)
+               .InitialValues({98.0})
+               .Updates({{0, 91.0, 200ms}})
+               .Expected({}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::either)
+               .InitialValues({100.0})
+               .Updates({{0, 80.0, 100ms}, {0, 85.0, 100ms}, {0, 91.0, 200ms}})
+               .Expected({{0, 80.0, 200ms}, {0, 91.0, 400ms}}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::either)
+               .InitialValues({100.0, 80.0})
+               .Updates({{0, 85.0, 100ms}, {1, 91.0, 200ms}})
+               .Expected({{0, 85.0, 200ms}, {1, 91.0, 300ms}})));
 
-TEST_P(TestNumericThresholdWithDwellTime,
-       senorsIsUpdatedMultipleTimesSleepAfterEveryUpdate)
+INSTANTIATE_TEST_SUITE_P(
+    SleepAfterLastUpdate, TestNumericThresholdWithDwellTime,
+    Values(NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::increasing)
+               .InitialValues({80.0})
+               .Updates({{0, 89.0, 300ms}})
+               .Expected({}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::increasing)
+               .InitialValues({80.0})
+               .Updates({{0, 91.0, 300ms}})
+               .Expected({{0, 91.0, 200ms}}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::increasing)
+               .InitialValues({80.0})
+               .Updates({{0, 99.0}, {0, 80.0}, {0, 98.0, 300ms}})
+               .Expected({{0, 98.0, 200ms}}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::increasing)
+               .InitialValues({80.0, 99.0})
+               .Updates({{0, 100.0}, {1, 98.0, 300ms}})
+               .Expected({{0, 100.0, 200ms}}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::decreasing)
+               .InitialValues({100.0})
+               .Updates({{0, 91.0, 300ms}})
+               .Expected({}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::decreasing)
+               .InitialValues({100.0})
+               .Updates({{0, 80.0, 300ms}})
+               .Expected({{0, 80.0, 200ms}}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::decreasing)
+               .InitialValues({100.0})
+               .Updates({{0, 80.0}, {0, 99.0}, {0, 85.0, 300ms}})
+               .Expected({{0, 85.0, 200ms}}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::decreasing)
+               .InitialValues({100.0, 99.0})
+               .Updates({{0, 80.0}, {1, 88.0, 300ms}})
+               .Expected({{0, 80.0, 200ms}, {1, 88.0, 200ms}}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::either)
+               .InitialValues({98.0})
+               .Updates({{0, 91.0, 300ms}})
+               .Expected({}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::either)
+               .InitialValues({100.0})
+               .Updates({{0, 80.0}, {0, 85.0}, {0, 91.0, 300ms}})
+               .Expected({{0, 91.0, 200ms}}),
+           NumericParams()
+               .DwellTime(200ms)
+               .ThresholdValue(90.0)
+               .Direction(numeric::Direction::either)
+               .InitialValues({100.0, 80.0})
+               .Updates({{0, 85.0}, {1, 91.0, 300ms}})
+               .Expected({{0, 85.0, 200ms}, {1, 91.0, 200ms}})));
+
+TEST_P(TestNumericThresholdWithDwellTime, senorsIsUpdatedMultipleTimes)
 {
-    InSequence seq;
-    for (const auto& [index, timestamp, value] : GetParam().expected)
-    {
-        EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value));
-    }
-
-    sut->initialize();
-    for (const auto& [index, timestamp, value] : GetParam().updates)
-    {
-        sut->sensorUpdated(*sensorMocks[index], timestamp, value);
-        sleep();
-    }
-}
-
-class TestNumericThresholdWithDwellTime2 :
-    public TestNumericThreshold,
-    public WithParamInterface<NumericParams>
-{
-  public:
-    void SetUp() override
-    {
-        for (size_t idx = 0; idx < sensorMocks.size(); idx++)
-        {
-            ON_CALL(*sensorMocks.at(idx), getName())
-                .WillByDefault(Return(sensorNames[idx]));
-        }
-
-        makeThreshold(2ms, GetParam().direction, 90.0);
-    }
-
-    void sleep()
-    {
-        DbusEnvironment::sleepFor(4ms);
-    }
-};
-
-INSTANTIATE_TEST_SUITE_P(_, TestNumericThresholdWithDwellTime2,
-                         Values(NumericParams()
-                                    .Direction(numeric::Direction::increasing)
-                                    .Updates({{0, 1ms, 80.0}, {0, 2ms, 89.0}})
-                                    .Expected({}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::increasing)
-                                    .Updates({{0, 1ms, 80.0}, {0, 2ms, 91.0}})
-                                    .Expected({{0, 2ms, 91.0}}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::increasing)
-                                    .Updates({{0, 1ms, 80.0},
-                                              {0, 2ms, 99.0},
-                                              {0, 3ms, 80.0},
-                                              {0, 4ms, 98.0}})
-                                    .Expected({{0, 4ms, 98.0}}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::increasing)
-                                    .Updates({{0, 1ms, 80.0},
-                                              {1, 2ms, 99.0},
-                                              {0, 3ms, 100.0},
-                                              {1, 4ms, 98.0}})
-                                    .Expected({{0, 3ms, 100.0}}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::decreasing)
-                                    .Updates({{0, 1ms, 100.0}, {0, 2ms, 91.0}})
-                                    .Expected({}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::decreasing)
-                                    .Updates({{0, 1ms, 100.0}, {0, 2ms, 80.0}})
-                                    .Expected({{0, 2ms, 80.0}}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::decreasing)
-                                    .Updates({{0, 1ms, 100.0},
-                                              {0, 2ms, 80.0},
-                                              {0, 3ms, 99.0},
-                                              {0, 4ms, 85.0}})
-                                    .Expected({{0, 4ms, 85.0}}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::decreasing)
-                                    .Updates({{0, 1ms, 100.0},
-                                              {0, 2ms, 80.0},
-                                              {1, 3ms, 99.0},
-                                              {1, 4ms, 88.0}})
-                                    .Expected({{0, 2ms, 80.0}, {1, 4ms, 88.0}}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::either)
-                                    .Updates({{0, 1ms, 98.0}, {0, 2ms, 91.0}})
-                                    .Expected({}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::either)
-                                    .Updates({{0, 1ms, 100.0},
-                                              {0, 2ms, 80.0},
-                                              {0, 3ms, 85.0},
-                                              {0, 4ms, 91.0}})
-                                    .Expected({{0, 4ms, 91.0}}),
-                                NumericParams()
-                                    .Direction(numeric::Direction::either)
-                                    .Updates({{0, 1ms, 100.0},
-                                              {1, 2ms, 80.0},
-                                              {0, 3ms, 85.0},
-                                              {1, 4ms, 91.0}})
-                                    .Expected({{0, 3ms, 85.0},
-                                               {1, 4ms, 91.0}})));
-
-TEST_P(TestNumericThresholdWithDwellTime2,
-       senorsIsUpdatedMultipleTimesSleepAfterLastUpdate)
-{
-    InSequence seq;
-    for (const auto& [index, timestamp, value] : GetParam().expected)
-    {
-        EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value));
-    }
-
-    sut->initialize();
-    for (const auto& [index, timestamp, value] : GetParam().updates)
-    {
-        sut->sensorUpdated(*sensorMocks[index], timestamp, value);
-    }
-    sleep();
+    testBodySensorIsUpdatedMultipleTimes();
 }
diff --git a/tests/src/test_on_change_threshold.cpp b/tests/src/test_on_change_threshold.cpp
index 60697da..b4a6fd3 100644
--- a/tests/src/test_on_change_threshold.cpp
+++ b/tests/src/test_on_change_threshold.cpp
@@ -1,5 +1,6 @@
 #include "dbus_environment.hpp"
 #include "helpers.hpp"
+#include "mocks/clock_mock.hpp"
 #include "mocks/sensor_mock.hpp"
 #include "mocks/trigger_action_mock.hpp"
 #include "on_change_threshold.hpp"
@@ -21,6 +22,9 @@
         std::make_unique<StrictMock<TriggerActionMock>>();
     TriggerActionMock& actionMock = *actionMockPtr;
     std::shared_ptr<OnChangeThreshold> sut;
+    std::string triggerId = "MyTrigger";
+    std::unique_ptr<NiceMock<ClockMock>> clockMockPtr =
+        std::make_unique<NiceMock<ClockMock>>();
 
     void SetUp() override
     {
@@ -34,9 +38,10 @@
         }
 
         sut = std::make_shared<OnChangeThreshold>(
+            triggerId,
             utils::convContainer<std::shared_ptr<interfaces::Sensor>>(
                 sensorMocks),
-            std::move(actions));
+            std::move(actions), std::move(clockMockPtr));
     }
 };
 
@@ -55,7 +60,7 @@
 
 TEST_F(TestOnChangeThreshold, thresholdIsNotInitializeExpectNoActionCommit)
 {
-    EXPECT_CALL(actionMock, commit(_, _, _)).Times(0);
+    EXPECT_CALL(actionMock, commit(_, _, _, _, _)).Times(0);
 }
 
 TEST_F(TestOnChangeThreshold, getLabeledParamsReturnsCorrectly)
@@ -66,7 +71,7 @@
 
 TEST_F(TestOnChangeThreshold, firstReadingDoesNoActionCommit)
 {
-    EXPECT_CALL(actionMock, commit(_, _, _)).Times(0);
+    EXPECT_CALL(actionMock, commit(_, _, _, _, _)).Times(0);
 
     sut->initialize();
     sut->sensorUpdated(*sensorMocks.front(), 0ms, 42);
@@ -74,8 +79,8 @@
 
 struct OnChangeParams
 {
-    using UpdateParams = std::tuple<size_t, Milliseconds, double>;
-    using ExpectedParams = std::tuple<size_t, Milliseconds, double>;
+    using UpdateParams = std::tuple<size_t, double>;
+    using ExpectedParams = std::tuple<size_t, double>;
 
     OnChangeParams& Updates(std::vector<UpdateParams> val)
     {
@@ -91,21 +96,17 @@
 
     friend void PrintTo(const OnChangeParams& o, std::ostream* os)
     {
-        *os << "{ Updates: ";
-        for (const auto& [index, timestamp, value] : o.updates)
+        *os << "{ Updates: [ ";
+        for (const auto& [index, value] : o.updates)
         {
-            *os << "{ SensorIndex: " << index
-                << ", Timestamp: " << timestamp.count() << ", Value: " << value
-                << " }, ";
+            *os << "{ SensorIndex: " << index << ", Value: " << value << " }, ";
         }
-        *os << "Expected: ";
-        for (const auto& [index, timestamp, value] : o.expected)
+        *os << " ] Expected: [ ";
+        for (const auto& [index, value] : o.expected)
         {
-            *os << "{ SensorIndex: " << index
-                << ", Timestamp: " << timestamp.count() << ", Value: " << value
-                << " }, ";
+            *os << "{ SensorIndex: " << index << ", Value: " << value << " }, ";
         }
-        *os << " }";
+        *os << " ] }";
     }
 
     std::vector<UpdateParams> updates;
@@ -119,33 +120,28 @@
 
 INSTANTIATE_TEST_SUITE_P(
     _, TestOnChangeThresholdUpdates,
-    Values(
-        OnChangeParams().Updates({{0, 1ms, 80.0}}).Expected({{0, 1ms, 80.0}}),
-        OnChangeParams()
-            .Updates({{0, 1ms, 80.0}, {1, 2ms, 81.0}})
-            .Expected({{0, 1ms, 80.0}, {1, 2ms, 81.0}}),
-        OnChangeParams()
-            .Updates({{0, 1ms, 80.0}, {0, 2ms, 90.0}})
-            .Expected({{0, 1ms, 80.0}, {0, 2ms, 90.0}}),
-        OnChangeParams()
-            .Updates({{0, 1ms, 80.0}, {1, 2ms, 90.0}, {0, 3ms, 90.0}})
-            .Expected({{0, 1ms, 80.0}, {1, 2ms, 90.0}, {0, 3ms, 90.0}}),
-        OnChangeParams()
-            .Updates({{0, 1ms, 80.0},
-                      {1, 2ms, 80.0},
-                      {1, 3ms, 90.0},
-                      {0, 4ms, 90.0}})
-            .Expected({{0, 1ms, 80.0},
-                       {1, 2ms, 80.0},
-                       {1, 3ms, 90.0},
-                       {0, 4ms, 90.0}})));
+    Values(OnChangeParams().Updates({{0, 80.0}}).Expected({{0, 80.0}}),
+           OnChangeParams()
+               .Updates({{0, 80.0}, {1, 81.0}})
+               .Expected({{0, 80.0}, {1, 81.0}}),
+           OnChangeParams()
+               .Updates({{0, 80.0}, {0, 90.0}})
+               .Expected({{0, 80.0}, {0, 90.0}}),
+           OnChangeParams()
+               .Updates({{0, 80.0}, {1, 90.0}, {0, 90.0}})
+               .Expected({{0, 80.0}, {1, 90.0}, {0, 90.0}}),
+           OnChangeParams()
+               .Updates({{0, 80.0}, {1, 80.0}, {1, 90.0}, {0, 90.0}})
+               .Expected({{0, 80.0}, {1, 80.0}, {1, 90.0}, {0, 90.0}})));
 
 TEST_P(TestOnChangeThresholdUpdates, senorsIsUpdatedMultipleTimes)
 {
     InSequence seq;
-    for (const auto& [index, timestamp, value] : GetParam().expected)
+    for (const auto& [index, value] : GetParam().expected)
     {
-        EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value));
+        EXPECT_CALL(actionMock,
+                    commit(triggerId, Eq(std::nullopt), sensorNames[index], _,
+                           TriggerValue(value)));
     }
 
     sut->initialize();
@@ -153,8 +149,8 @@
     // First reading will be skipped
     sut->sensorUpdated(*sensorMocks.front(), 0ms, 42);
 
-    for (const auto& [index, timestamp, value] : GetParam().updates)
+    for (const auto& [index, value] : GetParam().updates)
     {
-        sut->sensorUpdated(*sensorMocks[index], timestamp, value);
+        sut->sensorUpdated(*sensorMocks[index], 42ms, value);
     }
 }
diff --git a/tests/src/test_trigger.cpp b/tests/src/test_trigger.cpp
index cfb08e9..9032d05 100644
--- a/tests/src/test_trigger.cpp
+++ b/tests/src/test_trigger.cpp
@@ -21,7 +21,7 @@
 using namespace testing;
 using namespace std::literals::string_literals;
 
-static constexpr size_t expectedTriggerVersion = 1;
+static constexpr size_t expectedTriggerVersion = 2;
 
 class TestTrigger : public Test
 {
@@ -78,9 +78,11 @@
         thresholdMocks =
             ThresholdMock::makeThresholds(params.thresholdParams());
 
+        auto id = std::make_unique<const std::string>(params.id());
+
         return std::make_unique<Trigger>(
             DbusEnvironment::getIoc(), DbusEnvironment::getObjServer(),
-            params.id(), params.name(), params.triggerActions(),
+            std::move(id), params.name(), params.triggerActions(),
             std::make_shared<std::vector<std::string>>(
                 params.reportIds().begin(), params.reportIds().end()),
             std::vector<std::shared_ptr<interfaces::Threshold>>(thresholdMocks),
@@ -224,7 +226,7 @@
 
 TEST_F(TestTrigger, setPropertyThresholds)
 {
-    EXPECT_CALL(*triggerFactoryMockPtr, updateThresholds(_, _, _, _, _));
+    EXPECT_CALL(*triggerFactoryMockPtr, updateThresholds(_, _, _, _, _, _));
     TriggerThresholdParams newThresholds =
         std::vector<discrete::ThresholdParam>(
             {std::make_tuple("discrete threshold", "OK", 10, "12.3")});
diff --git a/tests/src/test_trigger_actions.cpp b/tests/src/test_trigger_actions.cpp
index 911197f..e8c48d4 100644
--- a/tests/src/test_trigger_actions.cpp
+++ b/tests/src/test_trigger_actions.cpp
@@ -31,26 +31,36 @@
         std::make_tuple(static_cast<::numeric::Type>(123), 123.0, 90));
 }
 
-class TestLogToJournalNumeric : public Test, public WithParamInterface<LogParam>
+template <typename ActionType>
+class TestActionNumeric : public Test, public WithParamInterface<LogParam>
 {
   public:
     void SetUp() override
     {
         auto [type, threshold, value] = GetParam();
-        sut = std::make_unique<numeric::LogToJournal>(type, threshold);
+        sut = std::make_unique<ActionType>(type, threshold);
         commmitValue = value;
     }
 
-    std::unique_ptr<numeric::LogToJournal> sut;
+    void commit()
+    {
+        sut->commit("MyTrigger", std::nullopt, "MySensor",
+                    Milliseconds{100'000}, commmitValue);
+    }
+
+    std::unique_ptr<ActionType> sut;
     double commmitValue;
 };
 
+class TestLogToJournalNumeric : public TestActionNumeric<LogToJournal>
+{};
+
 INSTANTIATE_TEST_SUITE_P(LogToJournalNumericParams, TestLogToJournalNumeric,
                          getCorrectParams());
 
 TEST_P(TestLogToJournalNumeric, commitAnActionDoesNotThrow)
 {
-    EXPECT_NO_THROW(sut->commit("Test", Milliseconds{100'000}, commmitValue));
+    EXPECT_NO_THROW(commit());
 }
 
 class TestLogToJournalNumericThrow : public TestLogToJournalNumeric
@@ -60,80 +70,91 @@
 
 TEST_P(TestLogToJournalNumericThrow, commitAnActionExpectThrow)
 {
-    EXPECT_ANY_THROW(sut->commit("Test", Milliseconds{100'000}, commmitValue));
+    EXPECT_ANY_THROW(commit());
 }
 
-class TestLogToRedfishNumeric : public Test, public WithParamInterface<LogParam>
-{
-  public:
-    void SetUp() override
-    {
-        auto [type, threshold, value] = GetParam();
-        sut = std::make_unique<LogToRedfish>(type, threshold);
-        commmitValue = value;
-    }
-
-    std::unique_ptr<LogToRedfish> sut;
-    double commmitValue;
-};
-
-INSTANTIATE_TEST_SUITE_P(LogToRedfishNumericParams, TestLogToRedfishNumeric,
-                         getCorrectParams());
-
-TEST_P(TestLogToRedfishNumeric, commitExpectNoThrow)
-{
-    EXPECT_NO_THROW(sut->commit("Test", Milliseconds{100'000}, commmitValue));
-}
-
-class TestLogToRedfishNumericThrow : public TestLogToRedfishNumeric
+class TestLogToRedfishEventLogNumeric :
+    public TestActionNumeric<LogToRedfishEventLog>
 {};
 
-INSTANTIATE_TEST_SUITE_P(_, TestLogToRedfishNumericThrow, getIncorrectParams());
+INSTANTIATE_TEST_SUITE_P(LogToRedfishEventLogNumericParams,
+                         TestLogToRedfishEventLogNumeric, getCorrectParams());
 
-TEST_P(TestLogToRedfishNumericThrow, commitExpectToThrow)
+TEST_P(TestLogToRedfishEventLogNumeric, commitExpectNoThrow)
 {
-    EXPECT_THROW(sut->commit("Test", Milliseconds{100'000}, commmitValue),
-                 std::runtime_error);
+    EXPECT_NO_THROW(commit());
+}
+
+class TestLogToRedfishEventLogNumericThrow :
+    public TestLogToRedfishEventLogNumeric
+{};
+
+INSTANTIATE_TEST_SUITE_P(_, TestLogToRedfishEventLogNumericThrow,
+                         getIncorrectParams());
+
+TEST_P(TestLogToRedfishEventLogNumericThrow, commitExpectToThrow)
+{
+    EXPECT_ANY_THROW(commit());
 }
 
 } // namespace numeric
 
 namespace discrete
 {
-using LogParam = ::discrete::Severity;
+using LogParam = std::tuple<::discrete::Severity, TriggerValue>;
 
 static auto getCorrectParams()
 {
-    return Values(::discrete::Severity::critical, ::discrete::Severity::warning,
-                  ::discrete::Severity::ok);
+    return Values(
+        std::make_tuple(::discrete::Severity::critical,
+                        TriggerValue("DiscreteVal")),
+        std::make_tuple(::discrete::Severity::warning, TriggerValue("On")),
+        std::make_tuple(::discrete::Severity::ok, TriggerValue("Off")));
 }
 
 static auto getIncorrectParams()
 {
-    return Values(static_cast<::discrete::Severity>(-1),
-                  static_cast<::discrete::Severity>(42));
+    return Values(
+        std::make_tuple(static_cast<::discrete::Severity>(-1),
+                        TriggerValue("DiscreteVal42")),
+        std::make_tuple(static_cast<::discrete::Severity>(42),
+                        TriggerValue("On")),
+        std::make_tuple(::discrete::Severity::critical, TriggerValue(42.0)),
+        std::make_tuple(::discrete::Severity::warning, TriggerValue(0.0)),
+        std::make_tuple(::discrete::Severity::ok, TriggerValue(0.1)));
 }
 
-class TestLogToJournalDiscrete :
-    public Test,
-    public WithParamInterface<LogParam>
+template <typename ActionType>
+class TestActionDiscrete : public Test, public WithParamInterface<LogParam>
 {
   public:
     void SetUp() override
     {
-        auto severity = GetParam();
-        sut = std::make_unique<LogToJournal>(severity);
+        auto [severity, value] = GetParam();
+        sut = std::make_unique<ActionType>(severity);
+        commitValue = value;
     }
 
-    std::unique_ptr<LogToJournal> sut;
+    void commit()
+    {
+        std::string thresholdName = "MyThreshold";
+        sut->commit("MyTrigger", std::cref(thresholdName), "MySensor",
+                    Milliseconds{100'000}, commitValue);
+    }
+
+    TriggerValue commitValue;
+    std::unique_ptr<ActionType> sut;
 };
 
+class TestLogToJournalDiscrete : public TestActionDiscrete<LogToJournal>
+{};
+
 INSTANTIATE_TEST_SUITE_P(LogToJournalDiscreteParams, TestLogToJournalDiscrete,
                          getCorrectParams());
 
-TEST_P(TestLogToJournalDiscrete, commitAnActionDoesNotThrow)
+TEST_P(TestLogToJournalDiscrete, commitAnActionWIthDiscreteValueDoesNotThrow)
 {
-    EXPECT_NO_THROW(sut->commit("Test", Milliseconds{100'000}, 90.0));
+    EXPECT_NO_THROW(commit());
 }
 
 class TestLogToJournalDiscreteThrow : public TestLogToJournalDiscrete
@@ -144,76 +165,83 @@
 
 TEST_P(TestLogToJournalDiscreteThrow, commitAnActionExpectThrow)
 {
-    EXPECT_ANY_THROW(sut->commit("Test", Milliseconds{100'000}, 90.0));
+    EXPECT_ANY_THROW(commit());
 }
 
-class TestLogToRedfishDiscrete :
-    public Test,
-    public WithParamInterface<LogParam>
-{
-  public:
-    void SetUp() override
-    {
-        auto severity = GetParam();
-        sut = std::make_unique<LogToRedfish>(severity);
-    }
-
-    std::unique_ptr<LogToRedfish> sut;
-};
-
-INSTANTIATE_TEST_SUITE_P(LogToRedfishDiscreteParams, TestLogToRedfishDiscrete,
-                         getCorrectParams());
-
-TEST_P(TestLogToRedfishDiscrete, commitExpectNoThrow)
-{
-    EXPECT_NO_THROW(sut->commit("Test", Milliseconds{100'000}, 90.0));
-}
-
-class TestLogToRedfishDiscreteThrow : public TestLogToRedfishDiscrete
+class TestLogToRedfishEventLogDiscrete :
+    public TestActionDiscrete<LogToRedfishEventLog>
 {};
 
-INSTANTIATE_TEST_SUITE_P(_, TestLogToRedfishDiscreteThrow,
+INSTANTIATE_TEST_SUITE_P(LogToRedfishEventLogDiscreteParams,
+                         TestLogToRedfishEventLogDiscrete, getCorrectParams());
+
+TEST_P(TestLogToRedfishEventLogDiscrete, commitExpectNoThrow)
+{
+    EXPECT_NO_THROW(commit());
+}
+
+class TestLogToRedfishEventLogDiscreteThrow :
+    public TestLogToRedfishEventLogDiscrete
+{};
+
+INSTANTIATE_TEST_SUITE_P(_, TestLogToRedfishEventLogDiscreteThrow,
                          getIncorrectParams());
 
-TEST_P(TestLogToRedfishDiscreteThrow, commitExpectToThrow)
+TEST_P(TestLogToRedfishEventLogDiscreteThrow, commitExpectToThrow)
 {
-    EXPECT_THROW(sut->commit("Test", Milliseconds{100'000}, 90.0),
-                 std::runtime_error);
+    EXPECT_ANY_THROW(commit());
 }
 
 namespace onChange
 {
-class TestLogToJournalDiscreteOnChange : public Test
+
+template <typename ActionType>
+class TestActionOnChange : public Test
 {
   public:
     void SetUp() override
     {
-        sut = std::make_unique<LogToJournal>();
+        sut = std::make_unique<ActionType>();
     }
 
-    std::unique_ptr<LogToJournal> sut;
-};
-
-TEST_F(TestLogToJournalDiscreteOnChange, commitExpectNoThrow)
-{
-    EXPECT_NO_THROW(sut->commit("Test", Milliseconds{100'000}, 90.0));
-}
-
-class TestLogToRedfishDiscreteOnChange : public Test
-{
-  public:
-    void SetUp() override
+    void commit(TriggerValue value)
     {
-        sut = std::make_unique<LogToRedfish>();
+        sut->commit("MyTrigger", std::nullopt, "MySensor",
+                    Milliseconds{100'000}, value);
     }
 
-    std::unique_ptr<LogToRedfish> sut;
+    std::unique_ptr<ActionType> sut;
 };
 
-TEST_F(TestLogToRedfishDiscreteOnChange, commitExpectNoThrow)
+class TestLogToJournalDiscreteOnChange : public TestActionOnChange<LogToJournal>
+{};
+
+TEST_F(TestLogToJournalDiscreteOnChange, commitNumericValueExpectNoThrow)
 {
-    EXPECT_NO_THROW(sut->commit("Test", Milliseconds{100'000}, 90.0));
+    EXPECT_NO_THROW(commit(90.0));
 }
+
+TEST_F(TestLogToJournalDiscreteOnChange, commitDiscreteValueExpectNoThrow)
+{
+    EXPECT_NO_THROW(commit("Off"));
+}
+
+class TestLogToRedfishEventLogDiscreteOnChange :
+    public TestActionOnChange<LogToRedfishEventLog>
+{};
+
+TEST_F(TestLogToRedfishEventLogDiscreteOnChange,
+       commitNumericValueExpectNoThrow)
+{
+    EXPECT_NO_THROW(commit(90.0));
+}
+
+TEST_F(TestLogToRedfishEventLogDiscreteOnChange,
+       commitDiscreteValueExpectNoThrow)
+{
+    EXPECT_NO_THROW(commit("Off"));
+}
+
 } // namespace onChange
 } // namespace discrete
 
@@ -233,9 +261,16 @@
             std::make_shared<std::vector<std::string>>(std::move(names)));
     }
 
+    void commit(TriggerValue value)
+    {
+        sut->commit(triggerId, std::nullopt, "MySensor", Milliseconds{100'000},
+                    value);
+    }
+
     utils::Messanger messanger;
     NiceMock<MockFunction<void(const messages::UpdateReportInd&)>> updateReport;
     std::unique_ptr<UpdateReport> sut;
+    std::string triggerId = "MyTrigger";
 };
 
 TEST_F(TestUpdateReport, commitWhenReportNameIsEmptyExpectNoReportUpdate)
@@ -243,7 +278,7 @@
     EXPECT_CALL(updateReport, Call(_)).Times(0);
 
     make({});
-    sut->commit("Test", Milliseconds{100'000}, 90.0);
+    commit(90.0);
 }
 
 TEST_F(TestUpdateReport, commitExpectReportUpdate)
@@ -253,7 +288,7 @@
                 Call(FieldsAre(UnorderedElementsAreArray(names))));
 
     make(names);
-    sut->commit("Test", Milliseconds{100'000}, 90.0);
+    commit(90.0);
 }
 
 } // namespace action