Deduplicate event ids

Redfish specification states:
```
The value of the id field shall be the same as the Id property in the
event payload. The value of the Id property in the event payload should
be the same as the EventId property of the last event record in the
Events array. The value of the EventId property for an event record
should be a positive integer value and should be generated in a
sequential manner.
```

The event service code did not implement that correctly.  So:
1. Add ID fields for all events.
2. Remove the per-sse connection id field and rely solely on
   EventServiceManager.
3. Make sure all paths, (including metric report) are generating an
   event id that's based on the eventservice event id

Tested: Redfish event listener now sees events populated.
LastEventId when sent to the SSE socket now sees a contiguous id.

```
uri=$(curl -s --user "root:0penBmc" -k "https://192.168.7.2/redfish/v1/EventService" | jq -r .ServerSentEventUri)
curl -u root:0penBmc -vvv -k -N -H "Accept: text/event-stream" -H "Last-Event-Id: 0" "https://192.168.7.2$uri"
```

Change-Id: Ic32e036f40a53a9b2715639ae384d7891c768260
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/redfish-core/include/event_log.hpp b/redfish-core/include/event_log.hpp
index 40e5528..c902a09 100644
--- a/redfish-core/include/event_log.hpp
+++ b/redfish-core/include/event_log.hpp
@@ -2,6 +2,7 @@
 
 #include <nlohmann/json.hpp>
 
+#include <cstdint>
 #include <span>
 #include <string>
 #include <string_view>
@@ -19,10 +20,11 @@
                       std::string& messageID,
                       std::vector<std::string>& messageArgs);
 
-int formatEventLogEntry(
-    const std::string& logEntryID, const std::string& messageID,
-    std::span<std::string_view> messageArgs, std::string timestamp,
-    const std::string& customText, nlohmann::json::object_t& logEntryJson);
+int formatEventLogEntry(uint64_t eventId, const std::string& logEntryID,
+                        const std::string& messageID,
+                        std::span<std::string_view> messageArgs,
+                        std::string timestamp, const std::string& customText,
+                        nlohmann::json::object_t& logEntryJson);
 
 } // namespace event_log
 
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
index 5f29ca2..9ae34ad 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
@@ -70,8 +70,8 @@
 
     struct Event
     {
-        std::string id;
-        nlohmann::json message;
+        uint64_t id;
+        nlohmann::json::object_t message;
     };
 
     constexpr static size_t maxMessages = 200;
@@ -469,29 +469,37 @@
             BMCWEB_LOG_INFO("Attempting to find message for last id {}",
                             lastEventId);
             boost::circular_buffer<Event>::iterator lastEvent =
-                std::find_if(messages.begin(), messages.end(),
-                             [&lastEventId](const Event& event) {
-                                 return event.id == lastEventId;
-                             });
+                std::ranges::find_if(
+                    messages, [&lastEventId](const Event& event) {
+                        return std::to_string(event.id) == lastEventId;
+                    });
             // Can't find a matching ID
             if (lastEvent == messages.end())
             {
                 nlohmann::json msg = messages::eventBufferExceeded();
-                // If the buffer overloaded, send all messages.
-                subValue->sendEventToSubscriber(msg);
-                lastEvent = messages.begin();
+
+                std::string strMsg = msg.dump(
+                    2, ' ', true, nlohmann::json::error_handler_t::replace);
+                eventId++;
+                subValue->sendEventToSubscriber(eventId, std::move(strMsg));
             }
             else
             {
                 // Skip the last event the user already has
                 lastEvent++;
-            }
 
-            for (boost::circular_buffer<Event>::const_iterator event =
-                     lastEvent;
-                 lastEvent != messages.end(); lastEvent++)
-            {
-                subValue->sendEventToSubscriber(event->message);
+                for (boost::circular_buffer<Event>::const_iterator event =
+                         lastEvent;
+                     event != messages.end(); event++)
+                {
+                    std::string strMsg =
+                        nlohmann::json(event->message)
+                            .dump(2, ' ', true,
+                                  nlohmann::json::error_handler_t::replace);
+
+                    subValue->sendEventToSubscriber(event->id,
+                                                    std::move(strMsg));
+                }
             }
         }
         return id;
