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 TEST_F(PowerSupplyTests, Constructor) 96 { 97 /** 98 * @param[in] invpath - String for inventory path to use 99 * @param[in] i2cbus - The bus number this power supply is on 100 * @param[in] i2caddr - The 16-bit I2C address of the power supply 101 * @param[in] gpioLineName - The string for the gpio-line-name to read for 102 * presence. 103 * @param[in] bindDelay - Time in milliseconds to delay binding the device 104 * driver after seeing the presence line go active. 105 */ 106 auto bus = sdbusplus::bus::new_default(); 107 108 // Try where inventory path is empty, constructor should fail. 109 try 110 { 111 auto psu = 112 std::make_unique<PowerSupply>(bus, "", 3, 0x68, PSUGPIOLineName); 113 ADD_FAILURE() << "Should not have reached this line."; 114 } 115 catch (const std::invalid_argument& e) 116 { 117 EXPECT_STREQ(e.what(), "Invalid empty inventoryPath"); 118 } 119 catch (...) 120 { 121 ADD_FAILURE() << "Should not have caught exception."; 122 } 123 124 // TODO: Try invalid i2c address? 125 126 // Try where gpioLineName is empty. 127 try 128 { 129 auto psu = 130 std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, ""); 131 ADD_FAILURE() 132 << "Should not have reached this line. Invalid gpioLineName."; 133 } 134 catch (const std::invalid_argument& e) 135 { 136 EXPECT_STREQ(e.what(), "Invalid empty gpioLineName"); 137 } 138 catch (...) 139 { 140 ADD_FAILURE() << "Should not have caught exception."; 141 } 142 143 // Test with valid arguments 144 // NOT using D-Bus inventory path for presence. 145 try 146 { 147 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, 148 PSUGPIOLineName); 149 150 EXPECT_EQ(psu->isPresent(), false); 151 EXPECT_EQ(psu->isFaulted(), false); 152 EXPECT_EQ(psu->hasCommFault(), false); 153 EXPECT_EQ(psu->hasInputFault(), false); 154 EXPECT_EQ(psu->hasMFRFault(), false); 155 EXPECT_EQ(psu->hasVINUVFault(), false); 156 EXPECT_EQ(psu->hasVoutOVFault(), false); 157 EXPECT_EQ(psu->hasIoutOCFault(), false); 158 EXPECT_EQ(psu->hasVoutUVFault(), false); 159 EXPECT_EQ(psu->hasFanFault(), false); 160 EXPECT_EQ(psu->hasTempFault(), false); 161 EXPECT_EQ(psu->hasPgoodFault(), false); 162 } 163 catch (...) 164 { 165 ADD_FAILURE() << "Should not have caught exception."; 166 } 167 168 // Test with valid arguments 169 // TODO: Using D-Bus inventory path for presence. 170 try 171 { 172 // FIXME: How do I get that presenceGPIO.read() in the startup to throw 173 // an exception? 174 175 // EXPECT_CALL(mockedUtil, getPresence(_, 176 // StrEq(PSUInventoryPath))) 177 // .Times(1); 178 } 179 catch (...) 180 { 181 ADD_FAILURE() << "Should not have caught exception."; 182 } 183 } 184 185 TEST_F(PowerSupplyTests, Analyze) 186 { 187 auto bus = sdbusplus::bus::new_default(); 188 189 { 190 // If I default to reading the GPIO, I will NOT expect a call to 191 // getPresence(). 192 193 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName}; 194 MockedGPIOInterface* mockPresenceGPIO = 195 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 196 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0)); 197 198 psu.analyze(); 199 // By default, nothing should change. 200 EXPECT_EQ(psu.isPresent(), false); 201 EXPECT_EQ(psu.isFaulted(), false); 202 EXPECT_EQ(psu.hasInputFault(), false); 203 EXPECT_EQ(psu.hasMFRFault(), false); 204 EXPECT_EQ(psu.hasVINUVFault(), false); 205 EXPECT_EQ(psu.hasCommFault(), false); 206 EXPECT_EQ(psu.hasVoutOVFault(), false); 207 EXPECT_EQ(psu.hasIoutOCFault(), false); 208 EXPECT_EQ(psu.hasVoutUVFault(), false); 209 EXPECT_EQ(psu.hasFanFault(), false); 210 EXPECT_EQ(psu.hasTempFault(), false); 211 EXPECT_EQ(psu.hasPgoodFault(), false); 212 } 213 214 PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName}; 215 // In order to get the various faults tested, the power supply needs to 216 // be present in order to read from the PMBus device(s). 217 MockedGPIOInterface* mockPresenceGPIO2 = 218 static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO()); 219 ON_CALL(*mockPresenceGPIO2, read()).WillByDefault(Return(1)); 220 EXPECT_EQ(psu2.isPresent(), false); 221 222 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus()); 223 // Presence change from missing to present will trigger write to 224 // ON_OFF_CONFIG. 225 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, _, _)); 226 // Presence change from missing to present will trigger in1_input read 227 // in an attempt to get CLEAR_FAULTS called. 228 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000)); 229 230 // STATUS_WORD INPUT fault. 231 { 232 // Start with STATUS_WORD 0x0000. Powered on, no faults. 233 // Set expectations for a no fault 234 PMBusExpectations expectations; 235 setPMBusExpectations(mockPMBus, expectations); 236 psu2.analyze(); 237 EXPECT_EQ(psu2.isPresent(), true); 238 EXPECT_EQ(psu2.isFaulted(), false); 239 EXPECT_EQ(psu2.hasInputFault(), false); 240 EXPECT_EQ(psu2.hasMFRFault(), false); 241 EXPECT_EQ(psu2.hasVINUVFault(), false); 242 EXPECT_EQ(psu2.hasCommFault(), false); 243 EXPECT_EQ(psu2.hasVoutOVFault(), false); 244 EXPECT_EQ(psu2.hasIoutOCFault(), false); 245 EXPECT_EQ(psu2.hasVoutUVFault(), false); 246 EXPECT_EQ(psu2.hasFanFault(), false); 247 EXPECT_EQ(psu2.hasTempFault(), false); 248 EXPECT_EQ(psu2.hasPgoodFault(), false); 249 250 // Update expectations for STATUS_WORD input fault/warn 251 // STATUS_INPUT fault bits ... on. 252 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN); 253 expectations.statusInputValue = 0x38; 254 setPMBusExpectations(mockPMBus, expectations); 255 psu2.analyze(); 256 EXPECT_EQ(psu2.isPresent(), true); 257 EXPECT_EQ(psu2.isFaulted(), true); 258 EXPECT_EQ(psu2.hasInputFault(), true); 259 EXPECT_EQ(psu2.hasMFRFault(), false); 260 EXPECT_EQ(psu2.hasVINUVFault(), false); 261 EXPECT_EQ(psu2.hasCommFault(), false); 262 EXPECT_EQ(psu2.hasVoutOVFault(), false); 263 EXPECT_EQ(psu2.hasIoutOCFault(), false); 264 EXPECT_EQ(psu2.hasVoutUVFault(), false); 265 EXPECT_EQ(psu2.hasFanFault(), false); 266 EXPECT_EQ(psu2.hasTempFault(), false); 267 EXPECT_EQ(psu2.hasPgoodFault(), false); 268 } 269 270 // STATUS_WORD INPUT/UV fault. 271 { 272 // First need it to return good status, then the fault 273 PMBusExpectations expectations; 274 setPMBusExpectations(mockPMBus, expectations); 275 psu2.analyze(); 276 // Now set fault bits in STATUS_WORD 277 expectations.statusWordValue = 278 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT); 279 // STATUS_INPUT fault bits ... on. 280 expectations.statusInputValue = 0x38; 281 setPMBusExpectations(mockPMBus, expectations); 282 psu2.analyze(); 283 EXPECT_EQ(psu2.isPresent(), true); 284 EXPECT_EQ(psu2.isFaulted(), true); 285 EXPECT_EQ(psu2.hasInputFault(), true); 286 EXPECT_EQ(psu2.hasMFRFault(), false); 287 EXPECT_EQ(psu2.hasVINUVFault(), true); 288 EXPECT_EQ(psu2.hasCommFault(), false); 289 EXPECT_EQ(psu2.hasVoutOVFault(), false); 290 EXPECT_EQ(psu2.hasIoutOCFault(), false); 291 EXPECT_EQ(psu2.hasVoutUVFault(), false); 292 EXPECT_EQ(psu2.hasFanFault(), false); 293 EXPECT_EQ(psu2.hasTempFault(), false); 294 EXPECT_EQ(psu2.hasPgoodFault(), false); 295 } 296 297 // STATUS_WORD MFR fault. 298 { 299 // First need it to return good status, then the fault 300 PMBusExpectations expectations; 301 setPMBusExpectations(mockPMBus, expectations); 302 psu2.analyze(); 303 // Now STATUS_WORD with MFR fault bit on. 304 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 305 // STATUS_MFR bits on. 306 expectations.statusMFRValue = 0xFF; 307 setPMBusExpectations(mockPMBus, expectations); 308 psu2.analyze(); 309 EXPECT_EQ(psu2.isPresent(), true); 310 EXPECT_EQ(psu2.isFaulted(), true); 311 EXPECT_EQ(psu2.hasInputFault(), false); 312 EXPECT_EQ(psu2.hasMFRFault(), true); 313 EXPECT_EQ(psu2.hasVINUVFault(), false); 314 EXPECT_EQ(psu2.hasCommFault(), false); 315 EXPECT_EQ(psu2.hasVoutOVFault(), false); 316 EXPECT_EQ(psu2.hasIoutOCFault(), false); 317 EXPECT_EQ(psu2.hasVoutUVFault(), false); 318 EXPECT_EQ(psu2.hasFanFault(), false); 319 EXPECT_EQ(psu2.hasTempFault(), false); 320 EXPECT_EQ(psu2.hasPgoodFault(), false); 321 } 322 323 // Temperature fault. 324 { 325 // First STATUS_WORD with no bits set, then with temperature fault. 326 PMBusExpectations expectations; 327 setPMBusExpectations(mockPMBus, expectations); 328 psu2.analyze(); 329 // STATUS_WORD with temperature fault bit on. 330 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN); 331 // STATUS_TEMPERATURE with fault bit(s) on. 332 expectations.statusTempValue = 0x10; 333 setPMBusExpectations(mockPMBus, expectations); 334 psu2.analyze(); 335 EXPECT_EQ(psu2.isPresent(), true); 336 EXPECT_EQ(psu2.isFaulted(), true); 337 EXPECT_EQ(psu2.hasInputFault(), false); 338 EXPECT_EQ(psu2.hasMFRFault(), false); 339 EXPECT_EQ(psu2.hasVINUVFault(), false); 340 EXPECT_EQ(psu2.hasCommFault(), false); 341 EXPECT_EQ(psu2.hasVoutOVFault(), false); 342 EXPECT_EQ(psu2.hasIoutOCFault(), false); 343 EXPECT_EQ(psu2.hasVoutUVFault(), false); 344 EXPECT_EQ(psu2.hasFanFault(), false); 345 EXPECT_EQ(psu2.hasTempFault(), true); 346 EXPECT_EQ(psu2.hasPgoodFault(), false); 347 } 348 349 // CML fault 350 { 351 // First STATUS_WORD wit no bits set, then with CML fault. 352 PMBusExpectations expectations; 353 setPMBusExpectations(mockPMBus, expectations); 354 psu2.analyze(); 355 // STATUS_WORD with CML fault bit on. 356 expectations.statusWordValue = (status_word::CML_FAULT); 357 // Turn on STATUS_CML fault bit(s) 358 expectations.statusCMLValue = 0xFF; 359 setPMBusExpectations(mockPMBus, expectations); 360 psu2.analyze(); 361 EXPECT_EQ(psu2.isPresent(), true); 362 EXPECT_EQ(psu2.isFaulted(), true); 363 EXPECT_EQ(psu2.hasInputFault(), false); 364 EXPECT_EQ(psu2.hasMFRFault(), false); 365 EXPECT_EQ(psu2.hasVINUVFault(), false); 366 EXPECT_EQ(psu2.hasCommFault(), true); 367 EXPECT_EQ(psu2.hasVoutOVFault(), false); 368 EXPECT_EQ(psu2.hasIoutOCFault(), false); 369 EXPECT_EQ(psu2.hasVoutUVFault(), false); 370 EXPECT_EQ(psu2.hasFanFault(), false); 371 EXPECT_EQ(psu2.hasTempFault(), false); 372 EXPECT_EQ(psu2.hasPgoodFault(), false); 373 } 374 375 // VOUT_OV_FAULT fault 376 { 377 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault. 378 PMBusExpectations expectations; 379 setPMBusExpectations(mockPMBus, expectations); 380 psu2.analyze(); 381 // STATUS_WORD with VOUT/VOUT_OV fault. 382 expectations.statusWordValue = 383 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT)); 384 // Turn on STATUS_VOUT fault bit(s) 385 expectations.statusVOUTValue = 0xA0; 386 // STATUS_TEMPERATURE don't care (default) 387 setPMBusExpectations(mockPMBus, expectations); 388 psu2.analyze(); 389 EXPECT_EQ(psu2.isPresent(), true); 390 EXPECT_EQ(psu2.isFaulted(), true); 391 EXPECT_EQ(psu2.hasInputFault(), false); 392 EXPECT_EQ(psu2.hasMFRFault(), false); 393 EXPECT_EQ(psu2.hasVINUVFault(), false); 394 EXPECT_EQ(psu2.hasCommFault(), false); 395 EXPECT_EQ(psu2.hasVoutOVFault(), true); 396 EXPECT_EQ(psu2.hasVoutUVFault(), false); 397 EXPECT_EQ(psu2.hasIoutOCFault(), false); 398 EXPECT_EQ(psu2.hasFanFault(), false); 399 EXPECT_EQ(psu2.hasTempFault(), false); 400 EXPECT_EQ(psu2.hasPgoodFault(), false); 401 } 402 403 // IOUT_OC_FAULT fault 404 { 405 // First STATUS_WORD with no bits set, then with IOUT_OC fault. 406 PMBusExpectations expectations; 407 setPMBusExpectations(mockPMBus, expectations); 408 psu2.analyze(); 409 // STATUS_WORD with IOUT_OC fault. 410 expectations.statusWordValue = status_word::IOUT_OC_FAULT; 411 // Turn on STATUS_IOUT fault bit(s) 412 expectations.statusIOUTValue = 0x88; 413 setPMBusExpectations(mockPMBus, expectations); 414 psu2.analyze(); 415 EXPECT_EQ(psu2.isPresent(), true); 416 EXPECT_EQ(psu2.isFaulted(), true); 417 EXPECT_EQ(psu2.hasInputFault(), false); 418 EXPECT_EQ(psu2.hasMFRFault(), false); 419 EXPECT_EQ(psu2.hasVINUVFault(), false); 420 EXPECT_EQ(psu2.hasCommFault(), false); 421 EXPECT_EQ(psu2.hasVoutOVFault(), false); 422 EXPECT_EQ(psu2.hasIoutOCFault(), true); 423 EXPECT_EQ(psu2.hasVoutUVFault(), false); 424 EXPECT_EQ(psu2.hasFanFault(), false); 425 EXPECT_EQ(psu2.hasTempFault(), false); 426 EXPECT_EQ(psu2.hasPgoodFault(), false); 427 } 428 429 // VOUT_UV_FAULT 430 { 431 // First STATUS_WORD with no bits set, then with VOUT fault. 432 PMBusExpectations expectations; 433 setPMBusExpectations(mockPMBus, expectations); 434 psu2.analyze(); 435 // Change STATUS_WORD to indicate VOUT fault. 436 expectations.statusWordValue = (status_word::VOUT_FAULT); 437 // Turn on STATUS_VOUT fault bit(s) 438 expectations.statusVOUTValue = 0x30; 439 setPMBusExpectations(mockPMBus, expectations); 440 psu2.analyze(); 441 EXPECT_EQ(psu2.isPresent(), true); 442 EXPECT_EQ(psu2.isFaulted(), true); 443 EXPECT_EQ(psu2.hasInputFault(), false); 444 EXPECT_EQ(psu2.hasMFRFault(), false); 445 EXPECT_EQ(psu2.hasVINUVFault(), false); 446 EXPECT_EQ(psu2.hasCommFault(), false); 447 EXPECT_EQ(psu2.hasVoutOVFault(), false); 448 EXPECT_EQ(psu2.hasIoutOCFault(), false); 449 EXPECT_EQ(psu2.hasVoutUVFault(), true); 450 EXPECT_EQ(psu2.hasFanFault(), false); 451 EXPECT_EQ(psu2.hasTempFault(), false); 452 EXPECT_EQ(psu2.hasPgoodFault(), false); 453 } 454 455 // Fan fault 456 { 457 // First STATUS_WORD with no bits set, then with fan fault. 458 PMBusExpectations expectations; 459 setPMBusExpectations(mockPMBus, expectations); 460 psu2.analyze(); 461 expectations.statusWordValue = (status_word::FAN_FAULT); 462 // STATUS_FANS_1_2 with fan 1 warning & fault bits on. 463 expectations.statusFans12Value = 0xA0; 464 setPMBusExpectations(mockPMBus, expectations); 465 psu2.analyze(); 466 EXPECT_EQ(psu2.isPresent(), true); 467 EXPECT_EQ(psu2.isFaulted(), true); 468 EXPECT_EQ(psu2.hasInputFault(), false); 469 EXPECT_EQ(psu2.hasMFRFault(), false); 470 EXPECT_EQ(psu2.hasVINUVFault(), false); 471 EXPECT_EQ(psu2.hasCommFault(), false); 472 EXPECT_EQ(psu2.hasVoutOVFault(), false); 473 EXPECT_EQ(psu2.hasIoutOCFault(), false); 474 EXPECT_EQ(psu2.hasVoutUVFault(), false); 475 EXPECT_EQ(psu2.hasFanFault(), true); 476 EXPECT_EQ(psu2.hasTempFault(), false); 477 EXPECT_EQ(psu2.hasPgoodFault(), false); 478 } 479 480 // PGOOD/OFF fault. 481 { 482 // First STATUS_WORD with no bits set. 483 PMBusExpectations expectations; 484 setPMBusExpectations(mockPMBus, expectations); 485 psu2.analyze(); 486 EXPECT_EQ(psu2.isFaulted(), false); 487 // POWER_GOOD# inactive, and OFF bit on. 488 expectations.statusWordValue = 489 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF)); 490 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and 491 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults). 492 setPMBusExpectations(mockPMBus, expectations); 493 psu2.analyze(); 494 EXPECT_EQ(psu2.isPresent(), true); 495 EXPECT_EQ(psu2.isFaulted(), true); 496 EXPECT_EQ(psu2.hasInputFault(), false); 497 EXPECT_EQ(psu2.hasMFRFault(), false); 498 EXPECT_EQ(psu2.hasVINUVFault(), false); 499 EXPECT_EQ(psu2.hasCommFault(), false); 500 EXPECT_EQ(psu2.hasVoutOVFault(), false); 501 EXPECT_EQ(psu2.hasVoutUVFault(), false); 502 EXPECT_EQ(psu2.hasIoutOCFault(), false); 503 EXPECT_EQ(psu2.hasFanFault(), false); 504 EXPECT_EQ(psu2.hasTempFault(), false); 505 EXPECT_EQ(psu2.hasPgoodFault(), true); 506 } 507 508 // TODO: ReadFailure 509 } 510 511 TEST_F(PowerSupplyTests, OnOffConfig) 512 { 513 auto bus = sdbusplus::bus::new_default(); 514 uint8_t data = 0x15; 515 516 // Test where PSU is NOT present 517 try 518 { 519 // Assume GPIO presence, not inventory presence? 520 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName}; 521 522 MockedGPIOInterface* mockPresenceGPIO = 523 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 524 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0)); 525 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 526 // Constructor should set initial presence, default read returns 0. 527 // If it is not present, I should not be trying to write to it. 528 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0); 529 psu.onOffConfig(data); 530 } 531 catch (...) 532 {} 533 534 // Test where PSU is present 535 try 536 { 537 // Assume GPIO presence, not inventory presence? 538 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName}; 539 MockedGPIOInterface* mockPresenceGPIO = 540 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 541 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1)); 542 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 543 // TODO: expect setPresence call? 544 // updatePresence() private function reads gpio, called by analyze(). 545 psu.analyze(); 546 // TODO: ???should I check the filename? 547 EXPECT_CALL(mockPMBus, 548 writeBinary(_, ElementsAre(0x15), Type::HwmonDeviceDebug)) 549 .Times(1); 550 psu.onOffConfig(data); 551 } 552 catch (...) 553 {} 554 } 555 556 TEST_F(PowerSupplyTests, ClearFaults) 557 { 558 auto bus = sdbusplus::bus::new_default(); 559 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName}; 560 MockedGPIOInterface* mockPresenceGPIO = 561 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 562 // GPIO read return 1 to indicate present. 563 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1)); 564 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 565 // Presence change from missing to present will trigger in1_input read in 566 // an attempt to get CLEAR_FAULTS called. 567 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000)); 568 // STATUS_WORD 0x0000 is powered on, no faults. 569 PMBusExpectations expectations; 570 setPMBusExpectations(mockPMBus, expectations); 571 psu.analyze(); 572 EXPECT_EQ(psu.isPresent(), true); 573 EXPECT_EQ(psu.isFaulted(), false); 574 EXPECT_EQ(psu.hasInputFault(), false); 575 EXPECT_EQ(psu.hasMFRFault(), false); 576 EXPECT_EQ(psu.hasVINUVFault(), false); 577 EXPECT_EQ(psu.hasCommFault(), false); 578 EXPECT_EQ(psu.hasVoutOVFault(), false); 579 EXPECT_EQ(psu.hasIoutOCFault(), false); 580 EXPECT_EQ(psu.hasVoutUVFault(), false); 581 EXPECT_EQ(psu.hasFanFault(), false); 582 EXPECT_EQ(psu.hasTempFault(), false); 583 EXPECT_EQ(psu.hasPgoodFault(), false); 584 585 // STATUS_WORD with fault bits galore! 586 expectations.statusWordValue = 0xFFFF; 587 // STATUS_INPUT with fault bits on. 588 expectations.statusInputValue = 0xFF; 589 // STATUS_MFR_SPEFIC with bits on. 590 expectations.statusMFRValue = 0xFF; 591 // STATUS_CML with bits on. 592 expectations.statusCMLValue = 0xFF; 593 // STATUS_VOUT with bits on. 594 expectations.statusVOUTValue = 0xFF; 595 // STATUS_IOUT with bits on. 596 expectations.statusIOUTValue = 0xFF; 597 // STATUS_FANS_1_2 with bits on. 598 expectations.statusFans12Value = 0xFF; 599 // STATUS_TEMPERATURE with bits on. 600 expectations.statusTempValue = 0xFF; 601 setPMBusExpectations(mockPMBus, expectations); 602 psu.analyze(); 603 EXPECT_EQ(psu.isPresent(), true); 604 EXPECT_EQ(psu.isFaulted(), true); 605 EXPECT_EQ(psu.hasInputFault(), true); 606 EXPECT_EQ(psu.hasMFRFault(), true); 607 EXPECT_EQ(psu.hasVINUVFault(), true); 608 EXPECT_EQ(psu.hasCommFault(), true); 609 EXPECT_EQ(psu.hasVoutOVFault(), true); 610 EXPECT_EQ(psu.hasIoutOCFault(), true); 611 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT. 612 // Rely on HasVoutUVFault() to verify this sets and clears. 613 EXPECT_EQ(psu.hasVoutUVFault(), false); 614 EXPECT_EQ(psu.hasFanFault(), true); 615 EXPECT_EQ(psu.hasTempFault(), true); 616 EXPECT_EQ(psu.hasPgoodFault(), true); 617 618 EXPECT_CALL(mockPMBus, read("in1_input", _)) 619 .Times(1) 620 .WillOnce(Return(209000)); 621 psu.clearFaults(); 622 EXPECT_EQ(psu.isPresent(), true); 623 EXPECT_EQ(psu.isFaulted(), false); 624 EXPECT_EQ(psu.hasInputFault(), false); 625 EXPECT_EQ(psu.hasMFRFault(), false); 626 EXPECT_EQ(psu.hasVINUVFault(), false); 627 EXPECT_EQ(psu.hasCommFault(), false); 628 EXPECT_EQ(psu.hasVoutOVFault(), false); 629 EXPECT_EQ(psu.hasIoutOCFault(), false); 630 EXPECT_EQ(psu.hasVoutUVFault(), false); 631 EXPECT_EQ(psu.hasFanFault(), false); 632 EXPECT_EQ(psu.hasTempFault(), false); 633 EXPECT_EQ(psu.hasPgoodFault(), false); 634 635 // TODO: Faults clear on missing/present? 636 } 637 638 TEST_F(PowerSupplyTests, UpdateInventory) 639 { 640 auto bus = sdbusplus::bus::new_default(); 641 642 try 643 { 644 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 645 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 646 // If it is not present, I should not be trying to read a string 647 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0); 648 psu.updateInventory(); 649 } 650 catch (...) 651 { 652 ADD_FAILURE() << "Should not have caught exception."; 653 } 654 655 try 656 { 657 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName}; 658 MockedGPIOInterface* mockPresenceGPIO = 659 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 660 // GPIO read return 1 to indicate present. 661 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1)); 662 psu.analyze(); 663 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 664 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return("")); 665 psu.updateInventory(); 666 667 #if IBM_VPD 668 EXPECT_CALL(mockPMBus, readString(_, _)) 669 .WillOnce(Return("CCIN")) 670 .WillOnce(Return("PN3456")) 671 .WillOnce(Return("FN3456")) 672 .WillOnce(Return("HEADER")) 673 .WillOnce(Return("SN3456")) 674 .WillOnce(Return("FW3456")); 675 #endif 676 psu.updateInventory(); 677 // TODO: D-Bus mocking to verify values stored on D-Bus (???) 678 } 679 catch (...) 680 { 681 ADD_FAILURE() << "Should not have caught exception."; 682 } 683 } 684 685 TEST_F(PowerSupplyTests, IsPresent) 686 { 687 auto bus = sdbusplus::bus::new_default(); 688 689 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 690 MockedGPIOInterface* mockPresenceGPIO = 691 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 692 EXPECT_EQ(psu.isPresent(), false); 693 694 // Change GPIO read to return 1 to indicate present. 695 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1)); 696 psu.analyze(); 697 EXPECT_EQ(psu.isPresent(), true); 698 } 699 700 TEST_F(PowerSupplyTests, IsFaulted) 701 { 702 auto bus = sdbusplus::bus::new_default(); 703 704 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName}; 705 MockedGPIOInterface* mockPresenceGPIO = 706 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 707 // Always return 1 to indicate present. 708 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 709 psu.analyze(); 710 EXPECT_EQ(psu.isFaulted(), false); 711 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 712 PMBusExpectations expectations; 713 // STATUS_WORD with fault bits on. 714 expectations.statusWordValue = 0xFFFF; 715 // STATUS_INPUT with fault bits on. 716 expectations.statusInputValue = 0xFF; 717 // STATUS_MFR_SPECIFIC with faults bits on. 718 expectations.statusMFRValue = 0xFF; 719 // STATUS_CML with faults bits on. 720 expectations.statusCMLValue = 0xFF; 721 // STATUS_VOUT with fault bits on. 722 expectations.statusVOUTValue = 0xFF; 723 // STATUS_IOUT with fault bits on. 724 expectations.statusIOUTValue = 0xFF; 725 // STATUS_FANS_1_2 with bits on. 726 expectations.statusFans12Value = 0xFF; 727 // STATUS_TEMPERATURE with fault bits on. 728 expectations.statusTempValue = 0xFF; 729 setPMBusExpectations(mockPMBus, expectations); 730 psu.analyze(); 731 EXPECT_EQ(psu.isFaulted(), true); 732 } 733 734 TEST_F(PowerSupplyTests, HasInputFault) 735 { 736 auto bus = sdbusplus::bus::new_default(); 737 738 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 739 MockedGPIOInterface* mockPresenceGPIO = 740 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 741 // Always return 1 to indicate present. 742 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 743 psu.analyze(); 744 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 745 EXPECT_EQ(psu.hasInputFault(), false); 746 // STATUS_WORD 0x0000 is powered on, no faults. 747 PMBusExpectations expectations; 748 setPMBusExpectations(mockPMBus, expectations); 749 psu.analyze(); 750 EXPECT_EQ(psu.hasInputFault(), false); 751 // STATUS_WORD with input fault/warn on. 752 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN); 753 // STATUS_INPUT with an input fault bit on. 754 expectations.statusInputValue = 0x80; 755 setPMBusExpectations(mockPMBus, expectations); 756 psu.analyze(); 757 EXPECT_EQ(psu.hasInputFault(), true); 758 // STATUS_WORD with no bits on. 759 expectations.statusWordValue = 0; 760 setPMBusExpectations(mockPMBus, expectations); 761 psu.analyze(); 762 EXPECT_EQ(psu.hasInputFault(), false); 763 } 764 765 TEST_F(PowerSupplyTests, HasMFRFault) 766 { 767 auto bus = sdbusplus::bus::new_default(); 768 769 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 770 MockedGPIOInterface* mockPresenceGPIO = 771 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 772 // Always return 1 to indicate present. 773 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 774 psu.analyze(); 775 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 776 EXPECT_EQ(psu.hasMFRFault(), false); 777 // First return STATUS_WORD with no bits on. 778 // STATUS_WORD 0x0000 is powered on, no faults. 779 PMBusExpectations expectations; 780 setPMBusExpectations(mockPMBus, expectations); 781 psu.analyze(); 782 EXPECT_EQ(psu.hasMFRFault(), false); 783 // Next return STATUS_WORD with MFR fault bit on. 784 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 785 // STATUS_MFR_SPEFIC with bit(s) on. 786 expectations.statusMFRValue = 0xFF; 787 setPMBusExpectations(mockPMBus, expectations); 788 psu.analyze(); 789 EXPECT_EQ(psu.hasMFRFault(), true); 790 // Back to no bits on in STATUS_WORD 791 expectations.statusWordValue = 0; 792 setPMBusExpectations(mockPMBus, expectations); 793 psu.analyze(); 794 EXPECT_EQ(psu.hasMFRFault(), false); 795 } 796 797 TEST_F(PowerSupplyTests, HasVINUVFault) 798 { 799 auto bus = sdbusplus::bus::new_default(); 800 801 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 802 MockedGPIOInterface* mockPresenceGPIO = 803 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 804 // Always return 1 to indicate present. 805 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 806 psu.analyze(); 807 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 808 EXPECT_EQ(psu.hasVINUVFault(), false); 809 // STATUS_WORD 0x0000 is powered on, no faults. 810 PMBusExpectations expectations; 811 setPMBusExpectations(mockPMBus, expectations); 812 psu.analyze(); 813 EXPECT_EQ(psu.hasVINUVFault(), false); 814 // Turn fault on. 815 expectations.statusWordValue = (status_word::VIN_UV_FAULT); 816 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by 817 // Figure 16, and assume bits on in STATUS_INPUT. 818 expectations.statusInputValue = 0x18; 819 setPMBusExpectations(mockPMBus, expectations); 820 psu.analyze(); 821 EXPECT_EQ(psu.hasVINUVFault(), true); 822 // Back to no fault bits on in STATUS_WORD 823 expectations.statusWordValue = 0; 824 setPMBusExpectations(mockPMBus, expectations); 825 psu.analyze(); 826 EXPECT_EQ(psu.hasVINUVFault(), false); 827 } 828 829 TEST_F(PowerSupplyTests, HasVoutOVFault) 830 { 831 auto bus = sdbusplus::bus::new_default(); 832 833 PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName}; 834 MockedGPIOInterface* mockPresenceGPIO = 835 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 836 // Always return 1 to indicate present. 837 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 838 psu.analyze(); 839 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 840 EXPECT_EQ(psu.hasVoutOVFault(), false); 841 // STATUS_WORD 0x0000 is powered on, no faults. 842 PMBusExpectations expectations; 843 setPMBusExpectations(mockPMBus, expectations); 844 psu.analyze(); 845 EXPECT_EQ(psu.hasVoutOVFault(), false); 846 // Turn fault on. 847 expectations.statusWordValue = (status_word::VOUT_OV_FAULT); 848 // STATUS_VOUT fault bit(s) 849 expectations.statusVOUTValue = 0x80; 850 // STATUS_TEMPERATURE default. 851 setPMBusExpectations(mockPMBus, expectations); 852 psu.analyze(); 853 EXPECT_EQ(psu.hasVoutOVFault(), true); 854 // Back to no fault bits on in STATUS_WORD 855 expectations.statusWordValue = 0; 856 setPMBusExpectations(mockPMBus, expectations); 857 psu.analyze(); 858 EXPECT_EQ(psu.hasVoutOVFault(), false); 859 } 860 861 TEST_F(PowerSupplyTests, HasIoutOCFault) 862 { 863 auto bus = sdbusplus::bus::new_default(); 864 865 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName}; 866 MockedGPIOInterface* mockPresenceGPIO = 867 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 868 // Always return 1 to indicate present. 869 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 870 psu.analyze(); 871 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 872 EXPECT_EQ(psu.hasIoutOCFault(), false); 873 // STATUS_WORD 0x0000 is powered on, no faults. 874 PMBusExpectations expectations; 875 setPMBusExpectations(mockPMBus, expectations); 876 psu.analyze(); 877 EXPECT_EQ(psu.hasIoutOCFault(), false); 878 // Turn fault on. 879 expectations.statusWordValue = status_word::IOUT_OC_FAULT; 880 // STATUS_IOUT fault bit(s) 881 expectations.statusIOUTValue = 0x88; 882 setPMBusExpectations(mockPMBus, expectations); 883 psu.analyze(); 884 EXPECT_EQ(psu.hasIoutOCFault(), true); 885 // Back to no fault bits on in STATUS_WORD 886 expectations.statusWordValue = 0; 887 setPMBusExpectations(mockPMBus, expectations); 888 psu.analyze(); 889 EXPECT_EQ(psu.hasIoutOCFault(), false); 890 } 891 892 TEST_F(PowerSupplyTests, HasVoutUVFault) 893 { 894 auto bus = sdbusplus::bus::new_default(); 895 896 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName}; 897 MockedGPIOInterface* mockPresenceGPIO = 898 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 899 // Always return 1 to indicate present. 900 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 901 psu.analyze(); 902 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 903 EXPECT_EQ(psu.hasVoutUVFault(), false); 904 PMBusExpectations expectations; 905 setPMBusExpectations(mockPMBus, expectations); 906 psu.analyze(); 907 EXPECT_EQ(psu.hasVoutUVFault(), false); 908 // Turn fault on. 909 expectations.statusWordValue = (status_word::VOUT_FAULT); 910 // STATUS_VOUT fault bit(s) 911 expectations.statusVOUTValue = 0x30; 912 setPMBusExpectations(mockPMBus, expectations); 913 psu.analyze(); 914 EXPECT_EQ(psu.hasVoutUVFault(), true); 915 // Back to no fault bits on in STATUS_WORD 916 expectations.statusWordValue = 0; 917 setPMBusExpectations(mockPMBus, expectations); 918 psu.analyze(); 919 EXPECT_EQ(psu.hasVoutUVFault(), false); 920 } 921 922 TEST_F(PowerSupplyTests, HasFanFault) 923 { 924 auto bus = sdbusplus::bus::new_default(); 925 926 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName}; 927 MockedGPIOInterface* mockPresenceGPIO = 928 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 929 // Always return 1 to indicate present. 930 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 931 psu.analyze(); 932 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 933 EXPECT_EQ(psu.hasFanFault(), false); 934 // STATUS_WORD 0x0000 is powered on, no faults. 935 PMBusExpectations expectations; 936 setPMBusExpectations(mockPMBus, expectations); 937 psu.analyze(); 938 EXPECT_EQ(psu.hasFanFault(), false); 939 // Turn fault on. 940 expectations.statusWordValue = (status_word::FAN_FAULT); 941 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault) 942 expectations.statusFans12Value = 0x80; 943 setPMBusExpectations(mockPMBus, expectations); 944 psu.analyze(); 945 EXPECT_EQ(psu.hasFanFault(), true); 946 // Back to no fault bits on in STATUS_WORD 947 expectations.statusWordValue = 0; 948 setPMBusExpectations(mockPMBus, expectations); 949 psu.analyze(); 950 EXPECT_EQ(psu.hasFanFault(), false); 951 } 952 953 TEST_F(PowerSupplyTests, HasTempFault) 954 { 955 auto bus = sdbusplus::bus::new_default(); 956 957 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName}; 958 MockedGPIOInterface* mockPresenceGPIO = 959 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 960 // Always return 1 to indicate present. 961 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 962 psu.analyze(); 963 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 964 EXPECT_EQ(psu.hasTempFault(), false); 965 // STATUS_WORD 0x0000 is powered on, no faults. 966 PMBusExpectations expectations; 967 setPMBusExpectations(mockPMBus, expectations); 968 psu.analyze(); 969 EXPECT_EQ(psu.hasTempFault(), false); 970 // Turn fault on. 971 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN); 972 // STATUS_TEMPERATURE fault bit on (OT Fault) 973 expectations.statusTempValue = 0x80; 974 setPMBusExpectations(mockPMBus, expectations); 975 psu.analyze(); 976 EXPECT_EQ(psu.hasTempFault(), true); 977 // Back to no fault bits on in STATUS_WORD 978 expectations.statusWordValue = 0; 979 setPMBusExpectations(mockPMBus, expectations); 980 psu.analyze(); 981 EXPECT_EQ(psu.hasTempFault(), false); 982 } 983 984 TEST_F(PowerSupplyTests, HasPgoodFault) 985 { 986 auto bus = sdbusplus::bus::new_default(); 987 988 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, PSUGPIOLineName}; 989 MockedGPIOInterface* mockPresenceGPIO = 990 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 991 // Always return 1 to indicate present. 992 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 993 psu.analyze(); 994 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 995 EXPECT_EQ(psu.hasPgoodFault(), false); 996 // STATUS_WORD 0x0000 is powered on, no faults. 997 PMBusExpectations expectations; 998 setPMBusExpectations(mockPMBus, expectations); 999 psu.analyze(); 1000 EXPECT_EQ(psu.hasPgoodFault(), false); 1001 // Turn PGOOD# off (fault on). 1002 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED); 1003 setPMBusExpectations(mockPMBus, expectations); 1004 psu.analyze(); 1005 EXPECT_EQ(psu.hasPgoodFault(), true); 1006 // Back to no fault bits on in STATUS_WORD 1007 expectations.statusWordValue = 0; 1008 setPMBusExpectations(mockPMBus, expectations); 1009 psu.analyze(); 1010 EXPECT_EQ(psu.hasPgoodFault(), false); 1011 // Turn OFF bit on 1012 expectations.statusWordValue = (status_word::UNIT_IS_OFF); 1013 setPMBusExpectations(mockPMBus, expectations); 1014 psu.analyze(); 1015 EXPECT_EQ(psu.hasPgoodFault(), true); 1016 // Back to no fault bits on in STATUS_WORD 1017 expectations.statusWordValue = 0; 1018 setPMBusExpectations(mockPMBus, expectations); 1019 psu.analyze(); 1020 EXPECT_EQ(psu.hasPgoodFault(), false); 1021 } 1022