13f1242f3SBrandon Wyman #include "../power_supply.hpp"
2c3324424SBrandon Wyman #include "../record_manager.hpp"
33f1242f3SBrandon Wyman #include "mock.hpp"
43f1242f3SBrandon Wyman 
53f1242f3SBrandon Wyman #include <xyz/openbmc_project/Common/Device/error.hpp>
63f1242f3SBrandon Wyman #include <xyz/openbmc_project/Common/error.hpp>
73f1242f3SBrandon Wyman 
83f1242f3SBrandon Wyman #include <gmock/gmock.h>
93f1242f3SBrandon Wyman #include <gtest/gtest.h>
103f1242f3SBrandon Wyman 
113f1242f3SBrandon Wyman using namespace phosphor::power::psu;
123f1242f3SBrandon Wyman using namespace phosphor::pmbus;
133f1242f3SBrandon Wyman 
143f1242f3SBrandon Wyman using ::testing::_;
1559a35793SBrandon Wyman using ::testing::Args;
163f1242f3SBrandon Wyman using ::testing::Assign;
173f1242f3SBrandon Wyman using ::testing::DoAll;
1859a35793SBrandon Wyman using ::testing::ElementsAre;
1959a35793SBrandon Wyman using ::testing::NotNull;
203f1242f3SBrandon Wyman using ::testing::Return;
213f1242f3SBrandon Wyman using ::testing::StrEq;
223f1242f3SBrandon Wyman 
233f1242f3SBrandon Wyman static auto PSUInventoryPath = "/xyz/bmc/inv/sys/chassis/board/powersupply0";
24681b2a36SB. J. Wyman static auto PSUGPIOLineName = "presence-ps0";
25*9464c429SGeorge Liu static auto isPowerOn = []() { return true; };
263f1242f3SBrandon Wyman 
27b654c619SBrandon Wyman struct PMBusExpectations
28b654c619SBrandon Wyman {
29b654c619SBrandon Wyman     uint16_t statusWordValue{0x0000};
30b654c619SBrandon Wyman     uint8_t statusInputValue{0x00};
31b654c619SBrandon Wyman     uint8_t statusMFRValue{0x00};
32b654c619SBrandon Wyman     uint8_t statusCMLValue{0x00};
33b654c619SBrandon Wyman     uint8_t statusVOUTValue{0x00};
34b10b3be0SBrandon Wyman     uint8_t statusIOUTValue{0x00};
357ee4d7e4SBrandon Wyman     uint8_t statusFans12Value{0x00};
3696893a46SBrandon Wyman     uint8_t statusTempValue{0x00};
37b654c619SBrandon Wyman };
38b654c619SBrandon Wyman 
398da35c51SBrandon Wyman // Helper function to setup expectations for various STATUS_* commands
40b654c619SBrandon Wyman void setPMBusExpectations(MockedPMBus& mockPMBus,
41b654c619SBrandon Wyman                           const PMBusExpectations& expectations)
428da35c51SBrandon Wyman {
4332453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _, _))
448da35c51SBrandon Wyman         .Times(1)
45b654c619SBrandon Wyman         .WillOnce(Return(expectations.statusWordValue));
468da35c51SBrandon Wyman 
47b654c619SBrandon Wyman     if (expectations.statusWordValue != 0)
488da35c51SBrandon Wyman     {
498da35c51SBrandon Wyman         // If fault bits are on in STATUS_WORD, there will also be a read of
5096893a46SBrandon Wyman         // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and
5196893a46SBrandon Wyman         // STATUS_TEMPERATURE.
5232453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _, _))
538da35c51SBrandon Wyman             .Times(1)
54b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusInputValue));
5532453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_MFR, _, _))
568da35c51SBrandon Wyman             .Times(1)
57b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusMFRValue));
5832453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_CML, _, _))
598da35c51SBrandon Wyman             .Times(1)
60b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusCMLValue));
616710ba2cSBrandon Wyman         // Page will need to be set to 0 to read STATUS_VOUT.
626710ba2cSBrandon Wyman         EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0))
636710ba2cSBrandon Wyman             .Times(1)
646710ba2cSBrandon Wyman             .WillOnce(Return("status0_vout"));
6532453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read("status0_vout", _, _))
666710ba2cSBrandon Wyman             .Times(1)
67b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusVOUTValue));
6832453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _, _))
69b10b3be0SBrandon Wyman             .Times(1)
70b10b3be0SBrandon Wyman             .WillOnce(Return(expectations.statusIOUTValue));
7132453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _, _))
727ee4d7e4SBrandon Wyman             .Times(1)
737ee4d7e4SBrandon Wyman             .WillOnce(Return(expectations.statusFans12Value));
7432453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _, _))
7596893a46SBrandon Wyman             .Times(1)
7696893a46SBrandon Wyman             .WillOnce(Return(expectations.statusTempValue));
778da35c51SBrandon Wyman     }
788da35c51SBrandon Wyman }
798da35c51SBrandon Wyman 
803f1242f3SBrandon Wyman class PowerSupplyTests : public ::testing::Test
813f1242f3SBrandon Wyman {
823f1242f3SBrandon Wyman   public:
833f1242f3SBrandon Wyman     PowerSupplyTests() :
843f1242f3SBrandon Wyman         mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
853f1242f3SBrandon Wyman     {
863f1242f3SBrandon Wyman         ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
873f1242f3SBrandon Wyman     }
883f1242f3SBrandon Wyman 
893f1242f3SBrandon Wyman     ~PowerSupplyTests() override
903f1242f3SBrandon Wyman     {
913f1242f3SBrandon Wyman         freeUtils();
923f1242f3SBrandon Wyman     }
933f1242f3SBrandon Wyman 
943f1242f3SBrandon Wyman     const MockedUtil& mockedUtil;
953f1242f3SBrandon Wyman };
963f1242f3SBrandon Wyman 
97391a0690SBrandon Wyman // Helper function for when a power supply goes from missing to present.
98391a0690SBrandon Wyman void setMissingToPresentExpects(MockedPMBus& pmbus, const MockedUtil& util)
99391a0690SBrandon Wyman {
100391a0690SBrandon Wyman     // Call to analyze() will update to present, that will trigger updating
101391a0690SBrandon Wyman     // to the correct/latest HWMON directory, in case it changes.
102391a0690SBrandon Wyman     EXPECT_CALL(pmbus, findHwmonDir());
103391a0690SBrandon Wyman     // Presence change from missing to present will trigger write to
104391a0690SBrandon Wyman     // ON_OFF_CONFIG.
105391a0690SBrandon Wyman     EXPECT_CALL(pmbus, writeBinary(ON_OFF_CONFIG, _, _));
106391a0690SBrandon Wyman     // Presence change from missing to present will trigger in1_input read
107391a0690SBrandon Wyman     // in an attempt to get CLEAR_FAULTS called.
10882affd94SBrandon Wyman     // This READ_VIN for CLEAR_FAULTS does not check the returned value.
1093225a45cSBrandon Wyman     EXPECT_CALL(pmbus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
1103225a45cSBrandon Wyman     // The call for clearing faults includes clearing VIN_UV fault.
1113225a45cSBrandon Wyman     // The voltage defaults to 0, the first call to analyze should update the
1123225a45cSBrandon Wyman     // voltage to the current reading, triggering clearing VIN_UV fault(s)
1133225a45cSBrandon Wyman     // due to below minimum to within range voltage.
1143225a45cSBrandon Wyman     EXPECT_CALL(pmbus, read("in1_lcrit_alarm", _, _))
11582affd94SBrandon Wyman         .Times(2)
1163225a45cSBrandon Wyman         .WillRepeatedly(Return(1));
117391a0690SBrandon Wyman     // Missing/present call will update Presence in inventory.
118391a0690SBrandon Wyman     EXPECT_CALL(util, setPresence(_, _, true, _));
119391a0690SBrandon Wyman }
120391a0690SBrandon Wyman 
1213f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Constructor)
1223f1242f3SBrandon Wyman {
1233f1242f3SBrandon Wyman     /**
1243f1242f3SBrandon Wyman      * @param[in] invpath - String for inventory path to use
1253f1242f3SBrandon Wyman      * @param[in] i2cbus - The bus number this power supply is on
1263f1242f3SBrandon Wyman      * @param[in] i2caddr - The 16-bit I2C address of the power supply
127681b2a36SB. J. Wyman      * @param[in] gpioLineName - The string for the gpio-line-name to read for
128681b2a36SB. J. Wyman      * presence.
129681b2a36SB. J. Wyman      * @param[in] bindDelay - Time in milliseconds to delay binding the device
130681b2a36SB. J. Wyman      * driver after seeing the presence line go active.
1313f1242f3SBrandon Wyman      */
1323f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1331d7a7df8SBrandon Wyman 
1341d7a7df8SBrandon Wyman     // Try where inventory path is empty, constructor should fail.
1351d7a7df8SBrandon Wyman     try
1361d7a7df8SBrandon Wyman     {
137c3324424SBrandon Wyman         auto psu = std::make_unique<PowerSupply>(bus, "", 3, 0x68, "ibm-cffps",
138*9464c429SGeorge Liu                                                  PSUGPIOLineName, isPowerOn);
1391d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have reached this line.";
1401d7a7df8SBrandon Wyman     }
1411d7a7df8SBrandon Wyman     catch (const std::invalid_argument& e)
1421d7a7df8SBrandon Wyman     {
1431d7a7df8SBrandon Wyman         EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
1441d7a7df8SBrandon Wyman     }
1451d7a7df8SBrandon Wyman     catch (...)
1461d7a7df8SBrandon Wyman     {
1471d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
1481d7a7df8SBrandon Wyman     }
1491d7a7df8SBrandon Wyman 
150681b2a36SB. J. Wyman     // TODO: Try invalid i2c address?
151681b2a36SB. J. Wyman 
152681b2a36SB. J. Wyman     // Try where gpioLineName is empty.
1531d7a7df8SBrandon Wyman     try
1541d7a7df8SBrandon Wyman     {
155c3324424SBrandon Wyman         auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
156*9464c429SGeorge Liu                                                  "ibm-cffps", "", isPowerOn);
157681b2a36SB. J. Wyman         ADD_FAILURE()
158681b2a36SB. J. Wyman             << "Should not have reached this line. Invalid gpioLineName.";
159681b2a36SB. J. Wyman     }
160681b2a36SB. J. Wyman     catch (const std::invalid_argument& e)
161681b2a36SB. J. Wyman     {
162681b2a36SB. J. Wyman         EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
163681b2a36SB. J. Wyman     }
164681b2a36SB. J. Wyman     catch (...)
165681b2a36SB. J. Wyman     {
166681b2a36SB. J. Wyman         ADD_FAILURE() << "Should not have caught exception.";
167681b2a36SB. J. Wyman     }
168681b2a36SB. J. Wyman 
169681b2a36SB. J. Wyman     // Test with valid arguments
170681b2a36SB. J. Wyman     // NOT using D-Bus inventory path for presence.
171681b2a36SB. J. Wyman     try
172681b2a36SB. J. Wyman     {
173681b2a36SB. J. Wyman         auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
174*9464c429SGeorge Liu                                                  "ibm-cffps", PSUGPIOLineName,
175*9464c429SGeorge Liu                                                  isPowerOn);
1763f1242f3SBrandon Wyman 
1773f1242f3SBrandon Wyman         EXPECT_EQ(psu->isPresent(), false);
1783f1242f3SBrandon Wyman         EXPECT_EQ(psu->isFaulted(), false);
1798da35c51SBrandon Wyman         EXPECT_EQ(psu->hasCommFault(), false);
1803f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasInputFault(), false);
1813f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasMFRFault(), false);
1823f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasVINUVFault(), false);
1836710ba2cSBrandon Wyman         EXPECT_EQ(psu->hasVoutOVFault(), false);
184b10b3be0SBrandon Wyman         EXPECT_EQ(psu->hasIoutOCFault(), false);
1852cf46945SBrandon Wyman         EXPECT_EQ(psu->hasVoutUVFault(), false);
1867ee4d7e4SBrandon Wyman         EXPECT_EQ(psu->hasFanFault(), false);
18796893a46SBrandon Wyman         EXPECT_EQ(psu->hasTempFault(), false);
1882916ea52SBrandon Wyman         EXPECT_EQ(psu->hasPgoodFault(), false);
18939ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPSKillFault(), false);
19039ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPS12VcsFault(), false);
19139ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPSCS12VFault(), false);
1923f1242f3SBrandon Wyman     }
1931d7a7df8SBrandon Wyman     catch (...)
1941d7a7df8SBrandon Wyman     {
1951d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
1961d7a7df8SBrandon Wyman     }
197681b2a36SB. J. Wyman 
198681b2a36SB. J. Wyman     // Test with valid arguments
199681b2a36SB. J. Wyman     // TODO: Using D-Bus inventory path for presence.
200681b2a36SB. J. Wyman     try
201681b2a36SB. J. Wyman     {
202681b2a36SB. J. Wyman         // FIXME: How do I get that presenceGPIO.read() in the startup to throw
203681b2a36SB. J. Wyman         // an exception?
204681b2a36SB. J. Wyman 
205681b2a36SB. J. Wyman         // EXPECT_CALL(mockedUtil, getPresence(_,
206681b2a36SB. J. Wyman         // StrEq(PSUInventoryPath)))
207681b2a36SB. J. Wyman         //    .Times(1);
208681b2a36SB. J. Wyman     }
209681b2a36SB. J. Wyman     catch (...)
210681b2a36SB. J. Wyman     {
211681b2a36SB. J. Wyman         ADD_FAILURE() << "Should not have caught exception.";
212681b2a36SB. J. Wyman     }
2131d7a7df8SBrandon Wyman }
2143f1242f3SBrandon Wyman 
2153f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Analyze)
2163f1242f3SBrandon Wyman {
2173f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
2183f1242f3SBrandon Wyman 
219b654c619SBrandon Wyman     {
220681b2a36SB. J. Wyman         // If I default to reading the GPIO, I will NOT expect a call to
221681b2a36SB. J. Wyman         // getPresence().
222681b2a36SB. J. Wyman 
223*9464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 4,        0x69,
224*9464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
2253ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
2263ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
227681b2a36SB. J. Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
228681b2a36SB. J. Wyman 
2293f1242f3SBrandon Wyman         psu.analyze();
2303f1242f3SBrandon Wyman         // By default, nothing should change.
2313f1242f3SBrandon Wyman         EXPECT_EQ(psu.isPresent(), false);
2323f1242f3SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), false);
2333f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), false);
2343f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), false);
2353f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), false);
23685c7bf41SBrandon Wyman         EXPECT_EQ(psu.hasCommFault(), false);
2376710ba2cSBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), false);
238b10b3be0SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), false);
2392cf46945SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), false);
2407ee4d7e4SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), false);
24196893a46SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), false);
2422916ea52SBrandon Wyman         EXPECT_EQ(psu.hasPgoodFault(), false);
24339ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), false);
24439ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), false);
24539ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), false);
246b654c619SBrandon Wyman     }
2473f1242f3SBrandon Wyman 
248*9464c429SGeorge Liu     PowerSupply psu2{bus,         PSUInventoryPath, 5,        0x6a,
249*9464c429SGeorge Liu                      "ibm-cffps", PSUGPIOLineName,  isPowerOn};
250681b2a36SB. J. Wyman     // In order to get the various faults tested, the power supply needs to
251681b2a36SB. J. Wyman     // be present in order to read from the PMBus device(s).
2523ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO2 =
2533ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
25406ca4590SBrandon Wyman     // Always return 1 to indicate present.
25506ca4590SBrandon Wyman     // Each analyze() call will trigger a read of the presence GPIO.
25606ca4590SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1));
257681b2a36SB. J. Wyman     EXPECT_EQ(psu2.isPresent(), false);
2583f1242f3SBrandon Wyman 
2593f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
260391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
261ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
262ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
263ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
264ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
265ae35ac5dSBrandon Wyman         .Times(1)
266ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
267b654c619SBrandon Wyman 
268b654c619SBrandon Wyman     // STATUS_WORD INPUT fault.
269b654c619SBrandon Wyman     {
270b654c619SBrandon Wyman         // Start with STATUS_WORD 0x0000. Powered on, no faults.
271b654c619SBrandon Wyman         // Set expectations for a no fault
272b654c619SBrandon Wyman         PMBusExpectations expectations;
273b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
27482affd94SBrandon Wyman         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
27582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
27682affd94SBrandon Wyman             .Times(1)
27782affd94SBrandon Wyman             .WillOnce(Return("206000"));
2783f1242f3SBrandon Wyman         psu2.analyze();
2793f1242f3SBrandon Wyman         EXPECT_EQ(psu2.isPresent(), true);
2803f1242f3SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
2813f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
2823f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasMFRFault(), false);
2833f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasVINUVFault(), false);
28485c7bf41SBrandon Wyman         EXPECT_EQ(psu2.hasCommFault(), false);
2856710ba2cSBrandon Wyman         EXPECT_EQ(psu2.hasVoutOVFault(), false);
286b10b3be0SBrandon Wyman         EXPECT_EQ(psu2.hasIoutOCFault(), false);
2872cf46945SBrandon Wyman         EXPECT_EQ(psu2.hasVoutUVFault(), false);
2887ee4d7e4SBrandon Wyman         EXPECT_EQ(psu2.hasFanFault(), false);
28996893a46SBrandon Wyman         EXPECT_EQ(psu2.hasTempFault(), false);
2902916ea52SBrandon Wyman         EXPECT_EQ(psu2.hasPgoodFault(), false);
29139ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPSKillFault(), false);
29239ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPS12VcsFault(), false);
29339ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPSCS12VFault(), false);
2943f1242f3SBrandon Wyman 
295b654c619SBrandon Wyman         // Update expectations for STATUS_WORD input fault/warn
29696893a46SBrandon Wyman         // STATUS_INPUT fault bits ... on.
297b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
2983225a45cSBrandon Wyman         // IIN_OC fault.
2993225a45cSBrandon Wyman         expectations.statusInputValue = 0x04;
300c2906f47SBrandon Wyman 
301c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
302c2906f47SBrandon Wyman         {
303b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
30482affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
30582affd94SBrandon Wyman                 .Times(1)
30682affd94SBrandon Wyman                 .WillOnce(Return("207000"));
3073f1242f3SBrandon Wyman             psu2.analyze();
3083f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
309c2906f47SBrandon Wyman             // Should not be faulted until it reaches the deglitch limit.
310c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
311c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
3123f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
3133f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
31485c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
3156710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
316b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
3172cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
3187ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
31996893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
3202916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
32139ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
32239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
32339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
324b654c619SBrandon Wyman         }
325c2906f47SBrandon Wyman     }
326c2906f47SBrandon Wyman 
32732453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
3283225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
3293225a45cSBrandon Wyman         .Times(1)
3303225a45cSBrandon Wyman         .WillOnce(Return(1));
331c2906f47SBrandon Wyman     psu2.clearFaults();
3323f1242f3SBrandon Wyman 
3333f1242f3SBrandon Wyman     // STATUS_WORD INPUT/UV fault.
334b654c619SBrandon Wyman     {
3353f1242f3SBrandon Wyman         // First need it to return good status, then the fault
336b654c619SBrandon Wyman         PMBusExpectations expectations;
337b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
33882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
33982affd94SBrandon Wyman             .Times(1)
34082affd94SBrandon Wyman             .WillOnce(Return("208000"));
3413f1242f3SBrandon Wyman         psu2.analyze();
342c2906f47SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
343c2906f47SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
3448da35c51SBrandon Wyman         // Now set fault bits in STATUS_WORD
345b654c619SBrandon Wyman         expectations.statusWordValue =
3468da35c51SBrandon Wyman             (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
3478da35c51SBrandon Wyman         // STATUS_INPUT fault bits ... on.
3483225a45cSBrandon Wyman         expectations.statusInputValue = 0x18;
349c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
350c2906f47SBrandon Wyman         {
351b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
35282affd94SBrandon Wyman             // Input/UV fault, so voltage should read back low.
35382affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
35482affd94SBrandon Wyman                 .Times(1)
35582affd94SBrandon Wyman                 .WillOnce(Return("19123"));
3563f1242f3SBrandon Wyman             psu2.analyze();
3573f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
358c2906f47SBrandon Wyman             // Only faulted if hit deglitch limit
359c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
360c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
361c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), x >= DEGLITCH_LIMIT);
3623f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
36385c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
3646710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
365b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
3662cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
3677ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
36896893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
3692916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
37039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
37139ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
37239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
373c2906f47SBrandon Wyman         }
37482affd94SBrandon Wyman         // Turning VIN_UV fault off causes clearing of faults, causing read of
37582affd94SBrandon Wyman         // in1_input as an attempt to get CLEAR_FAULTS called.
37682affd94SBrandon Wyman         expectations.statusWordValue = 0;
37782affd94SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
37882affd94SBrandon Wyman         // The call to read the voltage
37982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
38082affd94SBrandon Wyman             .Times(1)
38182affd94SBrandon Wyman             .WillOnce(Return("209000"));
3823225a45cSBrandon Wyman         // The call to clear VIN_UV/Off fault(s)
3833225a45cSBrandon Wyman         EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
38432453e9bSBrandon Wyman             .Times(1)
3853225a45cSBrandon Wyman             .WillOnce(Return(1));
38682affd94SBrandon Wyman         psu2.analyze();
38782affd94SBrandon Wyman         // Should remain present, no longer be faulted, no input fault, no
38882affd94SBrandon Wyman         // VIN_UV fault. Nothing else should change.
38982affd94SBrandon Wyman         EXPECT_EQ(psu2.isPresent(), true);
39082affd94SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
39182affd94SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
39282affd94SBrandon Wyman         EXPECT_EQ(psu2.hasVINUVFault(), false);
393b654c619SBrandon Wyman     }
3943f1242f3SBrandon Wyman 
39532453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
3963225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
3973225a45cSBrandon Wyman         .Times(1)
3983225a45cSBrandon Wyman         .WillOnce(Return(1));
399c2906f47SBrandon Wyman     psu2.clearFaults();
400c2906f47SBrandon Wyman 
4013f1242f3SBrandon Wyman     // STATUS_WORD MFR fault.
402b654c619SBrandon Wyman     {
403f07bc797SBrandon Wyman         // First need it to return good status, then the fault
404b654c619SBrandon Wyman         PMBusExpectations expectations;
405b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
40682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
40782affd94SBrandon Wyman             .Times(1)
40882affd94SBrandon Wyman             .WillOnce(Return("210000"));
4093f1242f3SBrandon Wyman         psu2.analyze();
4108da35c51SBrandon Wyman         // Now STATUS_WORD with MFR fault bit on.
411b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
4128da35c51SBrandon Wyman         // STATUS_MFR bits on.
413b654c619SBrandon Wyman         expectations.statusMFRValue = 0xFF;
414c2906f47SBrandon Wyman 
415c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
416c2906f47SBrandon Wyman         {
417b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
41882affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
41982affd94SBrandon Wyman                 .Times(1)
42082affd94SBrandon Wyman                 .WillOnce(Return("211000"));
4213f1242f3SBrandon Wyman             psu2.analyze();
4223f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
423c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
4243f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
425c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT);
426c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT);
427c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
428c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
4293f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
43085c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
4316710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
432b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
4332cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
4347ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
43596893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
4362916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
437c2906f47SBrandon Wyman         }
438b654c619SBrandon Wyman     }
4393f1242f3SBrandon Wyman 
44032453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
4413225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
4423225a45cSBrandon Wyman         .Times(1)
4433225a45cSBrandon Wyman         .WillOnce(Return(1));
444c2906f47SBrandon Wyman     psu2.clearFaults();
4453225a45cSBrandon Wyman 
44696893a46SBrandon Wyman     // Temperature fault.
447b654c619SBrandon Wyman     {
448f07bc797SBrandon Wyman         // First STATUS_WORD with no bits set, then with temperature fault.
449b654c619SBrandon Wyman         PMBusExpectations expectations;
450b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
45182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
45282affd94SBrandon Wyman             .Times(1)
45382affd94SBrandon Wyman             .WillOnce(Return("212000"));
4543f1242f3SBrandon Wyman         psu2.analyze();
4558da35c51SBrandon Wyman         // STATUS_WORD with temperature fault bit on.
456b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
45796893a46SBrandon Wyman         // STATUS_TEMPERATURE with fault bit(s) on.
45896893a46SBrandon Wyman         expectations.statusTempValue = 0x10;
459c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
460c2906f47SBrandon Wyman         {
461b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
46282affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
46382affd94SBrandon Wyman                 .Times(1)
46482affd94SBrandon Wyman                 .WillOnce(Return("213000"));
4653f1242f3SBrandon Wyman             psu2.analyze();
4663f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
467c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
4683f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
4693f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
4703f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
47185c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
4726710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
473b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
4742cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
4757ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
476c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT);
4772916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
47839ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
47939ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
48039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
481b654c619SBrandon Wyman         }
482c2906f47SBrandon Wyman     }
48385c7bf41SBrandon Wyman 
48432453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
4853225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
4863225a45cSBrandon Wyman         .Times(1)
4873225a45cSBrandon Wyman         .WillOnce(Return(1));
488c2906f47SBrandon Wyman     psu2.clearFaults();
4893225a45cSBrandon Wyman 
49085c7bf41SBrandon Wyman     // CML fault
491b654c619SBrandon Wyman     {
49285c7bf41SBrandon Wyman         // First STATUS_WORD wit no bits set, then with CML fault.
493b654c619SBrandon Wyman         PMBusExpectations expectations;
494b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
49582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
49682affd94SBrandon Wyman             .Times(1)
49782affd94SBrandon Wyman             .WillOnce(Return("214000"));
49885c7bf41SBrandon Wyman         psu2.analyze();
4998da35c51SBrandon Wyman         // STATUS_WORD with CML fault bit on.
500b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::CML_FAULT);
50185c7bf41SBrandon Wyman         // Turn on STATUS_CML fault bit(s)
502b654c619SBrandon Wyman         expectations.statusCMLValue = 0xFF;
503c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
504c2906f47SBrandon Wyman         {
505b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
50682affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
50782affd94SBrandon Wyman                 .Times(1)
50882affd94SBrandon Wyman                 .WillOnce(Return("215000"));
50985c7bf41SBrandon Wyman             psu2.analyze();
51085c7bf41SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
511c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
512c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), x >= DEGLITCH_LIMIT);
51385c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
51485c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
51585c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
5166710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
517b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
5182cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
5197ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
52096893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
5212916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
52239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
52339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
52439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
525b654c619SBrandon Wyman         }
526c2906f47SBrandon Wyman     }
5276710ba2cSBrandon Wyman 
52832453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
5293225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
5303225a45cSBrandon Wyman         .Times(1)
5313225a45cSBrandon Wyman         .WillOnce(Return(1));
532c2906f47SBrandon Wyman     psu2.clearFaults();
5333225a45cSBrandon Wyman 
5346710ba2cSBrandon Wyman     // VOUT_OV_FAULT fault
535b654c619SBrandon Wyman     {
5366710ba2cSBrandon Wyman         // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
537b654c619SBrandon Wyman         PMBusExpectations expectations;
538b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
53982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
54082affd94SBrandon Wyman             .Times(1)
54182affd94SBrandon Wyman             .WillOnce(Return("216000"));
5426710ba2cSBrandon Wyman         psu2.analyze();
5436710ba2cSBrandon Wyman         // STATUS_WORD with VOUT/VOUT_OV fault.
544b654c619SBrandon Wyman         expectations.statusWordValue =
5456710ba2cSBrandon Wyman             ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
5466710ba2cSBrandon Wyman         // Turn on STATUS_VOUT fault bit(s)
547b654c619SBrandon Wyman         expectations.statusVOUTValue = 0xA0;
548c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
549c2906f47SBrandon Wyman         {
55096893a46SBrandon Wyman             // STATUS_TEMPERATURE don't care (default)
551b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
55282affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
55382affd94SBrandon Wyman                 .Times(1)
55482affd94SBrandon Wyman                 .WillOnce(Return("217000"));
5556710ba2cSBrandon Wyman             psu2.analyze();
5566710ba2cSBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
557c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
5586710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
5596710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
5606710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
5616710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
562c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
5632cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
564b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
5657ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
566b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
567b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
56839ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
56939ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
57039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
571b10b3be0SBrandon Wyman         }
572c2906f47SBrandon Wyman     }
573b10b3be0SBrandon Wyman 
574b10b3be0SBrandon Wyman     // IOUT_OC_FAULT fault
575b10b3be0SBrandon Wyman     {
576b10b3be0SBrandon Wyman         // First STATUS_WORD with no bits set, then with IOUT_OC fault.
577b10b3be0SBrandon Wyman         PMBusExpectations expectations;
578b10b3be0SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
57982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
58082affd94SBrandon Wyman             .Times(1)
58182affd94SBrandon Wyman             .WillOnce(Return("218000"));
582b10b3be0SBrandon Wyman         psu2.analyze();
583b10b3be0SBrandon Wyman         // STATUS_WORD with IOUT_OC fault.
584b10b3be0SBrandon Wyman         expectations.statusWordValue = status_word::IOUT_OC_FAULT;
585b10b3be0SBrandon Wyman         // Turn on STATUS_IOUT fault bit(s)
586b10b3be0SBrandon Wyman         expectations.statusIOUTValue = 0x88;
587c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
588c2906f47SBrandon Wyman         {
589b10b3be0SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
59082affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
59182affd94SBrandon Wyman                 .Times(1)
59282affd94SBrandon Wyman                 .WillOnce(Return("219000"));
593b10b3be0SBrandon Wyman             psu2.analyze();
594b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
595c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
596b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
597b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
598b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
599b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
600b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
601c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
6022cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
6037ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
6042cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6052cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
60639ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
60739ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
60839ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
6092cf46945SBrandon Wyman         }
610c2906f47SBrandon Wyman     }
6112cf46945SBrandon Wyman 
6122cf46945SBrandon Wyman     // VOUT_UV_FAULT
6132cf46945SBrandon Wyman     {
6142cf46945SBrandon Wyman         // First STATUS_WORD with no bits set, then with VOUT fault.
6152cf46945SBrandon Wyman         PMBusExpectations expectations;
6162cf46945SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
61782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
61882affd94SBrandon Wyman             .Times(1)
61982affd94SBrandon Wyman             .WillOnce(Return("220000"));
6202cf46945SBrandon Wyman         psu2.analyze();
6212cf46945SBrandon Wyman         // Change STATUS_WORD to indicate VOUT fault.
6222cf46945SBrandon Wyman         expectations.statusWordValue = (status_word::VOUT_FAULT);
6232cf46945SBrandon Wyman         // Turn on STATUS_VOUT fault bit(s)
6242cf46945SBrandon Wyman         expectations.statusVOUTValue = 0x30;
625c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
626c2906f47SBrandon Wyman         {
6272cf46945SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
62882affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
62982affd94SBrandon Wyman                 .Times(1)
63082affd94SBrandon Wyman                 .WillOnce(Return("221000"));
6312cf46945SBrandon Wyman             psu2.analyze();
6322cf46945SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
633c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
6342cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
6352cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
6362cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
6372cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
6382cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
6392cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
640c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
6417ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
64296893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6432916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
64439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
64539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
64639ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
647b654c619SBrandon Wyman         }
648c2906f47SBrandon Wyman     }
6493f1242f3SBrandon Wyman 
6507ee4d7e4SBrandon Wyman     // Fan fault
651b654c619SBrandon Wyman     {
652b654c619SBrandon Wyman         // First STATUS_WORD with no bits set, then with fan fault.
653b654c619SBrandon Wyman         PMBusExpectations expectations;
654b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
65582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
65682affd94SBrandon Wyman             .Times(1)
65782affd94SBrandon Wyman             .WillOnce(Return("222000"));
6583f1242f3SBrandon Wyman         psu2.analyze();
659b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::FAN_FAULT);
6607ee4d7e4SBrandon Wyman         // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
6617ee4d7e4SBrandon Wyman         expectations.statusFans12Value = 0xA0;
662c2906f47SBrandon Wyman 
663c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
664c2906f47SBrandon Wyman         {
665b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
66682affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
66782affd94SBrandon Wyman                 .Times(1)
66882affd94SBrandon Wyman                 .WillOnce(Return("223000"));
6693f1242f3SBrandon Wyman             psu2.analyze();
6703f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
671c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
672c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT);
6733f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
6743f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
6753f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
67685c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
6776710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
678b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
6792cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
68096893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6812916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
68239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
68339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
68439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
685b654c619SBrandon Wyman         }
686c2906f47SBrandon Wyman     }
6872916ea52SBrandon Wyman 
68806ca4590SBrandon Wyman     // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
6892cf46945SBrandon Wyman     {
6902916ea52SBrandon Wyman         // First STATUS_WORD with no bits set.
6912916ea52SBrandon Wyman         PMBusExpectations expectations;
6922916ea52SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
69382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
69482affd94SBrandon Wyman             .Times(1)
69582affd94SBrandon Wyman             .WillOnce(Return("123000"));
6962916ea52SBrandon Wyman         psu2.analyze();
6972916ea52SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
6982916ea52SBrandon Wyman         // POWER_GOOD# inactive, and OFF bit on.
6992916ea52SBrandon Wyman         expectations.statusWordValue =
7002916ea52SBrandon Wyman             ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
7016d469fd4SBrandon Wyman         for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++)
70206ca4590SBrandon Wyman         {
7032916ea52SBrandon Wyman             // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
7042916ea52SBrandon Wyman             // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
7052916ea52SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
70682affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
70782affd94SBrandon Wyman                 .Times(1)
70882affd94SBrandon Wyman                 .WillOnce(Return("124000"));
7092916ea52SBrandon Wyman             psu2.analyze();
7102916ea52SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
7116d469fd4SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= PGOOD_DEGLITCH_LIMIT);
7122916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
7132916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
7142916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
7152916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
7162916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
7172cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
718b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
7197ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
7202916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
7216d469fd4SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT);
72206ca4590SBrandon Wyman         }
72306ca4590SBrandon Wyman     }
7242916ea52SBrandon Wyman 
7253f1242f3SBrandon Wyman     // TODO: ReadFailure
7263f1242f3SBrandon Wyman }
7273f1242f3SBrandon Wyman 
72859a35793SBrandon Wyman TEST_F(PowerSupplyTests, OnOffConfig)
72959a35793SBrandon Wyman {
73059a35793SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
73159a35793SBrandon Wyman     uint8_t data = 0x15;
73259a35793SBrandon Wyman 
73359a35793SBrandon Wyman     // Test where PSU is NOT present
73459a35793SBrandon Wyman     try
73559a35793SBrandon Wyman     {
736681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
7370975eaf4SMatt Spinler         EXPECT_CALL(mockedUtil, setAvailable(_, _, _)).Times(0);
738*9464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 4,        0x69,
739*9464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
740681b2a36SB. J. Wyman 
7413ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
7423ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
743681b2a36SB. J. Wyman         ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
74459a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
745681b2a36SB. J. Wyman         // Constructor should set initial presence, default read returns 0.
74659a35793SBrandon Wyman         // If it is not present, I should not be trying to write to it.
74759a35793SBrandon Wyman         EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
74859a35793SBrandon Wyman         psu.onOffConfig(data);
74959a35793SBrandon Wyman     }
75059a35793SBrandon Wyman     catch (...)
7510c9a33d6SAdriana Kobylak     {}
75259a35793SBrandon Wyman 
75359a35793SBrandon Wyman     // Test where PSU is present
75459a35793SBrandon Wyman     try
75559a35793SBrandon Wyman     {
756681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
7570975eaf4SMatt Spinler         EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
758*9464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 5,        0x6a,
759*9464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
7603ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
7613ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
762391a0690SBrandon Wyman         // There will potentially be multiple calls, we want it to continue
763391a0690SBrandon Wyman         // returning 1 for the GPIO read to keep the power supply present.
764391a0690SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
76559a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
766391a0690SBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
767ae35ac5dSBrandon Wyman         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
768ae35ac5dSBrandon Wyman         // for INPUT_HISTORY will check max_power_out to see if it is
769ae35ac5dSBrandon Wyman         // old/unsupported power supply. Indicate good value, supported.
770ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
771ae35ac5dSBrandon Wyman             .Times(1)
772ae35ac5dSBrandon Wyman             .WillOnce(Return("2000"));
773391a0690SBrandon Wyman         // If I am calling analyze(), I should probably give it good data.
774391a0690SBrandon Wyman         // STATUS_WORD 0x0000 is powered on, no faults.
775391a0690SBrandon Wyman         PMBusExpectations expectations;
776391a0690SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
77782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
77882affd94SBrandon Wyman             .Times(1)
77982affd94SBrandon Wyman             .WillOnce(Return("205000"));
780681b2a36SB. J. Wyman         psu.analyze();
781391a0690SBrandon Wyman         // I definitely should be writting ON_OFF_CONFIG if I call the function
782391a0690SBrandon Wyman         EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
783391a0690SBrandon Wyman                                            Type::HwmonDeviceDebug))
78459a35793SBrandon Wyman             .Times(1);
78559a35793SBrandon Wyman         psu.onOffConfig(data);
78659a35793SBrandon Wyman     }
78759a35793SBrandon Wyman     catch (...)
7880c9a33d6SAdriana Kobylak     {}
78959a35793SBrandon Wyman }
79059a35793SBrandon Wyman 
7913f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, ClearFaults)
7923f1242f3SBrandon Wyman {
7933f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
794*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 13,       0x68,
795*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
7963ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
7973ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
79806ca4590SBrandon Wyman     // Always return 1 to indicate present.
79906ca4590SBrandon Wyman     // Each analyze() call will trigger a read of the presence GPIO.
80006ca4590SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
801681b2a36SB. J. Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
802391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
803ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
804ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
805ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
806ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
807ae35ac5dSBrandon Wyman         .Times(1)
808ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
8098da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
810b654c619SBrandon Wyman     PMBusExpectations expectations;
811b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
81282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
81382affd94SBrandon Wyman         .Times(1)
81482affd94SBrandon Wyman         .WillOnce(Return("207000"));
815681b2a36SB. J. Wyman     psu.analyze();
8163f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
8173f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
8183f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
8193f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
8203f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
82185c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
8226710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
823b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
8242cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
8257ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
82696893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
8272916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
82839ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
82939ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
83039ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
831b654c619SBrandon Wyman 
832f07bc797SBrandon Wyman     // STATUS_WORD with fault bits galore!
833b654c619SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
834f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
835b654c619SBrandon Wyman     expectations.statusInputValue = 0xFF;
836f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
837b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
83885c7bf41SBrandon Wyman     // STATUS_CML with bits on.
839b654c619SBrandon Wyman     expectations.statusCMLValue = 0xFF;
8406710ba2cSBrandon Wyman     // STATUS_VOUT with bits on.
841b654c619SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
842b10b3be0SBrandon Wyman     // STATUS_IOUT with bits on.
843b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
8447ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
8457ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0xFF;
84696893a46SBrandon Wyman     // STATUS_TEMPERATURE with bits on.
84796893a46SBrandon Wyman     expectations.statusTempValue = 0xFF;
848c2906f47SBrandon Wyman 
8496d469fd4SBrandon Wyman     for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++)
850c2906f47SBrandon Wyman     {
851b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
85282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
85382affd94SBrandon Wyman             .Times(1)
85482affd94SBrandon Wyman             .WillOnce(Return("0"));
8550975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
8560975eaf4SMatt Spinler         {
8570975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
8580975eaf4SMatt Spinler         }
8593f1242f3SBrandon Wyman         psu.analyze();
8603f1242f3SBrandon Wyman         EXPECT_EQ(psu.isPresent(), true);
8612cf46945SBrandon Wyman         // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
8622cf46945SBrandon Wyman         // Rely on HasVoutUVFault() to verify this sets and clears.
8632cf46945SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), false);
8646d469fd4SBrandon Wyman         // pgoodFault at PGOOD_DEGLITCH_LIMIT, all other faults are deglitched
8656d469fd4SBrandon Wyman         // up to DEGLITCH_LIMIT
866c2906f47SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
867c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
868c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
869c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
870c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT);
871c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
872c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
873c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
874c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
8756d469fd4SBrandon Wyman         EXPECT_EQ(psu.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT);
876c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
877c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
878c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
879c2906f47SBrandon Wyman     }
880c2906f47SBrandon Wyman 
88132453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _))
88232453e9bSBrandon Wyman         .Times(1)
88332453e9bSBrandon Wyman         .WillOnce(Return(207000));
8843225a45cSBrandon Wyman     // Clearing VIN_UV fault via in1_lcrit_alarm
8853225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
8863225a45cSBrandon Wyman         .Times(1)
8873225a45cSBrandon Wyman         .WillOnce(Return(1));
8880975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
8893f1242f3SBrandon Wyman     psu.clearFaults();
8903f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
8913f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
8923f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
8933f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
8943f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
89585c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
8966710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
897b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
8982cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
8997ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
90096893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
9012916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
90239ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
90339ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
90439ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
905681b2a36SB. J. Wyman 
90682affd94SBrandon Wyman     // Faults clear on READ_VIN 0 -> !0
90782affd94SBrandon Wyman     // STATUS_WORD with fault bits galore!
90882affd94SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
90982affd94SBrandon Wyman     // STATUS_INPUT with fault bits on.
91082affd94SBrandon Wyman     expectations.statusInputValue = 0xFF;
91182affd94SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
91282affd94SBrandon Wyman     expectations.statusMFRValue = 0xFF;
91382affd94SBrandon Wyman     // STATUS_CML with bits on.
91482affd94SBrandon Wyman     expectations.statusCMLValue = 0xFF;
91582affd94SBrandon Wyman     // STATUS_VOUT with bits on.
91682affd94SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
91782affd94SBrandon Wyman     // STATUS_IOUT with bits on.
91882affd94SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
91982affd94SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
92082affd94SBrandon Wyman     expectations.statusFans12Value = 0xFF;
92182affd94SBrandon Wyman     // STATUS_TEMPERATURE with bits on.
92282affd94SBrandon Wyman     expectations.statusTempValue = 0xFF;
923c2906f47SBrandon Wyman 
9246d469fd4SBrandon Wyman     // All faults deglitched now. Check for false before limit above.
925c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
926c2906f47SBrandon Wyman     {
92782affd94SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
92882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
92982affd94SBrandon Wyman             .Times(1)
93082affd94SBrandon Wyman             .WillOnce(Return("0"));
9310975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
9320975eaf4SMatt Spinler         {
9330975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
9340975eaf4SMatt Spinler         }
93582affd94SBrandon Wyman         psu.analyze();
936c2906f47SBrandon Wyman     }
937c2906f47SBrandon Wyman 
93882affd94SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
93982affd94SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
94082affd94SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), true);
94182affd94SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
94282affd94SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), true);
94382affd94SBrandon Wyman     // True due to CML fault bits on
94482affd94SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), true);
94582affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
94682affd94SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), true);
94782affd94SBrandon Wyman     // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
94882affd94SBrandon Wyman     // Rely on HasVoutUVFault() to verify this sets and clears.
94982affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
95082affd94SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), true);
95182affd94SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), true);
9526d469fd4SBrandon Wyman     // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT
9536d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
95482affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), true);
95582affd94SBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), true);
95682affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), true);
95782affd94SBrandon Wyman     // STATUS_WORD with INPUT/VIN_UV fault bits off.
95882affd94SBrandon Wyman     expectations.statusWordValue = 0xDFF7;
95982affd94SBrandon Wyman     // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
96082affd94SBrandon Wyman     // Insufficient Input Voltage bits off.
96182affd94SBrandon Wyman     expectations.statusInputValue = 0xC7;
96282affd94SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
96382affd94SBrandon Wyman     // READ_VIN back in range.
96482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
96582affd94SBrandon Wyman         .Times(1)
96682affd94SBrandon Wyman         .WillOnce(Return("206000"));
9673225a45cSBrandon Wyman     // VIN_UV cleared via in1_lcrit_alarm when voltage back in range.
9683225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
9693225a45cSBrandon Wyman         .Times(1)
9703225a45cSBrandon Wyman         .WillOnce(Return(1));
9713225a45cSBrandon Wyman     psu.analyze();
9723225a45cSBrandon Wyman     // We only cleared the VIN_UV and OFF faults.
9733225a45cSBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
9743225a45cSBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
9753225a45cSBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
9763225a45cSBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
9773225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
9783225a45cSBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), true);
9793225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
9803225a45cSBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), true);
9813225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
9823225a45cSBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), true);
9833225a45cSBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), true);
9846d469fd4SBrandon Wyman     // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT
9856d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
9863225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), true);
9873225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), true);
9883225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), true);
9893225a45cSBrandon Wyman 
9903225a45cSBrandon Wyman     // All faults cleared
9913225a45cSBrandon Wyman     expectations = {0};
9923225a45cSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
9933225a45cSBrandon Wyman     // READ_VIN back in range.
9943225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
9953225a45cSBrandon Wyman         .Times(1)
9963225a45cSBrandon Wyman         .WillOnce(Return("206000"));
9970975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
99882affd94SBrandon Wyman     psu.analyze();
99982affd94SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
100082affd94SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
100182affd94SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
100282affd94SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
100382affd94SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
100482affd94SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
100582affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
100682affd94SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
100782affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
100882affd94SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
100982affd94SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
101082affd94SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
101182affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
101282affd94SBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
101382affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
101482affd94SBrandon Wyman 
1015681b2a36SB. J. Wyman     // TODO: Faults clear on missing/present?
10163f1242f3SBrandon Wyman }
10173f1242f3SBrandon Wyman 
10183f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, UpdateInventory)
10193f1242f3SBrandon Wyman {
10203f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
10211d7a7df8SBrandon Wyman 
10221d7a7df8SBrandon Wyman     try
10231d7a7df8SBrandon Wyman     {
1024*9464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
1025*9464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
10261d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
10271d7a7df8SBrandon Wyman         // If it is not present, I should not be trying to read a string
10281d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
10291d7a7df8SBrandon Wyman         psu.updateInventory();
10301d7a7df8SBrandon Wyman     }
10311d7a7df8SBrandon Wyman     catch (...)
10321d7a7df8SBrandon Wyman     {
10331d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
10341d7a7df8SBrandon Wyman     }
10351d7a7df8SBrandon Wyman 
10361d7a7df8SBrandon Wyman     try
10371d7a7df8SBrandon Wyman     {
1038*9464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 13,       0x69,
1039*9464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
10403ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
10413ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1042681b2a36SB. J. Wyman         // GPIO read return 1 to indicate present.
1043681b2a36SB. J. Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
10441d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1045391a0690SBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
1046ae35ac5dSBrandon Wyman         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1047ae35ac5dSBrandon Wyman         // for INPUT_HISTORY will check max_power_out to see if it is
1048ae35ac5dSBrandon Wyman         // old/unsupported power supply. Indicate good value, supported.
1049ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1050ae35ac5dSBrandon Wyman             .Times(1)
1051ae35ac5dSBrandon Wyman             .WillOnce(Return("2000"));
1052391a0690SBrandon Wyman         // STATUS_WORD 0x0000 is powered on, no faults.
1053391a0690SBrandon Wyman         PMBusExpectations expectations;
1054391a0690SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
105582affd94SBrandon Wyman         // Call to analyze will read voltage, trigger clear faults for 0 to
105682affd94SBrandon Wyman         // within range.
105782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
105882affd94SBrandon Wyman             .Times(1)
105982affd94SBrandon Wyman             .WillOnce(Return("123456"));
1060391a0690SBrandon Wyman         psu.analyze();
10611d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
10623f1242f3SBrandon Wyman         psu.updateInventory();
10631d7a7df8SBrandon Wyman 
10643c530fbdSBrandon Wyman #if IBM_VPD
10651d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _))
10661d7a7df8SBrandon Wyman             .WillOnce(Return("CCIN"))
10671d7a7df8SBrandon Wyman             .WillOnce(Return("PN3456"))
10681d7a7df8SBrandon Wyman             .WillOnce(Return("FN3456"))
10691d7a7df8SBrandon Wyman             .WillOnce(Return("HEADER"))
10701d7a7df8SBrandon Wyman             .WillOnce(Return("SN3456"))
10711d7a7df8SBrandon Wyman             .WillOnce(Return("FW3456"));
10723c530fbdSBrandon Wyman #endif
10731d7a7df8SBrandon Wyman         psu.updateInventory();
10741d7a7df8SBrandon Wyman         // TODO: D-Bus mocking to verify values stored on D-Bus (???)
10751d7a7df8SBrandon Wyman     }
10761d7a7df8SBrandon Wyman     catch (...)
10771d7a7df8SBrandon Wyman     {
10781d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
10791d7a7df8SBrandon Wyman     }
10803f1242f3SBrandon Wyman }
10813f1242f3SBrandon Wyman 
10823f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsPresent)
10833f1242f3SBrandon Wyman {
10843f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1085681b2a36SB. J. Wyman 
1086*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
1087*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
10883ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
10893ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
10903f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), false);
10913f1242f3SBrandon Wyman 
1092681b2a36SB. J. Wyman     // Change GPIO read to return 1 to indicate present.
1093681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
1094391a0690SBrandon Wyman     // Call to analyze() will update to present, that will trigger updating
1095391a0690SBrandon Wyman     // to the correct/latest HWMON directory, in case it changes.
1096391a0690SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1097391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1098ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1099ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1100ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1101ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1102ae35ac5dSBrandon Wyman         .Times(1)
1103ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
1104391a0690SBrandon Wyman     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1105391a0690SBrandon Wyman     // Default expectations will be on, no faults.
1106391a0690SBrandon Wyman     PMBusExpectations expectations;
1107391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
110882affd94SBrandon Wyman     // Give it an input voltage in the 100-volt range.
110982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
111082affd94SBrandon Wyman         .Times(1)
111182affd94SBrandon Wyman         .WillOnce(Return("123456"));
11120975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1113681b2a36SB. J. Wyman     psu.analyze();
1114681b2a36SB. J. Wyman     EXPECT_EQ(psu.isPresent(), true);
11153f1242f3SBrandon Wyman }
11163f1242f3SBrandon Wyman 
11173f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsFaulted)
11183f1242f3SBrandon Wyman {
11193f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1120681b2a36SB. J. Wyman 
1121*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 11,       0x6f,
1122*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
11233ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
11243ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1125681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1126681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1127391a0690SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1128391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1129ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1130ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1131ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1132ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1133ae35ac5dSBrandon Wyman         .Times(1)
1134ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
1135391a0690SBrandon Wyman     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1136391a0690SBrandon Wyman     // Default expectations will be on, no faults.
1137391a0690SBrandon Wyman     PMBusExpectations expectations;
1138391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
113982affd94SBrandon Wyman     // Give it an input voltage in the 100-volt range.
114082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
114182affd94SBrandon Wyman         .Times(1)
114282affd94SBrandon Wyman         .WillOnce(Return("124680"));
1143681b2a36SB. J. Wyman     psu.analyze();
11443f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
1145f07bc797SBrandon Wyman     // STATUS_WORD with fault bits on.
1146b654c619SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
1147f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
1148b654c619SBrandon Wyman     expectations.statusInputValue = 0xFF;
1149f07bc797SBrandon Wyman     // STATUS_MFR_SPECIFIC with faults bits on.
1150b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
115185c7bf41SBrandon Wyman     // STATUS_CML with faults bits on.
1152b654c619SBrandon Wyman     expectations.statusCMLValue = 0xFF;
11536710ba2cSBrandon Wyman     // STATUS_VOUT with fault bits on.
1154b654c619SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
1155b10b3be0SBrandon Wyman     // STATUS_IOUT with fault bits on.
1156b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
11577ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
11587ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0xFF;
115996893a46SBrandon Wyman     // STATUS_TEMPERATURE with fault bits on.
116096893a46SBrandon Wyman     expectations.statusTempValue = 0xFF;
1161c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1162c2906f47SBrandon Wyman     {
1163b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
11644fc191f0SBrandon Wyman         // Also get another read of READ_VIN, faulted, so not in 100-volt range
116582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
116682affd94SBrandon Wyman             .Times(1)
11674fc191f0SBrandon Wyman             .WillOnce(Return("19000"));
11680975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
11690975eaf4SMatt Spinler         {
11700975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
11710975eaf4SMatt Spinler         }
11723f1242f3SBrandon Wyman         psu.analyze();
1173c2906f47SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
1174c2906f47SBrandon Wyman     }
11753f1242f3SBrandon Wyman }
11763f1242f3SBrandon Wyman 
11773f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasInputFault)
11783f1242f3SBrandon Wyman {
11793f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1180681b2a36SB. J. Wyman 
1181*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
1182*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
11833ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
11843ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1185681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1186681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
11873f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1188391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1189ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1190ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1191ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1192ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1193ae35ac5dSBrandon Wyman         .Times(1)
1194ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
11958da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1196b654c619SBrandon Wyman     PMBusExpectations expectations;
1197b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
119882affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
119982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
120082affd94SBrandon Wyman         .Times(1)
120182affd94SBrandon Wyman         .WillOnce(Return("201100"));
12023f1242f3SBrandon Wyman     psu.analyze();
12033f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
1204f07bc797SBrandon Wyman     // STATUS_WORD with input fault/warn on.
1205b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
1206f07bc797SBrandon Wyman     // STATUS_INPUT with an input fault bit on.
1207b654c619SBrandon Wyman     expectations.statusInputValue = 0x80;
1208c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1209c2906f47SBrandon Wyman     {
1210b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
121182affd94SBrandon Wyman         // Analyze call will also need good READ_VIN value to check.
121282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
121382affd94SBrandon Wyman             .Times(1)
121482affd94SBrandon Wyman             .WillOnce(Return("201200"));
12150975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
12160975eaf4SMatt Spinler         {
12170975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
12180975eaf4SMatt Spinler         }
12193f1242f3SBrandon Wyman         psu.analyze();
1220c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
1221c2906f47SBrandon Wyman     }
1222f07bc797SBrandon Wyman     // STATUS_WORD with no bits on.
1223b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1224b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
122582affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
122682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
122782affd94SBrandon Wyman         .Times(1)
122882affd94SBrandon Wyman         .WillOnce(Return("201300"));
12290975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
12303f1242f3SBrandon Wyman     psu.analyze();
12313f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
12323f1242f3SBrandon Wyman }
12333f1242f3SBrandon Wyman 
12343f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasMFRFault)
12353f1242f3SBrandon Wyman {
12363f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1237681b2a36SB. J. Wyman 
1238*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
1239*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
12403ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
12413ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1242681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1243681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
12443f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1245391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1246ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1247ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1248ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1249ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1250ae35ac5dSBrandon Wyman         .Times(1)
1251ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
1252f07bc797SBrandon Wyman     // First return STATUS_WORD with no bits on.
12538da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1254b654c619SBrandon Wyman     PMBusExpectations expectations;
1255b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
125682affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
125782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
125882affd94SBrandon Wyman         .Times(1)
125982affd94SBrandon Wyman         .WillOnce(Return("202100"));
12603f1242f3SBrandon Wyman     psu.analyze();
12613f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
1262f07bc797SBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
1263b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1264f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
1265b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
1266c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1267c2906f47SBrandon Wyman     {
1268b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
126982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
127082affd94SBrandon Wyman             .Times(1)
127182affd94SBrandon Wyman             .WillOnce(Return("202200"));
12723f1242f3SBrandon Wyman         psu.analyze();
1273c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1274c2906f47SBrandon Wyman     }
1275f07bc797SBrandon Wyman     // Back to no bits on in STATUS_WORD
1276b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1277b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
127882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
127982affd94SBrandon Wyman         .Times(1)
128082affd94SBrandon Wyman         .WillOnce(Return("202300"));
12813f1242f3SBrandon Wyman     psu.analyze();
12823f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
12833f1242f3SBrandon Wyman }
12843f1242f3SBrandon Wyman 
12853f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasVINUVFault)
12863f1242f3SBrandon Wyman {
12873f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1288681b2a36SB. J. Wyman 
1289*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
1290*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
12913ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
12923ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1293681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1294681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
12953f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1296391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1297ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1298ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1299ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1300ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1301ae35ac5dSBrandon Wyman         .Times(1)
1302ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
130382affd94SBrandon Wyman 
130482affd94SBrandon Wyman     // Presence change from missing to present will trigger in1_input read in
130582affd94SBrandon Wyman     // an attempt to get CLEAR_FAULTS called. Return value ignored.
130682affd94SBrandon Wyman     // Zero to non-zero voltage, for missing/present change, triggers clear
130782affd94SBrandon Wyman     // faults call again. Return value ignored.
130882affd94SBrandon Wyman     // Fault (low voltage) to not faulted (voltage in range) triggers clear
130982affd94SBrandon Wyman     // faults call a third time.
131082affd94SBrandon Wyman 
13118da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1312b654c619SBrandon Wyman     PMBusExpectations expectations;
1313b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
131482affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
131582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
131682affd94SBrandon Wyman         .Times(1)
131782affd94SBrandon Wyman         .WillOnce(Return("201100"));
13183f1242f3SBrandon Wyman     psu.analyze();
13193f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
1320f07bc797SBrandon Wyman     // Turn fault on.
1321b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::VIN_UV_FAULT);
132285c7bf41SBrandon Wyman     // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
132385c7bf41SBrandon Wyman     // Figure 16, and assume bits on in STATUS_INPUT.
1324b654c619SBrandon Wyman     expectations.statusInputValue = 0x18;
1325c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1326c2906f47SBrandon Wyman     {
1327b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
132882affd94SBrandon Wyman         // If there is a VIN_UV fault, fake reading voltage of less than 20V
132982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
133082affd94SBrandon Wyman             .Times(1)
133182affd94SBrandon Wyman             .WillOnce(Return("19876"));
13320975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
13330975eaf4SMatt Spinler         {
13340975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
13350975eaf4SMatt Spinler         }
13363f1242f3SBrandon Wyman         psu.analyze();
1337c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1338c2906f47SBrandon Wyman     }
1339f07bc797SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1340b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1341b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
134282affd94SBrandon Wyman     // Updates now result in clearing faults if read voltage goes from below the
134382affd94SBrandon Wyman     // minimum, to within a valid range.
134482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
134582affd94SBrandon Wyman         .Times(1)
134682affd94SBrandon Wyman         .WillOnce(Return("201300"));
13473225a45cSBrandon Wyman     // Went from below minimum to within range, expect clearVinUVFault().
13483225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
13493225a45cSBrandon Wyman         .Times(1)
13503225a45cSBrandon Wyman         .WillOnce(Return(1));
13510975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
13523f1242f3SBrandon Wyman     psu.analyze();
13533f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
13543f1242f3SBrandon Wyman }
13556710ba2cSBrandon Wyman 
13566710ba2cSBrandon Wyman TEST_F(PowerSupplyTests, HasVoutOVFault)
13576710ba2cSBrandon Wyman {
13586710ba2cSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
13596710ba2cSBrandon Wyman 
1360*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x69,
1361*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
13626710ba2cSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
13636710ba2cSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
13646710ba2cSBrandon Wyman     // Always return 1 to indicate present.
13656710ba2cSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
13666710ba2cSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1367391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1368ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1369ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1370ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1371ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1372ae35ac5dSBrandon Wyman         .Times(1)
1373ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
13746710ba2cSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1375b654c619SBrandon Wyman     PMBusExpectations expectations;
1376b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
137782affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
137882affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
137982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
138082affd94SBrandon Wyman         .Times(1)
138182affd94SBrandon Wyman         .WillOnce(Return("202100"));
13826710ba2cSBrandon Wyman     psu.analyze();
13836710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
13846710ba2cSBrandon Wyman     // Turn fault on.
1385b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
13866710ba2cSBrandon Wyman     // STATUS_VOUT fault bit(s)
1387b654c619SBrandon Wyman     expectations.statusVOUTValue = 0x80;
1388c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1389c2906f47SBrandon Wyman     {
1390b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
139182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
139282affd94SBrandon Wyman             .Times(1)
139382affd94SBrandon Wyman             .WillOnce(Return("202200"));
13946710ba2cSBrandon Wyman         psu.analyze();
1395c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1396c2906f47SBrandon Wyman     }
13976710ba2cSBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1398b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1399b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
140082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
140182affd94SBrandon Wyman         .Times(1)
140282affd94SBrandon Wyman         .WillOnce(Return("202300"));
14036710ba2cSBrandon Wyman     psu.analyze();
14046710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
14056710ba2cSBrandon Wyman }
140696893a46SBrandon Wyman 
1407b10b3be0SBrandon Wyman TEST_F(PowerSupplyTests, HasIoutOCFault)
1408b10b3be0SBrandon Wyman {
1409b10b3be0SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1410b10b3be0SBrandon Wyman 
1411*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6d,
1412*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1413b10b3be0SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
1414b10b3be0SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1415b10b3be0SBrandon Wyman     // Always return 1 to indicate present.
1416b10b3be0SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1417b10b3be0SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1418391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1419ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1420ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1421ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1422ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1423ae35ac5dSBrandon Wyman         .Times(1)
1424ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
1425b10b3be0SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1426b10b3be0SBrandon Wyman     PMBusExpectations expectations;
1427b10b3be0SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
142882affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
142982affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
143082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
143182affd94SBrandon Wyman         .Times(1)
143282affd94SBrandon Wyman         .WillOnce(Return("203100"));
1433b10b3be0SBrandon Wyman     psu.analyze();
1434b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
1435b10b3be0SBrandon Wyman     // Turn fault on.
1436b10b3be0SBrandon Wyman     expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1437b10b3be0SBrandon Wyman     // STATUS_IOUT fault bit(s)
1438b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0x88;
1439c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1440c2906f47SBrandon Wyman     {
1441b10b3be0SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
144282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
144382affd94SBrandon Wyman             .Times(1)
144482affd94SBrandon Wyman             .WillOnce(Return("203200"));
14450975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
14460975eaf4SMatt Spinler         {
14470975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
14480975eaf4SMatt Spinler         }
1449b10b3be0SBrandon Wyman         psu.analyze();
1450c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1451c2906f47SBrandon Wyman     }
1452b10b3be0SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1453b10b3be0SBrandon Wyman     expectations.statusWordValue = 0;
1454b10b3be0SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
145582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
145682affd94SBrandon Wyman         .Times(1)
145782affd94SBrandon Wyman         .WillOnce(Return("203300"));
14580975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1459b10b3be0SBrandon Wyman     psu.analyze();
1460b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
1461b10b3be0SBrandon Wyman }
1462b10b3be0SBrandon Wyman 
14632cf46945SBrandon Wyman TEST_F(PowerSupplyTests, HasVoutUVFault)
14642cf46945SBrandon Wyman {
14652cf46945SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
14662cf46945SBrandon Wyman 
1467*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6a,
1468*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
14692cf46945SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
14702cf46945SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
14712cf46945SBrandon Wyman     // Always return 1 to indicate present.
14722cf46945SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
14732cf46945SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1474391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1475ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1476ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1477ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1478ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1479ae35ac5dSBrandon Wyman         .Times(1)
1480ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
1481391a0690SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
14822cf46945SBrandon Wyman     PMBusExpectations expectations;
14832cf46945SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
148482affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
148582affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
148682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
148782affd94SBrandon Wyman         .Times(1)
148882affd94SBrandon Wyman         .WillOnce(Return("204100"));
14892cf46945SBrandon Wyman     psu.analyze();
14902cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
14912cf46945SBrandon Wyman     // Turn fault on.
14922cf46945SBrandon Wyman     expectations.statusWordValue = (status_word::VOUT_FAULT);
14932cf46945SBrandon Wyman     // STATUS_VOUT fault bit(s)
14942cf46945SBrandon Wyman     expectations.statusVOUTValue = 0x30;
1495c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1496c2906f47SBrandon Wyman     {
14972cf46945SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
149882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
149982affd94SBrandon Wyman             .Times(1)
150082affd94SBrandon Wyman             .WillOnce(Return("204200"));
15012cf46945SBrandon Wyman         psu.analyze();
1502c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1503c2906f47SBrandon Wyman     }
15042cf46945SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
15052cf46945SBrandon Wyman     expectations.statusWordValue = 0;
15062cf46945SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
150782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
150882affd94SBrandon Wyman         .Times(1)
150982affd94SBrandon Wyman         .WillOnce(Return("204300"));
15102cf46945SBrandon Wyman     psu.analyze();
15112cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
15122cf46945SBrandon Wyman }
15132cf46945SBrandon Wyman 
15147ee4d7e4SBrandon Wyman TEST_F(PowerSupplyTests, HasFanFault)
15157ee4d7e4SBrandon Wyman {
15167ee4d7e4SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
15177ee4d7e4SBrandon Wyman 
15180975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
15190975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
15200975eaf4SMatt Spinler 
1521*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6d,
1522*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
15237ee4d7e4SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
15247ee4d7e4SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
15257ee4d7e4SBrandon Wyman     // Always return 1 to indicate present.
15267ee4d7e4SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
15277ee4d7e4SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1528391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1529ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1530ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1531ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1532ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1533ae35ac5dSBrandon Wyman         .Times(1)
1534ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
15357ee4d7e4SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
15367ee4d7e4SBrandon Wyman     PMBusExpectations expectations;
15377ee4d7e4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
153882affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
153982affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
154082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
154182affd94SBrandon Wyman         .Times(1)
154282affd94SBrandon Wyman         .WillOnce(Return("205100"));
15437ee4d7e4SBrandon Wyman     psu.analyze();
15447ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
15457ee4d7e4SBrandon Wyman     // Turn fault on.
15467ee4d7e4SBrandon Wyman     expectations.statusWordValue = (status_word::FAN_FAULT);
15477ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
15487ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0x80;
1549c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1550c2906f47SBrandon Wyman     {
15517ee4d7e4SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
155282affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
155382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
155482affd94SBrandon Wyman             .Times(1)
155582affd94SBrandon Wyman             .WillOnce(Return("205200"));
15567ee4d7e4SBrandon Wyman         psu.analyze();
1557c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1558c2906f47SBrandon Wyman     }
15597ee4d7e4SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
15607ee4d7e4SBrandon Wyman     expectations.statusWordValue = 0;
15617ee4d7e4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
156282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
156382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
156482affd94SBrandon Wyman         .Times(1)
156582affd94SBrandon Wyman         .WillOnce(Return("205300"));
15667ee4d7e4SBrandon Wyman     psu.analyze();
15677ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
15687ee4d7e4SBrandon Wyman }
15697ee4d7e4SBrandon Wyman 
157096893a46SBrandon Wyman TEST_F(PowerSupplyTests, HasTempFault)
157196893a46SBrandon Wyman {
157296893a46SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
157396893a46SBrandon Wyman 
15740975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
15750975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
15760975eaf4SMatt Spinler 
1577*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6a,
1578*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
157996893a46SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
158096893a46SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
158196893a46SBrandon Wyman     // Always return 1 to indicate present.
158296893a46SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
158396893a46SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1584391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1585ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1586ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1587ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1588ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1589ae35ac5dSBrandon Wyman         .Times(1)
1590ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
159196893a46SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
159296893a46SBrandon Wyman     PMBusExpectations expectations;
159396893a46SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
159482affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
159582affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
159682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
159782affd94SBrandon Wyman         .Times(1)
159882affd94SBrandon Wyman         .WillOnce(Return("206100"));
159996893a46SBrandon Wyman     psu.analyze();
160096893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
160196893a46SBrandon Wyman     // Turn fault on.
160296893a46SBrandon Wyman     expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
160396893a46SBrandon Wyman     // STATUS_TEMPERATURE fault bit on (OT Fault)
160496893a46SBrandon Wyman     expectations.statusTempValue = 0x80;
1605c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1606c2906f47SBrandon Wyman     {
160796893a46SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
160882affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
160982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
161082affd94SBrandon Wyman             .Times(1)
161182affd94SBrandon Wyman             .WillOnce(Return("206200"));
161296893a46SBrandon Wyman         psu.analyze();
1613c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1614c2906f47SBrandon Wyman     }
161596893a46SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
161696893a46SBrandon Wyman     expectations.statusWordValue = 0;
161796893a46SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
161882affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
161982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
162082affd94SBrandon Wyman         .Times(1)
162182affd94SBrandon Wyman         .WillOnce(Return("206300"));
162296893a46SBrandon Wyman     psu.analyze();
162396893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
162496893a46SBrandon Wyman }
16252916ea52SBrandon Wyman 
16262916ea52SBrandon Wyman TEST_F(PowerSupplyTests, HasPgoodFault)
16272916ea52SBrandon Wyman {
16282916ea52SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
16292916ea52SBrandon Wyman 
1630*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6b,
1631*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
16322916ea52SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
16332916ea52SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
16342916ea52SBrandon Wyman     // Always return 1 to indicate present.
16352916ea52SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
16362916ea52SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1637391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1638ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1639ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1640ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1641ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1642ae35ac5dSBrandon Wyman         .Times(1)
1643ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
16442916ea52SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
16452916ea52SBrandon Wyman     PMBusExpectations expectations;
16462916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
164782affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
164882affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
164982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
165082affd94SBrandon Wyman         .Times(1)
165182affd94SBrandon Wyman         .WillOnce(Return("207100"));
16522916ea52SBrandon Wyman     psu.analyze();
16532916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
1654391a0690SBrandon Wyman     // Setup another expectation of no faults.
1655391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
165682affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
165782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
165882affd94SBrandon Wyman         .Times(1)
165982affd94SBrandon Wyman         .WillOnce(Return("207200"));
166082affd94SBrandon Wyman     psu.analyze();
166182affd94SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
166282affd94SBrandon Wyman     // Setup another expectation of no faults.
166382affd94SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
166482affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
166582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
166682affd94SBrandon Wyman         .Times(1)
166782affd94SBrandon Wyman         .WillOnce(Return("207300"));
1668391a0690SBrandon Wyman     psu.analyze();
1669391a0690SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
16702916ea52SBrandon Wyman     // Turn PGOOD# off (fault on).
16712916ea52SBrandon Wyman     expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
16722916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
167382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
167482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
167582affd94SBrandon Wyman         .Times(1)
167682affd94SBrandon Wyman         .WillOnce(Return("207400"));
16772916ea52SBrandon Wyman     psu.analyze();
16786d469fd4SBrandon Wyman     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 1
167906ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
168006ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
168182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
168282affd94SBrandon Wyman         .Times(1)
168382affd94SBrandon Wyman         .WillOnce(Return("207500"));
168406ca4590SBrandon Wyman     psu.analyze();
16856d469fd4SBrandon Wyman     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 2
168606ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
168706ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
168882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
168982affd94SBrandon Wyman         .Times(1)
169082affd94SBrandon Wyman         .WillOnce(Return("207600"));
169106ca4590SBrandon Wyman     psu.analyze();
16926d469fd4SBrandon Wyman     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 3
16936d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
16946d469fd4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
16956d469fd4SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
16966d469fd4SBrandon Wyman         .Times(1)
16976d469fd4SBrandon Wyman         .WillOnce(Return("207700"));
16986d469fd4SBrandon Wyman     psu.analyze();
16996d469fd4SBrandon Wyman     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 4
17006d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
17016d469fd4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
17026d469fd4SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
17036d469fd4SBrandon Wyman         .Times(1)
17046d469fd4SBrandon Wyman         .WillOnce(Return("207800"));
17056d469fd4SBrandon Wyman     psu.analyze();
17066d469fd4SBrandon Wyman     // Expect true. PGOOD_DEGLITCH_LIMIT @ 5
17072916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
17082916ea52SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
17092916ea52SBrandon Wyman     expectations.statusWordValue = 0;
17102916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
171182affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
171282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
171382affd94SBrandon Wyman         .Times(1)
171482affd94SBrandon Wyman         .WillOnce(Return("207700"));
17152916ea52SBrandon Wyman     psu.analyze();
17162916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
171782affd94SBrandon Wyman 
17182916ea52SBrandon Wyman     // Turn OFF bit on
17192916ea52SBrandon Wyman     expectations.statusWordValue = (status_word::UNIT_IS_OFF);
17202916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
172182affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
172282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
172382affd94SBrandon Wyman         .Times(1)
172482affd94SBrandon Wyman         .WillOnce(Return("208100"));
17252916ea52SBrandon Wyman     psu.analyze();
172606ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
172706ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
172882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
172982affd94SBrandon Wyman         .Times(1)
173082affd94SBrandon Wyman         .WillOnce(Return("208200"));
173106ca4590SBrandon Wyman     psu.analyze();
173206ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
173306ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
173482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
173582affd94SBrandon Wyman         .Times(1)
173682affd94SBrandon Wyman         .WillOnce(Return("208300"));
173706ca4590SBrandon Wyman     psu.analyze();
17386d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
17396d469fd4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
17406d469fd4SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
17416d469fd4SBrandon Wyman         .Times(1)
17426d469fd4SBrandon Wyman         .WillOnce(Return("208400"));
17436d469fd4SBrandon Wyman     psu.analyze();
17446d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
17456d469fd4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
17466d469fd4SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
17476d469fd4SBrandon Wyman         .Times(1)
17486d469fd4SBrandon Wyman         .WillOnce(Return("208500"));
17496d469fd4SBrandon Wyman     psu.analyze();
17502916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
17512916ea52SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
17522916ea52SBrandon Wyman     expectations.statusWordValue = 0;
17532916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
175482affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
175582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
175682affd94SBrandon Wyman         .Times(1)
17576d469fd4SBrandon Wyman         .WillOnce(Return("208000"));
17582916ea52SBrandon Wyman     psu.analyze();
17592916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
17602916ea52SBrandon Wyman }
176139ea02bcSBrandon Wyman 
176239ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPSKillFault)
176339ea02bcSBrandon Wyman {
176439ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1765*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 4,        0x6d,
1766*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
176739ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
176839ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
176939ea02bcSBrandon Wyman     // Always return 1 to indicate present.
177039ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
177139ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
177282affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1773ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1774ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1775ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1776ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1777ae35ac5dSBrandon Wyman         .Times(1)
1778ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
177939ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
178039ea02bcSBrandon Wyman     PMBusExpectations expectations;
178139ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
178282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
178382affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
178482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
178582affd94SBrandon Wyman         .Times(1)
178682affd94SBrandon Wyman         .WillOnce(Return("208100"));
178739ea02bcSBrandon Wyman     psu.analyze();
178839ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
178939ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
179039ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
179139ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
179239ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1793c2906f47SBrandon Wyman 
1794c2906f47SBrandon Wyman     // Deglitching faults, false until read the fault bits on up to the limit.
1795c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1796c2906f47SBrandon Wyman     {
179739ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
179882affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
179982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
180082affd94SBrandon Wyman             .Times(1)
180182affd94SBrandon Wyman             .WillOnce(Return("208200"));
18020975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
18030975eaf4SMatt Spinler         {
18040975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
18050975eaf4SMatt Spinler         }
180639ea02bcSBrandon Wyman         psu.analyze();
1807c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1808c2906f47SBrandon Wyman     }
1809c2906f47SBrandon Wyman 
181039ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
181139ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
181239ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
181382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
181482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
181582affd94SBrandon Wyman         .Times(1)
181682affd94SBrandon Wyman         .WillOnce(Return("208300"));
18170975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
181839ea02bcSBrandon Wyman     psu.analyze();
181939ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
182039ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
182139ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
182239ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 4 on.
182339ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x10;
1824c2906f47SBrandon Wyman 
1825c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1826c2906f47SBrandon Wyman     {
182739ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
182882affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
182982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
183082affd94SBrandon Wyman             .Times(1)
183182affd94SBrandon Wyman             .WillOnce(Return("208400"));
18320975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
18330975eaf4SMatt Spinler         {
18340975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
18350975eaf4SMatt Spinler         }
183639ea02bcSBrandon Wyman         psu.analyze();
1837c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1838c2906f47SBrandon Wyman     }
1839c2906f47SBrandon Wyman 
184039ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
184139ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
184239ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
184382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
184482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
184582affd94SBrandon Wyman         .Times(1)
184682affd94SBrandon Wyman         .WillOnce(Return("208500"));
18470975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
184839ea02bcSBrandon Wyman     psu.analyze();
184939ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
185039ea02bcSBrandon Wyman }
185139ea02bcSBrandon Wyman 
185239ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPS12VcsFault)
185339ea02bcSBrandon Wyman {
185439ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1855*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 5,        0x6e,
1856*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
185739ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
185839ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
185939ea02bcSBrandon Wyman     // Always return 1 to indicate present.
186039ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
186139ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
186282affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1863ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1864ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1865ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1866ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1867ae35ac5dSBrandon Wyman         .Times(1)
1868ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
186939ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
187039ea02bcSBrandon Wyman     PMBusExpectations expectations;
187139ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
187282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
187382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
187482affd94SBrandon Wyman         .Times(1)
187582affd94SBrandon Wyman         .WillOnce(Return("209100"));
187639ea02bcSBrandon Wyman     psu.analyze();
187739ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
187839ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
187939ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
188039ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
188139ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1882c2906f47SBrandon Wyman 
1883c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1884c2906f47SBrandon Wyman     {
188539ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
188682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
188782affd94SBrandon Wyman             .Times(1)
188882affd94SBrandon Wyman             .WillOnce(Return("209200"));
188939ea02bcSBrandon Wyman         psu.analyze();
1890c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1891c2906f47SBrandon Wyman     }
1892c2906f47SBrandon Wyman 
189339ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
189439ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
189539ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
189682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
189782affd94SBrandon Wyman         .Times(1)
189882affd94SBrandon Wyman         .WillOnce(Return("209300"));
189939ea02bcSBrandon Wyman     psu.analyze();
190039ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
190139ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
190239ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
190339ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 6 on.
190439ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x40;
1905c2906f47SBrandon Wyman 
1906c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1907c2906f47SBrandon Wyman     {
190839ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
190982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
191082affd94SBrandon Wyman             .Times(1)
191182affd94SBrandon Wyman             .WillOnce(Return("209400"));
191239ea02bcSBrandon Wyman         psu.analyze();
1913c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1914c2906f47SBrandon Wyman     }
1915c2906f47SBrandon Wyman 
191639ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
191739ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
191839ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
191982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
192082affd94SBrandon Wyman         .Times(1)
192182affd94SBrandon Wyman         .WillOnce(Return("209500"));
192239ea02bcSBrandon Wyman     psu.analyze();
192339ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
192439ea02bcSBrandon Wyman }
192539ea02bcSBrandon Wyman 
192639ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPSCS12VFault)
192739ea02bcSBrandon Wyman {
192839ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1929*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 6,        0x6f,
1930*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
193139ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
193239ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
193339ea02bcSBrandon Wyman     // Always return 1 to indicate present.
193439ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
193539ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
193682affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1937ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1938ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1939ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1940ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1941ae35ac5dSBrandon Wyman         .Times(1)
1942ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
194339ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
194439ea02bcSBrandon Wyman     PMBusExpectations expectations;
194539ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
194682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
194782affd94SBrandon Wyman         .Times(1)
194882affd94SBrandon Wyman         .WillOnce(Return("209100"));
194939ea02bcSBrandon Wyman     psu.analyze();
195039ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
195139ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
195239ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
195339ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
195439ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1955c2906f47SBrandon Wyman 
1956c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1957c2906f47SBrandon Wyman     {
195839ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
195982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
196082affd94SBrandon Wyman             .Times(1)
196182affd94SBrandon Wyman             .WillOnce(Return("209200"));
196239ea02bcSBrandon Wyman         psu.analyze();
1963c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1964c2906f47SBrandon Wyman     }
1965c2906f47SBrandon Wyman 
196639ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
196739ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
196839ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
196982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
197082affd94SBrandon Wyman         .Times(1)
197182affd94SBrandon Wyman         .WillOnce(Return("209300"));
197239ea02bcSBrandon Wyman     psu.analyze();
197339ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
197439ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
197539ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
197639ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 7 on.
197739ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x80;
1978c2906f47SBrandon Wyman 
1979c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1980c2906f47SBrandon Wyman     {
198139ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
198282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
198382affd94SBrandon Wyman             .Times(1)
198482affd94SBrandon Wyman             .WillOnce(Return("209400"));
198539ea02bcSBrandon Wyman         psu.analyze();
1986c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1987c2906f47SBrandon Wyman     }
1988c2906f47SBrandon Wyman 
198939ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
199039ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
199139ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
199282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
199382affd94SBrandon Wyman         .Times(1)
199482affd94SBrandon Wyman         .WillOnce(Return("209500"));
199539ea02bcSBrandon Wyman     psu.analyze();
199639ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
199739ea02bcSBrandon Wyman }
1998c3324424SBrandon Wyman 
1999c3324424SBrandon Wyman TEST_F(PowerSupplyTests, SetupInputHistory)
2000c3324424SBrandon Wyman {
2001c3324424SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
2002c3324424SBrandon Wyman     {
2003*9464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 6,        0x6f,
2004*9464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
2005c3324424SBrandon Wyman         // Defaults to not present due to constructor and mock ordering.
2006c3324424SBrandon Wyman         psu.setupInputHistory();
2007c3324424SBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
2008c3324424SBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
2009c3324424SBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2010ae35ac5dSBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2011c3324424SBrandon Wyman         // Always return 1 to indicate present.
2012c3324424SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2013ae35ac5dSBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
2014ae35ac5dSBrandon Wyman         PMBusExpectations expectations;
2015ae35ac5dSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
2016ae35ac5dSBrandon Wyman         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
2017ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2018ae35ac5dSBrandon Wyman             .Times(1)
2019ae35ac5dSBrandon Wyman             .WillOnce(Return("206000"));
2020ae35ac5dSBrandon Wyman         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2021ae35ac5dSBrandon Wyman         // for INPUT_HISTORY will check max_power_out to see if it is
2022ae35ac5dSBrandon Wyman         // old/unsupported power supply. Indicate good value, supported.
2023ae35ac5dSBrandon Wyman         /// Also called when I redo setupInputHistory().
2024ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2025ae35ac5dSBrandon Wyman             .Times(2)
2026ae35ac5dSBrandon Wyman             .WillRepeatedly(Return("2000"));
2027ae35ac5dSBrandon Wyman         // Call to analyze() and above expectations to get missing/present and
2028ae35ac5dSBrandon Wyman         // good status.
2029c3324424SBrandon Wyman         psu.analyze();
2030c3324424SBrandon Wyman         psu.setupInputHistory();
2031c3324424SBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), true);
2032c3324424SBrandon Wyman     }
2033c3324424SBrandon Wyman     {
2034ae35ac5dSBrandon Wyman         // Workaround - Disable INPUT_HISTORY collection if 1400W
2035*9464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
2036*9464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
2037ae35ac5dSBrandon Wyman         // Defaults to not present due to constructor and mock ordering.
2038ae35ac5dSBrandon Wyman         psu.setupInputHistory();
2039ae35ac5dSBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
2040ae35ac5dSBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
2041ae35ac5dSBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2042ae35ac5dSBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2043ae35ac5dSBrandon Wyman         // Always return 1 to indicate present.
2044ae35ac5dSBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2045ae35ac5dSBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
2046ae35ac5dSBrandon Wyman         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2047ae35ac5dSBrandon Wyman         // for INPUT_HISTORY will check max_power_out to see if it is
2048ae35ac5dSBrandon Wyman         // old/unsupported power supply. Indicate 1400W IBM value, unsupported.
2049ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2050ae35ac5dSBrandon Wyman             .Times(2)
2051ae35ac5dSBrandon Wyman             .WillRepeatedly(Return("30725"));
2052ae35ac5dSBrandon Wyman         PMBusExpectations expectations;
2053ae35ac5dSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
2054ae35ac5dSBrandon Wyman         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
2055ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2056ae35ac5dSBrandon Wyman             .Times(1)
2057ae35ac5dSBrandon Wyman             .WillOnce(Return("206000"));
2058ae35ac5dSBrandon Wyman         // Call to analyze() and above expectations to get missing/present and
2059ae35ac5dSBrandon Wyman         // good status.
2060ae35ac5dSBrandon Wyman         psu.analyze();
2061ae35ac5dSBrandon Wyman         psu.setupInputHistory();
2062ae35ac5dSBrandon Wyman         // After updating to present, and retrying setup, expect ibm-cffps with
2063ae35ac5dSBrandon Wyman         // 1400W to still not support INPUT_HISTORY.
2064ae35ac5dSBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
2065ae35ac5dSBrandon Wyman     }
2066ae35ac5dSBrandon Wyman     {
2067c3324424SBrandon Wyman         PowerSupply psu{bus,      PSUInventoryPath, 11,
2068*9464c429SGeorge Liu                         0x58,     "inspur-ipsps",   PSUGPIOLineName,
2069*9464c429SGeorge Liu                         isPowerOn};
2070c3324424SBrandon Wyman         // Defaults to not present due to constructor and mock ordering.
2071c3324424SBrandon Wyman         psu.setupInputHistory();
2072c3324424SBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
2073c3324424SBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
2074c3324424SBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2075ae35ac5dSBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2076c3324424SBrandon Wyman         // Always return 1 to indicate present.
2077c3324424SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2078ae35ac5dSBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
2079ae35ac5dSBrandon Wyman         PMBusExpectations expectations;
2080ae35ac5dSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
2081ae35ac5dSBrandon Wyman         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
2082ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2083ae35ac5dSBrandon Wyman             .Times(1)
2084ae35ac5dSBrandon Wyman             .WillOnce(Return("206000"));
2085ae35ac5dSBrandon Wyman         // Call to analyze() and above expectations to get missing/present and
2086ae35ac5dSBrandon Wyman         // good status.
2087c3324424SBrandon Wyman         psu.analyze();
2088c3324424SBrandon Wyman         psu.setupInputHistory();
2089c3324424SBrandon Wyman         // After updating to present, and retrying setup, expect inspur-ipsps to
2090c3324424SBrandon Wyman         // still not support INPUT_HISTORY.
2091c3324424SBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
2092c3324424SBrandon Wyman     }
2093c3324424SBrandon Wyman }
2094c3324424SBrandon Wyman 
2095c3324424SBrandon Wyman TEST_F(PowerSupplyTests, UpdateHistory)
2096c3324424SBrandon Wyman {
2097c3324424SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
2098*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 7,        0x6e,
2099*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
2100c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), false);
2101c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
2102c3324424SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
2103c3324424SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2104c3324424SBrandon Wyman     // Always return 1 to indicate present.
2105c3324424SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2106c3324424SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2107c3324424SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
2108ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2109ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
2110ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
2111ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2112ae35ac5dSBrandon Wyman         .Times(1)
2113ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
2114c3324424SBrandon Wyman     PMBusExpectations expectations;
2115c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2116c3324424SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2117c3324424SBrandon Wyman         .Times(6)
2118c3324424SBrandon Wyman         .WillRepeatedly(Return("205000"));
2119c3324424SBrandon Wyman     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
2120c3324424SBrandon Wyman     // First read after missing/present will have no data.
2121c3324424SBrandon Wyman     std::vector<uint8_t> emptyHistory{};
2122c3324424SBrandon Wyman     // Second read, after about 30 seconds, should have a record. 5-bytes.
2123c3324424SBrandon Wyman     // Sequence Number: 0x00, Average: 0x50 0xf3 (212), Maximum: 0x54 0xf3 (213)
2124c3324424SBrandon Wyman     std::vector<uint8_t> firstHistory{0x00, 0x50, 0xf3, 0x54, 0xf3};
2125c3324424SBrandon Wyman     // Third read, after about 60 seconds, should have two records, 10-bytes,
2126c3324424SBrandon Wyman     // but only reading 5 bytes, so make sure new/next sequence number
2127c3324424SBrandon Wyman     std::vector<uint8_t> secondHistory{0x01, 0x54, 0xf3, 0x58, 0xf3};
2128c3324424SBrandon Wyman     // Fourth read, 3rd sequence number (0x02).
2129c3324424SBrandon Wyman     std::vector<uint8_t> thirdHistory{0x02, 0x54, 0xf3, 0x58, 0xf3};
2130c3324424SBrandon Wyman     // Fifth read, out of sequence, clear and insert this one?
2131c3324424SBrandon Wyman     std::vector<uint8_t> outseqHistory{0xff, 0x5c, 0xf3, 0x60, 0xf3};
2132c3324424SBrandon Wyman     EXPECT_CALL(
2133c3324424SBrandon Wyman         mockPMBus,
2134c3324424SBrandon Wyman         readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug,
2135c3324424SBrandon Wyman                    phosphor::power::history::RecordManager::RAW_RECORD_SIZE))
2136c3324424SBrandon Wyman         .Times(6)
2137c3324424SBrandon Wyman         .WillOnce(Return(emptyHistory))
2138c3324424SBrandon Wyman         .WillOnce(Return(firstHistory))
2139c3324424SBrandon Wyman         .WillOnce(Return(secondHistory))
2140c3324424SBrandon Wyman         .WillOnce(Return(thirdHistory))
2141c3324424SBrandon Wyman         .WillOnce(Return(outseqHistory))
2142c3324424SBrandon Wyman         .WillOnce(Return(emptyHistory));
2143c3324424SBrandon Wyman     // Calling analyze will update the presence, which will setup the input
2144c3324424SBrandon Wyman     // history if the power supply went from missing to present.
2145c3324424SBrandon Wyman     psu.analyze();
2146c3324424SBrandon Wyman     // The ibm-cffps power supply should support input history
2147c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2148c3324424SBrandon Wyman     // Usually should have empty buffer right after missing to present.
2149c3324424SBrandon Wyman     // Faked that out above with mocked readBinary with emptyHistory data.
2150c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
2151c3324424SBrandon Wyman     // Second run through...
2152c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2153c3324424SBrandon Wyman     psu.analyze();
2154c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2155c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 1);
2156c3324424SBrandon Wyman     // Third run through
2157c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2158c3324424SBrandon Wyman     psu.analyze();
2159c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2160c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 2);
2161c3324424SBrandon Wyman     // Fourth run through. Up to 3 records now?
2162c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2163c3324424SBrandon Wyman     psu.analyze();
2164c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2165c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 3);
2166c3324424SBrandon Wyman     // Out of sequencer, reset, insert new one.
2167c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2168c3324424SBrandon Wyman     psu.analyze();
2169c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2170c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 1);
2171c3324424SBrandon Wyman     // Empty one after last one good. Reset/clear.
2172c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2173c3324424SBrandon Wyman     psu.analyze();
2174c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2175c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
2176c3324424SBrandon Wyman }
217718a24d92SBrandon Wyman 
217818a24d92SBrandon Wyman TEST_F(PowerSupplyTests, IsSyncHistoryRequired)
217918a24d92SBrandon Wyman {
218018a24d92SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
2181*9464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 8,        0x6f,
2182*9464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
218318a24d92SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), false);
218418a24d92SBrandon Wyman     EXPECT_EQ(psu.isSyncHistoryRequired(), false);
218518a24d92SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
218618a24d92SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
218718a24d92SBrandon Wyman     // Always return 1 to indicate present.
218818a24d92SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
218918a24d92SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
219018a24d92SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
2191ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2192ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
2193ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
2194ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2195ae35ac5dSBrandon Wyman         .Times(1)
2196ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
219718a24d92SBrandon Wyman     PMBusExpectations expectations;
219818a24d92SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
219918a24d92SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
220018a24d92SBrandon Wyman         .Times(1)
220118a24d92SBrandon Wyman         .WillRepeatedly(Return("205000"));
220218a24d92SBrandon Wyman     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
220318a24d92SBrandon Wyman     psu.analyze();
220418a24d92SBrandon Wyman     // The ibm-cffps power supply should support input history
220518a24d92SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
220618a24d92SBrandon Wyman     // Missing -> Present requires history sync
220718a24d92SBrandon Wyman     EXPECT_EQ(psu.isSyncHistoryRequired(), true);
220818a24d92SBrandon Wyman     psu.clearSyncHistoryRequired();
220918a24d92SBrandon Wyman     EXPECT_EQ(psu.isSyncHistoryRequired(), false);
221018a24d92SBrandon Wyman }
2211