From a80a3af035d4fe989acd81c45aee4acf8c3d998a Mon Sep 17 00:00:00 2001 From: Andrew Geissler Date: Mon, 4 Feb 2019 14:01:49 -0600 Subject: unit-test: Create initial associations file Make interface more unit testable by moving to separate file and documenting it. Change-Id: Ia27f33d706c62a0011790ec94185dd6be3922f21 Signed-off-by: Andrew Geissler --- Makefile.am | 3 +- src/associations.cpp | 76 +++++++++++++++++++++++++++++++++++ src/associations.hpp | 58 +++++++++++++++++++++++++++ src/main.cpp | 109 +-------------------------------------------------- 4 files changed, 137 insertions(+), 109 deletions(-) create mode 100644 src/associations.cpp create mode 100644 src/associations.hpp diff --git a/Makefile.am b/Makefile.am index 62fe99e..668a529 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,7 +26,8 @@ libmapper_la_SOURCES = libmapper/mapper.c libmapper_la_LDFLAGS = $(SYSTEMD_LIBS) -version-info 1:0:0 -shared libmapper_la_CFLAGS = $(SYSTEMD_CFLAGS) -mapperx_SOURCES = src/main.cpp src/argument.cpp src/processing.cpp +mapperx_SOURCES = src/main.cpp src/argument.cpp src/processing.cpp \ + src/associations.cpp mapperx_LDFLAGS = $(SDBUSPLUS_LIBS) -pthread -ltinyxml2 mapperx_CXXFLAGS = $(SYSTEMD_CFLAGS) -DBOOST_SYSTEM_NO_DEPRECATED -DBOOST_ERROR_CODE_HEADER_ONLY -DBOOST_ALL_NO_LIB diff --git a/src/associations.cpp b/src/associations.cpp new file mode 100644 index 0000000..3ae7db4 --- /dev/null +++ b/src/associations.cpp @@ -0,0 +1,76 @@ +#include "associations.hpp" + +void removeAssociation(const std::string& sourcePath, const std::string& owner, + sdbusplus::asio::object_server& server, + AssociationOwnersType& assocOwners, + AssociationInterfaces& assocInterfaces) +{ + // Use associationOwners to find the association paths and endpoints + // that the passed in object path and service own. Remove all of + // these endpoints from the actual association D-Bus objects, and if + // the endpoints property is then empty, the whole association object + // can be removed. Note there can be multiple services that own an + // association, and also that sourcePath is the path of the object + // that contains the org.openbmc.Associations interface and not the + // association path itself. + + // Find the services that have associations for this object path + auto owners = assocOwners.find(sourcePath); + if (owners == assocOwners.end()) + { + return; + } + + // Find the association paths and endpoints owned by this object + // path for this service. + auto assocs = owners->second.find(owner); + if (assocs == owners->second.end()) + { + return; + } + + for (const auto& [assocPath, endpointsToRemove] : assocs->second) + { + // Get the association D-Bus object for this assocPath + auto target = assocInterfaces.find(assocPath); + if (target == assocInterfaces.end()) + { + continue; + } + + // Remove the entries in the endpoints D-Bus property for this + // path/owner/association-path. + auto& existingEndpoints = std::get(target->second); + for (const auto& endpointToRemove : endpointsToRemove) + { + auto e = std::find(existingEndpoints.begin(), + existingEndpoints.end(), endpointToRemove); + + if (e != existingEndpoints.end()) + { + existingEndpoints.erase(e); + } + } + + // Remove the association from D-Bus if there are no more endpoints, + // otherwise just update the endpoints property. + if (existingEndpoints.empty()) + { + server.remove_interface(std::get(target->second)); + std::get(target->second) = nullptr; + std::get(target->second).clear(); + } + else + { + std::get(target->second) + ->set_property("endpoints", existingEndpoints); + } + } + + // Remove the associationOwners entries for this owning path/service. + owners->second.erase(assocs); + if (owners->second.empty()) + { + assocOwners.erase(owners); + } +} diff --git a/src/associations.hpp b/src/associations.hpp new file mode 100644 index 0000000..41df157 --- /dev/null +++ b/src/associations.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +// Associations and some metadata are stored in associationInterfaces. +// The fields are: +// * ifacePos - holds the D-Bus interface object +// * endpointsPos - holds the endpoints array that shadows the property +static constexpr auto ifacePos = 0; +static constexpr auto endpointsPos = 1; +using Endpoints = std::vector; + +using AssociationInterfaces = boost::container::flat_map< + std::string, + std::tuple, Endpoints>>; + +// The associationOwners map contains information about creators of +// associations, so that when a org.openbmc.Association interface is +// removed or its 'associations' property is changed, the mapper owned +// association objects can be correctly handled. It is a map of the +// object path of the org.openbmc.Association owner to a map of the +// service the path is owned by, to a map of the association objects to +// their endpoint paths: +// map[ownerPath : map[service : map[assocPath : [endpoint paths]]] +// For example: +// [/logging/entry/1 : +// [xyz.openbmc_project.Logging : +// [/logging/entry/1/callout : [/system/cpu0], +// /system/cpu0/fault : [/logging/entry/1]]]] + +using AssociationPaths = + boost::container::flat_map>; + +using AssociationOwnersType = boost::container::flat_map< + std::string, boost::container::flat_map>; + +/** @brief Remove input association + * + * @param[in] sourcePath - Path of the object that contains the + * org.openbmc.Associations + * @param[in] owner - The Dbus service having its associations + * removed + * @param[in,out] server - sdbus system object + * @param[in,out] assocOwners - Owners of associations + * @param[in,out] assocInterfaces - Associations endpoints + * + * @return Void, server, assocOwners, and assocInterfaces updated if needed + */ +void removeAssociation(const std::string& sourcePath, const std::string& owner, + sdbusplus::asio::object_server& server, + AssociationOwnersType& assocOwners, + AssociationInterfaces& assocInterfaces); diff --git a/src/main.cpp b/src/main.cpp index 801d910..e96ffe3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,3 +1,4 @@ +#include "associations.hpp" #include "processing.hpp" #include "src/argument.hpp" @@ -29,40 +30,7 @@ using interface_map_type = boost::container::flat_map< using Association = std::tuple; -// Associations and some metadata are stored in associationInterfaces. -// The fields are: -// * ifacePos - holds the D-Bus interface object -// * endpointsPos - holds the endpoints array that shadows the property -static constexpr auto ifacePos = 0; -static constexpr auto endpointsPos = 1; -using Endpoints = std::vector; -using AssociationInterfaces = boost::container::flat_map< - std::string, - std::tuple, Endpoints>>; - AssociationInterfaces associationInterfaces; - -// The associationOwners map contains information about creators of -// associations, so that when a org.openbmc.Association interface is -// removed or its 'associations' property is changed, the mapper owned -// association objects can be correctly handled. It is a map of the -// object path of the org.openbmc.Association owner to a map of the -// service the path is owned by, to a map of the association objects to -// their endpoint paths: -// map[ownerPath : map[service : map[assocPath : [endpoint paths]]] -// For example: -// [/logging/entry/1 : -// [xyz.openbmc_project.Logging : -// [/logging/entry/1/callout : [/system/cpu0], -// /system/cpu0/fault : [/logging/entry/1]]]] - -using AssociationPaths = - boost::container::flat_map>; - -using AssociationOwnersType = boost::container::flat_map< - std::string, boost::container::flat_map>; - AssociationOwnersType associationOwners; static WhiteBlackList service_whitelist; @@ -365,81 +333,6 @@ void associationChanged(sdbusplus::asio::object_server& objectServer, } } -void removeAssociation(const std::string& sourcePath, const std::string& owner, - sdbusplus::asio::object_server& server, - AssociationOwnersType& assocOwners, - AssociationInterfaces& assocInterfaces) -{ - // Use associationOwners to find the association paths and endpoints - // that the passed in object path and service own. Remove all of - // these endpoints from the actual association D-Bus objects, and if - // the endpoints property is then empty, the whole association object - // can be removed. Note there can be multiple services that own an - // association, and also that sourcePath is the path of the object - // that contains the org.openbmc.Associations interface and not the - // association path itself. - - // Find the services that have associations for this object path - auto owners = assocOwners.find(sourcePath); - if (owners == assocOwners.end()) - { - return; - } - - // Find the association paths and endpoints owned by this object - // path for this service. - auto assocs = owners->second.find(owner); - if (assocs == owners->second.end()) - { - return; - } - - for (const auto& [assocPath, endpointsToRemove] : assocs->second) - { - // Get the association D-Bus object for this assocPath - auto target = assocInterfaces.find(assocPath); - if (target == assocInterfaces.end()) - { - continue; - } - - // Remove the entries in the endpoints D-Bus property for this - // path/owner/association-path. - auto& existingEndpoints = std::get(target->second); - for (const auto& endpointToRemove : endpointsToRemove) - { - auto e = std::find(existingEndpoints.begin(), - existingEndpoints.end(), endpointToRemove); - - if (e != existingEndpoints.end()) - { - existingEndpoints.erase(e); - } - } - - // Remove the association from D-Bus if there are no more endpoints, - // otherwise just update the endpoints property. - if (existingEndpoints.empty()) - { - server.remove_interface(std::get(target->second)); - std::get(target->second) = nullptr; - std::get(target->second).clear(); - } - else - { - std::get(target->second) - ->set_property("endpoints", existingEndpoints); - } - } - - // Remove the associationOwners entries for this owning path/service. - owners->second.erase(assocs); - if (owners->second.empty()) - { - associationOwners.erase(owners); - } -} - void do_associations(sdbusplus::asio::connection* system_bus, sdbusplus::asio::object_server& objectServer, const std::string& processName, const std::string& path) -- cgit v1.2.1