test: Add dbus handler unit tests

Created unit tests for all of the object mapper dbus handlers.

Refactor the handlers to handler.cpp to allow unit testing.
Also updated to use std::set_intersection.

Change-Id: Ib87ab81f949d27f7dab55899d3e8d380e43bda04
Signed-off-by: Willy Tu <wltu@google.com>
diff --git a/src/main.cpp b/src/main.cpp
index 991852e..5f43767 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,4 +1,5 @@
 #include "associations.hpp"
+#include "handler.hpp"
 #include "processing.hpp"
 #include "types.hpp"
 
@@ -279,27 +280,6 @@
     }
 }
 
-// TODO(ed) replace with std::set_intersection once c++17 is available
-template <class InputIt1, class InputIt2>
-bool intersect(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
-{
-    while (first1 != last1 && first2 != last2)
-    {
-        if (*first1 < *first2)
-        {
-            ++first1;
-            continue;
-        }
-        if (*first2 < *first1)
-        {
-            ++first2;
-            continue;
-        }
-        return true;
-    }
-    return false;
-}
-
 void doListNames(
     boost::asio::io_context& io, InterfaceMapType& interfaceMap,
     sdbusplus::asio::connection* systemBus,
@@ -342,32 +322,6 @@
         "ListNames");
 }
 
-void addObjectMapResult(std::vector<InterfaceMapType::value_type>& objectMap,
-                        const std::string& objectPath,
-                        const ConnectionNames::value_type& interfaceMap)
-{
-    // Adds an object path/service name/interface list entry to
-    // the results of GetSubTree and GetAncestors.
-    // If an entry for the object path already exists, just add the
-    // service name and interfaces to that entry, otherwise create
-    // a new entry.
-    auto entry = std::find_if(
-        objectMap.begin(), objectMap.end(),
-        [&objectPath](const auto& i) { return objectPath == i.first; });
-
-    if (entry != objectMap.end())
-    {
-        entry->second.emplace(interfaceMap);
-    }
-    else
-    {
-        InterfaceMapType::value_type object;
-        object.first = objectPath;
-        object.second.emplace(interfaceMap);
-        objectMap.push_back(object);
-    }
-}
-
 // Remove parents of the passed in path that:
 // 1) Only have the 3 default interfaces on them
 //    - Means D-Bus created these, not application code,
@@ -430,223 +384,6 @@
     }
 }
 