@@ -584,10 +592,66 @@
 
     bool sendTestEventLog(TestEvent& testEvent)
     {
+        eventId++;
+        nlohmann::json::array_t logEntryArray;
+        nlohmann::json& logEntryJson = logEntryArray.emplace_back();
+
+        if (testEvent.eventGroupId)
+        {
+            logEntryJson["EventGroupId"] = *testEvent.eventGroupId;
+        }
+
+        if (testEvent.eventTimestamp)
+        {
+            logEntryJson["EventTimestamp"] = *testEvent.eventTimestamp;
+        }
+
+        if (testEvent.originOfCondition)
+        {
+            logEntryJson["OriginOfCondition"]["@odata.id"] =
+                *testEvent.originOfCondition;
+        }
+        if (testEvent.severity)
+        {
+            logEntryJson["Severity"] = *testEvent.severity;
+        }
+
+        if (testEvent.message)
+        {
+            logEntryJson["Message"] = *testEvent.message;
+        }
+
+        if (testEvent.resolution)
+        {
+            logEntryJson["Resolution"] = *testEvent.resolution;
+        }
+
+        if (testEvent.messageId)
+        {
+            logEntryJson["MessageId"] = *testEvent.messageId;
+        }
+
+        if (testEvent.messageArgs)
+        {
+            logEntryJson["MessageArgs"] = *testEvent.messageArgs;
+        }
+        // MemberId is 0 : since we are sending one event record.
+        logEntryJson["MemberId"] = "0";
+
+        nlohmann::json msg;
+        msg["@odata.type"] = "#Event.v1_4_0.Event";
+        msg["Id"] = std::to_string(eventId);
+        msg["Name"] = "Event Log";
+        msg["Events"] = logEntryArray;
+
+        std::string strMsg =
+            msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace);
+
+        messages.push_back(Event(eventId, msg));
         for (const auto& it : subscriptionsMap)
         {
             std::shared_ptr<Subscription> entry = it.second;
-            if (!entry->sendTestEventLog(testEvent))
+            if (!entry->sendEventToSubscriber(eventId, std::string(strMsg)))
             {
                 return false;
             }
@@ -598,38 +662,46 @@
     static void sendEventsToSubs(
         const std::vector<EventLogObjectsType>& eventRecords)
     {
-        for (const auto& it :
-             EventServiceManager::getInstance().subscriptionsMap)
+        EventServiceManager& mgr = EventServiceManager::getInstance();
+        mgr.eventId++;
+        for (const auto& it : mgr.subscriptionsMap)
         {
             Subscription& entry = *it.second;
-            entry.filterAndSendEventLogs(eventRecords);
+            entry.filterAndSendEventLogs(mgr.eventId, eventRecords);
         }
     }
 
     static void sendTelemetryReportToSubs(
         const std::string& reportId, const telemetry::TimestampReadings& var)
     {
-        for (const auto& it :
-             EventServiceManager::getInstance().subscriptionsMap)
+        EventServiceManager& mgr = EventServiceManager::getInstance();
+        mgr.eventId++;
+
+        for (const auto& it : mgr.subscriptionsMap)
         {
             Subscription& entry = *it.second;
-            entry.filterAndSendReports(reportId, var);
+            entry.filterAndSendReports(mgr.eventId, reportId, var);
         }
     }
 
     void sendEvent(nlohmann::json::object_t eventMessage,
                    std::string_view origin, std::string_view resourceType)
     {
+        eventId++;
         eventMessage["EventId"] = eventId;
 
         eventMessage["EventTimestamp"] =
             redfish::time_utils::getDateTimeOffsetNow().first;
-        eventMessage["OriginOfCondition"] = origin;
+
+        if (!origin.empty())
+        {
+            eventMessage["OriginOfCondition"] = origin;
+        }
 
         // MemberId is 0 : since we are sending one event record.
         eventMessage["MemberId"] = "0";
 
-        messages.push_back(Event(std::to_string(eventId), eventMessage));
+        messages.push_back(Event(eventId, eventMessage));
 
         for (auto& it : subscriptionsMap)
         {
@@ -653,9 +725,8 @@
 
             std::string strMsg = msgJson.dump(
                 2, ' ', true, nlohmann::json::error_handler_t::replace);
-            entry->sendEventToSubscriber(std::move(strMsg));
+            entry->sendEventToSubscriber(eventId, std::move(strMsg));
         }
-        eventId++; // increment the eventId
     }
 };
 
