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