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