1 /** 2 * Copyright © 2020 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include "action.hpp" 17 #include "chassis.hpp" 18 #include "configuration.hpp" 19 #include "device.hpp" 20 #include "i2c_interface.hpp" 21 #include "id_map.hpp" 22 #include "log_phase_fault_action.hpp" 23 #include "mock_action.hpp" 24 #include "mock_error_logging.hpp" 25 #include "mock_journal.hpp" 26 #include "mock_sensors.hpp" 27 #include "mock_services.hpp" 28 #include "mocked_i2c_interface.hpp" 29 #include "phase_fault.hpp" 30 #include "phase_fault_detection.hpp" 31 #include "presence_detection.hpp" 32 #include "rail.hpp" 33 #include "rule.hpp" 34 #include "sensor_monitoring.hpp" 35 #include "sensors.hpp" 36 #include "system.hpp" 37 #include "test_sdbus_error.hpp" 38 #include "test_utils.hpp" 39 40 #include <memory> 41 #include <stdexcept> 42 #include <string> 43 #include <utility> 44 #include <vector> 45 46 #include <gmock/gmock.h> 47 #include <gtest/gtest.h> 48 49 using namespace phosphor::power::regulators; 50 using namespace phosphor::power::regulators::test_utils; 51 52 using ::testing::A; 53 using ::testing::Return; 54 using ::testing::Throw; 55 using ::testing::TypedEq; 56 57 class ChassisTests : public ::testing::Test 58 { 59 public: 60 /** 61 * Constructor. 62 * 63 * Creates the System object needed for calling some Chassis methods. 64 */ 65 ChassisTests() : ::testing::Test{} 66 { 67 std::vector<std::unique_ptr<Rule>> rules{}; 68 std::vector<std::unique_ptr<Chassis>> chassis{}; 69 system = std::make_unique<System>(std::move(rules), std::move(chassis)); 70 } 71 72 protected: 73 const std::string defaultInventoryPath{ 74 "/xyz/openbmc_project/inventory/system/chassis"}; 75 76 std::unique_ptr<System> system{}; 77 }; 78 79 TEST_F(ChassisTests, Constructor) 80 { 81 // Test where works: Only required parameters are specified 82 { 83 Chassis chassis{2, defaultInventoryPath}; 84 EXPECT_EQ(chassis.getNumber(), 2); 85 EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath); 86 EXPECT_EQ(chassis.getDevices().size(), 0); 87 } 88 89 // Test where works: All parameters are specified 90 { 91 // Create vector of Device objects 92 std::vector<std::unique_ptr<Device>> devices{}; 93 devices.emplace_back(createDevice("vdd_reg1")); 94 devices.emplace_back(createDevice("vdd_reg2")); 95 96 // Create Chassis 97 Chassis chassis{1, defaultInventoryPath, std::move(devices)}; 98 EXPECT_EQ(chassis.getNumber(), 1); 99 EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath); 100 EXPECT_EQ(chassis.getDevices().size(), 2); 101 } 102 103 // Test where fails: Invalid chassis number < 1 104 try 105 { 106 Chassis chassis{0, defaultInventoryPath}; 107 ADD_FAILURE() << "Should not have reached this line."; 108 } 109 catch (const std::invalid_argument& e) 110 { 111 EXPECT_STREQ(e.what(), "Invalid chassis number: 0"); 112 } 113 catch (...) 114 { 115 ADD_FAILURE() << "Should not have caught exception."; 116 } 117 } 118 119 TEST_F(ChassisTests, AddToIDMap) 120 { 121 // Create vector of Device objects 122 std::vector<std::unique_ptr<Device>> devices{}; 123 devices.emplace_back(createDevice("reg1", {"rail1"})); 124 devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"})); 125 devices.emplace_back(createDevice("reg3")); 126 127 // Create Chassis 128 Chassis chassis{1, defaultInventoryPath, std::move(devices)}; 129 130 // Add Device and Rail objects within the Chassis to an IDMap 131 IDMap idMap{}; 132 chassis.addToIDMap(idMap); 133 134 // Verify all Devices are in the IDMap 135 EXPECT_NO_THROW(idMap.getDevice("reg1")); 136 EXPECT_NO_THROW(idMap.getDevice("reg2")); 137 EXPECT_NO_THROW(idMap.getDevice("reg3")); 138 EXPECT_THROW(idMap.getDevice("reg4"), std::invalid_argument); 139 140 // Verify all Rails are in the IDMap 141 EXPECT_NO_THROW(idMap.getRail("rail1")); 142 EXPECT_NO_THROW(idMap.getRail("rail2a")); 143 EXPECT_NO_THROW(idMap.getRail("rail2b")); 144 EXPECT_THROW(idMap.getRail("rail3"), std::invalid_argument); 145 } 146 147 TEST_F(ChassisTests, ClearCache) 148 { 149 // Create PresenceDetection 150 std::vector<std::unique_ptr<Action>> actions{}; 151 auto presenceDetection = 152 std::make_unique<PresenceDetection>(std::move(actions)); 153 PresenceDetection* presenceDetectionPtr = presenceDetection.get(); 154 155 // Create Device that contains PresenceDetection 156 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 157 auto device = std::make_unique<Device>( 158 "reg1", true, 159 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 160 std::move(i2cInterface), std::move(presenceDetection)); 161 Device* devicePtr = device.get(); 162 163 // Create Chassis that contains Device 164 std::vector<std::unique_ptr<Device>> devices{}; 165 devices.emplace_back(std::move(device)); 166 Chassis chassis{1, defaultInventoryPath, std::move(devices)}; 167 168 // Cache presence value in PresenceDetection 169 MockServices services{}; 170 presenceDetectionPtr->execute(services, *system, chassis, *devicePtr); 171 EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value()); 172 173 // Clear cached data in Chassis 174 chassis.clearCache(); 175 176 // Verify presence value no longer cached in PresenceDetection 177 EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value()); 178 } 179 180 TEST_F(ChassisTests, ClearErrorHistory) 181 { 182 // Create SensorMonitoring. Will fail with a DBus exception. 183 auto action = std::make_unique<MockAction>(); 184 EXPECT_CALL(*action, execute) 185 .WillRepeatedly(Throw(TestSDBusError{"Unable to set sensor value"})); 186 std::vector<std::unique_ptr<Action>> actions{}; 187 actions.emplace_back(std::move(action)); 188 auto sensorMonitoring = 189 std::make_unique<SensorMonitoring>(std::move(actions)); 190 191 // Create Rail 192 std::unique_ptr<Configuration> configuration{}; 193 auto rail = std::make_unique<Rail>("vddr1", std::move(configuration), 194 std::move(sensorMonitoring)); 195 196 // Create Device that contains Rail 197 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 198 std::unique_ptr<PresenceDetection> presenceDetection{}; 199 std::unique_ptr<Configuration> deviceConfiguration{}; 200 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{}; 201 std::vector<std::unique_ptr<Rail>> rails{}; 202 rails.emplace_back(std::move(rail)); 203 auto device = std::make_unique<Device>( 204 "reg1", true, 205 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 206 std::move(i2cInterface), std::move(presenceDetection), 207 std::move(deviceConfiguration), std::move(phaseFaultDetection), 208 std::move(rails)); 209 210 // Create Chassis that contains Device 211 std::vector<std::unique_ptr<Device>> devices{}; 212 devices.emplace_back(std::move(device)); 213 Chassis chassis{1, defaultInventoryPath, std::move(devices)}; 214 215 // Create lambda that sets MockServices expectations. The lambda allows 216 // us to set expectations multiple times without duplicate code. 217 auto setExpectations = [](MockServices& services) { 218 // Expect Sensors service to be called 10 times 219 MockSensors& sensors = services.getMockSensors(); 220 EXPECT_CALL(sensors, startRail).Times(10); 221 EXPECT_CALL(sensors, setValue).Times(0); 222 EXPECT_CALL(sensors, endRail).Times(10); 223 224 // Expect Journal service to be called 6 times to log error messages 225 MockJournal& journal = services.getMockJournal(); 226 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>())) 227 .Times(6); 228 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(6); 229 230 // Expect ErrorLogging service to be called once to log a DBus error 231 MockErrorLogging& errorLogging = services.getMockErrorLogging(); 232 EXPECT_CALL(errorLogging, logDBusError).Times(1); 233 }; 234 235 // Monitor sensors 10 times. Verify errors logged. 236 { 237 // Create mock services. Set expectations via lambda. 238 MockServices services{}; 239 setExpectations(services); 240 241 for (int i = 1; i <= 10; ++i) 242 { 243 chassis.monitorSensors(services, *system); 244 } 245 } 246 247 // Clear error history 248 chassis.clearErrorHistory(); 249 250 // Monitor sensors 10 more times. Verify errors logged again. 251 { 252 // Create mock services. Set expectations via lambda. 253 MockServices services{}; 254 setExpectations(services); 255 256 for (int i = 1; i <= 10; ++i) 257 { 258 chassis.monitorSensors(services, *system); 259 } 260 } 261 } 262 263 TEST_F(ChassisTests, CloseDevices) 264 { 265 // Test where no devices were specified in constructor 266 { 267 // Create mock services. Expect logDebug() to be called. 268 MockServices services{}; 269 MockJournal& journal = services.getMockJournal(); 270 EXPECT_CALL(journal, logDebug("Closing devices in chassis 2")).Times(1); 271 272 // Create Chassis 273 Chassis chassis{2, defaultInventoryPath}; 274 275 // Call closeDevices() 276 chassis.closeDevices(services); 277 } 278 279 // Test where devices were specified in constructor 280 { 281 std::vector<std::unique_ptr<Device>> devices{}; 282 283 // Create mock services. Expect logDebug() to be called. 284 MockServices services{}; 285 MockJournal& journal = services.getMockJournal(); 286 EXPECT_CALL(journal, logDebug("Closing devices in chassis 1")).Times(1); 287 288 // Create Device vdd0_reg 289 { 290 // Create mock I2CInterface: isOpen() and close() should be called 291 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 292 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 293 EXPECT_CALL(*i2cInterface, close).Times(1); 294 295 // Create Device 296 auto device = 297 std::make_unique<Device>("vdd0_reg", true, 298 "/xyz/openbmc_project/inventory/" 299 "system/chassis/motherboard/vdd0_reg", 300 std::move(i2cInterface)); 301 devices.emplace_back(std::move(device)); 302 } 303 304 // Create Device vdd1_reg 305 { 306 // Create mock I2CInterface: isOpen() and close() should be called 307 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 308 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 309 EXPECT_CALL(*i2cInterface, close).Times(1); 310 311 // Create Device 312 auto device = 313 std::make_unique<Device>("vdd1_reg", true, 314 "/xyz/openbmc_project/inventory/" 315 "system/chassis/motherboard/vdd1_reg", 316 std::move(i2cInterface)); 317 devices.emplace_back(std::move(device)); 318 } 319 320 // Create Chassis 321 Chassis chassis{1, defaultInventoryPath, std::move(devices)}; 322 323 // Call closeDevices() 324 chassis.closeDevices(services); 325 } 326 } 327 328 TEST_F(ChassisTests, Configure) 329 { 330 // Test where no devices were specified in constructor 331 { 332 // Create mock services. Expect logInfo() to be called. 333 MockServices services{}; 334 MockJournal& journal = services.getMockJournal(); 335 EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1); 336 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 337 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 338 339 // Create Chassis 340 Chassis chassis{1, defaultInventoryPath}; 341 342 // Call configure() 343 chassis.configure(services, *system); 344 } 345 346 // Test where devices were specified in constructor 347 { 348 std::vector<std::unique_ptr<Device>> devices{}; 349 350 // Create mock services. Expect logInfo() and logDebug() to be called. 351 MockServices services{}; 352 MockJournal& journal = services.getMockJournal(); 353 EXPECT_CALL(journal, logInfo("Configuring chassis 2")).Times(1); 354 EXPECT_CALL(journal, logDebug("Configuring vdd0_reg: volts=1.300000")) 355 .Times(1); 356 EXPECT_CALL(journal, logDebug("Configuring vdd1_reg: volts=1.200000")) 357 .Times(1); 358 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 359 360 // Create Device vdd0_reg 361 { 362 // Create Configuration 363 std::vector<std::unique_ptr<Action>> actions{}; 364 auto configuration = 365 std::make_unique<Configuration>(1.3, std::move(actions)); 366 367 // Create Device 368 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 369 std::unique_ptr<PresenceDetection> presenceDetection{}; 370 auto device = std::make_unique<Device>( 371 "vdd0_reg", true, 372 "/xyz/openbmc_project/inventory/system/chassis/motherboard/" 373 "vdd0_reg", 374 std::move(i2cInterface), std::move(presenceDetection), 375 std::move(configuration)); 376 devices.emplace_back(std::move(device)); 377 } 378 379 // Create Device vdd1_reg 380 { 381 // Create Configuration 382 std::vector<std::unique_ptr<Action>> actions{}; 383 auto configuration = 384 std::make_unique<Configuration>(1.2, std::move(actions)); 385 386 // Create Device 387 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 388 std::unique_ptr<PresenceDetection> presenceDetection{}; 389 auto device = std::make_unique<Device>( 390 "vdd1_reg", true, 391 "/xyz/openbmc_project/inventory/system/chassis/motherboard/" 392 "vdd1_reg", 393 std::move(i2cInterface), std::move(presenceDetection), 394 std::move(configuration)); 395 devices.emplace_back(std::move(device)); 396 } 397 398 // Create Chassis 399 Chassis chassis{2, defaultInventoryPath, std::move(devices)}; 400 401 // Call configure() 402 chassis.configure(services, *system); 403 } 404 } 405 406 TEST_F(ChassisTests, DetectPhaseFaults) 407 { 408 // Test where no devices were specified in constructor 409 { 410 // Create mock services. No errors should be logged. 411 MockServices services{}; 412 MockJournal& journal = services.getMockJournal(); 413 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 414 MockErrorLogging& errorLogging = services.getMockErrorLogging(); 415 EXPECT_CALL(errorLogging, logPhaseFault).Times(0); 416 417 // Create Chassis 418 Chassis chassis{1, defaultInventoryPath}; 419 420 // Call detectPhaseFaults() 5 times. Should do nothing. 421 for (int i = 1; i <= 5; ++i) 422 { 423 chassis.detectPhaseFaults(services, *system); 424 } 425 } 426 427 // Test where devices were specified in constructor 428 { 429 // Create mock services with the following expectations: 430 // - 2 error messages in journal for N phase fault detected in reg0 431 // - 2 error messages in journal for N phase fault detected in reg1 432 // - 1 N phase fault error logged for reg0 433 // - 1 N phase fault error logged for reg1 434 MockServices services{}; 435 MockJournal& journal = services.getMockJournal(); 436 EXPECT_CALL( 437 journal, 438 logError("n phase fault detected in regulator reg0: count=1")) 439 .Times(1); 440 EXPECT_CALL( 441 journal, 442 logError("n phase fault detected in regulator reg0: count=2")) 443 .Times(1); 444 EXPECT_CALL( 445 journal, 446 logError("n phase fault detected in regulator reg1: count=1")) 447 .Times(1); 448 EXPECT_CALL( 449 journal, 450 logError("n phase fault detected in regulator reg1: count=2")) 451 .Times(1); 452 MockErrorLogging& errorLogging = services.getMockErrorLogging(); 453 EXPECT_CALL(errorLogging, logPhaseFault).Times(2); 454 455 std::vector<std::unique_ptr<Device>> devices{}; 456 457 // Create Device reg0 458 { 459 // Create PhaseFaultDetection 460 auto action = 461 std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n); 462 std::vector<std::unique_ptr<Action>> actions{}; 463 actions.push_back(std::move(action)); 464 auto phaseFaultDetection = 465 std::make_unique<PhaseFaultDetection>(std::move(actions)); 466 467 // Create Device 468 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 469 std::unique_ptr<PresenceDetection> presenceDetection{}; 470 std::unique_ptr<Configuration> configuration{}; 471 auto device = std::make_unique<Device>( 472 "reg0", true, 473 "/xyz/openbmc_project/inventory/system/chassis/motherboard/" 474 "reg0", 475 std::move(i2cInterface), std::move(presenceDetection), 476 std::move(configuration), std::move(phaseFaultDetection)); 477 devices.emplace_back(std::move(device)); 478 } 479 480 // Create Device reg1 481 { 482 // Create PhaseFaultDetection 483 auto action = 484 std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n); 485 std::vector<std::unique_ptr<Action>> actions{}; 486 actions.push_back(std::move(action)); 487 auto phaseFaultDetection = 488 std::make_unique<PhaseFaultDetection>(std::move(actions)); 489 490 // Create Device 491 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 492 std::unique_ptr<PresenceDetection> presenceDetection{}; 493 std::unique_ptr<Configuration> configuration{}; 494 auto device = std::make_unique<Device>( 495 "reg1", true, 496 "/xyz/openbmc_project/inventory/system/chassis/motherboard/" 497 "reg1", 498 std::move(i2cInterface), std::move(presenceDetection), 499 std::move(configuration), std::move(phaseFaultDetection)); 500 devices.emplace_back(std::move(device)); 501 } 502 503 // Create Chassis 504 Chassis chassis{2, defaultInventoryPath, std::move(devices)}; 505 506 // Call detectPhaseFaults() 5 times 507 for (int i = 1; i <= 5; ++i) 508 { 509 chassis.detectPhaseFaults(services, *system); 510 } 511 } 512 } 513 514 TEST_F(ChassisTests, GetDevices) 515 { 516 // Test where no devices were specified in constructor 517 { 518 Chassis chassis{2, defaultInventoryPath}; 519 EXPECT_EQ(chassis.getDevices().size(), 0); 520 } 521 522 // Test where devices were specified in constructor 523 { 524 // Create vector of Device objects 525 std::vector<std::unique_ptr<Device>> devices{}; 526 devices.emplace_back(createDevice("vdd_reg1")); 527 devices.emplace_back(createDevice("vdd_reg2")); 528 529 // Create Chassis 530 Chassis chassis{1, defaultInventoryPath, std::move(devices)}; 531 EXPECT_EQ(chassis.getDevices().size(), 2); 532 EXPECT_EQ(chassis.getDevices()[0]->getID(), "vdd_reg1"); 533 EXPECT_EQ(chassis.getDevices()[1]->getID(), "vdd_reg2"); 534 } 535 } 536 537 TEST_F(ChassisTests, GetInventoryPath) 538 { 539 Chassis chassis{3, defaultInventoryPath}; 540 EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath); 541 } 542 543 TEST_F(ChassisTests, GetNumber) 544 { 545 Chassis chassis{3, defaultInventoryPath}; 546 EXPECT_EQ(chassis.getNumber(), 3); 547 } 548 549 TEST_F(ChassisTests, MonitorSensors) 550 { 551 // Test where no devices were specified in constructor 552 { 553 // Create mock services. No Sensors methods should be called. 554 MockServices services{}; 555 MockSensors& sensors = services.getMockSensors(); 556 EXPECT_CALL(sensors, startRail).Times(0); 557 EXPECT_CALL(sensors, setValue).Times(0); 558 EXPECT_CALL(sensors, endRail).Times(0); 559 560 // Create Chassis 561 Chassis chassis{1, defaultInventoryPath}; 562 563 // Call monitorSensors(). Should do nothing. 564 chassis.monitorSensors(services, *system); 565 } 566 567 // Test where devices were specified in constructor 568 { 569 // Create mock services. Set Sensors service expectations. 570 MockServices services{}; 571 MockSensors& sensors = services.getMockSensors(); 572 EXPECT_CALL(sensors, startRail("vdd0", 573 "/xyz/openbmc_project/inventory/system/" 574 "chassis/motherboard/vdd0_reg", 575 defaultInventoryPath)) 576 .Times(1); 577 EXPECT_CALL(sensors, startRail("vdd1", 578 "/xyz/openbmc_project/inventory/system/" 579 "chassis/motherboard/vdd1_reg", 580 defaultInventoryPath)) 581 .Times(1); 582 EXPECT_CALL(sensors, setValue).Times(0); 583 EXPECT_CALL(sensors, endRail(false)).Times(2); 584 585 std::vector<std::unique_ptr<Device>> devices{}; 586 587 // Create Device vdd0_reg 588 { 589 // Create SensorMonitoring for Rail 590 auto action = std::make_unique<MockAction>(); 591 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 592 std::vector<std::unique_ptr<Action>> actions{}; 593 actions.emplace_back(std::move(action)); 594 auto sensorMonitoring = 595 std::make_unique<SensorMonitoring>(std::move(actions)); 596 597 // Create Rail 598 std::unique_ptr<Configuration> configuration{}; 599 auto rail = std::make_unique<Rail>("vdd0", std::move(configuration), 600 std::move(sensorMonitoring)); 601 602 // Create Device 603 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 604 std::unique_ptr<PresenceDetection> presenceDetection{}; 605 std::unique_ptr<Configuration> deviceConfiguration{}; 606 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{}; 607 std::vector<std::unique_ptr<Rail>> rails{}; 608 rails.emplace_back(std::move(rail)); 609 auto device = std::make_unique<Device>( 610 "vdd0_reg", true, 611 "/xyz/openbmc_project/inventory/system/chassis/motherboard/" 612 "vdd0_reg", 613 std::move(i2cInterface), std::move(presenceDetection), 614 std::move(deviceConfiguration), std::move(phaseFaultDetection), 615 std::move(rails)); 616 devices.emplace_back(std::move(device)); 617 } 618 619 // Create Device vdd1_reg 620 { 621 // Create SensorMonitoring for Rail 622 auto action = std::make_unique<MockAction>(); 623 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 624 std::vector<std::unique_ptr<Action>> actions{}; 625 actions.emplace_back(std::move(action)); 626 auto sensorMonitoring = 627 std::make_unique<SensorMonitoring>(std::move(actions)); 628 629 // Create Rail 630 std::unique_ptr<Configuration> configuration{}; 631 auto rail = std::make_unique<Rail>("vdd1", std::move(configuration), 632 std::move(sensorMonitoring)); 633 634 // Create Device 635 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 636 std::unique_ptr<PresenceDetection> presenceDetection{}; 637 std::unique_ptr<Configuration> deviceConfiguration{}; 638 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{}; 639 std::vector<std::unique_ptr<Rail>> rails{}; 640 rails.emplace_back(std::move(rail)); 641 auto device = std::make_unique<Device>( 642 "vdd1_reg", true, 643 "/xyz/openbmc_project/inventory/system/chassis/motherboard/" 644 "vdd1_reg", 645 std::move(i2cInterface), std::move(presenceDetection), 646 std::move(deviceConfiguration), std::move(phaseFaultDetection), 647 std::move(rails)); 648 devices.emplace_back(std::move(device)); 649 } 650 651 // Create Chassis that contains Devices 652 Chassis chassis{2, defaultInventoryPath, std::move(devices)}; 653 654 // Call monitorSensors() 655 chassis.monitorSensors(services, *system); 656 } 657 } 658