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