-std::vector<InterfaceMapType::value_type>
-    getAncestors(const InterfaceMapType& interfaceMap, std::string reqPath,
-                 std::vector<std::string>& interfaces)
-{
-    // Interfaces need to be sorted for intersect to function
-    std::sort(interfaces.begin(), interfaces.end());
-
-    if (reqPath.ends_with("/"))
-    {
-        reqPath.pop_back();
-    }
-    if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
-    {
-        throw sdbusplus::xyz::openbmc_project::Common::Error::
-            ResourceNotFound();
-    }
-
-    std::vector<InterfaceMapType::value_type> ret;
-    for (const auto& objectPath : interfaceMap)
-    {
-        const auto& thisPath = objectPath.first;
-
-        if (reqPath == thisPath)
-        {
-            continue;
-        }
-
-        if (reqPath.starts_with(thisPath))
-        {
-            if (interfaces.empty())
-            {
-                ret.emplace_back(objectPath);
-            }
-            else
-            {
-                for (const auto& interfaceMap : objectPath.second)
-                {
-                    if (intersect(interfaces.begin(), interfaces.end(),
-                                  interfaceMap.second.begin(),
-                                  interfaceMap.second.end()))
-                    {
-                        addObjectMapResult(ret, thisPath, interfaceMap);
-                    }
-                }
-            }
-        }
-    }
-
-    return ret;
-}
-
-ConnectionNames getObject(const InterfaceMapType& interfaceMap,
-                          const std::string& path,
-                          std::vector<std::string>& interfaces)
-{
-    ConnectionNames results;
-
-    // Interfaces need to be sorted for intersect to function
-    std::sort(interfaces.begin(), interfaces.end());
-    auto pathRef = interfaceMap.find(path);
-    if (pathRef == interfaceMap.end())
-    {
-        throw sdbusplus::xyz::openbmc_project::Common::Error::
-            ResourceNotFound();
-    }
-    if (interfaces.empty())
-    {
-        return pathRef->second;
-    }
-    for (const auto& interfaceMap : pathRef->second)
-    {
-        if (intersect(interfaces.begin(), interfaces.end(),
-                      interfaceMap.second.begin(), interfaceMap.second.end()))
-        {
-            results.emplace(interfaceMap.first, interfaceMap.second);
-        }
-    }
-
-    if (results.empty())
-    {
-        throw sdbusplus::xyz::openbmc_project::Common::Error::
-            ResourceNotFound();
-    }
-
-    return results;
-}
-
-std::vector<InterfaceMapType::value_type>
-    getSubTree(const InterfaceMapType& interfaceMap, std::string reqPath,
-               int32_t depth, std::vector<std::string>& interfaces)
-{
-    if (depth <= 0)
-    {
-        depth = std::numeric_limits<int32_t>::max();
-    }
-    // Interfaces need to be sorted for intersect to function
-    std::sort(interfaces.begin(), interfaces.end());
-
-    // reqPath is now guaranteed to have a trailing "/" while reqPathStripped
-    // will be guaranteed not to have a trailing "/"
-    if (!reqPath.ends_with("/"))
-    {
-        reqPath += "/";
-    }
-    std::string_view reqPathStripped =
-        std::string_view(reqPath).substr(0, reqPath.size() - 1);
-
-    if (!reqPathStripped.empty() &&
-        interfaceMap.find(reqPathStripped) == interfaceMap.end())
-    {
-        throw sdbusplus::xyz::openbmc_project::Common::Error::
-            ResourceNotFound();
-    }
-
-    std::vector<InterfaceMapType::value_type> ret;
-    for (const auto& objectPath : interfaceMap)
-    {
-        const auto& thisPath = objectPath.first;
-
-        // Skip exact match on stripped search term
-        if (thisPath == reqPathStripped)
-        {
-            continue;
-        }
-
-        if (thisPath.starts_with(reqPath))
-        {
-            // count the number of slashes past the stripped search term
-            int32_t thisDepth = std::count(
-                thisPath.begin() + reqPathStripped.size(), thisPath.end(), '/');
-            if (thisDepth <= depth)
-            {
-                for (const auto& interfaceMap : objectPath.second)
-                {
-                    if (intersect(interfaces.begin(), interfaces.end(),
-                                  interfaceMap.second.begin(),
-                                  interfaceMap.second.end()) ||
-                        interfaces.empty())
-                    {
-                        addObjectMapResult(ret, thisPath, interfaceMap);
-                    }
-                }
-            }
-        }
-    }
-
-    return ret;
-}
-
-std::vector<std::string> getSubTreePaths(const InterfaceMapType& interfaceMap,
-                                         std::string reqPath, int32_t depth,
-                                         std::vector<std::string>& interfaces)
-{
-    if (depth <= 0)
-    {
-        depth = std::numeric_limits<int32_t>::max();
-    }
-    // Interfaces need to be sorted for intersect to function
-    std::sort(interfaces.begin(), interfaces.end());
-
-    // reqPath is now guaranteed to have a trailing "/" while reqPathStripped
-    // will be guaranteed not to have a trailing "/"
-    if (!reqPath.ends_with("/"))
-    {
-        reqPath += "/";
-    }
-    std::string_view reqPathStripped =
-        std::string_view(reqPath).substr(0, reqPath.size() - 1);
-
-    if (!reqPathStripped.empty() &&
-        interfaceMap.find(reqPathStripped) == interfaceMap.end())
-    {
-        throw sdbusplus::xyz::openbmc_project::Common::Error::
-            ResourceNotFound();
-    }
-
-    std::vector<std::string> ret;
-    for (const auto& objectPath : interfaceMap)
-    {
-        const auto& thisPath = objectPath.first;
-
-        // Skip exact match on stripped search term
-        if (thisPath == reqPathStripped)
-        {
-            continue;
-        }
-
-        if (thisPath.starts_with(reqPath))
-        {
-            // count the number of slashes past the stripped search term
-            int thisDepth = std::count(
-                thisPath.begin() + reqPathStripped.size(), thisPath.end(), '/');
-            if (thisDepth <= depth)
-            {
-                bool add = interfaces.empty();
-                for (const auto& interfaceMap : objectPath.second)
-                {
-                    if (intersect(interfaces.begin(), interfaces.end(),
-                                  interfaceMap.second.begin(),
-                                  interfaceMap.second.end()))
-                    {
-                        add = true;
-                        break;
-                    }
-                }
-                if (add)
-                {
-                    // TODO(ed) this is a copy
-                    ret.emplace_back(thisPath);
-                }
-            }
-        }
-    }
-
-    return ret;
-}
-
 int main()
 {
     boost::asio::io_context io;