13f1242f3SBrandon Wyman #include "../power_supply.hpp" 23f1242f3SBrandon Wyman #include "mock.hpp" 33f1242f3SBrandon Wyman 43f1242f3SBrandon Wyman #include <xyz/openbmc_project/Common/Device/error.hpp> 53f1242f3SBrandon Wyman #include <xyz/openbmc_project/Common/error.hpp> 63f1242f3SBrandon Wyman 73f1242f3SBrandon Wyman #include <gmock/gmock.h> 83f1242f3SBrandon Wyman #include <gtest/gtest.h> 93f1242f3SBrandon Wyman 103f1242f3SBrandon Wyman using namespace phosphor::power::psu; 113f1242f3SBrandon Wyman using namespace phosphor::pmbus; 123f1242f3SBrandon Wyman 133f1242f3SBrandon Wyman using ::testing::_; 1459a35793SBrandon Wyman using ::testing::Args; 153f1242f3SBrandon Wyman using ::testing::Assign; 163f1242f3SBrandon Wyman using ::testing::DoAll; 1759a35793SBrandon Wyman using ::testing::ElementsAre; 1859a35793SBrandon Wyman using ::testing::NotNull; 193f1242f3SBrandon Wyman using ::testing::Return; 203f1242f3SBrandon Wyman using ::testing::StrEq; 213f1242f3SBrandon Wyman 223f1242f3SBrandon Wyman static auto PSUInventoryPath = "/xyz/bmc/inv/sys/chassis/board/powersupply0"; 23681b2a36SB. J. Wyman static auto PSUGPIOLineName = "presence-ps0"; 243f1242f3SBrandon Wyman 25b654c619SBrandon Wyman struct PMBusExpectations 26b654c619SBrandon Wyman { 27b654c619SBrandon Wyman uint16_t statusWordValue{0x0000}; 28b654c619SBrandon Wyman uint8_t statusInputValue{0x00}; 29b654c619SBrandon Wyman uint8_t statusMFRValue{0x00}; 30b654c619SBrandon Wyman uint8_t statusCMLValue{0x00}; 31b654c619SBrandon Wyman uint8_t statusVOUTValue{0x00}; 32*b10b3be0SBrandon Wyman uint8_t statusIOUTValue{0x00}; 3396893a46SBrandon Wyman uint8_t statusTempValue{0x00}; 34b654c619SBrandon Wyman }; 35b654c619SBrandon Wyman 368da35c51SBrandon Wyman // Helper function to setup expectations for various STATUS_* commands 37b654c619SBrandon Wyman void setPMBusExpectations(MockedPMBus& mockPMBus, 38b654c619SBrandon Wyman const PMBusExpectations& expectations) 398da35c51SBrandon Wyman { 408da35c51SBrandon Wyman EXPECT_CALL(mockPMBus, read(STATUS_WORD, _)) 418da35c51SBrandon Wyman .Times(1) 42b654c619SBrandon Wyman .WillOnce(Return(expectations.statusWordValue)); 438da35c51SBrandon Wyman 44b654c619SBrandon Wyman if (expectations.statusWordValue != 0) 458da35c51SBrandon Wyman { 468da35c51SBrandon Wyman // If fault bits are on in STATUS_WORD, there will also be a read of 4796893a46SBrandon Wyman // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and 4896893a46SBrandon Wyman // STATUS_TEMPERATURE. 498da35c51SBrandon Wyman EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _)) 508da35c51SBrandon Wyman .Times(1) 51b654c619SBrandon Wyman .WillOnce(Return(expectations.statusInputValue)); 528da35c51SBrandon Wyman EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)) 538da35c51SBrandon Wyman .Times(1) 54b654c619SBrandon Wyman .WillOnce(Return(expectations.statusMFRValue)); 558da35c51SBrandon Wyman EXPECT_CALL(mockPMBus, read(STATUS_CML, _)) 568da35c51SBrandon Wyman .Times(1) 57b654c619SBrandon Wyman .WillOnce(Return(expectations.statusCMLValue)); 586710ba2cSBrandon Wyman // Page will need to be set to 0 to read STATUS_VOUT. 596710ba2cSBrandon Wyman EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0)) 606710ba2cSBrandon Wyman .Times(1) 616710ba2cSBrandon Wyman .WillOnce(Return("status0_vout")); 626710ba2cSBrandon Wyman EXPECT_CALL(mockPMBus, read("status0_vout", _)) 636710ba2cSBrandon Wyman .Times(1) 64b654c619SBrandon Wyman .WillOnce(Return(expectations.statusVOUTValue)); 65*b10b3be0SBrandon Wyman EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _)) 66*b10b3be0SBrandon Wyman .Times(1) 67*b10b3be0SBrandon Wyman .WillOnce(Return(expectations.statusIOUTValue)); 6896893a46SBrandon Wyman EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _)) 6996893a46SBrandon Wyman .Times(1) 7096893a46SBrandon Wyman .WillOnce(Return(expectations.statusTempValue)); 718da35c51SBrandon Wyman } 728da35c51SBrandon Wyman } 738da35c51SBrandon Wyman 743f1242f3SBrandon Wyman class PowerSupplyTests : public ::testing::Test 753f1242f3SBrandon Wyman { 763f1242f3SBrandon Wyman public: 773f1242f3SBrandon Wyman PowerSupplyTests() : 783f1242f3SBrandon Wyman mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils())) 793f1242f3SBrandon Wyman { 803f1242f3SBrandon Wyman ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false)); 813f1242f3SBrandon Wyman } 823f1242f3SBrandon Wyman 833f1242f3SBrandon Wyman ~PowerSupplyTests() override 843f1242f3SBrandon Wyman { 853f1242f3SBrandon Wyman freeUtils(); 863f1242f3SBrandon Wyman } 873f1242f3SBrandon Wyman 883f1242f3SBrandon Wyman const MockedUtil& mockedUtil; 893f1242f3SBrandon Wyman }; 903f1242f3SBrandon Wyman 913f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Constructor) 923f1242f3SBrandon Wyman { 933f1242f3SBrandon Wyman /** 943f1242f3SBrandon Wyman * @param[in] invpath - String for inventory path to use 953f1242f3SBrandon Wyman * @param[in] i2cbus - The bus number this power supply is on 963f1242f3SBrandon Wyman * @param[in] i2caddr - The 16-bit I2C address of the power supply 97681b2a36SB. J. Wyman * @param[in] gpioLineName - The string for the gpio-line-name to read for 98681b2a36SB. J. Wyman * presence. 99681b2a36SB. J. Wyman * @param[in] bindDelay - Time in milliseconds to delay binding the device 100681b2a36SB. J. Wyman * driver after seeing the presence line go active. 1013f1242f3SBrandon Wyman */ 1023f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 1031d7a7df8SBrandon Wyman 1041d7a7df8SBrandon Wyman // Try where inventory path is empty, constructor should fail. 1051d7a7df8SBrandon Wyman try 1061d7a7df8SBrandon Wyman { 107681b2a36SB. J. Wyman auto psu = 108681b2a36SB. J. Wyman std::make_unique<PowerSupply>(bus, "", 3, 0x68, PSUGPIOLineName); 1091d7a7df8SBrandon Wyman ADD_FAILURE() << "Should not have reached this line."; 1101d7a7df8SBrandon Wyman } 1111d7a7df8SBrandon Wyman catch (const std::invalid_argument& e) 1121d7a7df8SBrandon Wyman { 1131d7a7df8SBrandon Wyman EXPECT_STREQ(e.what(), "Invalid empty inventoryPath"); 1141d7a7df8SBrandon Wyman } 1151d7a7df8SBrandon Wyman catch (...) 1161d7a7df8SBrandon Wyman { 1171d7a7df8SBrandon Wyman ADD_FAILURE() << "Should not have caught exception."; 1181d7a7df8SBrandon Wyman } 1191d7a7df8SBrandon Wyman 120681b2a36SB. J. Wyman // TODO: Try invalid i2c address? 121681b2a36SB. J. Wyman 122681b2a36SB. J. Wyman // Try where gpioLineName is empty. 1231d7a7df8SBrandon Wyman try 1241d7a7df8SBrandon Wyman { 1251d7a7df8SBrandon Wyman auto psu = 126681b2a36SB. J. Wyman std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, ""); 127681b2a36SB. J. Wyman ADD_FAILURE() 128681b2a36SB. J. Wyman << "Should not have reached this line. Invalid gpioLineName."; 129681b2a36SB. J. Wyman } 130681b2a36SB. J. Wyman catch (const std::invalid_argument& e) 131681b2a36SB. J. Wyman { 132681b2a36SB. J. Wyman EXPECT_STREQ(e.what(), "Invalid empty gpioLineName"); 133681b2a36SB. J. Wyman } 134681b2a36SB. J. Wyman catch (...) 135681b2a36SB. J. Wyman { 136681b2a36SB. J. Wyman ADD_FAILURE() << "Should not have caught exception."; 137681b2a36SB. J. Wyman } 138681b2a36SB. J. Wyman 139681b2a36SB. J. Wyman // Test with valid arguments 140681b2a36SB. J. Wyman // NOT using D-Bus inventory path for presence. 141681b2a36SB. J. Wyman try 142681b2a36SB. J. Wyman { 143681b2a36SB. J. Wyman auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, 144681b2a36SB. J. Wyman PSUGPIOLineName); 1453f1242f3SBrandon Wyman 1463f1242f3SBrandon Wyman EXPECT_EQ(psu->isPresent(), false); 1473f1242f3SBrandon Wyman EXPECT_EQ(psu->isFaulted(), false); 1488da35c51SBrandon Wyman EXPECT_EQ(psu->hasCommFault(), false); 1493f1242f3SBrandon Wyman EXPECT_EQ(psu->hasInputFault(), false); 1503f1242f3SBrandon Wyman EXPECT_EQ(psu->hasMFRFault(), false); 1513f1242f3SBrandon Wyman EXPECT_EQ(psu->hasVINUVFault(), false); 1526710ba2cSBrandon Wyman EXPECT_EQ(psu->hasVoutOVFault(), false); 153*b10b3be0SBrandon Wyman EXPECT_EQ(psu->hasIoutOCFault(), false); 15496893a46SBrandon Wyman EXPECT_EQ(psu->hasTempFault(), false); 1552916ea52SBrandon Wyman EXPECT_EQ(psu->hasPgoodFault(), false); 1563f1242f3SBrandon Wyman } 1571d7a7df8SBrandon Wyman catch (...) 1581d7a7df8SBrandon Wyman { 1591d7a7df8SBrandon Wyman ADD_FAILURE() << "Should not have caught exception."; 1601d7a7df8SBrandon Wyman } 161681b2a36SB. J. Wyman 162681b2a36SB. J. Wyman // Test with valid arguments 163681b2a36SB. J. Wyman // TODO: Using D-Bus inventory path for presence. 164681b2a36SB. J. Wyman try 165681b2a36SB. J. Wyman { 166681b2a36SB. J. Wyman // FIXME: How do I get that presenceGPIO.read() in the startup to throw 167681b2a36SB. J. Wyman // an exception? 168681b2a36SB. J. Wyman 169681b2a36SB. J. Wyman // EXPECT_CALL(mockedUtil, getPresence(_, 170681b2a36SB. J. Wyman // StrEq(PSUInventoryPath))) 171681b2a36SB. J. Wyman // .Times(1); 172681b2a36SB. J. Wyman } 173681b2a36SB. J. Wyman catch (...) 174681b2a36SB. J. Wyman { 175681b2a36SB. J. Wyman ADD_FAILURE() << "Should not have caught exception."; 176681b2a36SB. J. Wyman } 1771d7a7df8SBrandon Wyman } 1783f1242f3SBrandon Wyman 1793f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Analyze) 1803f1242f3SBrandon Wyman { 1813f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 1823f1242f3SBrandon Wyman 183b654c619SBrandon Wyman { 184681b2a36SB. J. Wyman // If I default to reading the GPIO, I will NOT expect a call to 185681b2a36SB. J. Wyman // getPresence(). 186681b2a36SB. J. Wyman 187681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName}; 1883ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 1893ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 190681b2a36SB. J. Wyman EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0)); 191681b2a36SB. J. Wyman 1923f1242f3SBrandon Wyman psu.analyze(); 1933f1242f3SBrandon Wyman // By default, nothing should change. 1943f1242f3SBrandon Wyman EXPECT_EQ(psu.isPresent(), false); 1953f1242f3SBrandon Wyman EXPECT_EQ(psu.isFaulted(), false); 1963f1242f3SBrandon Wyman EXPECT_EQ(psu.hasInputFault(), false); 1973f1242f3SBrandon Wyman EXPECT_EQ(psu.hasMFRFault(), false); 1983f1242f3SBrandon Wyman EXPECT_EQ(psu.hasVINUVFault(), false); 19985c7bf41SBrandon Wyman EXPECT_EQ(psu.hasCommFault(), false); 2006710ba2cSBrandon Wyman EXPECT_EQ(psu.hasVoutOVFault(), false); 201*b10b3be0SBrandon Wyman EXPECT_EQ(psu.hasIoutOCFault(), false); 20296893a46SBrandon Wyman EXPECT_EQ(psu.hasTempFault(), false); 2032916ea52SBrandon Wyman EXPECT_EQ(psu.hasPgoodFault(), false); 204b654c619SBrandon Wyman } 2053f1242f3SBrandon Wyman 206681b2a36SB. J. Wyman PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName}; 207681b2a36SB. J. Wyman // In order to get the various faults tested, the power supply needs to 208681b2a36SB. J. Wyman // be present in order to read from the PMBus device(s). 2093ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO2 = 2103ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO()); 211681b2a36SB. J. Wyman ON_CALL(*mockPresenceGPIO2, read()).WillByDefault(Return(1)); 212681b2a36SB. J. Wyman EXPECT_EQ(psu2.isPresent(), false); 2133f1242f3SBrandon Wyman 2143f1242f3SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus()); 2158da35c51SBrandon Wyman // Presence change from missing to present will trigger write to 2168da35c51SBrandon Wyman // ON_OFF_CONFIG. 2178da35c51SBrandon Wyman EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, _, _)); 218b654c619SBrandon Wyman // Presence change from missing to present will trigger in1_input read 219b654c619SBrandon Wyman // in an attempt to get CLEAR_FAULTS called. 220f07bc797SBrandon Wyman EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000)); 221b654c619SBrandon Wyman 222b654c619SBrandon Wyman // STATUS_WORD INPUT fault. 223b654c619SBrandon Wyman { 224b654c619SBrandon Wyman // Start with STATUS_WORD 0x0000. Powered on, no faults. 225b654c619SBrandon Wyman // Set expectations for a no fault 226b654c619SBrandon Wyman PMBusExpectations expectations; 227b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 2283f1242f3SBrandon Wyman psu2.analyze(); 2293f1242f3SBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 2303f1242f3SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), false); 2313f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), false); 2323f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), false); 2333f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), false); 23485c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), false); 2356710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), false); 236*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasIoutOCFault(), false); 23796893a46SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), false); 2382916ea52SBrandon Wyman EXPECT_EQ(psu2.hasPgoodFault(), false); 2393f1242f3SBrandon Wyman 240b654c619SBrandon Wyman // Update expectations for STATUS_WORD input fault/warn 24196893a46SBrandon Wyman // STATUS_INPUT fault bits ... on. 242b654c619SBrandon Wyman expectations.statusWordValue = (status_word::INPUT_FAULT_WARN); 243b654c619SBrandon Wyman expectations.statusInputValue = 0x38; 244b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 2453f1242f3SBrandon Wyman psu2.analyze(); 2463f1242f3SBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 2473f1242f3SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), true); 2483f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), true); 2493f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), false); 2503f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), false); 25185c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), false); 2526710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), false); 253*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasIoutOCFault(), false); 25496893a46SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), false); 2552916ea52SBrandon Wyman EXPECT_EQ(psu2.hasPgoodFault(), false); 256b654c619SBrandon Wyman } 2573f1242f3SBrandon Wyman 2583f1242f3SBrandon Wyman // STATUS_WORD INPUT/UV fault. 259b654c619SBrandon Wyman { 2603f1242f3SBrandon Wyman // First need it to return good status, then the fault 261b654c619SBrandon Wyman PMBusExpectations expectations; 262b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 2633f1242f3SBrandon Wyman psu2.analyze(); 2648da35c51SBrandon Wyman // Now set fault bits in STATUS_WORD 265b654c619SBrandon Wyman expectations.statusWordValue = 2668da35c51SBrandon Wyman (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT); 2678da35c51SBrandon Wyman // STATUS_INPUT fault bits ... on. 268b654c619SBrandon Wyman expectations.statusInputValue = 0x38; 269b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 2703f1242f3SBrandon Wyman psu2.analyze(); 2713f1242f3SBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 2723f1242f3SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), true); 273f07bc797SBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), true); 2743f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), false); 2753f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), true); 27685c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), false); 2776710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), false); 278*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasIoutOCFault(), false); 27996893a46SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), false); 2802916ea52SBrandon Wyman EXPECT_EQ(psu2.hasPgoodFault(), false); 281b654c619SBrandon Wyman } 2823f1242f3SBrandon Wyman 2833f1242f3SBrandon Wyman // STATUS_WORD MFR fault. 284b654c619SBrandon Wyman { 285f07bc797SBrandon Wyman // First need it to return good status, then the fault 286b654c619SBrandon Wyman PMBusExpectations expectations; 287b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 2883f1242f3SBrandon Wyman psu2.analyze(); 2898da35c51SBrandon Wyman // Now STATUS_WORD with MFR fault bit on. 290b654c619SBrandon Wyman expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 2918da35c51SBrandon Wyman // STATUS_MFR bits on. 292b654c619SBrandon Wyman expectations.statusMFRValue = 0xFF; 293b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 2943f1242f3SBrandon Wyman psu2.analyze(); 2953f1242f3SBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 2963f1242f3SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), true); 2973f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), false); 2983f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), true); 2993f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), false); 30085c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), false); 3016710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), false); 302*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasIoutOCFault(), false); 30396893a46SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), false); 3042916ea52SBrandon Wyman EXPECT_EQ(psu2.hasPgoodFault(), false); 305b654c619SBrandon Wyman } 3063f1242f3SBrandon Wyman 30796893a46SBrandon Wyman // Temperature fault. 308b654c619SBrandon Wyman { 309f07bc797SBrandon Wyman // First STATUS_WORD with no bits set, then with temperature fault. 310b654c619SBrandon Wyman PMBusExpectations expectations; 311b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 3123f1242f3SBrandon Wyman psu2.analyze(); 3138da35c51SBrandon Wyman // STATUS_WORD with temperature fault bit on. 314b654c619SBrandon Wyman expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN); 31596893a46SBrandon Wyman // STATUS_TEMPERATURE with fault bit(s) on. 31696893a46SBrandon Wyman expectations.statusTempValue = 0x10; 317b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 3183f1242f3SBrandon Wyman psu2.analyze(); 3193f1242f3SBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 32096893a46SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), true); 3213f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), false); 3223f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), false); 3233f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), false); 32485c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), false); 3256710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), false); 326*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasIoutOCFault(), false); 32796893a46SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), true); 3282916ea52SBrandon Wyman EXPECT_EQ(psu2.hasPgoodFault(), false); 329b654c619SBrandon Wyman } 33085c7bf41SBrandon Wyman 33185c7bf41SBrandon Wyman // CML fault 332b654c619SBrandon Wyman { 33385c7bf41SBrandon Wyman // First STATUS_WORD wit no bits set, then with CML fault. 334b654c619SBrandon Wyman PMBusExpectations expectations; 335b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 33685c7bf41SBrandon Wyman psu2.analyze(); 3378da35c51SBrandon Wyman // STATUS_WORD with CML fault bit on. 338b654c619SBrandon Wyman expectations.statusWordValue = (status_word::CML_FAULT); 33985c7bf41SBrandon Wyman // Turn on STATUS_CML fault bit(s) 340b654c619SBrandon Wyman expectations.statusCMLValue = 0xFF; 341b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 34285c7bf41SBrandon Wyman psu2.analyze(); 34385c7bf41SBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 34485c7bf41SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), true); 34585c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), false); 34685c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), false); 34785c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), false); 34885c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), true); 3496710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), false); 350*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasIoutOCFault(), false); 35196893a46SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), false); 3522916ea52SBrandon Wyman EXPECT_EQ(psu2.hasPgoodFault(), false); 353b654c619SBrandon Wyman } 3546710ba2cSBrandon Wyman 3556710ba2cSBrandon Wyman // VOUT_OV_FAULT fault 356b654c619SBrandon Wyman { 3576710ba2cSBrandon Wyman // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault. 358b654c619SBrandon Wyman PMBusExpectations expectations; 359b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 3606710ba2cSBrandon Wyman psu2.analyze(); 3616710ba2cSBrandon Wyman // STATUS_WORD with VOUT/VOUT_OV fault. 362b654c619SBrandon Wyman expectations.statusWordValue = 3636710ba2cSBrandon Wyman ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT)); 3646710ba2cSBrandon Wyman // Turn on STATUS_VOUT fault bit(s) 365b654c619SBrandon Wyman expectations.statusVOUTValue = 0xA0; 36696893a46SBrandon Wyman // STATUS_TEMPERATURE don't care (default) 367b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 3686710ba2cSBrandon Wyman psu2.analyze(); 3696710ba2cSBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 3706710ba2cSBrandon Wyman EXPECT_EQ(psu2.isFaulted(), true); 3716710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), false); 3726710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), false); 3736710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), false); 3746710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), false); 3756710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), true); 376*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasIoutOCFault(), false); 377*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), false); 378*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasPgoodFault(), false); 379*b10b3be0SBrandon Wyman } 380*b10b3be0SBrandon Wyman 381*b10b3be0SBrandon Wyman // IOUT_OC_FAULT fault 382*b10b3be0SBrandon Wyman { 383*b10b3be0SBrandon Wyman // First STATUS_WORD with no bits set, then with IOUT_OC fault. 384*b10b3be0SBrandon Wyman PMBusExpectations expectations; 385*b10b3be0SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 386*b10b3be0SBrandon Wyman psu2.analyze(); 387*b10b3be0SBrandon Wyman // STATUS_WORD with IOUT_OC fault. 388*b10b3be0SBrandon Wyman expectations.statusWordValue = status_word::IOUT_OC_FAULT; 389*b10b3be0SBrandon Wyman // Turn on STATUS_IOUT fault bit(s) 390*b10b3be0SBrandon Wyman expectations.statusIOUTValue = 0x88; 391*b10b3be0SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 392*b10b3be0SBrandon Wyman psu2.analyze(); 393*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 394*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), true); 395*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), false); 396*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), false); 397*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), false); 398*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), false); 399*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), false); 400*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasIoutOCFault(), true); 40196893a46SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), false); 4022916ea52SBrandon Wyman EXPECT_EQ(psu2.hasPgoodFault(), false); 403b654c619SBrandon Wyman } 4043f1242f3SBrandon Wyman 4053f1242f3SBrandon Wyman // Ignore fan fault 406b654c619SBrandon Wyman { 407b654c619SBrandon Wyman // First STATUS_WORD with no bits set, then with fan fault. 408b654c619SBrandon Wyman PMBusExpectations expectations; 409b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 4103f1242f3SBrandon Wyman psu2.analyze(); 411b654c619SBrandon Wyman expectations.statusWordValue = (status_word::FAN_FAULT); 412b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 4133f1242f3SBrandon Wyman psu2.analyze(); 4143f1242f3SBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 4153f1242f3SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), false); 4163f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), false); 4173f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), false); 4183f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), false); 41985c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), false); 4206710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), false); 421*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasIoutOCFault(), false); 42296893a46SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), false); 4232916ea52SBrandon Wyman EXPECT_EQ(psu2.hasPgoodFault(), false); 424b654c619SBrandon Wyman } 4252916ea52SBrandon Wyman 4262916ea52SBrandon Wyman { 4272916ea52SBrandon Wyman // PGOOD/OFF fault. 4282916ea52SBrandon Wyman // First STATUS_WORD with no bits set. 4292916ea52SBrandon Wyman PMBusExpectations expectations; 4302916ea52SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 4312916ea52SBrandon Wyman psu2.analyze(); 4322916ea52SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), false); 4332916ea52SBrandon Wyman // POWER_GOOD# inactive, and OFF bit on. 4342916ea52SBrandon Wyman expectations.statusWordValue = 4352916ea52SBrandon Wyman ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF)); 4362916ea52SBrandon Wyman // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and 4372916ea52SBrandon Wyman // STATUS_TEMPERATURE: Don't care if bits set or not (defaults). 4382916ea52SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 4392916ea52SBrandon Wyman psu2.analyze(); 4402916ea52SBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 4412916ea52SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), true); 4422916ea52SBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), false); 4432916ea52SBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), false); 4442916ea52SBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), false); 4452916ea52SBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), false); 4462916ea52SBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), false); 447*b10b3be0SBrandon Wyman EXPECT_EQ(psu2.hasIoutOCFault(), false); 4482916ea52SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), false); 4492916ea52SBrandon Wyman EXPECT_EQ(psu2.hasPgoodFault(), true); 4502916ea52SBrandon Wyman } 4512916ea52SBrandon Wyman 4523f1242f3SBrandon Wyman // TODO: ReadFailure 4533f1242f3SBrandon Wyman } 4543f1242f3SBrandon Wyman 45559a35793SBrandon Wyman TEST_F(PowerSupplyTests, OnOffConfig) 45659a35793SBrandon Wyman { 45759a35793SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 45859a35793SBrandon Wyman uint8_t data = 0x15; 45959a35793SBrandon Wyman 46059a35793SBrandon Wyman // Test where PSU is NOT present 46159a35793SBrandon Wyman try 46259a35793SBrandon Wyman { 463681b2a36SB. J. Wyman // Assume GPIO presence, not inventory presence? 464681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName}; 465681b2a36SB. J. Wyman 4663ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 4673ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 468681b2a36SB. J. Wyman ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0)); 46959a35793SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 470681b2a36SB. J. Wyman // Constructor should set initial presence, default read returns 0. 47159a35793SBrandon Wyman // If it is not present, I should not be trying to write to it. 47259a35793SBrandon Wyman EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0); 47359a35793SBrandon Wyman psu.onOffConfig(data); 47459a35793SBrandon Wyman } 47559a35793SBrandon Wyman catch (...) 4760c9a33d6SAdriana Kobylak {} 47759a35793SBrandon Wyman 47859a35793SBrandon Wyman // Test where PSU is present 47959a35793SBrandon Wyman try 48059a35793SBrandon Wyman { 481681b2a36SB. J. Wyman // Assume GPIO presence, not inventory presence? 482681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName}; 4833ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 4843ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 485681b2a36SB. J. Wyman ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1)); 48659a35793SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 487681b2a36SB. J. Wyman // TODO: expect setPresence call? 488681b2a36SB. J. Wyman // updatePresence() private function reads gpio, called by analyze(). 489681b2a36SB. J. Wyman psu.analyze(); 49059a35793SBrandon Wyman // TODO: ???should I check the filename? 49159a35793SBrandon Wyman EXPECT_CALL(mockPMBus, 49259a35793SBrandon Wyman writeBinary(_, ElementsAre(0x15), Type::HwmonDeviceDebug)) 49359a35793SBrandon Wyman .Times(1); 49459a35793SBrandon Wyman psu.onOffConfig(data); 49559a35793SBrandon Wyman } 49659a35793SBrandon Wyman catch (...) 4970c9a33d6SAdriana Kobylak {} 49859a35793SBrandon Wyman } 49959a35793SBrandon Wyman 5003f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, ClearFaults) 5013f1242f3SBrandon Wyman { 5023f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 503681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName}; 5043ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 5053ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 506681b2a36SB. J. Wyman // GPIO read return 1 to indicate present. 507681b2a36SB. J. Wyman ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1)); 508681b2a36SB. J. Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 5098da35c51SBrandon Wyman // Presence change from missing to present will trigger in1_input read in 5108da35c51SBrandon Wyman // an attempt to get CLEAR_FAULTS called. 5118da35c51SBrandon Wyman EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000)); 5128da35c51SBrandon Wyman // STATUS_WORD 0x0000 is powered on, no faults. 513b654c619SBrandon Wyman PMBusExpectations expectations; 514b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 515681b2a36SB. J. Wyman psu.analyze(); 5163f1242f3SBrandon Wyman EXPECT_EQ(psu.isPresent(), true); 5173f1242f3SBrandon Wyman EXPECT_EQ(psu.isFaulted(), false); 5183f1242f3SBrandon Wyman EXPECT_EQ(psu.hasInputFault(), false); 5193f1242f3SBrandon Wyman EXPECT_EQ(psu.hasMFRFault(), false); 5203f1242f3SBrandon Wyman EXPECT_EQ(psu.hasVINUVFault(), false); 52185c7bf41SBrandon Wyman EXPECT_EQ(psu.hasCommFault(), false); 5226710ba2cSBrandon Wyman EXPECT_EQ(psu.hasVoutOVFault(), false); 523*b10b3be0SBrandon Wyman EXPECT_EQ(psu.hasIoutOCFault(), false); 52496893a46SBrandon Wyman EXPECT_EQ(psu.hasTempFault(), false); 5252916ea52SBrandon Wyman EXPECT_EQ(psu.hasPgoodFault(), false); 526b654c619SBrandon Wyman 527f07bc797SBrandon Wyman // STATUS_WORD with fault bits galore! 528b654c619SBrandon Wyman expectations.statusWordValue = 0xFFFF; 529f07bc797SBrandon Wyman // STATUS_INPUT with fault bits on. 530b654c619SBrandon Wyman expectations.statusInputValue = 0xFF; 531f07bc797SBrandon Wyman // STATUS_MFR_SPEFIC with bits on. 532b654c619SBrandon Wyman expectations.statusMFRValue = 0xFF; 53385c7bf41SBrandon Wyman // STATUS_CML with bits on. 534b654c619SBrandon Wyman expectations.statusCMLValue = 0xFF; 5356710ba2cSBrandon Wyman // STATUS_VOUT with bits on. 536b654c619SBrandon Wyman expectations.statusVOUTValue = 0xFF; 537*b10b3be0SBrandon Wyman // STATUS_IOUT with bits on. 538*b10b3be0SBrandon Wyman expectations.statusIOUTValue = 0xFF; 53996893a46SBrandon Wyman // STATUS_TEMPERATURE with bits on. 54096893a46SBrandon Wyman expectations.statusTempValue = 0xFF; 541b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 5423f1242f3SBrandon Wyman psu.analyze(); 5433f1242f3SBrandon Wyman EXPECT_EQ(psu.isPresent(), true); 5443f1242f3SBrandon Wyman EXPECT_EQ(psu.isFaulted(), true); 5453f1242f3SBrandon Wyman EXPECT_EQ(psu.hasInputFault(), true); 5463f1242f3SBrandon Wyman EXPECT_EQ(psu.hasMFRFault(), true); 5473f1242f3SBrandon Wyman EXPECT_EQ(psu.hasVINUVFault(), true); 54885c7bf41SBrandon Wyman EXPECT_EQ(psu.hasCommFault(), true); 5496710ba2cSBrandon Wyman EXPECT_EQ(psu.hasVoutOVFault(), true); 550*b10b3be0SBrandon Wyman EXPECT_EQ(psu.hasIoutOCFault(), true); 55196893a46SBrandon Wyman EXPECT_EQ(psu.hasTempFault(), true); 5522916ea52SBrandon Wyman EXPECT_EQ(psu.hasPgoodFault(), true); 5533c208464SBrandon Wyman EXPECT_CALL(mockPMBus, read("in1_input", _)) 5543c208464SBrandon Wyman .Times(1) 5553c208464SBrandon Wyman .WillOnce(Return(209000)); 5563f1242f3SBrandon Wyman psu.clearFaults(); 5573f1242f3SBrandon Wyman EXPECT_EQ(psu.isPresent(), true); 5583f1242f3SBrandon Wyman EXPECT_EQ(psu.isFaulted(), false); 5593f1242f3SBrandon Wyman EXPECT_EQ(psu.hasInputFault(), false); 5603f1242f3SBrandon Wyman EXPECT_EQ(psu.hasMFRFault(), false); 5613f1242f3SBrandon Wyman EXPECT_EQ(psu.hasVINUVFault(), false); 56285c7bf41SBrandon Wyman EXPECT_EQ(psu.hasCommFault(), false); 5636710ba2cSBrandon Wyman EXPECT_EQ(psu.hasVoutOVFault(), false); 564*b10b3be0SBrandon Wyman EXPECT_EQ(psu.hasIoutOCFault(), false); 56596893a46SBrandon Wyman EXPECT_EQ(psu.hasTempFault(), false); 5662916ea52SBrandon Wyman EXPECT_EQ(psu.hasPgoodFault(), false); 567681b2a36SB. J. Wyman 568681b2a36SB. J. Wyman // TODO: Faults clear on missing/present? 5693f1242f3SBrandon Wyman } 5703f1242f3SBrandon Wyman 5713f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, UpdateInventory) 5723f1242f3SBrandon Wyman { 5733f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 5741d7a7df8SBrandon Wyman 5751d7a7df8SBrandon Wyman try 5761d7a7df8SBrandon Wyman { 577681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 5781d7a7df8SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 5791d7a7df8SBrandon Wyman // If it is not present, I should not be trying to read a string 5801d7a7df8SBrandon Wyman EXPECT_CALL(mockPMBus, readString(_, _)).Times(0); 5811d7a7df8SBrandon Wyman psu.updateInventory(); 5821d7a7df8SBrandon Wyman } 5831d7a7df8SBrandon Wyman catch (...) 5841d7a7df8SBrandon Wyman { 5851d7a7df8SBrandon Wyman ADD_FAILURE() << "Should not have caught exception."; 5861d7a7df8SBrandon Wyman } 5871d7a7df8SBrandon Wyman 5881d7a7df8SBrandon Wyman try 5891d7a7df8SBrandon Wyman { 590681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName}; 5913ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 5923ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 593681b2a36SB. J. Wyman // GPIO read return 1 to indicate present. 594681b2a36SB. J. Wyman EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1)); 595681b2a36SB. J. Wyman psu.analyze(); 5961d7a7df8SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 5971d7a7df8SBrandon Wyman EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return("")); 5983f1242f3SBrandon Wyman psu.updateInventory(); 5991d7a7df8SBrandon Wyman 6003c530fbdSBrandon Wyman #if IBM_VPD 6011d7a7df8SBrandon Wyman EXPECT_CALL(mockPMBus, readString(_, _)) 6021d7a7df8SBrandon Wyman .WillOnce(Return("CCIN")) 6031d7a7df8SBrandon Wyman .WillOnce(Return("PN3456")) 6041d7a7df8SBrandon Wyman .WillOnce(Return("FN3456")) 6051d7a7df8SBrandon Wyman .WillOnce(Return("HEADER")) 6061d7a7df8SBrandon Wyman .WillOnce(Return("SN3456")) 6071d7a7df8SBrandon Wyman .WillOnce(Return("FW3456")); 6083c530fbdSBrandon Wyman #endif 6091d7a7df8SBrandon Wyman psu.updateInventory(); 6101d7a7df8SBrandon Wyman // TODO: D-Bus mocking to verify values stored on D-Bus (???) 6111d7a7df8SBrandon Wyman } 6121d7a7df8SBrandon Wyman catch (...) 6131d7a7df8SBrandon Wyman { 6141d7a7df8SBrandon Wyman ADD_FAILURE() << "Should not have caught exception."; 6151d7a7df8SBrandon Wyman } 6163f1242f3SBrandon Wyman } 6173f1242f3SBrandon Wyman 6183f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsPresent) 6193f1242f3SBrandon Wyman { 6203f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 621681b2a36SB. J. Wyman 622681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 6233ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 6243ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 6253f1242f3SBrandon Wyman EXPECT_EQ(psu.isPresent(), false); 6263f1242f3SBrandon Wyman 627681b2a36SB. J. Wyman // Change GPIO read to return 1 to indicate present. 628681b2a36SB. J. Wyman EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1)); 629681b2a36SB. J. Wyman psu.analyze(); 630681b2a36SB. J. Wyman EXPECT_EQ(psu.isPresent(), true); 6313f1242f3SBrandon Wyman } 6323f1242f3SBrandon Wyman 6333f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsFaulted) 6343f1242f3SBrandon Wyman { 6353f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 636681b2a36SB. J. Wyman 637681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName}; 6383ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 6393ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 640681b2a36SB. J. Wyman // Always return 1 to indicate present. 641681b2a36SB. J. Wyman EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 642681b2a36SB. J. Wyman psu.analyze(); 6433f1242f3SBrandon Wyman EXPECT_EQ(psu.isFaulted(), false); 6443f1242f3SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 645b654c619SBrandon Wyman PMBusExpectations expectations; 646f07bc797SBrandon Wyman // STATUS_WORD with fault bits on. 647b654c619SBrandon Wyman expectations.statusWordValue = 0xFFFF; 648f07bc797SBrandon Wyman // STATUS_INPUT with fault bits on. 649b654c619SBrandon Wyman expectations.statusInputValue = 0xFF; 650f07bc797SBrandon Wyman // STATUS_MFR_SPECIFIC with faults bits on. 651b654c619SBrandon Wyman expectations.statusMFRValue = 0xFF; 65285c7bf41SBrandon Wyman // STATUS_CML with faults bits on. 653b654c619SBrandon Wyman expectations.statusCMLValue = 0xFF; 6546710ba2cSBrandon Wyman // STATUS_VOUT with fault bits on. 655b654c619SBrandon Wyman expectations.statusVOUTValue = 0xFF; 656*b10b3be0SBrandon Wyman // STATUS_IOUT with fault bits on. 657*b10b3be0SBrandon Wyman expectations.statusIOUTValue = 0xFF; 65896893a46SBrandon Wyman // STATUS_TEMPERATURE with fault bits on. 65996893a46SBrandon Wyman expectations.statusTempValue = 0xFF; 660b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 6613f1242f3SBrandon Wyman psu.analyze(); 6623f1242f3SBrandon Wyman EXPECT_EQ(psu.isFaulted(), true); 6633f1242f3SBrandon Wyman } 6643f1242f3SBrandon Wyman 6653f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasInputFault) 6663f1242f3SBrandon Wyman { 6673f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 668681b2a36SB. J. Wyman 669681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 6703ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 6713ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 672681b2a36SB. J. Wyman // Always return 1 to indicate present. 673681b2a36SB. J. Wyman EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 674681b2a36SB. J. Wyman psu.analyze(); 6753f1242f3SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 6763f1242f3SBrandon Wyman EXPECT_EQ(psu.hasInputFault(), false); 6778da35c51SBrandon Wyman // STATUS_WORD 0x0000 is powered on, no faults. 678b654c619SBrandon Wyman PMBusExpectations expectations; 679b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 6803f1242f3SBrandon Wyman psu.analyze(); 6813f1242f3SBrandon Wyman EXPECT_EQ(psu.hasInputFault(), false); 682f07bc797SBrandon Wyman // STATUS_WORD with input fault/warn on. 683b654c619SBrandon Wyman expectations.statusWordValue = (status_word::INPUT_FAULT_WARN); 684f07bc797SBrandon Wyman // STATUS_INPUT with an input fault bit on. 685b654c619SBrandon Wyman expectations.statusInputValue = 0x80; 686b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 6873f1242f3SBrandon Wyman psu.analyze(); 6883f1242f3SBrandon Wyman EXPECT_EQ(psu.hasInputFault(), true); 689f07bc797SBrandon Wyman // STATUS_WORD with no bits on. 690b654c619SBrandon Wyman expectations.statusWordValue = 0; 691b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 6923f1242f3SBrandon Wyman psu.analyze(); 6933f1242f3SBrandon Wyman EXPECT_EQ(psu.hasInputFault(), false); 6943f1242f3SBrandon Wyman } 6953f1242f3SBrandon Wyman 6963f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasMFRFault) 6973f1242f3SBrandon Wyman { 6983f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 699681b2a36SB. J. Wyman 700681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 7013ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 7023ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 703681b2a36SB. J. Wyman // Always return 1 to indicate present. 704681b2a36SB. J. Wyman EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 705681b2a36SB. J. Wyman psu.analyze(); 7063f1242f3SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 7073f1242f3SBrandon Wyman EXPECT_EQ(psu.hasMFRFault(), false); 708f07bc797SBrandon Wyman // First return STATUS_WORD with no bits on. 7098da35c51SBrandon Wyman // STATUS_WORD 0x0000 is powered on, no faults. 710b654c619SBrandon Wyman PMBusExpectations expectations; 711b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 7123f1242f3SBrandon Wyman psu.analyze(); 7133f1242f3SBrandon Wyman EXPECT_EQ(psu.hasMFRFault(), false); 714f07bc797SBrandon Wyman // Next return STATUS_WORD with MFR fault bit on. 715b654c619SBrandon Wyman expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 716f07bc797SBrandon Wyman // STATUS_MFR_SPEFIC with bit(s) on. 717b654c619SBrandon Wyman expectations.statusMFRValue = 0xFF; 718b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 7193f1242f3SBrandon Wyman psu.analyze(); 7203f1242f3SBrandon Wyman EXPECT_EQ(psu.hasMFRFault(), true); 721f07bc797SBrandon Wyman // Back to no bits on in STATUS_WORD 722b654c619SBrandon Wyman expectations.statusWordValue = 0; 723b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 7243f1242f3SBrandon Wyman psu.analyze(); 7253f1242f3SBrandon Wyman EXPECT_EQ(psu.hasMFRFault(), false); 7263f1242f3SBrandon Wyman } 7273f1242f3SBrandon Wyman 7283f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasVINUVFault) 7293f1242f3SBrandon Wyman { 7303f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 731681b2a36SB. J. Wyman 732681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 7333ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 7343ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 735681b2a36SB. J. Wyman // Always return 1 to indicate present. 736681b2a36SB. J. Wyman EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 737681b2a36SB. J. Wyman psu.analyze(); 7383f1242f3SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 7393f1242f3SBrandon Wyman EXPECT_EQ(psu.hasVINUVFault(), false); 7408da35c51SBrandon Wyman // STATUS_WORD 0x0000 is powered on, no faults. 741b654c619SBrandon Wyman PMBusExpectations expectations; 742b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 7433f1242f3SBrandon Wyman psu.analyze(); 7443f1242f3SBrandon Wyman EXPECT_EQ(psu.hasVINUVFault(), false); 745f07bc797SBrandon Wyman // Turn fault on. 746b654c619SBrandon Wyman expectations.statusWordValue = (status_word::VIN_UV_FAULT); 74785c7bf41SBrandon Wyman // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by 74885c7bf41SBrandon Wyman // Figure 16, and assume bits on in STATUS_INPUT. 749b654c619SBrandon Wyman expectations.statusInputValue = 0x18; 750b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 7513f1242f3SBrandon Wyman psu.analyze(); 7523f1242f3SBrandon Wyman EXPECT_EQ(psu.hasVINUVFault(), true); 753f07bc797SBrandon Wyman // Back to no fault bits on in STATUS_WORD 754b654c619SBrandon Wyman expectations.statusWordValue = 0; 755b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 7563f1242f3SBrandon Wyman psu.analyze(); 7573f1242f3SBrandon Wyman EXPECT_EQ(psu.hasVINUVFault(), false); 7583f1242f3SBrandon Wyman } 7596710ba2cSBrandon Wyman 7606710ba2cSBrandon Wyman TEST_F(PowerSupplyTests, HasVoutOVFault) 7616710ba2cSBrandon Wyman { 7626710ba2cSBrandon Wyman auto bus = sdbusplus::bus::new_default(); 7636710ba2cSBrandon Wyman 7646710ba2cSBrandon Wyman PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName}; 7656710ba2cSBrandon Wyman MockedGPIOInterface* mockPresenceGPIO = 7666710ba2cSBrandon Wyman static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 7676710ba2cSBrandon Wyman // Always return 1 to indicate present. 7686710ba2cSBrandon Wyman EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 7696710ba2cSBrandon Wyman psu.analyze(); 7706710ba2cSBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 7716710ba2cSBrandon Wyman EXPECT_EQ(psu.hasVoutOVFault(), false); 7726710ba2cSBrandon Wyman // STATUS_WORD 0x0000 is powered on, no faults. 773b654c619SBrandon Wyman PMBusExpectations expectations; 774b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 7756710ba2cSBrandon Wyman psu.analyze(); 7766710ba2cSBrandon Wyman EXPECT_EQ(psu.hasVoutOVFault(), false); 7776710ba2cSBrandon Wyman // Turn fault on. 778b654c619SBrandon Wyman expectations.statusWordValue = (status_word::VOUT_OV_FAULT); 7796710ba2cSBrandon Wyman // STATUS_VOUT fault bit(s) 780b654c619SBrandon Wyman expectations.statusVOUTValue = 0x80; 78196893a46SBrandon Wyman // STATUS_TEMPERATURE default. 782b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 7836710ba2cSBrandon Wyman psu.analyze(); 7846710ba2cSBrandon Wyman EXPECT_EQ(psu.hasVoutOVFault(), true); 7856710ba2cSBrandon Wyman // Back to no fault bits on in STATUS_WORD 786b654c619SBrandon Wyman expectations.statusWordValue = 0; 787b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 7886710ba2cSBrandon Wyman psu.analyze(); 7896710ba2cSBrandon Wyman EXPECT_EQ(psu.hasVoutOVFault(), false); 7906710ba2cSBrandon Wyman } 79196893a46SBrandon Wyman 792*b10b3be0SBrandon Wyman TEST_F(PowerSupplyTests, HasIoutOCFault) 793*b10b3be0SBrandon Wyman { 794*b10b3be0SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 795*b10b3be0SBrandon Wyman 796*b10b3be0SBrandon Wyman PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName}; 797*b10b3be0SBrandon Wyman MockedGPIOInterface* mockPresenceGPIO = 798*b10b3be0SBrandon Wyman static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 799*b10b3be0SBrandon Wyman // Always return 1 to indicate present. 800*b10b3be0SBrandon Wyman EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 801*b10b3be0SBrandon Wyman psu.analyze(); 802*b10b3be0SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 803*b10b3be0SBrandon Wyman EXPECT_EQ(psu.hasIoutOCFault(), false); 804*b10b3be0SBrandon Wyman // STATUS_WORD 0x0000 is powered on, no faults. 805*b10b3be0SBrandon Wyman PMBusExpectations expectations; 806*b10b3be0SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 807*b10b3be0SBrandon Wyman psu.analyze(); 808*b10b3be0SBrandon Wyman EXPECT_EQ(psu.hasIoutOCFault(), false); 809*b10b3be0SBrandon Wyman // Turn fault on. 810*b10b3be0SBrandon Wyman expectations.statusWordValue = status_word::IOUT_OC_FAULT; 811*b10b3be0SBrandon Wyman // STATUS_IOUT fault bit(s) 812*b10b3be0SBrandon Wyman expectations.statusIOUTValue = 0x88; 813*b10b3be0SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 814*b10b3be0SBrandon Wyman psu.analyze(); 815*b10b3be0SBrandon Wyman EXPECT_EQ(psu.hasIoutOCFault(), true); 816*b10b3be0SBrandon Wyman // Back to no fault bits on in STATUS_WORD 817*b10b3be0SBrandon Wyman expectations.statusWordValue = 0; 818*b10b3be0SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 819*b10b3be0SBrandon Wyman psu.analyze(); 820*b10b3be0SBrandon Wyman EXPECT_EQ(psu.hasIoutOCFault(), false); 821*b10b3be0SBrandon Wyman } 822*b10b3be0SBrandon Wyman 82396893a46SBrandon Wyman TEST_F(PowerSupplyTests, HasTempFault) 82496893a46SBrandon Wyman { 82596893a46SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 82696893a46SBrandon Wyman 82796893a46SBrandon Wyman PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName}; 82896893a46SBrandon Wyman MockedGPIOInterface* mockPresenceGPIO = 82996893a46SBrandon Wyman static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 83096893a46SBrandon Wyman // Always return 1 to indicate present. 83196893a46SBrandon Wyman EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 83296893a46SBrandon Wyman psu.analyze(); 83396893a46SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 83496893a46SBrandon Wyman EXPECT_EQ(psu.hasTempFault(), false); 83596893a46SBrandon Wyman // STATUS_WORD 0x0000 is powered on, no faults. 83696893a46SBrandon Wyman PMBusExpectations expectations; 83796893a46SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 83896893a46SBrandon Wyman psu.analyze(); 83996893a46SBrandon Wyman EXPECT_EQ(psu.hasTempFault(), false); 84096893a46SBrandon Wyman // Turn fault on. 84196893a46SBrandon Wyman expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN); 84296893a46SBrandon Wyman // STATUS_TEMPERATURE fault bit on (OT Fault) 84396893a46SBrandon Wyman expectations.statusTempValue = 0x80; 84496893a46SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 84596893a46SBrandon Wyman psu.analyze(); 84696893a46SBrandon Wyman EXPECT_EQ(psu.hasTempFault(), true); 84796893a46SBrandon Wyman // Back to no fault bits on in STATUS_WORD 84896893a46SBrandon Wyman expectations.statusWordValue = 0; 84996893a46SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 85096893a46SBrandon Wyman psu.analyze(); 85196893a46SBrandon Wyman EXPECT_EQ(psu.hasTempFault(), false); 85296893a46SBrandon Wyman } 8532916ea52SBrandon Wyman 8542916ea52SBrandon Wyman TEST_F(PowerSupplyTests, HasPgoodFault) 8552916ea52SBrandon Wyman { 8562916ea52SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 8572916ea52SBrandon Wyman 8582916ea52SBrandon Wyman PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, PSUGPIOLineName}; 8592916ea52SBrandon Wyman MockedGPIOInterface* mockPresenceGPIO = 8602916ea52SBrandon Wyman static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 8612916ea52SBrandon Wyman // Always return 1 to indicate present. 8622916ea52SBrandon Wyman EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 8632916ea52SBrandon Wyman psu.analyze(); 8642916ea52SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 8652916ea52SBrandon Wyman EXPECT_EQ(psu.hasPgoodFault(), false); 8662916ea52SBrandon Wyman // STATUS_WORD 0x0000 is powered on, no faults. 8672916ea52SBrandon Wyman PMBusExpectations expectations; 8682916ea52SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 8692916ea52SBrandon Wyman psu.analyze(); 8702916ea52SBrandon Wyman EXPECT_EQ(psu.hasPgoodFault(), false); 8712916ea52SBrandon Wyman // Turn PGOOD# off (fault on). 8722916ea52SBrandon Wyman expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED); 8732916ea52SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 8742916ea52SBrandon Wyman psu.analyze(); 8752916ea52SBrandon Wyman EXPECT_EQ(psu.hasPgoodFault(), true); 8762916ea52SBrandon Wyman // Back to no fault bits on in STATUS_WORD 8772916ea52SBrandon Wyman expectations.statusWordValue = 0; 8782916ea52SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 8792916ea52SBrandon Wyman psu.analyze(); 8802916ea52SBrandon Wyman EXPECT_EQ(psu.hasPgoodFault(), false); 8812916ea52SBrandon Wyman // Turn OFF bit on 8822916ea52SBrandon Wyman expectations.statusWordValue = (status_word::UNIT_IS_OFF); 8832916ea52SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 8842916ea52SBrandon Wyman psu.analyze(); 8852916ea52SBrandon Wyman EXPECT_EQ(psu.hasPgoodFault(), true); 8862916ea52SBrandon Wyman // Back to no fault bits on in STATUS_WORD 8872916ea52SBrandon Wyman expectations.statusWordValue = 0; 8882916ea52SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 8892916ea52SBrandon Wyman psu.analyze(); 8902916ea52SBrandon Wyman EXPECT_EQ(psu.hasPgoodFault(), false); 8912916ea52SBrandon Wyman } 892