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 260 // STATUS_WORD INPUT fault. 261 { 262 // Start with STATUS_WORD 0x0000. Powered on, no faults. 263 // Set expectations for a no fault 264 PMBusExpectations expectations; 265 setPMBusExpectations(mockPMBus, expectations); 266 // After reading STATUS_WORD, etc., there will be a READ_VIN check. 267 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 268 .Times(1) 269 .WillOnce(Return("206000")); 270 psu2.analyze(); 271 EXPECT_EQ(psu2.isPresent(), true); 272 EXPECT_EQ(psu2.isFaulted(), false); 273 EXPECT_EQ(psu2.hasInputFault(), false); 274 EXPECT_EQ(psu2.hasMFRFault(), false); 275 EXPECT_EQ(psu2.hasVINUVFault(), false); 276 EXPECT_EQ(psu2.hasCommFault(), false); 277 EXPECT_EQ(psu2.hasVoutOVFault(), false); 278 EXPECT_EQ(psu2.hasIoutOCFault(), false); 279 EXPECT_EQ(psu2.hasVoutUVFault(), false); 280 EXPECT_EQ(psu2.hasFanFault(), false); 281 EXPECT_EQ(psu2.hasTempFault(), false); 282 EXPECT_EQ(psu2.hasPgoodFault(), false); 283 EXPECT_EQ(psu2.hasPSKillFault(), false); 284 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 285 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 286 287 // Update expectations for STATUS_WORD input fault/warn 288 // STATUS_INPUT fault bits ... on. 289 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN); 290 // IIN_OC fault. 291 expectations.statusInputValue = 0x04; 292 293 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 294 { 295 setPMBusExpectations(mockPMBus, expectations); 296 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 297 .Times(1) 298 .WillOnce(Return("207000")); 299 psu2.analyze(); 300 EXPECT_EQ(psu2.isPresent(), true); 301 // Should not be faulted until it reaches the deglitch limit. 302 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 303 EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT); 304 EXPECT_EQ(psu2.hasMFRFault(), false); 305 EXPECT_EQ(psu2.hasVINUVFault(), false); 306 EXPECT_EQ(psu2.hasCommFault(), false); 307 EXPECT_EQ(psu2.hasVoutOVFault(), false); 308 EXPECT_EQ(psu2.hasIoutOCFault(), false); 309 EXPECT_EQ(psu2.hasVoutUVFault(), false); 310 EXPECT_EQ(psu2.hasFanFault(), false); 311 EXPECT_EQ(psu2.hasTempFault(), false); 312 EXPECT_EQ(psu2.hasPgoodFault(), false); 313 EXPECT_EQ(psu2.hasPSKillFault(), false); 314 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 315 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 316 } 317 } 318 319 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1)); 320 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 321 .Times(1) 322 .WillOnce(Return(1)); 323 psu2.clearFaults(); 324 325 // STATUS_WORD INPUT/UV fault. 326 { 327 // First need it to return good status, then the fault 328 PMBusExpectations expectations; 329 setPMBusExpectations(mockPMBus, expectations); 330 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 331 .Times(1) 332 .WillOnce(Return("208000")); 333 psu2.analyze(); 334 EXPECT_EQ(psu2.isFaulted(), false); 335 EXPECT_EQ(psu2.hasInputFault(), false); 336 // Now set fault bits in STATUS_WORD 337 expectations.statusWordValue = 338 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT); 339 // STATUS_INPUT fault bits ... on. 340 expectations.statusInputValue = 0x18; 341 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 342 { 343 setPMBusExpectations(mockPMBus, expectations); 344 // Input/UV fault, so voltage should read back low. 345 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 346 .Times(1) 347 .WillOnce(Return("19123")); 348 psu2.analyze(); 349 EXPECT_EQ(psu2.isPresent(), true); 350 // Only faulted if hit deglitch limit 351 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 352 EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT); 353 EXPECT_EQ(psu2.hasVINUVFault(), x >= DEGLITCH_LIMIT); 354 EXPECT_EQ(psu2.hasMFRFault(), false); 355 EXPECT_EQ(psu2.hasCommFault(), false); 356 EXPECT_EQ(psu2.hasVoutOVFault(), false); 357 EXPECT_EQ(psu2.hasIoutOCFault(), false); 358 EXPECT_EQ(psu2.hasVoutUVFault(), false); 359 EXPECT_EQ(psu2.hasFanFault(), false); 360 EXPECT_EQ(psu2.hasTempFault(), false); 361 EXPECT_EQ(psu2.hasPgoodFault(), false); 362 EXPECT_EQ(psu2.hasPSKillFault(), false); 363 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 364 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 365 } 366 // Turning VIN_UV fault off causes clearing of faults, causing read of 367 // in1_input as an attempt to get CLEAR_FAULTS called. 368 expectations.statusWordValue = 0; 369 setPMBusExpectations(mockPMBus, expectations); 370 // The call to read the voltage 371 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 372 .Times(1) 373 .WillOnce(Return("209000")); 374 // The call to clear VIN_UV/Off fault(s) 375 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 376 .Times(1) 377 .WillOnce(Return(1)); 378 psu2.analyze(); 379 // Should remain present, no longer be faulted, no input fault, no 380 // VIN_UV fault. Nothing else should change. 381 EXPECT_EQ(psu2.isPresent(), true); 382 EXPECT_EQ(psu2.isFaulted(), false); 383 EXPECT_EQ(psu2.hasInputFault(), false); 384 EXPECT_EQ(psu2.hasVINUVFault(), false); 385 } 386 387 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1)); 388 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 389 .Times(1) 390 .WillOnce(Return(1)); 391 psu2.clearFaults(); 392 393 // STATUS_WORD MFR fault. 394 { 395 // First need it to return good status, then the fault 396 PMBusExpectations expectations; 397 setPMBusExpectations(mockPMBus, expectations); 398 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 399 .Times(1) 400 .WillOnce(Return("210000")); 401 psu2.analyze(); 402 // Now STATUS_WORD with MFR fault bit on. 403 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 404 // STATUS_MFR bits on. 405 expectations.statusMFRValue = 0xFF; 406 407 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 408 { 409 setPMBusExpectations(mockPMBus, expectations); 410 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 411 .Times(1) 412 .WillOnce(Return("211000")); 413 psu2.analyze(); 414 EXPECT_EQ(psu2.isPresent(), true); 415 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 416 EXPECT_EQ(psu2.hasInputFault(), false); 417 EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT); 418 EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT); 419 EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT); 420 EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT); 421 EXPECT_EQ(psu2.hasVINUVFault(), false); 422 EXPECT_EQ(psu2.hasCommFault(), false); 423 EXPECT_EQ(psu2.hasVoutOVFault(), false); 424 EXPECT_EQ(psu2.hasIoutOCFault(), false); 425 EXPECT_EQ(psu2.hasVoutUVFault(), false); 426 EXPECT_EQ(psu2.hasFanFault(), false); 427 EXPECT_EQ(psu2.hasTempFault(), false); 428 EXPECT_EQ(psu2.hasPgoodFault(), false); 429 } 430 } 431 432 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1)); 433 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 434 .Times(1) 435 .WillOnce(Return(1)); 436 psu2.clearFaults(); 437 438 // Temperature fault. 439 { 440 // First STATUS_WORD with no bits set, then with temperature fault. 441 PMBusExpectations expectations; 442 setPMBusExpectations(mockPMBus, expectations); 443 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 444 .Times(1) 445 .WillOnce(Return("212000")); 446 psu2.analyze(); 447 // STATUS_WORD with temperature fault bit on. 448 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN); 449 // STATUS_TEMPERATURE with fault bit(s) on. 450 expectations.statusTempValue = 0x10; 451 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 452 { 453 setPMBusExpectations(mockPMBus, expectations); 454 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 455 .Times(1) 456 .WillOnce(Return("213000")); 457 psu2.analyze(); 458 EXPECT_EQ(psu2.isPresent(), true); 459 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 460 EXPECT_EQ(psu2.hasInputFault(), false); 461 EXPECT_EQ(psu2.hasMFRFault(), false); 462 EXPECT_EQ(psu2.hasVINUVFault(), false); 463 EXPECT_EQ(psu2.hasCommFault(), false); 464 EXPECT_EQ(psu2.hasVoutOVFault(), false); 465 EXPECT_EQ(psu2.hasIoutOCFault(), false); 466 EXPECT_EQ(psu2.hasVoutUVFault(), false); 467 EXPECT_EQ(psu2.hasFanFault(), false); 468 EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT); 469 EXPECT_EQ(psu2.hasPgoodFault(), false); 470 EXPECT_EQ(psu2.hasPSKillFault(), false); 471 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 472 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 473 } 474 } 475 476 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1)); 477 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 478 .Times(1) 479 .WillOnce(Return(1)); 480 psu2.clearFaults(); 481 482 // CML fault 483 { 484 // First STATUS_WORD wit no bits set, then with CML fault. 485 PMBusExpectations expectations; 486 setPMBusExpectations(mockPMBus, expectations); 487 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 488 .Times(1) 489 .WillOnce(Return("214000")); 490 psu2.analyze(); 491 // STATUS_WORD with CML fault bit on. 492 expectations.statusWordValue = (status_word::CML_FAULT); 493 // Turn on STATUS_CML fault bit(s) 494 expectations.statusCMLValue = 0xFF; 495 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 496 { 497 setPMBusExpectations(mockPMBus, expectations); 498 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 499 .Times(1) 500 .WillOnce(Return("215000")); 501 psu2.analyze(); 502 EXPECT_EQ(psu2.isPresent(), true); 503 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 504 EXPECT_EQ(psu2.hasCommFault(), x >= DEGLITCH_LIMIT); 505 EXPECT_EQ(psu2.hasInputFault(), false); 506 EXPECT_EQ(psu2.hasMFRFault(), false); 507 EXPECT_EQ(psu2.hasVINUVFault(), false); 508 EXPECT_EQ(psu2.hasVoutOVFault(), false); 509 EXPECT_EQ(psu2.hasIoutOCFault(), false); 510 EXPECT_EQ(psu2.hasVoutUVFault(), false); 511 EXPECT_EQ(psu2.hasFanFault(), false); 512 EXPECT_EQ(psu2.hasTempFault(), false); 513 EXPECT_EQ(psu2.hasPgoodFault(), false); 514 EXPECT_EQ(psu2.hasPSKillFault(), false); 515 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 516 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 517 } 518 } 519 520 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1)); 521 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 522 .Times(1) 523 .WillOnce(Return(1)); 524 psu2.clearFaults(); 525 526 // VOUT_OV_FAULT fault 527 { 528 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault. 529 PMBusExpectations expectations; 530 setPMBusExpectations(mockPMBus, expectations); 531 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 532 .Times(1) 533 .WillOnce(Return("216000")); 534 psu2.analyze(); 535 // STATUS_WORD with VOUT/VOUT_OV fault. 536 expectations.statusWordValue = 537 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT)); 538 // Turn on STATUS_VOUT fault bit(s) 539 expectations.statusVOUTValue = 0xA0; 540 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 541 { 542 // STATUS_TEMPERATURE don't care (default) 543 setPMBusExpectations(mockPMBus, expectations); 544 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 545 .Times(1) 546 .WillOnce(Return("217000")); 547 psu2.analyze(); 548 EXPECT_EQ(psu2.isPresent(), true); 549 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 550 EXPECT_EQ(psu2.hasInputFault(), false); 551 EXPECT_EQ(psu2.hasMFRFault(), false); 552 EXPECT_EQ(psu2.hasVINUVFault(), false); 553 EXPECT_EQ(psu2.hasCommFault(), false); 554 EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT); 555 EXPECT_EQ(psu2.hasVoutUVFault(), false); 556 EXPECT_EQ(psu2.hasIoutOCFault(), false); 557 EXPECT_EQ(psu2.hasFanFault(), false); 558 EXPECT_EQ(psu2.hasTempFault(), false); 559 EXPECT_EQ(psu2.hasPgoodFault(), false); 560 EXPECT_EQ(psu2.hasPSKillFault(), false); 561 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 562 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 563 } 564 } 565 566 // IOUT_OC_FAULT fault 567 { 568 // First STATUS_WORD with no bits set, then with IOUT_OC fault. 569 PMBusExpectations expectations; 570 setPMBusExpectations(mockPMBus, expectations); 571 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 572 .Times(1) 573 .WillOnce(Return("218000")); 574 psu2.analyze(); 575 // STATUS_WORD with IOUT_OC fault. 576 expectations.statusWordValue = status_word::IOUT_OC_FAULT; 577 // Turn on STATUS_IOUT fault bit(s) 578 expectations.statusIOUTValue = 0x88; 579 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 580 { 581 setPMBusExpectations(mockPMBus, expectations); 582 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 583 .Times(1) 584 .WillOnce(Return("219000")); 585 psu2.analyze(); 586 EXPECT_EQ(psu2.isPresent(), true); 587 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 588 EXPECT_EQ(psu2.hasInputFault(), false); 589 EXPECT_EQ(psu2.hasMFRFault(), false); 590 EXPECT_EQ(psu2.hasVINUVFault(), false); 591 EXPECT_EQ(psu2.hasCommFault(), false); 592 EXPECT_EQ(psu2.hasVoutOVFault(), false); 593 EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT); 594 EXPECT_EQ(psu2.hasVoutUVFault(), false); 595 EXPECT_EQ(psu2.hasFanFault(), false); 596 EXPECT_EQ(psu2.hasTempFault(), false); 597 EXPECT_EQ(psu2.hasPgoodFault(), false); 598 EXPECT_EQ(psu2.hasPSKillFault(), false); 599 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 600 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 601 } 602 } 603 604 // VOUT_UV_FAULT 605 { 606 // First STATUS_WORD with no bits set, then with VOUT fault. 607 PMBusExpectations expectations; 608 setPMBusExpectations(mockPMBus, expectations); 609 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 610 .Times(1) 611 .WillOnce(Return("220000")); 612 psu2.analyze(); 613 // Change STATUS_WORD to indicate VOUT fault. 614 expectations.statusWordValue = (status_word::VOUT_FAULT); 615 // Turn on STATUS_VOUT fault bit(s) 616 expectations.statusVOUTValue = 0x30; 617 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 618 { 619 setPMBusExpectations(mockPMBus, expectations); 620 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 621 .Times(1) 622 .WillOnce(Return("221000")); 623 psu2.analyze(); 624 EXPECT_EQ(psu2.isPresent(), true); 625 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 626 EXPECT_EQ(psu2.hasInputFault(), false); 627 EXPECT_EQ(psu2.hasMFRFault(), false); 628 EXPECT_EQ(psu2.hasVINUVFault(), false); 629 EXPECT_EQ(psu2.hasCommFault(), false); 630 EXPECT_EQ(psu2.hasVoutOVFault(), false); 631 EXPECT_EQ(psu2.hasIoutOCFault(), false); 632 EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT); 633 EXPECT_EQ(psu2.hasFanFault(), false); 634 EXPECT_EQ(psu2.hasTempFault(), false); 635 EXPECT_EQ(psu2.hasPgoodFault(), false); 636 EXPECT_EQ(psu2.hasPSKillFault(), false); 637 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 638 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 639 } 640 } 641 642 // Fan fault 643 { 644 // First STATUS_WORD with no bits set, then with fan fault. 645 PMBusExpectations expectations; 646 setPMBusExpectations(mockPMBus, expectations); 647 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 648 .Times(1) 649 .WillOnce(Return("222000")); 650 psu2.analyze(); 651 expectations.statusWordValue = (status_word::FAN_FAULT); 652 // STATUS_FANS_1_2 with fan 1 warning & fault bits on. 653 expectations.statusFans12Value = 0xA0; 654 655 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 656 { 657 setPMBusExpectations(mockPMBus, expectations); 658 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 659 .Times(1) 660 .WillOnce(Return("223000")); 661 psu2.analyze(); 662 EXPECT_EQ(psu2.isPresent(), true); 663 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 664 EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT); 665 EXPECT_EQ(psu2.hasInputFault(), false); 666 EXPECT_EQ(psu2.hasMFRFault(), false); 667 EXPECT_EQ(psu2.hasVINUVFault(), false); 668 EXPECT_EQ(psu2.hasCommFault(), false); 669 EXPECT_EQ(psu2.hasVoutOVFault(), false); 670 EXPECT_EQ(psu2.hasIoutOCFault(), false); 671 EXPECT_EQ(psu2.hasVoutUVFault(), false); 672 EXPECT_EQ(psu2.hasTempFault(), false); 673 EXPECT_EQ(psu2.hasPgoodFault(), false); 674 EXPECT_EQ(psu2.hasPSKillFault(), false); 675 EXPECT_EQ(psu2.hasPS12VcsFault(), false); 676 EXPECT_EQ(psu2.hasPSCS12VFault(), false); 677 } 678 } 679 680 // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT. 681 { 682 // First STATUS_WORD with no bits set. 683 PMBusExpectations expectations; 684 setPMBusExpectations(mockPMBus, expectations); 685 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 686 .Times(1) 687 .WillOnce(Return("123000")); 688 psu2.analyze(); 689 EXPECT_EQ(psu2.isFaulted(), false); 690 // POWER_GOOD# inactive, and OFF bit on. 691 expectations.statusWordValue = 692 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF)); 693 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 694 { 695 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and 696 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults). 697 setPMBusExpectations(mockPMBus, expectations); 698 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 699 .Times(1) 700 .WillOnce(Return("124000")); 701 psu2.analyze(); 702 EXPECT_EQ(psu2.isPresent(), true); 703 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT); 704 EXPECT_EQ(psu2.hasInputFault(), false); 705 EXPECT_EQ(psu2.hasMFRFault(), false); 706 EXPECT_EQ(psu2.hasVINUVFault(), false); 707 EXPECT_EQ(psu2.hasCommFault(), false); 708 EXPECT_EQ(psu2.hasVoutOVFault(), false); 709 EXPECT_EQ(psu2.hasVoutUVFault(), false); 710 EXPECT_EQ(psu2.hasIoutOCFault(), false); 711 EXPECT_EQ(psu2.hasFanFault(), false); 712 EXPECT_EQ(psu2.hasTempFault(), false); 713 EXPECT_EQ(psu2.hasPgoodFault(), x >= DEGLITCH_LIMIT); 714 } 715 } 716 717 // TODO: ReadFailure 718 } 719 720 TEST_F(PowerSupplyTests, OnOffConfig) 721 { 722 auto bus = sdbusplus::bus::new_default(); 723 uint8_t data = 0x15; 724 725 // Test where PSU is NOT present 726 try 727 { 728 // Assume GPIO presence, not inventory presence? 729 EXPECT_CALL(mockedUtil, setAvailable(_, _, _)).Times(0); 730 PowerSupply psu{bus, PSUInventoryPath, 4, 731 0x69, "ibm-cffps", PSUGPIOLineName}; 732 733 MockedGPIOInterface* mockPresenceGPIO = 734 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 735 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0)); 736 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 737 // Constructor should set initial presence, default read returns 0. 738 // If it is not present, I should not be trying to write to it. 739 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0); 740 psu.onOffConfig(data); 741 } 742 catch (...) 743 {} 744 745 // Test where PSU is present 746 try 747 { 748 // Assume GPIO presence, not inventory presence? 749 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 750 PowerSupply psu{bus, PSUInventoryPath, 5, 751 0x6a, "ibm-cffps", PSUGPIOLineName}; 752 MockedGPIOInterface* mockPresenceGPIO = 753 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 754 // There will potentially be multiple calls, we want it to continue 755 // returning 1 for the GPIO read to keep the power supply present. 756 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 757 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 758 setMissingToPresentExpects(mockPMBus, mockedUtil); 759 // If I am calling analyze(), I should probably give it good data. 760 // STATUS_WORD 0x0000 is powered on, no faults. 761 PMBusExpectations expectations; 762 setPMBusExpectations(mockPMBus, expectations); 763 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 764 .Times(1) 765 .WillOnce(Return("205000")); 766 psu.analyze(); 767 // I definitely should be writting ON_OFF_CONFIG if I call the function 768 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15), 769 Type::HwmonDeviceDebug)) 770 .Times(1); 771 psu.onOffConfig(data); 772 } 773 catch (...) 774 {} 775 } 776 777 TEST_F(PowerSupplyTests, ClearFaults) 778 { 779 auto bus = sdbusplus::bus::new_default(); 780 PowerSupply psu{bus, PSUInventoryPath, 13, 781 0x68, "ibm-cffps", PSUGPIOLineName}; 782 MockedGPIOInterface* mockPresenceGPIO = 783 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 784 // Always return 1 to indicate present. 785 // Each analyze() call will trigger a read of the presence GPIO. 786 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 787 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 788 setMissingToPresentExpects(mockPMBus, mockedUtil); 789 // STATUS_WORD 0x0000 is powered on, no faults. 790 PMBusExpectations expectations; 791 setPMBusExpectations(mockPMBus, expectations); 792 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 793 .Times(1) 794 .WillOnce(Return("207000")); 795 psu.analyze(); 796 EXPECT_EQ(psu.isPresent(), true); 797 EXPECT_EQ(psu.isFaulted(), false); 798 EXPECT_EQ(psu.hasInputFault(), false); 799 EXPECT_EQ(psu.hasMFRFault(), false); 800 EXPECT_EQ(psu.hasVINUVFault(), false); 801 EXPECT_EQ(psu.hasCommFault(), false); 802 EXPECT_EQ(psu.hasVoutOVFault(), false); 803 EXPECT_EQ(psu.hasIoutOCFault(), false); 804 EXPECT_EQ(psu.hasVoutUVFault(), false); 805 EXPECT_EQ(psu.hasFanFault(), false); 806 EXPECT_EQ(psu.hasTempFault(), false); 807 EXPECT_EQ(psu.hasPgoodFault(), false); 808 EXPECT_EQ(psu.hasPSKillFault(), false); 809 EXPECT_EQ(psu.hasPS12VcsFault(), false); 810 EXPECT_EQ(psu.hasPSCS12VFault(), false); 811 812 // STATUS_WORD with fault bits galore! 813 expectations.statusWordValue = 0xFFFF; 814 // STATUS_INPUT with fault bits on. 815 expectations.statusInputValue = 0xFF; 816 // STATUS_MFR_SPEFIC with bits on. 817 expectations.statusMFRValue = 0xFF; 818 // STATUS_CML with bits on. 819 expectations.statusCMLValue = 0xFF; 820 // STATUS_VOUT with bits on. 821 expectations.statusVOUTValue = 0xFF; 822 // STATUS_IOUT with bits on. 823 expectations.statusIOUTValue = 0xFF; 824 // STATUS_FANS_1_2 with bits on. 825 expectations.statusFans12Value = 0xFF; 826 // STATUS_TEMPERATURE with bits on. 827 expectations.statusTempValue = 0xFF; 828 829 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 830 { 831 setPMBusExpectations(mockPMBus, expectations); 832 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 833 .Times(1) 834 .WillOnce(Return("0")); 835 if (x == DEGLITCH_LIMIT) 836 { 837 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 838 } 839 psu.analyze(); 840 EXPECT_EQ(psu.isPresent(), true); 841 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT. 842 // Rely on HasVoutUVFault() to verify this sets and clears. 843 EXPECT_EQ(psu.hasVoutUVFault(), false); 844 // All faults are deglitched up to DEGLITCH_LIMIT 845 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT); 846 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT); 847 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT); 848 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT); 849 EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT); 850 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT); 851 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT); 852 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT); 853 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT); 854 EXPECT_EQ(psu.hasPgoodFault(), x >= DEGLITCH_LIMIT); 855 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT); 856 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT); 857 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT); 858 } 859 860 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)) 861 .Times(1) 862 .WillOnce(Return(207000)); 863 // Clearing VIN_UV fault via in1_lcrit_alarm 864 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 865 .Times(1) 866 .WillOnce(Return(1)); 867 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 868 psu.clearFaults(); 869 EXPECT_EQ(psu.isPresent(), true); 870 EXPECT_EQ(psu.isFaulted(), false); 871 EXPECT_EQ(psu.hasInputFault(), false); 872 EXPECT_EQ(psu.hasMFRFault(), false); 873 EXPECT_EQ(psu.hasVINUVFault(), false); 874 EXPECT_EQ(psu.hasCommFault(), false); 875 EXPECT_EQ(psu.hasVoutOVFault(), false); 876 EXPECT_EQ(psu.hasIoutOCFault(), false); 877 EXPECT_EQ(psu.hasVoutUVFault(), false); 878 EXPECT_EQ(psu.hasFanFault(), false); 879 EXPECT_EQ(psu.hasTempFault(), false); 880 EXPECT_EQ(psu.hasPgoodFault(), false); 881 EXPECT_EQ(psu.hasPSKillFault(), false); 882 EXPECT_EQ(psu.hasPS12VcsFault(), false); 883 EXPECT_EQ(psu.hasPSCS12VFault(), false); 884 885 // Faults clear on READ_VIN 0 -> !0 886 // STATUS_WORD with fault bits galore! 887 expectations.statusWordValue = 0xFFFF; 888 // STATUS_INPUT with fault bits on. 889 expectations.statusInputValue = 0xFF; 890 // STATUS_MFR_SPEFIC with bits on. 891 expectations.statusMFRValue = 0xFF; 892 // STATUS_CML with bits on. 893 expectations.statusCMLValue = 0xFF; 894 // STATUS_VOUT with bits on. 895 expectations.statusVOUTValue = 0xFF; 896 // STATUS_IOUT with bits on. 897 expectations.statusIOUTValue = 0xFF; 898 // STATUS_FANS_1_2 with bits on. 899 expectations.statusFans12Value = 0xFF; 900 // STATUS_TEMPERATURE with bits on. 901 expectations.statusTempValue = 0xFF; 902 903 // All faults degltiched now. Check for false before limit above. 904 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 905 { 906 setPMBusExpectations(mockPMBus, expectations); 907 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 908 .Times(1) 909 .WillOnce(Return("0")); 910 if (x == DEGLITCH_LIMIT) 911 { 912 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 913 } 914 psu.analyze(); 915 } 916 917 EXPECT_EQ(psu.isPresent(), true); 918 EXPECT_EQ(psu.isFaulted(), true); 919 EXPECT_EQ(psu.hasInputFault(), true); 920 EXPECT_EQ(psu.hasMFRFault(), true); 921 EXPECT_EQ(psu.hasVINUVFault(), true); 922 // True due to CML fault bits on 923 EXPECT_EQ(psu.hasCommFault(), true); 924 EXPECT_EQ(psu.hasVoutOVFault(), true); 925 EXPECT_EQ(psu.hasIoutOCFault(), true); 926 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT. 927 // Rely on HasVoutUVFault() to verify this sets and clears. 928 EXPECT_EQ(psu.hasVoutUVFault(), false); 929 EXPECT_EQ(psu.hasFanFault(), true); 930 EXPECT_EQ(psu.hasTempFault(), true); 931 EXPECT_EQ(psu.hasPgoodFault(), true); 932 EXPECT_EQ(psu.hasPSKillFault(), true); 933 EXPECT_EQ(psu.hasPS12VcsFault(), true); 934 EXPECT_EQ(psu.hasPSCS12VFault(), true); 935 // STATUS_WORD with INPUT/VIN_UV fault bits off. 936 expectations.statusWordValue = 0xDFF7; 937 // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For 938 // Insufficient Input Voltage bits off. 939 expectations.statusInputValue = 0xC7; 940 setPMBusExpectations(mockPMBus, expectations); 941 // READ_VIN back in range. 942 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 943 .Times(1) 944 .WillOnce(Return("206000")); 945 // VIN_UV cleared via in1_lcrit_alarm when voltage back in range. 946 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 947 .Times(1) 948 .WillOnce(Return(1)); 949 psu.analyze(); 950 // We only cleared the VIN_UV and OFF faults. 951 EXPECT_EQ(psu.isPresent(), true); 952 EXPECT_EQ(psu.isFaulted(), true); 953 EXPECT_EQ(psu.hasInputFault(), false); 954 EXPECT_EQ(psu.hasMFRFault(), true); 955 EXPECT_EQ(psu.hasVINUVFault(), false); 956 EXPECT_EQ(psu.hasCommFault(), true); 957 EXPECT_EQ(psu.hasVoutOVFault(), true); 958 EXPECT_EQ(psu.hasIoutOCFault(), true); 959 EXPECT_EQ(psu.hasVoutUVFault(), false); 960 EXPECT_EQ(psu.hasFanFault(), true); 961 EXPECT_EQ(psu.hasTempFault(), true); 962 EXPECT_EQ(psu.hasPgoodFault(), true); 963 EXPECT_EQ(psu.hasPSKillFault(), true); 964 EXPECT_EQ(psu.hasPS12VcsFault(), true); 965 EXPECT_EQ(psu.hasPSCS12VFault(), true); 966 967 // All faults cleared 968 expectations = {0}; 969 setPMBusExpectations(mockPMBus, expectations); 970 // READ_VIN back in range. 971 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 972 .Times(1) 973 .WillOnce(Return("206000")); 974 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 975 psu.analyze(); 976 EXPECT_EQ(psu.isPresent(), true); 977 EXPECT_EQ(psu.isFaulted(), false); 978 EXPECT_EQ(psu.hasInputFault(), false); 979 EXPECT_EQ(psu.hasMFRFault(), false); 980 EXPECT_EQ(psu.hasVINUVFault(), false); 981 EXPECT_EQ(psu.hasCommFault(), false); 982 EXPECT_EQ(psu.hasVoutOVFault(), false); 983 EXPECT_EQ(psu.hasIoutOCFault(), false); 984 EXPECT_EQ(psu.hasVoutUVFault(), false); 985 EXPECT_EQ(psu.hasFanFault(), false); 986 EXPECT_EQ(psu.hasTempFault(), false); 987 EXPECT_EQ(psu.hasPgoodFault(), false); 988 EXPECT_EQ(psu.hasPSKillFault(), false); 989 EXPECT_EQ(psu.hasPS12VcsFault(), false); 990 EXPECT_EQ(psu.hasPSCS12VFault(), false); 991 992 // TODO: Faults clear on missing/present? 993 } 994 995 TEST_F(PowerSupplyTests, UpdateInventory) 996 { 997 auto bus = sdbusplus::bus::new_default(); 998 999 try 1000 { 1001 PowerSupply psu{bus, PSUInventoryPath, 3, 1002 0x68, "ibm-cffps", PSUGPIOLineName}; 1003 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1004 // If it is not present, I should not be trying to read a string 1005 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0); 1006 psu.updateInventory(); 1007 } 1008 catch (...) 1009 { 1010 ADD_FAILURE() << "Should not have caught exception."; 1011 } 1012 1013 try 1014 { 1015 PowerSupply psu{bus, PSUInventoryPath, 13, 1016 0x69, "ibm-cffps", PSUGPIOLineName}; 1017 MockedGPIOInterface* mockPresenceGPIO = 1018 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1019 // GPIO read return 1 to indicate present. 1020 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1)); 1021 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1022 setMissingToPresentExpects(mockPMBus, mockedUtil); 1023 // STATUS_WORD 0x0000 is powered on, no faults. 1024 PMBusExpectations expectations; 1025 setPMBusExpectations(mockPMBus, expectations); 1026 // Call to analyze will read voltage, trigger clear faults for 0 to 1027 // within range. 1028 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1029 .Times(1) 1030 .WillOnce(Return("123456")); 1031 psu.analyze(); 1032 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return("")); 1033 psu.updateInventory(); 1034 1035 #if IBM_VPD 1036 EXPECT_CALL(mockPMBus, readString(_, _)) 1037 .WillOnce(Return("CCIN")) 1038 .WillOnce(Return("PN3456")) 1039 .WillOnce(Return("FN3456")) 1040 .WillOnce(Return("HEADER")) 1041 .WillOnce(Return("SN3456")) 1042 .WillOnce(Return("FW3456")); 1043 #endif 1044 psu.updateInventory(); 1045 // TODO: D-Bus mocking to verify values stored on D-Bus (???) 1046 } 1047 catch (...) 1048 { 1049 ADD_FAILURE() << "Should not have caught exception."; 1050 } 1051 } 1052 1053 TEST_F(PowerSupplyTests, IsPresent) 1054 { 1055 auto bus = sdbusplus::bus::new_default(); 1056 1057 PowerSupply psu{bus, PSUInventoryPath, 3, 1058 0x68, "ibm-cffps", PSUGPIOLineName}; 1059 MockedGPIOInterface* mockPresenceGPIO = 1060 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1061 EXPECT_EQ(psu.isPresent(), false); 1062 1063 // Change GPIO read to return 1 to indicate present. 1064 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1)); 1065 // Call to analyze() will update to present, that will trigger updating 1066 // to the correct/latest HWMON directory, in case it changes. 1067 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1068 setMissingToPresentExpects(mockPMBus, mockedUtil); 1069 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN. 1070 // Default expectations will be on, no faults. 1071 PMBusExpectations expectations; 1072 setPMBusExpectations(mockPMBus, expectations); 1073 // Give it an input voltage in the 100-volt range. 1074 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1075 .Times(1) 1076 .WillOnce(Return("123456")); 1077 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1078 psu.analyze(); 1079 EXPECT_EQ(psu.isPresent(), true); 1080 } 1081 1082 TEST_F(PowerSupplyTests, IsFaulted) 1083 { 1084 auto bus = sdbusplus::bus::new_default(); 1085 1086 PowerSupply psu{bus, PSUInventoryPath, 11, 1087 0x6f, "ibm-cffps", PSUGPIOLineName}; 1088 MockedGPIOInterface* mockPresenceGPIO = 1089 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1090 // Always return 1 to indicate present. 1091 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1092 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1093 setMissingToPresentExpects(mockPMBus, mockedUtil); 1094 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN. 1095 // Default expectations will be on, no faults. 1096 PMBusExpectations expectations; 1097 setPMBusExpectations(mockPMBus, expectations); 1098 // Give it an input voltage in the 100-volt range. 1099 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1100 .Times(1) 1101 .WillOnce(Return("124680")); 1102 psu.analyze(); 1103 EXPECT_EQ(psu.isFaulted(), false); 1104 // STATUS_WORD with fault bits on. 1105 expectations.statusWordValue = 0xFFFF; 1106 // STATUS_INPUT with fault bits on. 1107 expectations.statusInputValue = 0xFF; 1108 // STATUS_MFR_SPECIFIC with faults bits on. 1109 expectations.statusMFRValue = 0xFF; 1110 // STATUS_CML with faults bits on. 1111 expectations.statusCMLValue = 0xFF; 1112 // STATUS_VOUT with fault bits on. 1113 expectations.statusVOUTValue = 0xFF; 1114 // STATUS_IOUT with fault bits on. 1115 expectations.statusIOUTValue = 0xFF; 1116 // STATUS_FANS_1_2 with bits on. 1117 expectations.statusFans12Value = 0xFF; 1118 // STATUS_TEMPERATURE with fault bits on. 1119 expectations.statusTempValue = 0xFF; 1120 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1121 { 1122 setPMBusExpectations(mockPMBus, expectations); 1123 // Also get another read of READ_VIN, faulted, so not in 100-volt range 1124 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1125 .Times(1) 1126 .WillOnce(Return("19000")); 1127 if (x == DEGLITCH_LIMIT) 1128 { 1129 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1130 } 1131 psu.analyze(); 1132 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT); 1133 } 1134 } 1135 1136 TEST_F(PowerSupplyTests, HasInputFault) 1137 { 1138 auto bus = sdbusplus::bus::new_default(); 1139 1140 PowerSupply psu{bus, PSUInventoryPath, 3, 1141 0x68, "ibm-cffps", PSUGPIOLineName}; 1142 MockedGPIOInterface* mockPresenceGPIO = 1143 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1144 // Always return 1 to indicate present. 1145 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1146 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1147 setMissingToPresentExpects(mockPMBus, mockedUtil); 1148 // STATUS_WORD 0x0000 is powered on, no faults. 1149 PMBusExpectations expectations; 1150 setPMBusExpectations(mockPMBus, expectations); 1151 // Analyze call will also need good READ_VIN value to check. 1152 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1153 .Times(1) 1154 .WillOnce(Return("201100")); 1155 psu.analyze(); 1156 EXPECT_EQ(psu.hasInputFault(), false); 1157 // STATUS_WORD with input fault/warn on. 1158 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN); 1159 // STATUS_INPUT with an input fault bit on. 1160 expectations.statusInputValue = 0x80; 1161 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1162 { 1163 setPMBusExpectations(mockPMBus, expectations); 1164 // Analyze call will also need good READ_VIN value to check. 1165 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1166 .Times(1) 1167 .WillOnce(Return("201200")); 1168 if (x == DEGLITCH_LIMIT) 1169 { 1170 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1171 } 1172 psu.analyze(); 1173 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT); 1174 } 1175 // STATUS_WORD with no bits on. 1176 expectations.statusWordValue = 0; 1177 setPMBusExpectations(mockPMBus, expectations); 1178 // Analyze call will also need good READ_VIN value to check. 1179 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1180 .Times(1) 1181 .WillOnce(Return("201300")); 1182 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1183 psu.analyze(); 1184 EXPECT_EQ(psu.hasInputFault(), false); 1185 } 1186 1187 TEST_F(PowerSupplyTests, HasMFRFault) 1188 { 1189 auto bus = sdbusplus::bus::new_default(); 1190 1191 PowerSupply psu{bus, PSUInventoryPath, 3, 1192 0x68, "ibm-cffps", PSUGPIOLineName}; 1193 MockedGPIOInterface* mockPresenceGPIO = 1194 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1195 // Always return 1 to indicate present. 1196 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1197 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1198 setMissingToPresentExpects(mockPMBus, mockedUtil); 1199 // First return STATUS_WORD with no bits on. 1200 // STATUS_WORD 0x0000 is powered on, no faults. 1201 PMBusExpectations expectations; 1202 setPMBusExpectations(mockPMBus, expectations); 1203 // Analyze call will also need good READ_VIN value to check. 1204 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1205 .Times(1) 1206 .WillOnce(Return("202100")); 1207 psu.analyze(); 1208 EXPECT_EQ(psu.hasMFRFault(), false); 1209 // Next return STATUS_WORD with MFR fault bit on. 1210 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1211 // STATUS_MFR_SPEFIC with bit(s) on. 1212 expectations.statusMFRValue = 0xFF; 1213 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1214 { 1215 setPMBusExpectations(mockPMBus, expectations); 1216 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1217 .Times(1) 1218 .WillOnce(Return("202200")); 1219 psu.analyze(); 1220 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT); 1221 } 1222 // Back to no bits on in STATUS_WORD 1223 expectations.statusWordValue = 0; 1224 setPMBusExpectations(mockPMBus, expectations); 1225 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1226 .Times(1) 1227 .WillOnce(Return("202300")); 1228 psu.analyze(); 1229 EXPECT_EQ(psu.hasMFRFault(), false); 1230 } 1231 1232 TEST_F(PowerSupplyTests, HasVINUVFault) 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 1245 // Presence change from missing to present will trigger in1_input read in 1246 // an attempt to get CLEAR_FAULTS called. Return value ignored. 1247 // Zero to non-zero voltage, for missing/present change, triggers clear 1248 // faults call again. Return value ignored. 1249 // Fault (low voltage) to not faulted (voltage in range) triggers clear 1250 // faults call a third time. 1251 1252 // STATUS_WORD 0x0000 is powered on, no faults. 1253 PMBusExpectations expectations; 1254 setPMBusExpectations(mockPMBus, expectations); 1255 // Analyze call will also need good READ_VIN value to check. 1256 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1257 .Times(1) 1258 .WillOnce(Return("201100")); 1259 psu.analyze(); 1260 EXPECT_EQ(psu.hasVINUVFault(), false); 1261 // Turn fault on. 1262 expectations.statusWordValue = (status_word::VIN_UV_FAULT); 1263 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by 1264 // Figure 16, and assume bits on in STATUS_INPUT. 1265 expectations.statusInputValue = 0x18; 1266 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1267 { 1268 setPMBusExpectations(mockPMBus, expectations); 1269 // If there is a VIN_UV fault, fake reading voltage of less than 20V 1270 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1271 .Times(1) 1272 .WillOnce(Return("19876")); 1273 if (x == DEGLITCH_LIMIT) 1274 { 1275 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1276 } 1277 psu.analyze(); 1278 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT); 1279 } 1280 // Back to no fault bits on in STATUS_WORD 1281 expectations.statusWordValue = 0; 1282 setPMBusExpectations(mockPMBus, expectations); 1283 // Updates now result in clearing faults if read voltage goes from below the 1284 // minimum, to within a valid range. 1285 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1286 .Times(1) 1287 .WillOnce(Return("201300")); 1288 // Went from below minimum to within range, expect clearVinUVFault(). 1289 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _)) 1290 .Times(1) 1291 .WillOnce(Return(1)); 1292 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1293 psu.analyze(); 1294 EXPECT_EQ(psu.hasVINUVFault(), false); 1295 } 1296 1297 TEST_F(PowerSupplyTests, HasVoutOVFault) 1298 { 1299 auto bus = sdbusplus::bus::new_default(); 1300 1301 PowerSupply psu{bus, PSUInventoryPath, 3, 1302 0x69, "ibm-cffps", PSUGPIOLineName}; 1303 MockedGPIOInterface* mockPresenceGPIO = 1304 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1305 // Always return 1 to indicate present. 1306 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1307 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1308 setMissingToPresentExpects(mockPMBus, mockedUtil); 1309 // STATUS_WORD 0x0000 is powered on, no faults. 1310 PMBusExpectations expectations; 1311 setPMBusExpectations(mockPMBus, expectations); 1312 // Call to analyze will trigger read of "in1_input" to check voltage. 1313 // Initial value would be 0, so this read updates it to non-zero. 1314 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1315 .Times(1) 1316 .WillOnce(Return("202100")); 1317 psu.analyze(); 1318 EXPECT_EQ(psu.hasVoutOVFault(), false); 1319 // Turn fault on. 1320 expectations.statusWordValue = (status_word::VOUT_OV_FAULT); 1321 // STATUS_VOUT fault bit(s) 1322 expectations.statusVOUTValue = 0x80; 1323 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1324 { 1325 setPMBusExpectations(mockPMBus, expectations); 1326 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1327 .Times(1) 1328 .WillOnce(Return("202200")); 1329 psu.analyze(); 1330 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT); 1331 } 1332 // Back to no fault bits on in STATUS_WORD 1333 expectations.statusWordValue = 0; 1334 setPMBusExpectations(mockPMBus, expectations); 1335 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1336 .Times(1) 1337 .WillOnce(Return("202300")); 1338 psu.analyze(); 1339 EXPECT_EQ(psu.hasVoutOVFault(), false); 1340 } 1341 1342 TEST_F(PowerSupplyTests, HasIoutOCFault) 1343 { 1344 auto bus = sdbusplus::bus::new_default(); 1345 1346 PowerSupply psu{bus, PSUInventoryPath, 3, 1347 0x6d, "ibm-cffps", PSUGPIOLineName}; 1348 MockedGPIOInterface* mockPresenceGPIO = 1349 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1350 // Always return 1 to indicate present. 1351 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1352 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1353 setMissingToPresentExpects(mockPMBus, mockedUtil); 1354 // STATUS_WORD 0x0000 is powered on, no faults. 1355 PMBusExpectations expectations; 1356 setPMBusExpectations(mockPMBus, expectations); 1357 // Call to analyze will trigger read of "in1_input" to check voltage. 1358 // Initial value would be 0, so this read updates it to non-zero. 1359 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1360 .Times(1) 1361 .WillOnce(Return("203100")); 1362 psu.analyze(); 1363 EXPECT_EQ(psu.hasIoutOCFault(), false); 1364 // Turn fault on. 1365 expectations.statusWordValue = status_word::IOUT_OC_FAULT; 1366 // STATUS_IOUT fault bit(s) 1367 expectations.statusIOUTValue = 0x88; 1368 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1369 { 1370 setPMBusExpectations(mockPMBus, expectations); 1371 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1372 .Times(1) 1373 .WillOnce(Return("203200")); 1374 if (x == DEGLITCH_LIMIT) 1375 { 1376 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1377 } 1378 psu.analyze(); 1379 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT); 1380 } 1381 // Back to no fault bits on in STATUS_WORD 1382 expectations.statusWordValue = 0; 1383 setPMBusExpectations(mockPMBus, expectations); 1384 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1385 .Times(1) 1386 .WillOnce(Return("203300")); 1387 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1388 psu.analyze(); 1389 EXPECT_EQ(psu.hasIoutOCFault(), false); 1390 } 1391 1392 TEST_F(PowerSupplyTests, HasVoutUVFault) 1393 { 1394 auto bus = sdbusplus::bus::new_default(); 1395 1396 PowerSupply psu{bus, PSUInventoryPath, 3, 1397 0x6a, "ibm-cffps", PSUGPIOLineName}; 1398 MockedGPIOInterface* mockPresenceGPIO = 1399 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1400 // Always return 1 to indicate present. 1401 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1402 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1403 setMissingToPresentExpects(mockPMBus, mockedUtil); 1404 // STATUS_WORD 0x0000 is powered on, no faults. 1405 PMBusExpectations expectations; 1406 setPMBusExpectations(mockPMBus, expectations); 1407 // Call to analyze will trigger read of "in1_input" to check voltage. 1408 // Initial value would be 0, so this read updates it to non-zero. 1409 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1410 .Times(1) 1411 .WillOnce(Return("204100")); 1412 psu.analyze(); 1413 EXPECT_EQ(psu.hasVoutUVFault(), false); 1414 // Turn fault on. 1415 expectations.statusWordValue = (status_word::VOUT_FAULT); 1416 // STATUS_VOUT fault bit(s) 1417 expectations.statusVOUTValue = 0x30; 1418 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1419 { 1420 setPMBusExpectations(mockPMBus, expectations); 1421 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1422 .Times(1) 1423 .WillOnce(Return("204200")); 1424 psu.analyze(); 1425 EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT); 1426 } 1427 // Back to no fault bits on in STATUS_WORD 1428 expectations.statusWordValue = 0; 1429 setPMBusExpectations(mockPMBus, expectations); 1430 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1431 .Times(1) 1432 .WillOnce(Return("204300")); 1433 psu.analyze(); 1434 EXPECT_EQ(psu.hasVoutUVFault(), false); 1435 } 1436 1437 TEST_F(PowerSupplyTests, HasFanFault) 1438 { 1439 auto bus = sdbusplus::bus::new_default(); 1440 1441 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1); 1442 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0); 1443 1444 PowerSupply psu{bus, PSUInventoryPath, 3, 1445 0x6d, "ibm-cffps", PSUGPIOLineName}; 1446 MockedGPIOInterface* mockPresenceGPIO = 1447 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1448 // Always return 1 to indicate present. 1449 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1450 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1451 setMissingToPresentExpects(mockPMBus, mockedUtil); 1452 // STATUS_WORD 0x0000 is powered on, no faults. 1453 PMBusExpectations expectations; 1454 setPMBusExpectations(mockPMBus, expectations); 1455 // Call to analyze will trigger read of "in1_input" to check voltage. 1456 // Initial value would be 0, so this read updates it to non-zero. 1457 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1458 .Times(1) 1459 .WillOnce(Return("205100")); 1460 psu.analyze(); 1461 EXPECT_EQ(psu.hasFanFault(), false); 1462 // Turn fault on. 1463 expectations.statusWordValue = (status_word::FAN_FAULT); 1464 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault) 1465 expectations.statusFans12Value = 0x80; 1466 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1467 { 1468 setPMBusExpectations(mockPMBus, expectations); 1469 // Call to analyze will trigger read of "in1_input" to check voltage. 1470 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1471 .Times(1) 1472 .WillOnce(Return("205200")); 1473 psu.analyze(); 1474 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT); 1475 } 1476 // Back to no fault bits on in STATUS_WORD 1477 expectations.statusWordValue = 0; 1478 setPMBusExpectations(mockPMBus, expectations); 1479 // Call to analyze will trigger read of "in1_input" to check voltage. 1480 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1481 .Times(1) 1482 .WillOnce(Return("205300")); 1483 psu.analyze(); 1484 EXPECT_EQ(psu.hasFanFault(), false); 1485 } 1486 1487 TEST_F(PowerSupplyTests, HasTempFault) 1488 { 1489 auto bus = sdbusplus::bus::new_default(); 1490 1491 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1); 1492 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0); 1493 1494 PowerSupply psu{bus, PSUInventoryPath, 3, 1495 0x6a, "ibm-cffps", PSUGPIOLineName}; 1496 MockedGPIOInterface* mockPresenceGPIO = 1497 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1498 // Always return 1 to indicate present. 1499 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1500 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1501 setMissingToPresentExpects(mockPMBus, mockedUtil); 1502 // STATUS_WORD 0x0000 is powered on, no faults. 1503 PMBusExpectations expectations; 1504 setPMBusExpectations(mockPMBus, expectations); 1505 // Call to analyze will trigger read of "in1_input" to check voltage. 1506 // Initial value would be 0, so this read updates it to non-zero. 1507 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1508 .Times(1) 1509 .WillOnce(Return("206100")); 1510 psu.analyze(); 1511 EXPECT_EQ(psu.hasTempFault(), false); 1512 // Turn fault on. 1513 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN); 1514 // STATUS_TEMPERATURE fault bit on (OT Fault) 1515 expectations.statusTempValue = 0x80; 1516 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1517 { 1518 setPMBusExpectations(mockPMBus, expectations); 1519 // Call to analyze will trigger read of "in1_input" to check voltage. 1520 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1521 .Times(1) 1522 .WillOnce(Return("206200")); 1523 psu.analyze(); 1524 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT); 1525 } 1526 // Back to no fault bits on in STATUS_WORD 1527 expectations.statusWordValue = 0; 1528 setPMBusExpectations(mockPMBus, expectations); 1529 // Call to analyze will trigger read of "in1_input" to check voltage. 1530 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1531 .Times(1) 1532 .WillOnce(Return("206300")); 1533 psu.analyze(); 1534 EXPECT_EQ(psu.hasTempFault(), false); 1535 } 1536 1537 TEST_F(PowerSupplyTests, HasPgoodFault) 1538 { 1539 auto bus = sdbusplus::bus::new_default(); 1540 1541 PowerSupply psu{bus, PSUInventoryPath, 3, 1542 0x6b, "ibm-cffps", PSUGPIOLineName}; 1543 MockedGPIOInterface* mockPresenceGPIO = 1544 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1545 // Always return 1 to indicate present. 1546 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1547 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1548 setMissingToPresentExpects(mockPMBus, mockedUtil); 1549 // STATUS_WORD 0x0000 is powered on, no faults. 1550 PMBusExpectations expectations; 1551 setPMBusExpectations(mockPMBus, expectations); 1552 // Call to analyze will trigger read of "in1_input" to check voltage. 1553 // Initial value would be 0, so this read updates it to non-zero. 1554 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1555 .Times(1) 1556 .WillOnce(Return("207100")); 1557 psu.analyze(); 1558 EXPECT_EQ(psu.hasPgoodFault(), false); 1559 // Setup another expectation of no faults. 1560 setPMBusExpectations(mockPMBus, expectations); 1561 // Call to analyze will trigger read of "in1_input" to check voltage. 1562 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1563 .Times(1) 1564 .WillOnce(Return("207200")); 1565 psu.analyze(); 1566 EXPECT_EQ(psu.hasPgoodFault(), false); 1567 // Setup another expectation of no faults. 1568 setPMBusExpectations(mockPMBus, expectations); 1569 // Call to analyze will trigger read of "in1_input" to check voltage. 1570 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1571 .Times(1) 1572 .WillOnce(Return("207300")); 1573 psu.analyze(); 1574 EXPECT_EQ(psu.hasPgoodFault(), false); 1575 // Turn PGOOD# off (fault on). 1576 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED); 1577 setPMBusExpectations(mockPMBus, expectations); 1578 // Call to analyze will trigger read of "in1_input" to check voltage. 1579 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1580 .Times(1) 1581 .WillOnce(Return("207400")); 1582 psu.analyze(); 1583 // Expect false until reaches DEGLITCH_LIMIT 1584 EXPECT_EQ(psu.hasPgoodFault(), false); 1585 setPMBusExpectations(mockPMBus, expectations); 1586 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1587 .Times(1) 1588 .WillOnce(Return("207500")); 1589 psu.analyze(); 1590 // Expect false until reaches DEGLITCH_LIMIT 1591 EXPECT_EQ(psu.hasPgoodFault(), false); 1592 setPMBusExpectations(mockPMBus, expectations); 1593 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1594 .Times(1) 1595 .WillOnce(Return("207600")); 1596 psu.analyze(); 1597 // DEGLITCH_LIMIT reached, expect true. 1598 EXPECT_EQ(psu.hasPgoodFault(), true); 1599 // Back to no fault bits on in STATUS_WORD 1600 expectations.statusWordValue = 0; 1601 setPMBusExpectations(mockPMBus, expectations); 1602 // Call to analyze will trigger read of "in1_input" to check voltage. 1603 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1604 .Times(1) 1605 .WillOnce(Return("207700")); 1606 psu.analyze(); 1607 EXPECT_EQ(psu.hasPgoodFault(), false); 1608 1609 // Turn OFF bit on 1610 expectations.statusWordValue = (status_word::UNIT_IS_OFF); 1611 setPMBusExpectations(mockPMBus, expectations); 1612 // Call to analyze will trigger read of "in1_input" to check voltage. 1613 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1614 .Times(1) 1615 .WillOnce(Return("208100")); 1616 psu.analyze(); 1617 EXPECT_EQ(psu.hasPgoodFault(), false); 1618 setPMBusExpectations(mockPMBus, expectations); 1619 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1620 .Times(1) 1621 .WillOnce(Return("208200")); 1622 psu.analyze(); 1623 EXPECT_EQ(psu.hasPgoodFault(), false); 1624 setPMBusExpectations(mockPMBus, expectations); 1625 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1626 .Times(1) 1627 .WillOnce(Return("208300")); 1628 psu.analyze(); 1629 EXPECT_EQ(psu.hasPgoodFault(), true); 1630 // Back to no fault bits on in STATUS_WORD 1631 expectations.statusWordValue = 0; 1632 setPMBusExpectations(mockPMBus, expectations); 1633 // Call to analyze will trigger read of "in1_input" to check voltage. 1634 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1635 .Times(1) 1636 .WillOnce(Return("208400")); 1637 psu.analyze(); 1638 EXPECT_EQ(psu.hasPgoodFault(), false); 1639 } 1640 1641 TEST_F(PowerSupplyTests, HasPSKillFault) 1642 { 1643 auto bus = sdbusplus::bus::new_default(); 1644 PowerSupply psu{bus, PSUInventoryPath, 4, 1645 0x6d, "ibm-cffps", PSUGPIOLineName}; 1646 MockedGPIOInterface* mockPresenceGPIO = 1647 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1648 // Always return 1 to indicate present. 1649 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1650 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1651 setMissingToPresentExpects(mockPMBus, mockedUtil); 1652 // STATUS_WORD 0x0000 is powered on, no faults. 1653 PMBusExpectations expectations; 1654 setPMBusExpectations(mockPMBus, expectations); 1655 // Call to analyze will trigger read of "in1_input" to check voltage. 1656 // Initial value would be 0, so this read updates it to non-zero. 1657 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1658 .Times(1) 1659 .WillOnce(Return("208100")); 1660 psu.analyze(); 1661 EXPECT_EQ(psu.hasPSKillFault(), false); 1662 // Next return STATUS_WORD with MFR fault bit on. 1663 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1664 // STATUS_MFR_SPEFIC with bit(s) on. 1665 expectations.statusMFRValue = 0xFF; 1666 1667 // Deglitching faults, false until read the fault bits on up to the limit. 1668 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1669 { 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("208200")); 1675 if (x == DEGLITCH_LIMIT) 1676 { 1677 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1678 } 1679 psu.analyze(); 1680 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT); 1681 } 1682 1683 // Back to no bits on in STATUS_WORD 1684 expectations.statusWordValue = 0; 1685 setPMBusExpectations(mockPMBus, expectations); 1686 // Call to analyze will trigger read of "in1_input" to check voltage. 1687 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1688 .Times(1) 1689 .WillOnce(Return("208300")); 1690 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1691 psu.analyze(); 1692 EXPECT_EQ(psu.hasPSKillFault(), false); 1693 // Next return STATUS_WORD with MFR fault bit on. 1694 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1695 // STATUS_MFR_SPEFIC with bit 4 on. 1696 expectations.statusMFRValue = 0x10; 1697 1698 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1699 { 1700 setPMBusExpectations(mockPMBus, expectations); 1701 // Call to analyze will trigger read of "in1_input" to check voltage. 1702 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1703 .Times(1) 1704 .WillOnce(Return("208400")); 1705 if (x == DEGLITCH_LIMIT) 1706 { 1707 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)); 1708 } 1709 psu.analyze(); 1710 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT); 1711 } 1712 1713 // Back to no bits on in STATUS_WORD 1714 expectations.statusWordValue = 0; 1715 setPMBusExpectations(mockPMBus, expectations); 1716 // Call to analyze will trigger read of "in1_input" to check voltage. 1717 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1718 .Times(1) 1719 .WillOnce(Return("208500")); 1720 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1721 psu.analyze(); 1722 EXPECT_EQ(psu.hasPSKillFault(), false); 1723 } 1724 1725 TEST_F(PowerSupplyTests, HasPS12VcsFault) 1726 { 1727 auto bus = sdbusplus::bus::new_default(); 1728 PowerSupply psu{bus, PSUInventoryPath, 5, 1729 0x6e, "ibm-cffps", PSUGPIOLineName}; 1730 MockedGPIOInterface* mockPresenceGPIO = 1731 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1732 // Always return 1 to indicate present. 1733 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1734 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1735 setMissingToPresentExpects(mockPMBus, mockedUtil); 1736 // STATUS_WORD 0x0000 is powered on, no faults. 1737 PMBusExpectations expectations; 1738 setPMBusExpectations(mockPMBus, expectations); 1739 // Call to analyze will trigger read of "in1_input" to check voltage. 1740 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1741 .Times(1) 1742 .WillOnce(Return("209100")); 1743 psu.analyze(); 1744 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1745 // Next return STATUS_WORD with MFR fault bit on. 1746 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1747 // STATUS_MFR_SPEFIC with bit(s) on. 1748 expectations.statusMFRValue = 0xFF; 1749 1750 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1751 { 1752 setPMBusExpectations(mockPMBus, expectations); 1753 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1754 .Times(1) 1755 .WillOnce(Return("209200")); 1756 psu.analyze(); 1757 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT); 1758 } 1759 1760 // Back to no bits on in STATUS_WORD 1761 expectations.statusWordValue = 0; 1762 setPMBusExpectations(mockPMBus, expectations); 1763 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1764 .Times(1) 1765 .WillOnce(Return("209300")); 1766 psu.analyze(); 1767 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1768 // Next return STATUS_WORD with MFR fault bit on. 1769 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1770 // STATUS_MFR_SPEFIC with bit 6 on. 1771 expectations.statusMFRValue = 0x40; 1772 1773 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1774 { 1775 setPMBusExpectations(mockPMBus, expectations); 1776 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1777 .Times(1) 1778 .WillOnce(Return("209400")); 1779 psu.analyze(); 1780 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT); 1781 } 1782 1783 // Back to no bits on in STATUS_WORD 1784 expectations.statusWordValue = 0; 1785 setPMBusExpectations(mockPMBus, expectations); 1786 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1787 .Times(1) 1788 .WillOnce(Return("209500")); 1789 psu.analyze(); 1790 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1791 } 1792 1793 TEST_F(PowerSupplyTests, HasPSCS12VFault) 1794 { 1795 auto bus = sdbusplus::bus::new_default(); 1796 PowerSupply psu{bus, PSUInventoryPath, 6, 1797 0x6f, "ibm-cffps", PSUGPIOLineName}; 1798 MockedGPIOInterface* mockPresenceGPIO = 1799 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1800 // Always return 1 to indicate present. 1801 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1802 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1803 setMissingToPresentExpects(mockPMBus, mockedUtil); 1804 // STATUS_WORD 0x0000 is powered on, no faults. 1805 PMBusExpectations expectations; 1806 setPMBusExpectations(mockPMBus, expectations); 1807 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1808 .Times(1) 1809 .WillOnce(Return("209100")); 1810 psu.analyze(); 1811 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1812 // Next return STATUS_WORD with MFR fault bit on. 1813 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1814 // STATUS_MFR_SPEFIC with bit(s) on. 1815 expectations.statusMFRValue = 0xFF; 1816 1817 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1818 { 1819 setPMBusExpectations(mockPMBus, expectations); 1820 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1821 .Times(1) 1822 .WillOnce(Return("209200")); 1823 psu.analyze(); 1824 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT); 1825 } 1826 1827 // Back to no bits on in STATUS_WORD 1828 expectations.statusWordValue = 0; 1829 setPMBusExpectations(mockPMBus, expectations); 1830 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1831 .Times(1) 1832 .WillOnce(Return("209300")); 1833 psu.analyze(); 1834 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1835 // Next return STATUS_WORD with MFR fault bit on. 1836 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1837 // STATUS_MFR_SPEFIC with bit 7 on. 1838 expectations.statusMFRValue = 0x80; 1839 1840 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1841 { 1842 setPMBusExpectations(mockPMBus, expectations); 1843 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1844 .Times(1) 1845 .WillOnce(Return("209400")); 1846 psu.analyze(); 1847 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT); 1848 } 1849 1850 // Back to no bits on in STATUS_WORD 1851 expectations.statusWordValue = 0; 1852 setPMBusExpectations(mockPMBus, expectations); 1853 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1854 .Times(1) 1855 .WillOnce(Return("209500")); 1856 psu.analyze(); 1857 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1858 } 1859 1860 TEST_F(PowerSupplyTests, SetupInputHistory) 1861 { 1862 auto bus = sdbusplus::bus::new_default(); 1863 { 1864 PowerSupply psu{bus, PSUInventoryPath, 6, 1865 0x6f, "ibm-cffps", PSUGPIOLineName}; 1866 // Defaults to not present due to constructor and mock ordering. 1867 psu.setupInputHistory(); 1868 EXPECT_EQ(psu.hasInputHistory(), false); 1869 MockedGPIOInterface* mockPresenceGPIO = 1870 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1871 // Always return 1 to indicate present. 1872 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1873 psu.analyze(); 1874 psu.setupInputHistory(); 1875 EXPECT_EQ(psu.hasInputHistory(), true); 1876 } 1877 { 1878 PowerSupply psu{bus, PSUInventoryPath, 11, 1879 0x58, "inspur-ipsps", PSUGPIOLineName}; 1880 // Defaults to not present due to constructor and mock ordering. 1881 psu.setupInputHistory(); 1882 EXPECT_EQ(psu.hasInputHistory(), false); 1883 MockedGPIOInterface* mockPresenceGPIO = 1884 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1885 // Always return 1 to indicate present. 1886 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1887 psu.analyze(); 1888 psu.setupInputHistory(); 1889 // After updating to present, and retrying setup, expect inspur-ipsps to 1890 // still not support INPUT_HISTORY. 1891 EXPECT_EQ(psu.hasInputHistory(), false); 1892 } 1893 } 1894 1895 TEST_F(PowerSupplyTests, UpdateHistory) 1896 { 1897 auto bus = sdbusplus::bus::new_default(); 1898 PowerSupply psu{bus, PSUInventoryPath, 7, 1899 0x6e, "ibm-cffps", PSUGPIOLineName}; 1900 EXPECT_EQ(psu.hasInputHistory(), false); 1901 EXPECT_EQ(psu.getNumInputHistoryRecords(), 0); 1902 MockedGPIOInterface* mockPresenceGPIO = 1903 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1904 // Always return 1 to indicate present. 1905 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1906 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1907 setMissingToPresentExpects(mockPMBus, mockedUtil); 1908 PMBusExpectations expectations; 1909 setPMBusExpectations(mockPMBus, expectations); 1910 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1911 .Times(6) 1912 .WillRepeatedly(Return("205000")); 1913 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1914 // First read after missing/present will have no data. 1915 std::vector<uint8_t> emptyHistory{}; 1916 // Second read, after about 30 seconds, should have a record. 5-bytes. 1917 // Sequence Number: 0x00, Average: 0x50 0xf3 (212), Maximum: 0x54 0xf3 (213) 1918 std::vector<uint8_t> firstHistory{0x00, 0x50, 0xf3, 0x54, 0xf3}; 1919 // Third read, after about 60 seconds, should have two records, 10-bytes, 1920 // but only reading 5 bytes, so make sure new/next sequence number 1921 std::vector<uint8_t> secondHistory{0x01, 0x54, 0xf3, 0x58, 0xf3}; 1922 // Fourth read, 3rd sequence number (0x02). 1923 std::vector<uint8_t> thirdHistory{0x02, 0x54, 0xf3, 0x58, 0xf3}; 1924 // Fifth read, out of sequence, clear and insert this one? 1925 std::vector<uint8_t> outseqHistory{0xff, 0x5c, 0xf3, 0x60, 0xf3}; 1926 EXPECT_CALL( 1927 mockPMBus, 1928 readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug, 1929 phosphor::power::history::RecordManager::RAW_RECORD_SIZE)) 1930 .Times(6) 1931 .WillOnce(Return(emptyHistory)) 1932 .WillOnce(Return(firstHistory)) 1933 .WillOnce(Return(secondHistory)) 1934 .WillOnce(Return(thirdHistory)) 1935 .WillOnce(Return(outseqHistory)) 1936 .WillOnce(Return(emptyHistory)); 1937 // Calling analyze will update the presence, which will setup the input 1938 // history if the power supply went from missing to present. 1939 psu.analyze(); 1940 // The ibm-cffps power supply should support input history 1941 EXPECT_EQ(psu.hasInputHistory(), true); 1942 // Usually should have empty buffer right after missing to present. 1943 // Faked that out above with mocked readBinary with emptyHistory data. 1944 EXPECT_EQ(psu.getNumInputHistoryRecords(), 0); 1945 // Second run through... 1946 setPMBusExpectations(mockPMBus, expectations); 1947 psu.analyze(); 1948 EXPECT_EQ(psu.hasInputHistory(), true); 1949 EXPECT_EQ(psu.getNumInputHistoryRecords(), 1); 1950 // Third run through 1951 setPMBusExpectations(mockPMBus, expectations); 1952 psu.analyze(); 1953 EXPECT_EQ(psu.hasInputHistory(), true); 1954 EXPECT_EQ(psu.getNumInputHistoryRecords(), 2); 1955 // Fourth run through. Up to 3 records now? 1956 setPMBusExpectations(mockPMBus, expectations); 1957 psu.analyze(); 1958 EXPECT_EQ(psu.hasInputHistory(), true); 1959 EXPECT_EQ(psu.getNumInputHistoryRecords(), 3); 1960 // Out of sequencer, reset, insert new one. 1961 setPMBusExpectations(mockPMBus, expectations); 1962 psu.analyze(); 1963 EXPECT_EQ(psu.hasInputHistory(), true); 1964 EXPECT_EQ(psu.getNumInputHistoryRecords(), 1); 1965 // Empty one after last one good. Reset/clear. 1966 setPMBusExpectations(mockPMBus, expectations); 1967 psu.analyze(); 1968 EXPECT_EQ(psu.hasInputHistory(), true); 1969 EXPECT_EQ(psu.getNumInputHistoryRecords(), 0); 1970 } 1971 1972 TEST_F(PowerSupplyTests, IsSyncHistoryRequired) 1973 { 1974 auto bus = sdbusplus::bus::new_default(); 1975 PowerSupply psu{bus, PSUInventoryPath, 8, 1976 0x6f, "ibm-cffps", PSUGPIOLineName}; 1977 EXPECT_EQ(psu.hasInputHistory(), false); 1978 EXPECT_EQ(psu.isSyncHistoryRequired(), false); 1979 MockedGPIOInterface* mockPresenceGPIO = 1980 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1981 // Always return 1 to indicate present. 1982 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1983 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1984 setMissingToPresentExpects(mockPMBus, mockedUtil); 1985 PMBusExpectations expectations; 1986 setPMBusExpectations(mockPMBus, expectations); 1987 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1988 .Times(1) 1989 .WillRepeatedly(Return("205000")); 1990 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)); 1991 psu.analyze(); 1992 // The ibm-cffps power supply should support input history 1993 EXPECT_EQ(psu.hasInputHistory(), true); 1994 // Missing -> Present requires history sync 1995 EXPECT_EQ(psu.isSyncHistoryRequired(), true); 1996 psu.clearSyncHistoryRequired(); 1997 EXPECT_EQ(psu.isSyncHistoryRequired(), false); 1998 } 1999