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