1 /** 2 * Copyright © 2019 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 <optional> 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::Ref; 54 using ::testing::Return; 55 using ::testing::Throw; 56 using ::testing::TypedEq; 57 58 class DeviceTests : public ::testing::Test 59 { 60 public: 61 /** 62 * Constructor. 63 * 64 * Creates the Chassis and System objects needed for calling some Device 65 * methods. 66 */ 67 DeviceTests() : ::testing::Test{} 68 { 69 // Create Chassis 70 auto chassis = std::make_unique<Chassis>(1, chassisInvPath); 71 this->chassis = chassis.get(); 72 73 // Create System 74 std::vector<std::unique_ptr<Rule>> rules{}; 75 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 76 chassisVec.emplace_back(std::move(chassis)); 77 this->system = 78 std::make_unique<System>(std::move(rules), std::move(chassisVec)); 79 } 80 81 protected: 82 const std::string deviceInvPath{ 83 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2"}; 84 const std::string chassisInvPath{ 85 "/xyz/openbmc_project/inventory/system/chassis"}; 86 87 // Note: This pointer does NOT need to be explicitly deleted. The Chassis 88 // object is owned by the System object and will be automatically deleted. 89 Chassis* chassis{nullptr}; 90 91 std::unique_ptr<System> system{}; 92 }; 93 94 TEST_F(DeviceTests, Constructor) 95 { 96 // Test where only required parameters are specified 97 { 98 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 99 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get(); 100 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)}; 101 EXPECT_EQ(device.getID(), "vdd_reg"); 102 EXPECT_EQ(device.isRegulator(), true); 103 EXPECT_EQ(device.getFRU(), deviceInvPath); 104 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr); 105 EXPECT_EQ(device.getPresenceDetection(), nullptr); 106 EXPECT_EQ(device.getConfiguration(), nullptr); 107 EXPECT_EQ(device.getPhaseFaultDetection(), nullptr); 108 EXPECT_EQ(device.getRails().size(), 0); 109 } 110 111 // Test where all parameters are specified 112 { 113 // Create I2CInterface 114 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 115 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get(); 116 117 // Create PresenceDetection 118 std::vector<std::unique_ptr<Action>> actions{}; 119 actions.push_back(std::make_unique<MockAction>()); 120 auto presenceDetection = 121 std::make_unique<PresenceDetection>(std::move(actions)); 122 123 // Create Configuration 124 std::optional<double> volts{}; 125 actions.clear(); 126 actions.push_back(std::make_unique<MockAction>()); 127 actions.push_back(std::make_unique<MockAction>()); 128 auto configuration = 129 std::make_unique<Configuration>(volts, std::move(actions)); 130 131 // Create PhaseFaultDetection 132 actions.clear(); 133 actions.push_back(std::make_unique<MockAction>()); 134 actions.push_back(std::make_unique<MockAction>()); 135 actions.push_back(std::make_unique<MockAction>()); 136 auto phaseFaultDetection = 137 std::make_unique<PhaseFaultDetection>(std::move(actions)); 138 139 // Create vector of Rail objects 140 std::vector<std::unique_ptr<Rail>> rails{}; 141 rails.push_back(std::make_unique<Rail>("vdd0")); 142 rails.push_back(std::make_unique<Rail>("vdd1")); 143 144 // Create Device 145 Device device{"vdd_reg", 146 false, 147 deviceInvPath, 148 std::move(i2cInterface), 149 std::move(presenceDetection), 150 std::move(configuration), 151 std::move(phaseFaultDetection), 152 std::move(rails)}; 153 EXPECT_EQ(device.getID(), "vdd_reg"); 154 EXPECT_EQ(device.isRegulator(), false); 155 EXPECT_EQ(device.getFRU(), deviceInvPath); 156 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr); 157 EXPECT_NE(device.getPresenceDetection(), nullptr); 158 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1); 159 EXPECT_NE(device.getConfiguration(), nullptr); 160 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), false); 161 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2); 162 EXPECT_NE(device.getPhaseFaultDetection(), nullptr); 163 EXPECT_EQ(device.getPhaseFaultDetection()->getActions().size(), 3); 164 EXPECT_EQ(device.getRails().size(), 2); 165 } 166 } 167 168 TEST_F(DeviceTests, AddToIDMap) 169 { 170 std::unique_ptr<PresenceDetection> presenceDetection{}; 171 std::unique_ptr<Configuration> configuration{}; 172 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{}; 173 174 // Create vector of Rail objects 175 std::vector<std::unique_ptr<Rail>> rails{}; 176 rails.push_back(std::make_unique<Rail>("vdd0")); 177 rails.push_back(std::make_unique<Rail>("vdd1")); 178 179 // Create Device 180 Device device{"vdd_reg", 181 false, 182 deviceInvPath, 183 std::move(createI2CInterface()), 184 std::move(presenceDetection), 185 std::move(configuration), 186 std::move(phaseFaultDetection), 187 std::move(rails)}; 188 189 // Add Device and Rail objects to an IDMap 190 IDMap idMap{}; 191 device.addToIDMap(idMap); 192 193 // Verify Device is in the IDMap 194 EXPECT_NO_THROW(idMap.getDevice("vdd_reg")); 195 EXPECT_THROW(idMap.getDevice("vio_reg"), std::invalid_argument); 196 197 // Verify all Rails are in the IDMap 198 EXPECT_NO_THROW(idMap.getRail("vdd0")); 199 EXPECT_NO_THROW(idMap.getRail("vdd1")); 200 EXPECT_THROW(idMap.getRail("vdd2"), std::invalid_argument); 201 } 202 203 TEST_F(DeviceTests, ClearCache) 204 { 205 // Test where Device does not contain a PresenceDetection object 206 try 207 { 208 Device device{"vdd_reg", false, deviceInvPath, 209 std::move(createI2CInterface())}; 210 device.clearCache(); 211 } 212 catch (...) 213 { 214 ADD_FAILURE() << "Should not have caught exception."; 215 } 216 217 // Test where Device contains a PresenceDetection object 218 { 219 // Create PresenceDetection 220 std::vector<std::unique_ptr<Action>> actions{}; 221 auto presenceDetection = 222 std::make_unique<PresenceDetection>(std::move(actions)); 223 PresenceDetection* presenceDetectionPtr = presenceDetection.get(); 224 225 // Create Device 226 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 227 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface), 228 std::move(presenceDetection)}; 229 230 // Cache presence value in PresenceDetection 231 MockServices services{}; 232 presenceDetectionPtr->execute(services, *system, *chassis, device); 233 EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value()); 234 235 // Clear cached data in Device 236 device.clearCache(); 237 238 // Verify presence value no longer cached in PresenceDetection 239 EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value()); 240 } 241 } 242 243 TEST_F(DeviceTests, ClearErrorHistory) 244 { 245 // Create SensorMonitoring. Will fail with a DBus exception. 246 std::unique_ptr<SensorMonitoring> sensorMonitoring{}; 247 { 248 auto action = std::make_unique<MockAction>(); 249 EXPECT_CALL(*action, execute) 250 .WillRepeatedly(Throw(TestSDBusError{"DBus Error"})); 251 std::vector<std::unique_ptr<Action>> actions{}; 252 actions.emplace_back(std::move(action)); 253 sensorMonitoring = 254 std::make_unique<SensorMonitoring>(std::move(actions)); 255 } 256 257 // Create Rail 258 std::unique_ptr<Configuration> configuration{}; 259 auto rail = std::make_unique<Rail>("vdd", std::move(configuration), 260 std::move(sensorMonitoring)); 261 262 // Create PhaseFaultDetection. Will log an N phase fault. 263 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{}; 264 { 265 auto action = std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n); 266 std::vector<std::unique_ptr<Action>> actions{}; 267 actions.emplace_back(std::move(action)); 268 phaseFaultDetection = 269 std::make_unique<PhaseFaultDetection>(std::move(actions)); 270 } 271 272 // Create Device 273 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 274 std::unique_ptr<PresenceDetection> presenceDetection{}; 275 std::unique_ptr<Configuration> deviceConfiguration{}; 276 std::vector<std::unique_ptr<Rail>> rails{}; 277 rails.emplace_back(std::move(rail)); 278 Device device{"reg2", 279 true, 280 deviceInvPath, 281 std::move(i2cInterface), 282 std::move(presenceDetection), 283 std::move(deviceConfiguration), 284 std::move(phaseFaultDetection), 285 std::move(rails)}; 286 287 // Create lambda that sets MockServices expectations. The lambda allows 288 // us to set expectations multiple times without duplicate code. 289 auto setExpectations = [](MockServices& services) { 290 // Set Journal service expectations: 291 // - 6 error messages for D-Bus errors 292 // - 6 error messages for inability to monitor sensors 293 // - 2 error messages for the N phase fault 294 MockJournal& journal = services.getMockJournal(); 295 EXPECT_CALL(journal, logError(std::vector<std::string>{"DBus Error"})) 296 .Times(6); 297 EXPECT_CALL(journal, logError("Unable to monitor sensors for rail vdd")) 298 .Times(6); 299 EXPECT_CALL( 300 journal, 301 logError("n phase fault detected in regulator reg2: count=1")) 302 .Times(1); 303 EXPECT_CALL( 304 journal, 305 logError("n phase fault detected in regulator reg2: count=2")) 306 .Times(1); 307 308 // Set ErrorLogging service expectations: 309 // - D-Bus error should be logged once for the D-Bus exceptions 310 // - N phase fault error should be logged once 311 MockErrorLogging& errorLogging = services.getMockErrorLogging(); 312 EXPECT_CALL(errorLogging, logDBusError).Times(1); 313 EXPECT_CALL(errorLogging, logPhaseFault).Times(1); 314 315 // Set Sensors service expections: 316 // - startRail() and endRail() called 10 times 317 MockSensors& sensors = services.getMockSensors(); 318 EXPECT_CALL(sensors, startRail).Times(10); 319 EXPECT_CALL(sensors, endRail).Times(10); 320 }; 321 322 // Monitor sensors and detect phase faults 10 times. Verify errors logged. 323 { 324 // Create mock services. Set expectations via lambda. 325 MockServices services{}; 326 setExpectations(services); 327 328 for (int i = 1; i <= 10; ++i) 329 { 330 device.monitorSensors(services, *system, *chassis); 331 device.detectPhaseFaults(services, *system, *chassis); 332 } 333 } 334 335 // Clear error history 336 device.clearErrorHistory(); 337 338 // Monitor sensors and detect phase faults 10 more times. Verify errors 339 // logged again. 340 { 341 // Create mock services. Set expectations via lambda. 342 MockServices services{}; 343 setExpectations(services); 344 345 for (int i = 1; i <= 10; ++i) 346 { 347 device.monitorSensors(services, *system, *chassis); 348 device.detectPhaseFaults(services, *system, *chassis); 349 } 350 } 351 } 352 353 TEST_F(DeviceTests, Close) 354 { 355 // Test where works: I2C interface is not open 356 { 357 // Create mock I2CInterface 358 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 359 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(false)); 360 EXPECT_CALL(*i2cInterface, close).Times(0); 361 362 // Create mock services. No logError should occur. 363 MockServices services{}; 364 MockJournal& journal = services.getMockJournal(); 365 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 366 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>())) 367 .Times(0); 368 369 // Create Device 370 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)}; 371 372 // Close Device 373 device.close(services); 374 } 375 376 // Test where works: I2C interface is open 377 { 378 // Create mock I2CInterface 379 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 380 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 381 EXPECT_CALL(*i2cInterface, close).Times(1); 382 383 // Create mock services. No logError should occur. 384 MockServices services{}; 385 MockJournal& journal = services.getMockJournal(); 386 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 387 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>())) 388 .Times(0); 389 390 // Create Device 391 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)}; 392 393 // Close Device 394 device.close(services); 395 } 396 397 // Test where fails: closing I2C interface fails 398 { 399 // Create mock I2CInterface 400 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>(); 401 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 402 EXPECT_CALL(*i2cInterface, close) 403 .Times(1) 404 .WillOnce(Throw( 405 i2c::I2CException{"Failed to close", "/dev/i2c-1", 0x70})); 406 407 // Create mock services. Expect logError() and logI2CError() to be 408 // called. 409 MockServices services{}; 410 MockErrorLogging& errorLogging = services.getMockErrorLogging(); 411 MockJournal& journal = services.getMockJournal(); 412 std::vector<std::string> expectedErrMessagesException{ 413 "I2CException: Failed to close: bus /dev/i2c-1, addr 0x70"}; 414 EXPECT_CALL(journal, logError("Unable to close device vdd_reg")) 415 .Times(1); 416 EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1); 417 EXPECT_CALL(errorLogging, 418 logI2CError(Entry::Level::Notice, Ref(journal), 419 "/dev/i2c-1", 0x70, 0)) 420 .Times(1); 421 422 // Create Device 423 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)}; 424 425 // Close Device 426 device.close(services); 427 } 428 } 429 430 TEST_F(DeviceTests, Configure) 431 { 432 // Test where device is not present 433 { 434 // Create mock services. No logging should occur. 435 MockServices services{}; 436 MockJournal& journal = services.getMockJournal(); 437 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 438 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 439 440 // Create PresenceDetection. Indicates device is not present. 441 std::unique_ptr<PresenceDetection> presenceDetection{}; 442 { 443 auto action = std::make_unique<MockAction>(); 444 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false)); 445 std::vector<std::unique_ptr<Action>> actions{}; 446 actions.emplace_back(std::move(action)); 447 presenceDetection = 448 std::make_unique<PresenceDetection>(std::move(actions)); 449 } 450 451 // Create Configuration. Action inside it should not be executed. 452 std::unique_ptr<Configuration> configuration{}; 453 { 454 std::optional<double> volts{}; 455 auto action = std::make_unique<MockAction>(); 456 EXPECT_CALL(*action, execute).Times(0); 457 std::vector<std::unique_ptr<Action>> actions{}; 458 actions.emplace_back(std::move(action)); 459 configuration = 460 std::make_unique<Configuration>(volts, std::move(actions)); 461 } 462 463 // Create Device 464 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 465 Device device{"reg2", 466 true, 467 deviceInvPath, 468 std::move(i2cInterface), 469 std::move(presenceDetection), 470 std::move(configuration)}; 471 472 // Call configure(). Should do nothing. 473 device.configure(services, *system, *chassis); 474 } 475 476 // Test where Configuration and Rails were not specified in constructor 477 { 478 // Create mock services. No logging should occur. 479 MockServices services{}; 480 MockJournal& journal = services.getMockJournal(); 481 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 482 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 483 484 // Create Device 485 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 486 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)}; 487 488 // Call configure(). 489 device.configure(services, *system, *chassis); 490 } 491 492 // Test where Configuration and Rails were specified in constructor 493 { 494 std::vector<std::unique_ptr<Rail>> rails{}; 495 496 // Create mock services. Expect logDebug() to be called. 497 // For the Device and both Rails, should execute the Configuration 498 // and log a debug message. 499 MockServices services{}; 500 MockJournal& journal = services.getMockJournal(); 501 EXPECT_CALL(journal, logDebug("Configuring reg2")).Times(1); 502 EXPECT_CALL(journal, logDebug("Configuring vdd0: volts=1.300000")) 503 .Times(1); 504 EXPECT_CALL(journal, logDebug("Configuring vio0: volts=3.200000")) 505 .Times(1); 506 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 507 508 // Create Rail vdd0 509 { 510 // Create Configuration for Rail 511 std::optional<double> volts{1.3}; 512 auto action = std::make_unique<MockAction>(); 513 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 514 std::vector<std::unique_ptr<Action>> actions{}; 515 actions.emplace_back(std::move(action)); 516 auto configuration = 517 std::make_unique<Configuration>(volts, std::move(actions)); 518 519 // Create Rail 520 auto rail = 521 std::make_unique<Rail>("vdd0", std::move(configuration)); 522 rails.emplace_back(std::move(rail)); 523 } 524 525 // Create Rail vio0 526 { 527 // Create Configuration for Rail 528 std::optional<double> volts{3.2}; 529 auto action = std::make_unique<MockAction>(); 530 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 531 std::vector<std::unique_ptr<Action>> actions{}; 532 actions.emplace_back(std::move(action)); 533 auto configuration = 534 std::make_unique<Configuration>(volts, std::move(actions)); 535 536 // Create Rail 537 auto rail = 538 std::make_unique<Rail>("vio0", std::move(configuration)); 539 rails.emplace_back(std::move(rail)); 540 } 541 542 // Create Configuration for Device 543 std::optional<double> volts{}; 544 auto action = std::make_unique<MockAction>(); 545 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 546 std::vector<std::unique_ptr<Action>> actions{}; 547 actions.emplace_back(std::move(action)); 548 auto configuration = 549 std::make_unique<Configuration>(volts, std::move(actions)); 550 551 // Create Device 552 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 553 std::unique_ptr<PresenceDetection> presenceDetection{}; 554 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{}; 555 Device device{"reg2", 556 true, 557 deviceInvPath, 558 std::move(i2cInterface), 559 std::move(presenceDetection), 560 std::move(configuration), 561 std::move(phaseFaultDetection), 562 std::move(rails)}; 563 564 // Call configure(). 565 device.configure(services, *system, *chassis); 566 } 567 } 568 569 TEST_F(DeviceTests, DetectPhaseFaults) 570 { 571 // Test where device is not present 572 { 573 // Create mock services. No errors should be logged. 574 MockServices services{}; 575 MockJournal& journal = services.getMockJournal(); 576 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 577 MockErrorLogging& errorLogging = services.getMockErrorLogging(); 578 EXPECT_CALL(errorLogging, logPhaseFault).Times(0); 579 580 // Create PresenceDetection. Indicates device is not present. 581 std::unique_ptr<PresenceDetection> presenceDetection{}; 582 { 583 auto action = std::make_unique<MockAction>(); 584 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false)); 585 std::vector<std::unique_ptr<Action>> actions{}; 586 actions.emplace_back(std::move(action)); 587 presenceDetection = 588 std::make_unique<PresenceDetection>(std::move(actions)); 589 } 590 591 // Create PhaseFaultDetection. Action inside it should not be executed. 592 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{}; 593 { 594 auto action = std::make_unique<MockAction>(); 595 EXPECT_CALL(*action, execute).Times(0); 596 std::vector<std::unique_ptr<Action>> actions{}; 597 actions.emplace_back(std::move(action)); 598 phaseFaultDetection = 599 std::make_unique<PhaseFaultDetection>(std::move(actions)); 600 } 601 602 // Create Device 603 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 604 std::unique_ptr<Configuration> configuration{}; 605 Device device{"reg2", 606 true, 607 deviceInvPath, 608 std::move(i2cInterface), 609 std::move(presenceDetection), 610 std::move(configuration), 611 std::move(phaseFaultDetection)}; 612 613 // Call detectPhaseFaults() 5 times. Should do nothing. 614 for (int i = 1; i <= 5; ++i) 615 { 616 device.detectPhaseFaults(services, *system, *chassis); 617 } 618 } 619 620 // Test where PhaseFaultDetection was not specified in constructor 621 { 622 // Create mock services. No errors should be logged. 623 MockServices services{}; 624 MockJournal& journal = services.getMockJournal(); 625 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 626 MockErrorLogging& errorLogging = services.getMockErrorLogging(); 627 EXPECT_CALL(errorLogging, logPhaseFault).Times(0); 628 629 // Create Device 630 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 631 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)}; 632 633 // Call detectPhaseFaults() 5 times. Should do nothing. 634 for (int i = 1; i <= 5; ++i) 635 { 636 device.detectPhaseFaults(services, *system, *chassis); 637 } 638 } 639 640 // Test where PhaseFaultDetection was specified in constructor 641 { 642 // Create mock services with the following expectations: 643 // - 2 error messages in journal for N phase fault detected 644 // - 1 N phase fault error logged 645 MockServices services{}; 646 MockJournal& journal = services.getMockJournal(); 647 EXPECT_CALL( 648 journal, 649 logError("n phase fault detected in regulator reg2: count=1")) 650 .Times(1); 651 EXPECT_CALL( 652 journal, 653 logError("n phase fault detected in regulator reg2: count=2")) 654 .Times(1); 655 MockErrorLogging& errorLogging = services.getMockErrorLogging(); 656 EXPECT_CALL(errorLogging, logPhaseFault).Times(1); 657 658 // Create PhaseFaultDetection 659 auto action = std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n); 660 std::vector<std::unique_ptr<Action>> actions{}; 661 actions.push_back(std::move(action)); 662 auto phaseFaultDetection = 663 std::make_unique<PhaseFaultDetection>(std::move(actions)); 664 665 // Create Device 666 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 667 std::unique_ptr<PresenceDetection> presenceDetection{}; 668 std::unique_ptr<Configuration> configuration{}; 669 Device device{"reg2", 670 true, 671 deviceInvPath, 672 std::move(i2cInterface), 673 std::move(presenceDetection), 674 std::move(configuration), 675 std::move(phaseFaultDetection)}; 676 677 // Call detectPhaseFaults() 5 times 678 for (int i = 1; i <= 5; ++i) 679 { 680 device.detectPhaseFaults(services, *system, *chassis); 681 } 682 } 683 } 684 685 TEST_F(DeviceTests, GetConfiguration) 686 { 687 // Test where Configuration was not specified in constructor 688 { 689 Device device{"vdd_reg", true, deviceInvPath, 690 std::move(createI2CInterface())}; 691 EXPECT_EQ(device.getConfiguration(), nullptr); 692 } 693 694 // Test where Configuration was specified in constructor 695 { 696 std::unique_ptr<PresenceDetection> presenceDetection{}; 697 698 // Create Configuration 699 std::optional<double> volts{3.2}; 700 std::vector<std::unique_ptr<Action>> actions{}; 701 actions.push_back(std::make_unique<MockAction>()); 702 actions.push_back(std::make_unique<MockAction>()); 703 auto configuration = 704 std::make_unique<Configuration>(volts, std::move(actions)); 705 706 // Create Device 707 Device device{"vdd_reg", 708 true, 709 deviceInvPath, 710 std::move(createI2CInterface()), 711 std::move(presenceDetection), 712 std::move(configuration)}; 713 EXPECT_NE(device.getConfiguration(), nullptr); 714 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), true); 715 EXPECT_EQ(device.getConfiguration()->getVolts().value(), 3.2); 716 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2); 717 } 718 } 719 720 TEST_F(DeviceTests, GetFRU) 721 { 722 Device device{"vdd_reg", true, deviceInvPath, 723 std::move(createI2CInterface())}; 724 EXPECT_EQ(device.getFRU(), deviceInvPath); 725 } 726 727 TEST_F(DeviceTests, GetI2CInterface) 728 { 729 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 730 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get(); 731 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)}; 732 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr); 733 } 734 735 TEST_F(DeviceTests, GetID) 736 { 737 Device device{"vdd_reg", false, deviceInvPath, 738 std::move(createI2CInterface())}; 739 EXPECT_EQ(device.getID(), "vdd_reg"); 740 } 741 742 TEST_F(DeviceTests, GetPhaseFaultDetection) 743 { 744 // Test where PhaseFaultDetection was not specified in constructor 745 { 746 Device device{"vdd_reg", true, deviceInvPath, 747 std::move(createI2CInterface())}; 748 EXPECT_EQ(device.getPhaseFaultDetection(), nullptr); 749 } 750 751 // Test where PhaseFaultDetection was specified in constructor 752 { 753 // Create PhaseFaultDetection 754 std::vector<std::unique_ptr<Action>> actions{}; 755 actions.push_back(std::make_unique<MockAction>()); 756 auto phaseFaultDetection = 757 std::make_unique<PhaseFaultDetection>(std::move(actions)); 758 759 // Create Device 760 std::unique_ptr<PresenceDetection> presenceDetection{}; 761 std::unique_ptr<Configuration> configuration{}; 762 Device device{"vdd_reg", 763 false, 764 deviceInvPath, 765 std::move(createI2CInterface()), 766 std::move(presenceDetection), 767 std::move(configuration), 768 std::move(phaseFaultDetection)}; 769 EXPECT_NE(device.getPhaseFaultDetection(), nullptr); 770 EXPECT_EQ(device.getPhaseFaultDetection()->getActions().size(), 1); 771 } 772 } 773 774 TEST_F(DeviceTests, GetPresenceDetection) 775 { 776 // Test where PresenceDetection was not specified in constructor 777 { 778 Device device{"vdd_reg", true, deviceInvPath, 779 std::move(createI2CInterface())}; 780 EXPECT_EQ(device.getPresenceDetection(), nullptr); 781 } 782 783 // Test where PresenceDetection was specified in constructor 784 { 785 // Create PresenceDetection 786 std::vector<std::unique_ptr<Action>> actions{}; 787 actions.push_back(std::make_unique<MockAction>()); 788 auto presenceDetection = 789 std::make_unique<PresenceDetection>(std::move(actions)); 790 791 // Create Device 792 Device device{"vdd_reg", false, deviceInvPath, 793 std::move(createI2CInterface()), 794 std::move(presenceDetection)}; 795 EXPECT_NE(device.getPresenceDetection(), nullptr); 796 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1); 797 } 798 } 799 800 TEST_F(DeviceTests, GetRails) 801 { 802 // Test where no rails were specified in constructor 803 { 804 Device device{"vdd_reg", true, deviceInvPath, 805 std::move(createI2CInterface())}; 806 EXPECT_EQ(device.getRails().size(), 0); 807 } 808 809 // Test where rails were specified in constructor 810 { 811 std::unique_ptr<PresenceDetection> presenceDetection{}; 812 std::unique_ptr<Configuration> configuration{}; 813 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{}; 814 815 // Create vector of Rail objects 816 std::vector<std::unique_ptr<Rail>> rails{}; 817 rails.push_back(std::make_unique<Rail>("vdd0")); 818 rails.push_back(std::make_unique<Rail>("vdd1")); 819 820 // Create Device 821 Device device{"vdd_reg", 822 false, 823 deviceInvPath, 824 std::move(createI2CInterface()), 825 std::move(presenceDetection), 826 std::move(configuration), 827 std::move(phaseFaultDetection), 828 std::move(rails)}; 829 EXPECT_EQ(device.getRails().size(), 2); 830 EXPECT_EQ(device.getRails()[0]->getID(), "vdd0"); 831 EXPECT_EQ(device.getRails()[1]->getID(), "vdd1"); 832 } 833 } 834 835 TEST_F(DeviceTests, IsPresent) 836 { 837 // Test where PresenceDetection not specified in constructor 838 { 839 // Create Device 840 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 841 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)}; 842 843 // Create MockServices 844 MockServices services{}; 845 846 // Since no PresenceDetection defined, isPresent() should return true 847 EXPECT_TRUE(device.isPresent(services, *system, *chassis)); 848 } 849 850 // Test where PresenceDetection was specified in constructor: Is present 851 { 852 // Create PresenceDetection. Indicates device is present. 853 auto action = std::make_unique<MockAction>(); 854 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 855 std::vector<std::unique_ptr<Action>> actions{}; 856 actions.emplace_back(std::move(action)); 857 auto presenceDetection = 858 std::make_unique<PresenceDetection>(std::move(actions)); 859 860 // Create Device 861 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 862 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface), 863 std::move(presenceDetection)}; 864 865 // Create MockServices 866 MockServices services{}; 867 868 // PresenceDetection::execute() and isPresent() should return true 869 EXPECT_TRUE(device.isPresent(services, *system, *chassis)); 870 } 871 872 // Test where PresenceDetection was specified in constructor: Is not present 873 { 874 // Create PresenceDetection. Indicates device is not present. 875 auto action = std::make_unique<MockAction>(); 876 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false)); 877 std::vector<std::unique_ptr<Action>> actions{}; 878 actions.emplace_back(std::move(action)); 879 auto presenceDetection = 880 std::make_unique<PresenceDetection>(std::move(actions)); 881 882 // Create Device 883 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 884 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface), 885 std::move(presenceDetection)}; 886 887 // Create MockServices 888 MockServices services{}; 889 890 // PresenceDetection::execute() and isPresent() should return false 891 EXPECT_FALSE(device.isPresent(services, *system, *chassis)); 892 } 893 } 894 895 TEST_F(DeviceTests, IsRegulator) 896 { 897 Device device{"vdd_reg", false, deviceInvPath, 898 std::move(createI2CInterface())}; 899 EXPECT_EQ(device.isRegulator(), false); 900 } 901 902 TEST_F(DeviceTests, MonitorSensors) 903 { 904 // Test where device is not present 905 { 906 // Create mock services. No Sensors methods should be called. 907 MockServices services{}; 908 MockSensors& sensors = services.getMockSensors(); 909 EXPECT_CALL(sensors, startRail).Times(0); 910 EXPECT_CALL(sensors, setValue).Times(0); 911 EXPECT_CALL(sensors, endRail).Times(0); 912 913 // Create SensorMonitoring. Action inside it should not be executed. 914 std::unique_ptr<SensorMonitoring> sensorMonitoring{}; 915 { 916 auto action = std::make_unique<MockAction>(); 917 EXPECT_CALL(*action, execute).Times(0); 918 std::vector<std::unique_ptr<Action>> actions{}; 919 actions.emplace_back(std::move(action)); 920 sensorMonitoring = 921 std::make_unique<SensorMonitoring>(std::move(actions)); 922 } 923 924 // Create Rail 925 std::unique_ptr<Configuration> configuration{}; 926 auto rail = std::make_unique<Rail>("vddr1", std::move(configuration), 927 std::move(sensorMonitoring)); 928 929 // Create PresenceDetection. Indicates device is not present. 930 std::unique_ptr<PresenceDetection> presenceDetection{}; 931 { 932 auto action = std::make_unique<MockAction>(); 933 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false)); 934 std::vector<std::unique_ptr<Action>> actions{}; 935 actions.emplace_back(std::move(action)); 936 presenceDetection = 937 std::make_unique<PresenceDetection>(std::move(actions)); 938 } 939 940 // Create Device 941 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 942 std::unique_ptr<Configuration> deviceConfiguration{}; 943 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{}; 944 std::vector<std::unique_ptr<Rail>> rails{}; 945 rails.emplace_back(std::move(rail)); 946 Device device{"reg2", 947 true, 948 deviceInvPath, 949 std::move(i2cInterface), 950 std::move(presenceDetection), 951 std::move(deviceConfiguration), 952 std::move(phaseFaultDetection), 953 std::move(rails)}; 954 955 // Call monitorSensors(). Should do nothing. 956 device.monitorSensors(services, *system, *chassis); 957 } 958 959 // Test where Rails were not specified in constructor 960 { 961 // Create mock services. No Sensors methods should be called. 962 MockServices services{}; 963 MockSensors& sensors = services.getMockSensors(); 964 EXPECT_CALL(sensors, startRail).Times(0); 965 EXPECT_CALL(sensors, setValue).Times(0); 966 EXPECT_CALL(sensors, endRail).Times(0); 967 968 // Create Device 969 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 970 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)}; 971 972 // Call monitorSensors(). Should do nothing. 973 device.monitorSensors(services, *system, *chassis); 974 } 975 976 // Test where Rails were specified in constructor 977 { 978 // Create mock services. Set Sensors service expectations. 979 MockServices services{}; 980 MockSensors& sensors = services.getMockSensors(); 981 EXPECT_CALL(sensors, startRail("vdd0", deviceInvPath, chassisInvPath)) 982 .Times(1); 983 EXPECT_CALL(sensors, startRail("vio0", deviceInvPath, chassisInvPath)) 984 .Times(1); 985 EXPECT_CALL(sensors, setValue).Times(0); 986 EXPECT_CALL(sensors, endRail(false)).Times(2); 987 988 std::vector<std::unique_ptr<Rail>> rails{}; 989 990 // Create Rail vdd0 991 { 992 // Create SensorMonitoring for Rail 993 auto action = std::make_unique<MockAction>(); 994 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 995 std::vector<std::unique_ptr<Action>> actions{}; 996 actions.emplace_back(std::move(action)); 997 auto sensorMonitoring = 998 std::make_unique<SensorMonitoring>(std::move(actions)); 999 1000 // Create Rail 1001 std::unique_ptr<Configuration> configuration{}; 1002 auto rail = std::make_unique<Rail>("vdd0", std::move(configuration), 1003 std::move(sensorMonitoring)); 1004 rails.emplace_back(std::move(rail)); 1005 } 1006 1007 // Create Rail vio0 1008 { 1009 // Create SensorMonitoring for Rail 1010 auto action = std::make_unique<MockAction>(); 1011 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 1012 std::vector<std::unique_ptr<Action>> actions{}; 1013 actions.emplace_back(std::move(action)); 1014 auto sensorMonitoring = 1015 std::make_unique<SensorMonitoring>(std::move(actions)); 1016 1017 // Create Rail 1018 std::unique_ptr<Configuration> configuration{}; 1019 auto rail = std::make_unique<Rail>("vio0", std::move(configuration), 1020 std::move(sensorMonitoring)); 1021 rails.emplace_back(std::move(rail)); 1022 } 1023 1024 // Create Device that contains Rails 1025 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 1026 std::unique_ptr<PresenceDetection> presenceDetection{}; 1027 std::unique_ptr<Configuration> configuration{}; 1028 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{}; 1029 Device device{"reg2", 1030 true, 1031 deviceInvPath, 1032 std::move(i2cInterface), 1033 std::move(presenceDetection), 1034 std::move(configuration), 1035 std::move(phaseFaultDetection), 1036 std::move(rails)}; 1037 1038 // Call monitorSensors(). Should monitor sensors in both rails. 1039 device.monitorSensors(services, *system, *chassis); 1040 } 1041 } 1042