diff --git a/redfish-core/include/subscription.hpp b/redfish-core/include/subscription.hpp
index 9c48dbb..704d07a 100644
--- a/redfish-core/include/subscription.hpp
+++ b/redfish-core/include/subscription.hpp
@@ -43,7 +43,6 @@
 struct TestEvent
 {
     std::optional<int64_t> eventGroupId;
-    std::optional<std::string> eventId;
     std::optional<std::string> eventTimestamp;
     std::optional<std::string> message;
     std::optional<std::vector<std::string>> messageArgs;
@@ -51,18 +50,6 @@
     std::optional<std::string> originOfCondition;
     std::optional<std::string> resolution;
     std::optional<std::string> severity;
-    // default constructor
-    TestEvent() = default;
-    // default assignment operator
-    TestEvent& operator=(const TestEvent&) = default;
-    // default copy constructor
-    TestEvent(const TestEvent&) = default;
-    // default move constructor
-    TestEvent(TestEvent&&) = default;
-    // default move assignment operator
-    TestEvent& operator=(TestEvent&&) = default;
-    // default destructor
-    ~TestEvent() = default;
 };
 
 class Subscription : public std::enable_shared_from_this<Subscription>
@@ -90,21 +77,17 @@
     void onHbTimeout(const std::weak_ptr<Subscription>& weakSelf,
                      const boost::system::error_code& ec);
 
-    bool sendEventToSubscriber(std::string&& msg);
-
-    bool sendTestEventLog(TestEvent& testEvent);
+    bool sendEventToSubscriber(uint64_t eventId, std::string&& msg);
 
     void filterAndSendEventLogs(
-        const std::vector<EventLogObjectsType>& eventRecords);
+        uint64_t eventId, const std::vector<EventLogObjectsType>& eventRecords);
 
-    void filterAndSendReports(const std::string& reportId,
+    void filterAndSendReports(uint64_t eventId, const std::string& reportId,
                               const telemetry::TimestampReadings& var);
 
     void updateRetryConfig(uint32_t retryAttempts,
                            uint32_t retryTimeoutInterval);
 
-    uint64_t getEventSeqNum() const;
-
     bool matchSseId(const crow::sse_socket::Connection& thisConn);
 
     // Check used to indicate what response codes are valid as part of our retry
@@ -115,7 +98,6 @@
     std::function<void()> deleter;
 
   private:
-    uint64_t eventSeqNum = 1;
     boost::urls::url host;
     std::shared_ptr<crow::ConnectionPolicy> policy;
     crow::sse_socket::Connection* sseConn = nullptr;
diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
index ea968af..fa003e3 100644
--- a/redfish-core/lib/event_service.hpp
+++ b/redfish-core/lib/event_service.hpp
@@ -197,12 +197,17 @@
                     return;
                 }
 
