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