1 #include "../power_supply.hpp" 2 #include "mock.hpp" 3 4 #include <xyz/openbmc_project/Common/Device/error.hpp> 5 #include <xyz/openbmc_project/Common/error.hpp> 6 7 #include <gmock/gmock.h> 8 #include <gtest/gtest.h> 9 10 using namespace phosphor::power::psu; 11 using namespace phosphor::pmbus; 12 13 using ::testing::_; 14 using ::testing::Args; 15 using ::testing::Assign; 16 using ::testing::DoAll; 17 using ::testing::ElementsAre; 18 using ::testing::NotNull; 19 using ::testing::Return; 20 using ::testing::StrEq; 21 22 static auto PSUInventoryPath = "/xyz/bmc/inv/sys/chassis/board/powersupply0"; 23 static auto PSUGPIOLineName = "presence-ps0"; 24 25 struct PMBusExpectations 26 { 27 uint16_t statusWordValue{0x0000}; 28 uint8_t statusInputValue{0x00}; 29 uint8_t statusMFRValue{0x00}; 30 uint8_t statusCMLValue{0x00}; 31 uint8_t statusVOUTValue{0x00}; 32 uint8_t statusIOUTValue{0x00}; 33 uint8_t statusFans12Value{0x00}; 34 uint8_t statusTempValue{0x00}; 35 }; 36 37 // Helper function to setup expectations for various STATUS_* commands 38 void setPMBusExpectations(MockedPMBus& mockPMBus, 39 const PMBusExpectations& expectations) 40 { 41 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _)) 42 .Times(1) 43 .WillOnce(Return(expectations.statusWordValue)); 44 45 if (expectations.statusWordValue != 0) 46 { 47 // If fault bits are on in STATUS_WORD, there will also be a read of 48 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and 49 // STATUS_TEMPERATURE. 50 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _)) 51 .Times(1) 52 .WillOnce(Return(expectations.statusInputValue)); 53 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)) 54 .Times(1) 55 .WillOnce(Return(expectations.statusMFRValue)); 56 EXPECT_CALL(mockPMBus, read(STATUS_CML, _)) 57 .Times(1) 58 .WillOnce(Return(expectations.statusCMLValue)); 59 // Page will need to be set to 0 to read STATUS_VOUT. 60 EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0)) 61 .Times(1) 62 .WillOnce(Return("status0_vout")); 63 EXPECT_CALL(mockPMBus, read("status0_vout", _)) 64 .Times(1) 65 .WillOnce(Return(expectations.statusVOUTValue)); 66 EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _)) 67 .Times(1) 68 .WillOnce(Return(expectations.statusIOUTValue)); 69 EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _)) 70 .Times(1) 71 .WillOnce(Return(expectations.statusFans12Value)); 72 EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _)) 73 .Times(1) 74 .WillOnce(Return(expectations.statusTempValue)); 75 } 76 } 77 78 class PowerSupplyTests : public ::testing::Test 79 { 80 public: 81 PowerSupplyTests() : 82 mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils())) 83 { 84 ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false)); 85 } 86 87 ~PowerSupplyTests() override 88 { 89 freeUtils(); 90 } 91 92 const MockedUtil& mockedUtil; 93 }; 94 95 // Helper function for when a power supply goes from missing to present. 96 void setMissingToPresentExpects(MockedPMBus& pmbus, const MockedUtil& util) 97 { 98 // Call to analyze() will update to present, that will trigger updating 99 // to the correct/latest HWMON directory, in case it changes. 100 EXPECT_CALL(pmbus, findHwmonDir()); 101 // Presence change from missing to present will trigger write to 102 // ON_OFF_CONFIG. 103 EXPECT_CALL(pmbus, writeBinary(ON_OFF_CONFIG, _, _)); 104 // Presence change from missing to present will trigger in1_input read 105 // in an attempt to get CLEAR_FAULTS called. 106 EXPECT_CALL(pmbus, read(READ_VIN, _)).Times(1).WillOnce(Return(1)); 107 // Missing/present call will update Presence in inventory. 108 // EXPECT_CALL(mockedUtil, setPresence(_, _, true, _)); 109 EXPECT_CALL(util, setPresence(_, _, true, _)); 110 } 111 112 TEST_F(PowerSupplyTests, Constructor) 113 { 114 /** 115 * @param[in] invpath - String for inventory path to use 116 * @param[in] i2cbus - The bus number this power supply is on 117 * @param[in] i2caddr - The 16-bit I2C address of the power supply 118 * @param[in] gpioLineName - The string for the gpio-line-name to read for 119 * presence. 120 * @param[in] bindDelay - Time in milliseconds to delay binding the device 121 * driver after seeing the presence line go active. 122 */ 123 auto bus = sdbusplus::bus::new_default(); 124 125 // Try where inventory path is empty, constructor should fail. 126 try 127 { 128 auto psu = 129 std::make_unique<PowerSupply>(bus, "", 3, 0x68, PSUGPIOLineName); 130 ADD_FAILURE() << "Should not have reached this line."; 131 } 132 catch (const std::invalid_argument& e) 133 { 134 EXPECT_STREQ(e.what(), "Invalid empty inventoryPath"); 135 } 136 catch (...) 137 { 138 ADD_FAILURE() << "Should not have caught exception."; 139 } 140 141 // TODO: Try invalid i2c address? 142 143 // Try where gpioLineName is empty. 144 try 145 { 146 auto psu = 147 std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, ""); 148 ADD_FAILURE() 149 << "Should not have reached this line. Invalid gpioLineName."; 150 } 151 catch (const std::invalid_argument& e) 152 { 153 EXPECT_STREQ(e.what(), "Invalid empty gpioLineName"); 154 } 155 catch (...) 156 { 157 ADD_FAILURE() << "Should not have caught exception."; 158 } 159 160 // Test with valid arguments 161 // NOT using D-Bus inventory path for presence. 162 try 163 { 164 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, 165 PSUGPIOLineName); 166 167 EXPECT_EQ(psu->isPresent(), false); 168 EXPECT_EQ(psu->isFaulted(), false); 169 EXPECT_EQ(psu->hasCommFault(), false); 170 EXPECT_EQ(psu->hasInputFault(), false); 171 EXPECT_EQ(psu->hasMFRFault(), false); 172 EXPECT_EQ(psu->hasVINUVFault(), false); 173 EXPECT_EQ(psu->hasVoutOVFault(), false); 174 EXPECT_EQ(psu->hasIoutOCFault(), false); 175 EXPECT_EQ(psu->hasVoutUVFault(), false); 176 EXPECT_EQ(psu->hasFanFault(), false); 177 EXPECT_EQ(psu->hasTempFault(), false); 178 EXPECT_EQ(psu->hasPgoodFault(), false); 179 EXPECT_EQ(psu->hasPSKillFault(), false); 180 EXPECT_EQ(psu->hasPS12VcsFault(), false); 181 EXPECT_EQ(psu->hasPSCS12VFault(), false); 182 } 183 catch (...) 184 { 185 ADD_FAILURE() << "Should not have caught exception."; 186 } 187 188 // Test with valid arguments 189 // TODO: Using D-Bus inventory path for presence. 190 try 191 { 192 // FIXME: How do I get that presenceGPIO.read() in the startup to throw 193 // an exception? 194 195 // EXPECT_CALL(mockedUtil, getPresence(_, 196 // StrEq(PSUInventoryPath))) 197 // .Times(1); 198 } 199 catch (...) 200 { 201 ADD_FAILURE() << "Should not have caught exception."; 202 } 203 } 204 205 TEST_F(PowerSupplyTests, Analyze) 206 { 207 auto bus = sdbusplus::bus::new_default(); 208 209 { 210 // If I default to reading the GPIO, I will NOT expect a call to 211 // getPresence(). 212 213 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName}; 214 MockedGPIOInterface* mockPresenceGPIO = 215 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 216 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0)); 217 218 psu.analyze(); 219 // By default, nothing should change. 220 EXPECT_EQ(psu.isPresent(), false); 221 EXPECT_EQ(psu.isFaulted(), false); 222 EXPECT_EQ(psu.hasInputFault(), false); 223 EXPECT_EQ(psu.hasMFRFault(), false); 224 EXPECT_EQ(psu.hasVINUVFault(), false); 225 EXPECT_EQ(psu.hasCommFault(), false); 226 EXPECT_EQ(psu.hasVoutOVFault(), false); 227 EXPECT_EQ(psu.hasIoutOCFault(), false); 228 EXPECT_EQ(psu.hasVoutUVFault(), false); 229 EXPECT_EQ(psu.hasFanFault(), false); 230 EXPECT_EQ(psu.hasTempFault(), false); 231 EXPECT_EQ(psu.hasPgoodFault(), false); 232 EXPECT_EQ(psu.hasPSKillFault(), false); 233 EXPECT_EQ(psu.hasPS12VcsFault(), false); 234 EXPECT_EQ(psu.hasPSCS12VFault(), false); 235 } 236 237 PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName}; 238 // In order to get the various faults tested, the power supply needs to 239 // be present in order to read from the PMBus device(s). 240 MockedGPIOInterface* mockPresenceGPIO2 = 241 static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO()); 242 // Always return 1 to indicate present. 243 // Each analyze() call will trigger a read of the presence GPIO. 244 EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1)); 245 EXPECT_EQ(psu2.isPresent(), false); 246 247 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus()); 248 setMissingToPresentExpects(mockPMBus, mockedUtil); 249 250 // STATUS_WORD INPUT fault. 251 { 252 // Start with STATUS_WORD 0x0000. Powered on, no faults. 253 // Set expectations for a no fault 254 PMBusExpectations expectations; 255 setPMBusExpectations(mockPMBus, expectations); 256 psu2.analyze(); 257 EXPECT_EQ(psu2.isPresent(), true); 258 EXPECT_EQ(psu2.isFaulted(), false); 259 EXPECT_EQ(psu2.hasInputFault(), false); 260 EXPECT_EQ(psu2.hasMFRFault(), false); 261 EXPECT_EQ(psu2.hasVINUVFault(), false); 262 EXPECT_EQ(psu2.hasCommFault(), false); 263 EXPECT_EQ(psu2.hasVoutOVFault(), false); 264 EXPECT_EQ(psu2.hasIoutOCFault(), false); 265 EXPECT_EQ(psu2.hasVoutUVFault(), false); 266 EXPECT_EQ(psu2.hasFanFault(), false); 267 EXPECT_EQ(psu2.hasTempFault(), false); 268 EXPECT_EQ(psu2.hasPgoodFault(), false); 269 EXPECT_EQ(psu2.hasPSKillFault(), false); 270 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 271 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 272 273 // Update expectations for STATUS_WORD input fault/warn 274 // STATUS_INPUT fault bits ... on. 275 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN); 276 expectations.statusInputValue = 0x38; 277 setPMBusExpectations(mockPMBus, expectations); 278 psu2.analyze(); 279 EXPECT_EQ(psu2.isPresent(), true); 280 EXPECT_EQ(psu2.isFaulted(), true); 281 EXPECT_EQ(psu2.hasInputFault(), true); 282 EXPECT_EQ(psu2.hasMFRFault(), false); 283 EXPECT_EQ(psu2.hasVINUVFault(), false); 284 EXPECT_EQ(psu2.hasCommFault(), false); 285 EXPECT_EQ(psu2.hasVoutOVFault(), false); 286 EXPECT_EQ(psu2.hasIoutOCFault(), false); 287 EXPECT_EQ(psu2.hasVoutUVFault(), false); 288 EXPECT_EQ(psu2.hasFanFault(), false); 289 EXPECT_EQ(psu2.hasTempFault(), false); 290 EXPECT_EQ(psu2.hasPgoodFault(), false); 291 EXPECT_EQ(psu2.hasPSKillFault(), false); 292 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 293 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 294 } 295 296 // STATUS_WORD INPUT/UV fault. 297 { 298 // First need it to return good status, then the fault 299 PMBusExpectations expectations; 300 setPMBusExpectations(mockPMBus, expectations); 301 psu2.analyze(); 302 // Now set fault bits in STATUS_WORD 303 expectations.statusWordValue = 304 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT); 305 // STATUS_INPUT fault bits ... on. 306 expectations.statusInputValue = 0x38; 307 setPMBusExpectations(mockPMBus, expectations); 308 psu2.analyze(); 309 EXPECT_EQ(psu2.isPresent(), true); 310 EXPECT_EQ(psu2.isFaulted(), true); 311 EXPECT_EQ(psu2.hasInputFault(), true); 312 EXPECT_EQ(psu2.hasMFRFault(), false); 313 EXPECT_EQ(psu2.hasVINUVFault(), true); 314 EXPECT_EQ(psu2.hasCommFault(), false); 315 EXPECT_EQ(psu2.hasVoutOVFault(), false); 316 EXPECT_EQ(psu2.hasIoutOCFault(), false); 317 EXPECT_EQ(psu2.hasVoutUVFault(), false); 318 EXPECT_EQ(psu2.hasFanFault(), false); 319 EXPECT_EQ(psu2.hasTempFault(), false); 320 EXPECT_EQ(psu2.hasPgoodFault(), false); 321 EXPECT_EQ(psu2.hasPSKillFault(), false); 322 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 323 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 324 } 325 326 // STATUS_WORD MFR fault. 327 { 328 // First need it to return good status, then the fault 329 PMBusExpectations expectations; 330 setPMBusExpectations(mockPMBus, expectations); 331 psu2.analyze(); 332 // Now STATUS_WORD with MFR fault bit on. 333 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 334 // STATUS_MFR bits on. 335 expectations.statusMFRValue = 0xFF; 336 setPMBusExpectations(mockPMBus, expectations); 337 psu2.analyze(); 338 EXPECT_EQ(psu2.isPresent(), true); 339 EXPECT_EQ(psu2.isFaulted(), true); 340 EXPECT_EQ(psu2.hasInputFault(), false); 341 EXPECT_EQ(psu2.hasMFRFault(), true); 342 EXPECT_EQ(psu2.hasVINUVFault(), false); 343 EXPECT_EQ(psu2.hasCommFault(), false); 344 EXPECT_EQ(psu2.hasVoutOVFault(), false); 345 EXPECT_EQ(psu2.hasIoutOCFault(), false); 346 EXPECT_EQ(psu2.hasVoutUVFault(), false); 347 EXPECT_EQ(psu2.hasFanFault(), false); 348 EXPECT_EQ(psu2.hasTempFault(), false); 349 EXPECT_EQ(psu2.hasPgoodFault(), false); 350 EXPECT_EQ(psu2.hasPSKillFault(), true); 351 EXPECT_EQ(psu2.hasPS12VcsFault(), true); 352 EXPECT_EQ(psu2.hasPSCS12VFault(), true); 353 } 354 355 // Temperature fault. 356 { 357 // First STATUS_WORD with no bits set, then with temperature fault. 358 PMBusExpectations expectations; 359 setPMBusExpectations(mockPMBus, expectations); 360 psu2.analyze(); 361 // STATUS_WORD with temperature fault bit on. 362 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN); 363 // STATUS_TEMPERATURE with fault bit(s) on. 364 expectations.statusTempValue = 0x10; 365 setPMBusExpectations(mockPMBus, expectations); 366 psu2.analyze(); 367 EXPECT_EQ(psu2.isPresent(), true); 368 EXPECT_EQ(psu2.isFaulted(), true); 369 EXPECT_EQ(psu2.hasInputFault(), false); 370 EXPECT_EQ(psu2.hasMFRFault(), false); 371 EXPECT_EQ(psu2.hasVINUVFault(), false); 372 EXPECT_EQ(psu2.hasCommFault(), false); 373 EXPECT_EQ(psu2.hasVoutOVFault(), false); 374 EXPECT_EQ(psu2.hasIoutOCFault(), false); 375 EXPECT_EQ(psu2.hasVoutUVFault(), false); 376 EXPECT_EQ(psu2.hasFanFault(), false); 377 EXPECT_EQ(psu2.hasTempFault(), true); 378 EXPECT_EQ(psu2.hasPgoodFault(), false); 379 EXPECT_EQ(psu2.hasPSKillFault(), false); 380 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 381 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 382 } 383 384 // CML fault 385 { 386 // First STATUS_WORD wit no bits set, then with CML fault. 387 PMBusExpectations expectations; 388 setPMBusExpectations(mockPMBus, expectations); 389 psu2.analyze(); 390 // STATUS_WORD with CML fault bit on. 391 expectations.statusWordValue = (status_word::CML_FAULT); 392 // Turn on STATUS_CML fault bit(s) 393 expectations.statusCMLValue = 0xFF; 394 setPMBusExpectations(mockPMBus, expectations); 395 psu2.analyze(); 396 EXPECT_EQ(psu2.isPresent(), true); 397 EXPECT_EQ(psu2.isFaulted(), true); 398 EXPECT_EQ(psu2.hasInputFault(), false); 399 EXPECT_EQ(psu2.hasMFRFault(), false); 400 EXPECT_EQ(psu2.hasVINUVFault(), false); 401 EXPECT_EQ(psu2.hasCommFault(), true); 402 EXPECT_EQ(psu2.hasVoutOVFault(), false); 403 EXPECT_EQ(psu2.hasIoutOCFault(), false); 404 EXPECT_EQ(psu2.hasVoutUVFault(), false); 405 EXPECT_EQ(psu2.hasFanFault(), false); 406 EXPECT_EQ(psu2.hasTempFault(), false); 407 EXPECT_EQ(psu2.hasPgoodFault(), false); 408 EXPECT_EQ(psu2.hasPSKillFault(), false); 409 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 410 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 411 } 412 413 // VOUT_OV_FAULT fault 414 { 415 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault. 416 PMBusExpectations expectations; 417 setPMBusExpectations(mockPMBus, expectations); 418 psu2.analyze(); 419 // STATUS_WORD with VOUT/VOUT_OV fault. 420 expectations.statusWordValue = 421 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT)); 422 // Turn on STATUS_VOUT fault bit(s) 423 expectations.statusVOUTValue = 0xA0; 424 // STATUS_TEMPERATURE don't care (default) 425 setPMBusExpectations(mockPMBus, expectations); 426 psu2.analyze(); 427 EXPECT_EQ(psu2.isPresent(), true); 428 EXPECT_EQ(psu2.isFaulted(), true); 429 EXPECT_EQ(psu2.hasInputFault(), false); 430 EXPECT_EQ(psu2.hasMFRFault(), false); 431 EXPECT_EQ(psu2.hasVINUVFault(), false); 432 EXPECT_EQ(psu2.hasCommFault(), false); 433 EXPECT_EQ(psu2.hasVoutOVFault(), true); 434 EXPECT_EQ(psu2.hasVoutUVFault(), false); 435 EXPECT_EQ(psu2.hasIoutOCFault(), false); 436 EXPECT_EQ(psu2.hasFanFault(), false); 437 EXPECT_EQ(psu2.hasTempFault(), false); 438 EXPECT_EQ(psu2.hasPgoodFault(), false); 439 EXPECT_EQ(psu2.hasPSKillFault(), false); 440 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 441 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 442 } 443 444 // IOUT_OC_FAULT fault 445 { 446 // First STATUS_WORD with no bits set, then with IOUT_OC fault. 447 PMBusExpectations expectations; 448 setPMBusExpectations(mockPMBus, expectations); 449 psu2.analyze(); 450 // STATUS_WORD with IOUT_OC fault. 451 expectations.statusWordValue = status_word::IOUT_OC_FAULT; 452 // Turn on STATUS_IOUT fault bit(s) 453 expectations.statusIOUTValue = 0x88; 454 setPMBusExpectations(mockPMBus, expectations); 455 psu2.analyze(); 456 EXPECT_EQ(psu2.isPresent(), true); 457 EXPECT_EQ(psu2.isFaulted(), true); 458 EXPECT_EQ(psu2.hasInputFault(), false); 459 EXPECT_EQ(psu2.hasMFRFault(), false); 460 EXPECT_EQ(psu2.hasVINUVFault(), false); 461 EXPECT_EQ(psu2.hasCommFault(), false); 462 EXPECT_EQ(psu2.hasVoutOVFault(), false); 463 EXPECT_EQ(psu2.hasIoutOCFault(), true); 464 EXPECT_EQ(psu2.hasVoutUVFault(), false); 465 EXPECT_EQ(psu2.hasFanFault(), false); 466 EXPECT_EQ(psu2.hasTempFault(), false); 467 EXPECT_EQ(psu2.hasPgoodFault(), false); 468 EXPECT_EQ(psu2.hasPSKillFault(), false); 469 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 470 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 471 } 472 473 // VOUT_UV_FAULT 474 { 475 // First STATUS_WORD with no bits set, then with VOUT fault. 476 PMBusExpectations expectations; 477 setPMBusExpectations(mockPMBus, expectations); 478 psu2.analyze(); 479 // Change STATUS_WORD to indicate VOUT fault. 480 expectations.statusWordValue = (status_word::VOUT_FAULT); 481 // Turn on STATUS_VOUT fault bit(s) 482 expectations.statusVOUTValue = 0x30; 483 setPMBusExpectations(mockPMBus, expectations); 484 psu2.analyze(); 485 EXPECT_EQ(psu2.isPresent(), true); 486 EXPECT_EQ(psu2.isFaulted(), true); 487 EXPECT_EQ(psu2.hasInputFault(), false); 488 EXPECT_EQ(psu2.hasMFRFault(), false); 489 EXPECT_EQ(psu2.hasVINUVFault(), false); 490 EXPECT_EQ(psu2.hasCommFault(), false); 491 EXPECT_EQ(psu2.hasVoutOVFault(), false); 492 EXPECT_EQ(psu2.hasIoutOCFault(), false); 493 EXPECT_EQ(psu2.hasVoutUVFault(), true); 494 EXPECT_EQ(psu2.hasFanFault(), false); 495 EXPECT_EQ(psu2.hasTempFault(), false); 496 EXPECT_EQ(psu2.hasPgoodFault(), false); 497 EXPECT_EQ(psu2.hasPSKillFault(), false); 498 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 499 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 500 } 501 502 // Fan fault 503 { 504 // First STATUS_WORD with no bits set, then with fan fault. 505 PMBusExpectations expectations; 506 setPMBusExpectations(mockPMBus, expectations); 507 psu2.analyze(); 508 expectations.statusWordValue = (status_word::FAN_FAULT); 509 // STATUS_FANS_1_2 with fan 1 warning & fault bits on. 510 expectations.statusFans12Value = 0xA0; 511 setPMBusExpectations(mockPMBus, expectations); 512 psu2.analyze(); 513 EXPECT_EQ(psu2.isPresent(), true); 514 EXPECT_EQ(psu2.isFaulted(), true); 515 EXPECT_EQ(psu2.hasInputFault(), false); 516 EXPECT_EQ(psu2.hasMFRFault(), false); 517 EXPECT_EQ(psu2.hasVINUVFault(), false); 518 EXPECT_EQ(psu2.hasCommFault(), false); 519 EXPECT_EQ(psu2.hasVoutOVFault(), false); 520 EXPECT_EQ(psu2.hasIoutOCFault(), false); 521 EXPECT_EQ(psu2.hasVoutUVFault(), false); 522 EXPECT_EQ(psu2.hasFanFault(), true); 523 EXPECT_EQ(psu2.hasTempFault(), false); 524 EXPECT_EQ(psu2.hasPgoodFault(), false); 525 EXPECT_EQ(psu2.hasPSKillFault(), false); 526 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 527 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 528 } 529 530 // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT. 531 { 532 // First STATUS_WORD with no bits set. 533 PMBusExpectations expectations; 534 setPMBusExpectations(mockPMBus, expectations); 535 psu2.analyze(); 536 EXPECT_EQ(psu2.isFaulted(), false); 537 // POWER_GOOD# inactive, and OFF bit on. 538 expectations.statusWordValue = 539 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF)); 540 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 541 { 542 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and 543 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults). 544 setPMBusExpectations(mockPMBus, expectations); 545 psu2.analyze(); 546 EXPECT_EQ(psu2.isPresent(), true); 547 if (x < DEGLITCH_LIMIT) 548 { 549 EXPECT_EQ(psu2.isFaulted(), false); 550 } 551 else 552 { 553 EXPECT_EQ(psu2.isFaulted(), true); 554 } 555 EXPECT_EQ(psu2.hasInputFault(), false); 556 EXPECT_EQ(psu2.hasMFRFault(), false); 557 EXPECT_EQ(psu2.hasVINUVFault(), false); 558 EXPECT_EQ(psu2.hasCommFault(), false); 559 EXPECT_EQ(psu2.hasVoutOVFault(), false); 560 EXPECT_EQ(psu2.hasVoutUVFault(), false); 561 EXPECT_EQ(psu2.hasIoutOCFault(), false); 562 EXPECT_EQ(psu2.hasFanFault(), false); 563 EXPECT_EQ(psu2.hasTempFault(), false); 564 if (x < DEGLITCH_LIMIT) 565 { 566 EXPECT_EQ(psu2.hasPgoodFault(), false); 567 } 568 else 569 { 570 EXPECT_EQ(psu2.hasPgoodFault(), true); 571 } 572 } 573 } 574 575 // TODO: ReadFailure 576 } 577 578 TEST_F(PowerSupplyTests, OnOffConfig) 579 { 580 auto bus = sdbusplus::bus::new_default(); 581 uint8_t data = 0x15; 582 583 // Test where PSU is NOT present 584 try 585 { 586 // Assume GPIO presence, not inventory presence? 587 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName}; 588 589 MockedGPIOInterface* mockPresenceGPIO = 590 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 591 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0)); 592 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 593 // Constructor should set initial presence, default read returns 0. 594 // If it is not present, I should not be trying to write to it. 595 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0); 596 psu.onOffConfig(data); 597 } 598 catch (...) 599 {} 600 601 // Test where PSU is present 602 try 603 { 604 // Assume GPIO presence, not inventory presence? 605 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName}; 606 MockedGPIOInterface* mockPresenceGPIO = 607 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 608 // There will potentially be multiple calls, we want it to continue 609 // returning 1 for the GPIO read to keep the power supply present. 610 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 611 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 612 setMissingToPresentExpects(mockPMBus, mockedUtil); 613 // If I am calling analyze(), I should probably give it good data. 614 // STATUS_WORD 0x0000 is powered on, no faults. 615 PMBusExpectations expectations; 616 setPMBusExpectations(mockPMBus, expectations); 617 psu.analyze(); 618 // I definitely should be writting ON_OFF_CONFIG if I call the function 619 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15), 620 Type::HwmonDeviceDebug)) 621 .Times(1); 622 psu.onOffConfig(data); 623 } 624 catch (...) 625 {} 626 } 627 628 TEST_F(PowerSupplyTests, ClearFaults) 629 { 630 auto bus = sdbusplus::bus::new_default(); 631 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName}; 632 MockedGPIOInterface* mockPresenceGPIO = 633 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 634 // Always return 1 to indicate present. 635 // Each analyze() call will trigger a read of the presence GPIO. 636 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 637 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 638 setMissingToPresentExpects(mockPMBus, mockedUtil); 639 // STATUS_WORD 0x0000 is powered on, no faults. 640 PMBusExpectations expectations; 641 setPMBusExpectations(mockPMBus, expectations); 642 psu.analyze(); 643 EXPECT_EQ(psu.isPresent(), true); 644 EXPECT_EQ(psu.isFaulted(), false); 645 EXPECT_EQ(psu.hasInputFault(), false); 646 EXPECT_EQ(psu.hasMFRFault(), false); 647 EXPECT_EQ(psu.hasVINUVFault(), false); 648 EXPECT_EQ(psu.hasCommFault(), false); 649 EXPECT_EQ(psu.hasVoutOVFault(), false); 650 EXPECT_EQ(psu.hasIoutOCFault(), false); 651 EXPECT_EQ(psu.hasVoutUVFault(), false); 652 EXPECT_EQ(psu.hasFanFault(), false); 653 EXPECT_EQ(psu.hasTempFault(), false); 654 EXPECT_EQ(psu.hasPgoodFault(), false); 655 EXPECT_EQ(psu.hasPSKillFault(), false); 656 EXPECT_EQ(psu.hasPS12VcsFault(), false); 657 EXPECT_EQ(psu.hasPSCS12VFault(), false); 658 659 // STATUS_WORD with fault bits galore! 660 expectations.statusWordValue = 0xFFFF; 661 // STATUS_INPUT with fault bits on. 662 expectations.statusInputValue = 0xFF; 663 // STATUS_MFR_SPEFIC with bits on. 664 expectations.statusMFRValue = 0xFF; 665 // STATUS_CML with bits on. 666 expectations.statusCMLValue = 0xFF; 667 // STATUS_VOUT with bits on. 668 expectations.statusVOUTValue = 0xFF; 669 // STATUS_IOUT with bits on. 670 expectations.statusIOUTValue = 0xFF; 671 // STATUS_FANS_1_2 with bits on. 672 expectations.statusFans12Value = 0xFF; 673 // STATUS_TEMPERATURE with bits on. 674 expectations.statusTempValue = 0xFF; 675 setPMBusExpectations(mockPMBus, expectations); 676 psu.analyze(); 677 EXPECT_EQ(psu.isPresent(), true); 678 EXPECT_EQ(psu.isFaulted(), true); 679 EXPECT_EQ(psu.hasInputFault(), true); 680 EXPECT_EQ(psu.hasMFRFault(), true); 681 EXPECT_EQ(psu.hasVINUVFault(), true); 682 EXPECT_EQ(psu.hasCommFault(), true); 683 EXPECT_EQ(psu.hasVoutOVFault(), true); 684 EXPECT_EQ(psu.hasIoutOCFault(), true); 685 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT. 686 // Rely on HasVoutUVFault() to verify this sets and clears. 687 EXPECT_EQ(psu.hasVoutUVFault(), false); 688 EXPECT_EQ(psu.hasFanFault(), true); 689 EXPECT_EQ(psu.hasTempFault(), true); 690 // pgoodFault is deglitched up to DEGLITCH_LIMIT 691 EXPECT_EQ(psu.hasPgoodFault(), false); 692 setPMBusExpectations(mockPMBus, expectations); 693 psu.analyze(); 694 EXPECT_EQ(psu.hasPgoodFault(), false); 695 setPMBusExpectations(mockPMBus, expectations); 696 psu.analyze(); 697 // DEGLITCH_LIMIT reached for pgoodFault 698 EXPECT_EQ(psu.hasPgoodFault(), true); 699 EXPECT_EQ(psu.hasPSKillFault(), true); 700 EXPECT_EQ(psu.hasPS12VcsFault(), true); 701 EXPECT_EQ(psu.hasPSCS12VFault(), true); 702 703 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(207000)); 704 psu.clearFaults(); 705 EXPECT_EQ(psu.isPresent(), true); 706 EXPECT_EQ(psu.isFaulted(), false); 707 EXPECT_EQ(psu.hasInputFault(), false); 708 EXPECT_EQ(psu.hasMFRFault(), false); 709 EXPECT_EQ(psu.hasVINUVFault(), false); 710 EXPECT_EQ(psu.hasCommFault(), false); 711 EXPECT_EQ(psu.hasVoutOVFault(), false); 712 EXPECT_EQ(psu.hasIoutOCFault(), false); 713 EXPECT_EQ(psu.hasVoutUVFault(), false); 714 EXPECT_EQ(psu.hasFanFault(), false); 715 EXPECT_EQ(psu.hasTempFault(), false); 716 EXPECT_EQ(psu.hasPgoodFault(), false); 717 EXPECT_EQ(psu.hasPSKillFault(), false); 718 EXPECT_EQ(psu.hasPS12VcsFault(), false); 719 EXPECT_EQ(psu.hasPSCS12VFault(), false); 720 721 // TODO: Faults clear on missing/present? 722 } 723 724 TEST_F(PowerSupplyTests, UpdateInventory) 725 { 726 auto bus = sdbusplus::bus::new_default(); 727 728 try 729 { 730 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 731 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 732 // If it is not present, I should not be trying to read a string 733 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0); 734 psu.updateInventory(); 735 } 736 catch (...) 737 { 738 ADD_FAILURE() << "Should not have caught exception."; 739 } 740 741 try 742 { 743 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName}; 744 MockedGPIOInterface* mockPresenceGPIO = 745 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 746 // GPIO read return 1 to indicate present. 747 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1)); 748 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 749 setMissingToPresentExpects(mockPMBus, mockedUtil); 750 // STATUS_WORD 0x0000 is powered on, no faults. 751 PMBusExpectations expectations; 752 setPMBusExpectations(mockPMBus, expectations); 753 // Need analyze call to update power supply from missing to present. 754 psu.analyze(); 755 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return("")); 756 psu.updateInventory(); 757 758 #if IBM_VPD 759 EXPECT_CALL(mockPMBus, readString(_, _)) 760 .WillOnce(Return("CCIN")) 761 .WillOnce(Return("PN3456")) 762 .WillOnce(Return("FN3456")) 763 .WillOnce(Return("HEADER")) 764 .WillOnce(Return("SN3456")) 765 .WillOnce(Return("FW3456")); 766 #endif 767 psu.updateInventory(); 768 // TODO: D-Bus mocking to verify values stored on D-Bus (???) 769 } 770 catch (...) 771 { 772 ADD_FAILURE() << "Should not have caught exception."; 773 } 774 } 775 776 TEST_F(PowerSupplyTests, IsPresent) 777 { 778 auto bus = sdbusplus::bus::new_default(); 779 780 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 781 MockedGPIOInterface* mockPresenceGPIO = 782 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 783 EXPECT_EQ(psu.isPresent(), false); 784 785 // Change GPIO read to return 1 to indicate present. 786 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1)); 787 // Call to analyze() will update to present, that will trigger updating 788 // to the correct/latest HWMON directory, in case it changes. 789 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 790 setMissingToPresentExpects(mockPMBus, mockedUtil); 791 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN. 792 // Default expectations will be on, no faults. 793 PMBusExpectations expectations; 794 setPMBusExpectations(mockPMBus, expectations); 795 psu.analyze(); 796 EXPECT_EQ(psu.isPresent(), true); 797 } 798 799 TEST_F(PowerSupplyTests, IsFaulted) 800 { 801 auto bus = sdbusplus::bus::new_default(); 802 803 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName}; 804 MockedGPIOInterface* mockPresenceGPIO = 805 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 806 // Always return 1 to indicate present. 807 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 808 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 809 setMissingToPresentExpects(mockPMBus, mockedUtil); 810 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN. 811 // Default expectations will be on, no faults. 812 PMBusExpectations expectations; 813 setPMBusExpectations(mockPMBus, expectations); 814 psu.analyze(); 815 EXPECT_EQ(psu.isFaulted(), false); 816 // STATUS_WORD with fault bits on. 817 expectations.statusWordValue = 0xFFFF; 818 // STATUS_INPUT with fault bits on. 819 expectations.statusInputValue = 0xFF; 820 // STATUS_MFR_SPECIFIC with faults bits on. 821 expectations.statusMFRValue = 0xFF; 822 // STATUS_CML with faults bits on. 823 expectations.statusCMLValue = 0xFF; 824 // STATUS_VOUT with fault bits on. 825 expectations.statusVOUTValue = 0xFF; 826 // STATUS_IOUT with fault bits on. 827 expectations.statusIOUTValue = 0xFF; 828 // STATUS_FANS_1_2 with bits on. 829 expectations.statusFans12Value = 0xFF; 830 // STATUS_TEMPERATURE with fault bits on. 831 expectations.statusTempValue = 0xFF; 832 setPMBusExpectations(mockPMBus, expectations); 833 psu.analyze(); 834 EXPECT_EQ(psu.isFaulted(), true); 835 } 836 837 TEST_F(PowerSupplyTests, HasInputFault) 838 { 839 auto bus = sdbusplus::bus::new_default(); 840 841 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 842 MockedGPIOInterface* mockPresenceGPIO = 843 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 844 // Always return 1 to indicate present. 845 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 846 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 847 setMissingToPresentExpects(mockPMBus, mockedUtil); 848 // STATUS_WORD 0x0000 is powered on, no faults. 849 PMBusExpectations expectations; 850 setPMBusExpectations(mockPMBus, expectations); 851 psu.analyze(); 852 EXPECT_EQ(psu.hasInputFault(), false); 853 // STATUS_WORD with input fault/warn on. 854 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN); 855 // STATUS_INPUT with an input fault bit on. 856 expectations.statusInputValue = 0x80; 857 setPMBusExpectations(mockPMBus, expectations); 858 psu.analyze(); 859 EXPECT_EQ(psu.hasInputFault(), true); 860 // STATUS_WORD with no bits on. 861 expectations.statusWordValue = 0; 862 setPMBusExpectations(mockPMBus, expectations); 863 psu.analyze(); 864 EXPECT_EQ(psu.hasInputFault(), false); 865 } 866 867 TEST_F(PowerSupplyTests, HasMFRFault) 868 { 869 auto bus = sdbusplus::bus::new_default(); 870 871 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 872 MockedGPIOInterface* mockPresenceGPIO = 873 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 874 // Always return 1 to indicate present. 875 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 876 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 877 setMissingToPresentExpects(mockPMBus, mockedUtil); 878 // First return STATUS_WORD with no bits on. 879 // STATUS_WORD 0x0000 is powered on, no faults. 880 PMBusExpectations expectations; 881 setPMBusExpectations(mockPMBus, expectations); 882 psu.analyze(); 883 EXPECT_EQ(psu.hasMFRFault(), false); 884 // Next return STATUS_WORD with MFR fault bit on. 885 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 886 // STATUS_MFR_SPEFIC with bit(s) on. 887 expectations.statusMFRValue = 0xFF; 888 setPMBusExpectations(mockPMBus, expectations); 889 psu.analyze(); 890 EXPECT_EQ(psu.hasMFRFault(), true); 891 // Back to no bits on in STATUS_WORD 892 expectations.statusWordValue = 0; 893 setPMBusExpectations(mockPMBus, expectations); 894 psu.analyze(); 895 EXPECT_EQ(psu.hasMFRFault(), false); 896 } 897 898 TEST_F(PowerSupplyTests, HasVINUVFault) 899 { 900 auto bus = sdbusplus::bus::new_default(); 901 902 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 903 MockedGPIOInterface* mockPresenceGPIO = 904 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 905 // Always return 1 to indicate present. 906 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 907 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 908 setMissingToPresentExpects(mockPMBus, mockedUtil); 909 // STATUS_WORD 0x0000 is powered on, no faults. 910 PMBusExpectations expectations; 911 setPMBusExpectations(mockPMBus, expectations); 912 psu.analyze(); 913 EXPECT_EQ(psu.hasVINUVFault(), false); 914 // Turn fault on. 915 expectations.statusWordValue = (status_word::VIN_UV_FAULT); 916 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by 917 // Figure 16, and assume bits on in STATUS_INPUT. 918 expectations.statusInputValue = 0x18; 919 setPMBusExpectations(mockPMBus, expectations); 920 psu.analyze(); 921 EXPECT_EQ(psu.hasVINUVFault(), true); 922 // Back to no fault bits on in STATUS_WORD 923 expectations.statusWordValue = 0; 924 setPMBusExpectations(mockPMBus, expectations); 925 psu.analyze(); 926 EXPECT_EQ(psu.hasVINUVFault(), false); 927 } 928 929 TEST_F(PowerSupplyTests, HasVoutOVFault) 930 { 931 auto bus = sdbusplus::bus::new_default(); 932 933 PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName}; 934 MockedGPIOInterface* mockPresenceGPIO = 935 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 936 // Always return 1 to indicate present. 937 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 938 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 939 setMissingToPresentExpects(mockPMBus, mockedUtil); 940 // STATUS_WORD 0x0000 is powered on, no faults. 941 PMBusExpectations expectations; 942 setPMBusExpectations(mockPMBus, expectations); 943 psu.analyze(); 944 EXPECT_EQ(psu.hasVoutOVFault(), false); 945 // Turn fault on. 946 expectations.statusWordValue = (status_word::VOUT_OV_FAULT); 947 // STATUS_VOUT fault bit(s) 948 expectations.statusVOUTValue = 0x80; 949 // STATUS_TEMPERATURE default. 950 setPMBusExpectations(mockPMBus, expectations); 951 psu.analyze(); 952 EXPECT_EQ(psu.hasVoutOVFault(), true); 953 // Back to no fault bits on in STATUS_WORD 954 expectations.statusWordValue = 0; 955 setPMBusExpectations(mockPMBus, expectations); 956 psu.analyze(); 957 EXPECT_EQ(psu.hasVoutOVFault(), false); 958 } 959 960 TEST_F(PowerSupplyTests, HasIoutOCFault) 961 { 962 auto bus = sdbusplus::bus::new_default(); 963 964 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName}; 965 MockedGPIOInterface* mockPresenceGPIO = 966 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 967 // Always return 1 to indicate present. 968 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 969 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 970 setMissingToPresentExpects(mockPMBus, mockedUtil); 971 // STATUS_WORD 0x0000 is powered on, no faults. 972 PMBusExpectations expectations; 973 setPMBusExpectations(mockPMBus, expectations); 974 psu.analyze(); 975 EXPECT_EQ(psu.hasIoutOCFault(), false); 976 // Turn fault on. 977 expectations.statusWordValue = status_word::IOUT_OC_FAULT; 978 // STATUS_IOUT fault bit(s) 979 expectations.statusIOUTValue = 0x88; 980 setPMBusExpectations(mockPMBus, expectations); 981 psu.analyze(); 982 EXPECT_EQ(psu.hasIoutOCFault(), true); 983 // Back to no fault bits on in STATUS_WORD 984 expectations.statusWordValue = 0; 985 setPMBusExpectations(mockPMBus, expectations); 986 psu.analyze(); 987 EXPECT_EQ(psu.hasIoutOCFault(), false); 988 } 989 990 TEST_F(PowerSupplyTests, HasVoutUVFault) 991 { 992 auto bus = sdbusplus::bus::new_default(); 993 994 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName}; 995 MockedGPIOInterface* mockPresenceGPIO = 996 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 997 // Always return 1 to indicate present. 998 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 999 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1000 setMissingToPresentExpects(mockPMBus, mockedUtil); 1001 // STATUS_WORD 0x0000 is powered on, no faults. 1002 PMBusExpectations expectations; 1003 setPMBusExpectations(mockPMBus, expectations); 1004 psu.analyze(); 1005 EXPECT_EQ(psu.hasVoutUVFault(), false); 1006 // Turn fault on. 1007 expectations.statusWordValue = (status_word::VOUT_FAULT); 1008 // STATUS_VOUT fault bit(s) 1009 expectations.statusVOUTValue = 0x30; 1010 setPMBusExpectations(mockPMBus, expectations); 1011 psu.analyze(); 1012 EXPECT_EQ(psu.hasVoutUVFault(), true); 1013 // Back to no fault bits on in STATUS_WORD 1014 expectations.statusWordValue = 0; 1015 setPMBusExpectations(mockPMBus, expectations); 1016 psu.analyze(); 1017 EXPECT_EQ(psu.hasVoutUVFault(), false); 1018 } 1019 1020 TEST_F(PowerSupplyTests, HasFanFault) 1021 { 1022 auto bus = sdbusplus::bus::new_default(); 1023 1024 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName}; 1025 MockedGPIOInterface* mockPresenceGPIO = 1026 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1027 // Always return 1 to indicate present. 1028 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1029 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1030 setMissingToPresentExpects(mockPMBus, mockedUtil); 1031 // STATUS_WORD 0x0000 is powered on, no faults. 1032 PMBusExpectations expectations; 1033 setPMBusExpectations(mockPMBus, expectations); 1034 psu.analyze(); 1035 EXPECT_EQ(psu.hasFanFault(), false); 1036 // Turn fault on. 1037 expectations.statusWordValue = (status_word::FAN_FAULT); 1038 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault) 1039 expectations.statusFans12Value = 0x80; 1040 setPMBusExpectations(mockPMBus, expectations); 1041 psu.analyze(); 1042 EXPECT_EQ(psu.hasFanFault(), true); 1043 // Back to no fault bits on in STATUS_WORD 1044 expectations.statusWordValue = 0; 1045 setPMBusExpectations(mockPMBus, expectations); 1046 psu.analyze(); 1047 EXPECT_EQ(psu.hasFanFault(), false); 1048 } 1049 1050 TEST_F(PowerSupplyTests, HasTempFault) 1051 { 1052 auto bus = sdbusplus::bus::new_default(); 1053 1054 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName}; 1055 MockedGPIOInterface* mockPresenceGPIO = 1056 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1057 // Always return 1 to indicate present. 1058 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1059 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1060 setMissingToPresentExpects(mockPMBus, mockedUtil); 1061 // STATUS_WORD 0x0000 is powered on, no faults. 1062 PMBusExpectations expectations; 1063 setPMBusExpectations(mockPMBus, expectations); 1064 psu.analyze(); 1065 EXPECT_EQ(psu.hasTempFault(), false); 1066 // Turn fault on. 1067 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN); 1068 // STATUS_TEMPERATURE fault bit on (OT Fault) 1069 expectations.statusTempValue = 0x80; 1070 setPMBusExpectations(mockPMBus, expectations); 1071 psu.analyze(); 1072 EXPECT_EQ(psu.hasTempFault(), true); 1073 // Back to no fault bits on in STATUS_WORD 1074 expectations.statusWordValue = 0; 1075 setPMBusExpectations(mockPMBus, expectations); 1076 psu.analyze(); 1077 EXPECT_EQ(psu.hasTempFault(), false); 1078 } 1079 1080 TEST_F(PowerSupplyTests, HasPgoodFault) 1081 { 1082 auto bus = sdbusplus::bus::new_default(); 1083 1084 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, PSUGPIOLineName}; 1085 MockedGPIOInterface* mockPresenceGPIO = 1086 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1087 // Always return 1 to indicate present. 1088 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1089 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1090 setMissingToPresentExpects(mockPMBus, mockedUtil); 1091 // STATUS_WORD 0x0000 is powered on, no faults. 1092 PMBusExpectations expectations; 1093 setPMBusExpectations(mockPMBus, expectations); 1094 psu.analyze(); 1095 EXPECT_EQ(psu.hasPgoodFault(), false); 1096 // Setup another expectation of no faults. 1097 setPMBusExpectations(mockPMBus, expectations); 1098 psu.analyze(); 1099 EXPECT_EQ(psu.hasPgoodFault(), false); 1100 // Turn PGOOD# off (fault on). 1101 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED); 1102 setPMBusExpectations(mockPMBus, expectations); 1103 psu.analyze(); 1104 // Expect false until reaches DEGLITCH_LIMIT 1105 EXPECT_EQ(psu.hasPgoodFault(), false); 1106 setPMBusExpectations(mockPMBus, expectations); 1107 psu.analyze(); 1108 // Expect false until reaches DEGLITCH_LIMIT 1109 EXPECT_EQ(psu.hasPgoodFault(), false); 1110 setPMBusExpectations(mockPMBus, expectations); 1111 psu.analyze(); 1112 // DEGLITCH_LIMIT reached, expect true. 1113 EXPECT_EQ(psu.hasPgoodFault(), true); 1114 // Back to no fault bits on in STATUS_WORD 1115 expectations.statusWordValue = 0; 1116 setPMBusExpectations(mockPMBus, expectations); 1117 psu.analyze(); 1118 EXPECT_EQ(psu.hasPgoodFault(), false); 1119 // Turn OFF bit on 1120 expectations.statusWordValue = (status_word::UNIT_IS_OFF); 1121 setPMBusExpectations(mockPMBus, expectations); 1122 psu.analyze(); 1123 EXPECT_EQ(psu.hasPgoodFault(), false); 1124 setPMBusExpectations(mockPMBus, expectations); 1125 psu.analyze(); 1126 EXPECT_EQ(psu.hasPgoodFault(), false); 1127 setPMBusExpectations(mockPMBus, expectations); 1128 psu.analyze(); 1129 EXPECT_EQ(psu.hasPgoodFault(), true); 1130 // Back to no fault bits on in STATUS_WORD 1131 expectations.statusWordValue = 0; 1132 setPMBusExpectations(mockPMBus, expectations); 1133 psu.analyze(); 1134 EXPECT_EQ(psu.hasPgoodFault(), false); 1135 } 1136 1137 TEST_F(PowerSupplyTests, HasPSKillFault) 1138 { 1139 auto bus = sdbusplus::bus::new_default(); 1140 PowerSupply psu{bus, PSUInventoryPath, 4, 0x6d, PSUGPIOLineName}; 1141 MockedGPIOInterface* mockPresenceGPIO = 1142 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1143 // Always return 1 to indicate present. 1144 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1145 psu.analyze(); 1146 EXPECT_EQ(psu.hasPSKillFault(), false); 1147 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1148 // STATUS_WORD 0x0000 is powered on, no faults. 1149 PMBusExpectations expectations; 1150 setPMBusExpectations(mockPMBus, expectations); 1151 psu.analyze(); 1152 EXPECT_EQ(psu.hasPSKillFault(), false); 1153 // Next return STATUS_WORD with MFR fault bit on. 1154 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1155 // STATUS_MFR_SPEFIC with bit(s) on. 1156 expectations.statusMFRValue = 0xFF; 1157 setPMBusExpectations(mockPMBus, expectations); 1158 psu.analyze(); 1159 EXPECT_EQ(psu.hasPSKillFault(), true); 1160 // Back to no bits on in STATUS_WORD 1161 expectations.statusWordValue = 0; 1162 setPMBusExpectations(mockPMBus, expectations); 1163 psu.analyze(); 1164 EXPECT_EQ(psu.hasPSKillFault(), false); 1165 // Next return STATUS_WORD with MFR fault bit on. 1166 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1167 // STATUS_MFR_SPEFIC with bit 4 on. 1168 expectations.statusMFRValue = 0x10; 1169 setPMBusExpectations(mockPMBus, expectations); 1170 psu.analyze(); 1171 EXPECT_EQ(psu.hasPSKillFault(), true); 1172 // Back to no bits on in STATUS_WORD 1173 expectations.statusWordValue = 0; 1174 setPMBusExpectations(mockPMBus, expectations); 1175 psu.analyze(); 1176 EXPECT_EQ(psu.hasPSKillFault(), false); 1177 } 1178 1179 TEST_F(PowerSupplyTests, HasPS12VcsFault) 1180 { 1181 auto bus = sdbusplus::bus::new_default(); 1182 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6e, PSUGPIOLineName}; 1183 MockedGPIOInterface* mockPresenceGPIO = 1184 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1185 // Always return 1 to indicate present. 1186 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1187 psu.analyze(); 1188 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1189 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1190 // STATUS_WORD 0x0000 is powered on, no faults. 1191 PMBusExpectations expectations; 1192 setPMBusExpectations(mockPMBus, expectations); 1193 psu.analyze(); 1194 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1195 // Next return STATUS_WORD with MFR fault bit on. 1196 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1197 // STATUS_MFR_SPEFIC with bit(s) on. 1198 expectations.statusMFRValue = 0xFF; 1199 setPMBusExpectations(mockPMBus, expectations); 1200 psu.analyze(); 1201 EXPECT_EQ(psu.hasPS12VcsFault(), true); 1202 // Back to no bits on in STATUS_WORD 1203 expectations.statusWordValue = 0; 1204 setPMBusExpectations(mockPMBus, expectations); 1205 psu.analyze(); 1206 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1207 // Next return STATUS_WORD with MFR fault bit on. 1208 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1209 // STATUS_MFR_SPEFIC with bit 6 on. 1210 expectations.statusMFRValue = 0x40; 1211 setPMBusExpectations(mockPMBus, expectations); 1212 psu.analyze(); 1213 EXPECT_EQ(psu.hasPS12VcsFault(), true); 1214 // Back to no bits on in STATUS_WORD 1215 expectations.statusWordValue = 0; 1216 setPMBusExpectations(mockPMBus, expectations); 1217 psu.analyze(); 1218 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1219 } 1220 1221 TEST_F(PowerSupplyTests, HasPSCS12VFault) 1222 { 1223 auto bus = sdbusplus::bus::new_default(); 1224 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f, PSUGPIOLineName}; 1225 MockedGPIOInterface* mockPresenceGPIO = 1226 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1227 // Always return 1 to indicate present. 1228 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1229 psu.analyze(); 1230 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1231 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1232 // STATUS_WORD 0x0000 is powered on, no faults. 1233 PMBusExpectations expectations; 1234 setPMBusExpectations(mockPMBus, expectations); 1235 psu.analyze(); 1236 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1237 // Next return STATUS_WORD with MFR fault bit on. 1238 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1239 // STATUS_MFR_SPEFIC with bit(s) on. 1240 expectations.statusMFRValue = 0xFF; 1241 setPMBusExpectations(mockPMBus, expectations); 1242 psu.analyze(); 1243 EXPECT_EQ(psu.hasPSCS12VFault(), true); 1244 // Back to no bits on in STATUS_WORD 1245 expectations.statusWordValue = 0; 1246 setPMBusExpectations(mockPMBus, expectations); 1247 psu.analyze(); 1248 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1249 // Next return STATUS_WORD with MFR fault bit on. 1250 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1251 // STATUS_MFR_SPEFIC with bit 7 on. 1252 expectations.statusMFRValue = 0x80; 1253 setPMBusExpectations(mockPMBus, expectations); 1254 psu.analyze(); 1255 EXPECT_EQ(psu.hasPSCS12VFault(), true); 1256 // Back to no bits on in STATUS_WORD 1257 expectations.statusWordValue = 0; 1258 setPMBusExpectations(mockPMBus, expectations); 1259 psu.analyze(); 1260 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1261 } 1262