+                // From the Redfish spec on EventId
+                // A service can ignore this value and replace it with its own.
+                // note that this parameter is intentionally ignored
+
+                std::optional<std::string> eventId;
                 TestEvent testEvent;
                 // clang-format off
                 if (!json_util::readJsonAction(
                         req, asyncResp->res,
                         "EventGroupId", testEvent.eventGroupId,
-                        "EventId", testEvent.eventId,
+                        "EventId", eventId,
                         "EventTimestamp", testEvent.eventTimestamp,
                         "Message", testEvent.message,
                         "MessageArgs", testEvent.messageArgs,
diff --git a/redfish-core/src/event_log.cpp b/redfish-core/src/event_log.cpp
index d7cd2f2..a4e7850 100644
--- a/redfish-core/src/event_log.cpp
+++ b/redfish-core/src/event_log.cpp
@@ -23,6 +23,7 @@
 
 #include <cerrno>
 #include <cstddef>
+#include <cstdint>
 #include <ctime>
 #include <iomanip>
 #include <span>
@@ -120,10 +121,11 @@
     return 0;
 }
 
-int formatEventLogEntry(
-    const std::string& logEntryID, const std::string& messageID,
-    const std::span<std::string_view> messageArgs, std::string timestamp,
-    const std::string& customText, nlohmann::json::object_t& logEntryJson)
+int formatEventLogEntry(uint64_t eventId, const std::string& logEntryID,
+                        const std::string& messageID,
+                        const std::span<std::string_view> messageArgs,
+                        std::string timestamp, const std::string& customText,
+                        nlohmann::json::object_t& logEntryJson)
 {
     // Get the Message from the MessageRegistry
     const registries::Message* message = registries::getMessage(messageID);
@@ -156,7 +158,7 @@
     }
 
     // Fill in the log entry with the gathered data
-    logEntryJson["EventId"] = logEntryID;
+    logEntryJson["EventId"] = std::to_string(eventId);
 
     logEntryJson["Severity"] = message->messageSeverity;
     logEntryJson["Message"] = std::move(msg);
diff --git a/redfish-core/src/subscription.cpp b/redfish-core/src/subscription.cpp
index 1ca8a5e..f35a8e9 100644
--- a/redfish-core/src/subscription.cpp
+++ b/redfish-core/src/subscription.cpp
@@ -107,9 +107,6 @@
 {
     // send the heartbeat message
     nlohmann::json eventMessage = messages::redfishServiceFunctional();
-
-    std::string heartEventId = std::to_string(eventSeqNum);
-    eventMessage["EventId"] = heartEventId;
     eventMessage["EventTimestamp"] = time_utils::getDateTimeOffsetNow().first;
     eventMessage["OriginOfCondition"] =
         std::format("/redfish/v1/EventService/Subscriptions/{}", userSub->id);
@@ -121,13 +118,15 @@
     nlohmann::json msgJson;
     msgJson["@odata.type"] = "#Event.v1_4_0.Event";
     msgJson["Name"] = "Heartbeat";
-    msgJson["Id"] = heartEventId;
     msgJson["Events"] = std::move(eventRecord);
 
     std::string strMsg =
         msgJson.dump(2, ' ', true, nlohmann::json::error_handler_t::replace);
-    sendEventToSubscriber(std::move(strMsg));
-    eventSeqNum++;
+
+    // Note, eventId here is always zero, because this is a a per subscription
+    // event and doesn't have an "ID"
+    uint64_t eventId = 0;
+    sendEventToSubscriber(eventId, std::move(strMsg));
 }
 
 void Subscription::scheduleNextHeartbeatEvent()
@@ -180,7 +179,7 @@
     scheduleNextHeartbeatEvent();
 }
 
-bool Subscription::sendEventToSubscriber(std::string&& msg)
+bool Subscription::sendEventToSubscriber(uint64_t eventId, std::string&& msg)
 {
     persistent_data::EventServiceConfig eventServiceConfig =
         persistent_data::EventServiceStore::getInstance()
@@ -206,77 +205,13 @@
 
     if (sseConn != nullptr)
     {
-        eventSeqNum++;
-        sseConn->sendSseEvent(std::to_string(eventSeqNum), msg);
+        sseConn->sendSseEvent(std::to_string(eventId), msg);
     }
     return true;
 }
 
