13f1242f3SBrandon Wyman #include "../power_supply.hpp"
2c3324424SBrandon Wyman #include "../record_manager.hpp"
33f1242f3SBrandon Wyman #include "mock.hpp"
43f1242f3SBrandon Wyman 
53f1242f3SBrandon Wyman #include <xyz/openbmc_project/Common/Device/error.hpp>
63f1242f3SBrandon Wyman #include <xyz/openbmc_project/Common/error.hpp>
73f1242f3SBrandon Wyman 
83f1242f3SBrandon Wyman #include <gmock/gmock.h>
93f1242f3SBrandon Wyman #include <gtest/gtest.h>
103f1242f3SBrandon Wyman 
113f1242f3SBrandon Wyman using namespace phosphor::power::psu;
123f1242f3SBrandon Wyman using namespace phosphor::pmbus;
133f1242f3SBrandon Wyman 
143f1242f3SBrandon Wyman using ::testing::_;
1559a35793SBrandon Wyman using ::testing::Args;
163f1242f3SBrandon Wyman using ::testing::Assign;
173f1242f3SBrandon Wyman using ::testing::DoAll;
1859a35793SBrandon Wyman using ::testing::ElementsAre;
1959a35793SBrandon Wyman using ::testing::NotNull;
203f1242f3SBrandon Wyman using ::testing::Return;
213f1242f3SBrandon Wyman using ::testing::StrEq;
223f1242f3SBrandon Wyman 
233f1242f3SBrandon Wyman static auto PSUInventoryPath = "/xyz/bmc/inv/sys/chassis/board/powersupply0";
24681b2a36SB. J. Wyman static auto PSUGPIOLineName = "presence-ps0";
253f1242f3SBrandon Wyman 
26b654c619SBrandon Wyman struct PMBusExpectations
27b654c619SBrandon Wyman {
28b654c619SBrandon Wyman     uint16_t statusWordValue{0x0000};
29b654c619SBrandon Wyman     uint8_t statusInputValue{0x00};
30b654c619SBrandon Wyman     uint8_t statusMFRValue{0x00};
31b654c619SBrandon Wyman     uint8_t statusCMLValue{0x00};
32b654c619SBrandon Wyman     uint8_t statusVOUTValue{0x00};
33b10b3be0SBrandon Wyman     uint8_t statusIOUTValue{0x00};
347ee4d7e4SBrandon Wyman     uint8_t statusFans12Value{0x00};
3596893a46SBrandon Wyman     uint8_t statusTempValue{0x00};
36b654c619SBrandon Wyman };
37b654c619SBrandon Wyman 
388da35c51SBrandon Wyman // Helper function to setup expectations for various STATUS_* commands
39b654c619SBrandon Wyman void setPMBusExpectations(MockedPMBus& mockPMBus,
40b654c619SBrandon Wyman                           const PMBusExpectations& expectations)
418da35c51SBrandon Wyman {
4232453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _, _))
438da35c51SBrandon Wyman         .Times(1)
44b654c619SBrandon Wyman         .WillOnce(Return(expectations.statusWordValue));
458da35c51SBrandon Wyman 
46b654c619SBrandon Wyman     if (expectations.statusWordValue != 0)
478da35c51SBrandon Wyman     {
488da35c51SBrandon Wyman         // If fault bits are on in STATUS_WORD, there will also be a read of
4996893a46SBrandon Wyman         // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and
5096893a46SBrandon Wyman         // STATUS_TEMPERATURE.
5132453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _, _))
528da35c51SBrandon Wyman             .Times(1)
53b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusInputValue));
5432453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_MFR, _, _))
558da35c51SBrandon Wyman             .Times(1)
56b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusMFRValue));
5732453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_CML, _, _))
588da35c51SBrandon Wyman             .Times(1)
59b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusCMLValue));
606710ba2cSBrandon Wyman         // Page will need to be set to 0 to read STATUS_VOUT.
616710ba2cSBrandon Wyman         EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0))
626710ba2cSBrandon Wyman             .Times(1)
636710ba2cSBrandon Wyman             .WillOnce(Return("status0_vout"));
6432453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read("status0_vout", _, _))
656710ba2cSBrandon Wyman             .Times(1)
66b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusVOUTValue));
6732453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _, _))
68b10b3be0SBrandon Wyman             .Times(1)
69b10b3be0SBrandon Wyman             .WillOnce(Return(expectations.statusIOUTValue));
7032453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _, _))
717ee4d7e4SBrandon Wyman             .Times(1)
727ee4d7e4SBrandon Wyman             .WillOnce(Return(expectations.statusFans12Value));
7332453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _, _))
7496893a46SBrandon Wyman             .Times(1)
7596893a46SBrandon Wyman             .WillOnce(Return(expectations.statusTempValue));
768da35c51SBrandon Wyman     }
778da35c51SBrandon Wyman }
788da35c51SBrandon Wyman 
793f1242f3SBrandon Wyman class PowerSupplyTests : public ::testing::Test
803f1242f3SBrandon Wyman {
813f1242f3SBrandon Wyman   public:
823f1242f3SBrandon Wyman     PowerSupplyTests() :
833f1242f3SBrandon Wyman         mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
843f1242f3SBrandon Wyman     {
853f1242f3SBrandon Wyman         ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
863f1242f3SBrandon Wyman     }
873f1242f3SBrandon Wyman 
883f1242f3SBrandon Wyman     ~PowerSupplyTests() override
893f1242f3SBrandon Wyman     {
903f1242f3SBrandon Wyman         freeUtils();
913f1242f3SBrandon Wyman     }
923f1242f3SBrandon Wyman 
933f1242f3SBrandon Wyman     const MockedUtil& mockedUtil;
943f1242f3SBrandon Wyman };
953f1242f3SBrandon Wyman 
96391a0690SBrandon Wyman // Helper function for when a power supply goes from missing to present.
97391a0690SBrandon Wyman void setMissingToPresentExpects(MockedPMBus& pmbus, const MockedUtil& util)
98391a0690SBrandon Wyman {
99391a0690SBrandon Wyman     // Call to analyze() will update to present, that will trigger updating
100391a0690SBrandon Wyman     // to the correct/latest HWMON directory, in case it changes.
101391a0690SBrandon Wyman     EXPECT_CALL(pmbus, findHwmonDir());
102391a0690SBrandon Wyman     // Presence change from missing to present will trigger write to
103391a0690SBrandon Wyman     // ON_OFF_CONFIG.
104391a0690SBrandon Wyman     EXPECT_CALL(pmbus, writeBinary(ON_OFF_CONFIG, _, _));
105391a0690SBrandon Wyman     // Presence change from missing to present will trigger in1_input read
106391a0690SBrandon Wyman     // in an attempt to get CLEAR_FAULTS called.
10782affd94SBrandon Wyman     // This READ_VIN for CLEAR_FAULTS does not check the returned value.
1083225a45cSBrandon Wyman     EXPECT_CALL(pmbus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
1093225a45cSBrandon Wyman     // The call for clearing faults includes clearing VIN_UV fault.
1103225a45cSBrandon Wyman     // The voltage defaults to 0, the first call to analyze should update the
1113225a45cSBrandon Wyman     // voltage to the current reading, triggering clearing VIN_UV fault(s)
1123225a45cSBrandon Wyman     // due to below minimum to within range voltage.
1133225a45cSBrandon Wyman     EXPECT_CALL(pmbus, read("in1_lcrit_alarm", _, _))
11482affd94SBrandon Wyman         .Times(2)
1153225a45cSBrandon Wyman         .WillRepeatedly(Return(1));
116391a0690SBrandon Wyman     // Missing/present call will update Presence in inventory.
117391a0690SBrandon Wyman     EXPECT_CALL(util, setPresence(_, _, true, _));
118391a0690SBrandon Wyman }
119391a0690SBrandon Wyman 
1203f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Constructor)
1213f1242f3SBrandon Wyman {
1223f1242f3SBrandon Wyman     /**
1233f1242f3SBrandon Wyman      * @param[in] invpath - String for inventory path to use
1243f1242f3SBrandon Wyman      * @param[in] i2cbus - The bus number this power supply is on
1253f1242f3SBrandon Wyman      * @param[in] i2caddr - The 16-bit I2C address of the power supply
126681b2a36SB. J. Wyman      * @param[in] gpioLineName - The string for the gpio-line-name to read for
127681b2a36SB. J. Wyman      * presence.
128681b2a36SB. J. Wyman      * @param[in] bindDelay - Time in milliseconds to delay binding the device
129681b2a36SB. J. Wyman      * driver after seeing the presence line go active.
1303f1242f3SBrandon Wyman      */
1313f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1321d7a7df8SBrandon Wyman 
1331d7a7df8SBrandon Wyman     // Try where inventory path is empty, constructor should fail.
1341d7a7df8SBrandon Wyman     try
1351d7a7df8SBrandon Wyman     {
136c3324424SBrandon Wyman         auto psu = std::make_unique<PowerSupply>(bus, "", 3, 0x68, "ibm-cffps",
137c3324424SBrandon Wyman                                                  PSUGPIOLineName);
1381d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have reached this line.";
1391d7a7df8SBrandon Wyman     }
1401d7a7df8SBrandon Wyman     catch (const std::invalid_argument& e)
1411d7a7df8SBrandon Wyman     {
1421d7a7df8SBrandon Wyman         EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
1431d7a7df8SBrandon Wyman     }
1441d7a7df8SBrandon Wyman     catch (...)
1451d7a7df8SBrandon Wyman     {
1461d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
1471d7a7df8SBrandon Wyman     }
1481d7a7df8SBrandon Wyman 
149681b2a36SB. J. Wyman     // TODO: Try invalid i2c address?
150681b2a36SB. J. Wyman 
151681b2a36SB. J. Wyman     // Try where gpioLineName is empty.
1521d7a7df8SBrandon Wyman     try
1531d7a7df8SBrandon Wyman     {
154c3324424SBrandon Wyman         auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
155c3324424SBrandon Wyman                                                  "ibm-cffps", "");
156681b2a36SB. J. Wyman         ADD_FAILURE()
157681b2a36SB. J. Wyman             << "Should not have reached this line. Invalid gpioLineName.";
158681b2a36SB. J. Wyman     }
159681b2a36SB. J. Wyman     catch (const std::invalid_argument& e)
160681b2a36SB. J. Wyman     {
161681b2a36SB. J. Wyman         EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
162681b2a36SB. J. Wyman     }
163681b2a36SB. J. Wyman     catch (...)
164681b2a36SB. J. Wyman     {
165681b2a36SB. J. Wyman         ADD_FAILURE() << "Should not have caught exception.";
166681b2a36SB. J. Wyman     }
167681b2a36SB. J. Wyman 
168681b2a36SB. J. Wyman     // Test with valid arguments
169681b2a36SB. J. Wyman     // NOT using D-Bus inventory path for presence.
170681b2a36SB. J. Wyman     try
171681b2a36SB. J. Wyman     {
172681b2a36SB. J. Wyman         auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
173c3324424SBrandon Wyman                                                  "ibm-cffps", PSUGPIOLineName);
1743f1242f3SBrandon Wyman 
1753f1242f3SBrandon Wyman         EXPECT_EQ(psu->isPresent(), false);
1763f1242f3SBrandon Wyman         EXPECT_EQ(psu->isFaulted(), false);
1778da35c51SBrandon Wyman         EXPECT_EQ(psu->hasCommFault(), false);
1783f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasInputFault(), false);
1793f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasMFRFault(), false);
1803f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasVINUVFault(), false);
1816710ba2cSBrandon Wyman         EXPECT_EQ(psu->hasVoutOVFault(), false);
182b10b3be0SBrandon Wyman         EXPECT_EQ(psu->hasIoutOCFault(), false);
1832cf46945SBrandon Wyman         EXPECT_EQ(psu->hasVoutUVFault(), false);
1847ee4d7e4SBrandon Wyman         EXPECT_EQ(psu->hasFanFault(), false);
18596893a46SBrandon Wyman         EXPECT_EQ(psu->hasTempFault(), false);
1862916ea52SBrandon Wyman         EXPECT_EQ(psu->hasPgoodFault(), false);
18739ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPSKillFault(), false);
18839ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPS12VcsFault(), false);
18939ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPSCS12VFault(), false);
1903f1242f3SBrandon Wyman     }
1911d7a7df8SBrandon Wyman     catch (...)
1921d7a7df8SBrandon Wyman     {
1931d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
1941d7a7df8SBrandon Wyman     }
195681b2a36SB. J. Wyman 
196681b2a36SB. J. Wyman     // Test with valid arguments
197681b2a36SB. J. Wyman     // TODO: Using D-Bus inventory path for presence.
198681b2a36SB. J. Wyman     try
199681b2a36SB. J. Wyman     {
200681b2a36SB. J. Wyman         // FIXME: How do I get that presenceGPIO.read() in the startup to throw
201681b2a36SB. J. Wyman         // an exception?
202681b2a36SB. J. Wyman 
203681b2a36SB. J. Wyman         // EXPECT_CALL(mockedUtil, getPresence(_,
204681b2a36SB. J. Wyman         // StrEq(PSUInventoryPath)))
205681b2a36SB. J. Wyman         //    .Times(1);
206681b2a36SB. J. Wyman     }
207681b2a36SB. J. Wyman     catch (...)
208681b2a36SB. J. Wyman     {
209681b2a36SB. J. Wyman         ADD_FAILURE() << "Should not have caught exception.";
210681b2a36SB. J. Wyman     }
2111d7a7df8SBrandon Wyman }
2123f1242f3SBrandon Wyman 
2133f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Analyze)
2143f1242f3SBrandon Wyman {
2153f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
2163f1242f3SBrandon Wyman 
217b654c619SBrandon Wyman     {
218681b2a36SB. J. Wyman         // If I default to reading the GPIO, I will NOT expect a call to
219681b2a36SB. J. Wyman         // getPresence().
220681b2a36SB. J. Wyman 
221c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 4,
222c3324424SBrandon Wyman                         0x69, "ibm-cffps",      PSUGPIOLineName};
2233ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
2243ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
225681b2a36SB. J. Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
226681b2a36SB. J. Wyman 
2273f1242f3SBrandon Wyman         psu.analyze();
2283f1242f3SBrandon Wyman         // By default, nothing should change.
2293f1242f3SBrandon Wyman         EXPECT_EQ(psu.isPresent(), false);
2303f1242f3SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), false);
2313f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), false);
2323f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), false);
2333f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), false);
23485c7bf41SBrandon Wyman         EXPECT_EQ(psu.hasCommFault(), false);
2356710ba2cSBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), false);
236b10b3be0SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), false);
2372cf46945SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), false);
2387ee4d7e4SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), false);
23996893a46SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), false);
2402916ea52SBrandon Wyman         EXPECT_EQ(psu.hasPgoodFault(), false);
24139ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), false);
24239ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), false);
24339ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), false);
244b654c619SBrandon Wyman     }
2453f1242f3SBrandon Wyman 
246c3324424SBrandon Wyman     PowerSupply psu2{bus,  PSUInventoryPath, 5,
247c3324424SBrandon Wyman                      0x6a, "ibm-cffps",      PSUGPIOLineName};
248681b2a36SB. J. Wyman     // In order to get the various faults tested, the power supply needs to
249681b2a36SB. J. Wyman     // be present in order to read from the PMBus device(s).
2503ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO2 =
2513ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
25206ca4590SBrandon Wyman     // Always return 1 to indicate present.
25306ca4590SBrandon Wyman     // Each analyze() call will trigger a read of the presence GPIO.
25406ca4590SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1));
255681b2a36SB. J. Wyman     EXPECT_EQ(psu2.isPresent(), false);
2563f1242f3SBrandon Wyman 
2573f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
258391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
259*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
260*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
261*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
262*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
263*ae35ac5dSBrandon Wyman         .Times(1)
264*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
265b654c619SBrandon Wyman 
266b654c619SBrandon Wyman     // STATUS_WORD INPUT fault.
267b654c619SBrandon Wyman     {
268b654c619SBrandon Wyman         // Start with STATUS_WORD 0x0000. Powered on, no faults.
269b654c619SBrandon Wyman         // Set expectations for a no fault
270b654c619SBrandon Wyman         PMBusExpectations expectations;
271b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
27282affd94SBrandon Wyman         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
27382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
27482affd94SBrandon Wyman             .Times(1)
27582affd94SBrandon Wyman             .WillOnce(Return("206000"));
2763f1242f3SBrandon Wyman         psu2.analyze();
2773f1242f3SBrandon Wyman         EXPECT_EQ(psu2.isPresent(), true);
2783f1242f3SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
2793f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
2803f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasMFRFault(), false);
2813f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasVINUVFault(), false);
28285c7bf41SBrandon Wyman         EXPECT_EQ(psu2.hasCommFault(), false);
2836710ba2cSBrandon Wyman         EXPECT_EQ(psu2.hasVoutOVFault(), false);
284b10b3be0SBrandon Wyman         EXPECT_EQ(psu2.hasIoutOCFault(), false);
2852cf46945SBrandon Wyman         EXPECT_EQ(psu2.hasVoutUVFault(), false);
2867ee4d7e4SBrandon Wyman         EXPECT_EQ(psu2.hasFanFault(), false);
28796893a46SBrandon Wyman         EXPECT_EQ(psu2.hasTempFault(), false);
2882916ea52SBrandon Wyman         EXPECT_EQ(psu2.hasPgoodFault(), false);
28939ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPSKillFault(), false);
29039ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPS12VcsFault(), false);
29139ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPSCS12VFault(), false);
2923f1242f3SBrandon Wyman 
293b654c619SBrandon Wyman         // Update expectations for STATUS_WORD input fault/warn
29496893a46SBrandon Wyman         // STATUS_INPUT fault bits ... on.
295b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
2963225a45cSBrandon Wyman         // IIN_OC fault.
2973225a45cSBrandon Wyman         expectations.statusInputValue = 0x04;
298c2906f47SBrandon Wyman 
299c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
300c2906f47SBrandon Wyman         {
301b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
30282affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
30382affd94SBrandon Wyman                 .Times(1)
30482affd94SBrandon Wyman                 .WillOnce(Return("207000"));
3053f1242f3SBrandon Wyman             psu2.analyze();
3063f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
307c2906f47SBrandon Wyman             // Should not be faulted until it reaches the deglitch limit.
308c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
309c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
3103f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
3113f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
31285c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
3136710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
314b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
3152cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
3167ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
31796893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
3182916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
31939ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
32039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
32139ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
322b654c619SBrandon Wyman         }
323c2906f47SBrandon Wyman     }
324c2906f47SBrandon Wyman 
32532453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
3263225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
3273225a45cSBrandon Wyman         .Times(1)
3283225a45cSBrandon Wyman         .WillOnce(Return(1));
329c2906f47SBrandon Wyman     psu2.clearFaults();
3303f1242f3SBrandon Wyman 
3313f1242f3SBrandon Wyman     // STATUS_WORD INPUT/UV fault.
332b654c619SBrandon Wyman     {
3333f1242f3SBrandon Wyman         // First need it to return good status, then the fault
334b654c619SBrandon Wyman         PMBusExpectations expectations;
335b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
33682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
33782affd94SBrandon Wyman             .Times(1)
33882affd94SBrandon Wyman             .WillOnce(Return("208000"));
3393f1242f3SBrandon Wyman         psu2.analyze();
340c2906f47SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
341c2906f47SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
3428da35c51SBrandon Wyman         // Now set fault bits in STATUS_WORD
343b654c619SBrandon Wyman         expectations.statusWordValue =
3448da35c51SBrandon Wyman             (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
3458da35c51SBrandon Wyman         // STATUS_INPUT fault bits ... on.
3463225a45cSBrandon Wyman         expectations.statusInputValue = 0x18;
347c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
348c2906f47SBrandon Wyman         {
349b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
35082affd94SBrandon Wyman             // Input/UV fault, so voltage should read back low.
35182affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
35282affd94SBrandon Wyman                 .Times(1)
35382affd94SBrandon Wyman                 .WillOnce(Return("19123"));
3543f1242f3SBrandon Wyman             psu2.analyze();
3553f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
356c2906f47SBrandon Wyman             // Only faulted if hit deglitch limit
357c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
358c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
359c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), x >= DEGLITCH_LIMIT);
3603f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
36185c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
3626710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
363b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
3642cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
3657ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
36696893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
3672916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
36839ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
36939ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
37039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
371c2906f47SBrandon Wyman         }
37282affd94SBrandon Wyman         // Turning VIN_UV fault off causes clearing of faults, causing read of
37382affd94SBrandon Wyman         // in1_input as an attempt to get CLEAR_FAULTS called.
37482affd94SBrandon Wyman         expectations.statusWordValue = 0;
37582affd94SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
37682affd94SBrandon Wyman         // The call to read the voltage
37782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
37882affd94SBrandon Wyman             .Times(1)
37982affd94SBrandon Wyman             .WillOnce(Return("209000"));
3803225a45cSBrandon Wyman         // The call to clear VIN_UV/Off fault(s)
3813225a45cSBrandon Wyman         EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
38232453e9bSBrandon Wyman             .Times(1)
3833225a45cSBrandon Wyman             .WillOnce(Return(1));
38482affd94SBrandon Wyman         psu2.analyze();
38582affd94SBrandon Wyman         // Should remain present, no longer be faulted, no input fault, no
38682affd94SBrandon Wyman         // VIN_UV fault. Nothing else should change.
38782affd94SBrandon Wyman         EXPECT_EQ(psu2.isPresent(), true);
38882affd94SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
38982affd94SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
39082affd94SBrandon Wyman         EXPECT_EQ(psu2.hasVINUVFault(), false);
391b654c619SBrandon Wyman     }
3923f1242f3SBrandon Wyman 
39332453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
3943225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
3953225a45cSBrandon Wyman         .Times(1)
3963225a45cSBrandon Wyman         .WillOnce(Return(1));
397c2906f47SBrandon Wyman     psu2.clearFaults();
398c2906f47SBrandon Wyman 
3993f1242f3SBrandon Wyman     // STATUS_WORD MFR fault.
400b654c619SBrandon Wyman     {
401f07bc797SBrandon Wyman         // First need it to return good status, then the fault
402b654c619SBrandon Wyman         PMBusExpectations expectations;
403b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
40482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
40582affd94SBrandon Wyman             .Times(1)
40682affd94SBrandon Wyman             .WillOnce(Return("210000"));
4073f1242f3SBrandon Wyman         psu2.analyze();
4088da35c51SBrandon Wyman         // Now STATUS_WORD with MFR fault bit on.
409b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
4108da35c51SBrandon Wyman         // STATUS_MFR bits on.
411b654c619SBrandon Wyman         expectations.statusMFRValue = 0xFF;
412c2906f47SBrandon Wyman 
413c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
414c2906f47SBrandon Wyman         {
415b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
41682affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
41782affd94SBrandon Wyman                 .Times(1)
41882affd94SBrandon Wyman                 .WillOnce(Return("211000"));
4193f1242f3SBrandon Wyman             psu2.analyze();
4203f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
421c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
4223f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
423c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT);
424c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT);
425c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
426c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
4273f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
42885c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
4296710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
430b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
4312cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
4327ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
43396893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
4342916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
435c2906f47SBrandon Wyman         }
436b654c619SBrandon Wyman     }
4373f1242f3SBrandon Wyman 
43832453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
4393225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
4403225a45cSBrandon Wyman         .Times(1)
4413225a45cSBrandon Wyman         .WillOnce(Return(1));
442c2906f47SBrandon Wyman     psu2.clearFaults();
4433225a45cSBrandon Wyman 
44496893a46SBrandon Wyman     // Temperature fault.
445b654c619SBrandon Wyman     {
446f07bc797SBrandon Wyman         // First STATUS_WORD with no bits set, then with temperature fault.
447b654c619SBrandon Wyman         PMBusExpectations expectations;
448b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
44982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
45082affd94SBrandon Wyman             .Times(1)
45182affd94SBrandon Wyman             .WillOnce(Return("212000"));
4523f1242f3SBrandon Wyman         psu2.analyze();
4538da35c51SBrandon Wyman         // STATUS_WORD with temperature fault bit on.
454b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
45596893a46SBrandon Wyman         // STATUS_TEMPERATURE with fault bit(s) on.
45696893a46SBrandon Wyman         expectations.statusTempValue = 0x10;
457c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
458c2906f47SBrandon Wyman         {
459b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
46082affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
46182affd94SBrandon Wyman                 .Times(1)
46282affd94SBrandon Wyman                 .WillOnce(Return("213000"));
4633f1242f3SBrandon Wyman             psu2.analyze();
4643f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
465c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
4663f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
4673f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
4683f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
46985c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
4706710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
471b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
4722cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
4737ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
474c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT);
4752916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
47639ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
47739ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
47839ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
479b654c619SBrandon Wyman         }
480c2906f47SBrandon Wyman     }
48185c7bf41SBrandon Wyman 
48232453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
4833225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
4843225a45cSBrandon Wyman         .Times(1)
4853225a45cSBrandon Wyman         .WillOnce(Return(1));
486c2906f47SBrandon Wyman     psu2.clearFaults();
4873225a45cSBrandon Wyman 
48885c7bf41SBrandon Wyman     // CML fault
489b654c619SBrandon Wyman     {
49085c7bf41SBrandon Wyman         // First STATUS_WORD wit no bits set, then with CML 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("214000"));
49685c7bf41SBrandon Wyman         psu2.analyze();
4978da35c51SBrandon Wyman         // STATUS_WORD with CML fault bit on.
498b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::CML_FAULT);
49985c7bf41SBrandon Wyman         // Turn on STATUS_CML fault bit(s)
500b654c619SBrandon Wyman         expectations.statusCMLValue = 0xFF;
501c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
502c2906f47SBrandon Wyman         {
503b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
50482affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
50582affd94SBrandon Wyman                 .Times(1)
50682affd94SBrandon Wyman                 .WillOnce(Return("215000"));
50785c7bf41SBrandon Wyman             psu2.analyze();
50885c7bf41SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
509c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
510c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), x >= DEGLITCH_LIMIT);
51185c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
51285c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
51385c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
5146710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
515b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
5162cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
5177ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
51896893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
5192916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
52039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
52139ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
52239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
523b654c619SBrandon Wyman         }
524c2906f47SBrandon Wyman     }
5256710ba2cSBrandon Wyman 
52632453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
5273225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
5283225a45cSBrandon Wyman         .Times(1)
5293225a45cSBrandon Wyman         .WillOnce(Return(1));
530c2906f47SBrandon Wyman     psu2.clearFaults();
5313225a45cSBrandon Wyman 
5326710ba2cSBrandon Wyman     // VOUT_OV_FAULT fault
533b654c619SBrandon Wyman     {
5346710ba2cSBrandon Wyman         // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
535b654c619SBrandon Wyman         PMBusExpectations expectations;
536b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
53782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
53882affd94SBrandon Wyman             .Times(1)
53982affd94SBrandon Wyman             .WillOnce(Return("216000"));
5406710ba2cSBrandon Wyman         psu2.analyze();
5416710ba2cSBrandon Wyman         // STATUS_WORD with VOUT/VOUT_OV fault.
542b654c619SBrandon Wyman         expectations.statusWordValue =
5436710ba2cSBrandon Wyman             ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
5446710ba2cSBrandon Wyman         // Turn on STATUS_VOUT fault bit(s)
545b654c619SBrandon Wyman         expectations.statusVOUTValue = 0xA0;
546c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
547c2906f47SBrandon Wyman         {
54896893a46SBrandon Wyman             // STATUS_TEMPERATURE don't care (default)
549b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
55082affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
55182affd94SBrandon Wyman                 .Times(1)
55282affd94SBrandon Wyman                 .WillOnce(Return("217000"));
5536710ba2cSBrandon Wyman             psu2.analyze();
5546710ba2cSBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
555c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
5566710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
5576710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
5586710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
5596710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
560c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
5612cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
562b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
5637ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
564b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
565b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
56639ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
56739ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
56839ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
569b10b3be0SBrandon Wyman         }
570c2906f47SBrandon Wyman     }
571b10b3be0SBrandon Wyman 
572b10b3be0SBrandon Wyman     // IOUT_OC_FAULT fault
573b10b3be0SBrandon Wyman     {
574b10b3be0SBrandon Wyman         // First STATUS_WORD with no bits set, then with IOUT_OC fault.
575b10b3be0SBrandon Wyman         PMBusExpectations expectations;
576b10b3be0SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
57782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
57882affd94SBrandon Wyman             .Times(1)
57982affd94SBrandon Wyman             .WillOnce(Return("218000"));
580b10b3be0SBrandon Wyman         psu2.analyze();
581b10b3be0SBrandon Wyman         // STATUS_WORD with IOUT_OC fault.
582b10b3be0SBrandon Wyman         expectations.statusWordValue = status_word::IOUT_OC_FAULT;
583b10b3be0SBrandon Wyman         // Turn on STATUS_IOUT fault bit(s)
584b10b3be0SBrandon Wyman         expectations.statusIOUTValue = 0x88;
585c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
586c2906f47SBrandon Wyman         {
587b10b3be0SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
58882affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
58982affd94SBrandon Wyman                 .Times(1)
59082affd94SBrandon Wyman                 .WillOnce(Return("219000"));
591b10b3be0SBrandon Wyman             psu2.analyze();
592b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
593c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
594b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
595b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
596b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
597b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
598b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
599c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
6002cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
6017ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
6022cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6032cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
60439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
60539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
60639ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
6072cf46945SBrandon Wyman         }
608c2906f47SBrandon Wyman     }
6092cf46945SBrandon Wyman 
6102cf46945SBrandon Wyman     // VOUT_UV_FAULT
6112cf46945SBrandon Wyman     {
6122cf46945SBrandon Wyman         // First STATUS_WORD with no bits set, then with VOUT fault.
6132cf46945SBrandon Wyman         PMBusExpectations expectations;
6142cf46945SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
61582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
61682affd94SBrandon Wyman             .Times(1)
61782affd94SBrandon Wyman             .WillOnce(Return("220000"));
6182cf46945SBrandon Wyman         psu2.analyze();
6192cf46945SBrandon Wyman         // Change STATUS_WORD to indicate VOUT fault.
6202cf46945SBrandon Wyman         expectations.statusWordValue = (status_word::VOUT_FAULT);
6212cf46945SBrandon Wyman         // Turn on STATUS_VOUT fault bit(s)
6222cf46945SBrandon Wyman         expectations.statusVOUTValue = 0x30;
623c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
624c2906f47SBrandon Wyman         {
6252cf46945SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
62682affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
62782affd94SBrandon Wyman                 .Times(1)
62882affd94SBrandon Wyman                 .WillOnce(Return("221000"));
6292cf46945SBrandon Wyman             psu2.analyze();
6302cf46945SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
631c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
6322cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
6332cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
6342cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
6352cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
6362cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
6372cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
638c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
6397ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
64096893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6412916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
64239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
64339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
64439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
645b654c619SBrandon Wyman         }
646c2906f47SBrandon Wyman     }
6473f1242f3SBrandon Wyman 
6487ee4d7e4SBrandon Wyman     // Fan fault
649b654c619SBrandon Wyman     {
650b654c619SBrandon Wyman         // First STATUS_WORD with no bits set, then with fan fault.
651b654c619SBrandon Wyman         PMBusExpectations expectations;
652b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
65382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
65482affd94SBrandon Wyman             .Times(1)
65582affd94SBrandon Wyman             .WillOnce(Return("222000"));
6563f1242f3SBrandon Wyman         psu2.analyze();
657b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::FAN_FAULT);
6587ee4d7e4SBrandon Wyman         // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
6597ee4d7e4SBrandon Wyman         expectations.statusFans12Value = 0xA0;
660c2906f47SBrandon Wyman 
661c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
662c2906f47SBrandon Wyman         {
663b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
66482affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
66582affd94SBrandon Wyman                 .Times(1)
66682affd94SBrandon Wyman                 .WillOnce(Return("223000"));
6673f1242f3SBrandon Wyman             psu2.analyze();
6683f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
669c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
670c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT);
6713f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
6723f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
6733f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
67485c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
6756710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
676b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
6772cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
67896893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6792916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
68039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
68139ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
68239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
683b654c619SBrandon Wyman         }
684c2906f47SBrandon Wyman     }
6852916ea52SBrandon Wyman 
68606ca4590SBrandon Wyman     // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
6872cf46945SBrandon Wyman     {
6882916ea52SBrandon Wyman         // First STATUS_WORD with no bits set.
6892916ea52SBrandon Wyman         PMBusExpectations expectations;
6902916ea52SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
69182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
69282affd94SBrandon Wyman             .Times(1)
69382affd94SBrandon Wyman             .WillOnce(Return("123000"));
6942916ea52SBrandon Wyman         psu2.analyze();
6952916ea52SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
6962916ea52SBrandon Wyman         // POWER_GOOD# inactive, and OFF bit on.
6972916ea52SBrandon Wyman         expectations.statusWordValue =
6982916ea52SBrandon Wyman             ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
69906ca4590SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
70006ca4590SBrandon Wyman         {
7012916ea52SBrandon Wyman             // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
7022916ea52SBrandon Wyman             // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
7032916ea52SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
70482affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
70582affd94SBrandon Wyman                 .Times(1)
70682affd94SBrandon Wyman                 .WillOnce(Return("124000"));
7072916ea52SBrandon Wyman             psu2.analyze();
7082916ea52SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
709c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
7102916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
7112916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
7122916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
7132916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
7142916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
7152cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
716b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
7177ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
7182916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
71932453e9bSBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), x >= DEGLITCH_LIMIT);
72006ca4590SBrandon Wyman         }
72106ca4590SBrandon Wyman     }
7222916ea52SBrandon Wyman 
7233f1242f3SBrandon Wyman     // TODO: ReadFailure
7243f1242f3SBrandon Wyman }
7253f1242f3SBrandon Wyman 
72659a35793SBrandon Wyman TEST_F(PowerSupplyTests, OnOffConfig)
72759a35793SBrandon Wyman {
72859a35793SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
72959a35793SBrandon Wyman     uint8_t data = 0x15;
73059a35793SBrandon Wyman 
73159a35793SBrandon Wyman     // Test where PSU is NOT present
73259a35793SBrandon Wyman     try
73359a35793SBrandon Wyman     {
734681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
7350975eaf4SMatt Spinler         EXPECT_CALL(mockedUtil, setAvailable(_, _, _)).Times(0);
736c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 4,
737c3324424SBrandon Wyman                         0x69, "ibm-cffps",      PSUGPIOLineName};
738681b2a36SB. J. Wyman 
7393ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
7403ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
741681b2a36SB. J. Wyman         ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
74259a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
743681b2a36SB. J. Wyman         // Constructor should set initial presence, default read returns 0.
74459a35793SBrandon Wyman         // If it is not present, I should not be trying to write to it.
74559a35793SBrandon Wyman         EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
74659a35793SBrandon Wyman         psu.onOffConfig(data);
74759a35793SBrandon Wyman     }
74859a35793SBrandon Wyman     catch (...)
7490c9a33d6SAdriana Kobylak     {}
75059a35793SBrandon Wyman 
75159a35793SBrandon Wyman     // Test where PSU is present
75259a35793SBrandon Wyman     try
75359a35793SBrandon Wyman     {
754681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
7550975eaf4SMatt Spinler         EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
756c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 5,
757c3324424SBrandon Wyman                         0x6a, "ibm-cffps",      PSUGPIOLineName};
7583ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
7593ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
760391a0690SBrandon Wyman         // There will potentially be multiple calls, we want it to continue
761391a0690SBrandon Wyman         // returning 1 for the GPIO read to keep the power supply present.
762391a0690SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
76359a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
764391a0690SBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
765*ae35ac5dSBrandon Wyman         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
766*ae35ac5dSBrandon Wyman         // for INPUT_HISTORY will check max_power_out to see if it is
767*ae35ac5dSBrandon Wyman         // old/unsupported power supply. Indicate good value, supported.
768*ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
769*ae35ac5dSBrandon Wyman             .Times(1)
770*ae35ac5dSBrandon Wyman             .WillOnce(Return("2000"));
771391a0690SBrandon Wyman         // If I am calling analyze(), I should probably give it good data.
772391a0690SBrandon Wyman         // STATUS_WORD 0x0000 is powered on, no faults.
773391a0690SBrandon Wyman         PMBusExpectations expectations;
774391a0690SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
77582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
77682affd94SBrandon Wyman             .Times(1)
77782affd94SBrandon Wyman             .WillOnce(Return("205000"));
778681b2a36SB. J. Wyman         psu.analyze();
779391a0690SBrandon Wyman         // I definitely should be writting ON_OFF_CONFIG if I call the function
780391a0690SBrandon Wyman         EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
781391a0690SBrandon Wyman                                            Type::HwmonDeviceDebug))
78259a35793SBrandon Wyman             .Times(1);
78359a35793SBrandon Wyman         psu.onOffConfig(data);
78459a35793SBrandon Wyman     }
78559a35793SBrandon Wyman     catch (...)
7860c9a33d6SAdriana Kobylak     {}
78759a35793SBrandon Wyman }
78859a35793SBrandon Wyman 
7893f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, ClearFaults)
7903f1242f3SBrandon Wyman {
7913f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
792c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 13,
793c3324424SBrandon Wyman                     0x68, "ibm-cffps",      PSUGPIOLineName};
7943ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
7953ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
79606ca4590SBrandon Wyman     // Always return 1 to indicate present.
79706ca4590SBrandon Wyman     // Each analyze() call will trigger a read of the presence GPIO.
79806ca4590SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
799681b2a36SB. J. Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
800391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
801*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
802*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
803*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
804*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
805*ae35ac5dSBrandon Wyman         .Times(1)
806*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
8078da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
808b654c619SBrandon Wyman     PMBusExpectations expectations;
809b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
81082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
81182affd94SBrandon Wyman         .Times(1)
81282affd94SBrandon Wyman         .WillOnce(Return("207000"));
813681b2a36SB. J. Wyman     psu.analyze();
8143f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
8153f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
8163f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
8173f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
8183f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
81985c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
8206710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
821b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
8222cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
8237ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
82496893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
8252916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
82639ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
82739ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
82839ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
829b654c619SBrandon Wyman 
830f07bc797SBrandon Wyman     // STATUS_WORD with fault bits galore!
831b654c619SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
832f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
833b654c619SBrandon Wyman     expectations.statusInputValue = 0xFF;
834f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
835b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
83685c7bf41SBrandon Wyman     // STATUS_CML with bits on.
837b654c619SBrandon Wyman     expectations.statusCMLValue = 0xFF;
8386710ba2cSBrandon Wyman     // STATUS_VOUT with bits on.
839b654c619SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
840b10b3be0SBrandon Wyman     // STATUS_IOUT with bits on.
841b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
8427ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
8437ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0xFF;
84496893a46SBrandon Wyman     // STATUS_TEMPERATURE with bits on.
84596893a46SBrandon Wyman     expectations.statusTempValue = 0xFF;
846c2906f47SBrandon Wyman 
847c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
848c2906f47SBrandon Wyman     {
849b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
85082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
85182affd94SBrandon Wyman             .Times(1)
85282affd94SBrandon Wyman             .WillOnce(Return("0"));
8530975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
8540975eaf4SMatt Spinler         {
8550975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
8560975eaf4SMatt Spinler         }
8573f1242f3SBrandon Wyman         psu.analyze();
8583f1242f3SBrandon Wyman         EXPECT_EQ(psu.isPresent(), true);
8592cf46945SBrandon Wyman         // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
8602cf46945SBrandon Wyman         // Rely on HasVoutUVFault() to verify this sets and clears.
8612cf46945SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), false);
862c2906f47SBrandon Wyman         // All faults are deglitched up to DEGLITCH_LIMIT
863c2906f47SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
864c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
865c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
866c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
867c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT);
868c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
869c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
870c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
871c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
872c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPgoodFault(), x >= DEGLITCH_LIMIT);
873c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
874c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
875c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
876c2906f47SBrandon Wyman     }
877c2906f47SBrandon Wyman 
87832453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _))
87932453e9bSBrandon Wyman         .Times(1)
88032453e9bSBrandon Wyman         .WillOnce(Return(207000));
8813225a45cSBrandon Wyman     // Clearing VIN_UV fault via in1_lcrit_alarm
8823225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
8833225a45cSBrandon Wyman         .Times(1)
8843225a45cSBrandon Wyman         .WillOnce(Return(1));
8850975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
8863f1242f3SBrandon Wyman     psu.clearFaults();
8873f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
8883f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
8893f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
8903f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
8913f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
89285c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
8936710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
894b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
8952cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
8967ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
89796893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
8982916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
89939ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
90039ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
90139ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
902681b2a36SB. J. Wyman 
90382affd94SBrandon Wyman     // Faults clear on READ_VIN 0 -> !0
90482affd94SBrandon Wyman     // STATUS_WORD with fault bits galore!
90582affd94SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
90682affd94SBrandon Wyman     // STATUS_INPUT with fault bits on.
90782affd94SBrandon Wyman     expectations.statusInputValue = 0xFF;
90882affd94SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
90982affd94SBrandon Wyman     expectations.statusMFRValue = 0xFF;
91082affd94SBrandon Wyman     // STATUS_CML with bits on.
91182affd94SBrandon Wyman     expectations.statusCMLValue = 0xFF;
91282affd94SBrandon Wyman     // STATUS_VOUT with bits on.
91382affd94SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
91482affd94SBrandon Wyman     // STATUS_IOUT with bits on.
91582affd94SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
91682affd94SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
91782affd94SBrandon Wyman     expectations.statusFans12Value = 0xFF;
91882affd94SBrandon Wyman     // STATUS_TEMPERATURE with bits on.
91982affd94SBrandon Wyman     expectations.statusTempValue = 0xFF;
920c2906f47SBrandon Wyman 
921c2906f47SBrandon Wyman     // All faults degltiched now. Check for false before limit above.
922c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
923c2906f47SBrandon Wyman     {
92482affd94SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
92582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
92682affd94SBrandon Wyman             .Times(1)
92782affd94SBrandon Wyman             .WillOnce(Return("0"));
9280975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
9290975eaf4SMatt Spinler         {
9300975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
9310975eaf4SMatt Spinler         }
93282affd94SBrandon Wyman         psu.analyze();
933c2906f47SBrandon Wyman     }
934c2906f47SBrandon Wyman 
93582affd94SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
93682affd94SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
93782affd94SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), true);
93882affd94SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
93982affd94SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), true);
94082affd94SBrandon Wyman     // True due to CML fault bits on
94182affd94SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), true);
94282affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
94382affd94SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), true);
94482affd94SBrandon Wyman     // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
94582affd94SBrandon Wyman     // Rely on HasVoutUVFault() to verify this sets and clears.
94682affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
94782affd94SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), true);
94882affd94SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), true);
949c2906f47SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
95082affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), true);
95182affd94SBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), true);
95282affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), true);
95382affd94SBrandon Wyman     // STATUS_WORD with INPUT/VIN_UV fault bits off.
95482affd94SBrandon Wyman     expectations.statusWordValue = 0xDFF7;
95582affd94SBrandon Wyman     // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
95682affd94SBrandon Wyman     // Insufficient Input Voltage bits off.
95782affd94SBrandon Wyman     expectations.statusInputValue = 0xC7;
95882affd94SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
95982affd94SBrandon Wyman     // READ_VIN back in range.
96082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
96182affd94SBrandon Wyman         .Times(1)
96282affd94SBrandon Wyman         .WillOnce(Return("206000"));
9633225a45cSBrandon Wyman     // VIN_UV cleared via in1_lcrit_alarm when voltage back in range.
9643225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
9653225a45cSBrandon Wyman         .Times(1)
9663225a45cSBrandon Wyman         .WillOnce(Return(1));
9673225a45cSBrandon Wyman     psu.analyze();
9683225a45cSBrandon Wyman     // We only cleared the VIN_UV and OFF faults.
9693225a45cSBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
9703225a45cSBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
9713225a45cSBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
9723225a45cSBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
9733225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
9743225a45cSBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), true);
9753225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
9763225a45cSBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), true);
9773225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
9783225a45cSBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), true);
9793225a45cSBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), true);
9803225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
9813225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), true);
9823225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), true);
9833225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), true);
9843225a45cSBrandon Wyman 
9853225a45cSBrandon Wyman     // All faults cleared
9863225a45cSBrandon Wyman     expectations = {0};
9873225a45cSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
9883225a45cSBrandon Wyman     // READ_VIN back in range.
9893225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
9903225a45cSBrandon Wyman         .Times(1)
9913225a45cSBrandon Wyman         .WillOnce(Return("206000"));
9920975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
99382affd94SBrandon Wyman     psu.analyze();
99482affd94SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
99582affd94SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
99682affd94SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
99782affd94SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
99882affd94SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
99982affd94SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
100082affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
100182affd94SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
100282affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
100382affd94SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
100482affd94SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
100582affd94SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
100682affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
100782affd94SBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
100882affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
100982affd94SBrandon Wyman 
1010681b2a36SB. J. Wyman     // TODO: Faults clear on missing/present?
10113f1242f3SBrandon Wyman }
10123f1242f3SBrandon Wyman 
10133f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, UpdateInventory)
10143f1242f3SBrandon Wyman {
10153f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
10161d7a7df8SBrandon Wyman 
10171d7a7df8SBrandon Wyman     try
10181d7a7df8SBrandon Wyman     {
1019c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 3,
1020c3324424SBrandon Wyman                         0x68, "ibm-cffps",      PSUGPIOLineName};
10211d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
10221d7a7df8SBrandon Wyman         // If it is not present, I should not be trying to read a string
10231d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
10241d7a7df8SBrandon Wyman         psu.updateInventory();
10251d7a7df8SBrandon Wyman     }
10261d7a7df8SBrandon Wyman     catch (...)
10271d7a7df8SBrandon Wyman     {
10281d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
10291d7a7df8SBrandon Wyman     }
10301d7a7df8SBrandon Wyman 
10311d7a7df8SBrandon Wyman     try
10321d7a7df8SBrandon Wyman     {
1033c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 13,
1034c3324424SBrandon Wyman                         0x69, "ibm-cffps",      PSUGPIOLineName};
10353ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
10363ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1037681b2a36SB. J. Wyman         // GPIO read return 1 to indicate present.
1038681b2a36SB. J. Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
10391d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1040391a0690SBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
1041*ae35ac5dSBrandon Wyman         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1042*ae35ac5dSBrandon Wyman         // for INPUT_HISTORY will check max_power_out to see if it is
1043*ae35ac5dSBrandon Wyman         // old/unsupported power supply. Indicate good value, supported.
1044*ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1045*ae35ac5dSBrandon Wyman             .Times(1)
1046*ae35ac5dSBrandon Wyman             .WillOnce(Return("2000"));
1047391a0690SBrandon Wyman         // STATUS_WORD 0x0000 is powered on, no faults.
1048391a0690SBrandon Wyman         PMBusExpectations expectations;
1049391a0690SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
105082affd94SBrandon Wyman         // Call to analyze will read voltage, trigger clear faults for 0 to
105182affd94SBrandon Wyman         // within range.
105282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
105382affd94SBrandon Wyman             .Times(1)
105482affd94SBrandon Wyman             .WillOnce(Return("123456"));
1055391a0690SBrandon Wyman         psu.analyze();
10561d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
10573f1242f3SBrandon Wyman         psu.updateInventory();
10581d7a7df8SBrandon Wyman 
10593c530fbdSBrandon Wyman #if IBM_VPD
10601d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _))
10611d7a7df8SBrandon Wyman             .WillOnce(Return("CCIN"))
10621d7a7df8SBrandon Wyman             .WillOnce(Return("PN3456"))
10631d7a7df8SBrandon Wyman             .WillOnce(Return("FN3456"))
10641d7a7df8SBrandon Wyman             .WillOnce(Return("HEADER"))
10651d7a7df8SBrandon Wyman             .WillOnce(Return("SN3456"))
10661d7a7df8SBrandon Wyman             .WillOnce(Return("FW3456"));
10673c530fbdSBrandon Wyman #endif
10681d7a7df8SBrandon Wyman         psu.updateInventory();
10691d7a7df8SBrandon Wyman         // TODO: D-Bus mocking to verify values stored on D-Bus (???)
10701d7a7df8SBrandon Wyman     }
10711d7a7df8SBrandon Wyman     catch (...)
10721d7a7df8SBrandon Wyman     {
10731d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
10741d7a7df8SBrandon Wyman     }
10753f1242f3SBrandon Wyman }
10763f1242f3SBrandon Wyman 
10773f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsPresent)
10783f1242f3SBrandon Wyman {
10793f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1080681b2a36SB. J. Wyman 
1081c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1082c3324424SBrandon Wyman                     0x68, "ibm-cffps",      PSUGPIOLineName};
10833ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
10843ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
10853f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), false);
10863f1242f3SBrandon Wyman 
1087681b2a36SB. J. Wyman     // Change GPIO read to return 1 to indicate present.
1088681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
1089391a0690SBrandon Wyman     // Call to analyze() will update to present, that will trigger updating
1090391a0690SBrandon Wyman     // to the correct/latest HWMON directory, in case it changes.
1091391a0690SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1092391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1093*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1094*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1095*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1096*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1097*ae35ac5dSBrandon Wyman         .Times(1)
1098*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
1099391a0690SBrandon Wyman     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1100391a0690SBrandon Wyman     // Default expectations will be on, no faults.
1101391a0690SBrandon Wyman     PMBusExpectations expectations;
1102391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
110382affd94SBrandon Wyman     // Give it an input voltage in the 100-volt range.
110482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
110582affd94SBrandon Wyman         .Times(1)
110682affd94SBrandon Wyman         .WillOnce(Return("123456"));
11070975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1108681b2a36SB. J. Wyman     psu.analyze();
1109681b2a36SB. J. Wyman     EXPECT_EQ(psu.isPresent(), true);
11103f1242f3SBrandon Wyman }
11113f1242f3SBrandon Wyman 
11123f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsFaulted)
11133f1242f3SBrandon Wyman {
11143f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1115681b2a36SB. J. Wyman 
1116c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 11,
1117c3324424SBrandon Wyman                     0x6f, "ibm-cffps",      PSUGPIOLineName};
11183ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
11193ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1120681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1121681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1122391a0690SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1123391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1124*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1125*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1126*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1127*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1128*ae35ac5dSBrandon Wyman         .Times(1)
1129*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
1130391a0690SBrandon Wyman     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1131391a0690SBrandon Wyman     // Default expectations will be on, no faults.
1132391a0690SBrandon Wyman     PMBusExpectations expectations;
1133391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
113482affd94SBrandon Wyman     // Give it an input voltage in the 100-volt range.
113582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
113682affd94SBrandon Wyman         .Times(1)
113782affd94SBrandon Wyman         .WillOnce(Return("124680"));
1138681b2a36SB. J. Wyman     psu.analyze();
11393f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
1140f07bc797SBrandon Wyman     // STATUS_WORD with fault bits on.
1141b654c619SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
1142f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
1143b654c619SBrandon Wyman     expectations.statusInputValue = 0xFF;
1144f07bc797SBrandon Wyman     // STATUS_MFR_SPECIFIC with faults bits on.
1145b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
114685c7bf41SBrandon Wyman     // STATUS_CML with faults bits on.
1147b654c619SBrandon Wyman     expectations.statusCMLValue = 0xFF;
11486710ba2cSBrandon Wyman     // STATUS_VOUT with fault bits on.
1149b654c619SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
1150b10b3be0SBrandon Wyman     // STATUS_IOUT with fault bits on.
1151b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
11527ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
11537ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0xFF;
115496893a46SBrandon Wyman     // STATUS_TEMPERATURE with fault bits on.
115596893a46SBrandon Wyman     expectations.statusTempValue = 0xFF;
1156c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1157c2906f47SBrandon Wyman     {
1158b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
11594fc191f0SBrandon Wyman         // Also get another read of READ_VIN, faulted, so not in 100-volt range
116082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
116182affd94SBrandon Wyman             .Times(1)
11624fc191f0SBrandon Wyman             .WillOnce(Return("19000"));
11630975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
11640975eaf4SMatt Spinler         {
11650975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
11660975eaf4SMatt Spinler         }
11673f1242f3SBrandon Wyman         psu.analyze();
1168c2906f47SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
1169c2906f47SBrandon Wyman     }
11703f1242f3SBrandon Wyman }
11713f1242f3SBrandon Wyman 
11723f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasInputFault)
11733f1242f3SBrandon Wyman {
11743f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1175681b2a36SB. J. Wyman 
1176c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1177c3324424SBrandon Wyman                     0x68, "ibm-cffps",      PSUGPIOLineName};
11783ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
11793ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1180681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1181681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
11823f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1183391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1184*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1185*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1186*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1187*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1188*ae35ac5dSBrandon Wyman         .Times(1)
1189*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
11908da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1191b654c619SBrandon Wyman     PMBusExpectations expectations;
1192b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
119382affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
119482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
119582affd94SBrandon Wyman         .Times(1)
119682affd94SBrandon Wyman         .WillOnce(Return("201100"));
11973f1242f3SBrandon Wyman     psu.analyze();
11983f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
1199f07bc797SBrandon Wyman     // STATUS_WORD with input fault/warn on.
1200b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
1201f07bc797SBrandon Wyman     // STATUS_INPUT with an input fault bit on.
1202b654c619SBrandon Wyman     expectations.statusInputValue = 0x80;
1203c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1204c2906f47SBrandon Wyman     {
1205b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
120682affd94SBrandon Wyman         // Analyze call will also need good READ_VIN value to check.
120782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
120882affd94SBrandon Wyman             .Times(1)
120982affd94SBrandon Wyman             .WillOnce(Return("201200"));
12100975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
12110975eaf4SMatt Spinler         {
12120975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
12130975eaf4SMatt Spinler         }
12143f1242f3SBrandon Wyman         psu.analyze();
1215c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
1216c2906f47SBrandon Wyman     }
1217f07bc797SBrandon Wyman     // STATUS_WORD with no bits on.
1218b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1219b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
122082affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
122182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
122282affd94SBrandon Wyman         .Times(1)
122382affd94SBrandon Wyman         .WillOnce(Return("201300"));
12240975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
12253f1242f3SBrandon Wyman     psu.analyze();
12263f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
12273f1242f3SBrandon Wyman }
12283f1242f3SBrandon Wyman 
12293f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasMFRFault)
12303f1242f3SBrandon Wyman {
12313f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1232681b2a36SB. J. Wyman 
1233c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1234c3324424SBrandon Wyman                     0x68, "ibm-cffps",      PSUGPIOLineName};
12353ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
12363ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1237681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1238681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
12393f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1240391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1241*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1242*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1243*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1244*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1245*ae35ac5dSBrandon Wyman         .Times(1)
1246*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
1247f07bc797SBrandon Wyman     // First return STATUS_WORD with no bits on.
12488da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1249b654c619SBrandon Wyman     PMBusExpectations expectations;
1250b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
125182affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
125282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
125382affd94SBrandon Wyman         .Times(1)
125482affd94SBrandon Wyman         .WillOnce(Return("202100"));
12553f1242f3SBrandon Wyman     psu.analyze();
12563f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
1257f07bc797SBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
1258b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1259f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
1260b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
1261c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1262c2906f47SBrandon Wyman     {
1263b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
126482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
126582affd94SBrandon Wyman             .Times(1)
126682affd94SBrandon Wyman             .WillOnce(Return("202200"));
12673f1242f3SBrandon Wyman         psu.analyze();
1268c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1269c2906f47SBrandon Wyman     }
1270f07bc797SBrandon Wyman     // Back to no bits on in STATUS_WORD
1271b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1272b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
127382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
127482affd94SBrandon Wyman         .Times(1)
127582affd94SBrandon Wyman         .WillOnce(Return("202300"));
12763f1242f3SBrandon Wyman     psu.analyze();
12773f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
12783f1242f3SBrandon Wyman }
12793f1242f3SBrandon Wyman 
12803f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasVINUVFault)
12813f1242f3SBrandon Wyman {
12823f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1283681b2a36SB. J. Wyman 
1284c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1285c3324424SBrandon Wyman                     0x68, "ibm-cffps",      PSUGPIOLineName};
12863ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
12873ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1288681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1289681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
12903f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1291391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1292*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1293*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1294*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1295*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1296*ae35ac5dSBrandon Wyman         .Times(1)
1297*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
129882affd94SBrandon Wyman 
129982affd94SBrandon Wyman     // Presence change from missing to present will trigger in1_input read in
130082affd94SBrandon Wyman     // an attempt to get CLEAR_FAULTS called. Return value ignored.
130182affd94SBrandon Wyman     // Zero to non-zero voltage, for missing/present change, triggers clear
130282affd94SBrandon Wyman     // faults call again. Return value ignored.
130382affd94SBrandon Wyman     // Fault (low voltage) to not faulted (voltage in range) triggers clear
130482affd94SBrandon Wyman     // faults call a third time.
130582affd94SBrandon Wyman 
13068da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1307b654c619SBrandon Wyman     PMBusExpectations expectations;
1308b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
130982affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
131082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
131182affd94SBrandon Wyman         .Times(1)
131282affd94SBrandon Wyman         .WillOnce(Return("201100"));
13133f1242f3SBrandon Wyman     psu.analyze();
13143f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
1315f07bc797SBrandon Wyman     // Turn fault on.
1316b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::VIN_UV_FAULT);
131785c7bf41SBrandon Wyman     // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
131885c7bf41SBrandon Wyman     // Figure 16, and assume bits on in STATUS_INPUT.
1319b654c619SBrandon Wyman     expectations.statusInputValue = 0x18;
1320c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1321c2906f47SBrandon Wyman     {
1322b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
132382affd94SBrandon Wyman         // If there is a VIN_UV fault, fake reading voltage of less than 20V
132482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
132582affd94SBrandon Wyman             .Times(1)
132682affd94SBrandon Wyman             .WillOnce(Return("19876"));
13270975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
13280975eaf4SMatt Spinler         {
13290975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
13300975eaf4SMatt Spinler         }
13313f1242f3SBrandon Wyman         psu.analyze();
1332c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1333c2906f47SBrandon Wyman     }
1334f07bc797SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1335b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1336b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
133782affd94SBrandon Wyman     // Updates now result in clearing faults if read voltage goes from below the
133882affd94SBrandon Wyman     // minimum, to within a valid range.
133982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
134082affd94SBrandon Wyman         .Times(1)
134182affd94SBrandon Wyman         .WillOnce(Return("201300"));
13423225a45cSBrandon Wyman     // Went from below minimum to within range, expect clearVinUVFault().
13433225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
13443225a45cSBrandon Wyman         .Times(1)
13453225a45cSBrandon Wyman         .WillOnce(Return(1));
13460975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
13473f1242f3SBrandon Wyman     psu.analyze();
13483f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
13493f1242f3SBrandon Wyman }
13506710ba2cSBrandon Wyman 
13516710ba2cSBrandon Wyman TEST_F(PowerSupplyTests, HasVoutOVFault)
13526710ba2cSBrandon Wyman {
13536710ba2cSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
13546710ba2cSBrandon Wyman 
1355c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1356c3324424SBrandon Wyman                     0x69, "ibm-cffps",      PSUGPIOLineName};
13576710ba2cSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
13586710ba2cSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
13596710ba2cSBrandon Wyman     // Always return 1 to indicate present.
13606710ba2cSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
13616710ba2cSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1362391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1363*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1364*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1365*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1366*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1367*ae35ac5dSBrandon Wyman         .Times(1)
1368*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
13696710ba2cSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1370b654c619SBrandon Wyman     PMBusExpectations expectations;
1371b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
137282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
137382affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
137482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
137582affd94SBrandon Wyman         .Times(1)
137682affd94SBrandon Wyman         .WillOnce(Return("202100"));
13776710ba2cSBrandon Wyman     psu.analyze();
13786710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
13796710ba2cSBrandon Wyman     // Turn fault on.
1380b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
13816710ba2cSBrandon Wyman     // STATUS_VOUT fault bit(s)
1382b654c619SBrandon Wyman     expectations.statusVOUTValue = 0x80;
1383c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1384c2906f47SBrandon Wyman     {
1385b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
138682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
138782affd94SBrandon Wyman             .Times(1)
138882affd94SBrandon Wyman             .WillOnce(Return("202200"));
13896710ba2cSBrandon Wyman         psu.analyze();
1390c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1391c2906f47SBrandon Wyman     }
13926710ba2cSBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1393b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1394b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
139582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
139682affd94SBrandon Wyman         .Times(1)
139782affd94SBrandon Wyman         .WillOnce(Return("202300"));
13986710ba2cSBrandon Wyman     psu.analyze();
13996710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
14006710ba2cSBrandon Wyman }
140196893a46SBrandon Wyman 
1402b10b3be0SBrandon Wyman TEST_F(PowerSupplyTests, HasIoutOCFault)
1403b10b3be0SBrandon Wyman {
1404b10b3be0SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1405b10b3be0SBrandon Wyman 
1406c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1407c3324424SBrandon Wyman                     0x6d, "ibm-cffps",      PSUGPIOLineName};
1408b10b3be0SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
1409b10b3be0SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1410b10b3be0SBrandon Wyman     // Always return 1 to indicate present.
1411b10b3be0SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1412b10b3be0SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1413391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1414*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1415*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1416*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1417*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1418*ae35ac5dSBrandon Wyman         .Times(1)
1419*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
1420b10b3be0SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1421b10b3be0SBrandon Wyman     PMBusExpectations expectations;
1422b10b3be0SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
142382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
142482affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
142582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
142682affd94SBrandon Wyman         .Times(1)
142782affd94SBrandon Wyman         .WillOnce(Return("203100"));
1428b10b3be0SBrandon Wyman     psu.analyze();
1429b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
1430b10b3be0SBrandon Wyman     // Turn fault on.
1431b10b3be0SBrandon Wyman     expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1432b10b3be0SBrandon Wyman     // STATUS_IOUT fault bit(s)
1433b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0x88;
1434c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1435c2906f47SBrandon Wyman     {
1436b10b3be0SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
143782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
143882affd94SBrandon Wyman             .Times(1)
143982affd94SBrandon Wyman             .WillOnce(Return("203200"));
14400975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
14410975eaf4SMatt Spinler         {
14420975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
14430975eaf4SMatt Spinler         }
1444b10b3be0SBrandon Wyman         psu.analyze();
1445c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1446c2906f47SBrandon Wyman     }
1447b10b3be0SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1448b10b3be0SBrandon Wyman     expectations.statusWordValue = 0;
1449b10b3be0SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
145082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
145182affd94SBrandon Wyman         .Times(1)
145282affd94SBrandon Wyman         .WillOnce(Return("203300"));
14530975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1454b10b3be0SBrandon Wyman     psu.analyze();
1455b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
1456b10b3be0SBrandon Wyman }
1457b10b3be0SBrandon Wyman 
14582cf46945SBrandon Wyman TEST_F(PowerSupplyTests, HasVoutUVFault)
14592cf46945SBrandon Wyman {
14602cf46945SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
14612cf46945SBrandon Wyman 
1462c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1463c3324424SBrandon Wyman                     0x6a, "ibm-cffps",      PSUGPIOLineName};
14642cf46945SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
14652cf46945SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
14662cf46945SBrandon Wyman     // Always return 1 to indicate present.
14672cf46945SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
14682cf46945SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1469391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1470*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1471*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1472*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1473*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1474*ae35ac5dSBrandon Wyman         .Times(1)
1475*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
1476391a0690SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
14772cf46945SBrandon Wyman     PMBusExpectations expectations;
14782cf46945SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
147982affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
148082affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
148182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
148282affd94SBrandon Wyman         .Times(1)
148382affd94SBrandon Wyman         .WillOnce(Return("204100"));
14842cf46945SBrandon Wyman     psu.analyze();
14852cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
14862cf46945SBrandon Wyman     // Turn fault on.
14872cf46945SBrandon Wyman     expectations.statusWordValue = (status_word::VOUT_FAULT);
14882cf46945SBrandon Wyman     // STATUS_VOUT fault bit(s)
14892cf46945SBrandon Wyman     expectations.statusVOUTValue = 0x30;
1490c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1491c2906f47SBrandon Wyman     {
14922cf46945SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
149382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
149482affd94SBrandon Wyman             .Times(1)
149582affd94SBrandon Wyman             .WillOnce(Return("204200"));
14962cf46945SBrandon Wyman         psu.analyze();
1497c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1498c2906f47SBrandon Wyman     }
14992cf46945SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
15002cf46945SBrandon Wyman     expectations.statusWordValue = 0;
15012cf46945SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
150282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
150382affd94SBrandon Wyman         .Times(1)
150482affd94SBrandon Wyman         .WillOnce(Return("204300"));
15052cf46945SBrandon Wyman     psu.analyze();
15062cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
15072cf46945SBrandon Wyman }
15082cf46945SBrandon Wyman 
15097ee4d7e4SBrandon Wyman TEST_F(PowerSupplyTests, HasFanFault)
15107ee4d7e4SBrandon Wyman {
15117ee4d7e4SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
15127ee4d7e4SBrandon Wyman 
15130975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
15140975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
15150975eaf4SMatt Spinler 
1516c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1517c3324424SBrandon Wyman                     0x6d, "ibm-cffps",      PSUGPIOLineName};
15187ee4d7e4SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
15197ee4d7e4SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
15207ee4d7e4SBrandon Wyman     // Always return 1 to indicate present.
15217ee4d7e4SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
15227ee4d7e4SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1523391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1524*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1525*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1526*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1527*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1528*ae35ac5dSBrandon Wyman         .Times(1)
1529*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
15307ee4d7e4SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
15317ee4d7e4SBrandon Wyman     PMBusExpectations expectations;
15327ee4d7e4SBrandon 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("205100"));
15387ee4d7e4SBrandon Wyman     psu.analyze();
15397ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
15407ee4d7e4SBrandon Wyman     // Turn fault on.
15417ee4d7e4SBrandon Wyman     expectations.statusWordValue = (status_word::FAN_FAULT);
15427ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
15437ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0x80;
1544c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1545c2906f47SBrandon Wyman     {
15467ee4d7e4SBrandon 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("205200"));
15517ee4d7e4SBrandon Wyman         psu.analyze();
1552c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1553c2906f47SBrandon Wyman     }
15547ee4d7e4SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
15557ee4d7e4SBrandon Wyman     expectations.statusWordValue = 0;
15567ee4d7e4SBrandon 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("205300"));
15617ee4d7e4SBrandon Wyman     psu.analyze();
15627ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
15637ee4d7e4SBrandon Wyman }
15647ee4d7e4SBrandon Wyman 
156596893a46SBrandon Wyman TEST_F(PowerSupplyTests, HasTempFault)
156696893a46SBrandon Wyman {
156796893a46SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
156896893a46SBrandon Wyman 
15690975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
15700975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
15710975eaf4SMatt Spinler 
1572c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1573c3324424SBrandon Wyman                     0x6a, "ibm-cffps",      PSUGPIOLineName};
157496893a46SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
157596893a46SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
157696893a46SBrandon Wyman     // Always return 1 to indicate present.
157796893a46SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
157896893a46SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1579391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1580*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1581*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1582*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1583*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1584*ae35ac5dSBrandon Wyman         .Times(1)
1585*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
158696893a46SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
158796893a46SBrandon Wyman     PMBusExpectations expectations;
158896893a46SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
158982affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
159082affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
159182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
159282affd94SBrandon Wyman         .Times(1)
159382affd94SBrandon Wyman         .WillOnce(Return("206100"));
159496893a46SBrandon Wyman     psu.analyze();
159596893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
159696893a46SBrandon Wyman     // Turn fault on.
159796893a46SBrandon Wyman     expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
159896893a46SBrandon Wyman     // STATUS_TEMPERATURE fault bit on (OT Fault)
159996893a46SBrandon Wyman     expectations.statusTempValue = 0x80;
1600c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1601c2906f47SBrandon Wyman     {
160296893a46SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
160382affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
160482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
160582affd94SBrandon Wyman             .Times(1)
160682affd94SBrandon Wyman             .WillOnce(Return("206200"));
160796893a46SBrandon Wyman         psu.analyze();
1608c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1609c2906f47SBrandon Wyman     }
161096893a46SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
161196893a46SBrandon Wyman     expectations.statusWordValue = 0;
161296893a46SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
161382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
161482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
161582affd94SBrandon Wyman         .Times(1)
161682affd94SBrandon Wyman         .WillOnce(Return("206300"));
161796893a46SBrandon Wyman     psu.analyze();
161896893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
161996893a46SBrandon Wyman }
16202916ea52SBrandon Wyman 
16212916ea52SBrandon Wyman TEST_F(PowerSupplyTests, HasPgoodFault)
16222916ea52SBrandon Wyman {
16232916ea52SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
16242916ea52SBrandon Wyman 
1625c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1626c3324424SBrandon Wyman                     0x6b, "ibm-cffps",      PSUGPIOLineName};
16272916ea52SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
16282916ea52SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
16292916ea52SBrandon Wyman     // Always return 1 to indicate present.
16302916ea52SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
16312916ea52SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1632391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1633*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1634*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1635*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1636*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1637*ae35ac5dSBrandon Wyman         .Times(1)
1638*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
16392916ea52SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
16402916ea52SBrandon Wyman     PMBusExpectations expectations;
16412916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
164282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
164382affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
164482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
164582affd94SBrandon Wyman         .Times(1)
164682affd94SBrandon Wyman         .WillOnce(Return("207100"));
16472916ea52SBrandon Wyman     psu.analyze();
16482916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
1649391a0690SBrandon Wyman     // Setup another expectation of no faults.
1650391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
165182affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
165282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
165382affd94SBrandon Wyman         .Times(1)
165482affd94SBrandon Wyman         .WillOnce(Return("207200"));
165582affd94SBrandon Wyman     psu.analyze();
165682affd94SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
165782affd94SBrandon Wyman     // Setup another expectation of no faults.
165882affd94SBrandon 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("207300"));
1663391a0690SBrandon Wyman     psu.analyze();
1664391a0690SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
16652916ea52SBrandon Wyman     // Turn PGOOD# off (fault on).
16662916ea52SBrandon Wyman     expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
16672916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
166882affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
166982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
167082affd94SBrandon Wyman         .Times(1)
167182affd94SBrandon Wyman         .WillOnce(Return("207400"));
16722916ea52SBrandon Wyman     psu.analyze();
167306ca4590SBrandon Wyman     // Expect false until reaches DEGLITCH_LIMIT
167406ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
167506ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
167682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
167782affd94SBrandon Wyman         .Times(1)
167882affd94SBrandon Wyman         .WillOnce(Return("207500"));
167906ca4590SBrandon Wyman     psu.analyze();
168006ca4590SBrandon Wyman     // Expect false until reaches DEGLITCH_LIMIT
168106ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
168206ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
168382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
168482affd94SBrandon Wyman         .Times(1)
168582affd94SBrandon Wyman         .WillOnce(Return("207600"));
168606ca4590SBrandon Wyman     psu.analyze();
168706ca4590SBrandon Wyman     // DEGLITCH_LIMIT reached, expect true.
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)
169582affd94SBrandon Wyman         .WillOnce(Return("207700"));
16962916ea52SBrandon Wyman     psu.analyze();
16972916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
169882affd94SBrandon Wyman 
16992916ea52SBrandon Wyman     // Turn OFF bit on
17002916ea52SBrandon Wyman     expectations.statusWordValue = (status_word::UNIT_IS_OFF);
17012916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
170282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
170382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
170482affd94SBrandon Wyman         .Times(1)
170582affd94SBrandon Wyman         .WillOnce(Return("208100"));
17062916ea52SBrandon Wyman     psu.analyze();
170706ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
170806ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
170982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
171082affd94SBrandon Wyman         .Times(1)
171182affd94SBrandon Wyman         .WillOnce(Return("208200"));
171206ca4590SBrandon Wyman     psu.analyze();
171306ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
171406ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
171582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
171682affd94SBrandon Wyman         .Times(1)
171782affd94SBrandon Wyman         .WillOnce(Return("208300"));
171806ca4590SBrandon Wyman     psu.analyze();
17192916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
17202916ea52SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
17212916ea52SBrandon Wyman     expectations.statusWordValue = 0;
17222916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
172382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
172482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
172582affd94SBrandon Wyman         .Times(1)
172682affd94SBrandon Wyman         .WillOnce(Return("208400"));
17272916ea52SBrandon Wyman     psu.analyze();
17282916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
17292916ea52SBrandon Wyman }
173039ea02bcSBrandon Wyman 
173139ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPSKillFault)
173239ea02bcSBrandon Wyman {
173339ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1734c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 4,
1735c3324424SBrandon Wyman                     0x6d, "ibm-cffps",      PSUGPIOLineName};
173639ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
173739ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
173839ea02bcSBrandon Wyman     // Always return 1 to indicate present.
173939ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
174039ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
174182affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1742*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1743*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1744*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1745*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1746*ae35ac5dSBrandon Wyman         .Times(1)
1747*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
174839ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
174939ea02bcSBrandon Wyman     PMBusExpectations expectations;
175039ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
175182affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
175282affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
175382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
175482affd94SBrandon Wyman         .Times(1)
175582affd94SBrandon Wyman         .WillOnce(Return("208100"));
175639ea02bcSBrandon Wyman     psu.analyze();
175739ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
175839ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
175939ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
176039ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
176139ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1762c2906f47SBrandon Wyman 
1763c2906f47SBrandon Wyman     // Deglitching faults, false until read the fault bits on up to the limit.
1764c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1765c2906f47SBrandon Wyman     {
176639ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
176782affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
176882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
176982affd94SBrandon Wyman             .Times(1)
177082affd94SBrandon Wyman             .WillOnce(Return("208200"));
17710975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
17720975eaf4SMatt Spinler         {
17730975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
17740975eaf4SMatt Spinler         }
177539ea02bcSBrandon Wyman         psu.analyze();
1776c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1777c2906f47SBrandon Wyman     }
1778c2906f47SBrandon Wyman 
177939ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
178039ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
178139ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
178282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
178382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
178482affd94SBrandon Wyman         .Times(1)
178582affd94SBrandon Wyman         .WillOnce(Return("208300"));
17860975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
178739ea02bcSBrandon Wyman     psu.analyze();
178839ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
178939ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
179039ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
179139ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 4 on.
179239ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x10;
1793c2906f47SBrandon Wyman 
1794c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1795c2906f47SBrandon Wyman     {
179639ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
179782affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
179882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
179982affd94SBrandon Wyman             .Times(1)
180082affd94SBrandon Wyman             .WillOnce(Return("208400"));
18010975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
18020975eaf4SMatt Spinler         {
18030975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
18040975eaf4SMatt Spinler         }
180539ea02bcSBrandon Wyman         psu.analyze();
1806c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1807c2906f47SBrandon Wyman     }
1808c2906f47SBrandon Wyman 
180939ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
181039ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
181139ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
181282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
181382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
181482affd94SBrandon Wyman         .Times(1)
181582affd94SBrandon Wyman         .WillOnce(Return("208500"));
18160975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
181739ea02bcSBrandon Wyman     psu.analyze();
181839ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
181939ea02bcSBrandon Wyman }
182039ea02bcSBrandon Wyman 
182139ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPS12VcsFault)
182239ea02bcSBrandon Wyman {
182339ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1824c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 5,
1825c3324424SBrandon Wyman                     0x6e, "ibm-cffps",      PSUGPIOLineName};
182639ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
182739ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
182839ea02bcSBrandon Wyman     // Always return 1 to indicate present.
182939ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
183039ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
183182affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1832*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1833*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1834*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1835*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1836*ae35ac5dSBrandon Wyman         .Times(1)
1837*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
183839ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
183939ea02bcSBrandon Wyman     PMBusExpectations expectations;
184039ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
184182affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
184282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
184382affd94SBrandon Wyman         .Times(1)
184482affd94SBrandon Wyman         .WillOnce(Return("209100"));
184539ea02bcSBrandon Wyman     psu.analyze();
184639ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
184739ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
184839ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
184939ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
185039ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1851c2906f47SBrandon Wyman 
1852c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1853c2906f47SBrandon Wyman     {
185439ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
185582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
185682affd94SBrandon Wyman             .Times(1)
185782affd94SBrandon Wyman             .WillOnce(Return("209200"));
185839ea02bcSBrandon Wyman         psu.analyze();
1859c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1860c2906f47SBrandon Wyman     }
1861c2906f47SBrandon Wyman 
186239ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
186339ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
186439ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
186582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
186682affd94SBrandon Wyman         .Times(1)
186782affd94SBrandon Wyman         .WillOnce(Return("209300"));
186839ea02bcSBrandon Wyman     psu.analyze();
186939ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
187039ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
187139ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
187239ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 6 on.
187339ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x40;
1874c2906f47SBrandon Wyman 
1875c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1876c2906f47SBrandon Wyman     {
187739ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
187882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
187982affd94SBrandon Wyman             .Times(1)
188082affd94SBrandon Wyman             .WillOnce(Return("209400"));
188139ea02bcSBrandon Wyman         psu.analyze();
1882c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1883c2906f47SBrandon Wyman     }
1884c2906f47SBrandon Wyman 
188539ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
188639ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
188739ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
188882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
188982affd94SBrandon Wyman         .Times(1)
189082affd94SBrandon Wyman         .WillOnce(Return("209500"));
189139ea02bcSBrandon Wyman     psu.analyze();
189239ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
189339ea02bcSBrandon Wyman }
189439ea02bcSBrandon Wyman 
189539ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPSCS12VFault)
189639ea02bcSBrandon Wyman {
189739ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1898c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 6,
1899c3324424SBrandon Wyman                     0x6f, "ibm-cffps",      PSUGPIOLineName};
190039ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
190139ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
190239ea02bcSBrandon Wyman     // Always return 1 to indicate present.
190339ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
190439ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
190582affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1906*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1907*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1908*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1909*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1910*ae35ac5dSBrandon Wyman         .Times(1)
1911*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
191239ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
191339ea02bcSBrandon Wyman     PMBusExpectations expectations;
191439ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
191582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
191682affd94SBrandon Wyman         .Times(1)
191782affd94SBrandon Wyman         .WillOnce(Return("209100"));
191839ea02bcSBrandon Wyman     psu.analyze();
191939ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
192039ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
192139ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
192239ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
192339ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1924c2906f47SBrandon Wyman 
1925c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1926c2906f47SBrandon Wyman     {
192739ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
192882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
192982affd94SBrandon Wyman             .Times(1)
193082affd94SBrandon Wyman             .WillOnce(Return("209200"));
193139ea02bcSBrandon Wyman         psu.analyze();
1932c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1933c2906f47SBrandon Wyman     }
1934c2906f47SBrandon Wyman 
193539ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
193639ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
193739ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
193882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
193982affd94SBrandon Wyman         .Times(1)
194082affd94SBrandon Wyman         .WillOnce(Return("209300"));
194139ea02bcSBrandon Wyman     psu.analyze();
194239ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
194339ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
194439ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
194539ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 7 on.
194639ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x80;
1947c2906f47SBrandon Wyman 
1948c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1949c2906f47SBrandon Wyman     {
195039ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
195182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
195282affd94SBrandon Wyman             .Times(1)
195382affd94SBrandon Wyman             .WillOnce(Return("209400"));
195439ea02bcSBrandon Wyman         psu.analyze();
1955c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1956c2906f47SBrandon Wyman     }
1957c2906f47SBrandon Wyman 
195839ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
195939ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
196039ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
196182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
196282affd94SBrandon Wyman         .Times(1)
196382affd94SBrandon Wyman         .WillOnce(Return("209500"));
196439ea02bcSBrandon Wyman     psu.analyze();
196539ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
196639ea02bcSBrandon Wyman }
1967c3324424SBrandon Wyman 
1968c3324424SBrandon Wyman TEST_F(PowerSupplyTests, SetupInputHistory)
1969c3324424SBrandon Wyman {
1970c3324424SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1971c3324424SBrandon Wyman     {
1972c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 6,
1973c3324424SBrandon Wyman                         0x6f, "ibm-cffps",      PSUGPIOLineName};
1974c3324424SBrandon Wyman         // Defaults to not present due to constructor and mock ordering.
1975c3324424SBrandon Wyman         psu.setupInputHistory();
1976c3324424SBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
1977c3324424SBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
1978c3324424SBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1979*ae35ac5dSBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1980c3324424SBrandon Wyman         // Always return 1 to indicate present.
1981c3324424SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1982*ae35ac5dSBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
1983*ae35ac5dSBrandon Wyman         PMBusExpectations expectations;
1984*ae35ac5dSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
1985*ae35ac5dSBrandon Wyman         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
1986*ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1987*ae35ac5dSBrandon Wyman             .Times(1)
1988*ae35ac5dSBrandon Wyman             .WillOnce(Return("206000"));
1989*ae35ac5dSBrandon Wyman         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1990*ae35ac5dSBrandon Wyman         // for INPUT_HISTORY will check max_power_out to see if it is
1991*ae35ac5dSBrandon Wyman         // old/unsupported power supply. Indicate good value, supported.
1992*ae35ac5dSBrandon Wyman         /// Also called when I redo setupInputHistory().
1993*ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1994*ae35ac5dSBrandon Wyman             .Times(2)
1995*ae35ac5dSBrandon Wyman             .WillRepeatedly(Return("2000"));
1996*ae35ac5dSBrandon Wyman         // Call to analyze() and above expectations to get missing/present and
1997*ae35ac5dSBrandon Wyman         // good status.
1998c3324424SBrandon Wyman         psu.analyze();
1999c3324424SBrandon Wyman         psu.setupInputHistory();
2000c3324424SBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), true);
2001c3324424SBrandon Wyman     }
2002c3324424SBrandon Wyman     {
2003*ae35ac5dSBrandon Wyman         // Workaround - Disable INPUT_HISTORY collection if 1400W
2004*ae35ac5dSBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 3,
2005*ae35ac5dSBrandon Wyman                         0x68, "ibm-cffps",      PSUGPIOLineName};
2006*ae35ac5dSBrandon Wyman         // Defaults to not present due to constructor and mock ordering.
2007*ae35ac5dSBrandon Wyman         psu.setupInputHistory();
2008*ae35ac5dSBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
2009*ae35ac5dSBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
2010*ae35ac5dSBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2011*ae35ac5dSBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2012*ae35ac5dSBrandon Wyman         // Always return 1 to indicate present.
2013*ae35ac5dSBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2014*ae35ac5dSBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
2015*ae35ac5dSBrandon Wyman         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2016*ae35ac5dSBrandon Wyman         // for INPUT_HISTORY will check max_power_out to see if it is
2017*ae35ac5dSBrandon Wyman         // old/unsupported power supply. Indicate 1400W IBM value, unsupported.
2018*ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2019*ae35ac5dSBrandon Wyman             .Times(2)
2020*ae35ac5dSBrandon Wyman             .WillRepeatedly(Return("30725"));
2021*ae35ac5dSBrandon Wyman         PMBusExpectations expectations;
2022*ae35ac5dSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
2023*ae35ac5dSBrandon Wyman         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
2024*ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2025*ae35ac5dSBrandon Wyman             .Times(1)
2026*ae35ac5dSBrandon Wyman             .WillOnce(Return("206000"));
2027*ae35ac5dSBrandon Wyman         // Call to analyze() and above expectations to get missing/present and
2028*ae35ac5dSBrandon Wyman         // good status.
2029*ae35ac5dSBrandon Wyman         psu.analyze();
2030*ae35ac5dSBrandon Wyman         psu.setupInputHistory();
2031*ae35ac5dSBrandon Wyman         // After updating to present, and retrying setup, expect ibm-cffps with
2032*ae35ac5dSBrandon Wyman         // 1400W to still not support INPUT_HISTORY.
2033*ae35ac5dSBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
2034*ae35ac5dSBrandon Wyman     }
2035*ae35ac5dSBrandon Wyman     {
2036c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 11,
2037c3324424SBrandon Wyman                         0x58, "inspur-ipsps",   PSUGPIOLineName};
2038c3324424SBrandon Wyman         // Defaults to not present due to constructor and mock ordering.
2039c3324424SBrandon Wyman         psu.setupInputHistory();
2040c3324424SBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
2041c3324424SBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
2042c3324424SBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2043*ae35ac5dSBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2044c3324424SBrandon Wyman         // Always return 1 to indicate present.
2045c3324424SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2046*ae35ac5dSBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
2047*ae35ac5dSBrandon Wyman         PMBusExpectations expectations;
2048*ae35ac5dSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
2049*ae35ac5dSBrandon Wyman         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
2050*ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2051*ae35ac5dSBrandon Wyman             .Times(1)
2052*ae35ac5dSBrandon Wyman             .WillOnce(Return("206000"));
2053*ae35ac5dSBrandon Wyman         // Call to analyze() and above expectations to get missing/present and
2054*ae35ac5dSBrandon Wyman         // good status.
2055c3324424SBrandon Wyman         psu.analyze();
2056c3324424SBrandon Wyman         psu.setupInputHistory();
2057c3324424SBrandon Wyman         // After updating to present, and retrying setup, expect inspur-ipsps to
2058c3324424SBrandon Wyman         // still not support INPUT_HISTORY.
2059c3324424SBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
2060c3324424SBrandon Wyman     }
2061c3324424SBrandon Wyman }
2062c3324424SBrandon Wyman 
2063c3324424SBrandon Wyman TEST_F(PowerSupplyTests, UpdateHistory)
2064c3324424SBrandon Wyman {
2065c3324424SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
2066c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 7,
2067c3324424SBrandon Wyman                     0x6e, "ibm-cffps",      PSUGPIOLineName};
2068c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), false);
2069c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
2070c3324424SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
2071c3324424SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2072c3324424SBrandon Wyman     // Always return 1 to indicate present.
2073c3324424SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2074c3324424SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2075c3324424SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
2076*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2077*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
2078*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
2079*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2080*ae35ac5dSBrandon Wyman         .Times(1)
2081*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
2082c3324424SBrandon Wyman     PMBusExpectations expectations;
2083c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2084c3324424SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2085c3324424SBrandon Wyman         .Times(6)
2086c3324424SBrandon Wyman         .WillRepeatedly(Return("205000"));
2087c3324424SBrandon Wyman     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
2088c3324424SBrandon Wyman     // First read after missing/present will have no data.
2089c3324424SBrandon Wyman     std::vector<uint8_t> emptyHistory{};
2090c3324424SBrandon Wyman     // Second read, after about 30 seconds, should have a record. 5-bytes.
2091c3324424SBrandon Wyman     // Sequence Number: 0x00, Average: 0x50 0xf3 (212), Maximum: 0x54 0xf3 (213)
2092c3324424SBrandon Wyman     std::vector<uint8_t> firstHistory{0x00, 0x50, 0xf3, 0x54, 0xf3};
2093c3324424SBrandon Wyman     // Third read, after about 60 seconds, should have two records, 10-bytes,
2094c3324424SBrandon Wyman     // but only reading 5 bytes, so make sure new/next sequence number
2095c3324424SBrandon Wyman     std::vector<uint8_t> secondHistory{0x01, 0x54, 0xf3, 0x58, 0xf3};
2096c3324424SBrandon Wyman     // Fourth read, 3rd sequence number (0x02).
2097c3324424SBrandon Wyman     std::vector<uint8_t> thirdHistory{0x02, 0x54, 0xf3, 0x58, 0xf3};
2098c3324424SBrandon Wyman     // Fifth read, out of sequence, clear and insert this one?
2099c3324424SBrandon Wyman     std::vector<uint8_t> outseqHistory{0xff, 0x5c, 0xf3, 0x60, 0xf3};
2100c3324424SBrandon Wyman     EXPECT_CALL(
2101c3324424SBrandon Wyman         mockPMBus,
2102c3324424SBrandon Wyman         readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug,
2103c3324424SBrandon Wyman                    phosphor::power::history::RecordManager::RAW_RECORD_SIZE))
2104c3324424SBrandon Wyman         .Times(6)
2105c3324424SBrandon Wyman         .WillOnce(Return(emptyHistory))
2106c3324424SBrandon Wyman         .WillOnce(Return(firstHistory))
2107c3324424SBrandon Wyman         .WillOnce(Return(secondHistory))
2108c3324424SBrandon Wyman         .WillOnce(Return(thirdHistory))
2109c3324424SBrandon Wyman         .WillOnce(Return(outseqHistory))
2110c3324424SBrandon Wyman         .WillOnce(Return(emptyHistory));
2111c3324424SBrandon Wyman     // Calling analyze will update the presence, which will setup the input
2112c3324424SBrandon Wyman     // history if the power supply went from missing to present.
2113c3324424SBrandon Wyman     psu.analyze();
2114c3324424SBrandon Wyman     // The ibm-cffps power supply should support input history
2115c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2116c3324424SBrandon Wyman     // Usually should have empty buffer right after missing to present.
2117c3324424SBrandon Wyman     // Faked that out above with mocked readBinary with emptyHistory data.
2118c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
2119c3324424SBrandon Wyman     // Second run through...
2120c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2121c3324424SBrandon Wyman     psu.analyze();
2122c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2123c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 1);
2124c3324424SBrandon Wyman     // Third run through
2125c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2126c3324424SBrandon Wyman     psu.analyze();
2127c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2128c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 2);
2129c3324424SBrandon Wyman     // Fourth run through. Up to 3 records now?
2130c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2131c3324424SBrandon Wyman     psu.analyze();
2132c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2133c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 3);
2134c3324424SBrandon Wyman     // Out of sequencer, reset, insert new one.
2135c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2136c3324424SBrandon Wyman     psu.analyze();
2137c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2138c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 1);
2139c3324424SBrandon Wyman     // Empty one after last one good. Reset/clear.
2140c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2141c3324424SBrandon Wyman     psu.analyze();
2142c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2143c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
2144c3324424SBrandon Wyman }
214518a24d92SBrandon Wyman 
214618a24d92SBrandon Wyman TEST_F(PowerSupplyTests, IsSyncHistoryRequired)
214718a24d92SBrandon Wyman {
214818a24d92SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
214918a24d92SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 8,
215018a24d92SBrandon Wyman                     0x6f, "ibm-cffps",      PSUGPIOLineName};
215118a24d92SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), false);
215218a24d92SBrandon Wyman     EXPECT_EQ(psu.isSyncHistoryRequired(), false);
215318a24d92SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
215418a24d92SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
215518a24d92SBrandon Wyman     // Always return 1 to indicate present.
215618a24d92SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
215718a24d92SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
215818a24d92SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
2159*ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2160*ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
2161*ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
2162*ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2163*ae35ac5dSBrandon Wyman         .Times(1)
2164*ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
216518a24d92SBrandon Wyman     PMBusExpectations expectations;
216618a24d92SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
216718a24d92SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
216818a24d92SBrandon Wyman         .Times(1)
216918a24d92SBrandon Wyman         .WillRepeatedly(Return("205000"));
217018a24d92SBrandon Wyman     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
217118a24d92SBrandon Wyman     psu.analyze();
217218a24d92SBrandon Wyman     // The ibm-cffps power supply should support input history
217318a24d92SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
217418a24d92SBrandon Wyman     // Missing -> Present requires history sync
217518a24d92SBrandon Wyman     EXPECT_EQ(psu.isSyncHistoryRequired(), true);
217618a24d92SBrandon Wyman     psu.clearSyncHistoryRequired();
217718a24d92SBrandon Wyman     EXPECT_EQ(psu.isSyncHistoryRequired(), false);
217818a24d92SBrandon Wyman }
2179