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 
253f1242f3SBrandon Wyman class PowerSupplyTests : public ::testing::Test
263f1242f3SBrandon Wyman {
273f1242f3SBrandon Wyman   public:
283f1242f3SBrandon Wyman     PowerSupplyTests() :
293f1242f3SBrandon Wyman         mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
303f1242f3SBrandon Wyman     {
313f1242f3SBrandon Wyman         ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
323f1242f3SBrandon Wyman     }
333f1242f3SBrandon Wyman 
343f1242f3SBrandon Wyman     ~PowerSupplyTests() override
353f1242f3SBrandon Wyman     {
363f1242f3SBrandon Wyman         freeUtils();
373f1242f3SBrandon Wyman     }
383f1242f3SBrandon Wyman 
393f1242f3SBrandon Wyman     const MockedUtil& mockedUtil;
403f1242f3SBrandon Wyman };
413f1242f3SBrandon Wyman 
423f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Constructor)
433f1242f3SBrandon Wyman {
443f1242f3SBrandon Wyman     /**
453f1242f3SBrandon Wyman      * @param[in] invpath - String for inventory path to use
463f1242f3SBrandon Wyman      * @param[in] i2cbus - The bus number this power supply is on
473f1242f3SBrandon Wyman      * @param[in] i2caddr - The 16-bit I2C address of the power supply
48681b2a36SB. J. Wyman      * @param[in] gpioLineName - The string for the gpio-line-name to read for
49681b2a36SB. J. Wyman      * presence.
50681b2a36SB. J. Wyman      * @param[in] bindDelay - Time in milliseconds to delay binding the device
51681b2a36SB. J. Wyman      * driver after seeing the presence line go active.
523f1242f3SBrandon Wyman      */
533f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
541d7a7df8SBrandon Wyman 
551d7a7df8SBrandon Wyman     // Try where inventory path is empty, constructor should fail.
561d7a7df8SBrandon Wyman     try
571d7a7df8SBrandon Wyman     {
58681b2a36SB. J. Wyman         auto psu =
59681b2a36SB. J. Wyman             std::make_unique<PowerSupply>(bus, "", 3, 0x68, PSUGPIOLineName);
601d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have reached this line.";
611d7a7df8SBrandon Wyman     }
621d7a7df8SBrandon Wyman     catch (const std::invalid_argument& e)
631d7a7df8SBrandon Wyman     {
641d7a7df8SBrandon Wyman         EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
651d7a7df8SBrandon Wyman     }
661d7a7df8SBrandon Wyman     catch (...)
671d7a7df8SBrandon Wyman     {
681d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
691d7a7df8SBrandon Wyman     }
701d7a7df8SBrandon Wyman 
71681b2a36SB. J. Wyman     // TODO: Try invalid i2c address?
72681b2a36SB. J. Wyman 
73681b2a36SB. J. Wyman     // Try where gpioLineName is empty.
741d7a7df8SBrandon Wyman     try
751d7a7df8SBrandon Wyman     {
761d7a7df8SBrandon Wyman         auto psu =
77681b2a36SB. J. Wyman             std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, "");
78681b2a36SB. J. Wyman         ADD_FAILURE()
79681b2a36SB. J. Wyman             << "Should not have reached this line. Invalid gpioLineName.";
80681b2a36SB. J. Wyman     }
81681b2a36SB. J. Wyman     catch (const std::invalid_argument& e)
82681b2a36SB. J. Wyman     {
83681b2a36SB. J. Wyman         EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
84681b2a36SB. J. Wyman     }
85681b2a36SB. J. Wyman     catch (...)
86681b2a36SB. J. Wyman     {
87681b2a36SB. J. Wyman         ADD_FAILURE() << "Should not have caught exception.";
88681b2a36SB. J. Wyman     }
89681b2a36SB. J. Wyman 
90681b2a36SB. J. Wyman     // Test with valid arguments
91681b2a36SB. J. Wyman     // NOT using D-Bus inventory path for presence.
92681b2a36SB. J. Wyman     try
93681b2a36SB. J. Wyman     {
94681b2a36SB. J. Wyman         auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
95681b2a36SB. J. Wyman                                                  PSUGPIOLineName);
963f1242f3SBrandon Wyman 
973f1242f3SBrandon Wyman         EXPECT_EQ(psu->isPresent(), false);
983f1242f3SBrandon Wyman         EXPECT_EQ(psu->isFaulted(), false);
993f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasInputFault(), false);
1003f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasMFRFault(), false);
1013f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasVINUVFault(), false);
1023f1242f3SBrandon Wyman     }
1031d7a7df8SBrandon Wyman     catch (...)
1041d7a7df8SBrandon Wyman     {
1051d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
1061d7a7df8SBrandon Wyman     }
107681b2a36SB. J. Wyman 
108681b2a36SB. J. Wyman     // Test with valid arguments
109681b2a36SB. J. Wyman     // TODO: Using D-Bus inventory path for presence.
110681b2a36SB. J. Wyman     try
111681b2a36SB. J. Wyman     {
112681b2a36SB. J. Wyman         // FIXME: How do I get that presenceGPIO.read() in the startup to throw
113681b2a36SB. J. Wyman         // an exception?
114681b2a36SB. J. Wyman 
115681b2a36SB. J. Wyman         // EXPECT_CALL(mockedUtil, getPresence(_,
116681b2a36SB. J. Wyman         // StrEq(PSUInventoryPath)))
117681b2a36SB. J. Wyman         //    .Times(1);
118681b2a36SB. J. Wyman     }
119681b2a36SB. J. Wyman     catch (...)
120681b2a36SB. J. Wyman     {
121681b2a36SB. J. Wyman         ADD_FAILURE() << "Should not have caught exception.";
122681b2a36SB. J. Wyman     }
1231d7a7df8SBrandon Wyman }
1243f1242f3SBrandon Wyman 
1253f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Analyze)
1263f1242f3SBrandon Wyman {
1273f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1283f1242f3SBrandon Wyman 
129681b2a36SB. J. Wyman     // If I default to reading the GPIO, I will NOT expect a call to
130681b2a36SB. J. Wyman     // getPresence().
131681b2a36SB. J. Wyman 
132681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
1333ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
1343ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
135681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
136681b2a36SB. J. Wyman 
1373f1242f3SBrandon Wyman     psu.analyze();
1383f1242f3SBrandon Wyman     // By default, nothing should change.
1393f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), false);
1403f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
1413f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
1423f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
1433f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
144*85c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
1453f1242f3SBrandon Wyman 
146681b2a36SB. J. Wyman     PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
147681b2a36SB. J. Wyman     // In order to get the various faults tested, the power supply needs to
148681b2a36SB. J. Wyman     // be present in order to read from the PMBus device(s).
1493ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO2 =
1503ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
151681b2a36SB. J. Wyman     ON_CALL(*mockPresenceGPIO2, read()).WillByDefault(Return(1));
152681b2a36SB. J. Wyman 
153681b2a36SB. J. Wyman     EXPECT_EQ(psu2.isPresent(), false);
1543f1242f3SBrandon Wyman 
1553f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
156f07bc797SBrandon Wyman     // Presence change from missing to present will trigger in1_input read in
157f07bc797SBrandon Wyman     // an attempt to get CLEAR_FAULTS called.
158f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000));
159*85c7bf41SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
160f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
161f07bc797SBrandon Wyman         .Times(1)
162f07bc797SBrandon Wyman         .WillOnce(Return(0x0000));
1633f1242f3SBrandon Wyman     psu2.analyze();
1643f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
1653f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), false);
1663f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), false);
1673f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
1683f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
169*85c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasCommFault(), false);
1703f1242f3SBrandon Wyman 
1713f1242f3SBrandon Wyman     // STATUS_WORD input fault/warn
172f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
173f07bc797SBrandon Wyman         .Times(1)
174f07bc797SBrandon Wyman         .WillOnce(Return(status_word::INPUT_FAULT_WARN));
175f07bc797SBrandon Wyman     // Due to the fault bit on in STATUS_WORD, there will also be a read of
176*85c7bf41SBrandon Wyman     // STATUS_INPUT, STATUS_MFR, and STATUS_CML, so there should be 4 reads
177*85c7bf41SBrandon Wyman     // total expected.
178f07bc797SBrandon Wyman     // STATUS_INPUT fault bits ... on.
179f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
180f07bc797SBrandon Wyman         .Times(1)
181f07bc797SBrandon Wyman         .WillOnce(Return(0x38));
182f07bc797SBrandon Wyman     // STATUS_MFR don't care
183f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0));
184*85c7bf41SBrandon Wyman     // STATUS_CML don't care
185*85c7bf41SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0));
1863f1242f3SBrandon Wyman     psu2.analyze();
1873f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
1883f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), true);
1893f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), true);
1903f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
1913f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
192*85c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasCommFault(), false);
1933f1242f3SBrandon Wyman 
1943f1242f3SBrandon Wyman     // STATUS_WORD INPUT/UV fault.
1953f1242f3SBrandon Wyman     // First need it to return good status, then the fault
196f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
197f07bc797SBrandon Wyman         .Times(2)
1983f1242f3SBrandon Wyman         .WillOnce(Return(0x0000))
199f07bc797SBrandon Wyman         .WillOnce(Return(
200f07bc797SBrandon Wyman             (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT)));
201f07bc797SBrandon Wyman     // STATUS_INPUT fault bits ... on.
202f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
203f07bc797SBrandon Wyman         .Times(1)
204f07bc797SBrandon Wyman         .WillOnce(Return(0x38));
205f07bc797SBrandon Wyman     // STATUS_MFR don't care
206f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0));
207*85c7bf41SBrandon Wyman     // STATUS_CML don't care
208*85c7bf41SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0));
2093f1242f3SBrandon Wyman     psu2.analyze();
2103f1242f3SBrandon Wyman     psu2.analyze();
2113f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
2123f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), true);
213f07bc797SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), true);
2143f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
2153f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), true);
216*85c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasCommFault(), false);
2173f1242f3SBrandon Wyman 
2183f1242f3SBrandon Wyman     // STATUS_WORD MFR fault.
219f07bc797SBrandon Wyman     // First need it to return good status, then the fault
220f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
221f07bc797SBrandon Wyman         .Times(2)
2223f1242f3SBrandon Wyman         .WillOnce(Return(0x0000))
223f07bc797SBrandon Wyman         .WillOnce(Return(status_word::MFR_SPECIFIC_FAULT));
224f07bc797SBrandon Wyman     // STATUS_INPUT fault bits ... don't care.
225f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
226f07bc797SBrandon Wyman         .Times(1)
227f07bc797SBrandon Wyman         .WillOnce(Return(0x00));
228f07bc797SBrandon Wyman     // STATUS_MFR bits on.
229f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
230*85c7bf41SBrandon Wyman     // STATUS_CML don't care
231*85c7bf41SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0));
2323f1242f3SBrandon Wyman     psu2.analyze();
2333f1242f3SBrandon Wyman     psu2.analyze();
2343f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
2353f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), true);
2363f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), false);
2373f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), true);
2383f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
239*85c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasCommFault(), false);
2403f1242f3SBrandon Wyman 
2413f1242f3SBrandon Wyman     // Ignore Temperature fault.
242f07bc797SBrandon Wyman     // First STATUS_WORD with no bits set, then with temperature fault.
243f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
244f07bc797SBrandon Wyman         .Times(2)
2453f1242f3SBrandon Wyman         .WillOnce(Return(0x0000))
246f07bc797SBrandon Wyman         .WillOnce(Return(status_word::TEMPERATURE_FAULT_WARN));
247*85c7bf41SBrandon Wyman     // If the STATUS_WORD has bits on, STATUS_MFR_SPECIFIC, STATUS_INPUT, and
248*85c7bf41SBrandon Wyman     // STATUS_CML will also be read.
249f07bc797SBrandon Wyman     // STATUS_INPUT fault bits ... don't care.
250f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
251f07bc797SBrandon Wyman         .Times(1)
252f07bc797SBrandon Wyman         .WillOnce(Return(0x00));
253f07bc797SBrandon Wyman     // STATUS_MFR don't care
254f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0));
255*85c7bf41SBrandon Wyman     // STATUS_CML don't care
256*85c7bf41SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0));
2573f1242f3SBrandon Wyman     psu2.analyze();
2583f1242f3SBrandon Wyman     psu2.analyze();
2593f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
2603f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), false);
2613f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), false);
2623f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
2633f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
264*85c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasCommFault(), false);
265*85c7bf41SBrandon Wyman 
266*85c7bf41SBrandon Wyman     // CML fault
267*85c7bf41SBrandon Wyman     // First STATUS_WORD wit no bits set, then with CML fault.
268*85c7bf41SBrandon Wyman     // STATUS_WORD with CML fault bit on.
269*85c7bf41SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
270*85c7bf41SBrandon Wyman         .Times(2)
271*85c7bf41SBrandon Wyman         .WillOnce(Return(0x0000))
272*85c7bf41SBrandon Wyman         .WillOnce(Return(status_word::CML_FAULT));
273*85c7bf41SBrandon Wyman     psu2.analyze();
274*85c7bf41SBrandon Wyman     // If the STATUS_WORD has bits on, STATUS_MFR_SPECIFIC, STATUS_INPUT, and
275*85c7bf41SBrandon Wyman     // STATUS_CML will also be read.
276*85c7bf41SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
277*85c7bf41SBrandon Wyman         .Times(1)
278*85c7bf41SBrandon Wyman         .WillOnce(Return(0x00));
279*85c7bf41SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0x00));
280*85c7bf41SBrandon Wyman     // Turn on STATUS_CML fault bit(s)
281*85c7bf41SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0xFF));
282*85c7bf41SBrandon Wyman     psu2.analyze();
283*85c7bf41SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
284*85c7bf41SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), true);
285*85c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), false);
286*85c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
287*85c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
288*85c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasCommFault(), true);
2893f1242f3SBrandon Wyman 
2903f1242f3SBrandon Wyman     // Ignore fan fault
291f07bc797SBrandon Wyman     // First STATUS_WORD with no bits set, then with fan fault.
292f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
293f07bc797SBrandon Wyman         .Times(2)
2943f1242f3SBrandon Wyman         .WillOnce(Return(0x0000))
295f07bc797SBrandon Wyman         .WillOnce(Return(status_word::FAN_FAULT));
296*85c7bf41SBrandon Wyman     // If the STATUS_WORD has bits on, STATUS_MFR_SPECIFIC, STATUS_INPUT, and
297*85c7bf41SBrandon Wyman     // STATUS_CML will also be read.
298f07bc797SBrandon Wyman     // Don't care if bits set or not.
299f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
300f07bc797SBrandon Wyman         .Times(1)
301f07bc797SBrandon Wyman         .WillOnce(Return(0x00));
302f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0));
303*85c7bf41SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0));
3043f1242f3SBrandon Wyman     psu2.analyze();
3053f1242f3SBrandon Wyman     psu2.analyze();
3063f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
3073f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), false);
3083f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), false);
3093f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
3103f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
311*85c7bf41SBrandon Wyman     EXPECT_EQ(psu2.hasCommFault(), false);
3123f1242f3SBrandon Wyman 
3133f1242f3SBrandon Wyman     // TODO: ReadFailure
3143f1242f3SBrandon Wyman }
3153f1242f3SBrandon Wyman 
31659a35793SBrandon Wyman TEST_F(PowerSupplyTests, OnOffConfig)
31759a35793SBrandon Wyman {
31859a35793SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
31959a35793SBrandon Wyman     uint8_t data = 0x15;
32059a35793SBrandon Wyman 
32159a35793SBrandon Wyman     // Test where PSU is NOT present
32259a35793SBrandon Wyman     try
32359a35793SBrandon Wyman     {
324681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
325681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
326681b2a36SB. J. Wyman 
3273ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
3283ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
329681b2a36SB. J. Wyman         ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
33059a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
331681b2a36SB. J. Wyman         // Constructor should set initial presence, default read returns 0.
33259a35793SBrandon Wyman         // If it is not present, I should not be trying to write to it.
33359a35793SBrandon Wyman         EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
33459a35793SBrandon Wyman         psu.onOffConfig(data);
33559a35793SBrandon Wyman     }
33659a35793SBrandon Wyman     catch (...)
3370c9a33d6SAdriana Kobylak     {}
33859a35793SBrandon Wyman 
33959a35793SBrandon Wyman     // Test where PSU is present
34059a35793SBrandon Wyman     try
34159a35793SBrandon Wyman     {
342681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
343681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
3443ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
3453ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
346681b2a36SB. J. Wyman         ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1));
34759a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
348681b2a36SB. J. Wyman         // TODO: expect setPresence call?
349681b2a36SB. J. Wyman         // updatePresence() private function reads gpio, called by analyze().
350681b2a36SB. J. Wyman         psu.analyze();
35159a35793SBrandon Wyman         // TODO: ???should I check the filename?
35259a35793SBrandon Wyman         EXPECT_CALL(mockPMBus,
35359a35793SBrandon Wyman                     writeBinary(_, ElementsAre(0x15), Type::HwmonDeviceDebug))
35459a35793SBrandon Wyman             .Times(1);
35559a35793SBrandon Wyman         psu.onOffConfig(data);
35659a35793SBrandon Wyman     }
35759a35793SBrandon Wyman     catch (...)
3580c9a33d6SAdriana Kobylak     {}
35959a35793SBrandon Wyman }
36059a35793SBrandon Wyman 
3613f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, ClearFaults)
3623f1242f3SBrandon Wyman {
3633f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
364681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName};
3653ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
3663ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
367681b2a36SB. J. Wyman     // GPIO read return 1 to indicate present.
368681b2a36SB. J. Wyman     ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1));
369681b2a36SB. J. Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
370f07bc797SBrandon Wyman     ON_CALL(mockPMBus, read(STATUS_WORD, _)).WillByDefault(Return(0));
371681b2a36SB. J. Wyman     psu.analyze();
3723f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
3733f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
3743f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
3753f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
3763f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
377*85c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
378f07bc797SBrandon Wyman     // STATUS_WORD with fault bits galore!
379f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
380f07bc797SBrandon Wyman         .Times(1)
381f07bc797SBrandon Wyman         .WillOnce(Return(0xFFFF));
382*85c7bf41SBrandon Wyman     // If STATUS_WORD has any fault bits on, STATUS_MFR_SPECIFIC, STATUS_INPUT
383*85c7bf41SBrandon Wyman     // and STATUS_CML will be read.
384f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
385f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
386f07bc797SBrandon Wyman         .Times(1)
387f07bc797SBrandon Wyman         .WillOnce(Return(0xFF));
388f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
389f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
390*85c7bf41SBrandon Wyman     // STATUS_CML with bits on.
391*85c7bf41SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0xFF));
3923f1242f3SBrandon Wyman     psu.analyze();
3933f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
3943f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
3953f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), true);
3963f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
3973f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), true);
398*85c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), true);
3993c208464SBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_input", _))
4003c208464SBrandon Wyman         .Times(1)
4013c208464SBrandon Wyman         .WillOnce(Return(209000));
4023f1242f3SBrandon Wyman     psu.clearFaults();
4033f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
4043f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
4053f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
4063f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
4073f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
408*85c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
409681b2a36SB. J. Wyman 
410681b2a36SB. J. Wyman     // TODO: Faults clear on missing/present?
4113f1242f3SBrandon Wyman }
4123f1242f3SBrandon Wyman 
4133f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, UpdateInventory)
4143f1242f3SBrandon Wyman {
4153f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
4161d7a7df8SBrandon Wyman 
4171d7a7df8SBrandon Wyman     try
4181d7a7df8SBrandon Wyman     {
419681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
4201d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
4211d7a7df8SBrandon Wyman         // If it is not present, I should not be trying to read a string
4221d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
4231d7a7df8SBrandon Wyman         psu.updateInventory();
4241d7a7df8SBrandon Wyman     }
4251d7a7df8SBrandon Wyman     catch (...)
4261d7a7df8SBrandon Wyman     {
4271d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
4281d7a7df8SBrandon Wyman     }
4291d7a7df8SBrandon Wyman 
4301d7a7df8SBrandon Wyman     try
4311d7a7df8SBrandon Wyman     {
432681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName};
4333ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
4343ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
435681b2a36SB. J. Wyman         // GPIO read return 1 to indicate present.
436681b2a36SB. J. Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
437681b2a36SB. J. Wyman         psu.analyze();
4381d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
4391d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
4403f1242f3SBrandon Wyman         psu.updateInventory();
4411d7a7df8SBrandon Wyman 
4423c530fbdSBrandon Wyman #if IBM_VPD
4431d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _))
4441d7a7df8SBrandon Wyman             .WillOnce(Return("CCIN"))
4451d7a7df8SBrandon Wyman             .WillOnce(Return("PN3456"))
4461d7a7df8SBrandon Wyman             .WillOnce(Return("FN3456"))
4471d7a7df8SBrandon Wyman             .WillOnce(Return("HEADER"))
4481d7a7df8SBrandon Wyman             .WillOnce(Return("SN3456"))
4491d7a7df8SBrandon Wyman             .WillOnce(Return("FW3456"));
4503c530fbdSBrandon Wyman #endif
4511d7a7df8SBrandon Wyman         psu.updateInventory();
4521d7a7df8SBrandon Wyman         // TODO: D-Bus mocking to verify values stored on D-Bus (???)
4531d7a7df8SBrandon Wyman     }
4541d7a7df8SBrandon Wyman     catch (...)
4551d7a7df8SBrandon Wyman     {
4561d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
4571d7a7df8SBrandon Wyman     }
4583f1242f3SBrandon Wyman }
4593f1242f3SBrandon Wyman 
4603f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsPresent)
4613f1242f3SBrandon Wyman {
4623f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
463681b2a36SB. J. Wyman 
464681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
4653ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
4663ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
4673f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), false);
4683f1242f3SBrandon Wyman 
469681b2a36SB. J. Wyman     // Change GPIO read to return 1 to indicate present.
470681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
471681b2a36SB. J. Wyman     psu.analyze();
472681b2a36SB. J. Wyman     EXPECT_EQ(psu.isPresent(), true);
4733f1242f3SBrandon Wyman }
4743f1242f3SBrandon Wyman 
4753f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsFaulted)
4763f1242f3SBrandon Wyman {
4773f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
478681b2a36SB. J. Wyman 
479681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName};
4803ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
4813ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
482681b2a36SB. J. Wyman     // Always return 1 to indicate present.
483681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
484681b2a36SB. J. Wyman     psu.analyze();
4853f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
4863f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
487f07bc797SBrandon Wyman     // STATUS_WORD with fault bits on.
488f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
489f07bc797SBrandon Wyman         .Times(1)
490f07bc797SBrandon Wyman         .WillOnce(Return(0xFFFF));
491*85c7bf41SBrandon Wyman     // Fault bit(s) on in STATUS_WORD causes read of STATUS_MFR_SPECIFIC,
492*85c7bf41SBrandon Wyman     // STATUS_INPUT, and STATUS_CML.
493f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
494f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
495f07bc797SBrandon Wyman         .Times(1)
496f07bc797SBrandon Wyman         .WillOnce(Return(0xFF));
497f07bc797SBrandon Wyman     // STATUS_MFR_SPECIFIC with faults bits on.
498f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
499*85c7bf41SBrandon Wyman     // STATUS_CML with faults bits on.
500*85c7bf41SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0xFF));
5013f1242f3SBrandon Wyman     psu.analyze();
5023f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
5033f1242f3SBrandon Wyman }
5043f1242f3SBrandon Wyman 
5053f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasInputFault)
5063f1242f3SBrandon Wyman {
5073f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
508681b2a36SB. J. Wyman 
509681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
5103ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
5113ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
512681b2a36SB. J. Wyman     // Always return 1 to indicate present.
513681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
514681b2a36SB. J. Wyman     psu.analyze();
5153f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
5163f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
5173f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
5183f1242f3SBrandon Wyman     psu.analyze();
5193f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
520f07bc797SBrandon Wyman     // STATUS_WORD with input fault/warn on.
521f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
522f07bc797SBrandon Wyman         .Times(1)
523f07bc797SBrandon Wyman         .WillOnce(Return(status_word::INPUT_FAULT_WARN));
524*85c7bf41SBrandon Wyman     // Fault bit(s) on in STATUS_WORD causes read of STATUS_MFR_SPECIFIC,
525*85c7bf41SBrandon Wyman     // STATUS_INPUT, and STATUS_CML.
526f07bc797SBrandon Wyman     // STATUS_INPUT with an input fault bit on.
527f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
528f07bc797SBrandon Wyman         .Times(1)
529f07bc797SBrandon Wyman         .WillOnce(Return(0x80));
530f07bc797SBrandon Wyman     // STATUS_MFR don't care.
531f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0x00));
532*85c7bf41SBrandon Wyman     // STATUS_CML don't care.
533*85c7bf41SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0x00));
5343f1242f3SBrandon Wyman     psu.analyze();
5353f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), true);
536f07bc797SBrandon Wyman     // STATUS_WORD with no bits on.
537f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
538f07bc797SBrandon Wyman         .Times(1)
539f07bc797SBrandon Wyman         .WillOnce(Return(0x0000));
5403f1242f3SBrandon Wyman     psu.analyze();
5413f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
5423f1242f3SBrandon Wyman }
5433f1242f3SBrandon Wyman 
5443f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasMFRFault)
5453f1242f3SBrandon Wyman {
5463f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
547681b2a36SB. J. Wyman 
548681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
5493ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
5503ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
551681b2a36SB. J. Wyman     // Always return 1 to indicate present.
552681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
553681b2a36SB. J. Wyman     psu.analyze();
5543f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
5553f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
556f07bc797SBrandon Wyman     // First return STATUS_WORD with no bits on.
557f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
558f07bc797SBrandon Wyman         .Times(1)
559f07bc797SBrandon Wyman         .WillOnce(Return(0x0000));
5603f1242f3SBrandon Wyman     psu.analyze();
5613f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
562f07bc797SBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
563f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
564f07bc797SBrandon Wyman         .Times(1)
565f07bc797SBrandon Wyman         .WillOnce(Return(status_word::MFR_SPECIFIC_FAULT));
566*85c7bf41SBrandon Wyman     // Fault bit(s) on in STATUS_WORD causes read of STATUS_MFR_SPECIFIC,
567*85c7bf41SBrandon Wyman     // STATUS_INPUT, and STATUS_CML.
568f07bc797SBrandon Wyman     // STATUS_INPUT don't care
569f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
570f07bc797SBrandon Wyman         .Times(1)
571f07bc797SBrandon Wyman         .WillOnce(Return(0x00));
572f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
573f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
574*85c7bf41SBrandon Wyman     // STATUS_CML don't care.
575*85c7bf41SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0x00));
5763f1242f3SBrandon Wyman     psu.analyze();
5773f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
578f07bc797SBrandon Wyman     // Back to no bits on in STATUS_WORD
579f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
580f07bc797SBrandon Wyman         .Times(1)
581f07bc797SBrandon Wyman         .WillOnce(Return(0x0000));
5823f1242f3SBrandon Wyman     psu.analyze();
5833f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
5843f1242f3SBrandon Wyman }
5853f1242f3SBrandon Wyman 
5863f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasVINUVFault)
5873f1242f3SBrandon Wyman {
5883f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
589681b2a36SB. J. Wyman 
590681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
5913ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
5923ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
593681b2a36SB. J. Wyman     // Always return 1 to indicate present.
594681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
595681b2a36SB. J. Wyman     psu.analyze();
5963f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
5973f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
598f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
599f07bc797SBrandon Wyman         .Times(1)
600f07bc797SBrandon Wyman         .WillOnce(Return(0x0000));
6013f1242f3SBrandon Wyman     psu.analyze();
6023f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
603f07bc797SBrandon Wyman     // Turn fault on.
604f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
605f07bc797SBrandon Wyman         .Times(1)
606f07bc797SBrandon Wyman         .WillOnce(Return(status_word::VIN_UV_FAULT));
607*85c7bf41SBrandon Wyman     // Fault bit(s) on in STATUS_WORD causes read of STATUS_MFR_SPECIFIC,
608*85c7bf41SBrandon Wyman     // STATUS_INPUT, and STATUS_CML.
609*85c7bf41SBrandon Wyman     // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
610*85c7bf41SBrandon Wyman     // Figure 16, and assume bits on in STATUS_INPUT.
611f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
612f07bc797SBrandon Wyman         .Times(1)
613f07bc797SBrandon Wyman         .WillOnce(Return(0x18));
614f07bc797SBrandon Wyman     // STATUS_MFR don't care.
615f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0x00));
616*85c7bf41SBrandon Wyman     // STATUS_CML don't care.
617*85c7bf41SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0x00));
618f07bc797SBrandon Wyman 
6193f1242f3SBrandon Wyman     psu.analyze();
6203f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), true);
621f07bc797SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
622f07bc797SBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
623f07bc797SBrandon Wyman         .Times(1)
624f07bc797SBrandon Wyman         .WillOnce(Return(0x0000));
6253f1242f3SBrandon Wyman     psu.analyze();
6263f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
6273f1242f3SBrandon Wyman }
628