-bool Subscription::sendTestEventLog(TestEvent& testEvent)
-{
-    nlohmann::json::array_t logEntryArray;
-    nlohmann::json& logEntryJson = logEntryArray.emplace_back();
-
-    if (testEvent.eventGroupId)
-    {
-        logEntryJson["EventGroupId"] = *testEvent.eventGroupId;
-    }
-
-    if (testEvent.eventId)
-    {
-        logEntryJson["EventId"] = *testEvent.eventId;
-    }
-
-    if (testEvent.eventTimestamp)
-    {
-        logEntryJson["EventTimestamp"] = *testEvent.eventTimestamp;
-    }
-
-    if (testEvent.originOfCondition)
-    {
-        logEntryJson["OriginOfCondition"]["@odata.id"] =
-            *testEvent.originOfCondition;
-    }
-    if (testEvent.severity)
-    {
-        logEntryJson["Severity"] = *testEvent.severity;
-    }
-
-    if (testEvent.message)
-    {
-        logEntryJson["Message"] = *testEvent.message;
-    }
-
-    if (testEvent.resolution)
-    {
-        logEntryJson["Resolution"] = *testEvent.resolution;
-    }
-
-    if (testEvent.messageId)
-    {
-        logEntryJson["MessageId"] = *testEvent.messageId;
-    }
-
-    if (testEvent.messageArgs)
-    {
-        logEntryJson["MessageArgs"] = *testEvent.messageArgs;
-    }
-    // MemberId is 0 : since we are sending one event record.
-    logEntryJson["MemberId"] = "0";
-
-    nlohmann::json msg;
-    msg["@odata.type"] = "#Event.v1_4_0.Event";
-    msg["Id"] = std::to_string(eventSeqNum);
-    msg["Name"] = "Event Log";
-    msg["Events"] = logEntryArray;
-
-    std::string strMsg =
-        msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace);
-    return sendEventToSubscriber(std::move(strMsg));
-}
-
 void Subscription::filterAndSendEventLogs(
-    const std::vector<EventLogObjectsType>& eventRecords)
+    uint64_t eventId, const std::vector<EventLogObjectsType>& eventRecords)
 {
     nlohmann::json::array_t logEntryArray;
     for (const EventLogObjectsType& logEntry : eventRecords)
@@ -288,7 +223,7 @@
 
         nlohmann::json::object_t bmcLogEntry;
         if (event_log::formatEventLogEntry(
-                logEntry.id, logEntry.messageId, messageArgsView,
+                eventId, logEntry.id, logEntry.messageId, messageArgsView,
                 logEntry.timestamp, userSub->customText, bmcLogEntry) != 0)
         {
             BMCWEB_LOG_WARNING("Read eventLog entry failed");
@@ -312,6 +247,7 @@
         }
 
         logEntryArray.emplace_back(std::move(bmcLogEntry));
+        eventId++;
     }
 
     if (logEntryArray.empty())
@@ -322,16 +258,16 @@
 
     nlohmann::json msg;
     msg["@odata.type"] = "#Event.v1_4_0.Event";
-    msg["Id"] = std::to_string(eventSeqNum);
+    msg["Id"] = std::to_string(eventId);
     msg["Name"] = "Event Log";
     msg["Events"] = std::move(logEntryArray);
     std::string strMsg =
         msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace);
-    sendEventToSubscriber(std::move(strMsg));
-    eventSeqNum++;
+    sendEventToSubscriber(eventId, std::move(strMsg));
 }
 
