Refactor eventMatchesFilter

eventMatchesFilter no longer needs to be a member of the Subscription
class, because it no longer uses subscription data.  Refactor so it can
be in its own file, with its own set of unit tests.

Tested: Unit Tests pass.

Change-Id: I718fa36021078973609591c704cb717d31079df7
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/meson.build b/meson.build
index 8ae5d23..479900c 100644
--- a/meson.build
+++ b/meson.build
@@ -414,7 +414,7 @@
     'test/include/ossl_random.cpp',
     'test/include/ssl_key_handler_test.cpp',
     'test/include/str_utility_test.cpp',
-    'test/redfish-core/include/event_service_manager_test.cpp',
+    'test/redfish-core/include/event_matches_filter_test.cpp',
     'test/redfish-core/include/filter_expr_executor_test.cpp',
     'test/redfish-core/include/filter_expr_parser_test.cpp',
     'test/redfish-core/include/privileges_test.cpp',
diff --git a/redfish-core/include/event_matches_filter.hpp b/redfish-core/include/event_matches_filter.hpp
new file mode 100644
index 0000000..af4bf43
--- /dev/null
+++ b/redfish-core/include/event_matches_filter.hpp
@@ -0,0 +1,150 @@
+#pragma once
+
+#include "generated/enums/log_entry.hpp"
+#include "logging.hpp"
+#include "persistent_data.hpp"
+#include "str_utility.hpp"
+
+#include <nlohmann/json.hpp>
+
+#include <ranges>
+#include <string>
+#include <string_view>
+#include <vector>
+
+namespace redfish
+{
+
+inline void getRegistryAndMessageKey(const std::string& messageID,
+                                     std::string& registryName,
+                                     std::string& messageKey)
+{
+    // Redfish MessageIds are in the form
+    // RegistryName.MajorVersion.MinorVersion.MessageKey, so parse it to find
+    // the right Message
+    std::vector<std::string> fields;
+    fields.reserve(4);
+    bmcweb::split(fields, messageID, '.');
+    if (fields.size() == 4)
+    {
+        registryName = fields[0];
+        messageKey = fields[3];
+    }
+}
+
+inline bool eventMatchesFilter(const persistent_data::UserSubscription& userSub,
+                               const nlohmann::json::object_t& eventMessage,
+                               std::string_view resType)
+{
+    // If resourceTypes list is empty, assume all
+    if (!userSub.resourceTypes.empty())
+    {
+        // Search the resourceTypes list for the subscription.
+        auto resourceTypeIndex = std::ranges::find_if(
+            userSub.resourceTypes, [resType](const std::string& rtEntry) {
+                return rtEntry == resType;
+            });
+        if (resourceTypeIndex == userSub.resourceTypes.end())
+        {
+            BMCWEB_LOG_DEBUG("Not subscribed to this resource");
+            return false;
+        }
+        BMCWEB_LOG_DEBUG("ResourceType {} found in the subscribed list",
+                         resType);
+    }
+
+    // If registryPrefixes list is empty, don't filter events
+    // send everything.
+    if (!userSub.registryPrefixes.empty())
+    {
+        auto eventJson = eventMessage.find("MessageId");
+        if (eventJson == eventMessage.end())
+        {
+            return false;
+        }
+
+        const std::string* messageId =
+            eventJson->second.get_ptr<const std::string*>();
+        if (messageId == nullptr)
+        {
+            BMCWEB_LOG_ERROR("MessageId wasn't a string???");
+            return false;
+        }
+
+        std::string registry;
+        std::string messageKey;
+        getRegistryAndMessageKey(*messageId, registry, messageKey);
+
+        auto obj = std::ranges::find(userSub.registryPrefixes, registry);
+        if (obj == userSub.registryPrefixes.end())
+        {
+            return false;
+        }
+    }
+
+    if (!userSub.originResources.empty())
+    {
+        auto eventJson = eventMessage.find("OriginOfCondition");
+        if (eventJson == eventMessage.end())
+        {
+            return false;
+        }
+
+        const std::string* originOfCondition =
+            eventJson->second.get_ptr<const std::string*>();
+        if (originOfCondition == nullptr)
+        {
+            BMCWEB_LOG_ERROR("OriginOfCondition wasn't a string???");
+            return false;
+        }
+
+        auto obj =
+            std::ranges::find(userSub.originResources, *originOfCondition);
+
+        if (obj == userSub.originResources.end())
+        {
+            return false;
+        }
+    }
+
+    // If registryMsgIds list is empty, assume all
+    if (!userSub.registryMsgIds.empty())
+    {
+        auto eventJson = eventMessage.find("MessageId");
+        if (eventJson == eventMessage.end())
+        {
+            BMCWEB_LOG_DEBUG("'MessageId' not present");
+            return false;
+        }
+
+        const std::string* messageId =
+            eventJson->second.get_ptr<const std::string*>();
+        if (messageId == nullptr)
+        {
+            BMCWEB_LOG_ERROR("EventType wasn't a string???");
+            return false;
+        }
+
+        std::string registry;
+        std::string messageKey;
+        getRegistryAndMessageKey(*messageId, registry, messageKey);
+
+        BMCWEB_LOG_DEBUG("extracted registry {}", registry);
+        BMCWEB_LOG_DEBUG("extracted message key {}", messageKey);
+
+        auto obj = std::ranges::find(
+            userSub.registryMsgIds, std::format("{}.{}", registry, messageKey));
+        if (obj == userSub.registryMsgIds.end())
+        {
+            BMCWEB_LOG_DEBUG("did not find registry {} in registryMsgIds",
+                             registry);
+            BMCWEB_LOG_DEBUG("registryMsgIds has {} entries",
+                             userSub.registryMsgIds.size());
+            return false;
+        }
+    }
+
+    return true;
+}
+
+} // namespace redfish
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
index f9ac760..0d9a68b 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
@@ -16,6 +16,7 @@
 #pragma once
 #include "dbus_utility.hpp"
 #include "error_messages.hpp"
