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 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName}; 707 708 MockedGPIOInterface* mockPresenceGPIO = 709 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 710 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0)); 711 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 712 // Constructor should set initial presence, default read returns 0. 713 // If it is not present, I should not be trying to write to it. 714 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0); 715 psu.onOffConfig(data); 716 } 717 catch (...) 718 {} 719 720 // Test where PSU is present 721 try 722 { 723 // Assume GPIO presence, not inventory presence? 724 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName}; 725 MockedGPIOInterface* mockPresenceGPIO = 726 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 727 // There will potentially be multiple calls, we want it to continue 728 // returning 1 for the GPIO read to keep the power supply present. 729 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 730 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 731 setMissingToPresentExpects(mockPMBus, mockedUtil); 732 // If I am calling analyze(), I should probably give it good data. 733 // STATUS_WORD 0x0000 is powered on, no faults. 734 PMBusExpectations expectations; 735 setPMBusExpectations(mockPMBus, expectations); 736 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 737 .Times(1) 738 .WillOnce(Return("205000")); 739 psu.analyze(); 740 // I definitely should be writting ON_OFF_CONFIG if I call the function 741 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15), 742 Type::HwmonDeviceDebug)) 743 .Times(1); 744 psu.onOffConfig(data); 745 } 746 catch (...) 747 {} 748 } 749 750 TEST_F(PowerSupplyTests, ClearFaults) 751 { 752 auto bus = sdbusplus::bus::new_default(); 753 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName}; 754 MockedGPIOInterface* mockPresenceGPIO = 755 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 756 // Always return 1 to indicate present. 757 // Each analyze() call will trigger a read of the presence GPIO. 758 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 759 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 760 setMissingToPresentExpects(mockPMBus, mockedUtil); 761 // STATUS_WORD 0x0000 is powered on, no faults. 762 PMBusExpectations expectations; 763 setPMBusExpectations(mockPMBus, expectations); 764 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 765 .Times(1) 766 .WillOnce(Return("207000")); 767 psu.analyze(); 768 EXPECT_EQ(psu.isPresent(), true); 769 EXPECT_EQ(psu.isFaulted(), false); 770 EXPECT_EQ(psu.hasInputFault(), false); 771 EXPECT_EQ(psu.hasMFRFault(), false); 772 EXPECT_EQ(psu.hasVINUVFault(), false); 773 EXPECT_EQ(psu.hasCommFault(), false); 774 EXPECT_EQ(psu.hasVoutOVFault(), false); 775 EXPECT_EQ(psu.hasIoutOCFault(), false); 776 EXPECT_EQ(psu.hasVoutUVFault(), false); 777 EXPECT_EQ(psu.hasFanFault(), false); 778 EXPECT_EQ(psu.hasTempFault(), false); 779 EXPECT_EQ(psu.hasPgoodFault(), false); 780 EXPECT_EQ(psu.hasPSKillFault(), false); 781 EXPECT_EQ(psu.hasPS12VcsFault(), false); 782 EXPECT_EQ(psu.hasPSCS12VFault(), false); 783 784 // STATUS_WORD with fault bits galore! 785 expectations.statusWordValue = 0xFFFF; 786 // STATUS_INPUT with fault bits on. 787 expectations.statusInputValue = 0xFF; 788 // STATUS_MFR_SPEFIC with bits on. 789 expectations.statusMFRValue = 0xFF; 790 // STATUS_CML with bits on. 791 expectations.statusCMLValue = 0xFF; 792 // STATUS_VOUT with bits on. 793 expectations.statusVOUTValue = 0xFF; 794 // STATUS_IOUT with bits on. 795 expectations.statusIOUTValue = 0xFF; 796 // STATUS_FANS_1_2 with bits on. 797 expectations.statusFans12Value = 0xFF; 798 // STATUS_TEMPERATURE with bits on. 799 expectations.statusTempValue = 0xFF; 800 801 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 802 { 803 setPMBusExpectations(mockPMBus, expectations); 804 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 805 .Times(1) 806 .WillOnce(Return("0")); 807 psu.analyze(); 808 EXPECT_EQ(psu.isPresent(), true); 809 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT. 810 // Rely on HasVoutUVFault() to verify this sets and clears. 811 EXPECT_EQ(psu.hasVoutUVFault(), false); 812 // All faults are deglitched up to DEGLITCH_LIMIT 813 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT); 814 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT); 815 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT); 816 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT); 817 EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT); 818 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT); 819 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT); 820 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT); 821 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT); 822 EXPECT_EQ(psu.hasPgoodFault(), x >= DEGLITCH_LIMIT); 823 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT); 824 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT); 825 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT); 826 } 827 828 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)) 829 .Times(1) 830 .WillOnce(Return(207000)); 831 psu.clearFaults(); 832 EXPECT_EQ(psu.isPresent(), true); 833 EXPECT_EQ(psu.isFaulted(), false); 834 EXPECT_EQ(psu.hasInputFault(), false); 835 EXPECT_EQ(psu.hasMFRFault(), false); 836 EXPECT_EQ(psu.hasVINUVFault(), false); 837 EXPECT_EQ(psu.hasCommFault(), false); 838 EXPECT_EQ(psu.hasVoutOVFault(), false); 839 EXPECT_EQ(psu.hasIoutOCFault(), false); 840 EXPECT_EQ(psu.hasVoutUVFault(), false); 841 EXPECT_EQ(psu.hasFanFault(), false); 842 EXPECT_EQ(psu.hasTempFault(), false); 843 EXPECT_EQ(psu.hasPgoodFault(), false); 844 EXPECT_EQ(psu.hasPSKillFault(), false); 845 EXPECT_EQ(psu.hasPS12VcsFault(), false); 846 EXPECT_EQ(psu.hasPSCS12VFault(), false); 847 848 // Faults clear on READ_VIN 0 -> !0 849 // STATUS_WORD with fault bits galore! 850 expectations.statusWordValue = 0xFFFF; 851 // STATUS_INPUT with fault bits on. 852 expectations.statusInputValue = 0xFF; 853 // STATUS_MFR_SPEFIC with bits on. 854 expectations.statusMFRValue = 0xFF; 855 // STATUS_CML with bits on. 856 expectations.statusCMLValue = 0xFF; 857 // STATUS_VOUT with bits on. 858 expectations.statusVOUTValue = 0xFF; 859 // STATUS_IOUT with bits on. 860 expectations.statusIOUTValue = 0xFF; 861 // STATUS_FANS_1_2 with bits on. 862 expectations.statusFans12Value = 0xFF; 863 // STATUS_TEMPERATURE with bits on. 864 expectations.statusTempValue = 0xFF; 865 866 // All faults degltiched now. Check for false before limit above. 867 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 868 { 869 setPMBusExpectations(mockPMBus, expectations); 870 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 871 .Times(1) 872 .WillOnce(Return("0")); 873 psu.analyze(); 874 } 875 876 EXPECT_EQ(psu.isPresent(), true); 877 EXPECT_EQ(psu.isFaulted(), true); 878 EXPECT_EQ(psu.hasInputFault(), true); 879 EXPECT_EQ(psu.hasMFRFault(), true); 880 EXPECT_EQ(psu.hasVINUVFault(), true); 881 // True due to CML fault bits on 882 EXPECT_EQ(psu.hasCommFault(), true); 883 EXPECT_EQ(psu.hasVoutOVFault(), true); 884 EXPECT_EQ(psu.hasIoutOCFault(), true); 885 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT. 886 // Rely on HasVoutUVFault() to verify this sets and clears. 887 EXPECT_EQ(psu.hasVoutUVFault(), false); 888 EXPECT_EQ(psu.hasFanFault(), true); 889 EXPECT_EQ(psu.hasTempFault(), true); 890 EXPECT_EQ(psu.hasPgoodFault(), true); 891 EXPECT_EQ(psu.hasPSKillFault(), true); 892 EXPECT_EQ(psu.hasPS12VcsFault(), true); 893 EXPECT_EQ(psu.hasPSCS12VFault(), true); 894 // STATUS_WORD with INPUT/VIN_UV fault bits off. 895 expectations.statusWordValue = 0xDFF7; 896 // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For 897 // Insufficient Input Voltage bits off. 898 expectations.statusInputValue = 0xC7; 899 setPMBusExpectations(mockPMBus, expectations); 900 // READ_VIN back in range. 901 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 902 .Times(1) 903 .WillOnce(Return("206000")); 904 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(0)); 905 psu.analyze(); 906 EXPECT_EQ(psu.isPresent(), true); 907 EXPECT_EQ(psu.isFaulted(), false); 908 EXPECT_EQ(psu.hasInputFault(), false); 909 EXPECT_EQ(psu.hasMFRFault(), false); 910 EXPECT_EQ(psu.hasVINUVFault(), false); 911 EXPECT_EQ(psu.hasCommFault(), false); 912 EXPECT_EQ(psu.hasVoutOVFault(), false); 913 EXPECT_EQ(psu.hasIoutOCFault(), false); 914 EXPECT_EQ(psu.hasVoutUVFault(), false); 915 EXPECT_EQ(psu.hasFanFault(), false); 916 EXPECT_EQ(psu.hasTempFault(), false); 917 EXPECT_EQ(psu.hasPgoodFault(), false); 918 EXPECT_EQ(psu.hasPSKillFault(), false); 919 EXPECT_EQ(psu.hasPS12VcsFault(), false); 920 EXPECT_EQ(psu.hasPSCS12VFault(), false); 921 922 // TODO: Faults clear on missing/present? 923 } 924 925 TEST_F(PowerSupplyTests, UpdateInventory) 926 { 927 auto bus = sdbusplus::bus::new_default(); 928 929 try 930 { 931 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 932 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 933 // If it is not present, I should not be trying to read a string 934 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0); 935 psu.updateInventory(); 936 } 937 catch (...) 938 { 939 ADD_FAILURE() << "Should not have caught exception."; 940 } 941 942 try 943 { 944 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName}; 945 MockedGPIOInterface* mockPresenceGPIO = 946 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 947 // GPIO read return 1 to indicate present. 948 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1)); 949 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 950 setMissingToPresentExpects(mockPMBus, mockedUtil); 951 // STATUS_WORD 0x0000 is powered on, no faults. 952 PMBusExpectations expectations; 953 setPMBusExpectations(mockPMBus, expectations); 954 // Call to analyze will read voltage, trigger clear faults for 0 to 955 // within range. 956 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 957 .Times(1) 958 .WillOnce(Return("123456")); 959 psu.analyze(); 960 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return("")); 961 psu.updateInventory(); 962 963 #if IBM_VPD 964 EXPECT_CALL(mockPMBus, readString(_, _)) 965 .WillOnce(Return("CCIN")) 966 .WillOnce(Return("PN3456")) 967 .WillOnce(Return("FN3456")) 968 .WillOnce(Return("HEADER")) 969 .WillOnce(Return("SN3456")) 970 .WillOnce(Return("FW3456")); 971 #endif 972 psu.updateInventory(); 973 // TODO: D-Bus mocking to verify values stored on D-Bus (???) 974 } 975 catch (...) 976 { 977 ADD_FAILURE() << "Should not have caught exception."; 978 } 979 } 980 981 TEST_F(PowerSupplyTests, IsPresent) 982 { 983 auto bus = sdbusplus::bus::new_default(); 984 985 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 986 MockedGPIOInterface* mockPresenceGPIO = 987 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 988 EXPECT_EQ(psu.isPresent(), false); 989 990 // Change GPIO read to return 1 to indicate present. 991 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1)); 992 // Call to analyze() will update to present, that will trigger updating 993 // to the correct/latest HWMON directory, in case it changes. 994 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 995 setMissingToPresentExpects(mockPMBus, mockedUtil); 996 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN. 997 // Default expectations will be on, no faults. 998 PMBusExpectations expectations; 999 setPMBusExpectations(mockPMBus, expectations); 1000 // Give it an input voltage in the 100-volt range. 1001 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1002 .Times(1) 1003 .WillOnce(Return("123456")); 1004 psu.analyze(); 1005 EXPECT_EQ(psu.isPresent(), true); 1006 } 1007 1008 TEST_F(PowerSupplyTests, IsFaulted) 1009 { 1010 auto bus = sdbusplus::bus::new_default(); 1011 1012 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName}; 1013 MockedGPIOInterface* mockPresenceGPIO = 1014 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1015 // Always return 1 to indicate present. 1016 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1017 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1018 setMissingToPresentExpects(mockPMBus, mockedUtil); 1019 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN. 1020 // Default expectations will be on, no faults. 1021 PMBusExpectations expectations; 1022 setPMBusExpectations(mockPMBus, expectations); 1023 // Give it an input voltage in the 100-volt range. 1024 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1025 .Times(1) 1026 .WillOnce(Return("124680")); 1027 psu.analyze(); 1028 EXPECT_EQ(psu.isFaulted(), false); 1029 // STATUS_WORD with fault bits on. 1030 expectations.statusWordValue = 0xFFFF; 1031 // STATUS_INPUT with fault bits on. 1032 expectations.statusInputValue = 0xFF; 1033 // STATUS_MFR_SPECIFIC with faults bits on. 1034 expectations.statusMFRValue = 0xFF; 1035 // STATUS_CML with faults bits on. 1036 expectations.statusCMLValue = 0xFF; 1037 // STATUS_VOUT with fault bits on. 1038 expectations.statusVOUTValue = 0xFF; 1039 // STATUS_IOUT with fault bits on. 1040 expectations.statusIOUTValue = 0xFF; 1041 // STATUS_FANS_1_2 with bits on. 1042 expectations.statusFans12Value = 0xFF; 1043 // STATUS_TEMPERATURE with fault bits on. 1044 expectations.statusTempValue = 0xFF; 1045 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1046 { 1047 setPMBusExpectations(mockPMBus, expectations); 1048 // Also get another read of READ_VIN. 1049 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1050 .Times(1) 1051 .WillOnce(Return("125790")); 1052 psu.analyze(); 1053 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT); 1054 } 1055 } 1056 1057 TEST_F(PowerSupplyTests, HasInputFault) 1058 { 1059 auto bus = sdbusplus::bus::new_default(); 1060 1061 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 1062 MockedGPIOInterface* mockPresenceGPIO = 1063 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1064 // Always return 1 to indicate present. 1065 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1066 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1067 setMissingToPresentExpects(mockPMBus, mockedUtil); 1068 // STATUS_WORD 0x0000 is powered on, no faults. 1069 PMBusExpectations expectations; 1070 setPMBusExpectations(mockPMBus, expectations); 1071 // Analyze call will also need good READ_VIN value to check. 1072 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1073 .Times(1) 1074 .WillOnce(Return("201100")); 1075 psu.analyze(); 1076 EXPECT_EQ(psu.hasInputFault(), false); 1077 // STATUS_WORD with input fault/warn on. 1078 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN); 1079 // STATUS_INPUT with an input fault bit on. 1080 expectations.statusInputValue = 0x80; 1081 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1082 { 1083 setPMBusExpectations(mockPMBus, expectations); 1084 // Analyze call will also need good READ_VIN value to check. 1085 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1086 .Times(1) 1087 .WillOnce(Return("201200")); 1088 psu.analyze(); 1089 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT); 1090 } 1091 // STATUS_WORD with no bits on. 1092 expectations.statusWordValue = 0; 1093 setPMBusExpectations(mockPMBus, expectations); 1094 // Analyze call will also need good READ_VIN value to check. 1095 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1096 .Times(1) 1097 .WillOnce(Return("201300")); 1098 psu.analyze(); 1099 EXPECT_EQ(psu.hasInputFault(), false); 1100 } 1101 1102 TEST_F(PowerSupplyTests, HasMFRFault) 1103 { 1104 auto bus = sdbusplus::bus::new_default(); 1105 1106 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 1107 MockedGPIOInterface* mockPresenceGPIO = 1108 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1109 // Always return 1 to indicate present. 1110 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1111 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1112 setMissingToPresentExpects(mockPMBus, mockedUtil); 1113 // First return STATUS_WORD with no bits on. 1114 // STATUS_WORD 0x0000 is powered on, no faults. 1115 PMBusExpectations expectations; 1116 setPMBusExpectations(mockPMBus, expectations); 1117 // Analyze call will also need good READ_VIN value to check. 1118 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1119 .Times(1) 1120 .WillOnce(Return("202100")); 1121 psu.analyze(); 1122 EXPECT_EQ(psu.hasMFRFault(), false); 1123 // Next return STATUS_WORD with MFR fault bit on. 1124 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1125 // STATUS_MFR_SPEFIC with bit(s) on. 1126 expectations.statusMFRValue = 0xFF; 1127 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1128 { 1129 setPMBusExpectations(mockPMBus, expectations); 1130 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1131 .Times(1) 1132 .WillOnce(Return("202200")); 1133 psu.analyze(); 1134 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT); 1135 } 1136 // Back to no bits on in STATUS_WORD 1137 expectations.statusWordValue = 0; 1138 setPMBusExpectations(mockPMBus, expectations); 1139 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1140 .Times(1) 1141 .WillOnce(Return("202300")); 1142 psu.analyze(); 1143 EXPECT_EQ(psu.hasMFRFault(), false); 1144 } 1145 1146 TEST_F(PowerSupplyTests, HasVINUVFault) 1147 { 1148 auto bus = sdbusplus::bus::new_default(); 1149 1150 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 1151 MockedGPIOInterface* mockPresenceGPIO = 1152 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1153 // Always return 1 to indicate present. 1154 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1155 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1156 setMissingToPresentExpects(mockPMBus, mockedUtil); 1157 1158 // Presence change from missing to present will trigger in1_input read in 1159 // an attempt to get CLEAR_FAULTS called. Return value ignored. 1160 // Zero to non-zero voltage, for missing/present change, triggers clear 1161 // faults call again. Return value ignored. 1162 // Fault (low voltage) to not faulted (voltage in range) triggers clear 1163 // faults call a third time. 1164 1165 // STATUS_WORD 0x0000 is powered on, no faults. 1166 PMBusExpectations expectations; 1167 setPMBusExpectations(mockPMBus, expectations); 1168 // Analyze call will also need good READ_VIN value to check. 1169 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1170 .Times(1) 1171 .WillOnce(Return("201100")); 1172 psu.analyze(); 1173 EXPECT_EQ(psu.hasVINUVFault(), false); 1174 // Turn fault on. 1175 expectations.statusWordValue = (status_word::VIN_UV_FAULT); 1176 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by 1177 // Figure 16, and assume bits on in STATUS_INPUT. 1178 expectations.statusInputValue = 0x18; 1179 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1180 { 1181 setPMBusExpectations(mockPMBus, expectations); 1182 // If there is a VIN_UV fault, fake reading voltage of less than 20V 1183 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1184 .Times(1) 1185 .WillOnce(Return("19876")); 1186 psu.analyze(); 1187 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT); 1188 } 1189 // Back to no fault bits on in STATUS_WORD 1190 expectations.statusWordValue = 0; 1191 setPMBusExpectations(mockPMBus, expectations); 1192 // Updates now result in clearing faults if read voltage goes from below the 1193 // minimum, to within a valid range. 1194 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1195 .Times(1) 1196 .WillOnce(Return("201300")); 1197 // Went from below minimum to within range, expect CLEAR_FAULTS. 1198 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(3)); 1199 psu.analyze(); 1200 EXPECT_EQ(psu.hasVINUVFault(), false); 1201 } 1202 1203 TEST_F(PowerSupplyTests, HasVoutOVFault) 1204 { 1205 auto bus = sdbusplus::bus::new_default(); 1206 1207 PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName}; 1208 MockedGPIOInterface* mockPresenceGPIO = 1209 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1210 // Always return 1 to indicate present. 1211 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1212 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1213 setMissingToPresentExpects(mockPMBus, mockedUtil); 1214 // STATUS_WORD 0x0000 is powered on, no faults. 1215 PMBusExpectations expectations; 1216 setPMBusExpectations(mockPMBus, expectations); 1217 // Call to analyze will trigger read of "in1_input" to check voltage. 1218 // Initial value would be 0, so this read updates it to non-zero. 1219 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1220 .Times(1) 1221 .WillOnce(Return("202100")); 1222 psu.analyze(); 1223 EXPECT_EQ(psu.hasVoutOVFault(), false); 1224 // Turn fault on. 1225 expectations.statusWordValue = (status_word::VOUT_OV_FAULT); 1226 // STATUS_VOUT fault bit(s) 1227 expectations.statusVOUTValue = 0x80; 1228 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1229 { 1230 setPMBusExpectations(mockPMBus, expectations); 1231 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1232 .Times(1) 1233 .WillOnce(Return("202200")); 1234 psu.analyze(); 1235 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT); 1236 } 1237 // Back to no fault bits on in STATUS_WORD 1238 expectations.statusWordValue = 0; 1239 setPMBusExpectations(mockPMBus, expectations); 1240 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1241 .Times(1) 1242 .WillOnce(Return("202300")); 1243 psu.analyze(); 1244 EXPECT_EQ(psu.hasVoutOVFault(), false); 1245 } 1246 1247 TEST_F(PowerSupplyTests, HasIoutOCFault) 1248 { 1249 auto bus = sdbusplus::bus::new_default(); 1250 1251 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName}; 1252 MockedGPIOInterface* mockPresenceGPIO = 1253 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1254 // Always return 1 to indicate present. 1255 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1256 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1257 setMissingToPresentExpects(mockPMBus, mockedUtil); 1258 // STATUS_WORD 0x0000 is powered on, no faults. 1259 PMBusExpectations expectations; 1260 setPMBusExpectations(mockPMBus, expectations); 1261 // Call to analyze will trigger read of "in1_input" to check voltage. 1262 // Initial value would be 0, so this read updates it to non-zero. 1263 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1264 .Times(1) 1265 .WillOnce(Return("203100")); 1266 psu.analyze(); 1267 EXPECT_EQ(psu.hasIoutOCFault(), false); 1268 // Turn fault on. 1269 expectations.statusWordValue = status_word::IOUT_OC_FAULT; 1270 // STATUS_IOUT fault bit(s) 1271 expectations.statusIOUTValue = 0x88; 1272 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1273 { 1274 setPMBusExpectations(mockPMBus, expectations); 1275 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1276 .Times(1) 1277 .WillOnce(Return("203200")); 1278 psu.analyze(); 1279 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT); 1280 } 1281 // Back to no fault bits on in STATUS_WORD 1282 expectations.statusWordValue = 0; 1283 setPMBusExpectations(mockPMBus, expectations); 1284 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1285 .Times(1) 1286 .WillOnce(Return("203300")); 1287 psu.analyze(); 1288 EXPECT_EQ(psu.hasIoutOCFault(), false); 1289 } 1290 1291 TEST_F(PowerSupplyTests, HasVoutUVFault) 1292 { 1293 auto bus = sdbusplus::bus::new_default(); 1294 1295 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName}; 1296 MockedGPIOInterface* mockPresenceGPIO = 1297 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1298 // Always return 1 to indicate present. 1299 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1300 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1301 setMissingToPresentExpects(mockPMBus, mockedUtil); 1302 // STATUS_WORD 0x0000 is powered on, no faults. 1303 PMBusExpectations expectations; 1304 setPMBusExpectations(mockPMBus, expectations); 1305 // Call to analyze will trigger read of "in1_input" to check voltage. 1306 // Initial value would be 0, so this read updates it to non-zero. 1307 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1308 .Times(1) 1309 .WillOnce(Return("204100")); 1310 psu.analyze(); 1311 EXPECT_EQ(psu.hasVoutUVFault(), false); 1312 // Turn fault on. 1313 expectations.statusWordValue = (status_word::VOUT_FAULT); 1314 // STATUS_VOUT fault bit(s) 1315 expectations.statusVOUTValue = 0x30; 1316 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1317 { 1318 setPMBusExpectations(mockPMBus, expectations); 1319 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1320 .Times(1) 1321 .WillOnce(Return("204200")); 1322 psu.analyze(); 1323 EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT); 1324 } 1325 // Back to no fault bits on in STATUS_WORD 1326 expectations.statusWordValue = 0; 1327 setPMBusExpectations(mockPMBus, expectations); 1328 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1329 .Times(1) 1330 .WillOnce(Return("204300")); 1331 psu.analyze(); 1332 EXPECT_EQ(psu.hasVoutUVFault(), false); 1333 } 1334 1335 TEST_F(PowerSupplyTests, HasFanFault) 1336 { 1337 auto bus = sdbusplus::bus::new_default(); 1338 1339 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName}; 1340 MockedGPIOInterface* mockPresenceGPIO = 1341 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1342 // Always return 1 to indicate present. 1343 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1344 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1345 setMissingToPresentExpects(mockPMBus, mockedUtil); 1346 // STATUS_WORD 0x0000 is powered on, no faults. 1347 PMBusExpectations expectations; 1348 setPMBusExpectations(mockPMBus, expectations); 1349 // Call to analyze will trigger read of "in1_input" to check voltage. 1350 // Initial value would be 0, so this read updates it to non-zero. 1351 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1352 .Times(1) 1353 .WillOnce(Return("205100")); 1354 psu.analyze(); 1355 EXPECT_EQ(psu.hasFanFault(), false); 1356 // Turn fault on. 1357 expectations.statusWordValue = (status_word::FAN_FAULT); 1358 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault) 1359 expectations.statusFans12Value = 0x80; 1360 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1361 { 1362 setPMBusExpectations(mockPMBus, expectations); 1363 // Call to analyze will trigger read of "in1_input" to check voltage. 1364 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1365 .Times(1) 1366 .WillOnce(Return("205200")); 1367 psu.analyze(); 1368 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT); 1369 } 1370 // Back to no fault bits on in STATUS_WORD 1371 expectations.statusWordValue = 0; 1372 setPMBusExpectations(mockPMBus, expectations); 1373 // Call to analyze will trigger read of "in1_input" to check voltage. 1374 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1375 .Times(1) 1376 .WillOnce(Return("205300")); 1377 psu.analyze(); 1378 EXPECT_EQ(psu.hasFanFault(), false); 1379 } 1380 1381 TEST_F(PowerSupplyTests, HasTempFault) 1382 { 1383 auto bus = sdbusplus::bus::new_default(); 1384 1385 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName}; 1386 MockedGPIOInterface* mockPresenceGPIO = 1387 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1388 // Always return 1 to indicate present. 1389 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1390 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1391 setMissingToPresentExpects(mockPMBus, mockedUtil); 1392 // STATUS_WORD 0x0000 is powered on, no faults. 1393 PMBusExpectations expectations; 1394 setPMBusExpectations(mockPMBus, expectations); 1395 // Call to analyze will trigger read of "in1_input" to check voltage. 1396 // Initial value would be 0, so this read updates it to non-zero. 1397 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1398 .Times(1) 1399 .WillOnce(Return("206100")); 1400 psu.analyze(); 1401 EXPECT_EQ(psu.hasTempFault(), false); 1402 // Turn fault on. 1403 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN); 1404 // STATUS_TEMPERATURE fault bit on (OT Fault) 1405 expectations.statusTempValue = 0x80; 1406 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1407 { 1408 setPMBusExpectations(mockPMBus, expectations); 1409 // Call to analyze will trigger read of "in1_input" to check voltage. 1410 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1411 .Times(1) 1412 .WillOnce(Return("206200")); 1413 psu.analyze(); 1414 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT); 1415 } 1416 // Back to no fault bits on in STATUS_WORD 1417 expectations.statusWordValue = 0; 1418 setPMBusExpectations(mockPMBus, expectations); 1419 // Call to analyze will trigger read of "in1_input" to check voltage. 1420 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1421 .Times(1) 1422 .WillOnce(Return("206300")); 1423 psu.analyze(); 1424 EXPECT_EQ(psu.hasTempFault(), false); 1425 } 1426 1427 TEST_F(PowerSupplyTests, HasPgoodFault) 1428 { 1429 auto bus = sdbusplus::bus::new_default(); 1430 1431 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, PSUGPIOLineName}; 1432 MockedGPIOInterface* mockPresenceGPIO = 1433 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1434 // Always return 1 to indicate present. 1435 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1436 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1437 setMissingToPresentExpects(mockPMBus, mockedUtil); 1438 // STATUS_WORD 0x0000 is powered on, no faults. 1439 PMBusExpectations expectations; 1440 setPMBusExpectations(mockPMBus, expectations); 1441 // Call to analyze will trigger read of "in1_input" to check voltage. 1442 // Initial value would be 0, so this read updates it to non-zero. 1443 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1444 .Times(1) 1445 .WillOnce(Return("207100")); 1446 psu.analyze(); 1447 EXPECT_EQ(psu.hasPgoodFault(), false); 1448 // Setup another expectation of no faults. 1449 setPMBusExpectations(mockPMBus, expectations); 1450 // Call to analyze will trigger read of "in1_input" to check voltage. 1451 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1452 .Times(1) 1453 .WillOnce(Return("207200")); 1454 psu.analyze(); 1455 EXPECT_EQ(psu.hasPgoodFault(), false); 1456 // Setup another expectation of no faults. 1457 setPMBusExpectations(mockPMBus, expectations); 1458 // Call to analyze will trigger read of "in1_input" to check voltage. 1459 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1460 .Times(1) 1461 .WillOnce(Return("207300")); 1462 psu.analyze(); 1463 EXPECT_EQ(psu.hasPgoodFault(), false); 1464 // Turn PGOOD# off (fault on). 1465 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED); 1466 setPMBusExpectations(mockPMBus, expectations); 1467 // Call to analyze will trigger read of "in1_input" to check voltage. 1468 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1469 .Times(1) 1470 .WillOnce(Return("207400")); 1471 psu.analyze(); 1472 // Expect false until reaches DEGLITCH_LIMIT 1473 EXPECT_EQ(psu.hasPgoodFault(), false); 1474 setPMBusExpectations(mockPMBus, expectations); 1475 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1476 .Times(1) 1477 .WillOnce(Return("207500")); 1478 psu.analyze(); 1479 // Expect false until reaches DEGLITCH_LIMIT 1480 EXPECT_EQ(psu.hasPgoodFault(), false); 1481 setPMBusExpectations(mockPMBus, expectations); 1482 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1483 .Times(1) 1484 .WillOnce(Return("207600")); 1485 psu.analyze(); 1486 // DEGLITCH_LIMIT reached, expect true. 1487 EXPECT_EQ(psu.hasPgoodFault(), true); 1488 // Back to no fault bits on in STATUS_WORD 1489 expectations.statusWordValue = 0; 1490 setPMBusExpectations(mockPMBus, expectations); 1491 // Call to analyze will trigger read of "in1_input" to check voltage. 1492 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1493 .Times(1) 1494 .WillOnce(Return("207700")); 1495 psu.analyze(); 1496 EXPECT_EQ(psu.hasPgoodFault(), false); 1497 1498 // Turn OFF bit on 1499 expectations.statusWordValue = (status_word::UNIT_IS_OFF); 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("208100")); 1505 psu.analyze(); 1506 EXPECT_EQ(psu.hasPgoodFault(), false); 1507 setPMBusExpectations(mockPMBus, expectations); 1508 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1509 .Times(1) 1510 .WillOnce(Return("208200")); 1511 psu.analyze(); 1512 EXPECT_EQ(psu.hasPgoodFault(), false); 1513 setPMBusExpectations(mockPMBus, expectations); 1514 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1515 .Times(1) 1516 .WillOnce(Return("208300")); 1517 psu.analyze(); 1518 EXPECT_EQ(psu.hasPgoodFault(), true); 1519 // Back to no fault bits on in STATUS_WORD 1520 expectations.statusWordValue = 0; 1521 setPMBusExpectations(mockPMBus, expectations); 1522 // Call to analyze will trigger read of "in1_input" to check voltage. 1523 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1524 .Times(1) 1525 .WillOnce(Return("208400")); 1526 psu.analyze(); 1527 EXPECT_EQ(psu.hasPgoodFault(), false); 1528 } 1529 1530 TEST_F(PowerSupplyTests, HasPSKillFault) 1531 { 1532 auto bus = sdbusplus::bus::new_default(); 1533 PowerSupply psu{bus, PSUInventoryPath, 4, 0x6d, PSUGPIOLineName}; 1534 MockedGPIOInterface* mockPresenceGPIO = 1535 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1536 // Always return 1 to indicate present. 1537 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1538 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1539 setMissingToPresentExpects(mockPMBus, mockedUtil); 1540 // STATUS_WORD 0x0000 is powered on, no faults. 1541 PMBusExpectations expectations; 1542 setPMBusExpectations(mockPMBus, expectations); 1543 // Call to analyze will trigger read of "in1_input" to check voltage. 1544 // Initial value would be 0, so this read updates it to non-zero. 1545 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1546 .Times(1) 1547 .WillOnce(Return("208100")); 1548 psu.analyze(); 1549 EXPECT_EQ(psu.hasPSKillFault(), false); 1550 // Next return STATUS_WORD with MFR fault bit on. 1551 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1552 // STATUS_MFR_SPEFIC with bit(s) on. 1553 expectations.statusMFRValue = 0xFF; 1554 1555 // Deglitching faults, false until read the fault bits on up to the limit. 1556 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1557 { 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("208200")); 1563 psu.analyze(); 1564 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT); 1565 } 1566 1567 // Back to no bits on in STATUS_WORD 1568 expectations.statusWordValue = 0; 1569 setPMBusExpectations(mockPMBus, expectations); 1570 // Call to analyze will trigger read of "in1_input" to check voltage. 1571 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1572 .Times(1) 1573 .WillOnce(Return("208300")); 1574 psu.analyze(); 1575 EXPECT_EQ(psu.hasPSKillFault(), false); 1576 // Next return STATUS_WORD with MFR fault bit on. 1577 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1578 // STATUS_MFR_SPEFIC with bit 4 on. 1579 expectations.statusMFRValue = 0x10; 1580 1581 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1582 { 1583 setPMBusExpectations(mockPMBus, expectations); 1584 // Call to analyze will trigger read of "in1_input" to check voltage. 1585 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1586 .Times(1) 1587 .WillOnce(Return("208400")); 1588 psu.analyze(); 1589 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT); 1590 } 1591 1592 // Back to no bits on in STATUS_WORD 1593 expectations.statusWordValue = 0; 1594 setPMBusExpectations(mockPMBus, expectations); 1595 // Call to analyze will trigger read of "in1_input" to check voltage. 1596 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1597 .Times(1) 1598 .WillOnce(Return("208500")); 1599 psu.analyze(); 1600 EXPECT_EQ(psu.hasPSKillFault(), false); 1601 } 1602 1603 TEST_F(PowerSupplyTests, HasPS12VcsFault) 1604 { 1605 auto bus = sdbusplus::bus::new_default(); 1606 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6e, PSUGPIOLineName}; 1607 MockedGPIOInterface* mockPresenceGPIO = 1608 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1609 // Always return 1 to indicate present. 1610 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1611 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1612 setMissingToPresentExpects(mockPMBus, mockedUtil); 1613 // STATUS_WORD 0x0000 is powered on, no faults. 1614 PMBusExpectations expectations; 1615 setPMBusExpectations(mockPMBus, expectations); 1616 // Call to analyze will trigger read of "in1_input" to check voltage. 1617 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1618 .Times(1) 1619 .WillOnce(Return("209100")); 1620 psu.analyze(); 1621 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1622 // Next return STATUS_WORD with MFR fault bit on. 1623 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1624 // STATUS_MFR_SPEFIC with bit(s) on. 1625 expectations.statusMFRValue = 0xFF; 1626 1627 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1628 { 1629 setPMBusExpectations(mockPMBus, expectations); 1630 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1631 .Times(1) 1632 .WillOnce(Return("209200")); 1633 psu.analyze(); 1634 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT); 1635 } 1636 1637 // Back to no bits on in STATUS_WORD 1638 expectations.statusWordValue = 0; 1639 setPMBusExpectations(mockPMBus, expectations); 1640 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1641 .Times(1) 1642 .WillOnce(Return("209300")); 1643 psu.analyze(); 1644 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1645 // Next return STATUS_WORD with MFR fault bit on. 1646 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1647 // STATUS_MFR_SPEFIC with bit 6 on. 1648 expectations.statusMFRValue = 0x40; 1649 1650 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1651 { 1652 setPMBusExpectations(mockPMBus, expectations); 1653 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1654 .Times(1) 1655 .WillOnce(Return("209400")); 1656 psu.analyze(); 1657 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT); 1658 } 1659 1660 // Back to no bits on in STATUS_WORD 1661 expectations.statusWordValue = 0; 1662 setPMBusExpectations(mockPMBus, expectations); 1663 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1664 .Times(1) 1665 .WillOnce(Return("209500")); 1666 psu.analyze(); 1667 EXPECT_EQ(psu.hasPS12VcsFault(), false); 1668 } 1669 1670 TEST_F(PowerSupplyTests, HasPSCS12VFault) 1671 { 1672 auto bus = sdbusplus::bus::new_default(); 1673 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f, PSUGPIOLineName}; 1674 MockedGPIOInterface* mockPresenceGPIO = 1675 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 1676 // Always return 1 to indicate present. 1677 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 1678 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 1679 setMissingToPresentExpects(mockPMBus, mockedUtil); 1680 // STATUS_WORD 0x0000 is powered on, no faults. 1681 PMBusExpectations expectations; 1682 setPMBusExpectations(mockPMBus, expectations); 1683 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1684 .Times(1) 1685 .WillOnce(Return("209100")); 1686 psu.analyze(); 1687 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1688 // Next return STATUS_WORD with MFR fault bit on. 1689 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1690 // STATUS_MFR_SPEFIC with bit(s) on. 1691 expectations.statusMFRValue = 0xFF; 1692 1693 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1694 { 1695 setPMBusExpectations(mockPMBus, expectations); 1696 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1697 .Times(1) 1698 .WillOnce(Return("209200")); 1699 psu.analyze(); 1700 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT); 1701 } 1702 1703 // Back to no bits on in STATUS_WORD 1704 expectations.statusWordValue = 0; 1705 setPMBusExpectations(mockPMBus, expectations); 1706 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1707 .Times(1) 1708 .WillOnce(Return("209300")); 1709 psu.analyze(); 1710 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1711 // Next return STATUS_WORD with MFR fault bit on. 1712 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 1713 // STATUS_MFR_SPEFIC with bit 7 on. 1714 expectations.statusMFRValue = 0x80; 1715 1716 for (auto x = 1; x <= DEGLITCH_LIMIT; x++) 1717 { 1718 setPMBusExpectations(mockPMBus, expectations); 1719 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1720 .Times(1) 1721 .WillOnce(Return("209400")); 1722 psu.analyze(); 1723 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT); 1724 } 1725 1726 // Back to no bits on in STATUS_WORD 1727 expectations.statusWordValue = 0; 1728 setPMBusExpectations(mockPMBus, expectations); 1729 EXPECT_CALL(mockPMBus, readString(READ_VIN, _)) 1730 .Times(1) 1731 .WillOnce(Return("209500")); 1732 psu.analyze(); 1733 EXPECT_EQ(psu.hasPSCS12VFault(), false); 1734 } 1735