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 
258da35c51SBrandon Wyman // Helper function to setup expectations for various STATUS_* commands
268da35c51SBrandon Wyman void setPMBusExpectations(MockedPMBus& mockPMBus, uint16_t statusWordValue,
278da35c51SBrandon Wyman                           uint8_t statusInputValue = 0,
288da35c51SBrandon Wyman                           uint8_t statusMFRValue = 0,
29*6710ba2cSBrandon Wyman                           uint8_t statusCMLValue = 0,
30*6710ba2cSBrandon Wyman                           uint8_t statusVOUTValue = 0)
318da35c51SBrandon Wyman {
328da35c51SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
338da35c51SBrandon Wyman         .Times(1)
348da35c51SBrandon Wyman         .WillOnce(Return(statusWordValue));
358da35c51SBrandon Wyman 
368da35c51SBrandon Wyman     if (statusWordValue != 0)
378da35c51SBrandon Wyman     {
388da35c51SBrandon Wyman         // If fault bits are on in STATUS_WORD, there will also be a read of
398da35c51SBrandon Wyman         // STATUS_INPUT, STATUS_MFR, and STATUS_CML.
408da35c51SBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
418da35c51SBrandon Wyman             .Times(1)
428da35c51SBrandon Wyman             .WillOnce(Return(statusInputValue));
438da35c51SBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_MFR, _))
448da35c51SBrandon Wyman             .Times(1)
458da35c51SBrandon Wyman             .WillOnce(Return(statusMFRValue));
468da35c51SBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_CML, _))
478da35c51SBrandon Wyman             .Times(1)
488da35c51SBrandon Wyman             .WillOnce(Return(statusCMLValue));
49*6710ba2cSBrandon Wyman         // Page will need to be set to 0 to read STATUS_VOUT.
50*6710ba2cSBrandon Wyman         EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0))
51*6710ba2cSBrandon Wyman             .Times(1)
52*6710ba2cSBrandon Wyman             .WillOnce(Return("status0_vout"));
53*6710ba2cSBrandon Wyman         EXPECT_CALL(mockPMBus, read("status0_vout", _))
54*6710ba2cSBrandon Wyman             .Times(1)
55*6710ba2cSBrandon Wyman             .WillOnce(Return(statusVOUTValue));
568da35c51SBrandon Wyman     }
578da35c51SBrandon Wyman }
588da35c51SBrandon Wyman 
593f1242f3SBrandon Wyman class PowerSupplyTests : public ::testing::Test
603f1242f3SBrandon Wyman {
613f1242f3SBrandon Wyman   public:
623f1242f3SBrandon Wyman     PowerSupplyTests() :
633f1242f3SBrandon Wyman         mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
643f1242f3SBrandon Wyman     {
653f1242f3SBrandon Wyman         ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
663f1242f3SBrandon Wyman     }
673f1242f3SBrandon Wyman 
683f1242f3SBrandon Wyman     ~PowerSupplyTests() override
693f1242f3SBrandon Wyman     {
703f1242f3SBrandon Wyman         freeUtils();
713f1242f3SBrandon Wyman     }
723f1242f3SBrandon Wyman 
733f1242f3SBrandon Wyman     const MockedUtil& mockedUtil;
743f1242f3SBrandon Wyman };
753f1242f3SBrandon Wyman 
763f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Constructor)
773f1242f3SBrandon Wyman {
783f1242f3SBrandon Wyman     /**
793f1242f3SBrandon Wyman      * @param[in] invpath - String for inventory path to use
803f1242f3SBrandon Wyman      * @param[in] i2cbus - The bus number this power supply is on
813f1242f3SBrandon Wyman      * @param[in] i2caddr - The 16-bit I2C address of the power supply
82681b2a36SB. J. Wyman      * @param[in] gpioLineName - The string for the gpio-line-name to read for
83681b2a36SB. J. Wyman      * presence.
84681b2a36SB. J. Wyman      * @param[in] bindDelay - Time in milliseconds to delay binding the device
85681b2a36SB. J. Wyman      * driver after seeing the presence line go active.
863f1242f3SBrandon Wyman      */
873f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
881d7a7df8SBrandon Wyman 
891d7a7df8SBrandon Wyman     // Try where inventory path is empty, constructor should fail.
901d7a7df8SBrandon Wyman     try
911d7a7df8SBrandon Wyman     {
92681b2a36SB. J. Wyman         auto psu =
93681b2a36SB. J. Wyman             std::make_unique<PowerSupply>(bus, "", 3, 0x68, PSUGPIOLineName);
941d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have reached this line.";
951d7a7df8SBrandon Wyman     }
961d7a7df8SBrandon Wyman     catch (const std::invalid_argument& e)
971d7a7df8SBrandon Wyman     {
981d7a7df8SBrandon Wyman         EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
991d7a7df8SBrandon Wyman     }
1001d7a7df8SBrandon Wyman     catch (...)
1011d7a7df8SBrandon Wyman     {
1021d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
1031d7a7df8SBrandon Wyman     }
1041d7a7df8SBrandon Wyman 
105681b2a36SB. J. Wyman     // TODO: Try invalid i2c address?
106681b2a36SB. J. Wyman 
107681b2a36SB. J. Wyman     // Try where gpioLineName is empty.
1081d7a7df8SBrandon Wyman     try
1091d7a7df8SBrandon Wyman     {
1101d7a7df8SBrandon Wyman         auto psu =
111681b2a36SB. J. Wyman             std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, "");
112681b2a36SB. J. Wyman         ADD_FAILURE()
113681b2a36SB. J. Wyman             << "Should not have reached this line. Invalid gpioLineName.";
114681b2a36SB. J. Wyman     }
115681b2a36SB. J. Wyman     catch (const std::invalid_argument& e)
116681b2a36SB. J. Wyman     {
117681b2a36SB. J. Wyman         EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
118681b2a36SB. J. Wyman     }
119681b2a36SB. J. Wyman     catch (...)
120681b2a36SB. J. Wyman     {
121681b2a36SB. J. Wyman         ADD_FAILURE() << "Should not have caught exception.";
122681b2a36SB. J. Wyman     }
123681b2a36SB. J. Wyman 
124681b2a36SB. J. Wyman     // Test with valid arguments
125681b2a36SB. J. Wyman     // NOT using D-Bus inventory path for presence.
126681b2a36SB. J. Wyman     try
127681b2a36SB. J. Wyman     {
128681b2a36SB. J. Wyman         auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
129681b2a36SB. J. Wyman                                                  PSUGPIOLineName);
1303f1242f3SBrandon Wyman 
1313f1242f3SBrandon Wyman         EXPECT_EQ(psu->isPresent(), false);
1323f1242f3SBrandon Wyman         EXPECT_EQ(psu->isFaulted(), false);
1338da35c51SBrandon Wyman         EXPECT_EQ(psu->hasCommFault(), false);
1343f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasInputFault(), false);
1353f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasMFRFault(), false);
1363f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasVINUVFault(), false);
137*6710ba2cSBrandon Wyman         EXPECT_EQ(psu->hasVoutOVFault(), false);
1383f1242f3SBrandon Wyman     }
1391d7a7df8SBrandon Wyman     catch (...)
1401d7a7df8SBrandon Wyman     {
1411d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
1421d7a7df8SBrandon Wyman     }
143681b2a36SB. J. Wyman 
144681b2a36SB. J. Wyman     // Test with valid arguments
145681b2a36SB. J. Wyman     // TODO: Using D-Bus inventory path for presence.
146681b2a36SB. J. Wyman     try
147681b2a36SB. J. Wyman     {
148681b2a36SB. J. Wyman         // FIXME: How do I get that presenceGPIO.read() in the startup to throw
149681b2a36SB. J. Wyman         // an exception?
150681b2a36SB. J. Wyman 
151681b2a36SB. J. Wyman         // EXPECT_CALL(mockedUtil, getPresence(_,
152681b2a36SB. J. Wyman         // StrEq(PSUInventoryPath)))
153681b2a36SB. J. Wyman         //    .Times(1);
154681b2a36SB. J. Wyman     }
155681b2a36SB. J. Wyman     catch (...)
156681b2a36SB. J. Wyman     {
157681b2a36SB. J. Wyman         ADD_FAILURE() << "Should not have caught exception.";
158681b2a36SB. J. Wyman     }
1591d7a7df8SBrandon Wyman }
1603f1242f3SBrandon Wyman 
1613f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Analyze)
1623f1242f3SBrandon Wyman {
1633f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1643f1242f3SBrandon Wyman 
165681b2a36SB. J. Wyman     // If I default to reading the GPIO, I will NOT expect a call to
166681b2a36SB. J. Wyman     // getPresence().
167681b2a36SB. J. Wyman 
168681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
1693ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
1703ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
171681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
172681b2a36SB. J. Wyman 
1733f1242f3SBrandon Wyman     psu.analyze();
1743f1242f3SBrandon Wyman     // By default, nothing should change.
1753f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), false);
1763f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
1773f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
1783f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
1793f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
18085c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
181*6710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
1823f1242f3SBrandon Wyman 
183681b2a36SB. J. Wyman     PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
184681b2a36SB. J. Wyman     // In order to get the various faults tested, the power supply needs to
185681b2a36SB. J. Wyman     // be present in order to read from the PMBus device(s).
1863ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO2 =
1873ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
188681b2a36SB. J. Wyman     ON_CALL(*mockPresenceGPIO2, read()).WillByDefault(Return(1));
189681b2a36SB. J. Wyman 
190681b2a36SB. J. Wyman     EXPECT_EQ(psu2.isPresent(), false);
1913f1242f3SBrandon Wyman 
1923f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
1938da35c51SBrandon Wyman     // Presence change from missing to present will trigger write to
1948da35c51SBrandon Wyman     // ON_OFF_CONFIG.
1958da35c51SBrandon Wyman     EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, _, _));
196f07bc797SBrandon Wyman     // Presence change from missing to present will trigger in1_input read in
197f07bc797SBrandon Wyman     // an attempt to get CLEAR_FAULTS called.
198f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000));
19985c7bf41SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
2008da35c51SBrandon Wyman     uint16_t statusWordValue = 0;
2018da35c51SBrandon Wyman     uint8_t statusInputValue = 0;
2028da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
2033f1242f3SBrandon Wyman     psu2.analyze();
2043f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
2053f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), false);
2063f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), false);
2073f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
2083f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
20985c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasCommFault(), false);
210*6710ba2cSBrandon Wyman     EXPECT_EQ(psu2.hasVoutOVFault(), false);
2113f1242f3SBrandon Wyman 
2123f1242f3SBrandon Wyman     // STATUS_WORD input fault/warn
2138da35c51SBrandon Wyman     statusWordValue = (status_word::INPUT_FAULT_WARN);
214f07bc797SBrandon Wyman     // STATUS_INPUT fault bits ... on.
2158da35c51SBrandon Wyman     statusInputValue = 0x38;
216*6710ba2cSBrandon Wyman     // STATUS_MFR, STATUS_CML, and STATUS_VOUT don't care
2178da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue, statusInputValue);
2183f1242f3SBrandon Wyman     psu2.analyze();
2193f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
2203f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), true);
2213f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), true);
2223f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
2233f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
22485c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasCommFault(), false);
225*6710ba2cSBrandon Wyman     EXPECT_EQ(psu2.hasVoutOVFault(), false);
2263f1242f3SBrandon Wyman 
2273f1242f3SBrandon Wyman     // STATUS_WORD INPUT/UV fault.
2283f1242f3SBrandon Wyman     // First need it to return good status, then the fault
2298da35c51SBrandon Wyman     statusWordValue = 0;
2308da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
2313f1242f3SBrandon Wyman     psu2.analyze();
2328da35c51SBrandon Wyman     // Now set fault bits in STATUS_WORD
2338da35c51SBrandon Wyman     statusWordValue =
2348da35c51SBrandon Wyman         (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
2358da35c51SBrandon Wyman     // STATUS_INPUT fault bits ... on.
2368da35c51SBrandon Wyman     statusInputValue = 0x38;
237*6710ba2cSBrandon Wyman     // STATUS_MFR, STATUS_CML, and STATUS_VOUT don't care
2388da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue, statusInputValue);
2393f1242f3SBrandon Wyman     psu2.analyze();
2403f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
2413f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), true);
242f07bc797SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), true);
2433f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
2443f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), true);
24585c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasCommFault(), false);
246*6710ba2cSBrandon Wyman     EXPECT_EQ(psu2.hasVoutOVFault(), false);
2473f1242f3SBrandon Wyman 
2483f1242f3SBrandon Wyman     // STATUS_WORD MFR fault.
249f07bc797SBrandon Wyman     // First need it to return good status, then the fault
2508da35c51SBrandon Wyman     statusWordValue = 0;
2518da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
2523f1242f3SBrandon Wyman     psu2.analyze();
2538da35c51SBrandon Wyman     // Now STATUS_WORD with MFR fault bit on.
2548da35c51SBrandon Wyman     statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
2558da35c51SBrandon Wyman     // STATUS_INPUT fault bits ... don't care.
2568da35c51SBrandon Wyman     statusInputValue = 0;
2578da35c51SBrandon Wyman     // STATUS_MFR bits on.
2588da35c51SBrandon Wyman     uint8_t statusMFRValue = 0xFF;
259*6710ba2cSBrandon Wyman     // STATUS_CML and STATUS_VOUT don't care
2608da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue, statusInputValue,
2618da35c51SBrandon Wyman                          statusMFRValue);
2623f1242f3SBrandon Wyman     psu2.analyze();
2633f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
2643f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), true);
2653f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), false);
2663f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), true);
2673f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
26885c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasCommFault(), false);
269*6710ba2cSBrandon Wyman     EXPECT_EQ(psu2.hasVoutOVFault(), false);
2703f1242f3SBrandon Wyman 
2713f1242f3SBrandon Wyman     // Ignore Temperature fault.
272f07bc797SBrandon Wyman     // First STATUS_WORD with no bits set, then with temperature fault.
2738da35c51SBrandon Wyman     statusWordValue = 0;
2748da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
2753f1242f3SBrandon Wyman     psu2.analyze();
2768da35c51SBrandon Wyman     // STATUS_WORD with temperature fault bit on.
2778da35c51SBrandon Wyman     statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
278*6710ba2cSBrandon Wyman     // STATUS_INPUT, STATUS_MFR, STATUS_CML, and STATUS_VOUT fault bits ...
279*6710ba2cSBrandon Wyman     // don't care.
2808da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
2813f1242f3SBrandon Wyman     psu2.analyze();
2823f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
2833f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), false);
2843f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), false);
2853f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
2863f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
28785c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasCommFault(), false);
288*6710ba2cSBrandon Wyman     EXPECT_EQ(psu2.hasVoutOVFault(), false);
28985c7bf41SBrandon Wyman 
29085c7bf41SBrandon Wyman     // CML fault
29185c7bf41SBrandon Wyman     // First STATUS_WORD wit no bits set, then with CML fault.
2928da35c51SBrandon Wyman     statusWordValue = 0;
2938da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
29485c7bf41SBrandon Wyman     psu2.analyze();
2958da35c51SBrandon Wyman     // STATUS_WORD with CML fault bit on.
2968da35c51SBrandon Wyman     statusWordValue = (status_word::CML_FAULT);
2978da35c51SBrandon Wyman     // STATUS_INPUT fault bits ... don't care.
2988da35c51SBrandon Wyman     statusInputValue = 0;
2998da35c51SBrandon Wyman     // STATUS_MFR don't care
3008da35c51SBrandon Wyman     statusMFRValue = 0;
30185c7bf41SBrandon Wyman     // Turn on STATUS_CML fault bit(s)
3028da35c51SBrandon Wyman     uint8_t statusCMLValue = 0xFF;
303*6710ba2cSBrandon Wyman     // STATUS_VOUT don't care
3048da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue, statusInputValue,
3058da35c51SBrandon Wyman                          statusMFRValue, statusCMLValue);
30685c7bf41SBrandon Wyman     psu2.analyze();
30785c7bf41SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
30885c7bf41SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), true);
30985c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), false);
31085c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
31185c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
31285c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasCommFault(), true);
313*6710ba2cSBrandon Wyman     EXPECT_EQ(psu2.hasVoutOVFault(), false);
314*6710ba2cSBrandon Wyman 
315*6710ba2cSBrandon Wyman     // VOUT_OV_FAULT fault
316*6710ba2cSBrandon Wyman     // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
317*6710ba2cSBrandon Wyman     statusWordValue = 0;
318*6710ba2cSBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
319*6710ba2cSBrandon Wyman     psu2.analyze();
320*6710ba2cSBrandon Wyman     // STATUS_WORD with VOUT/VOUT_OV fault.
321*6710ba2cSBrandon Wyman     statusWordValue =
322*6710ba2cSBrandon Wyman         ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
323*6710ba2cSBrandon Wyman     // STATUS_INPUT fault bits ... don't care.
324*6710ba2cSBrandon Wyman     statusInputValue = 0;
325*6710ba2cSBrandon Wyman     // STATUS_MFR don't care
326*6710ba2cSBrandon Wyman     statusMFRValue = 0;
327*6710ba2cSBrandon Wyman     // STATUS_CML don't care
328*6710ba2cSBrandon Wyman     statusCMLValue = 0;
329*6710ba2cSBrandon Wyman     // Turn on STATUS_VOUT fault bit(s)
330*6710ba2cSBrandon Wyman     uint8_t statusVOUTValue = 0xA0;
331*6710ba2cSBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue, statusInputValue,
332*6710ba2cSBrandon Wyman                          statusMFRValue, statusCMLValue, statusVOUTValue);
333*6710ba2cSBrandon Wyman     psu2.analyze();
334*6710ba2cSBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
335*6710ba2cSBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), true);
336*6710ba2cSBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), false);
337*6710ba2cSBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
338*6710ba2cSBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
339*6710ba2cSBrandon Wyman     EXPECT_EQ(psu2.hasCommFault(), false);
340*6710ba2cSBrandon Wyman     EXPECT_EQ(psu2.hasVoutOVFault(), true);
3413f1242f3SBrandon Wyman 
3423f1242f3SBrandon Wyman     // Ignore fan fault
3438da35c51SBrandon Wyman     // First STATUS_WORD with no bits set, then with fan
3448da35c51SBrandon Wyman     // fault.
3458da35c51SBrandon Wyman     statusWordValue = 0;
3468da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
3473f1242f3SBrandon Wyman     psu2.analyze();
3488da35c51SBrandon Wyman     statusWordValue = (status_word::FAN_FAULT);
349*6710ba2cSBrandon Wyman     // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT: Don't care if
350*6710ba2cSBrandon Wyman     // bits set or not.
3518da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
3523f1242f3SBrandon Wyman     psu2.analyze();
3533f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
3543f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), false);
3553f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), false);
3563f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
3573f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
35885c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasCommFault(), false);
359*6710ba2cSBrandon Wyman     EXPECT_EQ(psu2.hasVoutOVFault(), false);
3603f1242f3SBrandon Wyman 
3613f1242f3SBrandon Wyman     // TODO: ReadFailure
3623f1242f3SBrandon Wyman }
3633f1242f3SBrandon Wyman 
36459a35793SBrandon Wyman TEST_F(PowerSupplyTests, OnOffConfig)
36559a35793SBrandon Wyman {
36659a35793SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
36759a35793SBrandon Wyman     uint8_t data = 0x15;
36859a35793SBrandon Wyman 
36959a35793SBrandon Wyman     // Test where PSU is NOT present
37059a35793SBrandon Wyman     try
37159a35793SBrandon Wyman     {
372681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
373681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
374681b2a36SB. J. Wyman 
3753ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
3763ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
377681b2a36SB. J. Wyman         ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
37859a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
379681b2a36SB. J. Wyman         // Constructor should set initial presence, default read returns 0.
38059a35793SBrandon Wyman         // If it is not present, I should not be trying to write to it.
38159a35793SBrandon Wyman         EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
38259a35793SBrandon Wyman         psu.onOffConfig(data);
38359a35793SBrandon Wyman     }
38459a35793SBrandon Wyman     catch (...)
3850c9a33d6SAdriana Kobylak     {}
38659a35793SBrandon Wyman 
38759a35793SBrandon Wyman     // Test where PSU is present
38859a35793SBrandon Wyman     try
38959a35793SBrandon Wyman     {
390681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
391681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
3923ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
3933ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
394681b2a36SB. J. Wyman         ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1));
39559a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
396681b2a36SB. J. Wyman         // TODO: expect setPresence call?
397681b2a36SB. J. Wyman         // updatePresence() private function reads gpio, called by analyze().
398681b2a36SB. J. Wyman         psu.analyze();
39959a35793SBrandon Wyman         // TODO: ???should I check the filename?
40059a35793SBrandon Wyman         EXPECT_CALL(mockPMBus,
40159a35793SBrandon Wyman                     writeBinary(_, ElementsAre(0x15), Type::HwmonDeviceDebug))
40259a35793SBrandon Wyman             .Times(1);
40359a35793SBrandon Wyman         psu.onOffConfig(data);
40459a35793SBrandon Wyman     }
40559a35793SBrandon Wyman     catch (...)
4060c9a33d6SAdriana Kobylak     {}
40759a35793SBrandon Wyman }
40859a35793SBrandon Wyman 
4093f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, ClearFaults)
4103f1242f3SBrandon Wyman {
4113f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
412681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName};
4133ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
4143ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
415681b2a36SB. J. Wyman     // GPIO read return 1 to indicate present.
416681b2a36SB. J. Wyman     ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1));
417681b2a36SB. J. Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
4188da35c51SBrandon Wyman     // Presence change from missing to present will trigger in1_input read in
4198da35c51SBrandon Wyman     // an attempt to get CLEAR_FAULTS called.
4208da35c51SBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000));
4218da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
4228da35c51SBrandon Wyman     uint16_t statusWordValue = 0;
4238da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
424681b2a36SB. J. Wyman     psu.analyze();
4253f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
4263f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
4273f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
4283f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
4293f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
43085c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
431*6710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
432f07bc797SBrandon Wyman     // STATUS_WORD with fault bits galore!
4338da35c51SBrandon Wyman     statusWordValue = 0xFFFF;
434f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
4358da35c51SBrandon Wyman     uint8_t statusInputValue = 0xFF;
436f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
4378da35c51SBrandon Wyman     uint8_t statusMFRValue = 0xFF;
43885c7bf41SBrandon Wyman     // STATUS_CML with bits on.
4398da35c51SBrandon Wyman     uint8_t statusCMLValue = 0xFF;
440*6710ba2cSBrandon Wyman     // STATUS_VOUT with bits on.
441*6710ba2cSBrandon Wyman     uint8_t statusVOUTValue = 0xFF;
4428da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue, statusInputValue,
443*6710ba2cSBrandon Wyman                          statusMFRValue, statusCMLValue, statusVOUTValue);
4443f1242f3SBrandon Wyman     psu.analyze();
4453f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
4463f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
4473f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), true);
4483f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
4493f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), true);
45085c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), true);
451*6710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
4523c208464SBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_input", _))
4533c208464SBrandon Wyman         .Times(1)
4543c208464SBrandon Wyman         .WillOnce(Return(209000));
4553f1242f3SBrandon Wyman     psu.clearFaults();
4563f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
4573f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
4583f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
4593f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
4603f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
46185c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
462*6710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
463681b2a36SB. J. Wyman 
464681b2a36SB. J. Wyman     // TODO: Faults clear on missing/present?
4653f1242f3SBrandon Wyman }
4663f1242f3SBrandon Wyman 
4673f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, UpdateInventory)
4683f1242f3SBrandon Wyman {
4693f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
4701d7a7df8SBrandon Wyman 
4711d7a7df8SBrandon Wyman     try
4721d7a7df8SBrandon Wyman     {
473681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
4741d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
4751d7a7df8SBrandon Wyman         // If it is not present, I should not be trying to read a string
4761d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
4771d7a7df8SBrandon Wyman         psu.updateInventory();
4781d7a7df8SBrandon Wyman     }
4791d7a7df8SBrandon Wyman     catch (...)
4801d7a7df8SBrandon Wyman     {
4811d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
4821d7a7df8SBrandon Wyman     }
4831d7a7df8SBrandon Wyman 
4841d7a7df8SBrandon Wyman     try
4851d7a7df8SBrandon Wyman     {
486681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName};
4873ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
4883ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
489681b2a36SB. J. Wyman         // GPIO read return 1 to indicate present.
490681b2a36SB. J. Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
491681b2a36SB. J. Wyman         psu.analyze();
4921d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
4931d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
4943f1242f3SBrandon Wyman         psu.updateInventory();
4951d7a7df8SBrandon Wyman 
4963c530fbdSBrandon Wyman #if IBM_VPD
4971d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _))
4981d7a7df8SBrandon Wyman             .WillOnce(Return("CCIN"))
4991d7a7df8SBrandon Wyman             .WillOnce(Return("PN3456"))
5001d7a7df8SBrandon Wyman             .WillOnce(Return("FN3456"))
5011d7a7df8SBrandon Wyman             .WillOnce(Return("HEADER"))
5021d7a7df8SBrandon Wyman             .WillOnce(Return("SN3456"))
5031d7a7df8SBrandon Wyman             .WillOnce(Return("FW3456"));
5043c530fbdSBrandon Wyman #endif
5051d7a7df8SBrandon Wyman         psu.updateInventory();
5061d7a7df8SBrandon Wyman         // TODO: D-Bus mocking to verify values stored on D-Bus (???)
5071d7a7df8SBrandon Wyman     }
5081d7a7df8SBrandon Wyman     catch (...)
5091d7a7df8SBrandon Wyman     {
5101d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
5111d7a7df8SBrandon Wyman     }
5123f1242f3SBrandon Wyman }
5133f1242f3SBrandon Wyman 
5143f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsPresent)
5153f1242f3SBrandon Wyman {
5163f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
517681b2a36SB. J. Wyman 
518681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
5193ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
5203ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
5213f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), false);
5223f1242f3SBrandon Wyman 
523681b2a36SB. J. Wyman     // Change GPIO read to return 1 to indicate present.
524681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
525681b2a36SB. J. Wyman     psu.analyze();
526681b2a36SB. J. Wyman     EXPECT_EQ(psu.isPresent(), true);
5273f1242f3SBrandon Wyman }
5283f1242f3SBrandon Wyman 
5293f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsFaulted)
5303f1242f3SBrandon Wyman {
5313f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
532681b2a36SB. J. Wyman 
533681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName};
5343ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
5353ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
536681b2a36SB. J. Wyman     // Always return 1 to indicate present.
537681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
538681b2a36SB. J. Wyman     psu.analyze();
5393f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
5403f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
541f07bc797SBrandon Wyman     // STATUS_WORD with fault bits on.
5428da35c51SBrandon Wyman     uint16_t statusWordValue = 0xFFFF;
543f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
5448da35c51SBrandon Wyman     uint8_t statusInputValue = 0xFF;
545f07bc797SBrandon Wyman     // STATUS_MFR_SPECIFIC with faults bits on.
5468da35c51SBrandon Wyman     uint8_t statusMFRValue = 0xFF;
54785c7bf41SBrandon Wyman     // STATUS_CML with faults bits on.
5488da35c51SBrandon Wyman     uint8_t statusCMLValue = 0xFF;
549*6710ba2cSBrandon Wyman     // STATUS_VOUT with fault bits on.
550*6710ba2cSBrandon Wyman     uint8_t statusVOUTValue = 0xFF;
5518da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue, statusInputValue,
552*6710ba2cSBrandon Wyman                          statusMFRValue, statusCMLValue, statusVOUTValue);
5533f1242f3SBrandon Wyman     psu.analyze();
5543f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
5553f1242f3SBrandon Wyman }
5563f1242f3SBrandon Wyman 
5573f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasInputFault)
5583f1242f3SBrandon Wyman {
5593f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
560681b2a36SB. J. Wyman 
561681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
5623ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
5633ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
564681b2a36SB. J. Wyman     // Always return 1 to indicate present.
565681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
566681b2a36SB. J. Wyman     psu.analyze();
5673f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
5683f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
5698da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
5708da35c51SBrandon Wyman     uint16_t statusWordValue = 0;
5718da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
5723f1242f3SBrandon Wyman     psu.analyze();
5733f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
574f07bc797SBrandon Wyman     // STATUS_WORD with input fault/warn on.
5758da35c51SBrandon Wyman     statusWordValue = (status_word::INPUT_FAULT_WARN);
576f07bc797SBrandon Wyman     // STATUS_INPUT with an input fault bit on.
5778da35c51SBrandon Wyman     uint8_t statusInputValue = 0x80;
578*6710ba2cSBrandon Wyman     // STATUS_MFR, STATUS_CML, and STATUS_VOUT don't care.
5798da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue, statusInputValue);
5803f1242f3SBrandon Wyman     psu.analyze();
5813f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), true);
582f07bc797SBrandon Wyman     // STATUS_WORD with no bits on.
5838da35c51SBrandon Wyman     statusWordValue = 0;
5848da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
5853f1242f3SBrandon Wyman     psu.analyze();
5863f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
5873f1242f3SBrandon Wyman }
5883f1242f3SBrandon Wyman 
5893f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasMFRFault)
5903f1242f3SBrandon Wyman {
5913f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
592681b2a36SB. J. Wyman 
593681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
5943ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
5953ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
596681b2a36SB. J. Wyman     // Always return 1 to indicate present.
597681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
598681b2a36SB. J. Wyman     psu.analyze();
5993f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
6003f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
601f07bc797SBrandon Wyman     // First return STATUS_WORD with no bits on.
6028da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
6038da35c51SBrandon Wyman     uint16_t statusWordValue = 0;
6048da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
6053f1242f3SBrandon Wyman     psu.analyze();
6063f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
607f07bc797SBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
6088da35c51SBrandon Wyman     statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
609f07bc797SBrandon Wyman     // STATUS_INPUT don't care
6108da35c51SBrandon Wyman     uint8_t statusInputValue = 0;
611f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
6128da35c51SBrandon Wyman     uint8_t statusMFRValue = 0xFF;
613*6710ba2cSBrandon Wyman     // STATUS_CML and STATUS_VOUT don't care.
6148da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue, statusInputValue,
6158da35c51SBrandon Wyman                          statusMFRValue);
6163f1242f3SBrandon Wyman     psu.analyze();
6173f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
618f07bc797SBrandon Wyman     // Back to no bits on in STATUS_WORD
6198da35c51SBrandon Wyman     statusWordValue = 0;
6208da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
6213f1242f3SBrandon Wyman     psu.analyze();
6223f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
6233f1242f3SBrandon Wyman }
6243f1242f3SBrandon Wyman 
6253f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasVINUVFault)
6263f1242f3SBrandon Wyman {
6273f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
628681b2a36SB. J. Wyman 
629681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
6303ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
6313ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
632681b2a36SB. J. Wyman     // Always return 1 to indicate present.
633681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
634681b2a36SB. J. Wyman     psu.analyze();
6353f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
6363f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
6378da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
6388da35c51SBrandon Wyman     uint16_t statusWordValue = 0;
6398da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
6403f1242f3SBrandon Wyman     psu.analyze();
6413f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
642f07bc797SBrandon Wyman     // Turn fault on.
6438da35c51SBrandon Wyman     statusWordValue = (status_word::VIN_UV_FAULT);
64485c7bf41SBrandon Wyman     // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
64585c7bf41SBrandon Wyman     // Figure 16, and assume bits on in STATUS_INPUT.
6468da35c51SBrandon Wyman     uint8_t statusInputValue = 0x18;
647*6710ba2cSBrandon Wyman     // STATUS_MFR, STATUS_CML, and STATUS_VOUT don't care.
6488da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue, statusInputValue);
6493f1242f3SBrandon Wyman     psu.analyze();
6503f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), true);
651f07bc797SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
6528da35c51SBrandon Wyman     statusWordValue = 0;
6538da35c51SBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
6543f1242f3SBrandon Wyman     psu.analyze();
6553f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
6563f1242f3SBrandon Wyman }
657*6710ba2cSBrandon Wyman 
658*6710ba2cSBrandon Wyman TEST_F(PowerSupplyTests, HasVoutOVFault)
659*6710ba2cSBrandon Wyman {
660*6710ba2cSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
661*6710ba2cSBrandon Wyman 
662*6710ba2cSBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName};
663*6710ba2cSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
664*6710ba2cSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
665*6710ba2cSBrandon Wyman     // Always return 1 to indicate present.
666*6710ba2cSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
667*6710ba2cSBrandon Wyman     psu.analyze();
668*6710ba2cSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
669*6710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
670*6710ba2cSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
671*6710ba2cSBrandon Wyman     uint16_t statusWordValue = 0;
672*6710ba2cSBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
673*6710ba2cSBrandon Wyman     psu.analyze();
674*6710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
675*6710ba2cSBrandon Wyman     // Turn fault on.
676*6710ba2cSBrandon Wyman     statusWordValue = (status_word::VOUT_OV_FAULT);
677*6710ba2cSBrandon Wyman     // STATUS_INPUT don't care.
678*6710ba2cSBrandon Wyman     uint8_t statusInputValue = 0;
679*6710ba2cSBrandon Wyman     // STATUS_MFR don't care.
680*6710ba2cSBrandon Wyman     uint8_t statusMFRValue = 0;
681*6710ba2cSBrandon Wyman     // STATUS_CML don't care.
682*6710ba2cSBrandon Wyman     uint8_t statusCMLValue = 0;
683*6710ba2cSBrandon Wyman     // STATUS_VOUT fault bit(s)
684*6710ba2cSBrandon Wyman     uint8_t statusVOUTValue = 0x80;
685*6710ba2cSBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue, statusInputValue,
686*6710ba2cSBrandon Wyman                          statusMFRValue, statusCMLValue, statusVOUTValue);
687*6710ba2cSBrandon Wyman     psu.analyze();
688*6710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
689*6710ba2cSBrandon Wyman     // Back to no fault bits on in STATUS_WORD
690*6710ba2cSBrandon Wyman     statusWordValue = 0;
691*6710ba2cSBrandon Wyman     setPMBusExpectations(mockPMBus, statusWordValue);
692*6710ba2cSBrandon Wyman     psu.analyze();
693*6710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
694*6710ba2cSBrandon Wyman }
695