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