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