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*96893a46SBrandon Wyman uint8_t statusTempValue{0x00}; 33b654c619SBrandon Wyman }; 34b654c619SBrandon Wyman 358da35c51SBrandon Wyman // Helper function to setup expectations for various STATUS_* commands 36b654c619SBrandon Wyman void setPMBusExpectations(MockedPMBus& mockPMBus, 37b654c619SBrandon Wyman const PMBusExpectations& expectations) 388da35c51SBrandon Wyman { 398da35c51SBrandon Wyman EXPECT_CALL(mockPMBus, read(STATUS_WORD, _)) 408da35c51SBrandon Wyman .Times(1) 41b654c619SBrandon Wyman .WillOnce(Return(expectations.statusWordValue)); 428da35c51SBrandon Wyman 43b654c619SBrandon Wyman if (expectations.statusWordValue != 0) 448da35c51SBrandon Wyman { 458da35c51SBrandon Wyman // If fault bits are on in STATUS_WORD, there will also be a read of 46*96893a46SBrandon Wyman // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and 47*96893a46SBrandon Wyman // STATUS_TEMPERATURE. 488da35c51SBrandon Wyman EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _)) 498da35c51SBrandon Wyman .Times(1) 50b654c619SBrandon Wyman .WillOnce(Return(expectations.statusInputValue)); 518da35c51SBrandon Wyman EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)) 528da35c51SBrandon Wyman .Times(1) 53b654c619SBrandon Wyman .WillOnce(Return(expectations.statusMFRValue)); 548da35c51SBrandon Wyman EXPECT_CALL(mockPMBus, read(STATUS_CML, _)) 558da35c51SBrandon Wyman .Times(1) 56b654c619SBrandon Wyman .WillOnce(Return(expectations.statusCMLValue)); 576710ba2cSBrandon Wyman // Page will need to be set to 0 to read STATUS_VOUT. 586710ba2cSBrandon Wyman EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0)) 596710ba2cSBrandon Wyman .Times(1) 606710ba2cSBrandon Wyman .WillOnce(Return("status0_vout")); 616710ba2cSBrandon Wyman EXPECT_CALL(mockPMBus, read("status0_vout", _)) 626710ba2cSBrandon Wyman .Times(1) 63b654c619SBrandon Wyman .WillOnce(Return(expectations.statusVOUTValue)); 64*96893a46SBrandon Wyman EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _)) 65*96893a46SBrandon Wyman .Times(1) 66*96893a46SBrandon Wyman .WillOnce(Return(expectations.statusTempValue)); 678da35c51SBrandon Wyman } 688da35c51SBrandon Wyman } 698da35c51SBrandon Wyman 703f1242f3SBrandon Wyman class PowerSupplyTests : public ::testing::Test 713f1242f3SBrandon Wyman { 723f1242f3SBrandon Wyman public: 733f1242f3SBrandon Wyman PowerSupplyTests() : 743f1242f3SBrandon Wyman mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils())) 753f1242f3SBrandon Wyman { 763f1242f3SBrandon Wyman ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false)); 773f1242f3SBrandon Wyman } 783f1242f3SBrandon Wyman 793f1242f3SBrandon Wyman ~PowerSupplyTests() override 803f1242f3SBrandon Wyman { 813f1242f3SBrandon Wyman freeUtils(); 823f1242f3SBrandon Wyman } 833f1242f3SBrandon Wyman 843f1242f3SBrandon Wyman const MockedUtil& mockedUtil; 853f1242f3SBrandon Wyman }; 863f1242f3SBrandon Wyman 873f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Constructor) 883f1242f3SBrandon Wyman { 893f1242f3SBrandon Wyman /** 903f1242f3SBrandon Wyman * @param[in] invpath - String for inventory path to use 913f1242f3SBrandon Wyman * @param[in] i2cbus - The bus number this power supply is on 923f1242f3SBrandon Wyman * @param[in] i2caddr - The 16-bit I2C address of the power supply 93681b2a36SB. J. Wyman * @param[in] gpioLineName - The string for the gpio-line-name to read for 94681b2a36SB. J. Wyman * presence. 95681b2a36SB. J. Wyman * @param[in] bindDelay - Time in milliseconds to delay binding the device 96681b2a36SB. J. Wyman * driver after seeing the presence line go active. 973f1242f3SBrandon Wyman */ 983f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 991d7a7df8SBrandon Wyman 1001d7a7df8SBrandon Wyman // Try where inventory path is empty, constructor should fail. 1011d7a7df8SBrandon Wyman try 1021d7a7df8SBrandon Wyman { 103681b2a36SB. J. Wyman auto psu = 104681b2a36SB. J. Wyman std::make_unique<PowerSupply>(bus, "", 3, 0x68, PSUGPIOLineName); 1051d7a7df8SBrandon Wyman ADD_FAILURE() << "Should not have reached this line."; 1061d7a7df8SBrandon Wyman } 1071d7a7df8SBrandon Wyman catch (const std::invalid_argument& e) 1081d7a7df8SBrandon Wyman { 1091d7a7df8SBrandon Wyman EXPECT_STREQ(e.what(), "Invalid empty inventoryPath"); 1101d7a7df8SBrandon Wyman } 1111d7a7df8SBrandon Wyman catch (...) 1121d7a7df8SBrandon Wyman { 1131d7a7df8SBrandon Wyman ADD_FAILURE() << "Should not have caught exception."; 1141d7a7df8SBrandon Wyman } 1151d7a7df8SBrandon Wyman 116681b2a36SB. J. Wyman // TODO: Try invalid i2c address? 117681b2a36SB. J. Wyman 118681b2a36SB. J. Wyman // Try where gpioLineName is empty. 1191d7a7df8SBrandon Wyman try 1201d7a7df8SBrandon Wyman { 1211d7a7df8SBrandon Wyman auto psu = 122681b2a36SB. J. Wyman std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, ""); 123681b2a36SB. J. Wyman ADD_FAILURE() 124681b2a36SB. J. Wyman << "Should not have reached this line. Invalid gpioLineName."; 125681b2a36SB. J. Wyman } 126681b2a36SB. J. Wyman catch (const std::invalid_argument& e) 127681b2a36SB. J. Wyman { 128681b2a36SB. J. Wyman EXPECT_STREQ(e.what(), "Invalid empty gpioLineName"); 129681b2a36SB. J. Wyman } 130681b2a36SB. J. Wyman catch (...) 131681b2a36SB. J. Wyman { 132681b2a36SB. J. Wyman ADD_FAILURE() << "Should not have caught exception."; 133681b2a36SB. J. Wyman } 134681b2a36SB. J. Wyman 135681b2a36SB. J. Wyman // Test with valid arguments 136681b2a36SB. J. Wyman // NOT using D-Bus inventory path for presence. 137681b2a36SB. J. Wyman try 138681b2a36SB. J. Wyman { 139681b2a36SB. J. Wyman auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, 140681b2a36SB. J. Wyman PSUGPIOLineName); 1413f1242f3SBrandon Wyman 1423f1242f3SBrandon Wyman EXPECT_EQ(psu->isPresent(), false); 1433f1242f3SBrandon Wyman EXPECT_EQ(psu->isFaulted(), false); 1448da35c51SBrandon Wyman EXPECT_EQ(psu->hasCommFault(), false); 1453f1242f3SBrandon Wyman EXPECT_EQ(psu->hasInputFault(), false); 1463f1242f3SBrandon Wyman EXPECT_EQ(psu->hasMFRFault(), false); 1473f1242f3SBrandon Wyman EXPECT_EQ(psu->hasVINUVFault(), false); 1486710ba2cSBrandon Wyman EXPECT_EQ(psu->hasVoutOVFault(), false); 149*96893a46SBrandon Wyman EXPECT_EQ(psu->hasTempFault(), false); 1503f1242f3SBrandon Wyman } 1511d7a7df8SBrandon Wyman catch (...) 1521d7a7df8SBrandon Wyman { 1531d7a7df8SBrandon Wyman ADD_FAILURE() << "Should not have caught exception."; 1541d7a7df8SBrandon Wyman } 155681b2a36SB. J. Wyman 156681b2a36SB. J. Wyman // Test with valid arguments 157681b2a36SB. J. Wyman // TODO: Using D-Bus inventory path for presence. 158681b2a36SB. J. Wyman try 159681b2a36SB. J. Wyman { 160681b2a36SB. J. Wyman // FIXME: How do I get that presenceGPIO.read() in the startup to throw 161681b2a36SB. J. Wyman // an exception? 162681b2a36SB. J. Wyman 163681b2a36SB. J. Wyman // EXPECT_CALL(mockedUtil, getPresence(_, 164681b2a36SB. J. Wyman // StrEq(PSUInventoryPath))) 165681b2a36SB. J. Wyman // .Times(1); 166681b2a36SB. J. Wyman } 167681b2a36SB. J. Wyman catch (...) 168681b2a36SB. J. Wyman { 169681b2a36SB. J. Wyman ADD_FAILURE() << "Should not have caught exception."; 170681b2a36SB. J. Wyman } 1711d7a7df8SBrandon Wyman } 1723f1242f3SBrandon Wyman 1733f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Analyze) 1743f1242f3SBrandon Wyman { 1753f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 1763f1242f3SBrandon Wyman 177b654c619SBrandon Wyman { 178681b2a36SB. J. Wyman // If I default to reading the GPIO, I will NOT expect a call to 179681b2a36SB. J. Wyman // getPresence(). 180681b2a36SB. J. Wyman 181681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName}; 1823ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 1833ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 184681b2a36SB. J. Wyman EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0)); 185681b2a36SB. J. Wyman 1863f1242f3SBrandon Wyman psu.analyze(); 1873f1242f3SBrandon Wyman // By default, nothing should change. 1883f1242f3SBrandon Wyman EXPECT_EQ(psu.isPresent(), false); 1893f1242f3SBrandon Wyman EXPECT_EQ(psu.isFaulted(), false); 1903f1242f3SBrandon Wyman EXPECT_EQ(psu.hasInputFault(), false); 1913f1242f3SBrandon Wyman EXPECT_EQ(psu.hasMFRFault(), false); 1923f1242f3SBrandon Wyman EXPECT_EQ(psu.hasVINUVFault(), false); 19385c7bf41SBrandon Wyman EXPECT_EQ(psu.hasCommFault(), false); 1946710ba2cSBrandon Wyman EXPECT_EQ(psu.hasVoutOVFault(), false); 195*96893a46SBrandon Wyman EXPECT_EQ(psu.hasTempFault(), false); 196b654c619SBrandon Wyman } 1973f1242f3SBrandon Wyman 198681b2a36SB. J. Wyman PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName}; 199681b2a36SB. J. Wyman // In order to get the various faults tested, the power supply needs to 200681b2a36SB. J. Wyman // be present in order to read from the PMBus device(s). 2013ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO2 = 2023ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO()); 203681b2a36SB. J. Wyman ON_CALL(*mockPresenceGPIO2, read()).WillByDefault(Return(1)); 204681b2a36SB. J. Wyman EXPECT_EQ(psu2.isPresent(), false); 2053f1242f3SBrandon Wyman 2063f1242f3SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus()); 2078da35c51SBrandon Wyman // Presence change from missing to present will trigger write to 2088da35c51SBrandon Wyman // ON_OFF_CONFIG. 2098da35c51SBrandon Wyman EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, _, _)); 210b654c619SBrandon Wyman // Presence change from missing to present will trigger in1_input read 211b654c619SBrandon Wyman // in an attempt to get CLEAR_FAULTS called. 212f07bc797SBrandon Wyman EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000)); 213b654c619SBrandon Wyman 214b654c619SBrandon Wyman // STATUS_WORD INPUT fault. 215b654c619SBrandon Wyman { 216b654c619SBrandon Wyman // Start with STATUS_WORD 0x0000. Powered on, no faults. 217b654c619SBrandon Wyman // Set expectations for a no fault 218b654c619SBrandon Wyman PMBusExpectations expectations; 219b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 2203f1242f3SBrandon Wyman psu2.analyze(); 2213f1242f3SBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 2223f1242f3SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), false); 2233f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), false); 2243f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), false); 2253f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), false); 22685c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), false); 2276710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), false); 228*96893a46SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), false); 2293f1242f3SBrandon Wyman 230b654c619SBrandon Wyman // Update expectations for STATUS_WORD input fault/warn 231*96893a46SBrandon Wyman // STATUS_INPUT fault bits ... on. 232b654c619SBrandon Wyman expectations.statusWordValue = (status_word::INPUT_FAULT_WARN); 233b654c619SBrandon Wyman expectations.statusInputValue = 0x38; 234b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 2353f1242f3SBrandon Wyman psu2.analyze(); 2363f1242f3SBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 2373f1242f3SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), true); 2383f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), true); 2393f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), false); 2403f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), false); 24185c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), false); 2426710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), false); 243*96893a46SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), false); 244b654c619SBrandon Wyman } 2453f1242f3SBrandon Wyman 2463f1242f3SBrandon Wyman // STATUS_WORD INPUT/UV fault. 247b654c619SBrandon Wyman { 2483f1242f3SBrandon Wyman // First need it to return good status, then the fault 249b654c619SBrandon Wyman PMBusExpectations expectations; 250b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 2513f1242f3SBrandon Wyman psu2.analyze(); 2528da35c51SBrandon Wyman // Now set fault bits in STATUS_WORD 253b654c619SBrandon Wyman expectations.statusWordValue = 2548da35c51SBrandon Wyman (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT); 2558da35c51SBrandon Wyman // STATUS_INPUT fault bits ... on. 256b654c619SBrandon Wyman expectations.statusInputValue = 0x38; 257b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 2583f1242f3SBrandon Wyman psu2.analyze(); 2593f1242f3SBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 2603f1242f3SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), true); 261f07bc797SBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), true); 2623f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), false); 2633f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), true); 26485c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), false); 2656710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), false); 266*96893a46SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), false); 267b654c619SBrandon Wyman } 2683f1242f3SBrandon Wyman 2693f1242f3SBrandon Wyman // STATUS_WORD MFR fault. 270b654c619SBrandon Wyman { 271f07bc797SBrandon Wyman // First need it to return good status, then the fault 272b654c619SBrandon Wyman PMBusExpectations expectations; 273b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 2743f1242f3SBrandon Wyman psu2.analyze(); 2758da35c51SBrandon Wyman // Now STATUS_WORD with MFR fault bit on. 276b654c619SBrandon Wyman expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 2778da35c51SBrandon Wyman // STATUS_MFR bits on. 278b654c619SBrandon Wyman expectations.statusMFRValue = 0xFF; 279b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 2803f1242f3SBrandon Wyman psu2.analyze(); 2813f1242f3SBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 2823f1242f3SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), true); 2833f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), false); 2843f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), true); 2853f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), false); 28685c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), false); 2876710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), false); 288*96893a46SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), false); 289b654c619SBrandon Wyman } 2903f1242f3SBrandon Wyman 291*96893a46SBrandon Wyman // Temperature fault. 292b654c619SBrandon Wyman { 293f07bc797SBrandon Wyman // First STATUS_WORD with no bits set, then with temperature fault. 294b654c619SBrandon Wyman PMBusExpectations expectations; 295b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 2963f1242f3SBrandon Wyman psu2.analyze(); 2978da35c51SBrandon Wyman // STATUS_WORD with temperature fault bit on. 298b654c619SBrandon Wyman expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN); 299*96893a46SBrandon Wyman // STATUS_TEMPERATURE with fault bit(s) on. 300*96893a46SBrandon Wyman expectations.statusTempValue = 0x10; 301b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 3023f1242f3SBrandon Wyman psu2.analyze(); 3033f1242f3SBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 304*96893a46SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), true); 3053f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), false); 3063f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), false); 3073f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), false); 30885c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), false); 3096710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), false); 310*96893a46SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), true); 311b654c619SBrandon Wyman } 31285c7bf41SBrandon Wyman 31385c7bf41SBrandon Wyman // CML fault 314b654c619SBrandon Wyman { 31585c7bf41SBrandon Wyman // First STATUS_WORD wit no bits set, then with CML fault. 316b654c619SBrandon Wyman PMBusExpectations expectations; 317b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 31885c7bf41SBrandon Wyman psu2.analyze(); 3198da35c51SBrandon Wyman // STATUS_WORD with CML fault bit on. 320b654c619SBrandon Wyman expectations.statusWordValue = (status_word::CML_FAULT); 32185c7bf41SBrandon Wyman // Turn on STATUS_CML fault bit(s) 322b654c619SBrandon Wyman expectations.statusCMLValue = 0xFF; 323b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 32485c7bf41SBrandon Wyman psu2.analyze(); 32585c7bf41SBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 32685c7bf41SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), true); 32785c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), false); 32885c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), false); 32985c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), false); 33085c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), true); 3316710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), false); 332*96893a46SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), false); 333b654c619SBrandon Wyman } 3346710ba2cSBrandon Wyman 3356710ba2cSBrandon Wyman // VOUT_OV_FAULT fault 336b654c619SBrandon Wyman { 3376710ba2cSBrandon Wyman // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault. 338b654c619SBrandon Wyman PMBusExpectations expectations; 339b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 3406710ba2cSBrandon Wyman psu2.analyze(); 3416710ba2cSBrandon Wyman // STATUS_WORD with VOUT/VOUT_OV fault. 342b654c619SBrandon Wyman expectations.statusWordValue = 3436710ba2cSBrandon Wyman ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT)); 3446710ba2cSBrandon Wyman // Turn on STATUS_VOUT fault bit(s) 345b654c619SBrandon Wyman expectations.statusVOUTValue = 0xA0; 346*96893a46SBrandon Wyman // STATUS_TEMPERATURE don't care (default) 347b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 3486710ba2cSBrandon Wyman psu2.analyze(); 3496710ba2cSBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 3506710ba2cSBrandon Wyman EXPECT_EQ(psu2.isFaulted(), true); 3516710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), false); 3526710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), false); 3536710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), false); 3546710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), false); 3556710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), true); 356*96893a46SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), false); 357b654c619SBrandon Wyman } 3583f1242f3SBrandon Wyman 3593f1242f3SBrandon Wyman // Ignore fan fault 360b654c619SBrandon Wyman { 361b654c619SBrandon Wyman // First STATUS_WORD with no bits set, then with fan fault. 362b654c619SBrandon Wyman PMBusExpectations expectations; 363b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 3643f1242f3SBrandon Wyman psu2.analyze(); 365b654c619SBrandon Wyman expectations.statusWordValue = (status_word::FAN_FAULT); 366b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 3673f1242f3SBrandon Wyman psu2.analyze(); 3683f1242f3SBrandon Wyman EXPECT_EQ(psu2.isPresent(), true); 3693f1242f3SBrandon Wyman EXPECT_EQ(psu2.isFaulted(), false); 3703f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasInputFault(), false); 3713f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasMFRFault(), false); 3723f1242f3SBrandon Wyman EXPECT_EQ(psu2.hasVINUVFault(), false); 37385c7bf41SBrandon Wyman EXPECT_EQ(psu2.hasCommFault(), false); 3746710ba2cSBrandon Wyman EXPECT_EQ(psu2.hasVoutOVFault(), false); 375*96893a46SBrandon Wyman EXPECT_EQ(psu2.hasTempFault(), false); 376b654c619SBrandon Wyman } 3773f1242f3SBrandon Wyman // TODO: ReadFailure 3783f1242f3SBrandon Wyman } 3793f1242f3SBrandon Wyman 38059a35793SBrandon Wyman TEST_F(PowerSupplyTests, OnOffConfig) 38159a35793SBrandon Wyman { 38259a35793SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 38359a35793SBrandon Wyman uint8_t data = 0x15; 38459a35793SBrandon Wyman 38559a35793SBrandon Wyman // Test where PSU is NOT present 38659a35793SBrandon Wyman try 38759a35793SBrandon Wyman { 388681b2a36SB. J. Wyman // Assume GPIO presence, not inventory presence? 389681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName}; 390681b2a36SB. J. Wyman 3913ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 3923ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 393681b2a36SB. J. Wyman ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0)); 39459a35793SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 395681b2a36SB. J. Wyman // Constructor should set initial presence, default read returns 0. 39659a35793SBrandon Wyman // If it is not present, I should not be trying to write to it. 39759a35793SBrandon Wyman EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0); 39859a35793SBrandon Wyman psu.onOffConfig(data); 39959a35793SBrandon Wyman } 40059a35793SBrandon Wyman catch (...) 4010c9a33d6SAdriana Kobylak {} 40259a35793SBrandon Wyman 40359a35793SBrandon Wyman // Test where PSU is present 40459a35793SBrandon Wyman try 40559a35793SBrandon Wyman { 406681b2a36SB. J. Wyman // Assume GPIO presence, not inventory presence? 407681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName}; 4083ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 4093ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 410681b2a36SB. J. Wyman ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1)); 41159a35793SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 412681b2a36SB. J. Wyman // TODO: expect setPresence call? 413681b2a36SB. J. Wyman // updatePresence() private function reads gpio, called by analyze(). 414681b2a36SB. J. Wyman psu.analyze(); 41559a35793SBrandon Wyman // TODO: ???should I check the filename? 41659a35793SBrandon Wyman EXPECT_CALL(mockPMBus, 41759a35793SBrandon Wyman writeBinary(_, ElementsAre(0x15), Type::HwmonDeviceDebug)) 41859a35793SBrandon Wyman .Times(1); 41959a35793SBrandon Wyman psu.onOffConfig(data); 42059a35793SBrandon Wyman } 42159a35793SBrandon Wyman catch (...) 4220c9a33d6SAdriana Kobylak {} 42359a35793SBrandon Wyman } 42459a35793SBrandon Wyman 4253f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, ClearFaults) 4263f1242f3SBrandon Wyman { 4273f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 428681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName}; 4293ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 4303ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 431681b2a36SB. J. Wyman // GPIO read return 1 to indicate present. 432681b2a36SB. J. Wyman ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1)); 433681b2a36SB. J. Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 4348da35c51SBrandon Wyman // Presence change from missing to present will trigger in1_input read in 4358da35c51SBrandon Wyman // an attempt to get CLEAR_FAULTS called. 4368da35c51SBrandon Wyman EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000)); 4378da35c51SBrandon Wyman // STATUS_WORD 0x0000 is powered on, no faults. 438b654c619SBrandon Wyman PMBusExpectations expectations; 439b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 440681b2a36SB. J. Wyman psu.analyze(); 4413f1242f3SBrandon Wyman EXPECT_EQ(psu.isPresent(), true); 4423f1242f3SBrandon Wyman EXPECT_EQ(psu.isFaulted(), false); 4433f1242f3SBrandon Wyman EXPECT_EQ(psu.hasInputFault(), false); 4443f1242f3SBrandon Wyman EXPECT_EQ(psu.hasMFRFault(), false); 4453f1242f3SBrandon Wyman EXPECT_EQ(psu.hasVINUVFault(), false); 44685c7bf41SBrandon Wyman EXPECT_EQ(psu.hasCommFault(), false); 4476710ba2cSBrandon Wyman EXPECT_EQ(psu.hasVoutOVFault(), false); 448*96893a46SBrandon Wyman EXPECT_EQ(psu.hasTempFault(), false); 449b654c619SBrandon Wyman 450f07bc797SBrandon Wyman // STATUS_WORD with fault bits galore! 451b654c619SBrandon Wyman expectations.statusWordValue = 0xFFFF; 452f07bc797SBrandon Wyman // STATUS_INPUT with fault bits on. 453b654c619SBrandon Wyman expectations.statusInputValue = 0xFF; 454f07bc797SBrandon Wyman // STATUS_MFR_SPEFIC with bits on. 455b654c619SBrandon Wyman expectations.statusMFRValue = 0xFF; 45685c7bf41SBrandon Wyman // STATUS_CML with bits on. 457b654c619SBrandon Wyman expectations.statusCMLValue = 0xFF; 4586710ba2cSBrandon Wyman // STATUS_VOUT with bits on. 459b654c619SBrandon Wyman expectations.statusVOUTValue = 0xFF; 460*96893a46SBrandon Wyman // STATUS_TEMPERATURE with bits on. 461*96893a46SBrandon Wyman expectations.statusTempValue = 0xFF; 462b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 4633f1242f3SBrandon Wyman psu.analyze(); 4643f1242f3SBrandon Wyman EXPECT_EQ(psu.isPresent(), true); 4653f1242f3SBrandon Wyman EXPECT_EQ(psu.isFaulted(), true); 4663f1242f3SBrandon Wyman EXPECT_EQ(psu.hasInputFault(), true); 4673f1242f3SBrandon Wyman EXPECT_EQ(psu.hasMFRFault(), true); 4683f1242f3SBrandon Wyman EXPECT_EQ(psu.hasVINUVFault(), true); 46985c7bf41SBrandon Wyman EXPECT_EQ(psu.hasCommFault(), true); 4706710ba2cSBrandon Wyman EXPECT_EQ(psu.hasVoutOVFault(), true); 471*96893a46SBrandon Wyman EXPECT_EQ(psu.hasTempFault(), true); 4723c208464SBrandon Wyman EXPECT_CALL(mockPMBus, read("in1_input", _)) 4733c208464SBrandon Wyman .Times(1) 4743c208464SBrandon Wyman .WillOnce(Return(209000)); 4753f1242f3SBrandon Wyman psu.clearFaults(); 4763f1242f3SBrandon Wyman EXPECT_EQ(psu.isPresent(), true); 4773f1242f3SBrandon Wyman EXPECT_EQ(psu.isFaulted(), false); 4783f1242f3SBrandon Wyman EXPECT_EQ(psu.hasInputFault(), false); 4793f1242f3SBrandon Wyman EXPECT_EQ(psu.hasMFRFault(), false); 4803f1242f3SBrandon Wyman EXPECT_EQ(psu.hasVINUVFault(), false); 48185c7bf41SBrandon Wyman EXPECT_EQ(psu.hasCommFault(), false); 4826710ba2cSBrandon Wyman EXPECT_EQ(psu.hasVoutOVFault(), false); 483*96893a46SBrandon Wyman EXPECT_EQ(psu.hasTempFault(), false); 484681b2a36SB. J. Wyman 485681b2a36SB. J. Wyman // TODO: Faults clear on missing/present? 4863f1242f3SBrandon Wyman } 4873f1242f3SBrandon Wyman 4883f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, UpdateInventory) 4893f1242f3SBrandon Wyman { 4903f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 4911d7a7df8SBrandon Wyman 4921d7a7df8SBrandon Wyman try 4931d7a7df8SBrandon Wyman { 494681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 4951d7a7df8SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 4961d7a7df8SBrandon Wyman // If it is not present, I should not be trying to read a string 4971d7a7df8SBrandon Wyman EXPECT_CALL(mockPMBus, readString(_, _)).Times(0); 4981d7a7df8SBrandon Wyman psu.updateInventory(); 4991d7a7df8SBrandon Wyman } 5001d7a7df8SBrandon Wyman catch (...) 5011d7a7df8SBrandon Wyman { 5021d7a7df8SBrandon Wyman ADD_FAILURE() << "Should not have caught exception."; 5031d7a7df8SBrandon Wyman } 5041d7a7df8SBrandon Wyman 5051d7a7df8SBrandon Wyman try 5061d7a7df8SBrandon Wyman { 507681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName}; 5083ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 5093ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 510681b2a36SB. J. Wyman // GPIO read return 1 to indicate present. 511681b2a36SB. J. Wyman EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1)); 512681b2a36SB. J. Wyman psu.analyze(); 5131d7a7df8SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 5141d7a7df8SBrandon Wyman EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return("")); 5153f1242f3SBrandon Wyman psu.updateInventory(); 5161d7a7df8SBrandon Wyman 5173c530fbdSBrandon Wyman #if IBM_VPD 5181d7a7df8SBrandon Wyman EXPECT_CALL(mockPMBus, readString(_, _)) 5191d7a7df8SBrandon Wyman .WillOnce(Return("CCIN")) 5201d7a7df8SBrandon Wyman .WillOnce(Return("PN3456")) 5211d7a7df8SBrandon Wyman .WillOnce(Return("FN3456")) 5221d7a7df8SBrandon Wyman .WillOnce(Return("HEADER")) 5231d7a7df8SBrandon Wyman .WillOnce(Return("SN3456")) 5241d7a7df8SBrandon Wyman .WillOnce(Return("FW3456")); 5253c530fbdSBrandon Wyman #endif 5261d7a7df8SBrandon Wyman psu.updateInventory(); 5271d7a7df8SBrandon Wyman // TODO: D-Bus mocking to verify values stored on D-Bus (???) 5281d7a7df8SBrandon Wyman } 5291d7a7df8SBrandon Wyman catch (...) 5301d7a7df8SBrandon Wyman { 5311d7a7df8SBrandon Wyman ADD_FAILURE() << "Should not have caught exception."; 5321d7a7df8SBrandon Wyman } 5333f1242f3SBrandon Wyman } 5343f1242f3SBrandon Wyman 5353f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsPresent) 5363f1242f3SBrandon Wyman { 5373f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 538681b2a36SB. J. Wyman 539681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 5403ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 5413ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 5423f1242f3SBrandon Wyman EXPECT_EQ(psu.isPresent(), false); 5433f1242f3SBrandon Wyman 544681b2a36SB. J. Wyman // Change GPIO read to return 1 to indicate present. 545681b2a36SB. J. Wyman EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1)); 546681b2a36SB. J. Wyman psu.analyze(); 547681b2a36SB. J. Wyman EXPECT_EQ(psu.isPresent(), true); 5483f1242f3SBrandon Wyman } 5493f1242f3SBrandon Wyman 5503f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsFaulted) 5513f1242f3SBrandon Wyman { 5523f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 553681b2a36SB. J. Wyman 554681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName}; 5553ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 5563ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 557681b2a36SB. J. Wyman // Always return 1 to indicate present. 558681b2a36SB. J. Wyman EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 559681b2a36SB. J. Wyman psu.analyze(); 5603f1242f3SBrandon Wyman EXPECT_EQ(psu.isFaulted(), false); 5613f1242f3SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 562b654c619SBrandon Wyman PMBusExpectations expectations; 563f07bc797SBrandon Wyman // STATUS_WORD with fault bits on. 564b654c619SBrandon Wyman expectations.statusWordValue = 0xFFFF; 565f07bc797SBrandon Wyman // STATUS_INPUT with fault bits on. 566b654c619SBrandon Wyman expectations.statusInputValue = 0xFF; 567f07bc797SBrandon Wyman // STATUS_MFR_SPECIFIC with faults bits on. 568b654c619SBrandon Wyman expectations.statusMFRValue = 0xFF; 56985c7bf41SBrandon Wyman // STATUS_CML with faults bits on. 570b654c619SBrandon Wyman expectations.statusCMLValue = 0xFF; 5716710ba2cSBrandon Wyman // STATUS_VOUT with fault bits on. 572b654c619SBrandon Wyman expectations.statusVOUTValue = 0xFF; 573*96893a46SBrandon Wyman // STATUS_TEMPERATURE with fault bits on. 574*96893a46SBrandon Wyman expectations.statusTempValue = 0xFF; 575b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 5763f1242f3SBrandon Wyman psu.analyze(); 5773f1242f3SBrandon Wyman EXPECT_EQ(psu.isFaulted(), true); 5783f1242f3SBrandon Wyman } 5793f1242f3SBrandon Wyman 5803f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasInputFault) 5813f1242f3SBrandon Wyman { 5823f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 583681b2a36SB. J. Wyman 584681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 5853ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 5863ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 587681b2a36SB. J. Wyman // Always return 1 to indicate present. 588681b2a36SB. J. Wyman EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 589681b2a36SB. J. Wyman psu.analyze(); 5903f1242f3SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 5913f1242f3SBrandon Wyman EXPECT_EQ(psu.hasInputFault(), false); 5928da35c51SBrandon Wyman // STATUS_WORD 0x0000 is powered on, no faults. 593b654c619SBrandon Wyman PMBusExpectations expectations; 594b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 5953f1242f3SBrandon Wyman psu.analyze(); 5963f1242f3SBrandon Wyman EXPECT_EQ(psu.hasInputFault(), false); 597f07bc797SBrandon Wyman // STATUS_WORD with input fault/warn on. 598b654c619SBrandon Wyman expectations.statusWordValue = (status_word::INPUT_FAULT_WARN); 599f07bc797SBrandon Wyman // STATUS_INPUT with an input fault bit on. 600b654c619SBrandon Wyman expectations.statusInputValue = 0x80; 601b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 6023f1242f3SBrandon Wyman psu.analyze(); 6033f1242f3SBrandon Wyman EXPECT_EQ(psu.hasInputFault(), true); 604f07bc797SBrandon Wyman // STATUS_WORD with no bits on. 605b654c619SBrandon Wyman expectations.statusWordValue = 0; 606b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 6073f1242f3SBrandon Wyman psu.analyze(); 6083f1242f3SBrandon Wyman EXPECT_EQ(psu.hasInputFault(), false); 6093f1242f3SBrandon Wyman } 6103f1242f3SBrandon Wyman 6113f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasMFRFault) 6123f1242f3SBrandon Wyman { 6133f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 614681b2a36SB. J. Wyman 615681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 6163ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 6173ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 618681b2a36SB. J. Wyman // Always return 1 to indicate present. 619681b2a36SB. J. Wyman EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 620681b2a36SB. J. Wyman psu.analyze(); 6213f1242f3SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 6223f1242f3SBrandon Wyman EXPECT_EQ(psu.hasMFRFault(), false); 623f07bc797SBrandon Wyman // First return STATUS_WORD with no bits on. 6248da35c51SBrandon Wyman // STATUS_WORD 0x0000 is powered on, no faults. 625b654c619SBrandon Wyman PMBusExpectations expectations; 626b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 6273f1242f3SBrandon Wyman psu.analyze(); 6283f1242f3SBrandon Wyman EXPECT_EQ(psu.hasMFRFault(), false); 629f07bc797SBrandon Wyman // Next return STATUS_WORD with MFR fault bit on. 630b654c619SBrandon Wyman expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT); 631f07bc797SBrandon Wyman // STATUS_MFR_SPEFIC with bit(s) on. 632b654c619SBrandon Wyman expectations.statusMFRValue = 0xFF; 633b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 6343f1242f3SBrandon Wyman psu.analyze(); 6353f1242f3SBrandon Wyman EXPECT_EQ(psu.hasMFRFault(), true); 636f07bc797SBrandon Wyman // Back to no bits on in STATUS_WORD 637b654c619SBrandon Wyman expectations.statusWordValue = 0; 638b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 6393f1242f3SBrandon Wyman psu.analyze(); 6403f1242f3SBrandon Wyman EXPECT_EQ(psu.hasMFRFault(), false); 6413f1242f3SBrandon Wyman } 6423f1242f3SBrandon Wyman 6433f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasVINUVFault) 6443f1242f3SBrandon Wyman { 6453f1242f3SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 646681b2a36SB. J. Wyman 647681b2a36SB. J. Wyman PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName}; 6483ca062aeSAdriana Kobylak MockedGPIOInterface* mockPresenceGPIO = 6493ca062aeSAdriana Kobylak static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 650681b2a36SB. J. Wyman // Always return 1 to indicate present. 651681b2a36SB. J. Wyman EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 652681b2a36SB. J. Wyman psu.analyze(); 6533f1242f3SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 6543f1242f3SBrandon Wyman EXPECT_EQ(psu.hasVINUVFault(), false); 6558da35c51SBrandon Wyman // STATUS_WORD 0x0000 is powered on, no faults. 656b654c619SBrandon Wyman PMBusExpectations expectations; 657b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 6583f1242f3SBrandon Wyman psu.analyze(); 6593f1242f3SBrandon Wyman EXPECT_EQ(psu.hasVINUVFault(), false); 660f07bc797SBrandon Wyman // Turn fault on. 661b654c619SBrandon Wyman expectations.statusWordValue = (status_word::VIN_UV_FAULT); 66285c7bf41SBrandon Wyman // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by 66385c7bf41SBrandon Wyman // Figure 16, and assume bits on in STATUS_INPUT. 664b654c619SBrandon Wyman expectations.statusInputValue = 0x18; 665b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 6663f1242f3SBrandon Wyman psu.analyze(); 6673f1242f3SBrandon Wyman EXPECT_EQ(psu.hasVINUVFault(), true); 668f07bc797SBrandon Wyman // Back to no fault bits on in STATUS_WORD 669b654c619SBrandon Wyman expectations.statusWordValue = 0; 670b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 6713f1242f3SBrandon Wyman psu.analyze(); 6723f1242f3SBrandon Wyman EXPECT_EQ(psu.hasVINUVFault(), false); 6733f1242f3SBrandon Wyman } 6746710ba2cSBrandon Wyman 6756710ba2cSBrandon Wyman TEST_F(PowerSupplyTests, HasVoutOVFault) 6766710ba2cSBrandon Wyman { 6776710ba2cSBrandon Wyman auto bus = sdbusplus::bus::new_default(); 6786710ba2cSBrandon Wyman 6796710ba2cSBrandon Wyman PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName}; 6806710ba2cSBrandon Wyman MockedGPIOInterface* mockPresenceGPIO = 6816710ba2cSBrandon Wyman static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 6826710ba2cSBrandon Wyman // Always return 1 to indicate present. 6836710ba2cSBrandon Wyman EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 6846710ba2cSBrandon Wyman psu.analyze(); 6856710ba2cSBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 6866710ba2cSBrandon Wyman EXPECT_EQ(psu.hasVoutOVFault(), false); 6876710ba2cSBrandon Wyman // STATUS_WORD 0x0000 is powered on, no faults. 688b654c619SBrandon Wyman PMBusExpectations expectations; 689b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 6906710ba2cSBrandon Wyman psu.analyze(); 6916710ba2cSBrandon Wyman EXPECT_EQ(psu.hasVoutOVFault(), false); 6926710ba2cSBrandon Wyman // Turn fault on. 693b654c619SBrandon Wyman expectations.statusWordValue = (status_word::VOUT_OV_FAULT); 6946710ba2cSBrandon Wyman // STATUS_VOUT fault bit(s) 695b654c619SBrandon Wyman expectations.statusVOUTValue = 0x80; 696*96893a46SBrandon Wyman // STATUS_TEMPERATURE default. 697b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 6986710ba2cSBrandon Wyman psu.analyze(); 6996710ba2cSBrandon Wyman EXPECT_EQ(psu.hasVoutOVFault(), true); 7006710ba2cSBrandon Wyman // Back to no fault bits on in STATUS_WORD 701b654c619SBrandon Wyman expectations.statusWordValue = 0; 702b654c619SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 7036710ba2cSBrandon Wyman psu.analyze(); 7046710ba2cSBrandon Wyman EXPECT_EQ(psu.hasVoutOVFault(), false); 7056710ba2cSBrandon Wyman } 706*96893a46SBrandon Wyman 707*96893a46SBrandon Wyman TEST_F(PowerSupplyTests, HasTempFault) 708*96893a46SBrandon Wyman { 709*96893a46SBrandon Wyman auto bus = sdbusplus::bus::new_default(); 710*96893a46SBrandon Wyman 711*96893a46SBrandon Wyman PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName}; 712*96893a46SBrandon Wyman MockedGPIOInterface* mockPresenceGPIO = 713*96893a46SBrandon Wyman static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO()); 714*96893a46SBrandon Wyman // Always return 1 to indicate present. 715*96893a46SBrandon Wyman EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1)); 716*96893a46SBrandon Wyman psu.analyze(); 717*96893a46SBrandon Wyman MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus()); 718*96893a46SBrandon Wyman EXPECT_EQ(psu.hasTempFault(), false); 719*96893a46SBrandon Wyman // STATUS_WORD 0x0000 is powered on, no faults. 720*96893a46SBrandon Wyman PMBusExpectations expectations; 721*96893a46SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 722*96893a46SBrandon Wyman psu.analyze(); 723*96893a46SBrandon Wyman EXPECT_EQ(psu.hasTempFault(), false); 724*96893a46SBrandon Wyman // Turn fault on. 725*96893a46SBrandon Wyman expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN); 726*96893a46SBrandon Wyman // STATUS_TEMPERATURE fault bit on (OT Fault) 727*96893a46SBrandon Wyman expectations.statusTempValue = 0x80; 728*96893a46SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 729*96893a46SBrandon Wyman psu.analyze(); 730*96893a46SBrandon Wyman EXPECT_EQ(psu.hasTempFault(), true); 731*96893a46SBrandon Wyman // Back to no fault bits on in STATUS_WORD 732*96893a46SBrandon Wyman expectations.statusWordValue = 0; 733*96893a46SBrandon Wyman setPMBusExpectations(mockPMBus, expectations); 734*96893a46SBrandon Wyman psu.analyze(); 735*96893a46SBrandon Wyman EXPECT_EQ(psu.hasTempFault(), false); 736*96893a46SBrandon Wyman } 737