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;
19*592bd27cSMatt Spinler using ::testing::IsNan;
2059a35793SBrandon Wyman using ::testing::NotNull;
213f1242f3SBrandon Wyman using ::testing::Return;
223f1242f3SBrandon Wyman using ::testing::StrEq;
233f1242f3SBrandon Wyman 
243f1242f3SBrandon Wyman static auto PSUInventoryPath = "/xyz/bmc/inv/sys/chassis/board/powersupply0";
25681b2a36SB. J. Wyman static auto PSUGPIOLineName = "presence-ps0";
269464c429SGeorge Liu static auto isPowerOn = []() { return true; };
273f1242f3SBrandon Wyman 
28b654c619SBrandon Wyman struct PMBusExpectations
29b654c619SBrandon Wyman {
30b654c619SBrandon Wyman     uint16_t statusWordValue{0x0000};
31b654c619SBrandon Wyman     uint8_t statusInputValue{0x00};
32b654c619SBrandon Wyman     uint8_t statusMFRValue{0x00};
33b654c619SBrandon Wyman     uint8_t statusCMLValue{0x00};
34b654c619SBrandon Wyman     uint8_t statusVOUTValue{0x00};
35b10b3be0SBrandon Wyman     uint8_t statusIOUTValue{0x00};
367ee4d7e4SBrandon Wyman     uint8_t statusFans12Value{0x00};
3796893a46SBrandon Wyman     uint8_t statusTempValue{0x00};
38b654c619SBrandon Wyman };
39b654c619SBrandon Wyman 
408da35c51SBrandon Wyman // Helper function to setup expectations for various STATUS_* commands
41b654c619SBrandon Wyman void setPMBusExpectations(MockedPMBus& mockPMBus,
42b654c619SBrandon Wyman                           const PMBusExpectations& expectations)
438da35c51SBrandon Wyman {
4432453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _, _))
458da35c51SBrandon Wyman         .Times(1)
46b654c619SBrandon Wyman         .WillOnce(Return(expectations.statusWordValue));
478da35c51SBrandon Wyman 
48b654c619SBrandon Wyman     if (expectations.statusWordValue != 0)
498da35c51SBrandon Wyman     {
508da35c51SBrandon Wyman         // If fault bits are on in STATUS_WORD, there will also be a read of
5196893a46SBrandon Wyman         // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and
5296893a46SBrandon Wyman         // STATUS_TEMPERATURE.
5332453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _, _))
548da35c51SBrandon Wyman             .Times(1)
55b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusInputValue));
5632453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_MFR, _, _))
578da35c51SBrandon Wyman             .Times(1)
58b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusMFRValue));
5932453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_CML, _, _))
608da35c51SBrandon Wyman             .Times(1)
61b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusCMLValue));
626710ba2cSBrandon Wyman         // Page will need to be set to 0 to read STATUS_VOUT.
636710ba2cSBrandon Wyman         EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0))
646710ba2cSBrandon Wyman             .Times(1)
656710ba2cSBrandon Wyman             .WillOnce(Return("status0_vout"));
6632453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read("status0_vout", _, _))
676710ba2cSBrandon Wyman             .Times(1)
68b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusVOUTValue));
6932453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _, _))
70b10b3be0SBrandon Wyman             .Times(1)
71b10b3be0SBrandon Wyman             .WillOnce(Return(expectations.statusIOUTValue));
7232453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _, _))
737ee4d7e4SBrandon Wyman             .Times(1)
747ee4d7e4SBrandon Wyman             .WillOnce(Return(expectations.statusFans12Value));
7532453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _, _))
7696893a46SBrandon Wyman             .Times(1)
7796893a46SBrandon Wyman             .WillOnce(Return(expectations.statusTempValue));
788da35c51SBrandon Wyman     }
79*592bd27cSMatt Spinler 
80*592bd27cSMatt Spinler     // Default max/peak is 213W
81*592bd27cSMatt Spinler     ON_CALL(mockPMBus, readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug, 5))
82*592bd27cSMatt Spinler         .WillByDefault(
83*592bd27cSMatt Spinler             Return(std::vector<uint8_t>{0x01, 0x5c, 0xf3, 0x54, 0xf3}));
848da35c51SBrandon Wyman }
858da35c51SBrandon Wyman 
863f1242f3SBrandon Wyman class PowerSupplyTests : public ::testing::Test
873f1242f3SBrandon Wyman {
883f1242f3SBrandon Wyman   public:
893f1242f3SBrandon Wyman     PowerSupplyTests() :
903f1242f3SBrandon Wyman         mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
913f1242f3SBrandon Wyman     {
923f1242f3SBrandon Wyman         ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
933f1242f3SBrandon Wyman     }
943f1242f3SBrandon Wyman 
953f1242f3SBrandon Wyman     ~PowerSupplyTests() override
963f1242f3SBrandon Wyman     {
973f1242f3SBrandon Wyman         freeUtils();
983f1242f3SBrandon Wyman     }
993f1242f3SBrandon Wyman 
1003f1242f3SBrandon Wyman     const MockedUtil& mockedUtil;
1013f1242f3SBrandon Wyman };
1023f1242f3SBrandon Wyman 
103391a0690SBrandon Wyman // Helper function for when a power supply goes from missing to present.
104391a0690SBrandon Wyman void setMissingToPresentExpects(MockedPMBus& pmbus, const MockedUtil& util)
105391a0690SBrandon Wyman {
106391a0690SBrandon Wyman     // Call to analyze() will update to present, that will trigger updating
107391a0690SBrandon Wyman     // to the correct/latest HWMON directory, in case it changes.
108391a0690SBrandon Wyman     EXPECT_CALL(pmbus, findHwmonDir());
109391a0690SBrandon Wyman     // Presence change from missing to present will trigger write to
110391a0690SBrandon Wyman     // ON_OFF_CONFIG.
111391a0690SBrandon Wyman     EXPECT_CALL(pmbus, writeBinary(ON_OFF_CONFIG, _, _));
112391a0690SBrandon Wyman     // Presence change from missing to present will trigger in1_input read
113391a0690SBrandon Wyman     // in an attempt to get CLEAR_FAULTS called.
11482affd94SBrandon Wyman     // This READ_VIN for CLEAR_FAULTS does not check the returned value.
1153225a45cSBrandon Wyman     EXPECT_CALL(pmbus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
1163225a45cSBrandon Wyman     // The call for clearing faults includes clearing VIN_UV fault.
1173225a45cSBrandon Wyman     // The voltage defaults to 0, the first call to analyze should update the
1183225a45cSBrandon Wyman     // voltage to the current reading, triggering clearing VIN_UV fault(s)
1193225a45cSBrandon Wyman     // due to below minimum to within range voltage.
1203225a45cSBrandon Wyman     EXPECT_CALL(pmbus, read("in1_lcrit_alarm", _, _))
12182affd94SBrandon Wyman         .Times(2)
1223225a45cSBrandon Wyman         .WillRepeatedly(Return(1));
123391a0690SBrandon Wyman     // Missing/present call will update Presence in inventory.
124391a0690SBrandon Wyman     EXPECT_CALL(util, setPresence(_, _, true, _));
125391a0690SBrandon Wyman }
126391a0690SBrandon Wyman 
1273f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Constructor)
1283f1242f3SBrandon Wyman {
1293f1242f3SBrandon Wyman     /**
1303f1242f3SBrandon Wyman      * @param[in] invpath - String for inventory path to use
1313f1242f3SBrandon Wyman      * @param[in] i2cbus - The bus number this power supply is on
1323f1242f3SBrandon Wyman      * @param[in] i2caddr - The 16-bit I2C address of the power supply
133681b2a36SB. J. Wyman      * @param[in] gpioLineName - The string for the gpio-line-name to read for
134681b2a36SB. J. Wyman      * presence.
135681b2a36SB. J. Wyman      * @param[in] bindDelay - Time in milliseconds to delay binding the device
136681b2a36SB. J. Wyman      * driver after seeing the presence line go active.
1373f1242f3SBrandon Wyman      */
1383f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1391d7a7df8SBrandon Wyman 
1401d7a7df8SBrandon Wyman     // Try where inventory path is empty, constructor should fail.
1411d7a7df8SBrandon Wyman     try
1421d7a7df8SBrandon Wyman     {
143c3324424SBrandon Wyman         auto psu = std::make_unique<PowerSupply>(bus, "", 3, 0x68, "ibm-cffps",
1449464c429SGeorge Liu                                                  PSUGPIOLineName, isPowerOn);
1451d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have reached this line.";
1461d7a7df8SBrandon Wyman     }
1471d7a7df8SBrandon Wyman     catch (const std::invalid_argument& e)
1481d7a7df8SBrandon Wyman     {
1491d7a7df8SBrandon Wyman         EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
1501d7a7df8SBrandon Wyman     }
1511d7a7df8SBrandon Wyman     catch (...)
1521d7a7df8SBrandon Wyman     {
1531d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
1541d7a7df8SBrandon Wyman     }
1551d7a7df8SBrandon Wyman 
156681b2a36SB. J. Wyman     // TODO: Try invalid i2c address?
157681b2a36SB. J. Wyman 
158681b2a36SB. J. Wyman     // Try where gpioLineName is empty.
1591d7a7df8SBrandon Wyman     try
1601d7a7df8SBrandon Wyman     {
161c3324424SBrandon Wyman         auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
1629464c429SGeorge Liu                                                  "ibm-cffps", "", isPowerOn);
163681b2a36SB. J. Wyman         ADD_FAILURE()
164681b2a36SB. J. Wyman             << "Should not have reached this line. Invalid gpioLineName.";
165681b2a36SB. J. Wyman     }
166681b2a36SB. J. Wyman     catch (const std::invalid_argument& e)
167681b2a36SB. J. Wyman     {
168681b2a36SB. J. Wyman         EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
169681b2a36SB. J. Wyman     }
170681b2a36SB. J. Wyman     catch (...)
171681b2a36SB. J. Wyman     {
172681b2a36SB. J. Wyman         ADD_FAILURE() << "Should not have caught exception.";
173681b2a36SB. J. Wyman     }
174681b2a36SB. J. Wyman 
175681b2a36SB. J. Wyman     // Test with valid arguments
176681b2a36SB. J. Wyman     // NOT using D-Bus inventory path for presence.
177681b2a36SB. J. Wyman     try
178681b2a36SB. J. Wyman     {
179681b2a36SB. J. Wyman         auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
1809464c429SGeorge Liu                                                  "ibm-cffps", PSUGPIOLineName,
1819464c429SGeorge Liu                                                  isPowerOn);
1823f1242f3SBrandon Wyman 
1833f1242f3SBrandon Wyman         EXPECT_EQ(psu->isPresent(), false);
1843f1242f3SBrandon Wyman         EXPECT_EQ(psu->isFaulted(), false);
1858da35c51SBrandon Wyman         EXPECT_EQ(psu->hasCommFault(), false);
1863f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasInputFault(), false);
1873f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasMFRFault(), false);
1883f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasVINUVFault(), false);
1896710ba2cSBrandon Wyman         EXPECT_EQ(psu->hasVoutOVFault(), false);
190b10b3be0SBrandon Wyman         EXPECT_EQ(psu->hasIoutOCFault(), false);
1912cf46945SBrandon Wyman         EXPECT_EQ(psu->hasVoutUVFault(), false);
1927ee4d7e4SBrandon Wyman         EXPECT_EQ(psu->hasFanFault(), false);
19396893a46SBrandon Wyman         EXPECT_EQ(psu->hasTempFault(), false);
1942916ea52SBrandon Wyman         EXPECT_EQ(psu->hasPgoodFault(), false);
19539ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPSKillFault(), false);
19639ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPS12VcsFault(), false);
19739ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPSCS12VFault(), false);
1983f1242f3SBrandon Wyman     }
1991d7a7df8SBrandon Wyman     catch (...)
2001d7a7df8SBrandon Wyman     {
2011d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
2021d7a7df8SBrandon Wyman     }
203681b2a36SB. J. Wyman 
204681b2a36SB. J. Wyman     // Test with valid arguments
205681b2a36SB. J. Wyman     // TODO: Using D-Bus inventory path for presence.
206681b2a36SB. J. Wyman     try
207681b2a36SB. J. Wyman     {
208681b2a36SB. J. Wyman         // FIXME: How do I get that presenceGPIO.read() in the startup to throw
209681b2a36SB. J. Wyman         // an exception?
210681b2a36SB. J. Wyman 
211681b2a36SB. J. Wyman         // EXPECT_CALL(mockedUtil, getPresence(_,
212681b2a36SB. J. Wyman         // StrEq(PSUInventoryPath)))
213681b2a36SB. J. Wyman         //    .Times(1);
214681b2a36SB. J. Wyman     }
215681b2a36SB. J. Wyman     catch (...)
216681b2a36SB. J. Wyman     {
217681b2a36SB. J. Wyman         ADD_FAILURE() << "Should not have caught exception.";
218681b2a36SB. J. Wyman     }
2191d7a7df8SBrandon Wyman }
2203f1242f3SBrandon Wyman 
2213f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Analyze)
2223f1242f3SBrandon Wyman {
2233f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
2243f1242f3SBrandon Wyman 
225b654c619SBrandon Wyman     {
226681b2a36SB. J. Wyman         // If I default to reading the GPIO, I will NOT expect a call to
227681b2a36SB. J. Wyman         // getPresence().
228681b2a36SB. J. Wyman 
2299464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 4,        0x69,
2309464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
2313ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
2323ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
233681b2a36SB. J. Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
234681b2a36SB. J. Wyman 
2353f1242f3SBrandon Wyman         psu.analyze();
2363f1242f3SBrandon Wyman         // By default, nothing should change.
2373f1242f3SBrandon Wyman         EXPECT_EQ(psu.isPresent(), false);
2383f1242f3SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), false);
2393f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), false);
2403f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), false);
2413f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), false);
24285c7bf41SBrandon Wyman         EXPECT_EQ(psu.hasCommFault(), false);
2436710ba2cSBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), false);
244b10b3be0SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), false);
2452cf46945SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), false);
2467ee4d7e4SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), false);
24796893a46SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), false);
2482916ea52SBrandon Wyman         EXPECT_EQ(psu.hasPgoodFault(), false);
24939ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), false);
25039ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), false);
25139ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), false);
252b654c619SBrandon Wyman     }
2533f1242f3SBrandon Wyman 
2549464c429SGeorge Liu     PowerSupply psu2{bus,         PSUInventoryPath, 5,        0x6a,
2559464c429SGeorge Liu                      "ibm-cffps", PSUGPIOLineName,  isPowerOn};
256681b2a36SB. J. Wyman     // In order to get the various faults tested, the power supply needs to
257681b2a36SB. J. Wyman     // be present in order to read from the PMBus device(s).
2583ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO2 =
2593ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
26006ca4590SBrandon Wyman     // Always return 1 to indicate present.
26106ca4590SBrandon Wyman     // Each analyze() call will trigger a read of the presence GPIO.
26206ca4590SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1));
263681b2a36SB. J. Wyman     EXPECT_EQ(psu2.isPresent(), false);
2643f1242f3SBrandon Wyman 
2653f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
266391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
267ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
268ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
269ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
270ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
271*592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
272b654c619SBrandon Wyman 
273b654c619SBrandon Wyman     // STATUS_WORD INPUT fault.
274b654c619SBrandon Wyman     {
275b654c619SBrandon Wyman         // Start with STATUS_WORD 0x0000. Powered on, no faults.
276b654c619SBrandon Wyman         // Set expectations for a no fault
277b654c619SBrandon Wyman         PMBusExpectations expectations;
278b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
27982affd94SBrandon Wyman         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
28082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
28182affd94SBrandon Wyman             .Times(1)
28282affd94SBrandon Wyman             .WillOnce(Return("206000"));
2833f1242f3SBrandon Wyman         psu2.analyze();
2843f1242f3SBrandon Wyman         EXPECT_EQ(psu2.isPresent(), true);
2853f1242f3SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
2863f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
2873f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasMFRFault(), false);
2883f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasVINUVFault(), false);
28985c7bf41SBrandon Wyman         EXPECT_EQ(psu2.hasCommFault(), false);
2906710ba2cSBrandon Wyman         EXPECT_EQ(psu2.hasVoutOVFault(), false);
291b10b3be0SBrandon Wyman         EXPECT_EQ(psu2.hasIoutOCFault(), false);
2922cf46945SBrandon Wyman         EXPECT_EQ(psu2.hasVoutUVFault(), false);
2937ee4d7e4SBrandon Wyman         EXPECT_EQ(psu2.hasFanFault(), false);
29496893a46SBrandon Wyman         EXPECT_EQ(psu2.hasTempFault(), false);
2952916ea52SBrandon Wyman         EXPECT_EQ(psu2.hasPgoodFault(), false);
29639ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPSKillFault(), false);
29739ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPS12VcsFault(), false);
29839ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPSCS12VFault(), false);
2993f1242f3SBrandon Wyman 
300b654c619SBrandon Wyman         // Update expectations for STATUS_WORD input fault/warn
30196893a46SBrandon Wyman         // STATUS_INPUT fault bits ... on.
302b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
3033225a45cSBrandon Wyman         // IIN_OC fault.
3043225a45cSBrandon Wyman         expectations.statusInputValue = 0x04;
305c2906f47SBrandon Wyman 
306c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
307c2906f47SBrandon Wyman         {
308b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
30982affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
31082affd94SBrandon Wyman                 .Times(1)
31182affd94SBrandon Wyman                 .WillOnce(Return("207000"));
3123f1242f3SBrandon Wyman             psu2.analyze();
3133f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
314c2906f47SBrandon Wyman             // Should not be faulted until it reaches the deglitch limit.
315c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
316c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
3173f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
3183f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
31985c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
3206710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
321b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
3222cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
3237ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
32496893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
3252916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
32639ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
32739ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
32839ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
329b654c619SBrandon Wyman         }
330c2906f47SBrandon Wyman     }
331c2906f47SBrandon Wyman 
33232453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
3333225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
3343225a45cSBrandon Wyman         .Times(1)
3353225a45cSBrandon Wyman         .WillOnce(Return(1));
336c2906f47SBrandon Wyman     psu2.clearFaults();
3373f1242f3SBrandon Wyman 
3383f1242f3SBrandon Wyman     // STATUS_WORD INPUT/UV fault.
339b654c619SBrandon Wyman     {
3403f1242f3SBrandon Wyman         // First need it to return good status, then the fault
341b654c619SBrandon Wyman         PMBusExpectations expectations;
342b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
34382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
34482affd94SBrandon Wyman             .Times(1)
34582affd94SBrandon Wyman             .WillOnce(Return("208000"));
3463f1242f3SBrandon Wyman         psu2.analyze();
347c2906f47SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
348c2906f47SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
3498da35c51SBrandon Wyman         // Now set fault bits in STATUS_WORD
350b654c619SBrandon Wyman         expectations.statusWordValue =
3518da35c51SBrandon Wyman             (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
3528da35c51SBrandon Wyman         // STATUS_INPUT fault bits ... on.
3533225a45cSBrandon Wyman         expectations.statusInputValue = 0x18;
354c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
355c2906f47SBrandon Wyman         {
356b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
35782affd94SBrandon Wyman             // Input/UV fault, so voltage should read back low.
35882affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
35982affd94SBrandon Wyman                 .Times(1)
36082affd94SBrandon Wyman                 .WillOnce(Return("19123"));
3613f1242f3SBrandon Wyman             psu2.analyze();
3623f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
363c2906f47SBrandon Wyman             // Only faulted if hit deglitch limit
364c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
365c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
366c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), x >= DEGLITCH_LIMIT);
3673f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
36885c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
3696710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
370b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
3712cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
3727ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
37396893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
3742916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
37539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
37639ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
37739ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
378c2906f47SBrandon Wyman         }
37982affd94SBrandon Wyman         // Turning VIN_UV fault off causes clearing of faults, causing read of
38082affd94SBrandon Wyman         // in1_input as an attempt to get CLEAR_FAULTS called.
38182affd94SBrandon Wyman         expectations.statusWordValue = 0;
38282affd94SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
38382affd94SBrandon Wyman         // The call to read the voltage
38482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
38582affd94SBrandon Wyman             .Times(1)
38682affd94SBrandon Wyman             .WillOnce(Return("209000"));
3873225a45cSBrandon Wyman         // The call to clear VIN_UV/Off fault(s)
3883225a45cSBrandon Wyman         EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
38932453e9bSBrandon Wyman             .Times(1)
3903225a45cSBrandon Wyman             .WillOnce(Return(1));
39182affd94SBrandon Wyman         psu2.analyze();
39282affd94SBrandon Wyman         // Should remain present, no longer be faulted, no input fault, no
39382affd94SBrandon Wyman         // VIN_UV fault. Nothing else should change.
39482affd94SBrandon Wyman         EXPECT_EQ(psu2.isPresent(), true);
39582affd94SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
39682affd94SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
39782affd94SBrandon Wyman         EXPECT_EQ(psu2.hasVINUVFault(), false);
398b654c619SBrandon Wyman     }
3993f1242f3SBrandon Wyman 
40032453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
4013225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
4023225a45cSBrandon Wyman         .Times(1)
4033225a45cSBrandon Wyman         .WillOnce(Return(1));
404c2906f47SBrandon Wyman     psu2.clearFaults();
405c2906f47SBrandon Wyman 
4063f1242f3SBrandon Wyman     // STATUS_WORD MFR fault.
407b654c619SBrandon Wyman     {
408f07bc797SBrandon Wyman         // First need it to return good status, then the fault
409b654c619SBrandon Wyman         PMBusExpectations expectations;
410b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
41182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
41282affd94SBrandon Wyman             .Times(1)
41382affd94SBrandon Wyman             .WillOnce(Return("210000"));
4143f1242f3SBrandon Wyman         psu2.analyze();
4158da35c51SBrandon Wyman         // Now STATUS_WORD with MFR fault bit on.
416b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
4178da35c51SBrandon Wyman         // STATUS_MFR bits on.
418b654c619SBrandon Wyman         expectations.statusMFRValue = 0xFF;
419c2906f47SBrandon Wyman 
420c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
421c2906f47SBrandon Wyman         {
422b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
42382affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
42482affd94SBrandon Wyman                 .Times(1)
42582affd94SBrandon Wyman                 .WillOnce(Return("211000"));
4263f1242f3SBrandon Wyman             psu2.analyze();
4273f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
428c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
4293f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
430c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT);
431c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT);
432c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
433c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
4343f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
43585c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
4366710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
437b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
4382cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
4397ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
44096893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
4412916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
442c2906f47SBrandon Wyman         }
443b654c619SBrandon Wyman     }
4443f1242f3SBrandon Wyman 
44532453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
4463225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
4473225a45cSBrandon Wyman         .Times(1)
4483225a45cSBrandon Wyman         .WillOnce(Return(1));
449c2906f47SBrandon Wyman     psu2.clearFaults();
4503225a45cSBrandon Wyman 
45196893a46SBrandon Wyman     // Temperature fault.
452b654c619SBrandon Wyman     {
453f07bc797SBrandon Wyman         // First STATUS_WORD with no bits set, then with temperature fault.
454b654c619SBrandon Wyman         PMBusExpectations expectations;
455b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
45682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
45782affd94SBrandon Wyman             .Times(1)
45882affd94SBrandon Wyman             .WillOnce(Return("212000"));
4593f1242f3SBrandon Wyman         psu2.analyze();
4608da35c51SBrandon Wyman         // STATUS_WORD with temperature fault bit on.
461b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
46296893a46SBrandon Wyman         // STATUS_TEMPERATURE with fault bit(s) on.
46396893a46SBrandon Wyman         expectations.statusTempValue = 0x10;
464c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
465c2906f47SBrandon Wyman         {
466b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
46782affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
46882affd94SBrandon Wyman                 .Times(1)
46982affd94SBrandon Wyman                 .WillOnce(Return("213000"));
4703f1242f3SBrandon Wyman             psu2.analyze();
4713f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
472c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
4733f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
4743f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
4753f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
47685c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
4776710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
478b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
4792cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
4807ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
481c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT);
4822916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
48339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
48439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
48539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
486b654c619SBrandon Wyman         }
487c2906f47SBrandon Wyman     }
48885c7bf41SBrandon Wyman 
48932453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
4903225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
4913225a45cSBrandon Wyman         .Times(1)
4923225a45cSBrandon Wyman         .WillOnce(Return(1));
493c2906f47SBrandon Wyman     psu2.clearFaults();
4943225a45cSBrandon Wyman 
49585c7bf41SBrandon Wyman     // CML fault
496b654c619SBrandon Wyman     {
49785c7bf41SBrandon Wyman         // First STATUS_WORD wit no bits set, then with CML fault.
498b654c619SBrandon Wyman         PMBusExpectations expectations;
499b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
50082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
50182affd94SBrandon Wyman             .Times(1)
50282affd94SBrandon Wyman             .WillOnce(Return("214000"));
50385c7bf41SBrandon Wyman         psu2.analyze();
5048da35c51SBrandon Wyman         // STATUS_WORD with CML fault bit on.
505b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::CML_FAULT);
50685c7bf41SBrandon Wyman         // Turn on STATUS_CML fault bit(s)
507b654c619SBrandon Wyman         expectations.statusCMLValue = 0xFF;
508c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
509c2906f47SBrandon Wyman         {
510b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
51182affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
51282affd94SBrandon Wyman                 .Times(1)
51382affd94SBrandon Wyman                 .WillOnce(Return("215000"));
51485c7bf41SBrandon Wyman             psu2.analyze();
51585c7bf41SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
516c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
517c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), x >= DEGLITCH_LIMIT);
51885c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
51985c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
52085c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
5216710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
522b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
5232cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
5247ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
52596893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
5262916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
52739ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
52839ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
52939ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
530b654c619SBrandon Wyman         }
531c2906f47SBrandon Wyman     }
5326710ba2cSBrandon Wyman 
53332453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
5343225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
5353225a45cSBrandon Wyman         .Times(1)
5363225a45cSBrandon Wyman         .WillOnce(Return(1));
537c2906f47SBrandon Wyman     psu2.clearFaults();
5383225a45cSBrandon Wyman 
5396710ba2cSBrandon Wyman     // VOUT_OV_FAULT fault
540b654c619SBrandon Wyman     {
5416710ba2cSBrandon Wyman         // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
542b654c619SBrandon Wyman         PMBusExpectations expectations;
543b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
54482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
54582affd94SBrandon Wyman             .Times(1)
54682affd94SBrandon Wyman             .WillOnce(Return("216000"));
5476710ba2cSBrandon Wyman         psu2.analyze();
5486710ba2cSBrandon Wyman         // STATUS_WORD with VOUT/VOUT_OV fault.
549b654c619SBrandon Wyman         expectations.statusWordValue =
5506710ba2cSBrandon Wyman             ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
5516710ba2cSBrandon Wyman         // Turn on STATUS_VOUT fault bit(s)
552b654c619SBrandon Wyman         expectations.statusVOUTValue = 0xA0;
553c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
554c2906f47SBrandon Wyman         {
55596893a46SBrandon Wyman             // STATUS_TEMPERATURE don't care (default)
556b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
55782affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
55882affd94SBrandon Wyman                 .Times(1)
55982affd94SBrandon Wyman                 .WillOnce(Return("217000"));
5606710ba2cSBrandon Wyman             psu2.analyze();
5616710ba2cSBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
562c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
5636710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
5646710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
5656710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
5666710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
567c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
5682cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
569b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
5707ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
571b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
572b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
57339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
57439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
57539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
576b10b3be0SBrandon Wyman         }
577c2906f47SBrandon Wyman     }
578b10b3be0SBrandon Wyman 
579b10b3be0SBrandon Wyman     // IOUT_OC_FAULT fault
580b10b3be0SBrandon Wyman     {
581b10b3be0SBrandon Wyman         // First STATUS_WORD with no bits set, then with IOUT_OC fault.
582b10b3be0SBrandon Wyman         PMBusExpectations expectations;
583b10b3be0SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
58482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
58582affd94SBrandon Wyman             .Times(1)
58682affd94SBrandon Wyman             .WillOnce(Return("218000"));
587b10b3be0SBrandon Wyman         psu2.analyze();
588b10b3be0SBrandon Wyman         // STATUS_WORD with IOUT_OC fault.
589b10b3be0SBrandon Wyman         expectations.statusWordValue = status_word::IOUT_OC_FAULT;
590b10b3be0SBrandon Wyman         // Turn on STATUS_IOUT fault bit(s)
591b10b3be0SBrandon Wyman         expectations.statusIOUTValue = 0x88;
592c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
593c2906f47SBrandon Wyman         {
594b10b3be0SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
59582affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
59682affd94SBrandon Wyman                 .Times(1)
59782affd94SBrandon Wyman                 .WillOnce(Return("219000"));
598b10b3be0SBrandon Wyman             psu2.analyze();
599b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
600c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
601b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
602b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
603b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
604b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
605b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
606c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
6072cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
6087ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
6092cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6102cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
61139ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
61239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
61339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
6142cf46945SBrandon Wyman         }
615c2906f47SBrandon Wyman     }
6162cf46945SBrandon Wyman 
6172cf46945SBrandon Wyman     // VOUT_UV_FAULT
6182cf46945SBrandon Wyman     {
6192cf46945SBrandon Wyman         // First STATUS_WORD with no bits set, then with VOUT fault.
6202cf46945SBrandon Wyman         PMBusExpectations expectations;
6212cf46945SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
62282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
62382affd94SBrandon Wyman             .Times(1)
62482affd94SBrandon Wyman             .WillOnce(Return("220000"));
6252cf46945SBrandon Wyman         psu2.analyze();
6262cf46945SBrandon Wyman         // Change STATUS_WORD to indicate VOUT fault.
6272cf46945SBrandon Wyman         expectations.statusWordValue = (status_word::VOUT_FAULT);
6282cf46945SBrandon Wyman         // Turn on STATUS_VOUT fault bit(s)
6292cf46945SBrandon Wyman         expectations.statusVOUTValue = 0x30;
630c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
631c2906f47SBrandon Wyman         {
6322cf46945SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
63382affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
63482affd94SBrandon Wyman                 .Times(1)
63582affd94SBrandon Wyman                 .WillOnce(Return("221000"));
6362cf46945SBrandon Wyman             psu2.analyze();
6372cf46945SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
638c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
6392cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
6402cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
6412cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
6422cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
6432cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
6442cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
645c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
6467ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
64796893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6482916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
64939ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
65039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
65139ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
652b654c619SBrandon Wyman         }
653c2906f47SBrandon Wyman     }
6543f1242f3SBrandon Wyman 
6557ee4d7e4SBrandon Wyman     // Fan fault
656b654c619SBrandon Wyman     {
657b654c619SBrandon Wyman         // First STATUS_WORD with no bits set, then with fan fault.
658b654c619SBrandon Wyman         PMBusExpectations expectations;
659b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
66082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
66182affd94SBrandon Wyman             .Times(1)
66282affd94SBrandon Wyman             .WillOnce(Return("222000"));
6633f1242f3SBrandon Wyman         psu2.analyze();
664b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::FAN_FAULT);
6657ee4d7e4SBrandon Wyman         // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
6667ee4d7e4SBrandon Wyman         expectations.statusFans12Value = 0xA0;
667c2906f47SBrandon Wyman 
668c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
669c2906f47SBrandon Wyman         {
670b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
67182affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
67282affd94SBrandon Wyman                 .Times(1)
67382affd94SBrandon Wyman                 .WillOnce(Return("223000"));
6743f1242f3SBrandon Wyman             psu2.analyze();
6753f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
676c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
677c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT);
6783f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
6793f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
6803f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
68185c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
6826710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
683b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
6842cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
68596893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6862916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
68739ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
68839ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
68939ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
690b654c619SBrandon Wyman         }
691c2906f47SBrandon Wyman     }
6922916ea52SBrandon Wyman 
69306ca4590SBrandon Wyman     // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
6942cf46945SBrandon Wyman     {
6952916ea52SBrandon Wyman         // First STATUS_WORD with no bits set.
6962916ea52SBrandon Wyman         PMBusExpectations expectations;
6972916ea52SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
69882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
69982affd94SBrandon Wyman             .Times(1)
70082affd94SBrandon Wyman             .WillOnce(Return("123000"));
7012916ea52SBrandon Wyman         psu2.analyze();
7022916ea52SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
7032916ea52SBrandon Wyman         // POWER_GOOD# inactive, and OFF bit on.
7042916ea52SBrandon Wyman         expectations.statusWordValue =
7052916ea52SBrandon Wyman             ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
7066d469fd4SBrandon Wyman         for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++)
70706ca4590SBrandon Wyman         {
7082916ea52SBrandon Wyman             // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
7092916ea52SBrandon Wyman             // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
7102916ea52SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
71182affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
71282affd94SBrandon Wyman                 .Times(1)
71382affd94SBrandon Wyman                 .WillOnce(Return("124000"));
7142916ea52SBrandon Wyman             psu2.analyze();
7152916ea52SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
7166d469fd4SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= PGOOD_DEGLITCH_LIMIT);
7172916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
7182916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
7192916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
7202916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
7212916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
7222cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
723b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
7247ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
7252916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
7266d469fd4SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT);
72706ca4590SBrandon Wyman         }
72806ca4590SBrandon Wyman     }
7292916ea52SBrandon Wyman 
7303f1242f3SBrandon Wyman     // TODO: ReadFailure
7313f1242f3SBrandon Wyman }
7323f1242f3SBrandon Wyman 
73359a35793SBrandon Wyman TEST_F(PowerSupplyTests, OnOffConfig)
73459a35793SBrandon Wyman {
73559a35793SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
73659a35793SBrandon Wyman     uint8_t data = 0x15;
73759a35793SBrandon Wyman 
73859a35793SBrandon Wyman     // Test where PSU is NOT present
73959a35793SBrandon Wyman     try
74059a35793SBrandon Wyman     {
741681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
7420975eaf4SMatt Spinler         EXPECT_CALL(mockedUtil, setAvailable(_, _, _)).Times(0);
7439464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 4,        0x69,
7449464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
745681b2a36SB. J. Wyman 
7463ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
7473ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
748681b2a36SB. J. Wyman         ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
74959a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
750681b2a36SB. J. Wyman         // Constructor should set initial presence, default read returns 0.
75159a35793SBrandon Wyman         // If it is not present, I should not be trying to write to it.
75259a35793SBrandon Wyman         EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
75359a35793SBrandon Wyman         psu.onOffConfig(data);
75459a35793SBrandon Wyman     }
75559a35793SBrandon Wyman     catch (...)
7560c9a33d6SAdriana Kobylak     {}
75759a35793SBrandon Wyman 
75859a35793SBrandon Wyman     // Test where PSU is present
75959a35793SBrandon Wyman     try
76059a35793SBrandon Wyman     {
761681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
7620975eaf4SMatt Spinler         EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
7639464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 5,        0x6a,
7649464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
7653ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
7663ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
767391a0690SBrandon Wyman         // There will potentially be multiple calls, we want it to continue
768391a0690SBrandon Wyman         // returning 1 for the GPIO read to keep the power supply present.
769391a0690SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
77059a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
771391a0690SBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
772ae35ac5dSBrandon Wyman         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
773ae35ac5dSBrandon Wyman         // for INPUT_HISTORY will check max_power_out to see if it is
774ae35ac5dSBrandon Wyman         // old/unsupported power supply. Indicate good value, supported.
775ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
776*592bd27cSMatt Spinler             .WillRepeatedly(Return("2000"));
777391a0690SBrandon Wyman         // If I am calling analyze(), I should probably give it good data.
778391a0690SBrandon Wyman         // STATUS_WORD 0x0000 is powered on, no faults.
779391a0690SBrandon Wyman         PMBusExpectations expectations;
780391a0690SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
78182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
78282affd94SBrandon Wyman             .Times(1)
78382affd94SBrandon Wyman             .WillOnce(Return("205000"));
784681b2a36SB. J. Wyman         psu.analyze();
785391a0690SBrandon Wyman         // I definitely should be writting ON_OFF_CONFIG if I call the function
786391a0690SBrandon Wyman         EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
787391a0690SBrandon Wyman                                            Type::HwmonDeviceDebug))
78859a35793SBrandon Wyman             .Times(1);
78959a35793SBrandon Wyman         psu.onOffConfig(data);
79059a35793SBrandon Wyman     }
79159a35793SBrandon Wyman     catch (...)
7920c9a33d6SAdriana Kobylak     {}
79359a35793SBrandon Wyman }
79459a35793SBrandon Wyman 
7953f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, ClearFaults)
7963f1242f3SBrandon Wyman {
7973f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
7989464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 13,       0x68,
7999464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
8003ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
8013ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
80206ca4590SBrandon Wyman     // Always return 1 to indicate present.
80306ca4590SBrandon Wyman     // Each analyze() call will trigger a read of the presence GPIO.
80406ca4590SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
805681b2a36SB. J. Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
806391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
807ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
808ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
809ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
810ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
811*592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
8128da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
813b654c619SBrandon Wyman     PMBusExpectations expectations;
814b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
81582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
81682affd94SBrandon Wyman         .Times(1)
81782affd94SBrandon Wyman         .WillOnce(Return("207000"));
818681b2a36SB. J. Wyman     psu.analyze();
8193f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
8203f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
8213f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
8223f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
8233f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
82485c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
8256710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
826b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
8272cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
8287ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
82996893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
8302916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
83139ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
83239ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
83339ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
834b654c619SBrandon Wyman 
835f07bc797SBrandon Wyman     // STATUS_WORD with fault bits galore!
836b654c619SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
837f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
838b654c619SBrandon Wyman     expectations.statusInputValue = 0xFF;
839f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
840b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
84185c7bf41SBrandon Wyman     // STATUS_CML with bits on.
842b654c619SBrandon Wyman     expectations.statusCMLValue = 0xFF;
8436710ba2cSBrandon Wyman     // STATUS_VOUT with bits on.
844b654c619SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
845b10b3be0SBrandon Wyman     // STATUS_IOUT with bits on.
846b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
8477ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
8487ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0xFF;
84996893a46SBrandon Wyman     // STATUS_TEMPERATURE with bits on.
85096893a46SBrandon Wyman     expectations.statusTempValue = 0xFF;
851c2906f47SBrandon Wyman 
8526d469fd4SBrandon Wyman     for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++)
853c2906f47SBrandon Wyman     {
854b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
85582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
85682affd94SBrandon Wyman             .Times(1)
85782affd94SBrandon Wyman             .WillOnce(Return("0"));
8580975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
8590975eaf4SMatt Spinler         {
8600975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
8610975eaf4SMatt Spinler         }
8623f1242f3SBrandon Wyman         psu.analyze();
8633f1242f3SBrandon Wyman         EXPECT_EQ(psu.isPresent(), true);
8642cf46945SBrandon Wyman         // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
8652cf46945SBrandon Wyman         // Rely on HasVoutUVFault() to verify this sets and clears.
8662cf46945SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), false);
8676d469fd4SBrandon Wyman         // pgoodFault at PGOOD_DEGLITCH_LIMIT, all other faults are deglitched
8686d469fd4SBrandon Wyman         // up to DEGLITCH_LIMIT
869c2906f47SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
870c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
871c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
872c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
873c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT);
874c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
875c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
876c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
877c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
8786d469fd4SBrandon Wyman         EXPECT_EQ(psu.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT);
879c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
880c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
881c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
882c2906f47SBrandon Wyman     }
883c2906f47SBrandon Wyman 
88432453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _))
88532453e9bSBrandon Wyman         .Times(1)
88632453e9bSBrandon Wyman         .WillOnce(Return(207000));
8873225a45cSBrandon Wyman     // Clearing VIN_UV fault via in1_lcrit_alarm
8883225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
8893225a45cSBrandon Wyman         .Times(1)
8903225a45cSBrandon Wyman         .WillOnce(Return(1));
8910975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
8923f1242f3SBrandon Wyman     psu.clearFaults();
8933f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
8943f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
8953f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
8963f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
8973f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
89885c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
8996710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
900b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
9012cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
9027ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
90396893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
9042916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
90539ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
90639ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
90739ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
908681b2a36SB. J. Wyman 
90982affd94SBrandon Wyman     // Faults clear on READ_VIN 0 -> !0
91082affd94SBrandon Wyman     // STATUS_WORD with fault bits galore!
91182affd94SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
91282affd94SBrandon Wyman     // STATUS_INPUT with fault bits on.
91382affd94SBrandon Wyman     expectations.statusInputValue = 0xFF;
91482affd94SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
91582affd94SBrandon Wyman     expectations.statusMFRValue = 0xFF;
91682affd94SBrandon Wyman     // STATUS_CML with bits on.
91782affd94SBrandon Wyman     expectations.statusCMLValue = 0xFF;
91882affd94SBrandon Wyman     // STATUS_VOUT with bits on.
91982affd94SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
92082affd94SBrandon Wyman     // STATUS_IOUT with bits on.
92182affd94SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
92282affd94SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
92382affd94SBrandon Wyman     expectations.statusFans12Value = 0xFF;
92482affd94SBrandon Wyman     // STATUS_TEMPERATURE with bits on.
92582affd94SBrandon Wyman     expectations.statusTempValue = 0xFF;
926c2906f47SBrandon Wyman 
9276d469fd4SBrandon Wyman     // All faults deglitched now. Check for false before limit above.
928c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
929c2906f47SBrandon Wyman     {
93082affd94SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
93182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
93282affd94SBrandon Wyman             .Times(1)
93382affd94SBrandon Wyman             .WillOnce(Return("0"));
9340975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
9350975eaf4SMatt Spinler         {
9360975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
9370975eaf4SMatt Spinler         }
93882affd94SBrandon Wyman         psu.analyze();
939c2906f47SBrandon Wyman     }
940c2906f47SBrandon Wyman 
94182affd94SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
94282affd94SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
94382affd94SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), true);
94482affd94SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
94582affd94SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), true);
94682affd94SBrandon Wyman     // True due to CML fault bits on
94782affd94SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), true);
94882affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
94982affd94SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), true);
95082affd94SBrandon Wyman     // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
95182affd94SBrandon Wyman     // Rely on HasVoutUVFault() to verify this sets and clears.
95282affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
95382affd94SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), true);
95482affd94SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), true);
9556d469fd4SBrandon Wyman     // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT
9566d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
95782affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), true);
95882affd94SBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), true);
95982affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), true);
96082affd94SBrandon Wyman     // STATUS_WORD with INPUT/VIN_UV fault bits off.
96182affd94SBrandon Wyman     expectations.statusWordValue = 0xDFF7;
96282affd94SBrandon Wyman     // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
96382affd94SBrandon Wyman     // Insufficient Input Voltage bits off.
96482affd94SBrandon Wyman     expectations.statusInputValue = 0xC7;
96582affd94SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
96682affd94SBrandon Wyman     // READ_VIN back in range.
96782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
96882affd94SBrandon Wyman         .Times(1)
96982affd94SBrandon Wyman         .WillOnce(Return("206000"));
9703225a45cSBrandon Wyman     // VIN_UV cleared via in1_lcrit_alarm when voltage back in range.
9713225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
9723225a45cSBrandon Wyman         .Times(1)
9733225a45cSBrandon Wyman         .WillOnce(Return(1));
9743225a45cSBrandon Wyman     psu.analyze();
9753225a45cSBrandon Wyman     // We only cleared the VIN_UV and OFF faults.
9763225a45cSBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
9773225a45cSBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
9783225a45cSBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
9793225a45cSBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
9803225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
9813225a45cSBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), true);
9823225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
9833225a45cSBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), true);
9843225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
9853225a45cSBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), true);
9863225a45cSBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), true);
9876d469fd4SBrandon Wyman     // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT
9886d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
9893225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), true);
9903225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), true);
9913225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), true);
9923225a45cSBrandon Wyman 
9933225a45cSBrandon Wyman     // All faults cleared
9943225a45cSBrandon Wyman     expectations = {0};
9953225a45cSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
9963225a45cSBrandon Wyman     // READ_VIN back in range.
9973225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
9983225a45cSBrandon Wyman         .Times(1)
9993225a45cSBrandon Wyman         .WillOnce(Return("206000"));
10000975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
100182affd94SBrandon Wyman     psu.analyze();
100282affd94SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
100382affd94SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
100482affd94SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
100582affd94SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
100682affd94SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
100782affd94SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
100882affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
100982affd94SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
101082affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
101182affd94SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
101282affd94SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
101382affd94SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
101482affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
101582affd94SBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
101682affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
101782affd94SBrandon Wyman 
1018681b2a36SB. J. Wyman     // TODO: Faults clear on missing/present?
10193f1242f3SBrandon Wyman }
10203f1242f3SBrandon Wyman 
10213f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, UpdateInventory)
10223f1242f3SBrandon Wyman {
10233f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
10241d7a7df8SBrandon Wyman 
10251d7a7df8SBrandon Wyman     try
10261d7a7df8SBrandon Wyman     {
10279464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
10289464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
10291d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
10301d7a7df8SBrandon Wyman         // If it is not present, I should not be trying to read a string
10311d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
10321d7a7df8SBrandon Wyman         psu.updateInventory();
10331d7a7df8SBrandon Wyman     }
10341d7a7df8SBrandon Wyman     catch (...)
10351d7a7df8SBrandon Wyman     {
10361d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
10371d7a7df8SBrandon Wyman     }
10381d7a7df8SBrandon Wyman 
10391d7a7df8SBrandon Wyman     try
10401d7a7df8SBrandon Wyman     {
10419464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 13,       0x69,
10429464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
10433ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
10443ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1045681b2a36SB. J. Wyman         // GPIO read return 1 to indicate present.
1046681b2a36SB. J. Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
10471d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1048391a0690SBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
1049ae35ac5dSBrandon Wyman         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1050ae35ac5dSBrandon Wyman         // for INPUT_HISTORY will check max_power_out to see if it is
1051ae35ac5dSBrandon Wyman         // old/unsupported power supply. Indicate good value, supported.
1052ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1053*592bd27cSMatt Spinler             .WillRepeatedly(Return("2000"));
1054391a0690SBrandon Wyman         // STATUS_WORD 0x0000 is powered on, no faults.
1055391a0690SBrandon Wyman         PMBusExpectations expectations;
1056391a0690SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
105782affd94SBrandon Wyman         // Call to analyze will read voltage, trigger clear faults for 0 to
105882affd94SBrandon Wyman         // within range.
105982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
106082affd94SBrandon Wyman             .Times(1)
106182affd94SBrandon Wyman             .WillOnce(Return("123456"));
1062391a0690SBrandon Wyman         psu.analyze();
10631d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
10643f1242f3SBrandon Wyman         psu.updateInventory();
10651d7a7df8SBrandon Wyman 
10663c530fbdSBrandon Wyman #if IBM_VPD
10671d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _))
10681d7a7df8SBrandon Wyman             .WillOnce(Return("CCIN"))
10691d7a7df8SBrandon Wyman             .WillOnce(Return("PN3456"))
10701d7a7df8SBrandon Wyman             .WillOnce(Return("FN3456"))
10711d7a7df8SBrandon Wyman             .WillOnce(Return("HEADER"))
10721d7a7df8SBrandon Wyman             .WillOnce(Return("SN3456"))
10731d7a7df8SBrandon Wyman             .WillOnce(Return("FW3456"));
10743c530fbdSBrandon Wyman #endif
10751d7a7df8SBrandon Wyman         psu.updateInventory();
10761d7a7df8SBrandon Wyman         // TODO: D-Bus mocking to verify values stored on D-Bus (???)
10771d7a7df8SBrandon Wyman     }
10781d7a7df8SBrandon Wyman     catch (...)
10791d7a7df8SBrandon Wyman     {
10801d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
10811d7a7df8SBrandon Wyman     }
10823f1242f3SBrandon Wyman }
10833f1242f3SBrandon Wyman 
10843f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsPresent)
10853f1242f3SBrandon Wyman {
10863f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1087681b2a36SB. J. Wyman 
10889464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
10899464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
10903ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
10913ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
10923f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), false);
10933f1242f3SBrandon Wyman 
1094681b2a36SB. J. Wyman     // Change GPIO read to return 1 to indicate present.
1095681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
1096391a0690SBrandon Wyman     // Call to analyze() will update to present, that will trigger updating
1097391a0690SBrandon Wyman     // to the correct/latest HWMON directory, in case it changes.
1098391a0690SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1099391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1100ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1101ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1102ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1103ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1104*592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
1105391a0690SBrandon Wyman     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1106391a0690SBrandon Wyman     // Default expectations will be on, no faults.
1107391a0690SBrandon Wyman     PMBusExpectations expectations;
1108391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
110982affd94SBrandon Wyman     // Give it an input voltage in the 100-volt range.
111082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
111182affd94SBrandon Wyman         .Times(1)
111282affd94SBrandon Wyman         .WillOnce(Return("123456"));
11130975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1114681b2a36SB. J. Wyman     psu.analyze();
1115681b2a36SB. J. Wyman     EXPECT_EQ(psu.isPresent(), true);
11163f1242f3SBrandon Wyman }
11173f1242f3SBrandon Wyman 
11183f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsFaulted)
11193f1242f3SBrandon Wyman {
11203f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1121681b2a36SB. J. Wyman 
11229464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 11,       0x6f,
11239464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
11243ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
11253ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1126681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1127681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1128391a0690SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1129391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1130ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1131ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1132ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1133ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1134*592bd27cSMatt Spinler         .WillRepeatedly(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 
11819464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
11829464c429SGeorge 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, _))
1193*592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
11948da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1195b654c619SBrandon Wyman     PMBusExpectations expectations;
1196b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
119782affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
119882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
119982affd94SBrandon Wyman         .Times(1)
120082affd94SBrandon Wyman         .WillOnce(Return("201100"));
12013f1242f3SBrandon Wyman     psu.analyze();
12023f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
1203f07bc797SBrandon Wyman     // STATUS_WORD with input fault/warn on.
1204b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
1205f07bc797SBrandon Wyman     // STATUS_INPUT with an input fault bit on.
1206b654c619SBrandon Wyman     expectations.statusInputValue = 0x80;
1207c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1208c2906f47SBrandon Wyman     {
1209b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
121082affd94SBrandon Wyman         // Analyze call will also need good READ_VIN value to check.
121182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
121282affd94SBrandon Wyman             .Times(1)
121382affd94SBrandon Wyman             .WillOnce(Return("201200"));
12140975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
12150975eaf4SMatt Spinler         {
12160975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
12170975eaf4SMatt Spinler         }
12183f1242f3SBrandon Wyman         psu.analyze();
1219c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
1220c2906f47SBrandon Wyman     }
1221f07bc797SBrandon Wyman     // STATUS_WORD with no bits on.
1222b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1223b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
122482affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
122582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
122682affd94SBrandon Wyman         .Times(1)
122782affd94SBrandon Wyman         .WillOnce(Return("201300"));
12280975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
12293f1242f3SBrandon Wyman     psu.analyze();
12303f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
12313f1242f3SBrandon Wyman }
12323f1242f3SBrandon Wyman 
12333f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasMFRFault)
12343f1242f3SBrandon Wyman {
12353f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1236681b2a36SB. J. Wyman 
12379464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
12389464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
12393ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
12403ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1241681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1242681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
12433f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1244391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1245ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1246ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1247ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1248ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1249*592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
1250f07bc797SBrandon Wyman     // First return STATUS_WORD with no bits on.
12518da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1252b654c619SBrandon Wyman     PMBusExpectations expectations;
1253b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
125482affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
125582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
125682affd94SBrandon Wyman         .Times(1)
125782affd94SBrandon Wyman         .WillOnce(Return("202100"));
12583f1242f3SBrandon Wyman     psu.analyze();
12593f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
1260f07bc797SBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
1261b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1262f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
1263b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
1264c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1265c2906f47SBrandon Wyman     {
1266b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
126782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
126882affd94SBrandon Wyman             .Times(1)
126982affd94SBrandon Wyman             .WillOnce(Return("202200"));
12703f1242f3SBrandon Wyman         psu.analyze();
1271c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1272c2906f47SBrandon Wyman     }
1273f07bc797SBrandon Wyman     // Back to no bits on in STATUS_WORD
1274b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1275b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
127682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
127782affd94SBrandon Wyman         .Times(1)
127882affd94SBrandon Wyman         .WillOnce(Return("202300"));
12793f1242f3SBrandon Wyman     psu.analyze();
12803f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
12813f1242f3SBrandon Wyman }
12823f1242f3SBrandon Wyman 
12833f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasVINUVFault)
12843f1242f3SBrandon Wyman {
12853f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1286681b2a36SB. J. Wyman 
12879464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
12889464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
12893ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
12903ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1291681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1292681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
12933f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1294391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1295ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1296ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1297ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1298ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1299*592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
130082affd94SBrandon Wyman 
130182affd94SBrandon Wyman     // Presence change from missing to present will trigger in1_input read in
130282affd94SBrandon Wyman     // an attempt to get CLEAR_FAULTS called. Return value ignored.
130382affd94SBrandon Wyman     // Zero to non-zero voltage, for missing/present change, triggers clear
130482affd94SBrandon Wyman     // faults call again. Return value ignored.
130582affd94SBrandon Wyman     // Fault (low voltage) to not faulted (voltage in range) triggers clear
130682affd94SBrandon Wyman     // faults call a third time.
130782affd94SBrandon Wyman 
13088da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1309b654c619SBrandon Wyman     PMBusExpectations expectations;
1310b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
131182affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
131282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
131382affd94SBrandon Wyman         .Times(1)
131482affd94SBrandon Wyman         .WillOnce(Return("201100"));
13153f1242f3SBrandon Wyman     psu.analyze();
13163f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
1317f07bc797SBrandon Wyman     // Turn fault on.
1318b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::VIN_UV_FAULT);
131985c7bf41SBrandon Wyman     // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
132085c7bf41SBrandon Wyman     // Figure 16, and assume bits on in STATUS_INPUT.
1321b654c619SBrandon Wyman     expectations.statusInputValue = 0x18;
1322c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1323c2906f47SBrandon Wyman     {
1324b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
132582affd94SBrandon Wyman         // If there is a VIN_UV fault, fake reading voltage of less than 20V
132682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
132782affd94SBrandon Wyman             .Times(1)
132882affd94SBrandon Wyman             .WillOnce(Return("19876"));
13290975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
13300975eaf4SMatt Spinler         {
13310975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
13320975eaf4SMatt Spinler         }
13333f1242f3SBrandon Wyman         psu.analyze();
1334c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1335c2906f47SBrandon Wyman     }
1336f07bc797SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1337b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1338b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
133982affd94SBrandon Wyman     // Updates now result in clearing faults if read voltage goes from below the
134082affd94SBrandon Wyman     // minimum, to within a valid range.
134182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
134282affd94SBrandon Wyman         .Times(1)
134382affd94SBrandon Wyman         .WillOnce(Return("201300"));
13443225a45cSBrandon Wyman     // Went from below minimum to within range, expect clearVinUVFault().
13453225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
13463225a45cSBrandon Wyman         .Times(1)
13473225a45cSBrandon Wyman         .WillOnce(Return(1));
13480975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
13493f1242f3SBrandon Wyman     psu.analyze();
13503f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
13513f1242f3SBrandon Wyman }
13526710ba2cSBrandon Wyman 
13536710ba2cSBrandon Wyman TEST_F(PowerSupplyTests, HasVoutOVFault)
13546710ba2cSBrandon Wyman {
13556710ba2cSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
13566710ba2cSBrandon Wyman 
13579464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x69,
13589464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
13596710ba2cSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
13606710ba2cSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
13616710ba2cSBrandon Wyman     // Always return 1 to indicate present.
13626710ba2cSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
13636710ba2cSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1364391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1365ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1366ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1367ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1368ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1369*592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
13706710ba2cSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1371b654c619SBrandon Wyman     PMBusExpectations expectations;
1372b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
137382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
137482affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
137582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
137682affd94SBrandon Wyman         .Times(1)
137782affd94SBrandon Wyman         .WillOnce(Return("202100"));
13786710ba2cSBrandon Wyman     psu.analyze();
13796710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
13806710ba2cSBrandon Wyman     // Turn fault on.
1381b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
13826710ba2cSBrandon Wyman     // STATUS_VOUT fault bit(s)
1383b654c619SBrandon Wyman     expectations.statusVOUTValue = 0x80;
1384c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1385c2906f47SBrandon Wyman     {
1386b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
138782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
138882affd94SBrandon Wyman             .Times(1)
138982affd94SBrandon Wyman             .WillOnce(Return("202200"));
13906710ba2cSBrandon Wyman         psu.analyze();
1391c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1392c2906f47SBrandon Wyman     }
13936710ba2cSBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1394b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1395b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
139682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
139782affd94SBrandon Wyman         .Times(1)
139882affd94SBrandon Wyman         .WillOnce(Return("202300"));
13996710ba2cSBrandon Wyman     psu.analyze();
14006710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
14016710ba2cSBrandon Wyman }
140296893a46SBrandon Wyman 
1403b10b3be0SBrandon Wyman TEST_F(PowerSupplyTests, HasIoutOCFault)
1404b10b3be0SBrandon Wyman {
1405b10b3be0SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1406b10b3be0SBrandon Wyman 
14079464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6d,
14089464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1409b10b3be0SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
1410b10b3be0SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1411b10b3be0SBrandon Wyman     // Always return 1 to indicate present.
1412b10b3be0SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1413b10b3be0SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1414391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1415ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1416ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1417ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1418ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1419*592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
1420b10b3be0SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1421b10b3be0SBrandon Wyman     PMBusExpectations expectations;
1422b10b3be0SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
142382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
142482affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
142582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
142682affd94SBrandon Wyman         .Times(1)
142782affd94SBrandon Wyman         .WillOnce(Return("203100"));
1428b10b3be0SBrandon Wyman     psu.analyze();
1429b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
1430b10b3be0SBrandon Wyman     // Turn fault on.
1431b10b3be0SBrandon Wyman     expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1432b10b3be0SBrandon Wyman     // STATUS_IOUT fault bit(s)
1433b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0x88;
1434c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1435c2906f47SBrandon Wyman     {
1436b10b3be0SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
143782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
143882affd94SBrandon Wyman             .Times(1)
143982affd94SBrandon Wyman             .WillOnce(Return("203200"));
14400975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
14410975eaf4SMatt Spinler         {
14420975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
14430975eaf4SMatt Spinler         }
1444b10b3be0SBrandon Wyman         psu.analyze();
1445c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1446c2906f47SBrandon Wyman     }
1447b10b3be0SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1448b10b3be0SBrandon Wyman     expectations.statusWordValue = 0;
1449b10b3be0SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
145082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
145182affd94SBrandon Wyman         .Times(1)
145282affd94SBrandon Wyman         .WillOnce(Return("203300"));
14530975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1454b10b3be0SBrandon Wyman     psu.analyze();
1455b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
1456b10b3be0SBrandon Wyman }
1457b10b3be0SBrandon Wyman 
14582cf46945SBrandon Wyman TEST_F(PowerSupplyTests, HasVoutUVFault)
14592cf46945SBrandon Wyman {
14602cf46945SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
14612cf46945SBrandon Wyman 
14629464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6a,
14639464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
14642cf46945SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
14652cf46945SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
14662cf46945SBrandon Wyman     // Always return 1 to indicate present.
14672cf46945SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
14682cf46945SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1469391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1470ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1471ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1472ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1473ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1474*592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
1475391a0690SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
14762cf46945SBrandon Wyman     PMBusExpectations expectations;
14772cf46945SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
147882affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
147982affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
148082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
148182affd94SBrandon Wyman         .Times(1)
148282affd94SBrandon Wyman         .WillOnce(Return("204100"));
14832cf46945SBrandon Wyman     psu.analyze();
14842cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
14852cf46945SBrandon Wyman     // Turn fault on.
14862cf46945SBrandon Wyman     expectations.statusWordValue = (status_word::VOUT_FAULT);
14872cf46945SBrandon Wyman     // STATUS_VOUT fault bit(s)
14882cf46945SBrandon Wyman     expectations.statusVOUTValue = 0x30;
1489c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1490c2906f47SBrandon Wyman     {
14912cf46945SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
149282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
149382affd94SBrandon Wyman             .Times(1)
149482affd94SBrandon Wyman             .WillOnce(Return("204200"));
14952cf46945SBrandon Wyman         psu.analyze();
1496c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1497c2906f47SBrandon Wyman     }
14982cf46945SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
14992cf46945SBrandon Wyman     expectations.statusWordValue = 0;
15002cf46945SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
150182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
150282affd94SBrandon Wyman         .Times(1)
150382affd94SBrandon Wyman         .WillOnce(Return("204300"));
15042cf46945SBrandon Wyman     psu.analyze();
15052cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
15062cf46945SBrandon Wyman }
15072cf46945SBrandon Wyman 
15087ee4d7e4SBrandon Wyman TEST_F(PowerSupplyTests, HasFanFault)
15097ee4d7e4SBrandon Wyman {
15107ee4d7e4SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
15117ee4d7e4SBrandon Wyman 
15120975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
15130975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
15140975eaf4SMatt Spinler 
15159464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6d,
15169464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
15177ee4d7e4SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
15187ee4d7e4SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
15197ee4d7e4SBrandon Wyman     // Always return 1 to indicate present.
15207ee4d7e4SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
15217ee4d7e4SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1522391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1523ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1524ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1525ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1526ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1527*592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
15287ee4d7e4SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
15297ee4d7e4SBrandon Wyman     PMBusExpectations expectations;
15307ee4d7e4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
153182affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
153282affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
153382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
153482affd94SBrandon Wyman         .Times(1)
153582affd94SBrandon Wyman         .WillOnce(Return("205100"));
15367ee4d7e4SBrandon Wyman     psu.analyze();
15377ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
15387ee4d7e4SBrandon Wyman     // Turn fault on.
15397ee4d7e4SBrandon Wyman     expectations.statusWordValue = (status_word::FAN_FAULT);
15407ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
15417ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0x80;
1542c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1543c2906f47SBrandon Wyman     {
15447ee4d7e4SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
154582affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
154682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
154782affd94SBrandon Wyman             .Times(1)
154882affd94SBrandon Wyman             .WillOnce(Return("205200"));
15497ee4d7e4SBrandon Wyman         psu.analyze();
1550c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1551c2906f47SBrandon Wyman     }
15527ee4d7e4SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
15537ee4d7e4SBrandon Wyman     expectations.statusWordValue = 0;
15547ee4d7e4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
155582affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
155682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
155782affd94SBrandon Wyman         .Times(1)
155882affd94SBrandon Wyman         .WillOnce(Return("205300"));
15597ee4d7e4SBrandon Wyman     psu.analyze();
15607ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
15617ee4d7e4SBrandon Wyman }
15627ee4d7e4SBrandon Wyman 
156396893a46SBrandon Wyman TEST_F(PowerSupplyTests, HasTempFault)
156496893a46SBrandon Wyman {
156596893a46SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
156696893a46SBrandon Wyman 
15670975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
15680975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
15690975eaf4SMatt Spinler 
15709464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6a,
15719464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
157296893a46SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
157396893a46SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
157496893a46SBrandon Wyman     // Always return 1 to indicate present.
157596893a46SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
157696893a46SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1577391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1578ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1579ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1580ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1581ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1582*592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
158396893a46SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
158496893a46SBrandon Wyman     PMBusExpectations expectations;
158596893a46SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
158682affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
158782affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
158882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
158982affd94SBrandon Wyman         .Times(1)
159082affd94SBrandon Wyman         .WillOnce(Return("206100"));
159196893a46SBrandon Wyman     psu.analyze();
159296893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
159396893a46SBrandon Wyman     // Turn fault on.
159496893a46SBrandon Wyman     expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
159596893a46SBrandon Wyman     // STATUS_TEMPERATURE fault bit on (OT Fault)
159696893a46SBrandon Wyman     expectations.statusTempValue = 0x80;
1597c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1598c2906f47SBrandon Wyman     {
159996893a46SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
160082affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
160182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
160282affd94SBrandon Wyman             .Times(1)
160382affd94SBrandon Wyman             .WillOnce(Return("206200"));
160496893a46SBrandon Wyman         psu.analyze();
1605c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1606c2906f47SBrandon Wyman     }
160796893a46SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
160896893a46SBrandon Wyman     expectations.statusWordValue = 0;
160996893a46SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
161082affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
161182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
161282affd94SBrandon Wyman         .Times(1)
161382affd94SBrandon Wyman         .WillOnce(Return("206300"));
161496893a46SBrandon Wyman     psu.analyze();
161596893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
161696893a46SBrandon Wyman }
16172916ea52SBrandon Wyman 
16182916ea52SBrandon Wyman TEST_F(PowerSupplyTests, HasPgoodFault)
16192916ea52SBrandon Wyman {
16202916ea52SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
16212916ea52SBrandon Wyman 
16229464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6b,
16239464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
16242916ea52SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
16252916ea52SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
16262916ea52SBrandon Wyman     // Always return 1 to indicate present.
16272916ea52SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
16282916ea52SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1629391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1630ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1631ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1632ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1633ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1634*592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
16352916ea52SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
16362916ea52SBrandon Wyman     PMBusExpectations expectations;
16372916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
163882affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
163982affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
164082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
164182affd94SBrandon Wyman         .Times(1)
164282affd94SBrandon Wyman         .WillOnce(Return("207100"));
16432916ea52SBrandon Wyman     psu.analyze();
16442916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
1645391a0690SBrandon Wyman     // Setup another expectation of no faults.
1646391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
164782affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
164882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
164982affd94SBrandon Wyman         .Times(1)
165082affd94SBrandon Wyman         .WillOnce(Return("207200"));
165182affd94SBrandon Wyman     psu.analyze();
165282affd94SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
165382affd94SBrandon Wyman     // Setup another expectation of no faults.
165482affd94SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
165582affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
165682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
165782affd94SBrandon Wyman         .Times(1)
165882affd94SBrandon Wyman         .WillOnce(Return("207300"));
1659391a0690SBrandon Wyman     psu.analyze();
1660391a0690SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
16612916ea52SBrandon Wyman     // Turn PGOOD# off (fault on).
16622916ea52SBrandon Wyman     expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
16632916ea52SBrandon 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("207400"));
16682916ea52SBrandon Wyman     psu.analyze();
16696d469fd4SBrandon Wyman     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 1
167006ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
167106ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
167282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
167382affd94SBrandon Wyman         .Times(1)
167482affd94SBrandon Wyman         .WillOnce(Return("207500"));
167506ca4590SBrandon Wyman     psu.analyze();
16766d469fd4SBrandon Wyman     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 2
167706ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
167806ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
167982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
168082affd94SBrandon Wyman         .Times(1)
168182affd94SBrandon Wyman         .WillOnce(Return("207600"));
168206ca4590SBrandon Wyman     psu.analyze();
16836d469fd4SBrandon Wyman     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 3
16846d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
16856d469fd4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
16866d469fd4SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
16876d469fd4SBrandon Wyman         .Times(1)
16886d469fd4SBrandon Wyman         .WillOnce(Return("207700"));
16896d469fd4SBrandon Wyman     psu.analyze();
16906d469fd4SBrandon Wyman     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 4
16916d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
16926d469fd4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
16936d469fd4SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
16946d469fd4SBrandon Wyman         .Times(1)
16956d469fd4SBrandon Wyman         .WillOnce(Return("207800"));
16966d469fd4SBrandon Wyman     psu.analyze();
16976d469fd4SBrandon Wyman     // Expect true. PGOOD_DEGLITCH_LIMIT @ 5
16982916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
16992916ea52SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
17002916ea52SBrandon Wyman     expectations.statusWordValue = 0;
17012916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
170282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
170382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
170482affd94SBrandon Wyman         .Times(1)
170582affd94SBrandon Wyman         .WillOnce(Return("207700"));
17062916ea52SBrandon Wyman     psu.analyze();
17072916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
170882affd94SBrandon Wyman 
17092916ea52SBrandon Wyman     // Turn OFF bit on
17102916ea52SBrandon Wyman     expectations.statusWordValue = (status_word::UNIT_IS_OFF);
17112916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
171282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
171382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
171482affd94SBrandon Wyman         .Times(1)
171582affd94SBrandon Wyman         .WillOnce(Return("208100"));
17162916ea52SBrandon Wyman     psu.analyze();
171706ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
171806ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
171982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
172082affd94SBrandon Wyman         .Times(1)
172182affd94SBrandon Wyman         .WillOnce(Return("208200"));
172206ca4590SBrandon Wyman     psu.analyze();
172306ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
172406ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
172582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
172682affd94SBrandon Wyman         .Times(1)
172782affd94SBrandon Wyman         .WillOnce(Return("208300"));
172806ca4590SBrandon Wyman     psu.analyze();
17296d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
17306d469fd4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
17316d469fd4SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
17326d469fd4SBrandon Wyman         .Times(1)
17336d469fd4SBrandon Wyman         .WillOnce(Return("208400"));
17346d469fd4SBrandon Wyman     psu.analyze();
17356d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
17366d469fd4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
17376d469fd4SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
17386d469fd4SBrandon Wyman         .Times(1)
17396d469fd4SBrandon Wyman         .WillOnce(Return("208500"));
17406d469fd4SBrandon Wyman     psu.analyze();
17412916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
17422916ea52SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
17432916ea52SBrandon Wyman     expectations.statusWordValue = 0;
17442916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
174582affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
174682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
174782affd94SBrandon Wyman         .Times(1)
17486d469fd4SBrandon Wyman         .WillOnce(Return("208000"));
17492916ea52SBrandon Wyman     psu.analyze();
17502916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
17512916ea52SBrandon Wyman }
175239ea02bcSBrandon Wyman 
175339ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPSKillFault)
175439ea02bcSBrandon Wyman {
175539ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
17569464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 4,        0x6d,
17579464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
175839ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
175939ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
176039ea02bcSBrandon Wyman     // Always return 1 to indicate present.
176139ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
176239ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
176382affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1764ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1765ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1766ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1767ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1768*592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
176939ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
177039ea02bcSBrandon Wyman     PMBusExpectations expectations;
177139ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
177282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
177382affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
177482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
177582affd94SBrandon Wyman         .Times(1)
177682affd94SBrandon Wyman         .WillOnce(Return("208100"));
177739ea02bcSBrandon Wyman     psu.analyze();
177839ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
177939ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
178039ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
178139ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
178239ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1783c2906f47SBrandon Wyman 
1784c2906f47SBrandon Wyman     // Deglitching faults, false until read the fault bits on up to the limit.
1785c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1786c2906f47SBrandon Wyman     {
178739ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
178882affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
178982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
179082affd94SBrandon Wyman             .Times(1)
179182affd94SBrandon Wyman             .WillOnce(Return("208200"));
17920975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
17930975eaf4SMatt Spinler         {
17940975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
17950975eaf4SMatt Spinler         }
179639ea02bcSBrandon Wyman         psu.analyze();
1797c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1798c2906f47SBrandon Wyman     }
1799c2906f47SBrandon Wyman 
180039ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
180139ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
180239ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
180382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
180482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
180582affd94SBrandon Wyman         .Times(1)
180682affd94SBrandon Wyman         .WillOnce(Return("208300"));
18070975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
180839ea02bcSBrandon Wyman     psu.analyze();
180939ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
181039ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
181139ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
181239ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 4 on.
181339ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x10;
1814c2906f47SBrandon Wyman 
1815c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1816c2906f47SBrandon Wyman     {
181739ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
181882affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
181982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
182082affd94SBrandon Wyman             .Times(1)
182182affd94SBrandon Wyman             .WillOnce(Return("208400"));
18220975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
18230975eaf4SMatt Spinler         {
18240975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
18250975eaf4SMatt Spinler         }
182639ea02bcSBrandon Wyman         psu.analyze();
1827c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1828c2906f47SBrandon Wyman     }
1829c2906f47SBrandon Wyman 
183039ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
183139ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
183239ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
183382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
183482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
183582affd94SBrandon Wyman         .Times(1)
183682affd94SBrandon Wyman         .WillOnce(Return("208500"));
18370975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
183839ea02bcSBrandon Wyman     psu.analyze();
183939ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
184039ea02bcSBrandon Wyman }
184139ea02bcSBrandon Wyman 
184239ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPS12VcsFault)
184339ea02bcSBrandon Wyman {
184439ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
18459464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 5,        0x6e,
18469464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
184739ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
184839ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
184939ea02bcSBrandon Wyman     // Always return 1 to indicate present.
185039ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
185139ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
185282affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1853ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1854ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1855ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1856ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1857*592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
185839ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
185939ea02bcSBrandon Wyman     PMBusExpectations expectations;
186039ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
186182affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
186282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
186382affd94SBrandon Wyman         .Times(1)
186482affd94SBrandon Wyman         .WillOnce(Return("209100"));
186539ea02bcSBrandon Wyman     psu.analyze();
186639ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
186739ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
186839ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
186939ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
187039ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1871c2906f47SBrandon Wyman 
1872c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1873c2906f47SBrandon Wyman     {
187439ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
187582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
187682affd94SBrandon Wyman             .Times(1)
187782affd94SBrandon Wyman             .WillOnce(Return("209200"));
187839ea02bcSBrandon Wyman         psu.analyze();
1879c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1880c2906f47SBrandon Wyman     }
1881c2906f47SBrandon Wyman 
188239ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
188339ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
188439ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
188582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
188682affd94SBrandon Wyman         .Times(1)
188782affd94SBrandon Wyman         .WillOnce(Return("209300"));
188839ea02bcSBrandon Wyman     psu.analyze();
188939ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
189039ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
189139ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
189239ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 6 on.
189339ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x40;
1894c2906f47SBrandon Wyman 
1895c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1896c2906f47SBrandon Wyman     {
189739ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
189882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
189982affd94SBrandon Wyman             .Times(1)
190082affd94SBrandon Wyman             .WillOnce(Return("209400"));
190139ea02bcSBrandon Wyman         psu.analyze();
1902c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1903c2906f47SBrandon Wyman     }
1904c2906f47SBrandon Wyman 
190539ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
190639ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
190739ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
190882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
190982affd94SBrandon Wyman         .Times(1)
191082affd94SBrandon Wyman         .WillOnce(Return("209500"));
191139ea02bcSBrandon Wyman     psu.analyze();
191239ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
191339ea02bcSBrandon Wyman }
191439ea02bcSBrandon Wyman 
191539ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPSCS12VFault)
191639ea02bcSBrandon Wyman {
191739ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
19189464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 6,        0x6f,
19199464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
192039ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
192139ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
192239ea02bcSBrandon Wyman     // Always return 1 to indicate present.
192339ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
192439ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
192582affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1926ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1927ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1928ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1929ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1930*592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
193139ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
193239ea02bcSBrandon Wyman     PMBusExpectations expectations;
193339ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
193482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
193582affd94SBrandon Wyman         .Times(1)
193682affd94SBrandon Wyman         .WillOnce(Return("209100"));
193739ea02bcSBrandon Wyman     psu.analyze();
193839ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
193939ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
194039ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
194139ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
194239ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1943c2906f47SBrandon Wyman 
1944c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1945c2906f47SBrandon Wyman     {
194639ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
194782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
194882affd94SBrandon Wyman             .Times(1)
194982affd94SBrandon Wyman             .WillOnce(Return("209200"));
195039ea02bcSBrandon Wyman         psu.analyze();
1951c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1952c2906f47SBrandon Wyman     }
1953c2906f47SBrandon Wyman 
195439ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
195539ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
195639ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
195782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
195882affd94SBrandon Wyman         .Times(1)
195982affd94SBrandon Wyman         .WillOnce(Return("209300"));
196039ea02bcSBrandon Wyman     psu.analyze();
196139ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
196239ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
196339ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
196439ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 7 on.
196539ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x80;
1966c2906f47SBrandon Wyman 
1967c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1968c2906f47SBrandon Wyman     {
196939ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
197082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
197182affd94SBrandon Wyman             .Times(1)
197282affd94SBrandon Wyman             .WillOnce(Return("209400"));
197339ea02bcSBrandon Wyman         psu.analyze();
1974c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1975c2906f47SBrandon Wyman     }
1976c2906f47SBrandon Wyman 
197739ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
197839ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
197939ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
198082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
198182affd94SBrandon Wyman         .Times(1)
198282affd94SBrandon Wyman         .WillOnce(Return("209500"));
198339ea02bcSBrandon Wyman     psu.analyze();
198439ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
198539ea02bcSBrandon Wyman }
1986c3324424SBrandon Wyman 
1987*592bd27cSMatt Spinler TEST_F(PowerSupplyTests, PeakInputPowerSensor)
1988c3324424SBrandon Wyman {
1989c3324424SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1990c3324424SBrandon Wyman     {
19919464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 6,        0x6f,
19929464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1993*592bd27cSMatt Spinler         EXPECT_EQ(psu.getPeakInputPower(), std::nullopt);
1994*592bd27cSMatt Spinler 
1995c3324424SBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
1996c3324424SBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1997ae35ac5dSBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1998c3324424SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1999*592bd27cSMatt Spinler 
2000ae35ac5dSBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
2001ae35ac5dSBrandon Wyman         PMBusExpectations expectations;
2002ae35ac5dSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
2003*592bd27cSMatt Spinler 
2004ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2005ae35ac5dSBrandon Wyman             .Times(1)
2006ae35ac5dSBrandon Wyman             .WillOnce(Return("206000"));
2007ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2008ae35ac5dSBrandon Wyman             .WillRepeatedly(Return("2000"));
2009*592bd27cSMatt Spinler 
2010c3324424SBrandon Wyman         psu.analyze();
2011*592bd27cSMatt Spinler         EXPECT_EQ(psu.getPeakInputPower().value_or(0), 213);
2012c3324424SBrandon Wyman     }
2013*592bd27cSMatt Spinler 
2014*592bd27cSMatt Spinler     // Test that there is no peak power sensor on 1400W PSs
2015c3324424SBrandon Wyman     {
20169464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
20179464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
2018ae35ac5dSBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
2019ae35ac5dSBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2020ae35ac5dSBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2021*592bd27cSMatt Spinler 
2022ae35ac5dSBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2023*592bd27cSMatt Spinler 
2024ae35ac5dSBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
2025*592bd27cSMatt Spinler 
2026ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2027ae35ac5dSBrandon Wyman             .WillRepeatedly(Return("30725"));
2028*592bd27cSMatt Spinler 
2029ae35ac5dSBrandon Wyman         PMBusExpectations expectations;
2030ae35ac5dSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
2031*592bd27cSMatt Spinler 
2032ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2033*592bd27cSMatt Spinler             .WillRepeatedly(Return("206000"));
2034ae35ac5dSBrandon Wyman         psu.analyze();
2035*592bd27cSMatt Spinler 
2036*592bd27cSMatt Spinler         EXPECT_EQ(psu.getPeakInputPower(), std::nullopt);
2037ae35ac5dSBrandon Wyman     }
2038*592bd27cSMatt Spinler 
2039*592bd27cSMatt Spinler     // Test that IPSPS power supplies don't have peak power
2040ae35ac5dSBrandon Wyman     {
2041c3324424SBrandon Wyman         PowerSupply psu{bus,      PSUInventoryPath, 11,
20429464c429SGeorge Liu                         0x58,     "inspur-ipsps",   PSUGPIOLineName,
20439464c429SGeorge Liu                         isPowerOn};
2044*592bd27cSMatt Spinler 
2045c3324424SBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
2046c3324424SBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2047*592bd27cSMatt Spinler 
2048ae35ac5dSBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2049*592bd27cSMatt Spinler 
2050c3324424SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2051*592bd27cSMatt Spinler 
2052ae35ac5dSBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
2053ae35ac5dSBrandon Wyman         PMBusExpectations expectations;
2054ae35ac5dSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
2055*592bd27cSMatt Spinler 
2056*592bd27cSMatt Spinler         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2057*592bd27cSMatt Spinler             .WillRepeatedly(Return("206000"));
2058*592bd27cSMatt Spinler 
2059*592bd27cSMatt Spinler         psu.analyze();
2060*592bd27cSMatt Spinler 
2061*592bd27cSMatt Spinler         EXPECT_EQ(psu.getPeakInputPower(), std::nullopt);
2062*592bd27cSMatt Spinler     }
2063*592bd27cSMatt Spinler 
2064*592bd27cSMatt Spinler     // Test that a bad response from the input_history command leads
2065*592bd27cSMatt Spinler     // to an NaN value.
2066*592bd27cSMatt Spinler     {
2067*592bd27cSMatt Spinler         PowerSupply psu{bus,         PSUInventoryPath, 6,        0x6f,
2068*592bd27cSMatt Spinler                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
2069*592bd27cSMatt Spinler 
2070*592bd27cSMatt Spinler         MockedGPIOInterface* mockPresenceGPIO =
2071*592bd27cSMatt Spinler             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2072*592bd27cSMatt Spinler         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2073*592bd27cSMatt Spinler 
2074*592bd27cSMatt Spinler         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2075*592bd27cSMatt Spinler 
2076*592bd27cSMatt Spinler         setMissingToPresentExpects(mockPMBus, mockedUtil);
2077*592bd27cSMatt Spinler         PMBusExpectations expectations;
2078*592bd27cSMatt Spinler         setPMBusExpectations(mockPMBus, expectations);
2079*592bd27cSMatt Spinler 
2080ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2081ae35ac5dSBrandon Wyman             .Times(1)
2082ae35ac5dSBrandon Wyman             .WillOnce(Return("206000"));
2083ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2084*592bd27cSMatt Spinler             .WillRepeatedly(Return("2000"));
2085*592bd27cSMatt Spinler 
2086*592bd27cSMatt Spinler         // Don't return the full 5 bytes.
2087*592bd27cSMatt Spinler         EXPECT_CALL(mockPMBus,
2088*592bd27cSMatt Spinler                     readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug, 5))
2089*592bd27cSMatt Spinler             .WillRepeatedly(Return(std::vector<uint8_t>{0x01, 0x5c}));
2090*592bd27cSMatt Spinler 
2091c3324424SBrandon Wyman         psu.analyze();
2092*592bd27cSMatt Spinler         EXPECT_THAT(psu.getPeakInputPower().value_or(0), IsNan());
2093*592bd27cSMatt Spinler     }
2094c3324424SBrandon Wyman }
209518a24d92SBrandon Wyman 
209618a24d92SBrandon Wyman TEST_F(PowerSupplyTests, IsSyncHistoryRequired)
209718a24d92SBrandon Wyman {
209818a24d92SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
20999464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 8,        0x6f,
21009464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
210118a24d92SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), false);
210218a24d92SBrandon Wyman     EXPECT_EQ(psu.isSyncHistoryRequired(), false);
210318a24d92SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
210418a24d92SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
210518a24d92SBrandon Wyman     // Always return 1 to indicate present.
210618a24d92SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
210718a24d92SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
210818a24d92SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
2109ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2110ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
2111ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
2112ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2113*592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
211418a24d92SBrandon Wyman     PMBusExpectations expectations;
211518a24d92SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
211618a24d92SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
211718a24d92SBrandon Wyman         .Times(1)
211818a24d92SBrandon Wyman         .WillRepeatedly(Return("205000"));
211918a24d92SBrandon Wyman     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
212018a24d92SBrandon Wyman     psu.analyze();
212118a24d92SBrandon Wyman     // The ibm-cffps power supply should support input history
212218a24d92SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
212318a24d92SBrandon Wyman     // Missing -> Present requires history sync
212418a24d92SBrandon Wyman     EXPECT_EQ(psu.isSyncHistoryRequired(), true);
212518a24d92SBrandon Wyman     psu.clearSyncHistoryRequired();
212618a24d92SBrandon Wyman     EXPECT_EQ(psu.isSyncHistoryRequired(), false);
212718a24d92SBrandon Wyman }
2128*592bd27cSMatt Spinler 
2129*592bd27cSMatt Spinler TEST_F(PowerSupplyTests, TestLinearConversions)
2130*592bd27cSMatt Spinler {
2131*592bd27cSMatt Spinler     // Mantissa > 0, exponent = 0
2132*592bd27cSMatt Spinler     EXPECT_EQ(0, PowerSupply::linearToInteger(0));
2133*592bd27cSMatt Spinler     EXPECT_EQ(1, PowerSupply::linearToInteger(1));
2134*592bd27cSMatt Spinler     EXPECT_EQ(38, PowerSupply::linearToInteger(0x26));
2135*592bd27cSMatt Spinler     EXPECT_EQ(1023, PowerSupply::linearToInteger(0x3FF));
2136*592bd27cSMatt Spinler 
2137*592bd27cSMatt Spinler     // Mantissa < 0, exponent = 0
2138*592bd27cSMatt Spinler     EXPECT_EQ(-1, PowerSupply::linearToInteger(0x7FF));
2139*592bd27cSMatt Spinler     EXPECT_EQ(-20, PowerSupply::linearToInteger(0x7EC));
2140*592bd27cSMatt Spinler     EXPECT_EQ(-769, PowerSupply::linearToInteger(0x4FF));
2141*592bd27cSMatt Spinler     EXPECT_EQ(-989, PowerSupply::linearToInteger(0x423));
2142*592bd27cSMatt Spinler     EXPECT_EQ(-1024, PowerSupply::linearToInteger(0x400));
2143*592bd27cSMatt Spinler 
2144*592bd27cSMatt Spinler     // Mantissa >= 0, exponent > 0
2145*592bd27cSMatt Spinler     // M = 1, E = 2
2146*592bd27cSMatt Spinler     EXPECT_EQ(4, PowerSupply::linearToInteger(0x1001));
2147*592bd27cSMatt Spinler 
2148*592bd27cSMatt Spinler     // M = 1000, E = 10
2149*592bd27cSMatt Spinler     EXPECT_EQ(1024000, PowerSupply::linearToInteger(0x53E8));
2150*592bd27cSMatt Spinler 
2151*592bd27cSMatt Spinler     // M = 10, E = 15
2152*592bd27cSMatt Spinler     EXPECT_EQ(327680, PowerSupply::linearToInteger(0x780A));
2153*592bd27cSMatt Spinler 
2154*592bd27cSMatt Spinler     // Mantissa >= 0, exponent < 0
2155*592bd27cSMatt Spinler     // M = 0, E = -1
2156*592bd27cSMatt Spinler     EXPECT_EQ(0, PowerSupply::linearToInteger(0xF800));
2157*592bd27cSMatt Spinler 
2158*592bd27cSMatt Spinler     // M = 100, E = -2
2159*592bd27cSMatt Spinler     EXPECT_EQ(25, PowerSupply::linearToInteger(0xF064));
2160*592bd27cSMatt Spinler 
2161*592bd27cSMatt Spinler     // Mantissa < 0, exponent < 0
2162*592bd27cSMatt Spinler     // M = -100, E = -1
2163*592bd27cSMatt Spinler     EXPECT_EQ(-50, PowerSupply::linearToInteger(0xFF9C));
2164*592bd27cSMatt Spinler 
2165*592bd27cSMatt Spinler     // M = -1024, E = -7
2166*592bd27cSMatt Spinler     EXPECT_EQ(-8, PowerSupply::linearToInteger(0xCC00));
2167*592bd27cSMatt Spinler }
2168