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