13f1242f3SBrandon Wyman #include "../power_supply.hpp"
23f1242f3SBrandon Wyman #include "mock.hpp"
33f1242f3SBrandon Wyman 
43f1242f3SBrandon Wyman #include <xyz/openbmc_project/Common/Device/error.hpp>
53f1242f3SBrandon Wyman #include <xyz/openbmc_project/Common/error.hpp>
63f1242f3SBrandon Wyman 
73f1242f3SBrandon Wyman #include <gmock/gmock.h>
83f1242f3SBrandon Wyman #include <gtest/gtest.h>
93f1242f3SBrandon Wyman 
103f1242f3SBrandon Wyman using namespace phosphor::power::psu;
113f1242f3SBrandon Wyman using namespace phosphor::pmbus;
123f1242f3SBrandon Wyman 
133f1242f3SBrandon Wyman using ::testing::_;
1459a35793SBrandon Wyman using ::testing::Args;
153f1242f3SBrandon Wyman using ::testing::Assign;
163f1242f3SBrandon Wyman using ::testing::DoAll;
1759a35793SBrandon Wyman using ::testing::ElementsAre;
18592bd27cSMatt Spinler using ::testing::IsNan;
1959a35793SBrandon Wyman using ::testing::NotNull;
203f1242f3SBrandon Wyman using ::testing::Return;
213f1242f3SBrandon Wyman using ::testing::StrEq;
223f1242f3SBrandon Wyman 
233f1242f3SBrandon Wyman static auto PSUInventoryPath = "/xyz/bmc/inv/sys/chassis/board/powersupply0";
24681b2a36SB. J. Wyman static auto PSUGPIOLineName = "presence-ps0";
259464c429SGeorge Liu static auto isPowerOn = []() { return true; };
263f1242f3SBrandon Wyman 
27b654c619SBrandon Wyman struct PMBusExpectations
28b654c619SBrandon Wyman {
29b654c619SBrandon Wyman     uint16_t statusWordValue{0x0000};
30b654c619SBrandon Wyman     uint8_t statusInputValue{0x00};
31b654c619SBrandon Wyman     uint8_t statusMFRValue{0x00};
32b654c619SBrandon Wyman     uint8_t statusCMLValue{0x00};
33b654c619SBrandon Wyman     uint8_t statusVOUTValue{0x00};
34b10b3be0SBrandon Wyman     uint8_t statusIOUTValue{0x00};
357ee4d7e4SBrandon Wyman     uint8_t statusFans12Value{0x00};
3696893a46SBrandon Wyman     uint8_t statusTempValue{0x00};
37b654c619SBrandon Wyman };
38b654c619SBrandon Wyman 
398da35c51SBrandon Wyman // Helper function to setup expectations for various STATUS_* commands
40b654c619SBrandon Wyman void setPMBusExpectations(MockedPMBus& mockPMBus,
41b654c619SBrandon Wyman                           const PMBusExpectations& expectations)
428da35c51SBrandon Wyman {
4332453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _, _))
448da35c51SBrandon Wyman         .Times(1)
45b654c619SBrandon Wyman         .WillOnce(Return(expectations.statusWordValue));
468da35c51SBrandon Wyman 
47b654c619SBrandon Wyman     if (expectations.statusWordValue != 0)
488da35c51SBrandon Wyman     {
498da35c51SBrandon Wyman         // If fault bits are on in STATUS_WORD, there will also be a read of
5096893a46SBrandon Wyman         // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and
5196893a46SBrandon Wyman         // STATUS_TEMPERATURE.
5232453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _, _))
538da35c51SBrandon Wyman             .Times(1)
54b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusInputValue));
5532453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_MFR, _, _))
568da35c51SBrandon Wyman             .Times(1)
57b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusMFRValue));
5832453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_CML, _, _))
598da35c51SBrandon Wyman             .Times(1)
60b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusCMLValue));
616710ba2cSBrandon Wyman         // Page will need to be set to 0 to read STATUS_VOUT.
626710ba2cSBrandon Wyman         EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0))
636710ba2cSBrandon Wyman             .Times(1)
646710ba2cSBrandon Wyman             .WillOnce(Return("status0_vout"));
6532453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read("status0_vout", _, _))
666710ba2cSBrandon Wyman             .Times(1)
67b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusVOUTValue));
6832453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _, _))
69b10b3be0SBrandon Wyman             .Times(1)
70b10b3be0SBrandon Wyman             .WillOnce(Return(expectations.statusIOUTValue));
7132453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _, _))
727ee4d7e4SBrandon Wyman             .Times(1)
737ee4d7e4SBrandon Wyman             .WillOnce(Return(expectations.statusFans12Value));
7432453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _, _))
7596893a46SBrandon Wyman             .Times(1)
7696893a46SBrandon Wyman             .WillOnce(Return(expectations.statusTempValue));
778da35c51SBrandon Wyman     }
78592bd27cSMatt Spinler 
79592bd27cSMatt Spinler     // Default max/peak is 213W
80592bd27cSMatt Spinler     ON_CALL(mockPMBus, readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug, 5))
81592bd27cSMatt Spinler         .WillByDefault(
82592bd27cSMatt Spinler             Return(std::vector<uint8_t>{0x01, 0x5c, 0xf3, 0x54, 0xf3}));
838da35c51SBrandon Wyman }
848da35c51SBrandon Wyman 
853f1242f3SBrandon Wyman class PowerSupplyTests : public ::testing::Test
863f1242f3SBrandon Wyman {
873f1242f3SBrandon Wyman   public:
883f1242f3SBrandon Wyman     PowerSupplyTests() :
893f1242f3SBrandon Wyman         mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
903f1242f3SBrandon Wyman     {
913f1242f3SBrandon Wyman         ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
923f1242f3SBrandon Wyman     }
933f1242f3SBrandon Wyman 
943f1242f3SBrandon Wyman     ~PowerSupplyTests() override
953f1242f3SBrandon Wyman     {
963f1242f3SBrandon Wyman         freeUtils();
973f1242f3SBrandon Wyman     }
983f1242f3SBrandon Wyman 
993f1242f3SBrandon Wyman     const MockedUtil& mockedUtil;
1003f1242f3SBrandon Wyman };
1013f1242f3SBrandon Wyman 
102391a0690SBrandon Wyman // Helper function for when a power supply goes from missing to present.
103391a0690SBrandon Wyman void setMissingToPresentExpects(MockedPMBus& pmbus, const MockedUtil& util)
104391a0690SBrandon Wyman {
105391a0690SBrandon Wyman     // Call to analyze() will update to present, that will trigger updating
106391a0690SBrandon Wyman     // to the correct/latest HWMON directory, in case it changes.
107391a0690SBrandon Wyman     EXPECT_CALL(pmbus, findHwmonDir());
108391a0690SBrandon Wyman     // Presence change from missing to present will trigger write to
109391a0690SBrandon Wyman     // ON_OFF_CONFIG.
110391a0690SBrandon Wyman     EXPECT_CALL(pmbus, writeBinary(ON_OFF_CONFIG, _, _));
111391a0690SBrandon Wyman     // Presence change from missing to present will trigger in1_input read
112391a0690SBrandon Wyman     // in an attempt to get CLEAR_FAULTS called.
11382affd94SBrandon Wyman     // This READ_VIN for CLEAR_FAULTS does not check the returned value.
1143225a45cSBrandon Wyman     EXPECT_CALL(pmbus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
1153225a45cSBrandon Wyman     // The call for clearing faults includes clearing VIN_UV fault.
1163225a45cSBrandon Wyman     // The voltage defaults to 0, the first call to analyze should update the
1173225a45cSBrandon Wyman     // voltage to the current reading, triggering clearing VIN_UV fault(s)
1183225a45cSBrandon Wyman     // due to below minimum to within range voltage.
1193225a45cSBrandon Wyman     EXPECT_CALL(pmbus, read("in1_lcrit_alarm", _, _))
12082affd94SBrandon Wyman         .Times(2)
1213225a45cSBrandon Wyman         .WillRepeatedly(Return(1));
122391a0690SBrandon Wyman     // Missing/present call will update Presence in inventory.
123391a0690SBrandon Wyman     EXPECT_CALL(util, setPresence(_, _, true, _));
124391a0690SBrandon Wyman }
125391a0690SBrandon Wyman 
1263f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Constructor)
1273f1242f3SBrandon Wyman {
1283f1242f3SBrandon Wyman     /**
1293f1242f3SBrandon Wyman      * @param[in] invpath - String for inventory path to use
1303f1242f3SBrandon Wyman      * @param[in] i2cbus - The bus number this power supply is on
1313f1242f3SBrandon Wyman      * @param[in] i2caddr - The 16-bit I2C address of the power supply
132681b2a36SB. J. Wyman      * @param[in] gpioLineName - The string for the gpio-line-name to read for
133681b2a36SB. J. Wyman      * presence.
134681b2a36SB. J. Wyman      * @param[in] bindDelay - Time in milliseconds to delay binding the device
135681b2a36SB. J. Wyman      * driver after seeing the presence line go active.
1363f1242f3SBrandon Wyman      */
1373f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1381d7a7df8SBrandon Wyman 
1391d7a7df8SBrandon Wyman     // Try where inventory path is empty, constructor should fail.
1401d7a7df8SBrandon Wyman     try
1411d7a7df8SBrandon Wyman     {
142c3324424SBrandon Wyman         auto psu = std::make_unique<PowerSupply>(bus, "", 3, 0x68, "ibm-cffps",
1439464c429SGeorge Liu                                                  PSUGPIOLineName, isPowerOn);
1441d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have reached this line.";
1451d7a7df8SBrandon Wyman     }
1461d7a7df8SBrandon Wyman     catch (const std::invalid_argument& e)
1471d7a7df8SBrandon Wyman     {
1481d7a7df8SBrandon Wyman         EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
1491d7a7df8SBrandon Wyman     }
1501d7a7df8SBrandon Wyman     catch (...)
1511d7a7df8SBrandon Wyman     {
1521d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
1531d7a7df8SBrandon Wyman     }
1541d7a7df8SBrandon Wyman 
155681b2a36SB. J. Wyman     // TODO: Try invalid i2c address?
156681b2a36SB. J. Wyman 
157681b2a36SB. J. Wyman     // Try where gpioLineName is empty.
1581d7a7df8SBrandon Wyman     try
1591d7a7df8SBrandon Wyman     {
160c3324424SBrandon Wyman         auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
1619464c429SGeorge Liu                                                  "ibm-cffps", "", isPowerOn);
162681b2a36SB. J. Wyman         ADD_FAILURE()
163681b2a36SB. J. Wyman             << "Should not have reached this line. Invalid gpioLineName.";
164681b2a36SB. J. Wyman     }
165681b2a36SB. J. Wyman     catch (const std::invalid_argument& e)
166681b2a36SB. J. Wyman     {
167681b2a36SB. J. Wyman         EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
168681b2a36SB. J. Wyman     }
169681b2a36SB. J. Wyman     catch (...)
170681b2a36SB. J. Wyman     {
171681b2a36SB. J. Wyman         ADD_FAILURE() << "Should not have caught exception.";
172681b2a36SB. J. Wyman     }
173681b2a36SB. J. Wyman 
174681b2a36SB. J. Wyman     // Test with valid arguments
175681b2a36SB. J. Wyman     // NOT using D-Bus inventory path for presence.
176681b2a36SB. J. Wyman     try
177681b2a36SB. J. Wyman     {
178681b2a36SB. J. Wyman         auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
1799464c429SGeorge Liu                                                  "ibm-cffps", PSUGPIOLineName,
1809464c429SGeorge Liu                                                  isPowerOn);
1813f1242f3SBrandon Wyman 
1823f1242f3SBrandon Wyman         EXPECT_EQ(psu->isPresent(), false);
1833f1242f3SBrandon Wyman         EXPECT_EQ(psu->isFaulted(), false);
1848da35c51SBrandon Wyman         EXPECT_EQ(psu->hasCommFault(), false);
1853f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasInputFault(), false);
1863f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasMFRFault(), false);
1873f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasVINUVFault(), false);
1886710ba2cSBrandon Wyman         EXPECT_EQ(psu->hasVoutOVFault(), false);
189b10b3be0SBrandon Wyman         EXPECT_EQ(psu->hasIoutOCFault(), false);
1902cf46945SBrandon Wyman         EXPECT_EQ(psu->hasVoutUVFault(), false);
1917ee4d7e4SBrandon Wyman         EXPECT_EQ(psu->hasFanFault(), false);
19296893a46SBrandon Wyman         EXPECT_EQ(psu->hasTempFault(), false);
1932916ea52SBrandon Wyman         EXPECT_EQ(psu->hasPgoodFault(), false);
19439ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPSKillFault(), false);
19539ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPS12VcsFault(), false);
19639ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPSCS12VFault(), false);
1973f1242f3SBrandon Wyman     }
1981d7a7df8SBrandon Wyman     catch (...)
1991d7a7df8SBrandon Wyman     {
2001d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
2011d7a7df8SBrandon Wyman     }
202681b2a36SB. J. Wyman 
203681b2a36SB. J. Wyman     // Test with valid arguments
204681b2a36SB. J. Wyman     // TODO: Using D-Bus inventory path for presence.
205681b2a36SB. J. Wyman     try
206681b2a36SB. J. Wyman     {
207681b2a36SB. J. Wyman         // FIXME: How do I get that presenceGPIO.read() in the startup to throw
208681b2a36SB. J. Wyman         // an exception?
209681b2a36SB. J. Wyman 
210681b2a36SB. J. Wyman         // EXPECT_CALL(mockedUtil, getPresence(_,
211681b2a36SB. J. Wyman         // StrEq(PSUInventoryPath)))
212681b2a36SB. J. Wyman         //    .Times(1);
213681b2a36SB. J. Wyman     }
214681b2a36SB. J. Wyman     catch (...)
215681b2a36SB. J. Wyman     {
216681b2a36SB. J. Wyman         ADD_FAILURE() << "Should not have caught exception.";
217681b2a36SB. J. Wyman     }
2181d7a7df8SBrandon Wyman }
2193f1242f3SBrandon Wyman 
2203f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Analyze)
2213f1242f3SBrandon Wyman {
2223f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
2233f1242f3SBrandon Wyman 
224b654c619SBrandon Wyman     {
225681b2a36SB. J. Wyman         // If I default to reading the GPIO, I will NOT expect a call to
226681b2a36SB. J. Wyman         // getPresence().
227681b2a36SB. J. Wyman 
2289464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 4,        0x69,
2299464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
2303ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
2313ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
232681b2a36SB. J. Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
233681b2a36SB. J. Wyman 
2343f1242f3SBrandon Wyman         psu.analyze();
2353f1242f3SBrandon Wyman         // By default, nothing should change.
2363f1242f3SBrandon Wyman         EXPECT_EQ(psu.isPresent(), false);
2373f1242f3SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), false);
2383f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), false);
2393f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), false);
2403f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), false);
24185c7bf41SBrandon Wyman         EXPECT_EQ(psu.hasCommFault(), false);
2426710ba2cSBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), false);
243b10b3be0SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), false);
2442cf46945SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), false);
2457ee4d7e4SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), false);
24696893a46SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), false);
2472916ea52SBrandon Wyman         EXPECT_EQ(psu.hasPgoodFault(), false);
24839ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), false);
24939ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), false);
25039ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), false);
251b654c619SBrandon Wyman     }
2523f1242f3SBrandon Wyman 
2539464c429SGeorge Liu     PowerSupply psu2{bus,         PSUInventoryPath, 5,        0x6a,
2549464c429SGeorge Liu                      "ibm-cffps", PSUGPIOLineName,  isPowerOn};
255681b2a36SB. J. Wyman     // In order to get the various faults tested, the power supply needs to
256681b2a36SB. J. Wyman     // be present in order to read from the PMBus device(s).
2573ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO2 =
2583ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
25906ca4590SBrandon Wyman     // Always return 1 to indicate present.
26006ca4590SBrandon Wyman     // Each analyze() call will trigger a read of the presence GPIO.
26106ca4590SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1));
262681b2a36SB. J. Wyman     EXPECT_EQ(psu2.isPresent(), false);
2633f1242f3SBrandon Wyman 
2643f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
265391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
266ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
267ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
268ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
269ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
270592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
271b654c619SBrandon Wyman 
272b654c619SBrandon Wyman     // STATUS_WORD INPUT fault.
273b654c619SBrandon Wyman     {
274b654c619SBrandon Wyman         // Start with STATUS_WORD 0x0000. Powered on, no faults.
275b654c619SBrandon Wyman         // Set expectations for a no fault
276b654c619SBrandon Wyman         PMBusExpectations expectations;
277b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
27882affd94SBrandon Wyman         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
27982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
28082affd94SBrandon Wyman             .Times(1)
28182affd94SBrandon Wyman             .WillOnce(Return("206000"));
2823f1242f3SBrandon Wyman         psu2.analyze();
2833f1242f3SBrandon Wyman         EXPECT_EQ(psu2.isPresent(), true);
2843f1242f3SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
2853f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
2863f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasMFRFault(), false);
2873f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasVINUVFault(), false);
28885c7bf41SBrandon Wyman         EXPECT_EQ(psu2.hasCommFault(), false);
2896710ba2cSBrandon Wyman         EXPECT_EQ(psu2.hasVoutOVFault(), false);
290b10b3be0SBrandon Wyman         EXPECT_EQ(psu2.hasIoutOCFault(), false);
2912cf46945SBrandon Wyman         EXPECT_EQ(psu2.hasVoutUVFault(), false);
2927ee4d7e4SBrandon Wyman         EXPECT_EQ(psu2.hasFanFault(), false);
29396893a46SBrandon Wyman         EXPECT_EQ(psu2.hasTempFault(), false);
2942916ea52SBrandon Wyman         EXPECT_EQ(psu2.hasPgoodFault(), false);
29539ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPSKillFault(), false);
29639ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPS12VcsFault(), false);
29739ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPSCS12VFault(), false);
2983f1242f3SBrandon Wyman 
299b654c619SBrandon Wyman         // Update expectations for STATUS_WORD input fault/warn
30096893a46SBrandon Wyman         // STATUS_INPUT fault bits ... on.
301b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
3023225a45cSBrandon Wyman         // IIN_OC fault.
3033225a45cSBrandon Wyman         expectations.statusInputValue = 0x04;
304c2906f47SBrandon Wyman 
305c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
306c2906f47SBrandon Wyman         {
307b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
30882affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
30982affd94SBrandon Wyman                 .Times(1)
31082affd94SBrandon Wyman                 .WillOnce(Return("207000"));
3113f1242f3SBrandon Wyman             psu2.analyze();
3123f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
313c2906f47SBrandon Wyman             // Should not be faulted until it reaches the deglitch limit.
314c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
315c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
3163f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
3173f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
31885c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
3196710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
320b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
3212cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
3227ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
32396893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
3242916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
32539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
32639ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
32739ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
328b654c619SBrandon Wyman         }
329c2906f47SBrandon Wyman     }
330c2906f47SBrandon Wyman 
33132453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
3323225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
3333225a45cSBrandon Wyman         .Times(1)
3343225a45cSBrandon Wyman         .WillOnce(Return(1));
335c2906f47SBrandon Wyman     psu2.clearFaults();
3363f1242f3SBrandon Wyman 
3373f1242f3SBrandon Wyman     // STATUS_WORD INPUT/UV fault.
338b654c619SBrandon Wyman     {
3393f1242f3SBrandon Wyman         // First need it to return good status, then the fault
340b654c619SBrandon Wyman         PMBusExpectations expectations;
341b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
34282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
34382affd94SBrandon Wyman             .Times(1)
34482affd94SBrandon Wyman             .WillOnce(Return("208000"));
3453f1242f3SBrandon Wyman         psu2.analyze();
346c2906f47SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
347c2906f47SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
3488da35c51SBrandon Wyman         // Now set fault bits in STATUS_WORD
349b654c619SBrandon Wyman         expectations.statusWordValue =
3508da35c51SBrandon Wyman             (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
3518da35c51SBrandon Wyman         // STATUS_INPUT fault bits ... on.
3523225a45cSBrandon Wyman         expectations.statusInputValue = 0x18;
353c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
354c2906f47SBrandon Wyman         {
355b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
35682affd94SBrandon Wyman             // Input/UV fault, so voltage should read back low.
35782affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
35882affd94SBrandon Wyman                 .Times(1)
35982affd94SBrandon Wyman                 .WillOnce(Return("19123"));
3603f1242f3SBrandon Wyman             psu2.analyze();
3613f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
362c2906f47SBrandon Wyman             // Only faulted if hit deglitch limit
363c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
364c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
365c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), x >= DEGLITCH_LIMIT);
3663f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
36785c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
3686710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
369b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
3702cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
3717ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
37296893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
3732916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
37439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
37539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
37639ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
377c2906f47SBrandon Wyman         }
37882affd94SBrandon Wyman         // Turning VIN_UV fault off causes clearing of faults, causing read of
37982affd94SBrandon Wyman         // in1_input as an attempt to get CLEAR_FAULTS called.
38082affd94SBrandon Wyman         expectations.statusWordValue = 0;
38182affd94SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
38282affd94SBrandon Wyman         // The call to read the voltage
38382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
38482affd94SBrandon Wyman             .Times(1)
38582affd94SBrandon Wyman             .WillOnce(Return("209000"));
3863225a45cSBrandon Wyman         // The call to clear VIN_UV/Off fault(s)
3873225a45cSBrandon Wyman         EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
38832453e9bSBrandon Wyman             .Times(1)
3893225a45cSBrandon Wyman             .WillOnce(Return(1));
39082affd94SBrandon Wyman         psu2.analyze();
39182affd94SBrandon Wyman         // Should remain present, no longer be faulted, no input fault, no
39282affd94SBrandon Wyman         // VIN_UV fault. Nothing else should change.
39382affd94SBrandon Wyman         EXPECT_EQ(psu2.isPresent(), true);
39482affd94SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
39582affd94SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
39682affd94SBrandon Wyman         EXPECT_EQ(psu2.hasVINUVFault(), false);
397b654c619SBrandon Wyman     }
3983f1242f3SBrandon Wyman 
39932453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
4003225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
4013225a45cSBrandon Wyman         .Times(1)
4023225a45cSBrandon Wyman         .WillOnce(Return(1));
403c2906f47SBrandon Wyman     psu2.clearFaults();
404c2906f47SBrandon Wyman 
4053f1242f3SBrandon Wyman     // STATUS_WORD MFR fault.
406b654c619SBrandon Wyman     {
407f07bc797SBrandon Wyman         // First need it to return good status, then the fault
408b654c619SBrandon Wyman         PMBusExpectations expectations;
409b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
41082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
41182affd94SBrandon Wyman             .Times(1)
41282affd94SBrandon Wyman             .WillOnce(Return("210000"));
4133f1242f3SBrandon Wyman         psu2.analyze();
4148da35c51SBrandon Wyman         // Now STATUS_WORD with MFR fault bit on.
415b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
4168da35c51SBrandon Wyman         // STATUS_MFR bits on.
417b654c619SBrandon Wyman         expectations.statusMFRValue = 0xFF;
418c2906f47SBrandon Wyman 
419c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
420c2906f47SBrandon Wyman         {
421b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
42282affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
42382affd94SBrandon Wyman                 .Times(1)
42482affd94SBrandon Wyman                 .WillOnce(Return("211000"));
4253f1242f3SBrandon Wyman             psu2.analyze();
4263f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
427c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
4283f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
429c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT);
430c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT);
431c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
432c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
4333f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
43485c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
4356710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
436b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
4372cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
4387ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
43996893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
4402916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
441c2906f47SBrandon Wyman         }
442b654c619SBrandon Wyman     }
4433f1242f3SBrandon Wyman 
44432453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
4453225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
4463225a45cSBrandon Wyman         .Times(1)
4473225a45cSBrandon Wyman         .WillOnce(Return(1));
448c2906f47SBrandon Wyman     psu2.clearFaults();
4493225a45cSBrandon Wyman 
45096893a46SBrandon Wyman     // Temperature fault.
451b654c619SBrandon Wyman     {
452f07bc797SBrandon Wyman         // First STATUS_WORD with no bits set, then with temperature fault.
453b654c619SBrandon Wyman         PMBusExpectations expectations;
454b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
45582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
45682affd94SBrandon Wyman             .Times(1)
45782affd94SBrandon Wyman             .WillOnce(Return("212000"));
4583f1242f3SBrandon Wyman         psu2.analyze();
4598da35c51SBrandon Wyman         // STATUS_WORD with temperature fault bit on.
460b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
46196893a46SBrandon Wyman         // STATUS_TEMPERATURE with fault bit(s) on.
46296893a46SBrandon Wyman         expectations.statusTempValue = 0x10;
463c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
464c2906f47SBrandon Wyman         {
465b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
46682affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
46782affd94SBrandon Wyman                 .Times(1)
46882affd94SBrandon Wyman                 .WillOnce(Return("213000"));
4693f1242f3SBrandon Wyman             psu2.analyze();
4703f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
471c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
4723f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
4733f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
4743f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
47585c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
4766710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
477b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
4782cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
4797ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
480c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT);
4812916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
48239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
48339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
48439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
485b654c619SBrandon Wyman         }
486c2906f47SBrandon Wyman     }
48785c7bf41SBrandon Wyman 
4886710ba2cSBrandon Wyman     // VOUT_OV_FAULT fault
489b654c619SBrandon Wyman     {
4906710ba2cSBrandon Wyman         // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
491b654c619SBrandon Wyman         PMBusExpectations expectations;
492b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
49382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
49482affd94SBrandon Wyman             .Times(1)
49582affd94SBrandon Wyman             .WillOnce(Return("216000"));
4966710ba2cSBrandon Wyman         psu2.analyze();
4976710ba2cSBrandon Wyman         // STATUS_WORD with VOUT/VOUT_OV fault.
498b654c619SBrandon Wyman         expectations.statusWordValue =
4996710ba2cSBrandon Wyman             ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
5006710ba2cSBrandon Wyman         // Turn on STATUS_VOUT fault bit(s)
501b654c619SBrandon Wyman         expectations.statusVOUTValue = 0xA0;
502c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
503c2906f47SBrandon Wyman         {
50496893a46SBrandon Wyman             // STATUS_TEMPERATURE don't care (default)
505b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
50682affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
50782affd94SBrandon Wyman                 .Times(1)
50882affd94SBrandon Wyman                 .WillOnce(Return("217000"));
5096710ba2cSBrandon Wyman             psu2.analyze();
5106710ba2cSBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
511c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
5126710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
5136710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
5146710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
5156710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
516c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
5172cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
518b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
5197ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
520b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
521b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
52239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
52339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
52439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
525b10b3be0SBrandon Wyman         }
526c2906f47SBrandon Wyman     }
527b10b3be0SBrandon Wyman 
528b10b3be0SBrandon Wyman     // IOUT_OC_FAULT fault
529b10b3be0SBrandon Wyman     {
530b10b3be0SBrandon Wyman         // First STATUS_WORD with no bits set, then with IOUT_OC fault.
531b10b3be0SBrandon Wyman         PMBusExpectations expectations;
532b10b3be0SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
53382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
53482affd94SBrandon Wyman             .Times(1)
53582affd94SBrandon Wyman             .WillOnce(Return("218000"));
536b10b3be0SBrandon Wyman         psu2.analyze();
537b10b3be0SBrandon Wyman         // STATUS_WORD with IOUT_OC fault.
538b10b3be0SBrandon Wyman         expectations.statusWordValue = status_word::IOUT_OC_FAULT;
539b10b3be0SBrandon Wyman         // Turn on STATUS_IOUT fault bit(s)
540b10b3be0SBrandon Wyman         expectations.statusIOUTValue = 0x88;
541c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
542c2906f47SBrandon Wyman         {
543b10b3be0SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
54482affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
54582affd94SBrandon Wyman                 .Times(1)
54682affd94SBrandon Wyman                 .WillOnce(Return("219000"));
547b10b3be0SBrandon Wyman             psu2.analyze();
548b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
549c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
550b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
551b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
552b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
553b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
554b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
555c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
5562cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
5577ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
5582cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
5592cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
56039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
56139ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
56239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
5632cf46945SBrandon Wyman         }
564c2906f47SBrandon Wyman     }
5652cf46945SBrandon Wyman 
5662cf46945SBrandon Wyman     // VOUT_UV_FAULT
5672cf46945SBrandon Wyman     {
5682cf46945SBrandon Wyman         // First STATUS_WORD with no bits set, then with VOUT fault.
5692cf46945SBrandon Wyman         PMBusExpectations expectations;
5702cf46945SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
57182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
57282affd94SBrandon Wyman             .Times(1)
57382affd94SBrandon Wyman             .WillOnce(Return("220000"));
5742cf46945SBrandon Wyman         psu2.analyze();
5752cf46945SBrandon Wyman         // Change STATUS_WORD to indicate VOUT fault.
5762cf46945SBrandon Wyman         expectations.statusWordValue = (status_word::VOUT_FAULT);
5772cf46945SBrandon Wyman         // Turn on STATUS_VOUT fault bit(s)
5782cf46945SBrandon Wyman         expectations.statusVOUTValue = 0x30;
579c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
580c2906f47SBrandon Wyman         {
5812cf46945SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
58282affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
58382affd94SBrandon Wyman                 .Times(1)
58482affd94SBrandon Wyman                 .WillOnce(Return("221000"));
5852cf46945SBrandon Wyman             psu2.analyze();
5862cf46945SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
587c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
5882cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
5892cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
5902cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
5912cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
5922cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
5932cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
594c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
5957ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
59696893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
5972916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
59839ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
59939ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
60039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
601b654c619SBrandon Wyman         }
602c2906f47SBrandon Wyman     }
6033f1242f3SBrandon Wyman 
6047ee4d7e4SBrandon Wyman     // Fan fault
605b654c619SBrandon Wyman     {
606b654c619SBrandon Wyman         // First STATUS_WORD with no bits set, then with fan fault.
607b654c619SBrandon Wyman         PMBusExpectations expectations;
608b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
60982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
61082affd94SBrandon Wyman             .Times(1)
61182affd94SBrandon Wyman             .WillOnce(Return("222000"));
6123f1242f3SBrandon Wyman         psu2.analyze();
613b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::FAN_FAULT);
6147ee4d7e4SBrandon Wyman         // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
6157ee4d7e4SBrandon Wyman         expectations.statusFans12Value = 0xA0;
616c2906f47SBrandon Wyman 
617c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
618c2906f47SBrandon Wyman         {
619b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
62082affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
62182affd94SBrandon Wyman                 .Times(1)
62282affd94SBrandon Wyman                 .WillOnce(Return("223000"));
6233f1242f3SBrandon Wyman             psu2.analyze();
6243f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
625c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
626c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT);
6273f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
6283f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
6293f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
63085c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
6316710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
632b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
6332cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
63496893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6352916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
63639ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
63739ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
63839ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
639b654c619SBrandon Wyman         }
640c2906f47SBrandon Wyman     }
6412916ea52SBrandon Wyman 
64206ca4590SBrandon Wyman     // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
6432cf46945SBrandon Wyman     {
6442916ea52SBrandon Wyman         // First STATUS_WORD with no bits set.
6452916ea52SBrandon Wyman         PMBusExpectations expectations;
6462916ea52SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
64782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
64882affd94SBrandon Wyman             .Times(1)
64982affd94SBrandon Wyman             .WillOnce(Return("123000"));
6502916ea52SBrandon Wyman         psu2.analyze();
6512916ea52SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
6522916ea52SBrandon Wyman         // POWER_GOOD# inactive, and OFF bit on.
6532916ea52SBrandon Wyman         expectations.statusWordValue =
6542916ea52SBrandon Wyman             ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
6556d469fd4SBrandon Wyman         for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++)
65606ca4590SBrandon Wyman         {
6572916ea52SBrandon Wyman             // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
6582916ea52SBrandon Wyman             // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
6592916ea52SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
66082affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
66182affd94SBrandon Wyman                 .Times(1)
66282affd94SBrandon Wyman                 .WillOnce(Return("124000"));
6632916ea52SBrandon Wyman             psu2.analyze();
6642916ea52SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
6656d469fd4SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= PGOOD_DEGLITCH_LIMIT);
6662916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
6672916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
6682916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
6692916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
6702916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
6712cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
672b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
6737ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
6742916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6756d469fd4SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT);
67606ca4590SBrandon Wyman         }
67706ca4590SBrandon Wyman     }
6782916ea52SBrandon Wyman 
6793f1242f3SBrandon Wyman     // TODO: ReadFailure
6803f1242f3SBrandon Wyman }
6813f1242f3SBrandon Wyman 
68259a35793SBrandon Wyman TEST_F(PowerSupplyTests, OnOffConfig)
68359a35793SBrandon Wyman {
68459a35793SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
68559a35793SBrandon Wyman     uint8_t data = 0x15;
68659a35793SBrandon Wyman 
68759a35793SBrandon Wyman     // Test where PSU is NOT present
68859a35793SBrandon Wyman     try
68959a35793SBrandon Wyman     {
690681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
6910975eaf4SMatt Spinler         EXPECT_CALL(mockedUtil, setAvailable(_, _, _)).Times(0);
6929464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 4,        0x69,
6939464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
694681b2a36SB. J. Wyman 
6953ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
6963ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
697681b2a36SB. J. Wyman         ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
69859a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
699681b2a36SB. J. Wyman         // Constructor should set initial presence, default read returns 0.
70059a35793SBrandon Wyman         // If it is not present, I should not be trying to write to it.
70159a35793SBrandon Wyman         EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
70259a35793SBrandon Wyman         psu.onOffConfig(data);
70359a35793SBrandon Wyman     }
70459a35793SBrandon Wyman     catch (...)
7050c9a33d6SAdriana Kobylak     {}
70659a35793SBrandon Wyman 
70759a35793SBrandon Wyman     // Test where PSU is present
70859a35793SBrandon Wyman     try
70959a35793SBrandon Wyman     {
710681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
7110975eaf4SMatt Spinler         EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
7129464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 5,        0x6a,
7139464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
7143ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
7153ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
716391a0690SBrandon Wyman         // There will potentially be multiple calls, we want it to continue
717391a0690SBrandon Wyman         // returning 1 for the GPIO read to keep the power supply present.
718391a0690SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
71959a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
720391a0690SBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
721ae35ac5dSBrandon Wyman         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
722ae35ac5dSBrandon Wyman         // for INPUT_HISTORY will check max_power_out to see if it is
723ae35ac5dSBrandon Wyman         // old/unsupported power supply. Indicate good value, supported.
724ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
725592bd27cSMatt Spinler             .WillRepeatedly(Return("2000"));
726391a0690SBrandon Wyman         // If I am calling analyze(), I should probably give it good data.
727391a0690SBrandon Wyman         // STATUS_WORD 0x0000 is powered on, no faults.
728391a0690SBrandon Wyman         PMBusExpectations expectations;
729391a0690SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
73082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
73182affd94SBrandon Wyman             .Times(1)
73282affd94SBrandon Wyman             .WillOnce(Return("205000"));
733681b2a36SB. J. Wyman         psu.analyze();
734391a0690SBrandon Wyman         // I definitely should be writting ON_OFF_CONFIG if I call the function
735391a0690SBrandon Wyman         EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
736391a0690SBrandon Wyman                                            Type::HwmonDeviceDebug))
73759a35793SBrandon Wyman             .Times(1);
73859a35793SBrandon Wyman         psu.onOffConfig(data);
73959a35793SBrandon Wyman     }
74059a35793SBrandon Wyman     catch (...)
7410c9a33d6SAdriana Kobylak     {}
74259a35793SBrandon Wyman }
74359a35793SBrandon Wyman 
7443f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, ClearFaults)
7453f1242f3SBrandon Wyman {
7463f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
7479464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 13,       0x68,
7489464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
7493ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
7503ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
75106ca4590SBrandon Wyman     // Always return 1 to indicate present.
75206ca4590SBrandon Wyman     // Each analyze() call will trigger a read of the presence GPIO.
75306ca4590SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
754681b2a36SB. J. Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
755391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
756ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
757ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
758ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
759ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
760592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
7618da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
762b654c619SBrandon Wyman     PMBusExpectations expectations;
763b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
76482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
76582affd94SBrandon Wyman         .Times(1)
76682affd94SBrandon Wyman         .WillOnce(Return("207000"));
767681b2a36SB. J. Wyman     psu.analyze();
7683f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
7693f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
7703f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
7713f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
7723f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
77385c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
7746710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
775b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
7762cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
7777ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
77896893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
7792916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
78039ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
78139ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
78239ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
783b654c619SBrandon Wyman 
784f07bc797SBrandon Wyman     // STATUS_WORD with fault bits galore!
785b654c619SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
786f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
787b654c619SBrandon Wyman     expectations.statusInputValue = 0xFF;
788f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
789b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
79085c7bf41SBrandon Wyman     // STATUS_CML with bits on.
791b654c619SBrandon Wyman     expectations.statusCMLValue = 0xFF;
7926710ba2cSBrandon Wyman     // STATUS_VOUT with bits on.
793b654c619SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
794b10b3be0SBrandon Wyman     // STATUS_IOUT with bits on.
795b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
7967ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
7977ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0xFF;
79896893a46SBrandon Wyman     // STATUS_TEMPERATURE with bits on.
79996893a46SBrandon Wyman     expectations.statusTempValue = 0xFF;
800c2906f47SBrandon Wyman 
8016d469fd4SBrandon Wyman     for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++)
802c2906f47SBrandon Wyman     {
803b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
80482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
80582affd94SBrandon Wyman             .Times(1)
80682affd94SBrandon Wyman             .WillOnce(Return("0"));
8070975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
8080975eaf4SMatt Spinler         {
8090975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
8100975eaf4SMatt Spinler         }
8113f1242f3SBrandon Wyman         psu.analyze();
8123f1242f3SBrandon Wyman         EXPECT_EQ(psu.isPresent(), true);
8132cf46945SBrandon Wyman         // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
8142cf46945SBrandon Wyman         // Rely on HasVoutUVFault() to verify this sets and clears.
8152cf46945SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), false);
8166d469fd4SBrandon Wyman         // pgoodFault at PGOOD_DEGLITCH_LIMIT, all other faults are deglitched
8176d469fd4SBrandon Wyman         // up to DEGLITCH_LIMIT
818c2906f47SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
819c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
820c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
821c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
822c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
823c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
824c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
825c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
8266d469fd4SBrandon Wyman         EXPECT_EQ(psu.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT);
827c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
828c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
829c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
830c2906f47SBrandon Wyman     }
831c2906f47SBrandon Wyman 
83232453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _))
83332453e9bSBrandon Wyman         .Times(1)
83432453e9bSBrandon Wyman         .WillOnce(Return(207000));
8353225a45cSBrandon Wyman     // Clearing VIN_UV fault via in1_lcrit_alarm
8363225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
8373225a45cSBrandon Wyman         .Times(1)
8383225a45cSBrandon Wyman         .WillOnce(Return(1));
8390975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
8403f1242f3SBrandon Wyman     psu.clearFaults();
8413f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
8423f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
8433f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
8443f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
8453f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
84685c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
8476710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
848b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
8492cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
8507ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
85196893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
8522916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
85339ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
85439ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
85539ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
856681b2a36SB. J. Wyman 
85782affd94SBrandon Wyman     // Faults clear on READ_VIN 0 -> !0
85882affd94SBrandon Wyman     // STATUS_WORD with fault bits galore!
85982affd94SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
86082affd94SBrandon Wyman     // STATUS_INPUT with fault bits on.
86182affd94SBrandon Wyman     expectations.statusInputValue = 0xFF;
86282affd94SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
86382affd94SBrandon Wyman     expectations.statusMFRValue = 0xFF;
86482affd94SBrandon Wyman     // STATUS_CML with bits on.
86582affd94SBrandon Wyman     expectations.statusCMLValue = 0xFF;
86682affd94SBrandon Wyman     // STATUS_VOUT with bits on.
86782affd94SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
86882affd94SBrandon Wyman     // STATUS_IOUT with bits on.
86982affd94SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
87082affd94SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
87182affd94SBrandon Wyman     expectations.statusFans12Value = 0xFF;
87282affd94SBrandon Wyman     // STATUS_TEMPERATURE with bits on.
87382affd94SBrandon Wyman     expectations.statusTempValue = 0xFF;
874c2906f47SBrandon Wyman 
8756d469fd4SBrandon Wyman     // All faults deglitched now. Check for false before limit above.
876c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
877c2906f47SBrandon Wyman     {
87882affd94SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
87982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
88082affd94SBrandon Wyman             .Times(1)
88182affd94SBrandon Wyman             .WillOnce(Return("0"));
8820975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
8830975eaf4SMatt Spinler         {
8840975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
8850975eaf4SMatt Spinler         }
88682affd94SBrandon Wyman         psu.analyze();
887c2906f47SBrandon Wyman     }
888c2906f47SBrandon Wyman 
88982affd94SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
89082affd94SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
89182affd94SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), true);
89282affd94SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
89382affd94SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), true);
894*6869acb3SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
89582affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
89682affd94SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), true);
89782affd94SBrandon Wyman     // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
89882affd94SBrandon Wyman     // Rely on HasVoutUVFault() to verify this sets and clears.
89982affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
90082affd94SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), true);
90182affd94SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), true);
9026d469fd4SBrandon Wyman     // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT
9036d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
90482affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), true);
90582affd94SBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), true);
90682affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), true);
90782affd94SBrandon Wyman     // STATUS_WORD with INPUT/VIN_UV fault bits off.
90882affd94SBrandon Wyman     expectations.statusWordValue = 0xDFF7;
90982affd94SBrandon Wyman     // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
91082affd94SBrandon Wyman     // Insufficient Input Voltage bits off.
91182affd94SBrandon Wyman     expectations.statusInputValue = 0xC7;
91282affd94SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
91382affd94SBrandon Wyman     // READ_VIN back in range.
91482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
91582affd94SBrandon Wyman         .Times(1)
91682affd94SBrandon Wyman         .WillOnce(Return("206000"));
9173225a45cSBrandon Wyman     // VIN_UV cleared via in1_lcrit_alarm when voltage back in range.
9183225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
9193225a45cSBrandon Wyman         .Times(1)
9203225a45cSBrandon Wyman         .WillOnce(Return(1));
9213225a45cSBrandon Wyman     psu.analyze();
9223225a45cSBrandon Wyman     // We only cleared the VIN_UV and OFF faults.
9233225a45cSBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
9243225a45cSBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
9253225a45cSBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
9263225a45cSBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
9273225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
928*6869acb3SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
9293225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
9303225a45cSBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), true);
9313225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
9323225a45cSBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), true);
9333225a45cSBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), true);
9346d469fd4SBrandon Wyman     // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT
9356d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
9363225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), true);
9373225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), true);
9383225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), true);
9393225a45cSBrandon Wyman 
9403225a45cSBrandon Wyman     // All faults cleared
9413225a45cSBrandon Wyman     expectations = {0};
9423225a45cSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
9433225a45cSBrandon Wyman     // READ_VIN back in range.
9443225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
9453225a45cSBrandon Wyman         .Times(1)
9463225a45cSBrandon Wyman         .WillOnce(Return("206000"));
9470975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
94882affd94SBrandon Wyman     psu.analyze();
94982affd94SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
95082affd94SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
95182affd94SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
95282affd94SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
95382affd94SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
95482affd94SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
95582affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
95682affd94SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
95782affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
95882affd94SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
95982affd94SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
96082affd94SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
96182affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
96282affd94SBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
96382affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
96482affd94SBrandon Wyman 
965681b2a36SB. J. Wyman     // TODO: Faults clear on missing/present?
9663f1242f3SBrandon Wyman }
9673f1242f3SBrandon Wyman 
9683f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, UpdateInventory)
9693f1242f3SBrandon Wyman {
9703f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
9711d7a7df8SBrandon Wyman 
9721d7a7df8SBrandon Wyman     try
9731d7a7df8SBrandon Wyman     {
9749464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
9759464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
9761d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
9771d7a7df8SBrandon Wyman         // If it is not present, I should not be trying to read a string
9781d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
9791d7a7df8SBrandon Wyman         psu.updateInventory();
9801d7a7df8SBrandon Wyman     }
9811d7a7df8SBrandon Wyman     catch (...)
9821d7a7df8SBrandon Wyman     {
9831d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
9841d7a7df8SBrandon Wyman     }
9851d7a7df8SBrandon Wyman 
9861d7a7df8SBrandon Wyman     try
9871d7a7df8SBrandon Wyman     {
9889464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 13,       0x69,
9899464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
9903ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
9913ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
992681b2a36SB. J. Wyman         // GPIO read return 1 to indicate present.
993681b2a36SB. J. Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
9941d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
995391a0690SBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
996ae35ac5dSBrandon Wyman         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
997ae35ac5dSBrandon Wyman         // for INPUT_HISTORY will check max_power_out to see if it is
998ae35ac5dSBrandon Wyman         // old/unsupported power supply. Indicate good value, supported.
999ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1000592bd27cSMatt Spinler             .WillRepeatedly(Return("2000"));
1001391a0690SBrandon Wyman         // STATUS_WORD 0x0000 is powered on, no faults.
1002391a0690SBrandon Wyman         PMBusExpectations expectations;
1003391a0690SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
100482affd94SBrandon Wyman         // Call to analyze will read voltage, trigger clear faults for 0 to
100582affd94SBrandon Wyman         // within range.
100682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
100782affd94SBrandon Wyman             .Times(1)
100882affd94SBrandon Wyman             .WillOnce(Return("123456"));
1009391a0690SBrandon Wyman         psu.analyze();
10101d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
10113f1242f3SBrandon Wyman         psu.updateInventory();
10121d7a7df8SBrandon Wyman 
10133c530fbdSBrandon Wyman #if IBM_VPD
10141d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _))
10151d7a7df8SBrandon Wyman             .WillOnce(Return("CCIN"))
10161d7a7df8SBrandon Wyman             .WillOnce(Return("PN3456"))
10171d7a7df8SBrandon Wyman             .WillOnce(Return("FN3456"))
10181d7a7df8SBrandon Wyman             .WillOnce(Return("HEADER"))
10191d7a7df8SBrandon Wyman             .WillOnce(Return("SN3456"))
10201d7a7df8SBrandon Wyman             .WillOnce(Return("FW3456"));
10213c530fbdSBrandon Wyman #endif
10221d7a7df8SBrandon Wyman         psu.updateInventory();
10231d7a7df8SBrandon Wyman         // TODO: D-Bus mocking to verify values stored on D-Bus (???)
10241d7a7df8SBrandon Wyman     }
10251d7a7df8SBrandon Wyman     catch (...)
10261d7a7df8SBrandon Wyman     {
10271d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
10281d7a7df8SBrandon Wyman     }
10293f1242f3SBrandon Wyman }
10303f1242f3SBrandon Wyman 
10313f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsPresent)
10323f1242f3SBrandon Wyman {
10333f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1034681b2a36SB. J. Wyman 
10359464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
10369464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
10373ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
10383ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
10393f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), false);
10403f1242f3SBrandon Wyman 
1041681b2a36SB. J. Wyman     // Change GPIO read to return 1 to indicate present.
1042681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
1043391a0690SBrandon Wyman     // Call to analyze() will update to present, that will trigger updating
1044391a0690SBrandon Wyman     // to the correct/latest HWMON directory, in case it changes.
1045391a0690SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1046391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1047ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1048ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1049ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1050ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1051592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
1052391a0690SBrandon Wyman     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1053391a0690SBrandon Wyman     // Default expectations will be on, no faults.
1054391a0690SBrandon Wyman     PMBusExpectations expectations;
1055391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
105682affd94SBrandon Wyman     // Give it an input voltage in the 100-volt range.
105782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
105882affd94SBrandon Wyman         .Times(1)
105982affd94SBrandon Wyman         .WillOnce(Return("123456"));
10600975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1061681b2a36SB. J. Wyman     psu.analyze();
1062681b2a36SB. J. Wyman     EXPECT_EQ(psu.isPresent(), true);
10633f1242f3SBrandon Wyman }
10643f1242f3SBrandon Wyman 
10653f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsFaulted)
10663f1242f3SBrandon Wyman {
10673f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1068681b2a36SB. J. Wyman 
10699464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 11,       0x6f,
10709464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
10713ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
10723ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1073681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1074681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1075391a0690SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1076391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1077ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1078ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1079ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1080ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1081592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
1082391a0690SBrandon Wyman     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1083391a0690SBrandon Wyman     // Default expectations will be on, no faults.
1084391a0690SBrandon Wyman     PMBusExpectations expectations;
1085391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
108682affd94SBrandon Wyman     // Give it an input voltage in the 100-volt range.
108782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
108882affd94SBrandon Wyman         .Times(1)
108982affd94SBrandon Wyman         .WillOnce(Return("124680"));
1090681b2a36SB. J. Wyman     psu.analyze();
10913f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
1092f07bc797SBrandon Wyman     // STATUS_WORD with fault bits on.
1093b654c619SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
1094f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
1095b654c619SBrandon Wyman     expectations.statusInputValue = 0xFF;
1096f07bc797SBrandon Wyman     // STATUS_MFR_SPECIFIC with faults bits on.
1097b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
109885c7bf41SBrandon Wyman     // STATUS_CML with faults bits on.
1099b654c619SBrandon Wyman     expectations.statusCMLValue = 0xFF;
11006710ba2cSBrandon Wyman     // STATUS_VOUT with fault bits on.
1101b654c619SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
1102b10b3be0SBrandon Wyman     // STATUS_IOUT with fault bits on.
1103b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
11047ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
11057ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0xFF;
110696893a46SBrandon Wyman     // STATUS_TEMPERATURE with fault bits on.
110796893a46SBrandon Wyman     expectations.statusTempValue = 0xFF;
1108c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1109c2906f47SBrandon Wyman     {
1110b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
11114fc191f0SBrandon Wyman         // Also get another read of READ_VIN, faulted, so not in 100-volt range
111282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
111382affd94SBrandon Wyman             .Times(1)
11144fc191f0SBrandon Wyman             .WillOnce(Return("19000"));
11150975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
11160975eaf4SMatt Spinler         {
11170975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
11180975eaf4SMatt Spinler         }
11193f1242f3SBrandon Wyman         psu.analyze();
1120c2906f47SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
1121c2906f47SBrandon Wyman     }
11223f1242f3SBrandon Wyman }
11233f1242f3SBrandon Wyman 
11243f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasInputFault)
11253f1242f3SBrandon Wyman {
11263f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1127681b2a36SB. J. Wyman 
11289464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
11299464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
11303ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
11313ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1132681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1133681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
11343f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1135391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1136ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1137ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1138ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1139ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1140592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
11418da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1142b654c619SBrandon Wyman     PMBusExpectations expectations;
1143b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
114482affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
114582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
114682affd94SBrandon Wyman         .Times(1)
114782affd94SBrandon Wyman         .WillOnce(Return("201100"));
11483f1242f3SBrandon Wyman     psu.analyze();
11493f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
1150f07bc797SBrandon Wyman     // STATUS_WORD with input fault/warn on.
1151b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
1152f07bc797SBrandon Wyman     // STATUS_INPUT with an input fault bit on.
1153b654c619SBrandon Wyman     expectations.statusInputValue = 0x80;
1154c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1155c2906f47SBrandon Wyman     {
1156b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
115782affd94SBrandon Wyman         // Analyze call will also need good READ_VIN value to check.
115882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
115982affd94SBrandon Wyman             .Times(1)
116082affd94SBrandon Wyman             .WillOnce(Return("201200"));
11610975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
11620975eaf4SMatt Spinler         {
11630975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
11640975eaf4SMatt Spinler         }
11653f1242f3SBrandon Wyman         psu.analyze();
1166c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
1167c2906f47SBrandon Wyman     }
1168f07bc797SBrandon Wyman     // STATUS_WORD with no bits on.
1169b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1170b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
117182affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
117282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
117382affd94SBrandon Wyman         .Times(1)
117482affd94SBrandon Wyman         .WillOnce(Return("201300"));
11750975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
11763f1242f3SBrandon Wyman     psu.analyze();
11773f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
11783f1242f3SBrandon Wyman }
11793f1242f3SBrandon Wyman 
11803f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasMFRFault)
11813f1242f3SBrandon Wyman {
11823f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1183681b2a36SB. J. Wyman 
11849464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
11859464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
11863ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
11873ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1188681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1189681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
11903f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1191391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1192ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1193ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1194ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1195ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1196592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
1197f07bc797SBrandon Wyman     // First return STATUS_WORD with no bits on.
11988da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1199b654c619SBrandon Wyman     PMBusExpectations expectations;
1200b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
120182affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
120282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
120382affd94SBrandon Wyman         .Times(1)
120482affd94SBrandon Wyman         .WillOnce(Return("202100"));
12053f1242f3SBrandon Wyman     psu.analyze();
12063f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
1207f07bc797SBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
1208b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1209f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
1210b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
1211c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1212c2906f47SBrandon Wyman     {
1213b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
121482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
121582affd94SBrandon Wyman             .Times(1)
121682affd94SBrandon Wyman             .WillOnce(Return("202200"));
12173f1242f3SBrandon Wyman         psu.analyze();
1218c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1219c2906f47SBrandon Wyman     }
1220f07bc797SBrandon Wyman     // Back to no bits on in STATUS_WORD
1221b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1222b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
122382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
122482affd94SBrandon Wyman         .Times(1)
122582affd94SBrandon Wyman         .WillOnce(Return("202300"));
12263f1242f3SBrandon Wyman     psu.analyze();
12273f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
12283f1242f3SBrandon Wyman }
12293f1242f3SBrandon Wyman 
12303f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasVINUVFault)
12313f1242f3SBrandon Wyman {
12323f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1233681b2a36SB. J. Wyman 
12349464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
12359464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
12363ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
12373ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1238681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1239681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
12403f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1241391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1242ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1243ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1244ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1245ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1246592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
124782affd94SBrandon Wyman 
124882affd94SBrandon Wyman     // Presence change from missing to present will trigger in1_input read in
124982affd94SBrandon Wyman     // an attempt to get CLEAR_FAULTS called. Return value ignored.
125082affd94SBrandon Wyman     // Zero to non-zero voltage, for missing/present change, triggers clear
125182affd94SBrandon Wyman     // faults call again. Return value ignored.
125282affd94SBrandon Wyman     // Fault (low voltage) to not faulted (voltage in range) triggers clear
125382affd94SBrandon Wyman     // faults call a third time.
125482affd94SBrandon Wyman 
12558da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1256b654c619SBrandon Wyman     PMBusExpectations expectations;
1257b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
125882affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
125982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
126082affd94SBrandon Wyman         .Times(1)
126182affd94SBrandon Wyman         .WillOnce(Return("201100"));
12623f1242f3SBrandon Wyman     psu.analyze();
12633f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
1264f07bc797SBrandon Wyman     // Turn fault on.
1265b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::VIN_UV_FAULT);
126685c7bf41SBrandon Wyman     // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
126785c7bf41SBrandon Wyman     // Figure 16, and assume bits on in STATUS_INPUT.
1268b654c619SBrandon Wyman     expectations.statusInputValue = 0x18;
1269c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1270c2906f47SBrandon Wyman     {
1271b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
127282affd94SBrandon Wyman         // If there is a VIN_UV fault, fake reading voltage of less than 20V
127382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
127482affd94SBrandon Wyman             .Times(1)
127582affd94SBrandon Wyman             .WillOnce(Return("19876"));
12760975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
12770975eaf4SMatt Spinler         {
12780975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
12790975eaf4SMatt Spinler         }
12803f1242f3SBrandon Wyman         psu.analyze();
1281c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1282c2906f47SBrandon Wyman     }
1283f07bc797SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1284b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1285b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
128682affd94SBrandon Wyman     // Updates now result in clearing faults if read voltage goes from below the
128782affd94SBrandon Wyman     // minimum, to within a valid range.
128882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
128982affd94SBrandon Wyman         .Times(1)
129082affd94SBrandon Wyman         .WillOnce(Return("201300"));
12913225a45cSBrandon Wyman     // Went from below minimum to within range, expect clearVinUVFault().
12923225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
12933225a45cSBrandon Wyman         .Times(1)
12943225a45cSBrandon Wyman         .WillOnce(Return(1));
12950975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
12963f1242f3SBrandon Wyman     psu.analyze();
12973f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
12983f1242f3SBrandon Wyman }
12996710ba2cSBrandon Wyman 
13006710ba2cSBrandon Wyman TEST_F(PowerSupplyTests, HasVoutOVFault)
13016710ba2cSBrandon Wyman {
13026710ba2cSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
13036710ba2cSBrandon Wyman 
13049464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x69,
13059464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
13066710ba2cSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
13076710ba2cSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
13086710ba2cSBrandon Wyman     // Always return 1 to indicate present.
13096710ba2cSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
13106710ba2cSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1311391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1312ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1313ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1314ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1315ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1316592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
13176710ba2cSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1318b654c619SBrandon Wyman     PMBusExpectations expectations;
1319b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
132082affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
132182affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
132282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
132382affd94SBrandon Wyman         .Times(1)
132482affd94SBrandon Wyman         .WillOnce(Return("202100"));
13256710ba2cSBrandon Wyman     psu.analyze();
13266710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
13276710ba2cSBrandon Wyman     // Turn fault on.
1328b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
13296710ba2cSBrandon Wyman     // STATUS_VOUT fault bit(s)
1330b654c619SBrandon Wyman     expectations.statusVOUTValue = 0x80;
1331c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1332c2906f47SBrandon Wyman     {
1333b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
133482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
133582affd94SBrandon Wyman             .Times(1)
133682affd94SBrandon Wyman             .WillOnce(Return("202200"));
13376710ba2cSBrandon Wyman         psu.analyze();
1338c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1339c2906f47SBrandon Wyman     }
13406710ba2cSBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1341b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1342b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
134382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
134482affd94SBrandon Wyman         .Times(1)
134582affd94SBrandon Wyman         .WillOnce(Return("202300"));
13466710ba2cSBrandon Wyman     psu.analyze();
13476710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
13486710ba2cSBrandon Wyman }
134996893a46SBrandon Wyman 
1350b10b3be0SBrandon Wyman TEST_F(PowerSupplyTests, HasIoutOCFault)
1351b10b3be0SBrandon Wyman {
1352b10b3be0SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1353b10b3be0SBrandon Wyman 
13549464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6d,
13559464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1356b10b3be0SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
1357b10b3be0SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1358b10b3be0SBrandon Wyman     // Always return 1 to indicate present.
1359b10b3be0SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1360b10b3be0SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1361391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1362ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1363ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1364ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1365ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1366592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
1367b10b3be0SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1368b10b3be0SBrandon Wyman     PMBusExpectations expectations;
1369b10b3be0SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
137082affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
137182affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
137282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
137382affd94SBrandon Wyman         .Times(1)
137482affd94SBrandon Wyman         .WillOnce(Return("203100"));
1375b10b3be0SBrandon Wyman     psu.analyze();
1376b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
1377b10b3be0SBrandon Wyman     // Turn fault on.
1378b10b3be0SBrandon Wyman     expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1379b10b3be0SBrandon Wyman     // STATUS_IOUT fault bit(s)
1380b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0x88;
1381c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1382c2906f47SBrandon Wyman     {
1383b10b3be0SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
138482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
138582affd94SBrandon Wyman             .Times(1)
138682affd94SBrandon Wyman             .WillOnce(Return("203200"));
13870975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
13880975eaf4SMatt Spinler         {
13890975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
13900975eaf4SMatt Spinler         }
1391b10b3be0SBrandon Wyman         psu.analyze();
1392c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1393c2906f47SBrandon Wyman     }
1394b10b3be0SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1395b10b3be0SBrandon Wyman     expectations.statusWordValue = 0;
1396b10b3be0SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
139782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
139882affd94SBrandon Wyman         .Times(1)
139982affd94SBrandon Wyman         .WillOnce(Return("203300"));
14000975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1401b10b3be0SBrandon Wyman     psu.analyze();
1402b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
1403b10b3be0SBrandon Wyman }
1404b10b3be0SBrandon Wyman 
14052cf46945SBrandon Wyman TEST_F(PowerSupplyTests, HasVoutUVFault)
14062cf46945SBrandon Wyman {
14072cf46945SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
14082cf46945SBrandon Wyman 
14099464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6a,
14109464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
14112cf46945SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
14122cf46945SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
14132cf46945SBrandon Wyman     // Always return 1 to indicate present.
14142cf46945SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
14152cf46945SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1416391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1417ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1418ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1419ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1420ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1421592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
1422391a0690SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
14232cf46945SBrandon Wyman     PMBusExpectations expectations;
14242cf46945SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
142582affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
142682affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
142782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
142882affd94SBrandon Wyman         .Times(1)
142982affd94SBrandon Wyman         .WillOnce(Return("204100"));
14302cf46945SBrandon Wyman     psu.analyze();
14312cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
14322cf46945SBrandon Wyman     // Turn fault on.
14332cf46945SBrandon Wyman     expectations.statusWordValue = (status_word::VOUT_FAULT);
14342cf46945SBrandon Wyman     // STATUS_VOUT fault bit(s)
14352cf46945SBrandon Wyman     expectations.statusVOUTValue = 0x30;
1436c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1437c2906f47SBrandon Wyman     {
14382cf46945SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
143982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
144082affd94SBrandon Wyman             .Times(1)
144182affd94SBrandon Wyman             .WillOnce(Return("204200"));
14422cf46945SBrandon Wyman         psu.analyze();
1443c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1444c2906f47SBrandon Wyman     }
14452cf46945SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
14462cf46945SBrandon Wyman     expectations.statusWordValue = 0;
14472cf46945SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
144882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
144982affd94SBrandon Wyman         .Times(1)
145082affd94SBrandon Wyman         .WillOnce(Return("204300"));
14512cf46945SBrandon Wyman     psu.analyze();
14522cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
14532cf46945SBrandon Wyman }
14542cf46945SBrandon Wyman 
14557ee4d7e4SBrandon Wyman TEST_F(PowerSupplyTests, HasFanFault)
14567ee4d7e4SBrandon Wyman {
14577ee4d7e4SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
14587ee4d7e4SBrandon Wyman 
14590975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
14600975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
14610975eaf4SMatt Spinler 
14629464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6d,
14639464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
14647ee4d7e4SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
14657ee4d7e4SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
14667ee4d7e4SBrandon Wyman     // Always return 1 to indicate present.
14677ee4d7e4SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
14687ee4d7e4SBrandon 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, _))
1474592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
14757ee4d7e4SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
14767ee4d7e4SBrandon Wyman     PMBusExpectations expectations;
14777ee4d7e4SBrandon 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("205100"));
14837ee4d7e4SBrandon Wyman     psu.analyze();
14847ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
14857ee4d7e4SBrandon Wyman     // Turn fault on.
14867ee4d7e4SBrandon Wyman     expectations.statusWordValue = (status_word::FAN_FAULT);
14877ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
14887ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0x80;
1489c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1490c2906f47SBrandon Wyman     {
14917ee4d7e4SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
149282affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
149382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
149482affd94SBrandon Wyman             .Times(1)
149582affd94SBrandon Wyman             .WillOnce(Return("205200"));
14967ee4d7e4SBrandon Wyman         psu.analyze();
1497c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1498c2906f47SBrandon Wyman     }
14997ee4d7e4SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
15007ee4d7e4SBrandon Wyman     expectations.statusWordValue = 0;
15017ee4d7e4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
150282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
150382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
150482affd94SBrandon Wyman         .Times(1)
150582affd94SBrandon Wyman         .WillOnce(Return("205300"));
15067ee4d7e4SBrandon Wyman     psu.analyze();
15077ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
15087ee4d7e4SBrandon Wyman }
15097ee4d7e4SBrandon Wyman 
151096893a46SBrandon Wyman TEST_F(PowerSupplyTests, HasTempFault)
151196893a46SBrandon Wyman {
151296893a46SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
151396893a46SBrandon Wyman 
15140975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
15150975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
15160975eaf4SMatt Spinler 
15179464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6a,
15189464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
151996893a46SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
152096893a46SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
152196893a46SBrandon Wyman     // Always return 1 to indicate present.
152296893a46SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
152396893a46SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1524391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1525ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1526ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1527ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1528ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1529592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
153096893a46SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
153196893a46SBrandon Wyman     PMBusExpectations expectations;
153296893a46SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
153382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
153482affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
153582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
153682affd94SBrandon Wyman         .Times(1)
153782affd94SBrandon Wyman         .WillOnce(Return("206100"));
153896893a46SBrandon Wyman     psu.analyze();
153996893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
154096893a46SBrandon Wyman     // Turn fault on.
154196893a46SBrandon Wyman     expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
154296893a46SBrandon Wyman     // STATUS_TEMPERATURE fault bit on (OT Fault)
154396893a46SBrandon Wyman     expectations.statusTempValue = 0x80;
1544c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1545c2906f47SBrandon Wyman     {
154696893a46SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
154782affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
154882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
154982affd94SBrandon Wyman             .Times(1)
155082affd94SBrandon Wyman             .WillOnce(Return("206200"));
155196893a46SBrandon Wyman         psu.analyze();
1552c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1553c2906f47SBrandon Wyman     }
155496893a46SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
155596893a46SBrandon Wyman     expectations.statusWordValue = 0;
155696893a46SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
155782affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
155882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
155982affd94SBrandon Wyman         .Times(1)
156082affd94SBrandon Wyman         .WillOnce(Return("206300"));
156196893a46SBrandon Wyman     psu.analyze();
156296893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
156396893a46SBrandon Wyman }
15642916ea52SBrandon Wyman 
15652916ea52SBrandon Wyman TEST_F(PowerSupplyTests, HasPgoodFault)
15662916ea52SBrandon Wyman {
15672916ea52SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
15682916ea52SBrandon Wyman 
15699464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6b,
15709464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
15712916ea52SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
15722916ea52SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
15732916ea52SBrandon Wyman     // Always return 1 to indicate present.
15742916ea52SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
15752916ea52SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1576391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1577ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1578ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1579ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1580ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1581592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
15822916ea52SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
15832916ea52SBrandon Wyman     PMBusExpectations expectations;
15842916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
158582affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
158682affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
158782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
158882affd94SBrandon Wyman         .Times(1)
158982affd94SBrandon Wyman         .WillOnce(Return("207100"));
15902916ea52SBrandon Wyman     psu.analyze();
15912916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
1592391a0690SBrandon Wyman     // Setup another expectation of no faults.
1593391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
159482affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
159582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
159682affd94SBrandon Wyman         .Times(1)
159782affd94SBrandon Wyman         .WillOnce(Return("207200"));
159882affd94SBrandon Wyman     psu.analyze();
159982affd94SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
160082affd94SBrandon Wyman     // Setup another expectation of no faults.
160182affd94SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
160282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
160382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
160482affd94SBrandon Wyman         .Times(1)
160582affd94SBrandon Wyman         .WillOnce(Return("207300"));
1606391a0690SBrandon Wyman     psu.analyze();
1607391a0690SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
16082916ea52SBrandon Wyman     // Turn PGOOD# off (fault on).
16092916ea52SBrandon Wyman     expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
16102916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
161182affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
161282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
161382affd94SBrandon Wyman         .Times(1)
161482affd94SBrandon Wyman         .WillOnce(Return("207400"));
16152916ea52SBrandon Wyman     psu.analyze();
16166d469fd4SBrandon Wyman     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 1
161706ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
161806ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
161982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
162082affd94SBrandon Wyman         .Times(1)
162182affd94SBrandon Wyman         .WillOnce(Return("207500"));
162206ca4590SBrandon Wyman     psu.analyze();
16236d469fd4SBrandon Wyman     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 2
162406ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
162506ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
162682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
162782affd94SBrandon Wyman         .Times(1)
162882affd94SBrandon Wyman         .WillOnce(Return("207600"));
162906ca4590SBrandon Wyman     psu.analyze();
16306d469fd4SBrandon Wyman     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 3
16316d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
16326d469fd4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
16336d469fd4SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
16346d469fd4SBrandon Wyman         .Times(1)
16356d469fd4SBrandon Wyman         .WillOnce(Return("207700"));
16366d469fd4SBrandon Wyman     psu.analyze();
16376d469fd4SBrandon Wyman     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 4
16386d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
16396d469fd4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
16406d469fd4SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
16416d469fd4SBrandon Wyman         .Times(1)
16426d469fd4SBrandon Wyman         .WillOnce(Return("207800"));
16436d469fd4SBrandon Wyman     psu.analyze();
16446d469fd4SBrandon Wyman     // Expect true. PGOOD_DEGLITCH_LIMIT @ 5
16452916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
16462916ea52SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
16472916ea52SBrandon Wyman     expectations.statusWordValue = 0;
16482916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
164982affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
165082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
165182affd94SBrandon Wyman         .Times(1)
165282affd94SBrandon Wyman         .WillOnce(Return("207700"));
16532916ea52SBrandon Wyman     psu.analyze();
16542916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
165582affd94SBrandon Wyman 
16562916ea52SBrandon Wyman     // Turn OFF bit on
16572916ea52SBrandon Wyman     expectations.statusWordValue = (status_word::UNIT_IS_OFF);
16582916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
165982affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
166082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
166182affd94SBrandon Wyman         .Times(1)
166282affd94SBrandon Wyman         .WillOnce(Return("208100"));
16632916ea52SBrandon Wyman     psu.analyze();
166406ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
166506ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
166682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
166782affd94SBrandon Wyman         .Times(1)
166882affd94SBrandon Wyman         .WillOnce(Return("208200"));
166906ca4590SBrandon Wyman     psu.analyze();
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("208300"));
167506ca4590SBrandon Wyman     psu.analyze();
16766d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
16776d469fd4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
16786d469fd4SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
16796d469fd4SBrandon Wyman         .Times(1)
16806d469fd4SBrandon Wyman         .WillOnce(Return("208400"));
16816d469fd4SBrandon Wyman     psu.analyze();
16826d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
16836d469fd4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
16846d469fd4SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
16856d469fd4SBrandon Wyman         .Times(1)
16866d469fd4SBrandon Wyman         .WillOnce(Return("208500"));
16876d469fd4SBrandon Wyman     psu.analyze();
16882916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
16892916ea52SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
16902916ea52SBrandon Wyman     expectations.statusWordValue = 0;
16912916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
169282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
169382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
169482affd94SBrandon Wyman         .Times(1)
16956d469fd4SBrandon Wyman         .WillOnce(Return("208000"));
16962916ea52SBrandon Wyman     psu.analyze();
16972916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
16982916ea52SBrandon Wyman }
169939ea02bcSBrandon Wyman 
170039ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPSKillFault)
170139ea02bcSBrandon Wyman {
170239ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
17039464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 4,        0x6d,
17049464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
170539ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
170639ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
170739ea02bcSBrandon Wyman     // Always return 1 to indicate present.
170839ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
170939ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
171082affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1711ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1712ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1713ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1714ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1715592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
171639ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
171739ea02bcSBrandon Wyman     PMBusExpectations expectations;
171839ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
171982affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
172082affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
172182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
172282affd94SBrandon Wyman         .Times(1)
172382affd94SBrandon Wyman         .WillOnce(Return("208100"));
172439ea02bcSBrandon Wyman     psu.analyze();
172539ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
172639ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
172739ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
172839ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
172939ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1730c2906f47SBrandon Wyman 
1731c2906f47SBrandon Wyman     // Deglitching faults, false until read the fault bits on up to the limit.
1732c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1733c2906f47SBrandon Wyman     {
173439ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
173582affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
173682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
173782affd94SBrandon Wyman             .Times(1)
173882affd94SBrandon Wyman             .WillOnce(Return("208200"));
17390975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
17400975eaf4SMatt Spinler         {
17410975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
17420975eaf4SMatt Spinler         }
174339ea02bcSBrandon Wyman         psu.analyze();
1744c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1745c2906f47SBrandon Wyman     }
1746c2906f47SBrandon Wyman 
174739ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
174839ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
174939ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
175082affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
175182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
175282affd94SBrandon Wyman         .Times(1)
175382affd94SBrandon Wyman         .WillOnce(Return("208300"));
17540975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
175539ea02bcSBrandon Wyman     psu.analyze();
175639ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
175739ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
175839ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
175939ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 4 on.
176039ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x10;
1761c2906f47SBrandon Wyman 
1762c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1763c2906f47SBrandon Wyman     {
176439ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
176582affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
176682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
176782affd94SBrandon Wyman             .Times(1)
176882affd94SBrandon Wyman             .WillOnce(Return("208400"));
17690975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
17700975eaf4SMatt Spinler         {
17710975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
17720975eaf4SMatt Spinler         }
177339ea02bcSBrandon Wyman         psu.analyze();
1774c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1775c2906f47SBrandon Wyman     }
1776c2906f47SBrandon Wyman 
177739ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
177839ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
177939ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
178082affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
178182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
178282affd94SBrandon Wyman         .Times(1)
178382affd94SBrandon Wyman         .WillOnce(Return("208500"));
17840975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
178539ea02bcSBrandon Wyman     psu.analyze();
178639ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
178739ea02bcSBrandon Wyman }
178839ea02bcSBrandon Wyman 
178939ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPS12VcsFault)
179039ea02bcSBrandon Wyman {
179139ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
17929464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 5,        0x6e,
17939464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
179439ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
179539ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
179639ea02bcSBrandon Wyman     // Always return 1 to indicate present.
179739ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
179839ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
179982affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1800ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1801ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1802ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1803ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1804592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
180539ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
180639ea02bcSBrandon Wyman     PMBusExpectations expectations;
180739ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
180882affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
180982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
181082affd94SBrandon Wyman         .Times(1)
181182affd94SBrandon Wyman         .WillOnce(Return("209100"));
181239ea02bcSBrandon Wyman     psu.analyze();
181339ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
181439ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
181539ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
181639ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
181739ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1818c2906f47SBrandon Wyman 
1819c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1820c2906f47SBrandon Wyman     {
182139ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
182282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
182382affd94SBrandon Wyman             .Times(1)
182482affd94SBrandon Wyman             .WillOnce(Return("209200"));
182539ea02bcSBrandon Wyman         psu.analyze();
1826c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1827c2906f47SBrandon Wyman     }
1828c2906f47SBrandon Wyman 
182939ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
183039ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
183139ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
183282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
183382affd94SBrandon Wyman         .Times(1)
183482affd94SBrandon Wyman         .WillOnce(Return("209300"));
183539ea02bcSBrandon Wyman     psu.analyze();
183639ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
183739ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
183839ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
183939ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 6 on.
184039ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x40;
1841c2906f47SBrandon Wyman 
1842c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1843c2906f47SBrandon Wyman     {
184439ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
184582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
184682affd94SBrandon Wyman             .Times(1)
184782affd94SBrandon Wyman             .WillOnce(Return("209400"));
184839ea02bcSBrandon Wyman         psu.analyze();
1849c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1850c2906f47SBrandon Wyman     }
1851c2906f47SBrandon Wyman 
185239ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
185339ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
185439ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
185582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
185682affd94SBrandon Wyman         .Times(1)
185782affd94SBrandon Wyman         .WillOnce(Return("209500"));
185839ea02bcSBrandon Wyman     psu.analyze();
185939ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
186039ea02bcSBrandon Wyman }
186139ea02bcSBrandon Wyman 
186239ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPSCS12VFault)
186339ea02bcSBrandon Wyman {
186439ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
18659464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 6,        0x6f,
18669464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
186739ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
186839ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
186939ea02bcSBrandon Wyman     // Always return 1 to indicate present.
187039ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
187139ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
187282affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1873ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1874ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1875ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1876ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1877592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
187839ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
187939ea02bcSBrandon Wyman     PMBusExpectations expectations;
188039ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
188182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
188282affd94SBrandon Wyman         .Times(1)
188382affd94SBrandon Wyman         .WillOnce(Return("209100"));
188439ea02bcSBrandon Wyman     psu.analyze();
188539ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
188639ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
188739ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
188839ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
188939ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1890c2906f47SBrandon Wyman 
1891c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1892c2906f47SBrandon Wyman     {
189339ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
189482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
189582affd94SBrandon Wyman             .Times(1)
189682affd94SBrandon Wyman             .WillOnce(Return("209200"));
189739ea02bcSBrandon Wyman         psu.analyze();
1898c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1899c2906f47SBrandon Wyman     }
1900c2906f47SBrandon Wyman 
190139ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
190239ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
190339ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
190482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
190582affd94SBrandon Wyman         .Times(1)
190682affd94SBrandon Wyman         .WillOnce(Return("209300"));
190739ea02bcSBrandon Wyman     psu.analyze();
190839ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
190939ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
191039ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
191139ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 7 on.
191239ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x80;
1913c2906f47SBrandon Wyman 
1914c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1915c2906f47SBrandon Wyman     {
191639ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
191782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
191882affd94SBrandon Wyman             .Times(1)
191982affd94SBrandon Wyman             .WillOnce(Return("209400"));
192039ea02bcSBrandon Wyman         psu.analyze();
1921c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1922c2906f47SBrandon Wyman     }
1923c2906f47SBrandon Wyman 
192439ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
192539ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
192639ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
192782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
192882affd94SBrandon Wyman         .Times(1)
192982affd94SBrandon Wyman         .WillOnce(Return("209500"));
193039ea02bcSBrandon Wyman     psu.analyze();
193139ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
193239ea02bcSBrandon Wyman }
1933c3324424SBrandon Wyman 
1934592bd27cSMatt Spinler TEST_F(PowerSupplyTests, PeakInputPowerSensor)
1935c3324424SBrandon Wyman {
1936c3324424SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1937c3324424SBrandon Wyman     {
19389464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 6,        0x6f,
19399464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1940592bd27cSMatt Spinler         EXPECT_EQ(psu.getPeakInputPower(), std::nullopt);
1941592bd27cSMatt Spinler 
1942c3324424SBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
1943c3324424SBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1944ae35ac5dSBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1945c3324424SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1946592bd27cSMatt Spinler 
1947ae35ac5dSBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
1948ae35ac5dSBrandon Wyman         PMBusExpectations expectations;
1949ae35ac5dSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
1950592bd27cSMatt Spinler 
1951ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1952ae35ac5dSBrandon Wyman             .Times(1)
1953ae35ac5dSBrandon Wyman             .WillOnce(Return("206000"));
1954ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1955ae35ac5dSBrandon Wyman             .WillRepeatedly(Return("2000"));
1956592bd27cSMatt Spinler 
1957c3324424SBrandon Wyman         psu.analyze();
1958592bd27cSMatt Spinler         EXPECT_EQ(psu.getPeakInputPower().value_or(0), 213);
1959c3324424SBrandon Wyman     }
1960592bd27cSMatt Spinler 
1961592bd27cSMatt Spinler     // Test that there is no peak power sensor on 1400W PSs
1962c3324424SBrandon Wyman     {
19639464c429SGeorge Liu         PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
19649464c429SGeorge Liu                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1965ae35ac5dSBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
1966ae35ac5dSBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1967ae35ac5dSBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1968592bd27cSMatt Spinler 
1969ae35ac5dSBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1970592bd27cSMatt Spinler 
1971ae35ac5dSBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
1972592bd27cSMatt Spinler 
1973ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1974ae35ac5dSBrandon Wyman             .WillRepeatedly(Return("30725"));
1975592bd27cSMatt Spinler 
1976ae35ac5dSBrandon Wyman         PMBusExpectations expectations;
1977ae35ac5dSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
1978592bd27cSMatt Spinler 
1979ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1980592bd27cSMatt Spinler             .WillRepeatedly(Return("206000"));
1981ae35ac5dSBrandon Wyman         psu.analyze();
1982592bd27cSMatt Spinler 
1983592bd27cSMatt Spinler         EXPECT_EQ(psu.getPeakInputPower(), std::nullopt);
1984ae35ac5dSBrandon Wyman     }
1985592bd27cSMatt Spinler 
1986592bd27cSMatt Spinler     // Test that IPSPS power supplies don't have peak power
1987ae35ac5dSBrandon Wyman     {
1988c3324424SBrandon Wyman         PowerSupply psu{bus,      PSUInventoryPath, 11,
19899464c429SGeorge Liu                         0x58,     "inspur-ipsps",   PSUGPIOLineName,
19909464c429SGeorge Liu                         isPowerOn};
1991592bd27cSMatt Spinler 
1992c3324424SBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
1993c3324424SBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1994592bd27cSMatt Spinler 
1995ae35ac5dSBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1996592bd27cSMatt Spinler 
1997c3324424SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1998592bd27cSMatt Spinler 
1999ae35ac5dSBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
2000ae35ac5dSBrandon Wyman         PMBusExpectations expectations;
2001ae35ac5dSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
2002592bd27cSMatt Spinler 
2003592bd27cSMatt Spinler         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2004592bd27cSMatt Spinler             .WillRepeatedly(Return("206000"));
2005592bd27cSMatt Spinler 
2006592bd27cSMatt Spinler         psu.analyze();
2007592bd27cSMatt Spinler 
2008592bd27cSMatt Spinler         EXPECT_EQ(psu.getPeakInputPower(), std::nullopt);
2009592bd27cSMatt Spinler     }
2010592bd27cSMatt Spinler 
2011592bd27cSMatt Spinler     // Test that a bad response from the input_history command leads
2012592bd27cSMatt Spinler     // to an NaN value.
2013592bd27cSMatt Spinler     {
2014592bd27cSMatt Spinler         PowerSupply psu{bus,         PSUInventoryPath, 6,        0x6f,
2015592bd27cSMatt Spinler                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
2016592bd27cSMatt Spinler 
2017592bd27cSMatt Spinler         MockedGPIOInterface* mockPresenceGPIO =
2018592bd27cSMatt Spinler             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2019592bd27cSMatt Spinler         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2020592bd27cSMatt Spinler 
2021592bd27cSMatt Spinler         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2022592bd27cSMatt Spinler 
2023592bd27cSMatt Spinler         setMissingToPresentExpects(mockPMBus, mockedUtil);
2024592bd27cSMatt Spinler         PMBusExpectations expectations;
2025592bd27cSMatt Spinler         setPMBusExpectations(mockPMBus, expectations);
2026592bd27cSMatt Spinler 
2027ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2028ae35ac5dSBrandon Wyman             .Times(1)
2029ae35ac5dSBrandon Wyman             .WillOnce(Return("206000"));
2030ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2031592bd27cSMatt Spinler             .WillRepeatedly(Return("2000"));
2032592bd27cSMatt Spinler 
2033592bd27cSMatt Spinler         // Don't return the full 5 bytes.
2034592bd27cSMatt Spinler         EXPECT_CALL(mockPMBus,
2035592bd27cSMatt Spinler                     readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug, 5))
2036592bd27cSMatt Spinler             .WillRepeatedly(Return(std::vector<uint8_t>{0x01, 0x5c}));
2037592bd27cSMatt Spinler 
2038c3324424SBrandon Wyman         psu.analyze();
2039592bd27cSMatt Spinler         EXPECT_THAT(psu.getPeakInputPower().value_or(0), IsNan());
2040592bd27cSMatt Spinler     }
2041c3324424SBrandon Wyman }
204218a24d92SBrandon Wyman 
204318a24d92SBrandon Wyman TEST_F(PowerSupplyTests, IsSyncHistoryRequired)
204418a24d92SBrandon Wyman {
204518a24d92SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
20469464c429SGeorge Liu     PowerSupply psu{bus,         PSUInventoryPath, 8,        0x6f,
20479464c429SGeorge Liu                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
204818a24d92SBrandon Wyman     EXPECT_EQ(psu.isSyncHistoryRequired(), false);
204918a24d92SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
205018a24d92SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
205118a24d92SBrandon Wyman     // Always return 1 to indicate present.
205218a24d92SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
205318a24d92SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
205418a24d92SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
2055ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2056ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
2057ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
2058ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2059592bd27cSMatt Spinler         .WillRepeatedly(Return("2000"));
206018a24d92SBrandon Wyman     PMBusExpectations expectations;
206118a24d92SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
206218a24d92SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
206318a24d92SBrandon Wyman         .Times(1)
206418a24d92SBrandon Wyman         .WillRepeatedly(Return("205000"));
206518a24d92SBrandon Wyman     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
206618a24d92SBrandon Wyman     psu.analyze();
206718a24d92SBrandon Wyman     // Missing -> Present requires history sync
206818a24d92SBrandon Wyman     EXPECT_EQ(psu.isSyncHistoryRequired(), true);
206918a24d92SBrandon Wyman     psu.clearSyncHistoryRequired();
207018a24d92SBrandon Wyman     EXPECT_EQ(psu.isSyncHistoryRequired(), false);
207118a24d92SBrandon Wyman }
2072592bd27cSMatt Spinler 
2073592bd27cSMatt Spinler TEST_F(PowerSupplyTests, TestLinearConversions)
2074592bd27cSMatt Spinler {
2075592bd27cSMatt Spinler     // Mantissa > 0, exponent = 0
2076592bd27cSMatt Spinler     EXPECT_EQ(0, PowerSupply::linearToInteger(0));
2077592bd27cSMatt Spinler     EXPECT_EQ(1, PowerSupply::linearToInteger(1));
2078592bd27cSMatt Spinler     EXPECT_EQ(38, PowerSupply::linearToInteger(0x26));
2079592bd27cSMatt Spinler     EXPECT_EQ(1023, PowerSupply::linearToInteger(0x3FF));
2080592bd27cSMatt Spinler 
2081592bd27cSMatt Spinler     // Mantissa < 0, exponent = 0
2082592bd27cSMatt Spinler     EXPECT_EQ(-1, PowerSupply::linearToInteger(0x7FF));
2083592bd27cSMatt Spinler     EXPECT_EQ(-20, PowerSupply::linearToInteger(0x7EC));
2084592bd27cSMatt Spinler     EXPECT_EQ(-769, PowerSupply::linearToInteger(0x4FF));
2085592bd27cSMatt Spinler     EXPECT_EQ(-989, PowerSupply::linearToInteger(0x423));
2086592bd27cSMatt Spinler     EXPECT_EQ(-1024, PowerSupply::linearToInteger(0x400));
2087592bd27cSMatt Spinler 
2088592bd27cSMatt Spinler     // Mantissa >= 0, exponent > 0
2089592bd27cSMatt Spinler     // M = 1, E = 2
2090592bd27cSMatt Spinler     EXPECT_EQ(4, PowerSupply::linearToInteger(0x1001));
2091592bd27cSMatt Spinler 
2092592bd27cSMatt Spinler     // M = 1000, E = 10
2093592bd27cSMatt Spinler     EXPECT_EQ(1024000, PowerSupply::linearToInteger(0x53E8));
2094592bd27cSMatt Spinler 
2095592bd27cSMatt Spinler     // M = 10, E = 15
2096592bd27cSMatt Spinler     EXPECT_EQ(327680, PowerSupply::linearToInteger(0x780A));
2097592bd27cSMatt Spinler 
2098592bd27cSMatt Spinler     // Mantissa >= 0, exponent < 0
2099592bd27cSMatt Spinler     // M = 0, E = -1
2100592bd27cSMatt Spinler     EXPECT_EQ(0, PowerSupply::linearToInteger(0xF800));
2101592bd27cSMatt Spinler 
2102592bd27cSMatt Spinler     // M = 100, E = -2
2103592bd27cSMatt Spinler     EXPECT_EQ(25, PowerSupply::linearToInteger(0xF064));
2104592bd27cSMatt Spinler 
2105592bd27cSMatt Spinler     // Mantissa < 0, exponent < 0
2106592bd27cSMatt Spinler     // M = -100, E = -1
2107592bd27cSMatt Spinler     EXPECT_EQ(-50, PowerSupply::linearToInteger(0xFF9C));
2108592bd27cSMatt Spinler 
2109592bd27cSMatt Spinler     // M = -1024, E = -7
2110592bd27cSMatt Spinler     EXPECT_EQ(-8, PowerSupply::linearToInteger(0xCC00));
2111592bd27cSMatt Spinler }
2112