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