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 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1)); 489 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 490 .Times(1) 491 .WillOnce(Return(1)); 492 psu2.clearFaults(); 493 494 // CML fault 495 { 496 // First STATUS_WORD wit no bits set, then with CML fault. 497 PMBusExpectations expectations; 498 setPMBusExpectations(mockPMBus, expectations); 499 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 500 .Times(1) 501 .WillOnce(Return("214000")); 502 psu2.analyze(); 503 // STATUS_WORD with CML fault bit on. 504 expectations.statusWordValue = (status_word::CML_FAULT); 505 // Turn on STATUS_CML fault bit(s) 506 expectations.statusCMLValue = 0xFF; 507 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 508 { 509 setPMBusExpectations(mockPMBus, expectations); 510 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 511 .Times(1) 512 .WillOnce(Return("215000")); 513 psu2.analyze(); 514 EXPECT_EQ(psu2.isPresent(), true); 515 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 516 EXPECT_EQ(psu2.hasCommFault(), x >= DEGLITCH_LIMIT); 517 EXPECT_EQ(psu2.hasInputFault(), false); 518 EXPECT_EQ(psu2.hasMFRFault(), false); 519 EXPECT_EQ(psu2.hasVINUVFault(), false); 520 EXPECT_EQ(psu2.hasVoutOVFault(), false); 521 EXPECT_EQ(psu2.hasIoutOCFault(), false); 522 EXPECT_EQ(psu2.hasVoutUVFault(), false); 523 EXPECT_EQ(psu2.hasFanFault(), false); 524 EXPECT_EQ(psu2.hasTempFault(), false); 525 EXPECT_EQ(psu2.hasPgoodFault(), false); 526 EXPECT_EQ(psu2.hasPSKillFault(), false); 527 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 528 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 529 } 530 } 531 532 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1)); 533 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 534 .Times(1) 535 .WillOnce(Return(1)); 536 psu2.clearFaults(); 537 538 // VOUT_OV_FAULT fault 539 { 540 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault. 541 PMBusExpectations expectations; 542 setPMBusExpectations(mockPMBus, expectations); 543 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 544 .Times(1) 545 .WillOnce(Return("216000")); 546 psu2.analyze(); 547 // STATUS_WORD with VOUT/VOUT_OV fault. 548 expectations.statusWordValue = 549 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT)); 550 // Turn on STATUS_VOUT fault bit(s) 551 expectations.statusVOUTValue = 0xA0; 552 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 553 { 554 // STATUS_TEMPERATURE don't care (default) 555 setPMBusExpectations(mockPMBus, expectations); 556 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 557 .Times(1) 558 .WillOnce(Return("217000")); 559 psu2.analyze(); 560 EXPECT_EQ(psu2.isPresent(), true); 561 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 562 EXPECT_EQ(psu2.hasInputFault(), false); 563 EXPECT_EQ(psu2.hasMFRFault(), false); 564 EXPECT_EQ(psu2.hasVINUVFault(), false); 565 EXPECT_EQ(psu2.hasCommFault(), false); 566 EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT); 567 EXPECT_EQ(psu2.hasVoutUVFault(), false); 568 EXPECT_EQ(psu2.hasIoutOCFault(), false); 569 EXPECT_EQ(psu2.hasFanFault(), false); 570 EXPECT_EQ(psu2.hasTempFault(), false); 571 EXPECT_EQ(psu2.hasPgoodFault(), false); 572 EXPECT_EQ(psu2.hasPSKillFault(), false); 573 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 574 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 575 } 576 } 577 578 // IOUT_OC_FAULT fault 579 { 580 // First STATUS_WORD with no bits set, then with IOUT_OC fault. 581 PMBusExpectations expectations; 582 setPMBusExpectations(mockPMBus, expectations); 583 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 584 .Times(1) 585 .WillOnce(Return("218000")); 586 psu2.analyze(); 587 // STATUS_WORD with IOUT_OC fault. 588 expectations.statusWordValue = status_word::IOUT_OC_FAULT; 589 // Turn on STATUS_IOUT fault bit(s) 590 expectations.statusIOUTValue = 0x88; 591 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 592 { 593 setPMBusExpectations(mockPMBus, expectations); 594 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 595 .Times(1) 596 .WillOnce(Return("219000")); 597 psu2.analyze(); 598 EXPECT_EQ(psu2.isPresent(), true); 599 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 600 EXPECT_EQ(psu2.hasInputFault(), false); 601 EXPECT_EQ(psu2.hasMFRFault(), false); 602 EXPECT_EQ(psu2.hasVINUVFault(), false); 603 EXPECT_EQ(psu2.hasCommFault(), false); 604 EXPECT_EQ(psu2.hasVoutOVFault(), false); 605 EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT); 606 EXPECT_EQ(psu2.hasVoutUVFault(), false); 607 EXPECT_EQ(psu2.hasFanFault(), false); 608 EXPECT_EQ(psu2.hasTempFault(), false); 609 EXPECT_EQ(psu2.hasPgoodFault(), false); 610 EXPECT_EQ(psu2.hasPSKillFault(), false); 611 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 612 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 613 } 614 } 615 616 // VOUT_UV_FAULT 617 { 618 // First STATUS_WORD with no bits set, then with VOUT fault. 619 PMBusExpectations expectations; 620 setPMBusExpectations(mockPMBus, expectations); 621 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 622 .Times(1) 623 .WillOnce(Return("220000")); 624 psu2.analyze(); 625 // Change STATUS_WORD to indicate VOUT fault. 626 expectations.statusWordValue = (status_word::VOUT_FAULT); 627 // Turn on STATUS_VOUT fault bit(s) 628 expectations.statusVOUTValue = 0x30; 629 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 630 { 631 setPMBusExpectations(mockPMBus, expectations); 632 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 633 .Times(1) 634 .WillOnce(Return("221000")); 635 psu2.analyze(); 636 EXPECT_EQ(psu2.isPresent(), true); 637 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 638 EXPECT_EQ(psu2.hasInputFault(), false); 639 EXPECT_EQ(psu2.hasMFRFault(), false); 640 EXPECT_EQ(psu2.hasVINUVFault(), false); 641 EXPECT_EQ(psu2.hasCommFault(), false); 642 EXPECT_EQ(psu2.hasVoutOVFault(), false); 643 EXPECT_EQ(psu2.hasIoutOCFault(), false); 644 EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT); 645 EXPECT_EQ(psu2.hasFanFault(), false); 646 EXPECT_EQ(psu2.hasTempFault(), false); 647 EXPECT_EQ(psu2.hasPgoodFault(), false); 648 EXPECT_EQ(psu2.hasPSKillFault(), false); 649 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 650 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 651 } 652 } 653 654 // Fan fault 655 { 656 // First STATUS_WORD with no bits set, then with fan fault. 657 PMBusExpectations expectations; 658 setPMBusExpectations(mockPMBus, expectations); 659 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 660 .Times(1) 661 .WillOnce(Return("222000")); 662 psu2.analyze(); 663 expectations.statusWordValue = (status_word::FAN_FAULT); 664 // STATUS_FANS_1_2 with fan 1 warning & fault bits on. 665 expectations.statusFans12Value = 0xA0; 666 667 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 668 { 669 setPMBusExpectations(mockPMBus, expectations); 670 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 671 .Times(1) 672 .WillOnce(Return("223000")); 673 psu2.analyze(); 674 EXPECT_EQ(psu2.isPresent(), true); 675 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 676 EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT); 677 EXPECT_EQ(psu2.hasInputFault(), false); 678 EXPECT_EQ(psu2.hasMFRFault(), false); 679 EXPECT_EQ(psu2.hasVINUVFault(), false); 680 EXPECT_EQ(psu2.hasCommFault(), false); 681 EXPECT_EQ(psu2.hasVoutOVFault(), false); 682 EXPECT_EQ(psu2.hasIoutOCFault(), false); 683 EXPECT_EQ(psu2.hasVoutUVFault(), false); 684 EXPECT_EQ(psu2.hasTempFault(), false); 685 EXPECT_EQ(psu2.hasPgoodFault(), false); 686 EXPECT_EQ(psu2.hasPSKillFault(), false); 687 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 688 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 689 } 690 } 691 692 // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT. 693 { 694 // First STATUS_WORD with no bits set. 695 PMBusExpectations expectations; 696 setPMBusExpectations(mockPMBus, expectations); 697 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 698 .Times(1) 699 .WillOnce(Return("123000")); 700 psu2.analyze(); 701 EXPECT_EQ(psu2.isFaulted(), false); 702 // POWER_GOOD# inactive, and OFF bit on. 703 expectations.statusWordValue = 704 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF)); 705 for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++) 706 { 707 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and 708 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults). 709 setPMBusExpectations(mockPMBus, expectations); 710 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 711 .Times(1) 712 .WillOnce(Return("124000")); 713 psu2.analyze(); 714 EXPECT_EQ(psu2.isPresent(), true); 715 EXPECT_EQ(psu2.isFaulted(), x >= PGOOD_DEGLITCH_LIMIT); 716 EXPECT_EQ(psu2.hasInputFault(), false); 717 EXPECT_EQ(psu2.hasMFRFault(), false); 718 EXPECT_EQ(psu2.hasVINUVFault(), false); 719 EXPECT_EQ(psu2.hasCommFault(), false); 720 EXPECT_EQ(psu2.hasVoutOVFault(), false); 721 EXPECT_EQ(psu2.hasVoutUVFault(), false); 722 EXPECT_EQ(psu2.hasIoutOCFault(), false); 723 EXPECT_EQ(psu2.hasFanFault(), false); 724 EXPECT_EQ(psu2.hasTempFault(), false); 725 EXPECT_EQ(psu2.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT); 726 } 727 } 728 729 // TODO: ReadFailure 730 } 731 732 TEST_F(PowerSupplyTests, OnOffConfig) 733 { 734 auto bus = sdbusplus::bus::new_default(); 735 uint8_t data = 0x15; 736 737 // Test where PSU is NOT present 738 try 739 { 740 // Assume GPIO presence, not inventory presence? 741 EXPECT_CALL(mockedUtil, setAvailable(_, _, _)).Times(0); 742 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, 743 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 744 745 MockedGPIOInterface* mockPresenceGPIO = 746 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 747 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0)); 748 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 749 // Constructor should set initial presence, default read returns 0. 750 // If it is not present, I should not be trying to write to it. 751 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0); 752 psu.onOffConfig(data); 753 } 754 catch (...) 755 {} 756 757 // Test where PSU is present 758 try 759 { 760 // Assume GPIO presence, not inventory presence? 761 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 762 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, 763 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 764 MockedGPIOInterface* mockPresenceGPIO = 765 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 766 // There will potentially be multiple calls, we want it to continue 767 // returning 1 for the GPIO read to keep the power supply present. 768 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 769 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 770 setMissingToPresentExpects(mockPMBus, mockedUtil); 771 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 772 // for INPUT_HISTORY will check max_power_out to see if it is 773 // old/unsupported power supply. Indicate good value, supported. 774 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 775 .WillRepeatedly(Return("2000")); 776 // If I am calling analyze(), I should probably give it good data. 777 // STATUS_WORD 0x0000 is powered on, no faults. 778 PMBusExpectations expectations; 779 setPMBusExpectations(mockPMBus, expectations); 780 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 781 .Times(1) 782 .WillOnce(Return("205000")); 783 psu.analyze(); 784 // I definitely should be writting ON_OFF_CONFIG if I call the function 785 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15), 786 Type::HwmonDeviceDebug)) 787 .Times(1); 788 psu.onOffConfig(data); 789 } 790 catch (...) 791 {} 792 } 793 794 TEST_F(PowerSupplyTests, ClearFaults) 795 { 796 auto bus = sdbusplus::bus::new_default(); 797 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, 798 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 799 MockedGPIOInterface* mockPresenceGPIO = 800 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 801 // Always return 1 to indicate present. 802 // Each analyze() call will trigger a read of the presence GPIO. 803 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 804 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 805 setMissingToPresentExpects(mockPMBus, mockedUtil); 806 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 807 // for INPUT_HISTORY will check max_power_out to see if it is 808 // old/unsupported power supply. Indicate good value, supported. 809 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 810 .WillRepeatedly(Return("2000")); 811 // STATUS_WORD 0x0000 is powered on, no faults. 812 PMBusExpectations expectations; 813 setPMBusExpectations(mockPMBus, expectations); 814 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 815 .Times(1) 816 .WillOnce(Return("207000")); 817 psu.analyze(); 818 EXPECT_EQ(psu.isPresent(), true); 819 EXPECT_EQ(psu.isFaulted(), false); 820 EXPECT_EQ(psu.hasInputFault(), false); 821 EXPECT_EQ(psu.hasMFRFault(), false); 822 EXPECT_EQ(psu.hasVINUVFault(), false); 823 EXPECT_EQ(psu.hasCommFault(), false); 824 EXPECT_EQ(psu.hasVoutOVFault(), false); 825 EXPECT_EQ(psu.hasIoutOCFault(), false); 826 EXPECT_EQ(psu.hasVoutUVFault(), false); 827 EXPECT_EQ(psu.hasFanFault(), false); 828 EXPECT_EQ(psu.hasTempFault(), false); 829 EXPECT_EQ(psu.hasPgoodFault(), false); 830 EXPECT_EQ(psu.hasPSKillFault(), false); 831 EXPECT_EQ(psu.hasPS12VcsFault(), false); 832 EXPECT_EQ(psu.hasPSCS12VFault(), false); 833 834 // STATUS_WORD with fault bits galore! 835 expectations.statusWordValue = 0xFFFF; 836 // STATUS_INPUT with fault bits on. 837 expectations.statusInputValue = 0xFF; 838 // STATUS_MFR_SPEFIC with bits on. 839 expectations.statusMFRValue = 0xFF; 840 // STATUS_CML with bits on. 841 expectations.statusCMLValue = 0xFF; 842 // STATUS_VOUT with bits on. 843 expectations.statusVOUTValue = 0xFF; 844 // STATUS_IOUT with bits on. 845 expectations.statusIOUTValue = 0xFF; 846 // STATUS_FANS_1_2 with bits on. 847 expectations.statusFans12Value = 0xFF; 848 // STATUS_TEMPERATURE with bits on. 849 expectations.statusTempValue = 0xFF; 850 851 for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++) 852 { 853 setPMBusExpectations(mockPMBus, expectations); 854 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 855 .Times(1) 856 .WillOnce(Return("0")); 857 if (x == DEGLITCH_LIMIT) 858 { 859 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 860 } 861 psu.analyze(); 862 EXPECT_EQ(psu.isPresent(), true); 863 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT. 864 // Rely on HasVoutUVFault() to verify this sets and clears. 865 EXPECT_EQ(psu.hasVoutUVFault(), false); 866 // pgoodFault at PGOOD_DEGLITCH_LIMIT, all other faults are deglitched 867 // up to DEGLITCH_LIMIT 868 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT); 869 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT); 870 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT); 871 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT); 872 EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT); 873 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT); 874 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT); 875 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT); 876 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT); 877 EXPECT_EQ(psu.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT); 878 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT); 879 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT); 880 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT); 881 } 882 883 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)) 884 .Times(1) 885 .WillOnce(Return(207000)); 886 // Clearing VIN_UV fault via in1_lcrit_alarm 887 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 888 .Times(1) 889 .WillOnce(Return(1)); 890 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 891 psu.clearFaults(); 892 EXPECT_EQ(psu.isPresent(), true); 893 EXPECT_EQ(psu.isFaulted(), false); 894 EXPECT_EQ(psu.hasInputFault(), false); 895 EXPECT_EQ(psu.hasMFRFault(), false); 896 EXPECT_EQ(psu.hasVINUVFault(), false); 897 EXPECT_EQ(psu.hasCommFault(), false); 898 EXPECT_EQ(psu.hasVoutOVFault(), false); 899 EXPECT_EQ(psu.hasIoutOCFault(), false); 900 EXPECT_EQ(psu.hasVoutUVFault(), false); 901 EXPECT_EQ(psu.hasFanFault(), false); 902 EXPECT_EQ(psu.hasTempFault(), false); 903 EXPECT_EQ(psu.hasPgoodFault(), false); 904 EXPECT_EQ(psu.hasPSKillFault(), false); 905 EXPECT_EQ(psu.hasPS12VcsFault(), false); 906 EXPECT_EQ(psu.hasPSCS12VFault(), false); 907 908 // Faults clear on READ_VIN 0 -> !0 909 // STATUS_WORD with fault bits galore! 910 expectations.statusWordValue = 0xFFFF; 911 // STATUS_INPUT with fault bits on. 912 expectations.statusInputValue = 0xFF; 913 // STATUS_MFR_SPEFIC with bits on. 914 expectations.statusMFRValue = 0xFF; 915 // STATUS_CML with bits on. 916 expectations.statusCMLValue = 0xFF; 917 // STATUS_VOUT with bits on. 918 expectations.statusVOUTValue = 0xFF; 919 // STATUS_IOUT with bits on. 920 expectations.statusIOUTValue = 0xFF; 921 // STATUS_FANS_1_2 with bits on. 922 expectations.statusFans12Value = 0xFF; 923 // STATUS_TEMPERATURE with bits on. 924 expectations.statusTempValue = 0xFF; 925 926 // All faults deglitched now. Check for false before limit above. 927 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 928 { 929 setPMBusExpectations(mockPMBus, expectations); 930 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 931 .Times(1) 932 .WillOnce(Return("0")); 933 if (x == DEGLITCH_LIMIT) 934 { 935 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 936 } 937 psu.analyze(); 938 } 939 940 EXPECT_EQ(psu.isPresent(), true); 941 EXPECT_EQ(psu.isFaulted(), true); 942 EXPECT_EQ(psu.hasInputFault(), true); 943 EXPECT_EQ(psu.hasMFRFault(), true); 944 EXPECT_EQ(psu.hasVINUVFault(), true); 945 // True due to CML fault bits on 946 EXPECT_EQ(psu.hasCommFault(), true); 947 EXPECT_EQ(psu.hasVoutOVFault(), true); 948 EXPECT_EQ(psu.hasIoutOCFault(), true); 949 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT. 950 // Rely on HasVoutUVFault() to verify this sets and clears. 951 EXPECT_EQ(psu.hasVoutUVFault(), false); 952 EXPECT_EQ(psu.hasFanFault(), true); 953 EXPECT_EQ(psu.hasTempFault(), true); 954 // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT 955 EXPECT_EQ(psu.hasPgoodFault(), false); 956 EXPECT_EQ(psu.hasPSKillFault(), true); 957 EXPECT_EQ(psu.hasPS12VcsFault(), true); 958 EXPECT_EQ(psu.hasPSCS12VFault(), true); 959 // STATUS_WORD with INPUT/VIN_UV fault bits off. 960 expectations.statusWordValue = 0xDFF7; 961 // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For 962 // Insufficient Input Voltage bits off. 963 expectations.statusInputValue = 0xC7; 964 setPMBusExpectations(mockPMBus, expectations); 965 // READ_VIN back in range. 966 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 967 .Times(1) 968 .WillOnce(Return("206000")); 969 // VIN_UV cleared via in1_lcrit_alarm when voltage back in range. 970 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 971 .Times(1) 972 .WillOnce(Return(1)); 973 psu.analyze(); 974 // We only cleared the VIN_UV and OFF faults. 975 EXPECT_EQ(psu.isPresent(), true); 976 EXPECT_EQ(psu.isFaulted(), true); 977 EXPECT_EQ(psu.hasInputFault(), false); 978 EXPECT_EQ(psu.hasMFRFault(), true); 979 EXPECT_EQ(psu.hasVINUVFault(), false); 980 EXPECT_EQ(psu.hasCommFault(), true); 981 EXPECT_EQ(psu.hasVoutOVFault(), true); 982 EXPECT_EQ(psu.hasIoutOCFault(), true); 983 EXPECT_EQ(psu.hasVoutUVFault(), false); 984 EXPECT_EQ(psu.hasFanFault(), true); 985 EXPECT_EQ(psu.hasTempFault(), true); 986 // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT 987 EXPECT_EQ(psu.hasPgoodFault(), false); 988 EXPECT_EQ(psu.hasPSKillFault(), true); 989 EXPECT_EQ(psu.hasPS12VcsFault(), true); 990 EXPECT_EQ(psu.hasPSCS12VFault(), true); 991 992 // All faults cleared 993 expectations = {0}; 994 setPMBusExpectations(mockPMBus, expectations); 995 // READ_VIN back in range. 996 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 997 .Times(1) 998 .WillOnce(Return("206000")); 999 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1000 psu.analyze(); 1001 EXPECT_EQ(psu.isPresent(), true); 1002 EXPECT_EQ(psu.isFaulted(), false); 1003 EXPECT_EQ(psu.hasInputFault(), false); 1004 EXPECT_EQ(psu.hasMFRFault(), false); 1005 EXPECT_EQ(psu.hasVINUVFault(), false); 1006 EXPECT_EQ(psu.hasCommFault(), false); 1007 EXPECT_EQ(psu.hasVoutOVFault(), false); 1008 EXPECT_EQ(psu.hasIoutOCFault(), false); 1009 EXPECT_EQ(psu.hasVoutUVFault(), false); 1010 EXPECT_EQ(psu.hasFanFault(), false); 1011 EXPECT_EQ(psu.hasTempFault(), false); 1012 EXPECT_EQ(psu.hasPgoodFault(), false); 1013 EXPECT_EQ(psu.hasPSKillFault(), false); 1014 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1015 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1016 1017 // TODO: Faults clear on missing/present? 1018 } 1019 1020 TEST_F(PowerSupplyTests, UpdateInventory) 1021 { 1022 auto bus = sdbusplus::bus::new_default(); 1023 1024 try 1025 { 1026 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, 1027 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1028 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1029 // If it is not present, I should not be trying to read a string 1030 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0); 1031 psu.updateInventory(); 1032 } 1033 catch (...) 1034 { 1035 ADD_FAILURE() << "Should not have caught exception."; 1036 } 1037 1038 try 1039 { 1040 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, 1041 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1042 MockedGPIOInterface* mockPresenceGPIO = 1043 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1044 // GPIO read return 1 to indicate present. 1045 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1)); 1046 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1047 setMissingToPresentExpects(mockPMBus, mockedUtil); 1048 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1049 // for INPUT_HISTORY will check max_power_out to see if it is 1050 // old/unsupported power supply. Indicate good value, supported. 1051 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1052 .WillRepeatedly(Return("2000")); 1053 // STATUS_WORD 0x0000 is powered on, no faults. 1054 PMBusExpectations expectations; 1055 setPMBusExpectations(mockPMBus, expectations); 1056 // Call to analyze will read voltage, trigger clear faults for 0 to 1057 // within range. 1058 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1059 .Times(1) 1060 .WillOnce(Return("123456")); 1061 psu.analyze(); 1062 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return("")); 1063 psu.updateInventory(); 1064 1065 #if IBM_VPD 1066 EXPECT_CALL(mockPMBus, readString(_, _)) 1067 .WillOnce(Return("CCIN")) 1068 .WillOnce(Return("PN3456")) 1069 .WillOnce(Return("FN3456")) 1070 .WillOnce(Return("HEADER")) 1071 .WillOnce(Return("SN3456")) 1072 .WillOnce(Return("FW3456")); 1073 #endif 1074 psu.updateInventory(); 1075 // TODO: D-Bus mocking to verify values stored on D-Bus (???) 1076 } 1077 catch (...) 1078 { 1079 ADD_FAILURE() << "Should not have caught exception."; 1080 } 1081 } 1082 1083 TEST_F(PowerSupplyTests, IsPresent) 1084 { 1085 auto bus = sdbusplus::bus::new_default(); 1086 1087 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, 1088 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1089 MockedGPIOInterface* mockPresenceGPIO = 1090 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1091 EXPECT_EQ(psu.isPresent(), false); 1092 1093 // Change GPIO read to return 1 to indicate present. 1094 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1)); 1095 // Call to analyze() will update to present, that will trigger updating 1096 // to the correct/latest HWMON directory, in case it changes. 1097 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1098 setMissingToPresentExpects(mockPMBus, mockedUtil); 1099 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1100 // for INPUT_HISTORY will check max_power_out to see if it is 1101 // old/unsupported power supply. Indicate good value, supported. 1102 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1103 .WillRepeatedly(Return("2000")); 1104 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN. 1105 // Default expectations will be on, no faults. 1106 PMBusExpectations expectations; 1107 setPMBusExpectations(mockPMBus, expectations); 1108 // Give it an input voltage in the 100-volt range. 1109 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1110 .Times(1) 1111 .WillOnce(Return("123456")); 1112 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1113 psu.analyze(); 1114 EXPECT_EQ(psu.isPresent(), true); 1115 } 1116 1117 TEST_F(PowerSupplyTests, IsFaulted) 1118 { 1119 auto bus = sdbusplus::bus::new_default(); 1120 1121 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, 1122 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1123 MockedGPIOInterface* mockPresenceGPIO = 1124 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1125 // Always return 1 to indicate present. 1126 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1127 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1128 setMissingToPresentExpects(mockPMBus, mockedUtil); 1129 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1130 // for INPUT_HISTORY will check max_power_out to see if it is 1131 // old/unsupported power supply. Indicate good value, supported. 1132 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1133 .WillRepeatedly(Return("2000")); 1134 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN. 1135 // Default expectations will be on, no faults. 1136 PMBusExpectations expectations; 1137 setPMBusExpectations(mockPMBus, expectations); 1138 // Give it an input voltage in the 100-volt range. 1139 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1140 .Times(1) 1141 .WillOnce(Return("124680")); 1142 psu.analyze(); 1143 EXPECT_EQ(psu.isFaulted(), false); 1144 // STATUS_WORD with fault bits on. 1145 expectations.statusWordValue = 0xFFFF; 1146 // STATUS_INPUT with fault bits on. 1147 expectations.statusInputValue = 0xFF; 1148 // STATUS_MFR_SPECIFIC with faults bits on. 1149 expectations.statusMFRValue = 0xFF; 1150 // STATUS_CML with faults bits on. 1151 expectations.statusCMLValue = 0xFF; 1152 // STATUS_VOUT with fault bits on. 1153 expectations.statusVOUTValue = 0xFF; 1154 // STATUS_IOUT with fault bits on. 1155 expectations.statusIOUTValue = 0xFF; 1156 // STATUS_FANS_1_2 with bits on. 1157 expectations.statusFans12Value = 0xFF; 1158 // STATUS_TEMPERATURE with fault bits on. 1159 expectations.statusTempValue = 0xFF; 1160 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1161 { 1162 setPMBusExpectations(mockPMBus, expectations); 1163 // Also get another read of READ_VIN, faulted, so not in 100-volt range 1164 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1165 .Times(1) 1166 .WillOnce(Return("19000")); 1167 if (x == DEGLITCH_LIMIT) 1168 { 1169 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1170 } 1171 psu.analyze(); 1172 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT); 1173 } 1174 } 1175 1176 TEST_F(PowerSupplyTests, HasInputFault) 1177 { 1178 auto bus = sdbusplus::bus::new_default(); 1179 1180 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, 1181 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1182 MockedGPIOInterface* mockPresenceGPIO = 1183 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1184 // Always return 1 to indicate present. 1185 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1186 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1187 setMissingToPresentExpects(mockPMBus, mockedUtil); 1188 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1189 // for INPUT_HISTORY will check max_power_out to see if it is 1190 // old/unsupported power supply. Indicate good value, supported. 1191 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1192 .WillRepeatedly(Return("2000")); 1193 // STATUS_WORD 0x0000 is powered on, no faults. 1194 PMBusExpectations expectations; 1195 setPMBusExpectations(mockPMBus, expectations); 1196 // Analyze call will also need good READ_VIN value to check. 1197 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1198 .Times(1) 1199 .WillOnce(Return("201100")); 1200 psu.analyze(); 1201 EXPECT_EQ(psu.hasInputFault(), false); 1202 // STATUS_WORD with input fault/warn on. 1203 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN); 1204 // STATUS_INPUT with an input fault bit on. 1205 expectations.statusInputValue = 0x80; 1206 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1207 { 1208 setPMBusExpectations(mockPMBus, expectations); 1209 // Analyze call will also need good READ_VIN value to check. 1210 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1211 .Times(1) 1212 .WillOnce(Return("201200")); 1213 if (x == DEGLITCH_LIMIT) 1214 { 1215 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1216 } 1217 psu.analyze(); 1218 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT); 1219 } 1220 // STATUS_WORD with no bits on. 1221 expectations.statusWordValue = 0; 1222 setPMBusExpectations(mockPMBus, expectations); 1223 // Analyze call will also need good READ_VIN value to check. 1224 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1225 .Times(1) 1226 .WillOnce(Return("201300")); 1227 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1228 psu.analyze(); 1229 EXPECT_EQ(psu.hasInputFault(), false); 1230 } 1231 1232 TEST_F(PowerSupplyTests, HasMFRFault) 1233 { 1234 auto bus = sdbusplus::bus::new_default(); 1235 1236 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, 1237 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1238 MockedGPIOInterface* mockPresenceGPIO = 1239 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1240 // Always return 1 to indicate present. 1241 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1242 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1243 setMissingToPresentExpects(mockPMBus, mockedUtil); 1244 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1245 // for INPUT_HISTORY will check max_power_out to see if it is 1246 // old/unsupported power supply. Indicate good value, supported. 1247 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1248 .WillRepeatedly(Return("2000")); 1249 // First return STATUS_WORD with no bits on. 1250 // STATUS_WORD 0x0000 is powered on, no faults. 1251 PMBusExpectations expectations; 1252 setPMBusExpectations(mockPMBus, expectations); 1253 // Analyze call will also need good READ_VIN value to check. 1254 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1255 .Times(1) 1256 .WillOnce(Return("202100")); 1257 psu.analyze(); 1258 EXPECT_EQ(psu.hasMFRFault(), false); 1259 // Next return STATUS_WORD with MFR fault bit on. 1260 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1261 // STATUS_MFR_SPEFIC with bit(s) on. 1262 expectations.statusMFRValue = 0xFF; 1263 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1264 { 1265 setPMBusExpectations(mockPMBus, expectations); 1266 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1267 .Times(1) 1268 .WillOnce(Return("202200")); 1269 psu.analyze(); 1270 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT); 1271 } 1272 // Back to no bits on in STATUS_WORD 1273 expectations.statusWordValue = 0; 1274 setPMBusExpectations(mockPMBus, expectations); 1275 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1276 .Times(1) 1277 .WillOnce(Return("202300")); 1278 psu.analyze(); 1279 EXPECT_EQ(psu.hasMFRFault(), false); 1280 } 1281 1282 TEST_F(PowerSupplyTests, HasVINUVFault) 1283 { 1284 auto bus = sdbusplus::bus::new_default(); 1285 1286 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, 1287 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1288 MockedGPIOInterface* mockPresenceGPIO = 1289 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1290 // Always return 1 to indicate present. 1291 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1292 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1293 setMissingToPresentExpects(mockPMBus, mockedUtil); 1294 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1295 // for INPUT_HISTORY will check max_power_out to see if it is 1296 // old/unsupported power supply. Indicate good value, supported. 1297 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1298 .WillRepeatedly(Return("2000")); 1299 1300 // Presence change from missing to present will trigger in1_input read in 1301 // an attempt to get CLEAR_FAULTS called. Return value ignored. 1302 // Zero to non-zero voltage, for missing/present change, triggers clear 1303 // faults call again. Return value ignored. 1304 // Fault (low voltage) to not faulted (voltage in range) triggers clear 1305 // faults call a third time. 1306 1307 // STATUS_WORD 0x0000 is powered on, no faults. 1308 PMBusExpectations expectations; 1309 setPMBusExpectations(mockPMBus, expectations); 1310 // Analyze call will also need good READ_VIN value to check. 1311 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1312 .Times(1) 1313 .WillOnce(Return("201100")); 1314 psu.analyze(); 1315 EXPECT_EQ(psu.hasVINUVFault(), false); 1316 // Turn fault on. 1317 expectations.statusWordValue = (status_word::VIN_UV_FAULT); 1318 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by 1319 // Figure 16, and assume bits on in STATUS_INPUT. 1320 expectations.statusInputValue = 0x18; 1321 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1322 { 1323 setPMBusExpectations(mockPMBus, expectations); 1324 // If there is a VIN_UV fault, fake reading voltage of less than 20V 1325 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1326 .Times(1) 1327 .WillOnce(Return("19876")); 1328 if (x == DEGLITCH_LIMIT) 1329 { 1330 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1331 } 1332 psu.analyze(); 1333 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT); 1334 } 1335 // Back to no fault bits on in STATUS_WORD 1336 expectations.statusWordValue = 0; 1337 setPMBusExpectations(mockPMBus, expectations); 1338 // Updates now result in clearing faults if read voltage goes from below the 1339 // minimum, to within a valid range. 1340 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1341 .Times(1) 1342 .WillOnce(Return("201300")); 1343 // Went from below minimum to within range, expect clearVinUVFault(). 1344 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 1345 .Times(1) 1346 .WillOnce(Return(1)); 1347 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1348 psu.analyze(); 1349 EXPECT_EQ(psu.hasVINUVFault(), false); 1350 } 1351 1352 TEST_F(PowerSupplyTests, HasVoutOVFault) 1353 { 1354 auto bus = sdbusplus::bus::new_default(); 1355 1356 PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, 1357 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1358 MockedGPIOInterface* mockPresenceGPIO = 1359 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1360 // Always return 1 to indicate present. 1361 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1362 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1363 setMissingToPresentExpects(mockPMBus, mockedUtil); 1364 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1365 // for INPUT_HISTORY will check max_power_out to see if it is 1366 // old/unsupported power supply. Indicate good value, supported. 1367 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1368 .WillRepeatedly(Return("2000")); 1369 // STATUS_WORD 0x0000 is powered on, no faults. 1370 PMBusExpectations expectations; 1371 setPMBusExpectations(mockPMBus, expectations); 1372 // Call to analyze will trigger read of "in1_input" to check voltage. 1373 // Initial value would be 0, so this read updates it to non-zero. 1374 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1375 .Times(1) 1376 .WillOnce(Return("202100")); 1377 psu.analyze(); 1378 EXPECT_EQ(psu.hasVoutOVFault(), false); 1379 // Turn fault on. 1380 expectations.statusWordValue = (status_word::VOUT_OV_FAULT); 1381 // STATUS_VOUT fault bit(s) 1382 expectations.statusVOUTValue = 0x80; 1383 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1384 { 1385 setPMBusExpectations(mockPMBus, expectations); 1386 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1387 .Times(1) 1388 .WillOnce(Return("202200")); 1389 psu.analyze(); 1390 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT); 1391 } 1392 // Back to no fault bits on in STATUS_WORD 1393 expectations.statusWordValue = 0; 1394 setPMBusExpectations(mockPMBus, expectations); 1395 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1396 .Times(1) 1397 .WillOnce(Return("202300")); 1398 psu.analyze(); 1399 EXPECT_EQ(psu.hasVoutOVFault(), false); 1400 } 1401 1402 TEST_F(PowerSupplyTests, HasIoutOCFault) 1403 { 1404 auto bus = sdbusplus::bus::new_default(); 1405 1406 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, 1407 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1408 MockedGPIOInterface* mockPresenceGPIO = 1409 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1410 // Always return 1 to indicate present. 1411 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1412 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1413 setMissingToPresentExpects(mockPMBus, mockedUtil); 1414 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1415 // for INPUT_HISTORY will check max_power_out to see if it is 1416 // old/unsupported power supply. Indicate good value, supported. 1417 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1418 .WillRepeatedly(Return("2000")); 1419 // STATUS_WORD 0x0000 is powered on, no faults. 1420 PMBusExpectations expectations; 1421 setPMBusExpectations(mockPMBus, expectations); 1422 // Call to analyze will trigger read of "in1_input" to check voltage. 1423 // Initial value would be 0, so this read updates it to non-zero. 1424 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1425 .Times(1) 1426 .WillOnce(Return("203100")); 1427 psu.analyze(); 1428 EXPECT_EQ(psu.hasIoutOCFault(), false); 1429 // Turn fault on. 1430 expectations.statusWordValue = status_word::IOUT_OC_FAULT; 1431 // STATUS_IOUT fault bit(s) 1432 expectations.statusIOUTValue = 0x88; 1433 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1434 { 1435 setPMBusExpectations(mockPMBus, expectations); 1436 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1437 .Times(1) 1438 .WillOnce(Return("203200")); 1439 if (x == DEGLITCH_LIMIT) 1440 { 1441 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1442 } 1443 psu.analyze(); 1444 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT); 1445 } 1446 // Back to no fault bits on in STATUS_WORD 1447 expectations.statusWordValue = 0; 1448 setPMBusExpectations(mockPMBus, expectations); 1449 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1450 .Times(1) 1451 .WillOnce(Return("203300")); 1452 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1453 psu.analyze(); 1454 EXPECT_EQ(psu.hasIoutOCFault(), false); 1455 } 1456 1457 TEST_F(PowerSupplyTests, HasVoutUVFault) 1458 { 1459 auto bus = sdbusplus::bus::new_default(); 1460 1461 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, 1462 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1463 MockedGPIOInterface* mockPresenceGPIO = 1464 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1465 // Always return 1 to indicate present. 1466 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1467 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1468 setMissingToPresentExpects(mockPMBus, mockedUtil); 1469 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1470 // for INPUT_HISTORY will check max_power_out to see if it is 1471 // old/unsupported power supply. Indicate good value, supported. 1472 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1473 .WillRepeatedly(Return("2000")); 1474 // STATUS_WORD 0x0000 is powered on, no faults. 1475 PMBusExpectations expectations; 1476 setPMBusExpectations(mockPMBus, expectations); 1477 // Call to analyze will trigger read of "in1_input" to check voltage. 1478 // Initial value would be 0, so this read updates it to non-zero. 1479 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1480 .Times(1) 1481 .WillOnce(Return("204100")); 1482 psu.analyze(); 1483 EXPECT_EQ(psu.hasVoutUVFault(), false); 1484 // Turn fault on. 1485 expectations.statusWordValue = (status_word::VOUT_FAULT); 1486 // STATUS_VOUT fault bit(s) 1487 expectations.statusVOUTValue = 0x30; 1488 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1489 { 1490 setPMBusExpectations(mockPMBus, expectations); 1491 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1492 .Times(1) 1493 .WillOnce(Return("204200")); 1494 psu.analyze(); 1495 EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT); 1496 } 1497 // Back to no fault bits on in STATUS_WORD 1498 expectations.statusWordValue = 0; 1499 setPMBusExpectations(mockPMBus, expectations); 1500 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1501 .Times(1) 1502 .WillOnce(Return("204300")); 1503 psu.analyze(); 1504 EXPECT_EQ(psu.hasVoutUVFault(), false); 1505 } 1506 1507 TEST_F(PowerSupplyTests, HasFanFault) 1508 { 1509 auto bus = sdbusplus::bus::new_default(); 1510 1511 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1); 1512 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0); 1513 1514 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, 1515 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1516 MockedGPIOInterface* mockPresenceGPIO = 1517 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1518 // Always return 1 to indicate present. 1519 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1520 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1521 setMissingToPresentExpects(mockPMBus, mockedUtil); 1522 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1523 // for INPUT_HISTORY will check max_power_out to see if it is 1524 // old/unsupported power supply. Indicate good value, supported. 1525 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1526 .WillRepeatedly(Return("2000")); 1527 // STATUS_WORD 0x0000 is powered on, no faults. 1528 PMBusExpectations expectations; 1529 setPMBusExpectations(mockPMBus, expectations); 1530 // Call to analyze will trigger read of "in1_input" to check voltage. 1531 // Initial value would be 0, so this read updates it to non-zero. 1532 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1533 .Times(1) 1534 .WillOnce(Return("205100")); 1535 psu.analyze(); 1536 EXPECT_EQ(psu.hasFanFault(), false); 1537 // Turn fault on. 1538 expectations.statusWordValue = (status_word::FAN_FAULT); 1539 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault) 1540 expectations.statusFans12Value = 0x80; 1541 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1542 { 1543 setPMBusExpectations(mockPMBus, expectations); 1544 // Call to analyze will trigger read of "in1_input" to check voltage. 1545 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1546 .Times(1) 1547 .WillOnce(Return("205200")); 1548 psu.analyze(); 1549 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT); 1550 } 1551 // Back to no fault bits on in STATUS_WORD 1552 expectations.statusWordValue = 0; 1553 setPMBusExpectations(mockPMBus, expectations); 1554 // Call to analyze will trigger read of "in1_input" to check voltage. 1555 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1556 .Times(1) 1557 .WillOnce(Return("205300")); 1558 psu.analyze(); 1559 EXPECT_EQ(psu.hasFanFault(), false); 1560 } 1561 1562 TEST_F(PowerSupplyTests, HasTempFault) 1563 { 1564 auto bus = sdbusplus::bus::new_default(); 1565 1566 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1); 1567 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0); 1568 1569 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, 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("206100")); 1590 psu.analyze(); 1591 EXPECT_EQ(psu.hasTempFault(), false); 1592 // Turn fault on. 1593 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN); 1594 // STATUS_TEMPERATURE fault bit on (OT Fault) 1595 expectations.statusTempValue = 0x80; 1596 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1597 { 1598 setPMBusExpectations(mockPMBus, expectations); 1599 // Call to analyze will trigger read of "in1_input" to check voltage. 1600 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1601 .Times(1) 1602 .WillOnce(Return("206200")); 1603 psu.analyze(); 1604 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT); 1605 } 1606 // Back to no fault bits on in STATUS_WORD 1607 expectations.statusWordValue = 0; 1608 setPMBusExpectations(mockPMBus, expectations); 1609 // Call to analyze will trigger read of "in1_input" to check voltage. 1610 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1611 .Times(1) 1612 .WillOnce(Return("206300")); 1613 psu.analyze(); 1614 EXPECT_EQ(psu.hasTempFault(), false); 1615 } 1616 1617 TEST_F(PowerSupplyTests, HasPgoodFault) 1618 { 1619 auto bus = sdbusplus::bus::new_default(); 1620 1621 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, 1622 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1623 MockedGPIOInterface* mockPresenceGPIO = 1624 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1625 // Always return 1 to indicate present. 1626 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1627 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1628 setMissingToPresentExpects(mockPMBus, mockedUtil); 1629 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1630 // for INPUT_HISTORY will check max_power_out to see if it is 1631 // old/unsupported power supply. Indicate good value, supported. 1632 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1633 .WillRepeatedly(Return("2000")); 1634 // STATUS_WORD 0x0000 is powered on, no faults. 1635 PMBusExpectations expectations; 1636 setPMBusExpectations(mockPMBus, expectations); 1637 // Call to analyze will trigger read of "in1_input" to check voltage. 1638 // Initial value would be 0, so this read updates it to non-zero. 1639 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1640 .Times(1) 1641 .WillOnce(Return("207100")); 1642 psu.analyze(); 1643 EXPECT_EQ(psu.hasPgoodFault(), false); 1644 // Setup another expectation of no faults. 1645 setPMBusExpectations(mockPMBus, expectations); 1646 // Call to analyze will trigger read of "in1_input" to check voltage. 1647 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1648 .Times(1) 1649 .WillOnce(Return("207200")); 1650 psu.analyze(); 1651 EXPECT_EQ(psu.hasPgoodFault(), false); 1652 // Setup another expectation of no faults. 1653 setPMBusExpectations(mockPMBus, expectations); 1654 // Call to analyze will trigger read of "in1_input" to check voltage. 1655 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1656 .Times(1) 1657 .WillOnce(Return("207300")); 1658 psu.analyze(); 1659 EXPECT_EQ(psu.hasPgoodFault(), false); 1660 // Turn PGOOD# off (fault on). 1661 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED); 1662 setPMBusExpectations(mockPMBus, expectations); 1663 // Call to analyze will trigger read of "in1_input" to check voltage. 1664 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1665 .Times(1) 1666 .WillOnce(Return("207400")); 1667 psu.analyze(); 1668 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 1 1669 EXPECT_EQ(psu.hasPgoodFault(), false); 1670 setPMBusExpectations(mockPMBus, expectations); 1671 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1672 .Times(1) 1673 .WillOnce(Return("207500")); 1674 psu.analyze(); 1675 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 2 1676 EXPECT_EQ(psu.hasPgoodFault(), false); 1677 setPMBusExpectations(mockPMBus, expectations); 1678 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1679 .Times(1) 1680 .WillOnce(Return("207600")); 1681 psu.analyze(); 1682 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 3 1683 EXPECT_EQ(psu.hasPgoodFault(), false); 1684 setPMBusExpectations(mockPMBus, expectations); 1685 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1686 .Times(1) 1687 .WillOnce(Return("207700")); 1688 psu.analyze(); 1689 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 4 1690 EXPECT_EQ(psu.hasPgoodFault(), false); 1691 setPMBusExpectations(mockPMBus, expectations); 1692 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1693 .Times(1) 1694 .WillOnce(Return("207800")); 1695 psu.analyze(); 1696 // Expect true. PGOOD_DEGLITCH_LIMIT @ 5 1697 EXPECT_EQ(psu.hasPgoodFault(), true); 1698 // Back to no fault bits on in STATUS_WORD 1699 expectations.statusWordValue = 0; 1700 setPMBusExpectations(mockPMBus, expectations); 1701 // Call to analyze will trigger read of "in1_input" to check voltage. 1702 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1703 .Times(1) 1704 .WillOnce(Return("207700")); 1705 psu.analyze(); 1706 EXPECT_EQ(psu.hasPgoodFault(), false); 1707 1708 // Turn OFF bit on 1709 expectations.statusWordValue = (status_word::UNIT_IS_OFF); 1710 setPMBusExpectations(mockPMBus, expectations); 1711 // Call to analyze will trigger read of "in1_input" to check voltage. 1712 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1713 .Times(1) 1714 .WillOnce(Return("208100")); 1715 psu.analyze(); 1716 EXPECT_EQ(psu.hasPgoodFault(), false); 1717 setPMBusExpectations(mockPMBus, expectations); 1718 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1719 .Times(1) 1720 .WillOnce(Return("208200")); 1721 psu.analyze(); 1722 EXPECT_EQ(psu.hasPgoodFault(), false); 1723 setPMBusExpectations(mockPMBus, expectations); 1724 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1725 .Times(1) 1726 .WillOnce(Return("208300")); 1727 psu.analyze(); 1728 EXPECT_EQ(psu.hasPgoodFault(), false); 1729 setPMBusExpectations(mockPMBus, expectations); 1730 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1731 .Times(1) 1732 .WillOnce(Return("208400")); 1733 psu.analyze(); 1734 EXPECT_EQ(psu.hasPgoodFault(), false); 1735 setPMBusExpectations(mockPMBus, expectations); 1736 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1737 .Times(1) 1738 .WillOnce(Return("208500")); 1739 psu.analyze(); 1740 EXPECT_EQ(psu.hasPgoodFault(), true); 1741 // Back to no fault bits on in STATUS_WORD 1742 expectations.statusWordValue = 0; 1743 setPMBusExpectations(mockPMBus, expectations); 1744 // Call to analyze will trigger read of "in1_input" to check voltage. 1745 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1746 .Times(1) 1747 .WillOnce(Return("208000")); 1748 psu.analyze(); 1749 EXPECT_EQ(psu.hasPgoodFault(), false); 1750 } 1751 1752 TEST_F(PowerSupplyTests, HasPSKillFault) 1753 { 1754 auto bus = sdbusplus::bus::new_default(); 1755 PowerSupply psu{bus, PSUInventoryPath, 4, 0x6d, 1756 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1757 MockedGPIOInterface* mockPresenceGPIO = 1758 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1759 // Always return 1 to indicate present. 1760 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1761 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1762 setMissingToPresentExpects(mockPMBus, mockedUtil); 1763 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1764 // for INPUT_HISTORY will check max_power_out to see if it is 1765 // old/unsupported power supply. Indicate good value, supported. 1766 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1767 .WillRepeatedly(Return("2000")); 1768 // STATUS_WORD 0x0000 is powered on, no faults. 1769 PMBusExpectations expectations; 1770 setPMBusExpectations(mockPMBus, expectations); 1771 // Call to analyze will trigger read of "in1_input" to check voltage. 1772 // Initial value would be 0, so this read updates it to non-zero. 1773 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1774 .Times(1) 1775 .WillOnce(Return("208100")); 1776 psu.analyze(); 1777 EXPECT_EQ(psu.hasPSKillFault(), false); 1778 // Next return STATUS_WORD with MFR fault bit on. 1779 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1780 // STATUS_MFR_SPEFIC with bit(s) on. 1781 expectations.statusMFRValue = 0xFF; 1782 1783 // Deglitching faults, false until read the fault bits on up to the limit. 1784 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1785 { 1786 setPMBusExpectations(mockPMBus, expectations); 1787 // Call to analyze will trigger read of "in1_input" to check voltage. 1788 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1789 .Times(1) 1790 .WillOnce(Return("208200")); 1791 if (x == DEGLITCH_LIMIT) 1792 { 1793 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1794 } 1795 psu.analyze(); 1796 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT); 1797 } 1798 1799 // Back to no bits on in STATUS_WORD 1800 expectations.statusWordValue = 0; 1801 setPMBusExpectations(mockPMBus, expectations); 1802 // Call to analyze will trigger read of "in1_input" to check voltage. 1803 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1804 .Times(1) 1805 .WillOnce(Return("208300")); 1806 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1807 psu.analyze(); 1808 EXPECT_EQ(psu.hasPSKillFault(), false); 1809 // Next return STATUS_WORD with MFR fault bit on. 1810 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1811 // STATUS_MFR_SPEFIC with bit 4 on. 1812 expectations.statusMFRValue = 0x10; 1813 1814 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1815 { 1816 setPMBusExpectations(mockPMBus, expectations); 1817 // Call to analyze will trigger read of "in1_input" to check voltage. 1818 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1819 .Times(1) 1820 .WillOnce(Return("208400")); 1821 if (x == DEGLITCH_LIMIT) 1822 { 1823 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1824 } 1825 psu.analyze(); 1826 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT); 1827 } 1828 1829 // Back to no bits on in STATUS_WORD 1830 expectations.statusWordValue = 0; 1831 setPMBusExpectations(mockPMBus, expectations); 1832 // Call to analyze will trigger read of "in1_input" to check voltage. 1833 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1834 .Times(1) 1835 .WillOnce(Return("208500")); 1836 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1837 psu.analyze(); 1838 EXPECT_EQ(psu.hasPSKillFault(), false); 1839 } 1840 1841 TEST_F(PowerSupplyTests, HasPS12VcsFault) 1842 { 1843 auto bus = sdbusplus::bus::new_default(); 1844 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6e, 1845 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1846 MockedGPIOInterface* mockPresenceGPIO = 1847 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1848 // Always return 1 to indicate present. 1849 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1850 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1851 setMissingToPresentExpects(mockPMBus, mockedUtil); 1852 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1853 // for INPUT_HISTORY will check max_power_out to see if it is 1854 // old/unsupported power supply. Indicate good value, supported. 1855 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1856 .WillRepeatedly(Return("2000")); 1857 // STATUS_WORD 0x0000 is powered on, no faults. 1858 PMBusExpectations expectations; 1859 setPMBusExpectations(mockPMBus, expectations); 1860 // Call to analyze will trigger read of "in1_input" to check voltage. 1861 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1862 .Times(1) 1863 .WillOnce(Return("209100")); 1864 psu.analyze(); 1865 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1866 // Next return STATUS_WORD with MFR fault bit on. 1867 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1868 // STATUS_MFR_SPEFIC with bit(s) on. 1869 expectations.statusMFRValue = 0xFF; 1870 1871 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1872 { 1873 setPMBusExpectations(mockPMBus, expectations); 1874 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1875 .Times(1) 1876 .WillOnce(Return("209200")); 1877 psu.analyze(); 1878 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT); 1879 } 1880 1881 // Back to no bits on in STATUS_WORD 1882 expectations.statusWordValue = 0; 1883 setPMBusExpectations(mockPMBus, expectations); 1884 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1885 .Times(1) 1886 .WillOnce(Return("209300")); 1887 psu.analyze(); 1888 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1889 // Next return STATUS_WORD with MFR fault bit on. 1890 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1891 // STATUS_MFR_SPEFIC with bit 6 on. 1892 expectations.statusMFRValue = 0x40; 1893 1894 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1895 { 1896 setPMBusExpectations(mockPMBus, expectations); 1897 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1898 .Times(1) 1899 .WillOnce(Return("209400")); 1900 psu.analyze(); 1901 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT); 1902 } 1903 1904 // Back to no bits on in STATUS_WORD 1905 expectations.statusWordValue = 0; 1906 setPMBusExpectations(mockPMBus, expectations); 1907 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1908 .Times(1) 1909 .WillOnce(Return("209500")); 1910 psu.analyze(); 1911 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1912 } 1913 1914 TEST_F(PowerSupplyTests, HasPSCS12VFault) 1915 { 1916 auto bus = sdbusplus::bus::new_default(); 1917 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f, 1918 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1919 MockedGPIOInterface* mockPresenceGPIO = 1920 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1921 // Always return 1 to indicate present. 1922 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1923 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1924 setMissingToPresentExpects(mockPMBus, mockedUtil); 1925 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 1926 // for INPUT_HISTORY will check max_power_out to see if it is 1927 // old/unsupported power supply. Indicate good value, supported. 1928 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 1929 .WillRepeatedly(Return("2000")); 1930 // STATUS_WORD 0x0000 is powered on, no faults. 1931 PMBusExpectations expectations; 1932 setPMBusExpectations(mockPMBus, expectations); 1933 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1934 .Times(1) 1935 .WillOnce(Return("209100")); 1936 psu.analyze(); 1937 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1938 // Next return STATUS_WORD with MFR fault bit on. 1939 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1940 // STATUS_MFR_SPEFIC with bit(s) on. 1941 expectations.statusMFRValue = 0xFF; 1942 1943 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1944 { 1945 setPMBusExpectations(mockPMBus, expectations); 1946 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1947 .Times(1) 1948 .WillOnce(Return("209200")); 1949 psu.analyze(); 1950 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT); 1951 } 1952 1953 // Back to no bits on in STATUS_WORD 1954 expectations.statusWordValue = 0; 1955 setPMBusExpectations(mockPMBus, expectations); 1956 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1957 .Times(1) 1958 .WillOnce(Return("209300")); 1959 psu.analyze(); 1960 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1961 // Next return STATUS_WORD with MFR fault bit on. 1962 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1963 // STATUS_MFR_SPEFIC with bit 7 on. 1964 expectations.statusMFRValue = 0x80; 1965 1966 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1967 { 1968 setPMBusExpectations(mockPMBus, expectations); 1969 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1970 .Times(1) 1971 .WillOnce(Return("209400")); 1972 psu.analyze(); 1973 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT); 1974 } 1975 1976 // Back to no bits on in STATUS_WORD 1977 expectations.statusWordValue = 0; 1978 setPMBusExpectations(mockPMBus, expectations); 1979 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1980 .Times(1) 1981 .WillOnce(Return("209500")); 1982 psu.analyze(); 1983 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1984 } 1985 1986 TEST_F(PowerSupplyTests, PeakInputPowerSensor) 1987 { 1988 auto bus = sdbusplus::bus::new_default(); 1989 { 1990 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f, 1991 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 1992 EXPECT_EQ(psu.getPeakInputPower(), std::nullopt); 1993 1994 MockedGPIOInterface* mockPresenceGPIO = 1995 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1996 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 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 .Times(1) 2005 .WillOnce(Return("206000")); 2006 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 2007 .WillRepeatedly(Return("2000")); 2008 2009 psu.analyze(); 2010 EXPECT_EQ(psu.getPeakInputPower().value_or(0), 213); 2011 } 2012 2013 // Test that there is no peak power sensor on 1400W PSs 2014 { 2015 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, 2016 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 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 2025 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 2026 .WillRepeatedly(Return("30725")); 2027 2028 PMBusExpectations expectations; 2029 setPMBusExpectations(mockPMBus, expectations); 2030 2031 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 2032 .WillRepeatedly(Return("206000")); 2033 psu.analyze(); 2034 2035 EXPECT_EQ(psu.getPeakInputPower(), std::nullopt); 2036 } 2037 2038 // Test that IPSPS power supplies don't have peak power 2039 { 2040 PowerSupply psu{bus, PSUInventoryPath, 11, 2041 0x58, "inspur-ipsps", PSUGPIOLineName, 2042 isPowerOn}; 2043 2044 MockedGPIOInterface* mockPresenceGPIO = 2045 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 2046 2047 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 2048 2049 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 2050 2051 setMissingToPresentExpects(mockPMBus, mockedUtil); 2052 PMBusExpectations expectations; 2053 setPMBusExpectations(mockPMBus, expectations); 2054 2055 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 2056 .WillRepeatedly(Return("206000")); 2057 2058 psu.analyze(); 2059 2060 EXPECT_EQ(psu.getPeakInputPower(), std::nullopt); 2061 } 2062 2063 // Test that a bad response from the input_history command leads 2064 // to an NaN value. 2065 { 2066 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f, 2067 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 2068 2069 MockedGPIOInterface* mockPresenceGPIO = 2070 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 2071 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 2072 2073 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 2074 2075 setMissingToPresentExpects(mockPMBus, mockedUtil); 2076 PMBusExpectations expectations; 2077 setPMBusExpectations(mockPMBus, expectations); 2078 2079 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 2080 .Times(1) 2081 .WillOnce(Return("206000")); 2082 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 2083 .WillRepeatedly(Return("2000")); 2084 2085 // Don't return the full 5 bytes. 2086 EXPECT_CALL(mockPMBus, 2087 readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug, 5)) 2088 .WillRepeatedly(Return(std::vector<uint8_t>{0x01, 0x5c})); 2089 2090 psu.analyze(); 2091 EXPECT_THAT(psu.getPeakInputPower().value_or(0), IsNan()); 2092 } 2093 } 2094 2095 TEST_F(PowerSupplyTests, IsSyncHistoryRequired) 2096 { 2097 auto bus = sdbusplus::bus::new_default(); 2098 PowerSupply psu{bus, PSUInventoryPath, 8, 0x6f, 2099 "ibm-cffps", PSUGPIOLineName, isPowerOn}; 2100 EXPECT_EQ(psu.isSyncHistoryRequired(), false); 2101 MockedGPIOInterface* mockPresenceGPIO = 2102 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 2103 // Always return 1 to indicate present. 2104 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 2105 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 2106 setMissingToPresentExpects(mockPMBus, mockedUtil); 2107 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup 2108 // for INPUT_HISTORY will check max_power_out to see if it is 2109 // old/unsupported power supply. Indicate good value, supported. 2110 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _)) 2111 .WillRepeatedly(Return("2000")); 2112 PMBusExpectations expectations; 2113 setPMBusExpectations(mockPMBus, expectations); 2114 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 2115 .Times(1) 2116 .WillRepeatedly(Return("205000")); 2117 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 2118 psu.analyze(); 2119 // Missing -> Present requires history sync 2120 EXPECT_EQ(psu.isSyncHistoryRequired(), true); 2121 psu.clearSyncHistoryRequired(); 2122 EXPECT_EQ(psu.isSyncHistoryRequired(), false); 2123 } 2124 2125 TEST_F(PowerSupplyTests, TestLinearConversions) 2126 { 2127 // Mantissa > 0, exponent = 0 2128 EXPECT_EQ(0, PowerSupply::linearToInteger(0)); 2129 EXPECT_EQ(1, PowerSupply::linearToInteger(1)); 2130 EXPECT_EQ(38, PowerSupply::linearToInteger(0x26)); 2131 EXPECT_EQ(1023, PowerSupply::linearToInteger(0x3FF)); 2132 2133 // Mantissa < 0, exponent = 0 2134 EXPECT_EQ(-1, PowerSupply::linearToInteger(0x7FF)); 2135 EXPECT_EQ(-20, PowerSupply::linearToInteger(0x7EC)); 2136 EXPECT_EQ(-769, PowerSupply::linearToInteger(0x4FF)); 2137 EXPECT_EQ(-989, PowerSupply::linearToInteger(0x423)); 2138 EXPECT_EQ(-1024, PowerSupply::linearToInteger(0x400)); 2139 2140 // Mantissa >= 0, exponent > 0 2141 // M = 1, E = 2 2142 EXPECT_EQ(4, PowerSupply::linearToInteger(0x1001)); 2143 2144 // M = 1000, E = 10 2145 EXPECT_EQ(1024000, PowerSupply::linearToInteger(0x53E8)); 2146 2147 // M = 10, E = 15 2148 EXPECT_EQ(327680, PowerSupply::linearToInteger(0x780A)); 2149 2150 // Mantissa >= 0, exponent < 0 2151 // M = 0, E = -1 2152 EXPECT_EQ(0, PowerSupply::linearToInteger(0xF800)); 2153 2154 // M = 100, E = -2 2155 EXPECT_EQ(25, PowerSupply::linearToInteger(0xF064)); 2156 2157 // Mantissa < 0, exponent < 0 2158 // M = -100, E = -1 2159 EXPECT_EQ(-50, PowerSupply::linearToInteger(0xFF9C)); 2160 2161 // M = -1024, E = -7 2162 EXPECT_EQ(-8, PowerSupply::linearToInteger(0xCC00)); 2163 } 2164