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 mock services 216 MockServices services{}; 217 218 // Expect Sensors service to be called 5+5=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 3+3=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 1+1=2 times to log a DBus error 231 MockErrorLogging& errorLogging = services.getMockErrorLogging(); 232 EXPECT_CALL(errorLogging, logDBusError).Times(2); 233 234 // Monitor sensors 5 times. Should fail every time, write to journal 3 235 // times, and log one error. 236 for (int i = 1; i <= 5; ++i) 237 { 238 chassis.monitorSensors(services, *system); 239 } 240 241 // Clear error history 242 chassis.clearErrorHistory(); 243 244 // Monitor sensors 5 times again. Should fail every time, write to journal 245 // 3 times, and log one error. 246 for (int i = 1; i <= 5; ++i) 247 { 248 chassis.monitorSensors(services, *system); 249 } 250 } 251 252 TEST_F(ChassisTests, CloseDevices) 253 { 254 // Test where no devices were specified in constructor 255 { 256 // Create mock services. Expect logDebug() to be called. 257 MockServices services{}; 258 MockJournal& journal = services.getMockJournal(); 259 EXPECT_CALL(journal, logDebug("Closing devices in chassis 2")).Times(1); 260 261 // Create Chassis 262 Chassis chassis{2, defaultInventoryPath}; 263 264 // Call closeDevices() 265 chassis.closeDevices(services); 266 } 267 268 // Test where devices were specified in constructor 269 { 270 std::vector<std::unique_ptr<Device>> devices{}; 271 272 // Create mock services. Expect logDebug() to be called. 273 MockServices services{}; 274 MockJournal& journal = services.getMockJournal(); 275 EXPECT_CALL(journal, logDebug("Closing devices in chassis 1")).Times(1); 276 277 // Create Device vdd0_reg 278 { 279 // Create mock I2CInterface: isOpen() and close() should be called 280 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 281 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 282 EXPECT_CALL(*i2cInterface, close).Times(1); 283 284 // Create Device 285 auto device = 286 std::make_unique<Device>("vdd0_reg", true, 287 "/xyz/openbmc_project/inventory/" 288 "system/chassis/motherboard/vdd0_reg", 289 std::move(i2cInterface)); 290 devices.emplace_back(std::move(device)); 291 } 292 293 // Create Device vdd1_reg 294 { 295 // Create mock I2CInterface: isOpen() and close() should be called 296 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 297 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 298 EXPECT_CALL(*i2cInterface, close).Times(1); 299 300 // Create Device 301 auto device = 302 std::make_unique<Device>("vdd1_reg", true, 303 "/xyz/openbmc_project/inventory/" 304 "system/chassis/motherboard/vdd1_reg", 305 std::move(i2cInterface)); 306 devices.emplace_back(std::move(device)); 307 } 308 309 // Create Chassis 310 Chassis chassis{1, defaultInventoryPath, std::move(devices)}; 311 312 // Call closeDevices() 313 chassis.closeDevices(services); 314 } 315 } 316 317 TEST_F(ChassisTests, Configure) 318 { 319 // Test where no devices were specified in constructor 320 { 321 // Create mock services. Expect logInfo() to be called. 322 MockServices services{}; 323 MockJournal& journal = services.getMockJournal(); 324 EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1); 325 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 326 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 327 328 // Create Chassis 329 Chassis chassis{1, defaultInventoryPath}; 330 331 // Call configure() 332 chassis.configure(services, *system); 333 } 334 335 // Test where devices were specified in constructor 336 { 337 std::vector<std::unique_ptr<Device>> devices{}; 338 339 // Create mock services. Expect logInfo() and logDebug() to be called. 340 MockServices services{}; 341 MockJournal& journal = services.getMockJournal(); 342 EXPECT_CALL(journal, logInfo("Configuring chassis 2")).Times(1); 343 EXPECT_CALL(journal, logDebug("Configuring vdd0_reg: volts=1.300000")) 344 .Times(1); 345 EXPECT_CALL(journal, logDebug("Configuring vdd1_reg: volts=1.200000")) 346 .Times(1); 347 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 348 349 // Create Device vdd0_reg 350 { 351 // Create Configuration 352 std::vector<std::unique_ptr<Action>> actions{}; 353 auto configuration = 354 std::make_unique<Configuration>(1.3, std::move(actions)); 355 356 // Create Device 357 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 358 std::unique_ptr<PresenceDetection> presenceDetection{}; 359 auto device = std::make_unique<Device>( 360 "vdd0_reg", true, 361 "/xyz/openbmc_project/inventory/system/chassis/motherboard/" 362 "vdd0_reg", 363 std::move(i2cInterface), std::move(presenceDetection), 364 std::move(configuration)); 365 devices.emplace_back(std::move(device)); 366 } 367 368 // Create Device vdd1_reg 369 { 370 // Create Configuration 371 std::vector<std::unique_ptr<Action>> actions{}; 372 auto configuration = 373 std::make_unique<Configuration>(1.2, std::move(actions)); 374 375 // Create Device 376 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 377 std::unique_ptr<PresenceDetection> presenceDetection{}; 378 auto device = std::make_unique<Device>( 379 "vdd1_reg", true, 380 "/xyz/openbmc_project/inventory/system/chassis/motherboard/" 381 "vdd1_reg", 382 std::move(i2cInterface), std::move(presenceDetection), 383 std::move(configuration)); 384 devices.emplace_back(std::move(device)); 385 } 386 387 // Create Chassis 388 Chassis chassis{2, defaultInventoryPath, std::move(devices)}; 389 390 // Call configure() 391 chassis.configure(services, *system); 392 } 393 } 394 395 TEST_F(ChassisTests, DetectPhaseFaults) 396 { 397 // Test where no devices were specified in constructor 398 { 399 // Create mock services. No errors should be logged. 400 MockServices services{}; 401 MockJournal& journal = services.getMockJournal(); 402 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 403 MockErrorLogging& errorLogging = services.getMockErrorLogging(); 404 EXPECT_CALL(errorLogging, logPhaseFault).Times(0); 405 406 // Create Chassis 407 Chassis chassis{1, defaultInventoryPath}; 408 409 // Call detectPhaseFaults() 5 times. Should do nothing. 410 for (int i = 1; i <= 5; ++i) 411 { 412 chassis.detectPhaseFaults(services, *system); 413 } 414 } 415 416 // Test where devices were specified in constructor 417 { 418 // Create mock services with the following expectations: 419 // - 2 error messages in journal for N phase fault detected in reg0 420 // - 2 error messages in journal for N phase fault detected in reg1 421 // - 1 N phase fault error logged for reg0 422 // - 1 N phase fault error logged for reg1 423 MockServices services{}; 424 MockJournal& journal = services.getMockJournal(); 425 EXPECT_CALL( 426 journal, 427 logError("n phase fault detected in regulator reg0: count=1")) 428 .Times(1); 429 EXPECT_CALL( 430 journal, 431 logError("n phase fault detected in regulator reg0: count=2")) 432 .Times(1); 433 EXPECT_CALL( 434 journal, 435 logError("n phase fault detected in regulator reg1: count=1")) 436 .Times(1); 437 EXPECT_CALL( 438 journal, 439 logError("n phase fault detected in regulator reg1: count=2")) 440 .Times(1); 441 MockErrorLogging& errorLogging = services.getMockErrorLogging(); 442 EXPECT_CALL(errorLogging, logPhaseFault).Times(2); 443 444 std::vector<std::unique_ptr<Device>> devices{}; 445 446 // Create Device reg0 447 { 448 // Create PhaseFaultDetection 449 auto action = 450 std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n); 451 std::vector<std::unique_ptr<Action>> actions{}; 452 actions.push_back(std::move(action)); 453 auto phaseFaultDetection = 454 std::make_unique<PhaseFaultDetection>(std::move(actions)); 455 456 // Create Device 457 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 458 std::unique_ptr<PresenceDetection> presenceDetection{}; 459 std::unique_ptr<Configuration> configuration{}; 460 auto device = std::make_unique<Device>( 461 "reg0", true, 462 "/xyz/openbmc_project/inventory/system/chassis/motherboard/" 463 "reg0", 464 std::move(i2cInterface), std::move(presenceDetection), 465 std::move(configuration), std::move(phaseFaultDetection)); 466 devices.emplace_back(std::move(device)); 467 } 468 469 // Create Device reg1 470 { 471 // Create PhaseFaultDetection 472 auto action = 473 std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n); 474 std::vector<std::unique_ptr<Action>> actions{}; 475 actions.push_back(std::move(action)); 476 auto phaseFaultDetection = 477 std::make_unique<PhaseFaultDetection>(std::move(actions)); 478 479 // Create Device 480 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 481 std::unique_ptr<PresenceDetection> presenceDetection{}; 482 std::unique_ptr<Configuration> configuration{}; 483 auto device = std::make_unique<Device>( 484 "reg1", true, 485 "/xyz/openbmc_project/inventory/system/chassis/motherboard/" 486 "reg1", 487 std::move(i2cInterface), std::move(presenceDetection), 488 std::move(configuration), std::move(phaseFaultDetection)); 489 devices.emplace_back(std::move(device)); 490 } 491 492 // Create Chassis 493 Chassis chassis{2, defaultInventoryPath, std::move(devices)}; 494 495 // Call detectPhaseFaults() 5 times 496 for (int i = 1; i <= 5; ++i) 497 { 498 chassis.detectPhaseFaults(services, *system); 499 } 500 } 501 } 502 503 TEST_F(ChassisTests, GetDevices) 504 { 505 // Test where no devices were specified in constructor 506 { 507 Chassis chassis{2, defaultInventoryPath}; 508 EXPECT_EQ(chassis.getDevices().size(), 0); 509 } 510 511 // Test where devices were specified in constructor 512 { 513 // Create vector of Device objects 514 std::vector<std::unique_ptr<Device>> devices{}; 515 devices.emplace_back(createDevice("vdd_reg1")); 516 devices.emplace_back(createDevice("vdd_reg2")); 517 518 // Create Chassis 519 Chassis chassis{1, defaultInventoryPath, std::move(devices)}; 520 EXPECT_EQ(chassis.getDevices().size(), 2); 521 EXPECT_EQ(chassis.getDevices()[0]->getID(), "vdd_reg1"); 522 EXPECT_EQ(chassis.getDevices()[1]->getID(), "vdd_reg2"); 523 } 524 } 525 526 TEST_F(ChassisTests, GetInventoryPath) 527 { 528 Chassis chassis{3, defaultInventoryPath}; 529 EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath); 530 } 531 532 TEST_F(ChassisTests, GetNumber) 533 { 534 Chassis chassis{3, defaultInventoryPath}; 535 EXPECT_EQ(chassis.getNumber(), 3); 536 } 537 538 TEST_F(ChassisTests, MonitorSensors) 539 { 540 // Test where no devices were specified in constructor 541 { 542 // Create mock services. No Sensors methods should be called. 543 MockServices services{}; 544 MockSensors& sensors = services.getMockSensors(); 545 EXPECT_CALL(sensors, startRail).Times(0); 546 EXPECT_CALL(sensors, setValue).Times(0); 547 EXPECT_CALL(sensors, endRail).Times(0); 548 549 // Create Chassis 550 Chassis chassis{1, defaultInventoryPath}; 551 552 // Call monitorSensors(). Should do nothing. 553 chassis.monitorSensors(services, *system); 554 } 555 556 // Test where devices were specified in constructor 557 { 558 // Create mock services. Set Sensors service expectations. 559 MockServices services{}; 560 MockSensors& sensors = services.getMockSensors(); 561 EXPECT_CALL(sensors, startRail("vdd0", 562 "/xyz/openbmc_project/inventory/system/" 563 "chassis/motherboard/vdd0_reg", 564 defaultInventoryPath)) 565 .Times(1); 566 EXPECT_CALL(sensors, startRail("vdd1", 567 "/xyz/openbmc_project/inventory/system/" 568 "chassis/motherboard/vdd1_reg", 569 defaultInventoryPath)) 570 .Times(1); 571 EXPECT_CALL(sensors, setValue).Times(0); 572 EXPECT_CALL(sensors, endRail(false)).Times(2); 573 574 std::vector<std::unique_ptr<Device>> devices{}; 575 576 // Create Device vdd0_reg 577 { 578 // Create SensorMonitoring for Rail 579 auto action = std::make_unique<MockAction>(); 580 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 581 std::vector<std::unique_ptr<Action>> actions{}; 582 actions.emplace_back(std::move(action)); 583 auto sensorMonitoring = 584 std::make_unique<SensorMonitoring>(std::move(actions)); 585 586 // Create Rail 587 std::unique_ptr<Configuration> configuration{}; 588 auto rail = std::make_unique<Rail>("vdd0", std::move(configuration), 589 std::move(sensorMonitoring)); 590 591 // Create Device 592 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 593 std::unique_ptr<PresenceDetection> presenceDetection{}; 594 std::unique_ptr<Configuration> deviceConfiguration{}; 595 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{}; 596 std::vector<std::unique_ptr<Rail>> rails{}; 597 rails.emplace_back(std::move(rail)); 598 auto device = std::make_unique<Device>( 599 "vdd0_reg", true, 600 "/xyz/openbmc_project/inventory/system/chassis/motherboard/" 601 "vdd0_reg", 602 std::move(i2cInterface), std::move(presenceDetection), 603 std::move(deviceConfiguration), std::move(phaseFaultDetection), 604 std::move(rails)); 605 devices.emplace_back(std::move(device)); 606 } 607 608 // Create Device vdd1_reg 609 { 610 // Create SensorMonitoring for Rail 611 auto action = std::make_unique<MockAction>(); 612 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 613 std::vector<std::unique_ptr<Action>> actions{}; 614 actions.emplace_back(std::move(action)); 615 auto sensorMonitoring = 616 std::make_unique<SensorMonitoring>(std::move(actions)); 617 618 // Create Rail 619 std::unique_ptr<Configuration> configuration{}; 620 auto rail = std::make_unique<Rail>("vdd1", std::move(configuration), 621 std::move(sensorMonitoring)); 622 623 // Create Device 624 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 625 std::unique_ptr<PresenceDetection> presenceDetection{}; 626 std::unique_ptr<Configuration> deviceConfiguration{}; 627 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{}; 628 std::vector<std::unique_ptr<Rail>> rails{}; 629 rails.emplace_back(std::move(rail)); 630 auto device = std::make_unique<Device>( 631 "vdd1_reg", true, 632 "/xyz/openbmc_project/inventory/system/chassis/motherboard/" 633 "vdd1_reg", 634 std::move(i2cInterface), std::move(presenceDetection), 635 std::move(deviceConfiguration), std::move(phaseFaultDetection), 636 std::move(rails)); 637 devices.emplace_back(std::move(device)); 638 } 639 640 // Create Chassis that contains Devices 641 Chassis chassis{2, defaultInventoryPath, std::move(devices)}; 642 643 // Call monitorSensors() 644 chassis.monitorSensors(services, *system); 645 } 646 } 647