+#include "event_matches_filter.hpp"
 #include "event_service_store.hpp"
 #include "filter_expr_executor.hpp"
 #include "generated/enums/event.hpp"
@@ -206,23 +207,6 @@
     return 0;
 }
 
-inline void getRegistryAndMessageKey(const std::string& messageID,
-                                     std::string& registryName,
-                                     std::string& messageKey)
-{
-    // Redfish MessageIds are in the form
-    // RegistryName.MajorVersion.MinorVersion.MessageKey, so parse it to find
-    // the right Message
-    std::vector<std::string> fields;
-    fields.reserve(4);
-    bmcweb::split(fields, messageID, '.');
-    if (fields.size() == 4)
-    {
-        registryName = fields[0];
-        messageKey = fields[3];
-    }
-}
-
 inline int formatEventLogEntry(
     const std::string& logEntryID, const std::string& messageID,
     const std::span<std::string_view> messageArgs, std::string timestamp,
@@ -319,132 +303,6 @@
         return true;
     }
 
-    bool eventMatchesFilter(const nlohmann::json::object_t& eventMessage,
-                            std::string_view resType)
-    {
-        // If resourceTypes list is empty, assume all
-        if (!userSub.resourceTypes.empty())
-        {
-            // Search the resourceTypes list for the subscription.
-            auto resourceTypeIndex = std::ranges::find_if(
-                userSub.resourceTypes, [resType](const std::string& rtEntry) {
-                    return rtEntry == resType;
-                });
-            if (resourceTypeIndex == userSub.resourceTypes.end())
-            {
-                BMCWEB_LOG_DEBUG("Not subscribed to this resource");
-                return false;
-            }
-            BMCWEB_LOG_DEBUG("ResourceType {} found in the subscribed list",
-                             resType);
-        }
-
-        // If registryPrefixes list is empty, don't filter events
-        // send everything.
-        if (!userSub.registryPrefixes.empty())
-        {
-            auto eventJson = eventMessage.find("MessageId");
-            if (eventJson == eventMessage.end())
-            {
-                return false;
-            }
-
-            const std::string* messageId =
-                eventJson->second.get_ptr<const std::string*>();
-            if (messageId == nullptr)
-            {
-                BMCWEB_LOG_ERROR("MessageId wasn't a string???");
-                return false;
-            }
-
-            std::string registry;
-            std::string messageKey;
-            event_log::getRegistryAndMessageKey(*messageId, registry,
-                                                messageKey);
-
-            auto obj = std::ranges::find(userSub.registryPrefixes, registry);
-            if (obj == userSub.registryPrefixes.end())
-            {
-                return false;
-            }
-        }
-
-        if (!userSub.originResources.empty())
-        {
-            auto eventJson = eventMessage.find("OriginOfCondition");
-            if (eventJson == eventMessage.end())
-            {
-                return false;
-            }
-
-            const std::string* originOfCondition =
-                eventJson->second.get_ptr<const std::string*>();
-            if (originOfCondition == nullptr)
-            {
-                BMCWEB_LOG_ERROR("OriginOfCondition wasn't a string???");
-                return false;
-            }
-
-            auto obj =
-                std::ranges::find(userSub.originResources, *originOfCondition);
-
-            if (obj == userSub.originResources.end())
-            {
-                return false;
-            }
-        }
-
-        // If registryMsgIds list is empty, assume all
-        if (!userSub.registryMsgIds.empty())
-        {
-            auto eventJson = eventMessage.find("MessageId");
-            if (eventJson == eventMessage.end())
-            {
-                BMCWEB_LOG_DEBUG("'MessageId' not present");
-                return false;
-            }
-
-            const std::string* messageId =
-                eventJson->second.get_ptr<const std::string*>();
-            if (messageId == nullptr)
-            {
-                BMCWEB_LOG_ERROR("EventType wasn't a string???");
-                return false;
-            }
-
-            std::string registry;
-            std::string messageKey;
-            event_log::getRegistryAndMessageKey(*messageId, registry,
-                                                messageKey);
-
-            BMCWEB_LOG_DEBUG("extracted registry {}", registry);
-            BMCWEB_LOG_DEBUG("extracted message key {}", messageKey);
-
-            auto obj =
-                std::ranges::find(userSub.registryMsgIds,
-                                  std::format("{}.{}", registry, messageKey));
-            if (obj == userSub.registryMsgIds.end())
-            {
-                BMCWEB_LOG_DEBUG("did not find registry {} in registryMsgIds",
-                                 registry);
-                BMCWEB_LOG_DEBUG("registryMsgIds has {} entries",
-                                 userSub.registryMsgIds.size());
-                return false;
-            }
-        }
-
-        if (filter)
-        {
-            if (!memberMatches(eventMessage, *filter))
-            {
-                BMCWEB_LOG_DEBUG("Filter didn't match");
-                return false;
-            }
-        }
-
-        return true;
-    }
-
     bool sendTestEventLog()
     {
         nlohmann::json::array_t logEntryArray;
@@ -490,13 +348,22 @@
                 continue;
             }
 
