1 #include "src/handler.hpp" 2 3 #include "src/types.hpp" 4 5 #include <xyz/openbmc_project/Common/error.hpp> 6 7 #include <span> 8 #include <utility> 9 #include <vector> 10 11 #include <gmock/gmock.h> 12 #include <gtest/gtest.h> 13 14 using ::testing::ElementsAre; 15 16 class TestHandler : public testing::Test 17 { 18 protected: 19 InterfaceMapType interfaceMap = { 20 { 21 "/test/object_path_0", 22 {{"test_object_connection_0", {"test_interface_0"}}}, 23 }, 24 { 25 "/test/object_path_0/child", 26 {{"test_object_connection_1", {"test_interface_1"}}}, 27 }, 28 { 29 "/test/object_path_0/child/grandchild", 30 {{"test_object_connection_2", {"test_interface_2"}}}, 31 }, 32 { 33 "/test/object_path_0/child/grandchild/dog", 34 {{"test_object_connection_3", {"test_interface_3"}}}, 35 }}; 36 }; 37 38 TEST_F(TestHandler, AddObjectMapResult) 39 { 40 std::vector<InterfaceMapType::value_type> interfaceMaps; 41 addObjectMapResult(interfaceMaps, "test_object_path", 42 std::pair<std::string, InterfaceNames>( 43 "test_object_connection_0", { 44 "test_interface_0", 45 "test_interface_1", 46 })); 47 48 addObjectMapResult(interfaceMaps, "test_object_path", 49 std::pair<std::string, InterfaceNames>( 50 "test_object_connection_1", { 51 "test_interface_0", 52 "test_interface_1", 53 })); 54 ASSERT_EQ(interfaceMaps.size(), 1); 55 56 auto entry = std::find_if( 57 interfaceMaps.begin(), interfaceMaps.end(), 58 [](const auto& i) { return "test_object_path" == i.first; }); 59 ASSERT_NE(entry, interfaceMap.end()); 60 for (const auto& [_, interfaces] : entry->second) 61 { 62 ASSERT_THAT(interfaces, 63 ElementsAre("test_interface_0", "test_interface_1")); 64 } 65 66 // Change the interface, but expect it to be unchanged 67 addObjectMapResult(interfaceMaps, "test_object_path", 68 std::pair<std::string, InterfaceNames>( 69 "test_object_connection_0", {"test_interface_2"})); 70 addObjectMapResult(interfaceMaps, "test_object_path", 71 std::pair<std::string, InterfaceNames>( 72 "test_object_connection_1", {"test_interface_2"})); 73 entry = std::find_if( 74 interfaceMaps.begin(), interfaceMaps.end(), 75 [](const auto& i) { return "test_object_path" == i.first; }); 76 ASSERT_NE(entry, interfaceMaps.end()); 77 for (const auto& [_, interfaces] : entry->second) 78 { 79 ASSERT_THAT(interfaces, 80 ElementsAre("test_interface_0", "test_interface_1")); 81 } 82 } 83 84 TEST_F(TestHandler, getAncestorsBad) 85 { 86 std::string path = "/test/object_path_0/child/grandchild"; 87 std::vector<std::string> interfaces = {"bad_interface"}; 88 std::vector<InterfaceMapType::value_type> ancestors = 89 getAncestors(interfaceMap, path, interfaces); 90 ASSERT_TRUE(ancestors.empty()); 91 92 path = "/invalid_path"; 93 EXPECT_THROW( 94 getAncestors(interfaceMap, path, interfaces), 95 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound); 96 } 97 98 TEST_F(TestHandler, getAncestorsGood) 99 { 100 std::string path = "/test/object_path_0/child/grandchild"; 101 std::vector<std::string> interfaces = {"test_interface_0", 102 "test_interface_1"}; 103 std::vector<InterfaceMapType::value_type> ancestors = 104 getAncestors(interfaceMap, path, interfaces); 105 ASSERT_EQ(ancestors.size(), 2); 106 107 // Grand Parent 108 EXPECT_EQ(ancestors[0].first, "/test/object_path_0"); 109 ASSERT_EQ(ancestors[0].second.size(), 1); 110 auto grandParent = ancestors[0].second.find("test_object_connection_0"); 111 ASSERT_NE(grandParent, ancestors[0].second.end()); 112 ASSERT_THAT(grandParent->second, ElementsAre("test_interface_0")); 113 114 // Parent 115 ASSERT_EQ(ancestors[1].first, "/test/object_path_0/child"); 116 ASSERT_EQ(ancestors[1].second.size(), 1); 117 auto parent = ancestors[1].second.find("test_object_connection_1"); 118 ASSERT_NE(parent, ancestors[1].second.end()); 119 ASSERT_THAT(parent->second, ElementsAre("test_interface_1")); 120 } 121 122 TEST_F(TestHandler, getObjectBad) 123 { 124 std::string path = "/test/object_path_0"; 125 std::vector<std::string> interfaces = {"bad_interface"}; 126 EXPECT_THROW( 127 getObject(interfaceMap, path, interfaces), 128 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound); 129 130 path = "/invalid_path"; 131 EXPECT_THROW( 132 getObject(interfaceMap, path, interfaces), 133 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound); 134 135 path = "/"; 136 EXPECT_THROW( 137 getObject(interfaceMap, path, interfaces), 138 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound); 139 } 140 141 TEST_F(TestHandler, getObjectGood) 142 { 143 std::string path = "/test/object_path_0"; 144 std::vector<std::string> interfaces = {"test_interface_0", 145 "test_interface_1"}; 146 ConnectionNames connection = getObject(interfaceMap, path, interfaces); 147 auto object = connection.find("test_object_connection_0"); 148 ASSERT_NE(object, connection.end()); 149 ASSERT_THAT(object->second, ElementsAre("test_interface_0")); 150 151 path = "/test/object_path_0/child"; 152 connection = getObject(interfaceMap, path, interfaces); 153 object = connection.find("test_object_connection_1"); 154 ASSERT_NE(object, connection.end()); 155 ASSERT_THAT(object->second, ElementsAre("test_interface_1")); 156 } 157 158 TEST_F(TestHandler, getSubTreeBad) 159 { 160 std::string path = "/test/object_path_0"; 161 std::vector<std::string> interfaces = {"bad_interface"}; 162 std::vector<InterfaceMapType::value_type> subtree = 163 getSubTree(interfaceMap, path, 0, interfaces); 164 ASSERT_TRUE(subtree.empty()); 165 166 path = "/invalid_path"; 167 EXPECT_THROW( 168 getSubTree(interfaceMap, path, 0, interfaces), 169 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound); 170 } 171 172 void verifySubtree(std::span<InterfaceMapType::value_type> subtree) 173 { 174 ASSERT_EQ(subtree.size(), 2); 175 ConnectionNames connection = subtree[0].second; 176 auto object = connection.find("test_object_connection_1"); 177 ASSERT_NE(object, connection.end()); 178 ASSERT_THAT(object->second, ElementsAre("test_interface_1")); 179 180 connection = subtree[1].second; 181 object = connection.find("test_object_connection_3"); 182 ASSERT_NE(object, connection.end()); 183 ASSERT_THAT(object->second, ElementsAre("test_interface_3")); 184 } 185 186 TEST_F(TestHandler, getSubTreeGood) 187 { 188 std::string path0 = "/test/object_path_0"; 189 std::string path1 = "/test/object_path_0/child/grandchild"; 190 std::vector<std::string> interfaces = {"test_interface_1", 191 "test_interface_3"}; 192 // Root 193 std::vector<InterfaceMapType::value_type> subtree = 194 getSubTree(interfaceMap, "/", 0, interfaces); 195 verifySubtree(subtree); 196 197 // Path0 198 subtree = getSubTree(interfaceMap, path0, 0, interfaces); 199 verifySubtree(subtree); 200 201 // Path0 with Depth path of 1 202 subtree = getSubTree(interfaceMap, path0, 1, interfaces); 203 ASSERT_EQ(subtree.size(), 1); 204 ConnectionNames connection = subtree[0].second; 205 auto object = connection.find("test_object_connection_1"); 206 ASSERT_NE(object, connection.end()); 207 ASSERT_THAT(object->second, ElementsAre("test_interface_1")); 208 209 // Path1 210 subtree = getSubTree(interfaceMap, path1, 0, interfaces); 211 ASSERT_EQ(subtree.size(), 1); 212 connection = subtree[0].second; 213 object = connection.find("test_object_connection_3"); 214 ASSERT_NE(object, connection.end()); 215 ASSERT_THAT(object->second, ElementsAre("test_interface_3")); 216 } 217 218 TEST_F(TestHandler, getSubTreePathsBad) 219 { 220 std::string path = "/test/object_path_0"; 221 std::vector<std::string> interfaces = {"bad_interface"}; 222 std::vector<std::string> subtreePath = 223 getSubTreePaths(interfaceMap, path, 0, interfaces); 224 ASSERT_TRUE(subtreePath.empty()); 225 226 path = "/invalid_path"; 227 EXPECT_THROW( 228 getSubTreePaths(interfaceMap, path, 0, interfaces), 229 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound); 230 } 231 232 TEST_F(TestHandler, getSubTreePathsGood) 233 { 234 std::string path0 = "/test/object_path_0"; 235 std::string path1 = "/test/object_path_0/child/grandchild"; 236 std::vector<std::string> interfaces = {"test_interface_1", 237 "test_interface_3"}; 238 // Root 239 std::vector<std::string> subtreePath = 240 getSubTreePaths(interfaceMap, "/", 0, interfaces); 241 ASSERT_THAT(subtreePath, 242 ElementsAre("/test/object_path_0/child", 243 "/test/object_path_0/child/grandchild/dog")); 244 245 // Path0 246 subtreePath = getSubTreePaths(interfaceMap, path0, 0, interfaces); 247 ASSERT_THAT(subtreePath, 248 ElementsAre("/test/object_path_0/child", 249 "/test/object_path_0/child/grandchild/dog")); 250 251 // Path0 + Depth path of 1 252 subtreePath = getSubTreePaths(interfaceMap, path0, 1, interfaces); 253 ASSERT_THAT(subtreePath, ElementsAre("/test/object_path_0/child")); 254 255 // Path1 256 subtreePath = getSubTreePaths(interfaceMap, path1, 0, interfaces); 257 ASSERT_THAT(subtreePath, 258 ElementsAre("/test/object_path_0/child/grandchild/dog")); 259 } 260