-void Subscription::filterAndSendReports(const std::string& reportId,
+void Subscription::filterAndSendReports(uint64_t eventId,
+                                        const std::string& reportId,
                                         const telemetry::TimestampReadings& var)
 {
     boost::urls::url mrdUri = boost::urls::format(
@@ -366,7 +302,7 @@
 
     std::string strMsg =
         msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace);
-    sendEventToSubscriber(std::move(strMsg));
+    sendEventToSubscriber(eventId, std::move(strMsg));
 }
 
 void Subscription::updateRetryConfig(uint32_t retryAttempts,
@@ -381,11 +317,6 @@
     policy->retryIntervalSecs = std::chrono::seconds(retryTimeoutInterval);
 }
 
-uint64_t Subscription::getEventSeqNum() const
-{
-    return eventSeqNum;
-}
-
 bool Subscription::matchSseId(const crow::sse_socket::Connection& thisConn)
 {
     return &thisConn == sseConn;
diff --git a/test/redfish-core/include/event_log_test.cpp b/test/redfish-core/include/event_log_test.cpp
index 759a144..c51eee6 100644
--- a/test/redfish-core/include/event_log_test.cpp
+++ b/test/redfish-core/include/event_log_test.cpp
@@ -4,6 +4,7 @@
 
 #include <cerrno>
 #include <cstddef>
+#include <cstdint>
 #include <ctime>
 #include <string>
 #include <string_view>
@@ -126,6 +127,7 @@
 TEST(RedfishEventLog, FormatEventLogEntrySuccess)
 {
     int status = 0;
+    uint64_t eventId = 0;
     std::string logEntryID = "23849423_3";
     std::string messageID = "OpenBMC.0.1.PowerSupplyFanFailed";
     std::vector<std::string_view> messageArgs = {"PSU 1", "FAN 2"};
@@ -133,13 +135,13 @@
     std::string customText = "customText";
 
     nlohmann::json::object_t logEntryJson;
-    status = formatEventLogEntry(logEntryID, messageID, messageArgs, timestamp,
-                                 customText, logEntryJson);
+    status = formatEventLogEntry(eventId, logEntryID, messageID, messageArgs,
+                                 timestamp, customText, logEntryJson);
 
     ASSERT_EQ(status, 0);
 
     ASSERT_TRUE(logEntryJson.contains("EventId"));
-    ASSERT_EQ(logEntryJson["EventId"], "23849423_3");
+    ASSERT_EQ(logEntryJson["EventId"], "0");
 
     ASSERT_TRUE(logEntryJson.contains("Message"));
     ASSERT_EQ(logEntryJson["Message"], "Power supply PSU 1 fan FAN 2 failed.");
@@ -164,6 +166,7 @@
 TEST(RedfishEventLog, FormatEventLogEntryFail)
 {
     int status = 0;
+    uint64_t eventId = 0;
     std::string logEntryID = "malformed";
     std::string messageID;
     std::vector<std::string_view> messageArgs;
@@ -171,8 +174,8 @@
     std::string customText;
 
     nlohmann::json::object_t logEntryJson;
-    status = formatEventLogEntry(logEntryID, messageID, messageArgs, timestamp,
-                                 customText, logEntryJson);
+    status = formatEventLogEntry(eventId, logEntryID, messageID, messageArgs,
+                                 timestamp, customText, logEntryJson);
 
     ASSERT_EQ(status, -1);
 }
diff --git a/test/redfish-core/include/submit_test_event_test.cpp b/test/redfish-core/include/submit_test_event_test.cpp
index 1451cc4..3e819ea 100644
--- a/test/redfish-core/include/submit_test_event_test.cpp
+++ b/test/redfish-core/include/submit_test_event_test.cpp
@@ -1,21 +1,23 @@
-#include "event_service_store.hpp"
+#include "event_service_manager.hpp"
 #include "subscription.hpp"
 
-#include <boost/asio/io_context.hpp>
 #include <boost/url/url.hpp>
 
-#include <memory>
 #include <string>
 #include <vector>
 
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
+
+using ::testing::Optional;
+using ::testing::StrEq;
+
 namespace redfish
 {
 static TestEvent createTestEvent()
 {
     TestEvent testEvent;
     testEvent.eventGroupId = 1;
-    testEvent.eventId = "dummyEvent";
     testEvent.eventTimestamp = "2021-01";
     testEvent.message = "Test Message";
     testEvent.messageArgs = std::vector<std::string>{"arg1", "arg2"};
@@ -26,22 +28,17 @@
     return testEvent;
 }
 
-TEST(Subscription, submitTestEVent)
+TEST(EventServiceManager, submitTestEVent)
 {
-    boost::asio::io_context io;
     boost::urls::url url;
-    auto userSubscription =
-        std::make_shared<persistent_data::UserSubscription>();
+    EventServiceManager& evt = EventServiceManager::getInstance();
     {
-        auto sub = std::make_shared<Subscription>(userSubscription, url, io);
         TestEvent testEvent;
-        EXPECT_TRUE(sub->sendTestEventLog(testEvent));
+        EXPECT_TRUE(evt.sendTestEventLog(testEvent));
     }
     {
-        auto sub = std::make_shared<Subscription>(userSubscription, url, io);
         TestEvent testEvent;
         testEvent.eventGroupId = 1;
-        testEvent.eventId = "GPU-RST-RECOMM-EVENT";
         testEvent.eventTimestamp = "2021-01-01T00:00:00Z";
         testEvent.message = "Custom Message";
         testEvent.messageArgs =
@@ -51,54 +48,23 @@
         testEvent.resolution =
             "Reset the GPU at the next service window since the ECC errors are contained";
         testEvent.severity = "Informational";
-        EXPECT_TRUE(sub->sendTestEventLog(testEvent));
+        EXPECT_TRUE(evt.sendTestEventLog(testEvent));
     }
     {
-        auto sub = std::make_shared<Subscription>(userSubscription, url, io);
         TestEvent testEvent = createTestEvent();
 
-        bool result = sub->sendTestEventLog(testEvent);
+        bool result = evt.sendTestEventLog(testEvent);
 
         EXPECT_TRUE(result);
-        if (testEvent.eventGroupId.has_value())
-        {
-            EXPECT_EQ(testEvent.eventGroupId.value(), 1);
-        }
-        if (testEvent.eventId.has_value())
-        {
-            EXPECT_EQ(testEvent.eventId.value(), "dummyEvent");
-        }
-        if (testEvent.eventTimestamp.has_value())
-        {
-            EXPECT_EQ(testEvent.eventTimestamp.value(), "2021-01");
-        }
-        if (testEvent.message.has_value())
-        {
-            EXPECT_EQ(testEvent.message.value(), "Test Message");
-        }
-        if (testEvent.messageArgs.has_value())
-        {
-            EXPECT_EQ(testEvent.messageArgs.value().size(), 2);
-            EXPECT_EQ(testEvent.messageArgs.value()[0], "arg1");
-            EXPECT_EQ(testEvent.messageArgs.value()[1], "arg2");
-        }
-        if (testEvent.messageId.has_value())
-        {
-            EXPECT_EQ(testEvent.messageId.value(), "Dummy message ID");
-        }
-        if (testEvent.originOfCondition.has_value())
-        {
-            EXPECT_EQ(testEvent.originOfCondition.value(),
-                      "/redfish/v1/Chassis/GPU_SXM_1");
-        }
-        if (testEvent.resolution.has_value())
-        {
-            EXPECT_EQ(testEvent.resolution.value(), "custom resolution");
-        }
-        if (testEvent.severity.has_value())
-        {
-            EXPECT_EQ(testEvent.severity.value(), "whatever");
-        }
+
+        EXPECT_THAT(testEvent.eventGroupId, Optional(1));
+        EXPECT_THAT(testEvent.eventTimestamp, Optional(StrEq("2021-01")));
+        EXPECT_THAT(testEvent.message, Optional(StrEq("Test Message")));
+        EXPECT_THAT(testEvent.messageId, Optional(StrEq("Dummy message ID")));
+        EXPECT_THAT(testEvent.originOfCondition,
+                    Optional(StrEq("/redfish/v1/Chassis/GPU_SXM_1")));
+        EXPECT_THAT(testEvent.resolution, Optional(StrEq("custom resolution")));
+        EXPECT_THAT(testEvent.severity, Optional(StrEq("whatever")));
     }
 }
 } // namespace redfish