-            if (!eventMatchesFilter(bmcLogEntry, ""))
+            if (!eventMatchesFilter(userSub, bmcLogEntry, ""))
             {
                 BMCWEB_LOG_DEBUG("Event {} did not match the filter",
                                  nlohmann::json(bmcLogEntry).dump());
                 continue;
             }
 
+            if (filter)
+            {
+                if (!memberMatches(bmcLogEntry, *filter))
+                {
+                    BMCWEB_LOG_DEBUG("Filter didn't match");
+                    continue;
+                }
+            }
+
             logEntryArray.emplace_back(std::move(bmcLogEntry));
         }
 
@@ -1118,7 +985,7 @@
         for (auto& it : subscriptionsMap)
         {
             std::shared_ptr<Subscription>& entry = it.second;
-            if (!entry->eventMatchesFilter(eventMessage, resourceType))
+            if (!eventMatchesFilter(entry->userSub, eventMessage, resourceType))
             {
                 BMCWEB_LOG_DEBUG("Filter didn't match");
                 continue;
diff --git a/test/redfish-core/include/event_matches_filter_test.cpp b/test/redfish-core/include/event_matches_filter_test.cpp
new file mode 100644
index 0000000..29dbc1a
--- /dev/null
+++ b/test/redfish-core/include/event_matches_filter_test.cpp
@@ -0,0 +1,82 @@
+#include "event_matches_filter.hpp"
+#include "event_service_store.hpp"
+
+#include <nlohmann/json.hpp>
+
+#include <string_view>
+
+#include <gtest/gtest.h>
+
+namespace redfish
+{
+
+TEST(EventServiceManager, eventMatchesFilter)
+{
+    {
+        persistent_data::UserSubscription sub;
+        nlohmann::json::object_t event;
+
+        // Default constructed should always pass
+        EXPECT_TRUE(eventMatchesFilter(sub, event, "Event"));
+    }
+    {
+        nlohmann::json::object_t event;
+        // Resource types filter
+        persistent_data::UserSubscription sub;
+        sub.resourceTypes.emplace_back("Task");
+        EXPECT_FALSE(eventMatchesFilter(sub, event, "Event"));
+        EXPECT_TRUE(eventMatchesFilter(sub, event, "Task"));
+    }
+    {
+        nlohmann::json::object_t event;
+        // Resource types filter
+        persistent_data::UserSubscription sub;
+        sub.registryMsgIds.emplace_back("OpenBMC.PostComplete");
+
+        // Correct message registry
+        event["MessageId"] = "OpenBMC.0.1.PostComplete";
+        EXPECT_TRUE(eventMatchesFilter(sub, event, "Event"));
+
+        // Different message registry
+        event["MessageId"] = "Task.0.1.PostComplete";
+        EXPECT_FALSE(eventMatchesFilter(sub, event, "Event"));
+
+        // Different MessageId
+        event["MessageId"] = "OpenBMC.0.1.NoMatch";
+        EXPECT_FALSE(eventMatchesFilter(sub, event, "Event"));
+    }
+    {
+        nlohmann::json::object_t event;
+        // Resource types filter
+        persistent_data::UserSubscription sub;
+        event["MessageId"] = "OpenBMC.0.1.PostComplete";
+
+        // Correct message registry
+        sub.registryPrefixes.emplace_back("OpenBMC");
+        EXPECT_TRUE(eventMatchesFilter(sub, event, "Event"));
+
+        // Different message registry
+        event["MessageId"] = "Task.0.1.PostComplete";
+        EXPECT_FALSE(eventMatchesFilter(sub, event, "Event"));
+    }
+    {
+        nlohmann::json::object_t event;
+        // Resource types filter
+        {
+            persistent_data::UserSubscription sub;
+            event["OriginOfCondition"] = "/redfish/v1/Managers/bmc";
+
+            // Correct origin
+            sub.originResources.emplace_back("/redfish/v1/Managers/bmc");
+            EXPECT_TRUE(eventMatchesFilter(sub, event, "Event"));
+        }
+        {
+            persistent_data::UserSubscription sub;
+            // Incorrect origin
+            sub.originResources.clear();
+            sub.originResources.emplace_back("/redfish/v1/Managers/bmc_not");
+            EXPECT_FALSE(eventMatchesFilter(sub, event, "Event"));
+        }
+    }
+}
+} // namespace redfish
diff --git a/test/redfish-core/include/event_service_manager_test.cpp b/test/redfish-core/include/event_service_manager_test.cpp
deleted file mode 100644
index fa3818d..0000000
--- a/test/redfish-core/include/event_service_manager_test.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-#include "event_service_manager.hpp"
-#include "event_service_store.hpp"
-#include "filter_expr_printer.hpp"
-
-#include <boost/asio/io_context.hpp>
-#include <boost/url/url.hpp>
-#include <nlohmann/json.hpp>
-
-#include <optional>
-#include <string_view>
-
-#include <gtest/gtest.h>
-
-namespace redfish
-{
-
-TEST(EventServiceManager, eventMatchesFilter)
-{
-    boost::asio::io_context io;
-    boost::urls::url url;
-
-    {
-        Subscription ioSub(url, io);
-        nlohmann::json::object_t event;
-
-        // Default constructed should always pass
-        EXPECT_TRUE(ioSub.eventMatchesFilter(event, "Event"));
-    }
-    {
-        nlohmann::json::object_t event;
-        // Resource types filter
-        Subscription ioSub(url, io);
-        persistent_data::UserSubscription& sub = ioSub.userSub;
-        sub.resourceTypes.emplace_back("Task");
-        EXPECT_FALSE(ioSub.eventMatchesFilter(event, "Event"));
-        EXPECT_TRUE(ioSub.eventMatchesFilter(event, "Task"));
-    }
-    {
-        nlohmann::json::object_t event;
-        // Resource types filter
-        Subscription ioSub(url, io);
-        persistent_data::UserSubscription& sub = ioSub.userSub;
-        sub.registryMsgIds.emplace_back("OpenBMC.PostComplete");
-
-        // Correct message registry
-        event["MessageId"] = "OpenBMC.0.1.PostComplete";
-        EXPECT_TRUE(ioSub.eventMatchesFilter(event, "Event"));
-
-        // Different message registry
-        event["MessageId"] = "Task.0.1.PostComplete";
-        EXPECT_FALSE(ioSub.eventMatchesFilter(event, "Event"));
-
-        // Different MessageId
-        event["MessageId"] = "OpenBMC.0.1.NoMatch";
-        EXPECT_FALSE(ioSub.eventMatchesFilter(event, "Event"));
-    }
-    {
-        nlohmann::json::object_t event;
-        // Resource types filter
-        Subscription ioSub(url, io);
-        event["MessageId"] = "OpenBMC.0.1.PostComplete";
-
-        // Correct message registry
-        ioSub.filter = parseFilter("MessageId eq 'OpenBMC.0.1.PostComplete'");
-        EXPECT_TRUE(ioSub.eventMatchesFilter(event, "Event"));
-
-        // Different message registry
-        ioSub.filter = parseFilter("MessageId ne 'OpenBMC.0.1.PostComplete'");
-        EXPECT_FALSE(ioSub.eventMatchesFilter(event, "Event"));
-    }
-    {
-        nlohmann::json::object_t event;
-        // Resource types filter
-        Subscription ioSub(url, io);
-        persistent_data::UserSubscription& sub = ioSub.userSub;
-        event["MessageId"] = "OpenBMC.0.1.PostComplete";
-
-        // Correct message registry
-        sub.registryPrefixes.emplace_back("OpenBMC");
-        EXPECT_TRUE(ioSub.eventMatchesFilter(event, "Event"));
-
-        // Different message registry
-        event["MessageId"] = "Task.0.1.PostComplete";
-        EXPECT_FALSE(ioSub.eventMatchesFilter(event, "Event"));
-    }
-    {
-        nlohmann::json::object_t event;
-        // Resource types filter
-        {
-            Subscription ioSub(url, io);
-            persistent_data::UserSubscription& sub = ioSub.userSub;
-            event["OriginOfCondition"] = "/redfish/v1/Managers/bmc";
-
-            // Correct origin
-            sub.originResources.emplace_back("/redfish/v1/Managers/bmc");
-            EXPECT_TRUE(ioSub.eventMatchesFilter(event, "Event"));
-        }
-        {
-            Subscription ioSub(url, io);
-            persistent_data::UserSubscription& sub = ioSub.userSub;
-            // Incorrect origin
-            sub.originResources.clear();
-            sub.originResources.emplace_back("/redfish/v1/Managers/bmc_not");
-            EXPECT_FALSE(ioSub.eventMatchesFilter(event, "Event"));
-        }
-    }
-}
-} // namespace redfish