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::IsNan; 19 using ::testing::NotNull; 20 using ::testing::Return; 21 using ::testing::StrEq; 22 23 static auto PSUInventoryPath = "/xyz/bmc/inv/sys/chassis/board/powersupply0"; 24 static auto PSUGPIOLineName = "presence-ps0"; 25 static auto isPowerOn = []() { return true; }; 26 27 struct PMBusExpectations 28 { 29 uint16_t statusWordValue{0x0000}; 30 uint8_t statusInputValue{0x00}; 31 uint8_t statusMFRValue{0x00}; 32 uint8_t statusCMLValue{0x00}; 33 uint8_t statusVOUTValue{0x00}; 34 uint8_t statusIOUTValue{0x00}; 35 uint8_t statusFans12Value{0x00}; 36 uint8_t statusTempValue{0x00}; 37 }; 38 39 // Helper function to setup expectations for various STATUS_* commands 40 void setPMBusExpectations(MockedPMBus& mockPMBus, 41 const PMBusExpectations& expectations) 42 { 43 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _, _)) 44 .Times(1) 45 .WillOnce(Return(expectations.statusWordValue)); 46 47 if (expectations.statusWordValue != 0) 48 { 49 // If fault bits are on in STATUS_WORD, there will also be a read of 50 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and 51 // STATUS_TEMPERATURE. 52 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _, _)) 53 .Times(1) 54 .WillOnce(Return(expectations.statusInputValue)); 55 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _, _)) 56 .Times(1) 57 .WillOnce(Return(expectations.statusMFRValue)); 58 EXPECT_CALL(mockPMBus, read(STATUS_CML, _, _)) 59 .Times(1) 60 .WillOnce(Return(expectations.statusCMLValue)); 61 // Page will need to be set to 0 to read STATUS_VOUT. 62 EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0)) 63 .Times(1) 64 .WillOnce(Return("status0_vout")); 65 EXPECT_CALL(mockPMBus, read("status0_vout", _, _)) 66 .Times(1) 67 .WillOnce(Return(expectations.statusVOUTValue)); 68 EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _, _)) 69 .Times(1) 70 .WillOnce(Return(expectations.statusIOUTValue)); 71 EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _, _)) 72 .Times(1) 73 .WillOnce(Return(expectations.statusFans12Value)); 74 EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _, _)) 75 .Times(1) 76 .WillOnce(Return(expectations.statusTempValue)); 77 } 78 79 // Default max/peak is 213W 80 ON_CALL(mockPMBus, readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug, 5)) 81 .WillByDefault( 82 Return(std::vector<uint8_t>{0x01, 0x5c, 0xf3, 0x54, 0xf3})); 83 } 84 85 class PowerSupplyTests : public ::testing::Test 86 { 87 public: 88 PowerSupplyTests() : 89 mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils())) 90 { 91 ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false)); 92 } 93 94 ~PowerSupplyTests() override 95 { 96 freeUtils(); 97 } 98 99 const MockedUtil& mockedUtil; 100 }; 101 102 // Helper function for when a power supply goes from missing to present. 103 void setMissingToPresentExpects(MockedPMBus& pmbus, const MockedUtil& util) 104 { 105 // Call to analyze() will update to present, that will trigger updating 106 // to the correct/latest HWMON directory, in case it changes. 107 EXPECT_CALL(pmbus, findHwmonDir()); 108 // Presence change from missing to present will trigger write to 109 // ON_OFF_CONFIG. 110 EXPECT_CALL(pmbus, writeBinary(ON_OFF_CONFIG, _, _)); 111 // Presence change from missing to present will trigger in1_input read 112 // in an attempt to get CLEAR_FAULTS called. 113 // This READ_VIN for CLEAR_FAULTS does not check the returned value. 114 EXPECT_CALL(pmbus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1)); 115 // The call for clearing faults includes clearing VIN_UV fault. 116 // The voltage defaults to 0, the first call to analyze should update the 117 // voltage to the current reading, triggering clearing VIN_UV fault(s) 118 // due to below minimum to within range voltage. 119 EXPECT_CALL(pmbus, read("in1_lcrit_alarm", _, _)) 120 .Times(2) 121 .WillRepeatedly(Return(1)); 122 // Missing/present call will update Presence in inventory. 123 EXPECT_CALL(util, setPresence(_, _, true, _)); 124 } 125 126 TEST_F(PowerSupplyTests, Constructor) 127 { 128 /** 129 * @param[in] invpath - String for inventory path to use 130 * @param[in] i2cbus - The bus number this power supply is on 131 * @param[in] i2caddr - The 16-bit I2C address of the power supply 132 * @param[in] gpioLineName - The string for the gpio-line-name to read for 133 * presence. 134 * @param[in] bindDelay - Time in milliseconds to delay binding the device 135 * driver after seeing the presence line go active. 136 */ 137 auto bus = sdbusplus::bus::new_default(); 138 139 // Try where inventory path is empty, constructor should fail. 140 try 141 { 142 auto psu = std::make_unique<PowerSupply>(bus, "", 3, 0x68, "ibm-cffps", 143 PSUGPIOLineName, isPowerOn); 144 ADD_FAILURE() << "Should not have reached this line."; 145 } 146 catch (const std::invalid_argument& e) 147 { 148 EXPECT_STREQ(e.what(), "Invalid empty inventoryPath"); 149 } 150 catch (...) 151 { 152 ADD_FAILURE() << "Should not have caught exception."; 153 } 154 155 // TODO: Try invalid i2c address? 156 157 // Try where gpioLineName is empty. 158 try 159 { 160 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, 161 "ibm-cffps", "", isPowerOn); 162 ADD_FAILURE() 163 << "Should not have reached this line. Invalid gpioLineName."; 164 } 165 catch (const std::invalid_argument& e) 166 { 167 EXPECT_STREQ(e.what(), "Invalid empty gpioLineName"); 168 } 169 catch (...) 170 { 171 ADD_FAILURE() << "Should not have caught exception."; 172 } 173 174 // Test with valid arguments 175 // NOT using D-Bus inventory path for presence. 176 try 177 { 178 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, 179 "ibm-cffps", PSUGPIOLineName, 180 isPowerOn); 181 182 EXPECT_EQ(psu->isPresent(), false); 183 EXPECT_EQ(psu->isFaulted(), false); 184 EXPECT_EQ(psu->hasCommFault(), false); 185 EXPECT_EQ(psu->hasInputFault(), false); 186 EXPECT_EQ(psu->hasMFRFault(), false); 187 EXPECT_EQ(psu->hasVINUVFault(), false); 188 EXPECT_EQ(psu->hasVoutOVFault(), false); 189 EXPECT_EQ(psu->hasIoutOCFault(), false); 190 EXPECT_EQ(psu->hasVoutUVFault(), false); 191 EXPECT_EQ(psu->hasFanFault(), false); 192 EXPECT_EQ(psu->hasTempFault(), false); 193 EXPECT_EQ(psu->hasPgoodFault(), false); 194 EXPECT_EQ(psu->hasPSKillFault(), false); 195 EXPECT_EQ(psu->hasPS12VcsFault(), false); 196 EXPECT_EQ(psu->hasPSCS12VFault(), false); 197 } 198 catch (...) 199 { 200 ADD_FAILURE() << "Should not have caught exception."; 201 } 202 203 // Test with valid arguments 204 // TODO: Using D-Bus inventory path for presence. 205 try 206 { 207 // FIXME: How do I get that presenceGPIO.read() in the startup to throw 208 // an exception? 209 210 // EXPECT_CALL(mockedUtil, getPresence(_, 211 // StrEq(PSUInventoryPath))) 212 // .Times(1); 213 } 214 catch (...) 215 { 216 ADD_FAILURE() << "Should not have caught exception."; 217 } 218 } 219 220 TEST_F(PowerSupplyTests, Analyze) 221 { 222 auto bus = sdbusplus::bus::new_default(); 223 224 { 225 // If I default to reading the GPIO, I will NOT expect a call to 226 // getPresence(). 227 228 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, 229 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 230 MockedGPIOInterface* mockPresenceGPIO = 231 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 232 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0)); 233 234 psu.analyze(); 235 // By default, nothing should change. 236 EXPECT_EQ(psu.isPresent(), false); 237 EXPECT_EQ(psu.isFaulted(), false); 238 EXPECT_EQ(psu.hasInputFault(), false); 239 EXPECT_EQ(psu.hasMFRFault(), false); 240 EXPECT_EQ(psu.hasVINUVFault(), false); 241 EXPECT_EQ(psu.hasCommFault(), false); 242 EXPECT_EQ(psu.hasVoutOVFault(), false); 243 EXPECT_EQ(psu.hasIoutOCFault(), false); 244 EXPECT_EQ(psu.hasVoutUVFault(), false); 245 EXPECT_EQ(psu.hasFanFault(), false); 246 EXPECT_EQ(psu.hasTempFault(), false); 247 EXPECT_EQ(psu.hasPgoodFault(), false); 248 EXPECT_EQ(psu.hasPSKillFault(), false); 249 EXPECT_EQ(psu.hasPS12VcsFault(), false); 250 EXPECT_EQ(psu.hasPSCS12VFault(), false); 251 } 252 253 PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, 254 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 255 // In order to get the various faults tested, the power supply needs to 256 // be present in order to read from the PMBus device(s). 257 MockedGPIOInterface* mockPresenceGPIO2 = 258 static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO()); 259 // Always return 1 to indicate present. 260 // Each analyze() call will trigger a read of the presence GPIO. 261 EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1)); 262 EXPECT_EQ(psu2.isPresent(), false); 263 264 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus()); 265 setMissingToPresentExpects(mockPMBus, mockedUtil); 266 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 267 // for INPUT_HISTORY will check max_power_out to see if it is 268 // old/unsupported power supply. Indicate good value, supported. 269 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 270 .WillRepeatedly(Return("2000")); 271 272 // STATUS_WORD INPUT fault. 273 { 274 // Start with STATUS_WORD 0x0000. Powered on, no faults. 275 // Set expectations for a no fault 276 PMBusExpectations expectations; 277 setPMBusExpectations(mockPMBus, expectations); 278 // After reading STATUS_WORD, etc., there will be a READ_VIN check. 279 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 280 .Times(1) 281 .WillOnce(Return("206000")); 282 psu2.analyze(); 283 EXPECT_EQ(psu2.isPresent(), true); 284 EXPECT_EQ(psu2.isFaulted(), false); 285 EXPECT_EQ(psu2.hasInputFault(), false); 286 EXPECT_EQ(psu2.hasMFRFault(), false); 287 EXPECT_EQ(psu2.hasVINUVFault(), false); 288 EXPECT_EQ(psu2.hasCommFault(), false); 289 EXPECT_EQ(psu2.hasVoutOVFault(), false); 290 EXPECT_EQ(psu2.hasIoutOCFault(), false); 291 EXPECT_EQ(psu2.hasVoutUVFault(), false); 292 EXPECT_EQ(psu2.hasFanFault(), false); 293 EXPECT_EQ(psu2.hasTempFault(), false); 294 EXPECT_EQ(psu2.hasPgoodFault(), false); 295 EXPECT_EQ(psu2.hasPSKillFault(), false); 296 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 297 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 298 299 // Update expectations for STATUS_WORD input fault/warn 300 // STATUS_INPUT fault bits ... on. 301 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN); 302 // IIN_OC fault. 303 expectations.statusInputValue = 0x04; 304 305 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 306 { 307 setPMBusExpectations(mockPMBus, expectations); 308 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 309 .Times(1) 310 .WillOnce(Return("207000")); 311 psu2.analyze(); 312 EXPECT_EQ(psu2.isPresent(), true); 313 // Should not be faulted until it reaches the deglitch limit. 314 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 315 EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT); 316 EXPECT_EQ(psu2.hasMFRFault(), false); 317 EXPECT_EQ(psu2.hasVINUVFault(), false); 318 EXPECT_EQ(psu2.hasCommFault(), false); 319 EXPECT_EQ(psu2.hasVoutOVFault(), false); 320 EXPECT_EQ(psu2.hasIoutOCFault(), false); 321 EXPECT_EQ(psu2.hasVoutUVFault(), false); 322 EXPECT_EQ(psu2.hasFanFault(), false); 323 EXPECT_EQ(psu2.hasTempFault(), false); 324 EXPECT_EQ(psu2.hasPgoodFault(), false); 325 EXPECT_EQ(psu2.hasPSKillFault(), false); 326 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 327 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 328 } 329 } 330 331 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1)); 332 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 333 .Times(1) 334 .WillOnce(Return(1)); 335 psu2.clearFaults(); 336 337 // STATUS_WORD INPUT/UV fault. 338 { 339 // First need it to return good status, then the fault 340 PMBusExpectations expectations; 341 setPMBusExpectations(mockPMBus, expectations); 342 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 343 .Times(1) 344 .WillOnce(Return("208000")); 345 psu2.analyze(); 346 EXPECT_EQ(psu2.isFaulted(), false); 347 EXPECT_EQ(psu2.hasInputFault(), false); 348 // Now set fault bits in STATUS_WORD 349 expectations.statusWordValue = 350 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT); 351 // STATUS_INPUT fault bits ... on. 352 expectations.statusInputValue = 0x18; 353 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 354 { 355 setPMBusExpectations(mockPMBus, expectations); 356 // Input/UV fault, so voltage should read back low. 357 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 358 .Times(1) 359 .WillOnce(Return("19123")); 360 psu2.analyze(); 361 EXPECT_EQ(psu2.isPresent(), true); 362 // Only faulted if hit deglitch limit 363 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 364 EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT); 365 EXPECT_EQ(psu2.hasVINUVFault(), x >= DEGLITCH_LIMIT); 366 EXPECT_EQ(psu2.hasMFRFault(), false); 367 EXPECT_EQ(psu2.hasCommFault(), false); 368 EXPECT_EQ(psu2.hasVoutOVFault(), false); 369 EXPECT_EQ(psu2.hasIoutOCFault(), false); 370 EXPECT_EQ(psu2.hasVoutUVFault(), false); 371 EXPECT_EQ(psu2.hasFanFault(), false); 372 EXPECT_EQ(psu2.hasTempFault(), false); 373 EXPECT_EQ(psu2.hasPgoodFault(), false); 374 EXPECT_EQ(psu2.hasPSKillFault(), false); 375 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 376 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 377 } 378 // Turning VIN_UV fault off causes clearing of faults, causing read of 379 // in1_input as an attempt to get CLEAR_FAULTS called. 380 expectations.statusWordValue = 0; 381 setPMBusExpectations(mockPMBus, expectations); 382 // The call to read the voltage 383 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 384 .Times(1) 385 .WillOnce(Return("209000")); 386 // The call to clear VIN_UV/Off fault(s) 387 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 388 .Times(1) 389 .WillOnce(Return(1)); 390 psu2.analyze(); 391 // Should remain present, no longer be faulted, no input fault, no 392 // VIN_UV fault. Nothing else should change. 393 EXPECT_EQ(psu2.isPresent(), true); 394 EXPECT_EQ(psu2.isFaulted(), false); 395 EXPECT_EQ(psu2.hasInputFault(), false); 396 EXPECT_EQ(psu2.hasVINUVFault(), false); 397 } 398 399 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1)); 400 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 401 .Times(1) 402 .WillOnce(Return(1)); 403 psu2.clearFaults(); 404 405 // STATUS_WORD MFR fault. 406 { 407 // First need it to return good status, then the fault 408 PMBusExpectations expectations; 409 setPMBusExpectations(mockPMBus, expectations); 410 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 411 .Times(1) 412 .WillOnce(Return("210000")); 413 psu2.analyze(); 414 // Now STATUS_WORD with MFR fault bit on. 415 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 416 // STATUS_MFR bits on. 417 expectations.statusMFRValue = 0xFF; 418 419 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 420 { 421 setPMBusExpectations(mockPMBus, expectations); 422 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 423 .Times(1) 424 .WillOnce(Return("211000")); 425 psu2.analyze(); 426 EXPECT_EQ(psu2.isPresent(), true); 427 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 428 EXPECT_EQ(psu2.hasInputFault(), false); 429 EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT); 430 EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT); 431 EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT); 432 EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT); 433 EXPECT_EQ(psu2.hasVINUVFault(), false); 434 EXPECT_EQ(psu2.hasCommFault(), false); 435 EXPECT_EQ(psu2.hasVoutOVFault(), false); 436 EXPECT_EQ(psu2.hasIoutOCFault(), false); 437 EXPECT_EQ(psu2.hasVoutUVFault(), false); 438 EXPECT_EQ(psu2.hasFanFault(), false); 439 EXPECT_EQ(psu2.hasTempFault(), false); 440 EXPECT_EQ(psu2.hasPgoodFault(), false); 441 } 442 } 443 444 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1)); 445 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 446 .Times(1) 447 .WillOnce(Return(1)); 448 psu2.clearFaults(); 449 450 // Temperature fault. 451 { 452 // First STATUS_WORD with no bits set, then with temperature fault. 453 PMBusExpectations expectations; 454 setPMBusExpectations(mockPMBus, expectations); 455 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 456 .Times(1) 457 .WillOnce(Return("212000")); 458 psu2.analyze(); 459 // STATUS_WORD with temperature fault bit on. 460 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN); 461 // STATUS_TEMPERATURE with fault bit(s) on. 462 expectations.statusTempValue = 0x10; 463 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 464 { 465 setPMBusExpectations(mockPMBus, expectations); 466 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 467 .Times(1) 468 .WillOnce(Return("213000")); 469 psu2.analyze(); 470 EXPECT_EQ(psu2.isPresent(), true); 471 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 472 EXPECT_EQ(psu2.hasInputFault(), false); 473 EXPECT_EQ(psu2.hasMFRFault(), false); 474 EXPECT_EQ(psu2.hasVINUVFault(), false); 475 EXPECT_EQ(psu2.hasCommFault(), false); 476 EXPECT_EQ(psu2.hasVoutOVFault(), false); 477 EXPECT_EQ(psu2.hasIoutOCFault(), false); 478 EXPECT_EQ(psu2.hasVoutUVFault(), false); 479 EXPECT_EQ(psu2.hasFanFault(), false); 480 EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT); 481 EXPECT_EQ(psu2.hasPgoodFault(), false); 482 EXPECT_EQ(psu2.hasPSKillFault(), false); 483 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 484 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 485 } 486 } 487 488 // VOUT_OV_FAULT fault 489 { 490 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault. 491 PMBusExpectations expectations; 492 setPMBusExpectations(mockPMBus, expectations); 493 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 494 .Times(1) 495 .WillOnce(Return("216000")); 496 psu2.analyze(); 497 // STATUS_WORD with VOUT/VOUT_OV fault. 498 expectations.statusWordValue = 499 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT)); 500 // Turn on STATUS_VOUT fault bit(s) 501 expectations.statusVOUTValue = 0xA0; 502 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 503 { 504 // STATUS_TEMPERATURE don't care (default) 505 setPMBusExpectations(mockPMBus, expectations); 506 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 507 .Times(1) 508 .WillOnce(Return("217000")); 509 psu2.analyze(); 510 EXPECT_EQ(psu2.isPresent(), true); 511 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 512 EXPECT_EQ(psu2.hasInputFault(), false); 513 EXPECT_EQ(psu2.hasMFRFault(), false); 514 EXPECT_EQ(psu2.hasVINUVFault(), false); 515 EXPECT_EQ(psu2.hasCommFault(), false); 516 EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT); 517 EXPECT_EQ(psu2.hasVoutUVFault(), false); 518 EXPECT_EQ(psu2.hasIoutOCFault(), false); 519 EXPECT_EQ(psu2.hasFanFault(), false); 520 EXPECT_EQ(psu2.hasTempFault(), false); 521 EXPECT_EQ(psu2.hasPgoodFault(), false); 522 EXPECT_EQ(psu2.hasPSKillFault(), false); 523 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 524 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 525 } 526 } 527 528 // IOUT_OC_FAULT fault 529 { 530 // First STATUS_WORD with no bits set, then with IOUT_OC fault. 531 PMBusExpectations expectations; 532 setPMBusExpectations(mockPMBus, expectations); 533 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 534 .Times(1) 535 .WillOnce(Return("218000")); 536 psu2.analyze(); 537 // STATUS_WORD with IOUT_OC fault. 538 expectations.statusWordValue = status_word::IOUT_OC_FAULT; 539 // Turn on STATUS_IOUT fault bit(s) 540 expectations.statusIOUTValue = 0x88; 541 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 542 { 543 setPMBusExpectations(mockPMBus, expectations); 544 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 545 .Times(1) 546 .WillOnce(Return("219000")); 547 psu2.analyze(); 548 EXPECT_EQ(psu2.isPresent(), true); 549 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 550 EXPECT_EQ(psu2.hasInputFault(), false); 551 EXPECT_EQ(psu2.hasMFRFault(), false); 552 EXPECT_EQ(psu2.hasVINUVFault(), false); 553 EXPECT_EQ(psu2.hasCommFault(), false); 554 EXPECT_EQ(psu2.hasVoutOVFault(), false); 555 EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT); 556 EXPECT_EQ(psu2.hasVoutUVFault(), false); 557 EXPECT_EQ(psu2.hasFanFault(), false); 558 EXPECT_EQ(psu2.hasTempFault(), false); 559 EXPECT_EQ(psu2.hasPgoodFault(), false); 560 EXPECT_EQ(psu2.hasPSKillFault(), false); 561 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 562 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 563 } 564 } 565 566 // VOUT_UV_FAULT 567 { 568 // First STATUS_WORD with no bits set, then with VOUT fault. 569 PMBusExpectations expectations; 570 setPMBusExpectations(mockPMBus, expectations); 571 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 572 .Times(1) 573 .WillOnce(Return("220000")); 574 psu2.analyze(); 575 // Change STATUS_WORD to indicate VOUT fault. 576 expectations.statusWordValue = (status_word::VOUT_FAULT); 577 // Turn on STATUS_VOUT fault bit(s) 578 expectations.statusVOUTValue = 0x30; 579 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 580 { 581 setPMBusExpectations(mockPMBus, expectations); 582 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 583 .Times(1) 584 .WillOnce(Return("221000")); 585 psu2.analyze(); 586 EXPECT_EQ(psu2.isPresent(), true); 587 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 588 EXPECT_EQ(psu2.hasInputFault(), false); 589 EXPECT_EQ(psu2.hasMFRFault(), false); 590 EXPECT_EQ(psu2.hasVINUVFault(), false); 591 EXPECT_EQ(psu2.hasCommFault(), false); 592 EXPECT_EQ(psu2.hasVoutOVFault(), false); 593 EXPECT_EQ(psu2.hasIoutOCFault(), false); 594 EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT); 595 EXPECT_EQ(psu2.hasFanFault(), false); 596 EXPECT_EQ(psu2.hasTempFault(), false); 597 EXPECT_EQ(psu2.hasPgoodFault(), false); 598 EXPECT_EQ(psu2.hasPSKillFault(), false); 599 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 600 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 601 } 602 } 603 604 // Fan fault 605 { 606 // First STATUS_WORD with no bits set, then with fan fault. 607 PMBusExpectations expectations; 608 setPMBusExpectations(mockPMBus, expectations); 609 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 610 .Times(1) 611 .WillOnce(Return("222000")); 612 psu2.analyze(); 613 expectations.statusWordValue = (status_word::FAN_FAULT); 614 // STATUS_FANS_1_2 with fan 1 warning & fault bits on. 615 expectations.statusFans12Value = 0xA0; 616 617 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 618 { 619 setPMBusExpectations(mockPMBus, expectations); 620 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 621 .Times(1) 622 .WillOnce(Return("223000")); 623 psu2.analyze(); 624 EXPECT_EQ(psu2.isPresent(), true); 625 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 626 EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT); 627 EXPECT_EQ(psu2.hasInputFault(), false); 628 EXPECT_EQ(psu2.hasMFRFault(), false); 629 EXPECT_EQ(psu2.hasVINUVFault(), false); 630 EXPECT_EQ(psu2.hasCommFault(), false); 631 EXPECT_EQ(psu2.hasVoutOVFault(), false); 632 EXPECT_EQ(psu2.hasIoutOCFault(), false); 633 EXPECT_EQ(psu2.hasVoutUVFault(), false); 634 EXPECT_EQ(psu2.hasTempFault(), false); 635 EXPECT_EQ(psu2.hasPgoodFault(), false); 636 EXPECT_EQ(psu2.hasPSKillFault(), false); 637 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 638 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 639 } 640 } 641 642 // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT. 643 { 644 // First STATUS_WORD with no bits set. 645 PMBusExpectations expectations; 646 setPMBusExpectations(mockPMBus, expectations); 647 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 648 .Times(1) 649 .WillOnce(Return("123000")); 650 psu2.analyze(); 651 EXPECT_EQ(psu2.isFaulted(), false); 652 // POWER_GOOD# inactive, and OFF bit on. 653 expectations.statusWordValue = 654 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF)); 655 for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++) 656 { 657 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and 658 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults). 659 setPMBusExpectations(mockPMBus, expectations); 660 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 661 .Times(1) 662 .WillOnce(Return("124000")); 663 psu2.analyze(); 664 EXPECT_EQ(psu2.isPresent(), true); 665 EXPECT_EQ(psu2.isFaulted(), x >= PGOOD_DEGLITCH_LIMIT); 666 EXPECT_EQ(psu2.hasInputFault(), false); 667 EXPECT_EQ(psu2.hasMFRFault(), false); 668 EXPECT_EQ(psu2.hasVINUVFault(), false); 669 EXPECT_EQ(psu2.hasCommFault(), false); 670 EXPECT_EQ(psu2.hasVoutOVFault(), false); 671 EXPECT_EQ(psu2.hasVoutUVFault(), false); 672 EXPECT_EQ(psu2.hasIoutOCFault(), false); 673 EXPECT_EQ(psu2.hasFanFault(), false); 674 EXPECT_EQ(psu2.hasTempFault(), false); 675 EXPECT_EQ(psu2.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT); 676 } 677 } 678 679 // TODO: ReadFailure 680 } 681 682 TEST_F(PowerSupplyTests, OnOffConfig) 683 { 684 auto bus = sdbusplus::bus::new_default(); 685 uint8_t data = 0x15; 686 687 // Test where PSU is NOT present 688 try 689 { 690 // Assume GPIO presence, not inventory presence? 691 EXPECT_CALL(mockedUtil, setAvailable(_, _, _)).Times(0); 692 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, 693 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 694 695 MockedGPIOInterface* mockPresenceGPIO = 696 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 697 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0)); 698 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 699 // Constructor should set initial presence, default read returns 0. 700 // If it is not present, I should not be trying to write to it. 701 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0); 702 psu.onOffConfig(data); 703 } 704 catch (...) 705 {} 706 707 // Test where PSU is present 708 try 709 { 710 // Assume GPIO presence, not inventory presence? 711 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 712 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, 713 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 714 MockedGPIOInterface* mockPresenceGPIO = 715 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 716 // There will potentially be multiple calls, we want it to continue 717 // returning 1 for the GPIO read to keep the power supply present. 718 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 719 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 720 setMissingToPresentExpects(mockPMBus, mockedUtil); 721 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 722 // for INPUT_HISTORY will check max_power_out to see if it is 723 // old/unsupported power supply. Indicate good value, supported. 724 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 725 .WillRepeatedly(Return("2000")); 726 // If I am calling analyze(), I should probably give it good data. 727 // STATUS_WORD 0x0000 is powered on, no faults. 728 PMBusExpectations expectations; 729 setPMBusExpectations(mockPMBus, expectations); 730 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 731 .Times(1) 732 .WillOnce(Return("205000")); 733 psu.analyze(); 734 // I definitely should be writting ON_OFF_CONFIG if I call the function 735 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15), 736 Type::HwmonDeviceDebug)) 737 .Times(1); 738 psu.onOffConfig(data); 739 } 740 catch (...) 741 {} 742 } 743 744 TEST_F(PowerSupplyTests, ClearFaults) 745 { 746 auto bus = sdbusplus::bus::new_default(); 747 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, 748 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 749 MockedGPIOInterface* mockPresenceGPIO = 750 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 751 // Always return 1 to indicate present. 752 // Each analyze() call will trigger a read of the presence GPIO. 753 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 754 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 755 setMissingToPresentExpects(mockPMBus, mockedUtil); 756 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 757 // for INPUT_HISTORY will check max_power_out to see if it is 758 // old/unsupported power supply. Indicate good value, supported. 759 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 760 .WillRepeatedly(Return("2000")); 761 // STATUS_WORD 0x0000 is powered on, no faults. 762 PMBusExpectations expectations; 763 setPMBusExpectations(mockPMBus, expectations); 764 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 765 .Times(1) 766 .WillOnce(Return("207000")); 767 psu.analyze(); 768 EXPECT_EQ(psu.isPresent(), true); 769 EXPECT_EQ(psu.isFaulted(), false); 770 EXPECT_EQ(psu.hasInputFault(), false); 771 EXPECT_EQ(psu.hasMFRFault(), false); 772 EXPECT_EQ(psu.hasVINUVFault(), false); 773 EXPECT_EQ(psu.hasCommFault(), false); 774 EXPECT_EQ(psu.hasVoutOVFault(), false); 775 EXPECT_EQ(psu.hasIoutOCFault(), false); 776 EXPECT_EQ(psu.hasVoutUVFault(), false); 777 EXPECT_EQ(psu.hasFanFault(), false); 778 EXPECT_EQ(psu.hasTempFault(), false); 779 EXPECT_EQ(psu.hasPgoodFault(), false); 780 EXPECT_EQ(psu.hasPSKillFault(), false); 781 EXPECT_EQ(psu.hasPS12VcsFault(), false); 782 EXPECT_EQ(psu.hasPSCS12VFault(), false); 783 784 // STATUS_WORD with fault bits galore! 785 expectations.statusWordValue = 0xFFFF; 786 // STATUS_INPUT with fault bits on. 787 expectations.statusInputValue = 0xFF; 788 // STATUS_MFR_SPEFIC with bits on. 789 expectations.statusMFRValue = 0xFF; 790 // STATUS_CML with bits on. 791 expectations.statusCMLValue = 0xFF; 792 // STATUS_VOUT with bits on. 793 expectations.statusVOUTValue = 0xFF; 794 // STATUS_IOUT with bits on. 795 expectations.statusIOUTValue = 0xFF; 796 // STATUS_FANS_1_2 with bits on. 797 expectations.statusFans12Value = 0xFF; 798 // STATUS_TEMPERATURE with bits on. 799 expectations.statusTempValue = 0xFF; 800 801 for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++) 802 { 803 setPMBusExpectations(mockPMBus, expectations); 804 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 805 .Times(1) 806 .WillOnce(Return("0")); 807 if (x == DEGLITCH_LIMIT) 808 { 809 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 810 } 811 psu.analyze(); 812 EXPECT_EQ(psu.isPresent(), true); 813 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT. 814 // Rely on HasVoutUVFault() to verify this sets and clears. 815 EXPECT_EQ(psu.hasVoutUVFault(), false); 816 // pgoodFault at PGOOD_DEGLITCH_LIMIT, all other faults are deglitched 817 // up to DEGLITCH_LIMIT 818 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT); 819 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT); 820 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT); 821 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT); 822 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT); 823 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT); 824 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT); 825 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT); 826 EXPECT_EQ(psu.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT); 827 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT); 828 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT); 829 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT); 830 } 831 832 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)) 833 .Times(1) 834 .WillOnce(Return(207000)); 835 // Clearing VIN_UV fault via in1_lcrit_alarm 836 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 837 .Times(1) 838 .WillOnce(Return(1)); 839 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 840 psu.clearFaults(); 841 EXPECT_EQ(psu.isPresent(), true); 842 EXPECT_EQ(psu.isFaulted(), false); 843 EXPECT_EQ(psu.hasInputFault(), false); 844 EXPECT_EQ(psu.hasMFRFault(), false); 845 EXPECT_EQ(psu.hasVINUVFault(), false); 846 EXPECT_EQ(psu.hasCommFault(), false); 847 EXPECT_EQ(psu.hasVoutOVFault(), false); 848 EXPECT_EQ(psu.hasIoutOCFault(), false); 849 EXPECT_EQ(psu.hasVoutUVFault(), false); 850 EXPECT_EQ(psu.hasFanFault(), false); 851 EXPECT_EQ(psu.hasTempFault(), false); 852 EXPECT_EQ(psu.hasPgoodFault(), false); 853 EXPECT_EQ(psu.hasPSKillFault(), false); 854 EXPECT_EQ(psu.hasPS12VcsFault(), false); 855 EXPECT_EQ(psu.hasPSCS12VFault(), false); 856 857 // Faults clear on READ_VIN 0 -> !0 858 // STATUS_WORD with fault bits galore! 859 expectations.statusWordValue = 0xFFFF; 860 // STATUS_INPUT with fault bits on. 861 expectations.statusInputValue = 0xFF; 862 // STATUS_MFR_SPEFIC with bits on. 863 expectations.statusMFRValue = 0xFF; 864 // STATUS_CML with bits on. 865 expectations.statusCMLValue = 0xFF; 866 // STATUS_VOUT with bits on. 867 expectations.statusVOUTValue = 0xFF; 868 // STATUS_IOUT with bits on. 869 expectations.statusIOUTValue = 0xFF; 870 // STATUS_FANS_1_2 with bits on. 871 expectations.statusFans12Value = 0xFF; 872 // STATUS_TEMPERATURE with bits on. 873 expectations.statusTempValue = 0xFF; 874 875 // All faults deglitched now. Check for false before limit above. 876 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 877 { 878 setPMBusExpectations(mockPMBus, expectations); 879 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 880 .Times(1) 881 .WillOnce(Return("0")); 882 if (x == DEGLITCH_LIMIT) 883 { 884 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 885 } 886 psu.analyze(); 887 } 888 889 EXPECT_EQ(psu.isPresent(), true); 890 EXPECT_EQ(psu.isFaulted(), true); 891 EXPECT_EQ(psu.hasInputFault(), true); 892 EXPECT_EQ(psu.hasMFRFault(), true); 893 EXPECT_EQ(psu.hasVINUVFault(), true); 894 EXPECT_EQ(psu.hasCommFault(), false); 895 EXPECT_EQ(psu.hasVoutOVFault(), true); 896 EXPECT_EQ(psu.hasIoutOCFault(), true); 897 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT. 898 // Rely on HasVoutUVFault() to verify this sets and clears. 899 EXPECT_EQ(psu.hasVoutUVFault(), false); 900 EXPECT_EQ(psu.hasFanFault(), true); 901 EXPECT_EQ(psu.hasTempFault(), true); 902 // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT 903 EXPECT_EQ(psu.hasPgoodFault(), false); 904 EXPECT_EQ(psu.hasPSKillFault(), true); 905 EXPECT_EQ(psu.hasPS12VcsFault(), true); 906 EXPECT_EQ(psu.hasPSCS12VFault(), true); 907 // STATUS_WORD with INPUT/VIN_UV fault bits off. 908 expectations.statusWordValue = 0xDFF7; 909 // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For 910 // Insufficient Input Voltage bits off. 911 expectations.statusInputValue = 0xC7; 912 setPMBusExpectations(mockPMBus, expectations); 913 // READ_VIN back in range. 914 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 915 .Times(1) 916 .WillOnce(Return("206000")); 917 // VIN_UV cleared via in1_lcrit_alarm when voltage back in range. 918 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 919 .Times(1) 920 .WillOnce(Return(1)); 921 psu.analyze(); 922 // We only cleared the VIN_UV and OFF faults. 923 EXPECT_EQ(psu.isPresent(), true); 924 EXPECT_EQ(psu.isFaulted(), true); 925 EXPECT_EQ(psu.hasInputFault(), false); 926 EXPECT_EQ(psu.hasMFRFault(), true); 927 EXPECT_EQ(psu.hasVINUVFault(), false); 928 EXPECT_EQ(psu.hasCommFault(), false); 929 EXPECT_EQ(psu.hasVoutOVFault(), true); 930 EXPECT_EQ(psu.hasIoutOCFault(), true); 931 EXPECT_EQ(psu.hasVoutUVFault(), false); 932 EXPECT_EQ(psu.hasFanFault(), true); 933 EXPECT_EQ(psu.hasTempFault(), true); 934 // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT 935 EXPECT_EQ(psu.hasPgoodFault(), false); 936 EXPECT_EQ(psu.hasPSKillFault(), true); 937 EXPECT_EQ(psu.hasPS12VcsFault(), true); 938 EXPECT_EQ(psu.hasPSCS12VFault(), true); 939 940 // All faults cleared 941 expectations = {0}; 942 setPMBusExpectations(mockPMBus, expectations); 943 // READ_VIN back in range. 944 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 945 .Times(1) 946 .WillOnce(Return("206000")); 947 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 948 psu.analyze(); 949 EXPECT_EQ(psu.isPresent(), true); 950 EXPECT_EQ(psu.isFaulted(), false); 951 EXPECT_EQ(psu.hasInputFault(), false); 952 EXPECT_EQ(psu.hasMFRFault(), false); 953 EXPECT_EQ(psu.hasVINUVFault(), false); 954 EXPECT_EQ(psu.hasCommFault(), false); 955 EXPECT_EQ(psu.hasVoutOVFault(), false); 956 EXPECT_EQ(psu.hasIoutOCFault(), false); 957 EXPECT_EQ(psu.hasVoutUVFault(), false); 958 EXPECT_EQ(psu.hasFanFault(), false); 959 EXPECT_EQ(psu.hasTempFault(), false); 960 EXPECT_EQ(psu.hasPgoodFault(), false); 961 EXPECT_EQ(psu.hasPSKillFault(), false); 962 EXPECT_EQ(psu.hasPS12VcsFault(), false); 963 EXPECT_EQ(psu.hasPSCS12VFault(), false); 964 965 // TODO: Faults clear on missing/present? 966 } 967 968 TEST_F(PowerSupplyTests, UpdateInventory) 969 { 970 auto bus = sdbusplus::bus::new_default(); 971 972 try 973 { 974 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, 975 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 976 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 977 // If it is not present, I should not be trying to read a string 978 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0); 979 psu.updateInventory(); 980 } 981 catch (...) 982 { 983 ADD_FAILURE() << "Should not have caught exception."; 984 } 985 986 try 987 { 988 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, 989 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 990 MockedGPIOInterface* mockPresenceGPIO = 991 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 992 // GPIO read return 1 to indicate present. 993 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1)); 994 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 995 setMissingToPresentExpects(mockPMBus, mockedUtil); 996 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 997 // for INPUT_HISTORY will check max_power_out to see if it is 998 // old/unsupported power supply. Indicate good value, supported. 999 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1000 .WillRepeatedly(Return("2000")); 1001 // STATUS_WORD 0x0000 is powered on, no faults. 1002 PMBusExpectations expectations; 1003 setPMBusExpectations(mockPMBus, expectations); 1004 // Call to analyze will read voltage, trigger clear faults for 0 to 1005 // within range. 1006 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1007 .Times(1) 1008 .WillOnce(Return("123456")); 1009 psu.analyze(); 1010 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return("")); 1011 psu.updateInventory(); 1012 1013 #if IBM_VPD 1014 EXPECT_CALL(mockPMBus, readString(_, _)) 1015 .WillOnce(Return("CCIN")) 1016 .WillOnce(Return("PN3456")) 1017 .WillOnce(Return("FN3456")) 1018 .WillOnce(Return("HEADER")) 1019 .WillOnce(Return("SN3456")) 1020 .WillOnce(Return("FW3456")); 1021 #endif 1022 psu.updateInventory(); 1023 // TODO: D-Bus mocking to verify values stored on D-Bus (???) 1024 } 1025 catch (...) 1026 { 1027 ADD_FAILURE() << "Should not have caught exception."; 1028 } 1029 } 1030 1031 TEST_F(PowerSupplyTests, IsPresent) 1032 { 1033 auto bus = sdbusplus::bus::new_default(); 1034 1035 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, 1036 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1037 MockedGPIOInterface* mockPresenceGPIO = 1038 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1039 EXPECT_EQ(psu.isPresent(), false); 1040 1041 // Change GPIO read to return 1 to indicate present. 1042 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1)); 1043 // Call to analyze() will update to present, that will trigger updating 1044 // to the correct/latest HWMON directory, in case it changes. 1045 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1046 setMissingToPresentExpects(mockPMBus, mockedUtil); 1047 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1048 // for INPUT_HISTORY will check max_power_out to see if it is 1049 // old/unsupported power supply. Indicate good value, supported. 1050 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1051 .WillRepeatedly(Return("2000")); 1052 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN. 1053 // Default expectations will be on, no faults. 1054 PMBusExpectations expectations; 1055 setPMBusExpectations(mockPMBus, expectations); 1056 // Give it an input voltage in the 100-volt range. 1057 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1058 .Times(1) 1059 .WillOnce(Return("123456")); 1060 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1061 psu.analyze(); 1062 EXPECT_EQ(psu.isPresent(), true); 1063 } 1064 1065 TEST_F(PowerSupplyTests, IsFaulted) 1066 { 1067 auto bus = sdbusplus::bus::new_default(); 1068 1069 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, 1070 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1071 MockedGPIOInterface* mockPresenceGPIO = 1072 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1073 // Always return 1 to indicate present. 1074 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1075 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1076 setMissingToPresentExpects(mockPMBus, mockedUtil); 1077 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1078 // for INPUT_HISTORY will check max_power_out to see if it is 1079 // old/unsupported power supply. Indicate good value, supported. 1080 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1081 .WillRepeatedly(Return("2000")); 1082 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN. 1083 // Default expectations will be on, no faults. 1084 PMBusExpectations expectations; 1085 setPMBusExpectations(mockPMBus, expectations); 1086 // Give it an input voltage in the 100-volt range. 1087 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1088 .Times(1) 1089 .WillOnce(Return("124680")); 1090 psu.analyze(); 1091 EXPECT_EQ(psu.isFaulted(), false); 1092 // STATUS_WORD with fault bits on. 1093 expectations.statusWordValue = 0xFFFF; 1094 // STATUS_INPUT with fault bits on. 1095 expectations.statusInputValue = 0xFF; 1096 // STATUS_MFR_SPECIFIC with faults bits on. 1097 expectations.statusMFRValue = 0xFF; 1098 // STATUS_CML with faults bits on. 1099 expectations.statusCMLValue = 0xFF; 1100 // STATUS_VOUT with fault bits on. 1101 expectations.statusVOUTValue = 0xFF; 1102 // STATUS_IOUT with fault bits on. 1103 expectations.statusIOUTValue = 0xFF; 1104 // STATUS_FANS_1_2 with bits on. 1105 expectations.statusFans12Value = 0xFF; 1106 // STATUS_TEMPERATURE with fault bits on. 1107 expectations.statusTempValue = 0xFF; 1108 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1109 { 1110 setPMBusExpectations(mockPMBus, expectations); 1111 // Also get another read of READ_VIN, faulted, so not in 100-volt range 1112 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1113 .Times(1) 1114 .WillOnce(Return("19000")); 1115 if (x == DEGLITCH_LIMIT) 1116 { 1117 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1118 } 1119 psu.analyze(); 1120 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT); 1121 } 1122 } 1123 1124 TEST_F(PowerSupplyTests, HasInputFault) 1125 { 1126 auto bus = sdbusplus::bus::new_default(); 1127 1128 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, 1129 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1130 MockedGPIOInterface* mockPresenceGPIO = 1131 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1132 // Always return 1 to indicate present. 1133 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1134 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1135 setMissingToPresentExpects(mockPMBus, mockedUtil); 1136 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1137 // for INPUT_HISTORY will check max_power_out to see if it is 1138 // old/unsupported power supply. Indicate good value, supported. 1139 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1140 .WillRepeatedly(Return("2000")); 1141 // STATUS_WORD 0x0000 is powered on, no faults. 1142 PMBusExpectations expectations; 1143 setPMBusExpectations(mockPMBus, expectations); 1144 // Analyze call will also need good READ_VIN value to check. 1145 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1146 .Times(1) 1147 .WillOnce(Return("201100")); 1148 psu.analyze(); 1149 EXPECT_EQ(psu.hasInputFault(), false); 1150 // STATUS_WORD with input fault/warn on. 1151 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN); 1152 // STATUS_INPUT with an input fault bit on. 1153 expectations.statusInputValue = 0x80; 1154 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1155 { 1156 setPMBusExpectations(mockPMBus, expectations); 1157 // Analyze call will also need good READ_VIN value to check. 1158 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1159 .Times(1) 1160 .WillOnce(Return("201200")); 1161 if (x == DEGLITCH_LIMIT) 1162 { 1163 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1164 } 1165 psu.analyze(); 1166 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT); 1167 } 1168 // STATUS_WORD with no bits on. 1169 expectations.statusWordValue = 0; 1170 setPMBusExpectations(mockPMBus, expectations); 1171 // Analyze call will also need good READ_VIN value to check. 1172 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1173 .Times(1) 1174 .WillOnce(Return("201300")); 1175 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1176 psu.analyze(); 1177 EXPECT_EQ(psu.hasInputFault(), false); 1178 } 1179 1180 TEST_F(PowerSupplyTests, HasMFRFault) 1181 { 1182 auto bus = sdbusplus::bus::new_default(); 1183 1184 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, 1185 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1186 MockedGPIOInterface* mockPresenceGPIO = 1187 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1188 // Always return 1 to indicate present. 1189 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1190 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1191 setMissingToPresentExpects(mockPMBus, mockedUtil); 1192 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1193 // for INPUT_HISTORY will check max_power_out to see if it is 1194 // old/unsupported power supply. Indicate good value, supported. 1195 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1196 .WillRepeatedly(Return("2000")); 1197 // First return STATUS_WORD with no bits on. 1198 // STATUS_WORD 0x0000 is powered on, no faults. 1199 PMBusExpectations expectations; 1200 setPMBusExpectations(mockPMBus, expectations); 1201 // Analyze call will also need good READ_VIN value to check. 1202 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1203 .Times(1) 1204 .WillOnce(Return("202100")); 1205 psu.analyze(); 1206 EXPECT_EQ(psu.hasMFRFault(), 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(s) on. 1210 expectations.statusMFRValue = 0xFF; 1211 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1212 { 1213 setPMBusExpectations(mockPMBus, expectations); 1214 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1215 .Times(1) 1216 .WillOnce(Return("202200")); 1217 psu.analyze(); 1218 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT); 1219 } 1220 // Back to no bits on in STATUS_WORD 1221 expectations.statusWordValue = 0; 1222 setPMBusExpectations(mockPMBus, expectations); 1223 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1224 .Times(1) 1225 .WillOnce(Return("202300")); 1226 psu.analyze(); 1227 EXPECT_EQ(psu.hasMFRFault(), false); 1228 } 1229 1230 TEST_F(PowerSupplyTests, HasVINUVFault) 1231 { 1232 auto bus = sdbusplus::bus::new_default(); 1233 1234 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, 1235 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1236 MockedGPIOInterface* mockPresenceGPIO = 1237 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1238 // Always return 1 to indicate present. 1239 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1240 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1241 setMissingToPresentExpects(mockPMBus, mockedUtil); 1242 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1243 // for INPUT_HISTORY will check max_power_out to see if it is 1244 // old/unsupported power supply. Indicate good value, supported. 1245 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1246 .WillRepeatedly(Return("2000")); 1247 1248 // Presence change from missing to present will trigger in1_input read in 1249 // an attempt to get CLEAR_FAULTS called. Return value ignored. 1250 // Zero to non-zero voltage, for missing/present change, triggers clear 1251 // faults call again. Return value ignored. 1252 // Fault (low voltage) to not faulted (voltage in range) triggers clear 1253 // faults call a third time. 1254 1255 // STATUS_WORD 0x0000 is powered on, no faults. 1256 PMBusExpectations expectations; 1257 setPMBusExpectations(mockPMBus, expectations); 1258 // Analyze call will also need good READ_VIN value to check. 1259 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1260 .Times(1) 1261 .WillOnce(Return("201100")); 1262 psu.analyze(); 1263 EXPECT_EQ(psu.hasVINUVFault(), false); 1264 // Turn fault on. 1265 expectations.statusWordValue = (status_word::VIN_UV_FAULT); 1266 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by 1267 // Figure 16, and assume bits on in STATUS_INPUT. 1268 expectations.statusInputValue = 0x18; 1269 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1270 { 1271 setPMBusExpectations(mockPMBus, expectations); 1272 // If there is a VIN_UV fault, fake reading voltage of less than 20V 1273 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1274 .Times(1) 1275 .WillOnce(Return("19876")); 1276 if (x == DEGLITCH_LIMIT) 1277 { 1278 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1279 } 1280 psu.analyze(); 1281 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT); 1282 } 1283 // Back to no fault bits on in STATUS_WORD 1284 expectations.statusWordValue = 0; 1285 setPMBusExpectations(mockPMBus, expectations); 1286 // Updates now result in clearing faults if read voltage goes from below the 1287 // minimum, to within a valid range. 1288 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1289 .Times(1) 1290 .WillOnce(Return("201300")); 1291 // Went from below minimum to within range, expect clearVinUVFault(). 1292 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 1293 .Times(1) 1294 .WillOnce(Return(1)); 1295 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1296 psu.analyze(); 1297 EXPECT_EQ(psu.hasVINUVFault(), false); 1298 } 1299 1300 TEST_F(PowerSupplyTests, HasVoutOVFault) 1301 { 1302 auto bus = sdbusplus::bus::new_default(); 1303 1304 PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, 1305 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1306 MockedGPIOInterface* mockPresenceGPIO = 1307 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1308 // Always return 1 to indicate present. 1309 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1310 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1311 setMissingToPresentExpects(mockPMBus, mockedUtil); 1312 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1313 // for INPUT_HISTORY will check max_power_out to see if it is 1314 // old/unsupported power supply. Indicate good value, supported. 1315 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1316 .WillRepeatedly(Return("2000")); 1317 // STATUS_WORD 0x0000 is powered on, no faults. 1318 PMBusExpectations expectations; 1319 setPMBusExpectations(mockPMBus, expectations); 1320 // Call to analyze will trigger read of "in1_input" to check voltage. 1321 // Initial value would be 0, so this read updates it to non-zero. 1322 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1323 .Times(1) 1324 .WillOnce(Return("202100")); 1325 psu.analyze(); 1326 EXPECT_EQ(psu.hasVoutOVFault(), false); 1327 // Turn fault on. 1328 expectations.statusWordValue = (status_word::VOUT_OV_FAULT); 1329 // STATUS_VOUT fault bit(s) 1330 expectations.statusVOUTValue = 0x80; 1331 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1332 { 1333 setPMBusExpectations(mockPMBus, expectations); 1334 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1335 .Times(1) 1336 .WillOnce(Return("202200")); 1337 psu.analyze(); 1338 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT); 1339 } 1340 // Back to no fault bits on in STATUS_WORD 1341 expectations.statusWordValue = 0; 1342 setPMBusExpectations(mockPMBus, expectations); 1343 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1344 .Times(1) 1345 .WillOnce(Return("202300")); 1346 psu.analyze(); 1347 EXPECT_EQ(psu.hasVoutOVFault(), false); 1348 } 1349 1350 TEST_F(PowerSupplyTests, HasIoutOCFault) 1351 { 1352 auto bus = sdbusplus::bus::new_default(); 1353 1354 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, 1355 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1356 MockedGPIOInterface* mockPresenceGPIO = 1357 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1358 // Always return 1 to indicate present. 1359 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1360 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1361 setMissingToPresentExpects(mockPMBus, mockedUtil); 1362 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1363 // for INPUT_HISTORY will check max_power_out to see if it is 1364 // old/unsupported power supply. Indicate good value, supported. 1365 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1366 .WillRepeatedly(Return("2000")); 1367 // STATUS_WORD 0x0000 is powered on, no faults. 1368 PMBusExpectations expectations; 1369 setPMBusExpectations(mockPMBus, expectations); 1370 // Call to analyze will trigger read of "in1_input" to check voltage. 1371 // Initial value would be 0, so this read updates it to non-zero. 1372 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1373 .Times(1) 1374 .WillOnce(Return("203100")); 1375 psu.analyze(); 1376 EXPECT_EQ(psu.hasIoutOCFault(), false); 1377 // Turn fault on. 1378 expectations.statusWordValue = status_word::IOUT_OC_FAULT; 1379 // STATUS_IOUT fault bit(s) 1380 expectations.statusIOUTValue = 0x88; 1381 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1382 { 1383 setPMBusExpectations(mockPMBus, expectations); 1384 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1385 .Times(1) 1386 .WillOnce(Return("203200")); 1387 if (x == DEGLITCH_LIMIT) 1388 { 1389 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1390 } 1391 psu.analyze(); 1392 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT); 1393 } 1394 // Back to no fault bits on in STATUS_WORD 1395 expectations.statusWordValue = 0; 1396 setPMBusExpectations(mockPMBus, expectations); 1397 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1398 .Times(1) 1399 .WillOnce(Return("203300")); 1400 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1401 psu.analyze(); 1402 EXPECT_EQ(psu.hasIoutOCFault(), false); 1403 } 1404 1405 TEST_F(PowerSupplyTests, HasVoutUVFault) 1406 { 1407 auto bus = sdbusplus::bus::new_default(); 1408 1409 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, 1410 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1411 MockedGPIOInterface* mockPresenceGPIO = 1412 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1413 // Always return 1 to indicate present. 1414 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1415 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1416 setMissingToPresentExpects(mockPMBus, mockedUtil); 1417 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1418 // for INPUT_HISTORY will check max_power_out to see if it is 1419 // old/unsupported power supply. Indicate good value, supported. 1420 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1421 .WillRepeatedly(Return("2000")); 1422 // STATUS_WORD 0x0000 is powered on, no faults. 1423 PMBusExpectations expectations; 1424 setPMBusExpectations(mockPMBus, expectations); 1425 // Call to analyze will trigger read of "in1_input" to check voltage. 1426 // Initial value would be 0, so this read updates it to non-zero. 1427 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1428 .Times(1) 1429 .WillOnce(Return("204100")); 1430 psu.analyze(); 1431 EXPECT_EQ(psu.hasVoutUVFault(), false); 1432 // Turn fault on. 1433 expectations.statusWordValue = (status_word::VOUT_FAULT); 1434 // STATUS_VOUT fault bit(s) 1435 expectations.statusVOUTValue = 0x30; 1436 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1437 { 1438 setPMBusExpectations(mockPMBus, expectations); 1439 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1440 .Times(1) 1441 .WillOnce(Return("204200")); 1442 psu.analyze(); 1443 EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT); 1444 } 1445 // Back to no fault bits on in STATUS_WORD 1446 expectations.statusWordValue = 0; 1447 setPMBusExpectations(mockPMBus, expectations); 1448 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1449 .Times(1) 1450 .WillOnce(Return("204300")); 1451 psu.analyze(); 1452 EXPECT_EQ(psu.hasVoutUVFault(), false); 1453 } 1454 1455 TEST_F(PowerSupplyTests, HasFanFault) 1456 { 1457 auto bus = sdbusplus::bus::new_default(); 1458 1459 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1); 1460 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0); 1461 1462 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, 1463 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1464 MockedGPIOInterface* mockPresenceGPIO = 1465 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1466 // Always return 1 to indicate present. 1467 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1468 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1469 setMissingToPresentExpects(mockPMBus, mockedUtil); 1470 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1471 // for INPUT_HISTORY will check max_power_out to see if it is 1472 // old/unsupported power supply. Indicate good value, supported. 1473 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1474 .WillRepeatedly(Return("2000")); 1475 // STATUS_WORD 0x0000 is powered on, no faults. 1476 PMBusExpectations expectations; 1477 setPMBusExpectations(mockPMBus, expectations); 1478 // Call to analyze will trigger read of "in1_input" to check voltage. 1479 // Initial value would be 0, so this read updates it to non-zero. 1480 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1481 .Times(1) 1482 .WillOnce(Return("205100")); 1483 psu.analyze(); 1484 EXPECT_EQ(psu.hasFanFault(), false); 1485 // Turn fault on. 1486 expectations.statusWordValue = (status_word::FAN_FAULT); 1487 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault) 1488 expectations.statusFans12Value = 0x80; 1489 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1490 { 1491 setPMBusExpectations(mockPMBus, expectations); 1492 // Call to analyze will trigger read of "in1_input" to check voltage. 1493 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1494 .Times(1) 1495 .WillOnce(Return("205200")); 1496 psu.analyze(); 1497 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT); 1498 } 1499 // Back to no fault bits on in STATUS_WORD 1500 expectations.statusWordValue = 0; 1501 setPMBusExpectations(mockPMBus, expectations); 1502 // Call to analyze will trigger read of "in1_input" to check voltage. 1503 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1504 .Times(1) 1505 .WillOnce(Return("205300")); 1506 psu.analyze(); 1507 EXPECT_EQ(psu.hasFanFault(), false); 1508 } 1509 1510 TEST_F(PowerSupplyTests, HasTempFault) 1511 { 1512 auto bus = sdbusplus::bus::new_default(); 1513 1514 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1); 1515 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0); 1516 1517 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, 1518 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1519 MockedGPIOInterface* mockPresenceGPIO = 1520 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1521 // Always return 1 to indicate present. 1522 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1523 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1524 setMissingToPresentExpects(mockPMBus, mockedUtil); 1525 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1526 // for INPUT_HISTORY will check max_power_out to see if it is 1527 // old/unsupported power supply. Indicate good value, supported. 1528 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1529 .WillRepeatedly(Return("2000")); 1530 // STATUS_WORD 0x0000 is powered on, no faults. 1531 PMBusExpectations expectations; 1532 setPMBusExpectations(mockPMBus, expectations); 1533 // Call to analyze will trigger read of "in1_input" to check voltage. 1534 // Initial value would be 0, so this read updates it to non-zero. 1535 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1536 .Times(1) 1537 .WillOnce(Return("206100")); 1538 psu.analyze(); 1539 EXPECT_EQ(psu.hasTempFault(), false); 1540 // Turn fault on. 1541 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN); 1542 // STATUS_TEMPERATURE fault bit on (OT Fault) 1543 expectations.statusTempValue = 0x80; 1544 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1545 { 1546 setPMBusExpectations(mockPMBus, expectations); 1547 // Call to analyze will trigger read of "in1_input" to check voltage. 1548 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1549 .Times(1) 1550 .WillOnce(Return("206200")); 1551 psu.analyze(); 1552 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT); 1553 } 1554 // Back to no fault bits on in STATUS_WORD 1555 expectations.statusWordValue = 0; 1556 setPMBusExpectations(mockPMBus, expectations); 1557 // Call to analyze will trigger read of "in1_input" to check voltage. 1558 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1559 .Times(1) 1560 .WillOnce(Return("206300")); 1561 psu.analyze(); 1562 EXPECT_EQ(psu.hasTempFault(), false); 1563 } 1564 1565 TEST_F(PowerSupplyTests, HasPgoodFault) 1566 { 1567 auto bus = sdbusplus::bus::new_default(); 1568 1569 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, 1570 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1571 MockedGPIOInterface* mockPresenceGPIO = 1572 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1573 // Always return 1 to indicate present. 1574 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1575 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1576 setMissingToPresentExpects(mockPMBus, mockedUtil); 1577 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1578 // for INPUT_HISTORY will check max_power_out to see if it is 1579 // old/unsupported power supply. Indicate good value, supported. 1580 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1581 .WillRepeatedly(Return("2000")); 1582 // STATUS_WORD 0x0000 is powered on, no faults. 1583 PMBusExpectations expectations; 1584 setPMBusExpectations(mockPMBus, expectations); 1585 // Call to analyze will trigger read of "in1_input" to check voltage. 1586 // Initial value would be 0, so this read updates it to non-zero. 1587 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1588 .Times(1) 1589 .WillOnce(Return("207100")); 1590 psu.analyze(); 1591 EXPECT_EQ(psu.hasPgoodFault(), false); 1592 // Setup another expectation of no faults. 1593 setPMBusExpectations(mockPMBus, expectations); 1594 // Call to analyze will trigger read of "in1_input" to check voltage. 1595 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1596 .Times(1) 1597 .WillOnce(Return("207200")); 1598 psu.analyze(); 1599 EXPECT_EQ(psu.hasPgoodFault(), false); 1600 // Setup another expectation of no faults. 1601 setPMBusExpectations(mockPMBus, expectations); 1602 // Call to analyze will trigger read of "in1_input" to check voltage. 1603 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1604 .Times(1) 1605 .WillOnce(Return("207300")); 1606 psu.analyze(); 1607 EXPECT_EQ(psu.hasPgoodFault(), false); 1608 // Turn PGOOD# off (fault on). 1609 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED); 1610 setPMBusExpectations(mockPMBus, expectations); 1611 // Call to analyze will trigger read of "in1_input" to check voltage. 1612 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1613 .Times(1) 1614 .WillOnce(Return("207400")); 1615 psu.analyze(); 1616 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 1 1617 EXPECT_EQ(psu.hasPgoodFault(), false); 1618 setPMBusExpectations(mockPMBus, expectations); 1619 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1620 .Times(1) 1621 .WillOnce(Return("207500")); 1622 psu.analyze(); 1623 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 2 1624 EXPECT_EQ(psu.hasPgoodFault(), false); 1625 setPMBusExpectations(mockPMBus, expectations); 1626 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1627 .Times(1) 1628 .WillOnce(Return("207600")); 1629 psu.analyze(); 1630 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 3 1631 EXPECT_EQ(psu.hasPgoodFault(), false); 1632 setPMBusExpectations(mockPMBus, expectations); 1633 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1634 .Times(1) 1635 .WillOnce(Return("207700")); 1636 psu.analyze(); 1637 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 4 1638 EXPECT_EQ(psu.hasPgoodFault(), false); 1639 setPMBusExpectations(mockPMBus, expectations); 1640 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1641 .Times(1) 1642 .WillOnce(Return("207800")); 1643 psu.analyze(); 1644 // Expect true. PGOOD_DEGLITCH_LIMIT @ 5 1645 EXPECT_EQ(psu.hasPgoodFault(), true); 1646 // Back to no fault bits on in STATUS_WORD 1647 expectations.statusWordValue = 0; 1648 setPMBusExpectations(mockPMBus, expectations); 1649 // Call to analyze will trigger read of "in1_input" to check voltage. 1650 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1651 .Times(1) 1652 .WillOnce(Return("207700")); 1653 psu.analyze(); 1654 EXPECT_EQ(psu.hasPgoodFault(), false); 1655 1656 // Turn OFF bit on 1657 expectations.statusWordValue = (status_word::UNIT_IS_OFF); 1658 setPMBusExpectations(mockPMBus, expectations); 1659 // Call to analyze will trigger read of "in1_input" to check voltage. 1660 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1661 .Times(1) 1662 .WillOnce(Return("208100")); 1663 psu.analyze(); 1664 EXPECT_EQ(psu.hasPgoodFault(), false); 1665 setPMBusExpectations(mockPMBus, expectations); 1666 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1667 .Times(1) 1668 .WillOnce(Return("208200")); 1669 psu.analyze(); 1670 EXPECT_EQ(psu.hasPgoodFault(), false); 1671 setPMBusExpectations(mockPMBus, expectations); 1672 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1673 .Times(1) 1674 .WillOnce(Return("208300")); 1675 psu.analyze(); 1676 EXPECT_EQ(psu.hasPgoodFault(), false); 1677 setPMBusExpectations(mockPMBus, expectations); 1678 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1679 .Times(1) 1680 .WillOnce(Return("208400")); 1681 psu.analyze(); 1682 EXPECT_EQ(psu.hasPgoodFault(), false); 1683 setPMBusExpectations(mockPMBus, expectations); 1684 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1685 .Times(1) 1686 .WillOnce(Return("208500")); 1687 psu.analyze(); 1688 EXPECT_EQ(psu.hasPgoodFault(), true); 1689 // Back to no fault bits on in STATUS_WORD 1690 expectations.statusWordValue = 0; 1691 setPMBusExpectations(mockPMBus, expectations); 1692 // Call to analyze will trigger read of "in1_input" to check voltage. 1693 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1694 .Times(1) 1695 .WillOnce(Return("208000")); 1696 psu.analyze(); 1697 EXPECT_EQ(psu.hasPgoodFault(), false); 1698 } 1699 1700 TEST_F(PowerSupplyTests, HasPSKillFault) 1701 { 1702 auto bus = sdbusplus::bus::new_default(); 1703 PowerSupply psu{bus, PSUInventoryPath, 4, 0x6d, 1704 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1705 MockedGPIOInterface* mockPresenceGPIO = 1706 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1707 // Always return 1 to indicate present. 1708 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1709 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1710 setMissingToPresentExpects(mockPMBus, mockedUtil); 1711 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1712 // for INPUT_HISTORY will check max_power_out to see if it is 1713 // old/unsupported power supply. Indicate good value, supported. 1714 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1715 .WillRepeatedly(Return("2000")); 1716 // STATUS_WORD 0x0000 is powered on, no faults. 1717 PMBusExpectations expectations; 1718 setPMBusExpectations(mockPMBus, expectations); 1719 // Call to analyze will trigger read of "in1_input" to check voltage. 1720 // Initial value would be 0, so this read updates it to non-zero. 1721 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1722 .Times(1) 1723 .WillOnce(Return("208100")); 1724 psu.analyze(); 1725 EXPECT_EQ(psu.hasPSKillFault(), false); 1726 // Next return STATUS_WORD with MFR fault bit on. 1727 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1728 // STATUS_MFR_SPEFIC with bit(s) on. 1729 expectations.statusMFRValue = 0xFF; 1730 1731 // Deglitching faults, false until read the fault bits on up to the limit. 1732 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1733 { 1734 setPMBusExpectations(mockPMBus, expectations); 1735 // Call to analyze will trigger read of "in1_input" to check voltage. 1736 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1737 .Times(1) 1738 .WillOnce(Return("208200")); 1739 if (x == DEGLITCH_LIMIT) 1740 { 1741 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1742 } 1743 psu.analyze(); 1744 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT); 1745 } 1746 1747 // Back to no bits on in STATUS_WORD 1748 expectations.statusWordValue = 0; 1749 setPMBusExpectations(mockPMBus, expectations); 1750 // Call to analyze will trigger read of "in1_input" to check voltage. 1751 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1752 .Times(1) 1753 .WillOnce(Return("208300")); 1754 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1755 psu.analyze(); 1756 EXPECT_EQ(psu.hasPSKillFault(), false); 1757 // Next return STATUS_WORD with MFR fault bit on. 1758 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1759 // STATUS_MFR_SPEFIC with bit 4 on. 1760 expectations.statusMFRValue = 0x10; 1761 1762 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1763 { 1764 setPMBusExpectations(mockPMBus, expectations); 1765 // Call to analyze will trigger read of "in1_input" to check voltage. 1766 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1767 .Times(1) 1768 .WillOnce(Return("208400")); 1769 if (x == DEGLITCH_LIMIT) 1770 { 1771 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1772 } 1773 psu.analyze(); 1774 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT); 1775 } 1776 1777 // Back to no bits on in STATUS_WORD 1778 expectations.statusWordValue = 0; 1779 setPMBusExpectations(mockPMBus, expectations); 1780 // Call to analyze will trigger read of "in1_input" to check voltage. 1781 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1782 .Times(1) 1783 .WillOnce(Return("208500")); 1784 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1785 psu.analyze(); 1786 EXPECT_EQ(psu.hasPSKillFault(), false); 1787 } 1788 1789 TEST_F(PowerSupplyTests, HasPS12VcsFault) 1790 { 1791 auto bus = sdbusplus::bus::new_default(); 1792 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6e, 1793 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1794 MockedGPIOInterface* mockPresenceGPIO = 1795 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1796 // Always return 1 to indicate present. 1797 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1798 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1799 setMissingToPresentExpects(mockPMBus, mockedUtil); 1800 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1801 // for INPUT_HISTORY will check max_power_out to see if it is 1802 // old/unsupported power supply. Indicate good value, supported. 1803 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1804 .WillRepeatedly(Return("2000")); 1805 // STATUS_WORD 0x0000 is powered on, no faults. 1806 PMBusExpectations expectations; 1807 setPMBusExpectations(mockPMBus, expectations); 1808 // Call to analyze will trigger read of "in1_input" to check voltage. 1809 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1810 .Times(1) 1811 .WillOnce(Return("209100")); 1812 psu.analyze(); 1813 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1814 // Next return STATUS_WORD with MFR fault bit on. 1815 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1816 // STATUS_MFR_SPEFIC with bit(s) on. 1817 expectations.statusMFRValue = 0xFF; 1818 1819 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1820 { 1821 setPMBusExpectations(mockPMBus, expectations); 1822 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1823 .Times(1) 1824 .WillOnce(Return("209200")); 1825 psu.analyze(); 1826 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT); 1827 } 1828 1829 // Back to no bits on in STATUS_WORD 1830 expectations.statusWordValue = 0; 1831 setPMBusExpectations(mockPMBus, expectations); 1832 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1833 .Times(1) 1834 .WillOnce(Return("209300")); 1835 psu.analyze(); 1836 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1837 // Next return STATUS_WORD with MFR fault bit on. 1838 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1839 // STATUS_MFR_SPEFIC with bit 6 on. 1840 expectations.statusMFRValue = 0x40; 1841 1842 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1843 { 1844 setPMBusExpectations(mockPMBus, expectations); 1845 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1846 .Times(1) 1847 .WillOnce(Return("209400")); 1848 psu.analyze(); 1849 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT); 1850 } 1851 1852 // Back to no bits on in STATUS_WORD 1853 expectations.statusWordValue = 0; 1854 setPMBusExpectations(mockPMBus, expectations); 1855 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1856 .Times(1) 1857 .WillOnce(Return("209500")); 1858 psu.analyze(); 1859 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1860 } 1861 1862 TEST_F(PowerSupplyTests, HasPSCS12VFault) 1863 { 1864 auto bus = sdbusplus::bus::new_default(); 1865 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f, 1866 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1867 MockedGPIOInterface* mockPresenceGPIO = 1868 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1869 // Always return 1 to indicate present. 1870 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1871 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1872 setMissingToPresentExpects(mockPMBus, mockedUtil); 1873 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1874 // for INPUT_HISTORY will check max_power_out to see if it is 1875 // old/unsupported power supply. Indicate good value, supported. 1876 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1877 .WillRepeatedly(Return("2000")); 1878 // STATUS_WORD 0x0000 is powered on, no faults. 1879 PMBusExpectations expectations; 1880 setPMBusExpectations(mockPMBus, expectations); 1881 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1882 .Times(1) 1883 .WillOnce(Return("209100")); 1884 psu.analyze(); 1885 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1886 // Next return STATUS_WORD with MFR fault bit on. 1887 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1888 // STATUS_MFR_SPEFIC with bit(s) on. 1889 expectations.statusMFRValue = 0xFF; 1890 1891 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1892 { 1893 setPMBusExpectations(mockPMBus, expectations); 1894 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1895 .Times(1) 1896 .WillOnce(Return("209200")); 1897 psu.analyze(); 1898 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT); 1899 } 1900 1901 // Back to no bits on in STATUS_WORD 1902 expectations.statusWordValue = 0; 1903 setPMBusExpectations(mockPMBus, expectations); 1904 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1905 .Times(1) 1906 .WillOnce(Return("209300")); 1907 psu.analyze(); 1908 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1909 // Next return STATUS_WORD with MFR fault bit on. 1910 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1911 // STATUS_MFR_SPEFIC with bit 7 on. 1912 expectations.statusMFRValue = 0x80; 1913 1914 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1915 { 1916 setPMBusExpectations(mockPMBus, expectations); 1917 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1918 .Times(1) 1919 .WillOnce(Return("209400")); 1920 psu.analyze(); 1921 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT); 1922 } 1923 1924 // Back to no bits on in STATUS_WORD 1925 expectations.statusWordValue = 0; 1926 setPMBusExpectations(mockPMBus, expectations); 1927 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1928 .Times(1) 1929 .WillOnce(Return("209500")); 1930 psu.analyze(); 1931 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1932 } 1933 1934 TEST_F(PowerSupplyTests, PeakInputPowerSensor) 1935 { 1936 auto bus = sdbusplus::bus::new_default(); 1937 { 1938 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f, 1939 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1940 EXPECT_EQ(psu.getPeakInputPower(), std::nullopt); 1941 1942 MockedGPIOInterface* mockPresenceGPIO = 1943 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1944 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1945 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1946 1947 setMissingToPresentExpects(mockPMBus, mockedUtil); 1948 PMBusExpectations expectations; 1949 setPMBusExpectations(mockPMBus, expectations); 1950 1951 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1952 .Times(1) 1953 .WillOnce(Return("206000")); 1954 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1955 .WillRepeatedly(Return("2000")); 1956 1957 psu.analyze(); 1958 EXPECT_EQ(psu.getPeakInputPower().value_or(0), 213); 1959 } 1960 1961 // Test that there is no peak power sensor on 1400W PSs 1962 { 1963 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, 1964 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1965 MockedGPIOInterface* mockPresenceGPIO = 1966 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1967 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1968 1969 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1970 1971 setMissingToPresentExpects(mockPMBus, mockedUtil); 1972 1973 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1974 .WillRepeatedly(Return("30725")); 1975 1976 PMBusExpectations expectations; 1977 setPMBusExpectations(mockPMBus, expectations); 1978 1979 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1980 .WillRepeatedly(Return("206000")); 1981 psu.analyze(); 1982 1983 EXPECT_EQ(psu.getPeakInputPower(), std::nullopt); 1984 } 1985 1986 // Test that IPSPS power supplies don't have peak power 1987 { 1988 PowerSupply psu{bus, PSUInventoryPath, 11, 1989 0x58, "inspur-ipsps", PSUGPIOLineName, 1990 isPowerOn}; 1991 1992 MockedGPIOInterface* mockPresenceGPIO = 1993 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1994 1995 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1996 1997 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1998 1999 setMissingToPresentExpects(mockPMBus, mockedUtil); 2000 PMBusExpectations expectations; 2001 setPMBusExpectations(mockPMBus, expectations); 2002 2003 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 2004 .WillRepeatedly(Return("206000")); 2005 2006 psu.analyze(); 2007 2008 EXPECT_EQ(psu.getPeakInputPower(), std::nullopt); 2009 } 2010 2011 // Test that a bad response from the input_history command leads 2012 // to an NaN value. 2013 { 2014 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f, 2015 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 2016 2017 MockedGPIOInterface* mockPresenceGPIO = 2018 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 2019 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 2020 2021 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 2022 2023 setMissingToPresentExpects(mockPMBus, mockedUtil); 2024 PMBusExpectations expectations; 2025 setPMBusExpectations(mockPMBus, expectations); 2026 2027 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 2028 .Times(1) 2029 .WillOnce(Return("206000")); 2030 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 2031 .WillRepeatedly(Return("2000")); 2032 2033 // Don't return the full 5 bytes. 2034 EXPECT_CALL(mockPMBus, 2035 readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug, 5)) 2036 .WillRepeatedly(Return(std::vector<uint8_t>{0x01, 0x5c})); 2037 2038 psu.analyze(); 2039 EXPECT_THAT(psu.getPeakInputPower().value_or(0), IsNan()); 2040 } 2041 } 2042 2043 TEST_F(PowerSupplyTests, IsSyncHistoryRequired) 2044 { 2045 auto bus = sdbusplus::bus::new_default(); 2046 PowerSupply psu{bus, PSUInventoryPath, 8, 0x6f, 2047 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 2048 EXPECT_EQ(psu.isSyncHistoryRequired(), false); 2049 MockedGPIOInterface* mockPresenceGPIO = 2050 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 2051 // Always return 1 to indicate present. 2052 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 2053 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 2054 setMissingToPresentExpects(mockPMBus, mockedUtil); 2055 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 2056 // for INPUT_HISTORY will check max_power_out to see if it is 2057 // old/unsupported power supply. Indicate good value, supported. 2058 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 2059 .WillRepeatedly(Return("2000")); 2060 PMBusExpectations expectations; 2061 setPMBusExpectations(mockPMBus, expectations); 2062 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 2063 .Times(1) 2064 .WillRepeatedly(Return("205000")); 2065 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 2066 psu.analyze(); 2067 // Missing -> Present requires history sync 2068 EXPECT_EQ(psu.isSyncHistoryRequired(), true); 2069 psu.clearSyncHistoryRequired(); 2070 EXPECT_EQ(psu.isSyncHistoryRequired(), false); 2071 } 2072 2073 TEST_F(PowerSupplyTests, TestLinearConversions) 2074 { 2075 // Mantissa > 0, exponent = 0 2076 EXPECT_EQ(0, PowerSupply::linearToInteger(0)); 2077 EXPECT_EQ(1, PowerSupply::linearToInteger(1)); 2078 EXPECT_EQ(38, PowerSupply::linearToInteger(0x26)); 2079 EXPECT_EQ(1023, PowerSupply::linearToInteger(0x3FF)); 2080 2081 // Mantissa < 0, exponent = 0 2082 EXPECT_EQ(-1, PowerSupply::linearToInteger(0x7FF)); 2083 EXPECT_EQ(-20, PowerSupply::linearToInteger(0x7EC)); 2084 EXPECT_EQ(-769, PowerSupply::linearToInteger(0x4FF)); 2085 EXPECT_EQ(-989, PowerSupply::linearToInteger(0x423)); 2086 EXPECT_EQ(-1024, PowerSupply::linearToInteger(0x400)); 2087 2088 // Mantissa >= 0, exponent > 0 2089 // M = 1, E = 2 2090 EXPECT_EQ(4, PowerSupply::linearToInteger(0x1001)); 2091 2092 // M = 1000, E = 10 2093 EXPECT_EQ(1024000, PowerSupply::linearToInteger(0x53E8)); 2094 2095 // M = 10, E = 15 2096 EXPECT_EQ(327680, PowerSupply::linearToInteger(0x780A)); 2097 2098 // Mantissa >= 0, exponent < 0 2099 // M = 0, E = -1 2100 EXPECT_EQ(0, PowerSupply::linearToInteger(0xF800)); 2101 2102 // M = 100, E = -2 2103 EXPECT_EQ(25, PowerSupply::linearToInteger(0xF064)); 2104 2105 // Mantissa < 0, exponent < 0 2106 // M = -100, E = -1 2107 EXPECT_EQ(-50, PowerSupply::linearToInteger(0xFF9C)); 2108 2109 // M = -1024, E = -7 2110 EXPECT_EQ(-8, PowerSupply::linearToInteger(0xCC00)); 2111 } 2112