1 #include "item_updater.hpp" 2 #include "mocked_utils.hpp" 3 4 #include <sdbusplus/test/sdbus_mock.hpp> 5 6 #include <gmock/gmock.h> 7 #include <gtest/gtest.h> 8 9 using namespace phosphor::software::updater; 10 using ::testing::_; 11 using ::testing::Pointee; 12 using ::testing::Return; 13 using ::testing::ReturnArg; 14 using ::testing::StrEq; 15 16 using std::experimental::any; 17 18 class TestItemUpdater : public ::testing::Test 19 { 20 public: 21 using Properties = ItemUpdater::Properties; 22 using PropertyType = utils::UtilsInterface::PropertyType; 23 24 TestItemUpdater() : 25 mockedUtils( 26 reinterpret_cast<const utils::MockedUtils&>(utils::getUtils())) 27 { 28 ON_CALL(mockedUtils, getVersionId(_)).WillByDefault(ReturnArg<0>()); 29 ON_CALL(mockedUtils, getPropertyImpl(_, _, _, _, StrEq(PRESENT))) 30 .WillByDefault(Return(any(PropertyType(true)))); 31 } 32 33 ~TestItemUpdater() 34 { 35 utils::freeUtils(); 36 } 37 38 const auto& GetActivations() 39 { 40 return itemUpdater->activations; 41 } 42 43 std::string getObjPath(const std::string& versionId) 44 { 45 return std::string(dBusPath) + "/" + versionId; 46 } 47 48 void onPsuInventoryChanged(const std::string& psuPath, 49 const Properties& properties) 50 { 51 itemUpdater->onPsuInventoryChanged(psuPath, properties); 52 } 53 54 void scanDirectory(const fs::path& p) 55 { 56 itemUpdater->scanDirectory(p); 57 } 58 59 static constexpr auto dBusPath = SOFTWARE_OBJPATH; 60 sdbusplus::SdBusMock sdbusMock; 61 sdbusplus::bus::bus mockedBus = sdbusplus::get_mocked_new(&sdbusMock); 62 const utils::MockedUtils& mockedUtils; 63 std::unique_ptr<ItemUpdater> itemUpdater; 64 }; 65 66 TEST_F(TestItemUpdater, ctordtor) 67 { 68 EXPECT_CALL(mockedUtils, getLatestVersion(_)).Times(1); 69 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath); 70 } 71 72 TEST_F(TestItemUpdater, NotCreateObjectOnNotPresent) 73 { 74 constexpr auto psuPath = "/com/example/inventory/psu0"; 75 constexpr auto service = "com.example.Software.Psu"; 76 constexpr auto version = "version0"; 77 std::string objPath = getObjPath(version); 78 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_)) 79 .WillOnce(Return(std::vector<std::string>({psuPath}))); 80 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _)) 81 .WillOnce(Return(service)); 82 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath))) 83 .WillOnce(Return(std::string(version))); 84 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath), 85 _, StrEq(PRESENT))) 86 .WillOnce(Return(any(PropertyType(false)))); // not present 87 88 // The item updater itself 89 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath))) 90 .Times(1); 91 92 // No activation/version objects are created 93 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) 94 .Times(0); 95 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath); 96 } 97 98 TEST_F(TestItemUpdater, CreateOnePSUOnPresent) 99 { 100 constexpr auto psuPath = "/com/example/inventory/psu0"; 101 constexpr auto service = "com.example.Software.Psu"; 102 constexpr auto version = "version0"; 103 std::string objPath = getObjPath(version); 104 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_)) 105 .WillOnce(Return(std::vector<std::string>({psuPath}))); 106 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _)) 107 .WillOnce(Return(service)); 108 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath))) 109 .WillOnce(Return(std::string(version))); 110 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath), 111 _, StrEq(PRESENT))) 112 .WillOnce(Return(any(PropertyType(true)))); // present 113 114 // The item updater itself 115 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath))) 116 .Times(1); 117 118 // activation and version object will be added 119 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) 120 .Times(2); 121 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath); 122 } 123 124 TEST_F(TestItemUpdater, CreateTwoPSUsWithSameVersion) 125 { 126 constexpr auto psu0 = "/com/example/inventory/psu0"; 127 constexpr auto psu1 = "/com/example/inventory/psu1"; 128 constexpr auto service = "com.example.Software.Psu"; 129 auto version0 = std::string("version0"); 130 auto version1 = std::string("version0"); 131 auto objPath0 = getObjPath(version0); 132 auto objPath1 = getObjPath(version1); 133 134 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_)) 135 .WillOnce(Return(std::vector<std::string>({psu0, psu1}))); 136 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu0), _)) 137 .WillOnce(Return(service)); 138 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu1), _)) 139 .WillOnce(Return(service)); 140 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0))) 141 .WillOnce(Return(std::string(version0))); 142 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _, 143 StrEq(PRESENT))) 144 .WillOnce(Return(any(PropertyType(true)))); // present 145 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1))) 146 .WillOnce(Return(std::string(version1))); 147 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _, 148 StrEq(PRESENT))) 149 .WillOnce(Return(any(PropertyType(true)))); // present 150 151 // The item updater itself 152 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath))) 153 .Times(1); 154 155 // activation and version object will be added 156 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath0))) 157 .Times(2); 158 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath); 159 160 // Verify there is only one activation and it has two associations 161 const auto& activations = GetActivations(); 162 EXPECT_EQ(1u, activations.size()); 163 const auto& activation = activations.find(version0)->second; 164 const auto& assocs = activation->associations(); 165 EXPECT_EQ(2u, assocs.size()); 166 EXPECT_EQ(psu0, std::get<2>(assocs[0])); 167 EXPECT_EQ(psu1, std::get<2>(assocs[1])); 168 } 169 170 TEST_F(TestItemUpdater, CreateTwoPSUsWithDifferentVersion) 171 { 172 constexpr auto psu0 = "/com/example/inventory/psu0"; 173 constexpr auto psu1 = "/com/example/inventory/psu1"; 174 constexpr auto service = "com.example.Software.Psu"; 175 auto version0 = std::string("version0"); 176 auto version1 = std::string("version1"); 177 auto objPath0 = getObjPath(version0); 178 auto objPath1 = getObjPath(version1); 179 180 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_)) 181 .WillOnce(Return(std::vector<std::string>({psu0, psu1}))); 182 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu0), _)) 183 .WillOnce(Return(service)); 184 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu1), _)) 185 .WillOnce(Return(service)); 186 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0))) 187 .WillOnce(Return(std::string(version0))); 188 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _, 189 StrEq(PRESENT))) 190 .WillOnce(Return(any(PropertyType(true)))); // present 191 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1))) 192 .WillOnce(Return(std::string(version1))); 193 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _, 194 StrEq(PRESENT))) 195 .WillOnce(Return(any(PropertyType(true)))); // present 196 197 // The item updater itself 198 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath))) 199 .Times(1); 200 201 // two new activation and version objects will be added 202 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath0))) 203 .Times(2); 204 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath1))) 205 .Times(2); 206 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath); 207 208 // Verify there are two activations and each with one association 209 const auto& activations = GetActivations(); 210 EXPECT_EQ(2u, activations.size()); 211 const auto& activation0 = activations.find(version0)->second; 212 const auto& assocs0 = activation0->associations(); 213 EXPECT_EQ(1u, assocs0.size()); 214 EXPECT_EQ(psu0, std::get<2>(assocs0[0])); 215 216 const auto& activation1 = activations.find(version1)->second; 217 const auto& assocs1 = activation1->associations(); 218 EXPECT_EQ(1u, assocs1.size()); 219 EXPECT_EQ(psu1, std::get<2>(assocs1[0])); 220 } 221 222 TEST_F(TestItemUpdater, OnOnePSURemoved) 223 { 224 constexpr auto psuPath = "/com/example/inventory/psu0"; 225 constexpr auto service = "com.example.Software.Psu"; 226 constexpr auto version = "version0"; 227 std::string objPath = getObjPath(version); 228 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_)) 229 .WillOnce(Return(std::vector<std::string>({psuPath}))); 230 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _)) 231 .WillOnce(Return(service)); 232 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath))) 233 .WillOnce(Return(std::string(version))); 234 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath), 235 _, StrEq(PRESENT))) 236 .WillOnce(Return(any(PropertyType(true)))); // present 237 238 // The item updater itself 239 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath))) 240 .Times(1); 241 242 // activation and version object will be added 243 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) 244 .Times(2); 245 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath); 246 247 // the activation and version object will be removed 248 Properties p{{PRESENT, PropertyType(false)}}; 249 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath))) 250 .Times(2); 251 onPsuInventoryChanged(psuPath, p); 252 253 // on exit, item updater is removed 254 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(dBusPath))) 255 .Times(1); 256 } 257 258 TEST_F(TestItemUpdater, OnOnePSUAdded) 259 { 260 constexpr auto psuPath = "/com/example/inventory/psu0"; 261 constexpr auto service = "com.example.Software.Psu"; 262 constexpr auto version = "version0"; 263 std::string objPath = getObjPath(version); 264 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_)) 265 .WillOnce(Return(std::vector<std::string>({psuPath}))); 266 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _)) 267 .WillOnce(Return(service)); 268 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath))) 269 .WillOnce(Return(std::string(version))); 270 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath), 271 _, StrEq(PRESENT))) 272 .WillOnce(Return(any(PropertyType(false)))); // not present 273 274 // The item updater itself 275 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath))) 276 .Times(1); 277 278 // No activation/version objects are created 279 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) 280 .Times(0); 281 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath); 282 283 // The PSU is present and version is added in a single call 284 Properties propAdded{{PRESENT, PropertyType(true)}}; 285 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath))) 286 .WillOnce(Return(std::string(version))); 287 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) 288 .Times(2); 289 onPsuInventoryChanged(psuPath, propAdded); 290 } 291 292 TEST_F(TestItemUpdater, OnOnePSURemovedAndAdded) 293 { 294 constexpr auto psuPath = "/com/example/inventory/psu0"; 295 constexpr auto service = "com.example.Software.Psu"; 296 constexpr auto version = "version0"; 297 std::string objPath = getObjPath(version); 298 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_)) 299 .WillOnce(Return(std::vector<std::string>({psuPath}))); 300 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _)) 301 .WillOnce(Return(service)); 302 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath))) 303 .WillOnce(Return(std::string(version))); 304 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath), 305 _, StrEq(PRESENT))) 306 .WillOnce(Return(any(PropertyType(true)))); // present 307 308 // The item updater itself 309 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath))) 310 .Times(1); 311 312 // activation and version object will be added 313 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) 314 .Times(2); 315 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath); 316 317 // the activation and version object will be removed 318 Properties propRemoved{{PRESENT, PropertyType(false)}}; 319 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath))) 320 .Times(2); 321 onPsuInventoryChanged(psuPath, propRemoved); 322 323 Properties propAdded{{PRESENT, PropertyType(true)}}; 324 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath))) 325 .WillOnce(Return(std::string(version))); 326 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) 327 .Times(2); 328 onPsuInventoryChanged(psuPath, propAdded); 329 330 // on exit, objects are removed 331 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath))) 332 .Times(2); 333 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(dBusPath))) 334 .Times(1); 335 } 336 337 TEST_F(TestItemUpdater, 338 TwoPSUsWithSameVersionRemovedAndAddedWithDifferntVersion) 339 { 340 constexpr auto psu0 = "/com/example/inventory/psu0"; 341 constexpr auto psu1 = "/com/example/inventory/psu1"; 342 constexpr auto service = "com.example.Software.Psu"; 343 auto version0 = std::string("version0"); 344 auto version1 = std::string("version0"); 345 auto objPath0 = getObjPath(version0); 346 auto objPath1 = getObjPath(version1); 347 348 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_)) 349 .WillOnce(Return(std::vector<std::string>({psu0, psu1}))); 350 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu0), _)) 351 .WillOnce(Return(service)); 352 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu1), _)) 353 .WillOnce(Return(service)); 354 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0))) 355 .WillOnce(Return(std::string(version0))); 356 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _, 357 StrEq(PRESENT))) 358 .WillOnce(Return(any(PropertyType(true)))); // present 359 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1))) 360 .WillOnce(Return(std::string(version1))); 361 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _, 362 StrEq(PRESENT))) 363 .WillOnce(Return(any(PropertyType(true)))); // present 364 365 // The item updater itself 366 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath))) 367 .Times(1); 368 369 // activation and version object will be added 370 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath0))) 371 .Times(2); 372 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath); 373 374 // Verify there is only one activation and it has two associations 375 const auto& activations = GetActivations(); 376 EXPECT_EQ(1u, activations.size()); 377 const auto& activation = activations.find(version0)->second; 378 auto assocs = activation->associations(); 379 EXPECT_EQ(2u, assocs.size()); 380 EXPECT_EQ(psu0, std::get<2>(assocs[0])); 381 EXPECT_EQ(psu1, std::get<2>(assocs[1])); 382 383 // PSU0 is removed, only associations shall be updated 384 Properties propRemoved{{PRESENT, PropertyType(false)}}; 385 onPsuInventoryChanged(psu0, propRemoved); 386 assocs = activation->associations(); 387 EXPECT_EQ(1u, assocs.size()); 388 EXPECT_EQ(psu1, std::get<2>(assocs[0])); 389 390 // PSU1 is removed, the activation and version object shall be removed 391 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath0))) 392 .Times(2); 393 onPsuInventoryChanged(psu1, propRemoved); 394 395 // Add PSU0 and PSU1 back, but PSU1 with a different version 396 version1 = "version1"; 397 objPath1 = getObjPath(version1); 398 Properties propAdded0{{PRESENT, PropertyType(true)}}; 399 Properties propAdded1{{PRESENT, PropertyType(true)}}; 400 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0))) 401 .WillOnce(Return(std::string(version0))); 402 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1))) 403 .WillOnce(Return(std::string(version1))); 404 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath0))) 405 .Times(2); 406 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath1))) 407 .Times(2); 408 onPsuInventoryChanged(psu0, propAdded0); 409 onPsuInventoryChanged(psu1, propAdded1); 410 411 // on exit, objects are removed 412 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath0))) 413 .Times(2); 414 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath1))) 415 .Times(2); 416 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(dBusPath))) 417 .Times(1); 418 } 419 420 TEST_F(TestItemUpdater, scanDirOnNoPSU) 421 { 422 constexpr auto psuPath = "/com/example/inventory/psu0"; 423 constexpr auto service = "com.example.Software.Psu"; 424 constexpr auto version = "version0"; 425 std::string objPath = getObjPath(version); 426 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_)) 427 .WillOnce(Return(std::vector<std::string>({psuPath}))); 428 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _)) 429 .WillOnce(Return(service)); 430 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath))) 431 .WillOnce(Return(std::string(version))); 432 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath), 433 _, StrEq(PRESENT))) 434 .WillOnce(Return(any(PropertyType(false)))); // not present 435 436 // The item updater itself 437 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath))) 438 .Times(1); 439 440 // No activation/version objects are created 441 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) 442 .Times(0); 443 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath); 444 445 // The valid image in test/psu-images-one-valid-one-invalid/model-1/ 446 auto objPathValid = getObjPath("psu-test.v0.4"); 447 auto objPathInvalid = getObjPath("psu-test.v0.5"); 448 // activation and version object will be added on scan dir 449 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPathValid))) 450 .Times(2); 451 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPathInvalid))) 452 .Times(0); 453 scanDirectory("./psu-images-one-valid-one-invalid"); 454 } 455 456 TEST_F(TestItemUpdater, scanDirOnSamePSUVersion) 457 { 458 constexpr auto psuPath = "/com/example/inventory/psu0"; 459 constexpr auto service = "com.example.Software.Psu"; 460 constexpr auto version = "version0"; 461 std::string objPath = getObjPath(version); 462 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_)) 463 .WillOnce(Return(std::vector<std::string>({psuPath}))); 464 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _)) 465 .WillOnce(Return(service)); 466 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath))) 467 .WillOnce(Return(std::string(version))); 468 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath), 469 _, StrEq(PRESENT))) 470 .WillOnce(Return(any(PropertyType(true)))); // present 471 472 // The item updater itself 473 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath))) 474 .Times(1); 475 476 // activation and version object will be added 477 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) 478 .Times(2); 479 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath); 480 481 // The valid image in test/psu-images-valid-version0/model-3/ has the same 482 // version as the running PSU, so no objects will be created, but only the 483 // path will be set to the version object 484 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) 485 .Times(0); 486 EXPECT_CALL(sdbusMock, sd_bus_emit_properties_changed_strv( 487 _, StrEq(objPath), 488 StrEq("xyz.openbmc_project.Common.FilePath"), 489 Pointee(StrEq("Path")))) 490 .Times(1); 491 scanDirectory("./psu-images-valid-version0"); 492 } 493