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);
259ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
260ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
261ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
262ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
263ae35ac5dSBrandon Wyman         .Times(1)
264ae35ac5dSBrandon 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));
699*6d469fd4SBrandon Wyman         for (auto x = 1; x <= PGOOD_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);
709*6d469fd4SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= PGOOD_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);
719*6d469fd4SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), x >= PGOOD_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);
765ae35ac5dSBrandon Wyman         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
766ae35ac5dSBrandon Wyman         // for INPUT_HISTORY will check max_power_out to see if it is
767ae35ac5dSBrandon Wyman         // old/unsupported power supply. Indicate good value, supported.
768ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
769ae35ac5dSBrandon Wyman             .Times(1)
770ae35ac5dSBrandon 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);
801ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
802ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
803ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
804ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
805ae35ac5dSBrandon Wyman         .Times(1)
806ae35ac5dSBrandon 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 
847*6d469fd4SBrandon Wyman     for (auto x = 1; x <= PGOOD_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);
862*6d469fd4SBrandon Wyman         // pgoodFault at PGOOD_DEGLITCH_LIMIT, all other faults are deglitched
863*6d469fd4SBrandon Wyman         // up to DEGLITCH_LIMIT
864c2906f47SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
865c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
866c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
867c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
868c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT);
869c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
870c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
871c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
872c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
873*6d469fd4SBrandon Wyman         EXPECT_EQ(psu.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT);
874c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
875c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
876c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
877c2906f47SBrandon Wyman     }
878c2906f47SBrandon Wyman 
87932453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _))
88032453e9bSBrandon Wyman         .Times(1)
88132453e9bSBrandon Wyman         .WillOnce(Return(207000));
8823225a45cSBrandon Wyman     // Clearing VIN_UV fault via in1_lcrit_alarm
8833225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
8843225a45cSBrandon Wyman         .Times(1)
8853225a45cSBrandon Wyman         .WillOnce(Return(1));
8860975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
8873f1242f3SBrandon Wyman     psu.clearFaults();
8883f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
8893f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
8903f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
8913f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
8923f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
89385c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
8946710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
895b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
8962cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
8977ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
89896893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
8992916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
90039ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
90139ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
90239ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
903681b2a36SB. J. Wyman 
90482affd94SBrandon Wyman     // Faults clear on READ_VIN 0 -> !0
90582affd94SBrandon Wyman     // STATUS_WORD with fault bits galore!
90682affd94SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
90782affd94SBrandon Wyman     // STATUS_INPUT with fault bits on.
90882affd94SBrandon Wyman     expectations.statusInputValue = 0xFF;
90982affd94SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
91082affd94SBrandon Wyman     expectations.statusMFRValue = 0xFF;
91182affd94SBrandon Wyman     // STATUS_CML with bits on.
91282affd94SBrandon Wyman     expectations.statusCMLValue = 0xFF;
91382affd94SBrandon Wyman     // STATUS_VOUT with bits on.
91482affd94SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
91582affd94SBrandon Wyman     // STATUS_IOUT with bits on.
91682affd94SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
91782affd94SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
91882affd94SBrandon Wyman     expectations.statusFans12Value = 0xFF;
91982affd94SBrandon Wyman     // STATUS_TEMPERATURE with bits on.
92082affd94SBrandon Wyman     expectations.statusTempValue = 0xFF;
921c2906f47SBrandon Wyman 
922*6d469fd4SBrandon Wyman     // All faults deglitched now. Check for false before limit above.
923c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
924c2906f47SBrandon Wyman     {
92582affd94SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
92682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
92782affd94SBrandon Wyman             .Times(1)
92882affd94SBrandon Wyman             .WillOnce(Return("0"));
9290975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
9300975eaf4SMatt Spinler         {
9310975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
9320975eaf4SMatt Spinler         }
93382affd94SBrandon Wyman         psu.analyze();
934c2906f47SBrandon Wyman     }
935c2906f47SBrandon Wyman 
93682affd94SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
93782affd94SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
93882affd94SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), true);
93982affd94SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
94082affd94SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), true);
94182affd94SBrandon Wyman     // True due to CML fault bits on
94282affd94SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), true);
94382affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
94482affd94SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), true);
94582affd94SBrandon Wyman     // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
94682affd94SBrandon Wyman     // Rely on HasVoutUVFault() to verify this sets and clears.
94782affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
94882affd94SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), true);
94982affd94SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), true);
950*6d469fd4SBrandon Wyman     // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT
951*6d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
95282affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), true);
95382affd94SBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), true);
95482affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), true);
95582affd94SBrandon Wyman     // STATUS_WORD with INPUT/VIN_UV fault bits off.
95682affd94SBrandon Wyman     expectations.statusWordValue = 0xDFF7;
95782affd94SBrandon Wyman     // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
95882affd94SBrandon Wyman     // Insufficient Input Voltage bits off.
95982affd94SBrandon Wyman     expectations.statusInputValue = 0xC7;
96082affd94SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
96182affd94SBrandon Wyman     // READ_VIN back in range.
96282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
96382affd94SBrandon Wyman         .Times(1)
96482affd94SBrandon Wyman         .WillOnce(Return("206000"));
9653225a45cSBrandon Wyman     // VIN_UV cleared via in1_lcrit_alarm when voltage back in range.
9663225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
9673225a45cSBrandon Wyman         .Times(1)
9683225a45cSBrandon Wyman         .WillOnce(Return(1));
9693225a45cSBrandon Wyman     psu.analyze();
9703225a45cSBrandon Wyman     // We only cleared the VIN_UV and OFF faults.
9713225a45cSBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
9723225a45cSBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
9733225a45cSBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
9743225a45cSBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
9753225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
9763225a45cSBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), true);
9773225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
9783225a45cSBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), true);
9793225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
9803225a45cSBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), true);
9813225a45cSBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), true);
982*6d469fd4SBrandon Wyman     // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT
983*6d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
9843225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), true);
9853225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), true);
9863225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), true);
9873225a45cSBrandon Wyman 
9883225a45cSBrandon Wyman     // All faults cleared
9893225a45cSBrandon Wyman     expectations = {0};
9903225a45cSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
9913225a45cSBrandon Wyman     // READ_VIN back in range.
9923225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
9933225a45cSBrandon Wyman         .Times(1)
9943225a45cSBrandon Wyman         .WillOnce(Return("206000"));
9950975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
99682affd94SBrandon Wyman     psu.analyze();
99782affd94SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
99882affd94SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
99982affd94SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
100082affd94SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
100182affd94SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
100282affd94SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
100382affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
100482affd94SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
100582affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
100682affd94SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
100782affd94SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
100882affd94SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
100982affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
101082affd94SBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
101182affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
101282affd94SBrandon Wyman 
1013681b2a36SB. J. Wyman     // TODO: Faults clear on missing/present?
10143f1242f3SBrandon Wyman }
10153f1242f3SBrandon Wyman 
10163f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, UpdateInventory)
10173f1242f3SBrandon Wyman {
10183f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
10191d7a7df8SBrandon Wyman 
10201d7a7df8SBrandon Wyman     try
10211d7a7df8SBrandon Wyman     {
1022c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 3,
1023c3324424SBrandon Wyman                         0x68, "ibm-cffps",      PSUGPIOLineName};
10241d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
10251d7a7df8SBrandon Wyman         // If it is not present, I should not be trying to read a string
10261d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
10271d7a7df8SBrandon Wyman         psu.updateInventory();
10281d7a7df8SBrandon Wyman     }
10291d7a7df8SBrandon Wyman     catch (...)
10301d7a7df8SBrandon Wyman     {
10311d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
10321d7a7df8SBrandon Wyman     }
10331d7a7df8SBrandon Wyman 
10341d7a7df8SBrandon Wyman     try
10351d7a7df8SBrandon Wyman     {
1036c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 13,
1037c3324424SBrandon Wyman                         0x69, "ibm-cffps",      PSUGPIOLineName};
10383ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
10393ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1040681b2a36SB. J. Wyman         // GPIO read return 1 to indicate present.
1041681b2a36SB. J. Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
10421d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1043391a0690SBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
1044ae35ac5dSBrandon Wyman         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1045ae35ac5dSBrandon Wyman         // for INPUT_HISTORY will check max_power_out to see if it is
1046ae35ac5dSBrandon Wyman         // old/unsupported power supply. Indicate good value, supported.
1047ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1048ae35ac5dSBrandon Wyman             .Times(1)
1049ae35ac5dSBrandon Wyman             .WillOnce(Return("2000"));
1050391a0690SBrandon Wyman         // STATUS_WORD 0x0000 is powered on, no faults.
1051391a0690SBrandon Wyman         PMBusExpectations expectations;
1052391a0690SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
105382affd94SBrandon Wyman         // Call to analyze will read voltage, trigger clear faults for 0 to
105482affd94SBrandon Wyman         // within range.
105582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
105682affd94SBrandon Wyman             .Times(1)
105782affd94SBrandon Wyman             .WillOnce(Return("123456"));
1058391a0690SBrandon Wyman         psu.analyze();
10591d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
10603f1242f3SBrandon Wyman         psu.updateInventory();
10611d7a7df8SBrandon Wyman 
10623c530fbdSBrandon Wyman #if IBM_VPD
10631d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _))
10641d7a7df8SBrandon Wyman             .WillOnce(Return("CCIN"))
10651d7a7df8SBrandon Wyman             .WillOnce(Return("PN3456"))
10661d7a7df8SBrandon Wyman             .WillOnce(Return("FN3456"))
10671d7a7df8SBrandon Wyman             .WillOnce(Return("HEADER"))
10681d7a7df8SBrandon Wyman             .WillOnce(Return("SN3456"))
10691d7a7df8SBrandon Wyman             .WillOnce(Return("FW3456"));
10703c530fbdSBrandon Wyman #endif
10711d7a7df8SBrandon Wyman         psu.updateInventory();
10721d7a7df8SBrandon Wyman         // TODO: D-Bus mocking to verify values stored on D-Bus (???)
10731d7a7df8SBrandon Wyman     }
10741d7a7df8SBrandon Wyman     catch (...)
10751d7a7df8SBrandon Wyman     {
10761d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
10771d7a7df8SBrandon Wyman     }
10783f1242f3SBrandon Wyman }
10793f1242f3SBrandon Wyman 
10803f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsPresent)
10813f1242f3SBrandon Wyman {
10823f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1083681b2a36SB. J. Wyman 
1084c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1085c3324424SBrandon Wyman                     0x68, "ibm-cffps",      PSUGPIOLineName};
10863ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
10873ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
10883f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), false);
10893f1242f3SBrandon Wyman 
1090681b2a36SB. J. Wyman     // Change GPIO read to return 1 to indicate present.
1091681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
1092391a0690SBrandon Wyman     // Call to analyze() will update to present, that will trigger updating
1093391a0690SBrandon Wyman     // to the correct/latest HWMON directory, in case it changes.
1094391a0690SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1095391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1096ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1097ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1098ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1099ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1100ae35ac5dSBrandon Wyman         .Times(1)
1101ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
1102391a0690SBrandon Wyman     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1103391a0690SBrandon Wyman     // Default expectations will be on, no faults.
1104391a0690SBrandon Wyman     PMBusExpectations expectations;
1105391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
110682affd94SBrandon Wyman     // Give it an input voltage in the 100-volt range.
110782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
110882affd94SBrandon Wyman         .Times(1)
110982affd94SBrandon Wyman         .WillOnce(Return("123456"));
11100975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1111681b2a36SB. J. Wyman     psu.analyze();
1112681b2a36SB. J. Wyman     EXPECT_EQ(psu.isPresent(), true);
11133f1242f3SBrandon Wyman }
11143f1242f3SBrandon Wyman 
11153f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsFaulted)
11163f1242f3SBrandon Wyman {
11173f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1118681b2a36SB. J. Wyman 
1119c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 11,
1120c3324424SBrandon Wyman                     0x6f, "ibm-cffps",      PSUGPIOLineName};
11213ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
11223ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1123681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1124681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1125391a0690SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1126391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1127ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1128ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1129ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1130ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1131ae35ac5dSBrandon Wyman         .Times(1)
1132ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
1133391a0690SBrandon Wyman     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1134391a0690SBrandon Wyman     // Default expectations will be on, no faults.
1135391a0690SBrandon Wyman     PMBusExpectations expectations;
1136391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
113782affd94SBrandon Wyman     // Give it an input voltage in the 100-volt range.
113882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
113982affd94SBrandon Wyman         .Times(1)
114082affd94SBrandon Wyman         .WillOnce(Return("124680"));
1141681b2a36SB. J. Wyman     psu.analyze();
11423f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
1143f07bc797SBrandon Wyman     // STATUS_WORD with fault bits on.
1144b654c619SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
1145f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
1146b654c619SBrandon Wyman     expectations.statusInputValue = 0xFF;
1147f07bc797SBrandon Wyman     // STATUS_MFR_SPECIFIC with faults bits on.
1148b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
114985c7bf41SBrandon Wyman     // STATUS_CML with faults bits on.
1150b654c619SBrandon Wyman     expectations.statusCMLValue = 0xFF;
11516710ba2cSBrandon Wyman     // STATUS_VOUT with fault bits on.
1152b654c619SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
1153b10b3be0SBrandon Wyman     // STATUS_IOUT with fault bits on.
1154b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
11557ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
11567ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0xFF;
115796893a46SBrandon Wyman     // STATUS_TEMPERATURE with fault bits on.
115896893a46SBrandon Wyman     expectations.statusTempValue = 0xFF;
1159c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1160c2906f47SBrandon Wyman     {
1161b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
11624fc191f0SBrandon Wyman         // Also get another read of READ_VIN, faulted, so not in 100-volt range
116382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
116482affd94SBrandon Wyman             .Times(1)
11654fc191f0SBrandon Wyman             .WillOnce(Return("19000"));
11660975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
11670975eaf4SMatt Spinler         {
11680975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
11690975eaf4SMatt Spinler         }
11703f1242f3SBrandon Wyman         psu.analyze();
1171c2906f47SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
1172c2906f47SBrandon Wyman     }
11733f1242f3SBrandon Wyman }
11743f1242f3SBrandon Wyman 
11753f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasInputFault)
11763f1242f3SBrandon Wyman {
11773f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1178681b2a36SB. J. Wyman 
1179c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1180c3324424SBrandon Wyman                     0x68, "ibm-cffps",      PSUGPIOLineName};
11813ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
11823ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1183681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1184681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
11853f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1186391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1187ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1188ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1189ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1190ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1191ae35ac5dSBrandon Wyman         .Times(1)
1192ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
11938da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1194b654c619SBrandon Wyman     PMBusExpectations expectations;
1195b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
119682affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
119782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
119882affd94SBrandon Wyman         .Times(1)
119982affd94SBrandon Wyman         .WillOnce(Return("201100"));
12003f1242f3SBrandon Wyman     psu.analyze();
12013f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
1202f07bc797SBrandon Wyman     // STATUS_WORD with input fault/warn on.
1203b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
1204f07bc797SBrandon Wyman     // STATUS_INPUT with an input fault bit on.
1205b654c619SBrandon Wyman     expectations.statusInputValue = 0x80;
1206c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1207c2906f47SBrandon Wyman     {
1208b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
120982affd94SBrandon Wyman         // Analyze call will also need good READ_VIN value to check.
121082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
121182affd94SBrandon Wyman             .Times(1)
121282affd94SBrandon Wyman             .WillOnce(Return("201200"));
12130975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
12140975eaf4SMatt Spinler         {
12150975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
12160975eaf4SMatt Spinler         }
12173f1242f3SBrandon Wyman         psu.analyze();
1218c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
1219c2906f47SBrandon Wyman     }
1220f07bc797SBrandon Wyman     // STATUS_WORD with no bits on.
1221b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1222b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
122382affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
122482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
122582affd94SBrandon Wyman         .Times(1)
122682affd94SBrandon Wyman         .WillOnce(Return("201300"));
12270975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
12283f1242f3SBrandon Wyman     psu.analyze();
12293f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
12303f1242f3SBrandon Wyman }
12313f1242f3SBrandon Wyman 
12323f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasMFRFault)
12333f1242f3SBrandon Wyman {
12343f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1235681b2a36SB. J. Wyman 
1236c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1237c3324424SBrandon Wyman                     0x68, "ibm-cffps",      PSUGPIOLineName};
12383ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
12393ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1240681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1241681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
12423f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1243391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1244ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1245ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1246ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1247ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1248ae35ac5dSBrandon Wyman         .Times(1)
1249ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
1250f07bc797SBrandon Wyman     // First return STATUS_WORD with no bits on.
12518da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1252b654c619SBrandon Wyman     PMBusExpectations expectations;
1253b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
125482affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
125582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
125682affd94SBrandon Wyman         .Times(1)
125782affd94SBrandon Wyman         .WillOnce(Return("202100"));
12583f1242f3SBrandon Wyman     psu.analyze();
12593f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
1260f07bc797SBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
1261b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1262f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
1263b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
1264c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1265c2906f47SBrandon Wyman     {
1266b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
126782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
126882affd94SBrandon Wyman             .Times(1)
126982affd94SBrandon Wyman             .WillOnce(Return("202200"));
12703f1242f3SBrandon Wyman         psu.analyze();
1271c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1272c2906f47SBrandon Wyman     }
1273f07bc797SBrandon Wyman     // Back to no bits on in STATUS_WORD
1274b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1275b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
127682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
127782affd94SBrandon Wyman         .Times(1)
127882affd94SBrandon Wyman         .WillOnce(Return("202300"));
12793f1242f3SBrandon Wyman     psu.analyze();
12803f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
12813f1242f3SBrandon Wyman }
12823f1242f3SBrandon Wyman 
12833f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasVINUVFault)
12843f1242f3SBrandon Wyman {
12853f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1286681b2a36SB. J. Wyman 
1287c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1288c3324424SBrandon Wyman                     0x68, "ibm-cffps",      PSUGPIOLineName};
12893ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
12903ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1291681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1292681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
12933f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1294391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1295ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1296ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1297ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1298ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1299ae35ac5dSBrandon Wyman         .Times(1)
1300ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
130182affd94SBrandon Wyman 
130282affd94SBrandon Wyman     // Presence change from missing to present will trigger in1_input read in
130382affd94SBrandon Wyman     // an attempt to get CLEAR_FAULTS called. Return value ignored.
130482affd94SBrandon Wyman     // Zero to non-zero voltage, for missing/present change, triggers clear
130582affd94SBrandon Wyman     // faults call again. Return value ignored.
130682affd94SBrandon Wyman     // Fault (low voltage) to not faulted (voltage in range) triggers clear
130782affd94SBrandon Wyman     // faults call a third time.
130882affd94SBrandon Wyman 
13098da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1310b654c619SBrandon Wyman     PMBusExpectations expectations;
1311b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
131282affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
131382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
131482affd94SBrandon Wyman         .Times(1)
131582affd94SBrandon Wyman         .WillOnce(Return("201100"));
13163f1242f3SBrandon Wyman     psu.analyze();
13173f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
1318f07bc797SBrandon Wyman     // Turn fault on.
1319b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::VIN_UV_FAULT);
132085c7bf41SBrandon Wyman     // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
132185c7bf41SBrandon Wyman     // Figure 16, and assume bits on in STATUS_INPUT.
1322b654c619SBrandon Wyman     expectations.statusInputValue = 0x18;
1323c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1324c2906f47SBrandon Wyman     {
1325b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
132682affd94SBrandon Wyman         // If there is a VIN_UV fault, fake reading voltage of less than 20V
132782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
132882affd94SBrandon Wyman             .Times(1)
132982affd94SBrandon Wyman             .WillOnce(Return("19876"));
13300975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
13310975eaf4SMatt Spinler         {
13320975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
13330975eaf4SMatt Spinler         }
13343f1242f3SBrandon Wyman         psu.analyze();
1335c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1336c2906f47SBrandon Wyman     }
1337f07bc797SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1338b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1339b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
134082affd94SBrandon Wyman     // Updates now result in clearing faults if read voltage goes from below the
134182affd94SBrandon Wyman     // minimum, to within a valid range.
134282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
134382affd94SBrandon Wyman         .Times(1)
134482affd94SBrandon Wyman         .WillOnce(Return("201300"));
13453225a45cSBrandon Wyman     // Went from below minimum to within range, expect clearVinUVFault().
13463225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
13473225a45cSBrandon Wyman         .Times(1)
13483225a45cSBrandon Wyman         .WillOnce(Return(1));
13490975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
13503f1242f3SBrandon Wyman     psu.analyze();
13513f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
13523f1242f3SBrandon Wyman }
13536710ba2cSBrandon Wyman 
13546710ba2cSBrandon Wyman TEST_F(PowerSupplyTests, HasVoutOVFault)
13556710ba2cSBrandon Wyman {
13566710ba2cSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
13576710ba2cSBrandon Wyman 
1358c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1359c3324424SBrandon Wyman                     0x69, "ibm-cffps",      PSUGPIOLineName};
13606710ba2cSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
13616710ba2cSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
13626710ba2cSBrandon Wyman     // Always return 1 to indicate present.
13636710ba2cSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
13646710ba2cSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1365391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1366ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1367ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1368ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1369ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1370ae35ac5dSBrandon Wyman         .Times(1)
1371ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
13726710ba2cSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1373b654c619SBrandon Wyman     PMBusExpectations expectations;
1374b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
137582affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
137682affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
137782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
137882affd94SBrandon Wyman         .Times(1)
137982affd94SBrandon Wyman         .WillOnce(Return("202100"));
13806710ba2cSBrandon Wyman     psu.analyze();
13816710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
13826710ba2cSBrandon Wyman     // Turn fault on.
1383b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
13846710ba2cSBrandon Wyman     // STATUS_VOUT fault bit(s)
1385b654c619SBrandon Wyman     expectations.statusVOUTValue = 0x80;
1386c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1387c2906f47SBrandon Wyman     {
1388b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
138982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
139082affd94SBrandon Wyman             .Times(1)
139182affd94SBrandon Wyman             .WillOnce(Return("202200"));
13926710ba2cSBrandon Wyman         psu.analyze();
1393c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1394c2906f47SBrandon Wyman     }
13956710ba2cSBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1396b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1397b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
139882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
139982affd94SBrandon Wyman         .Times(1)
140082affd94SBrandon Wyman         .WillOnce(Return("202300"));
14016710ba2cSBrandon Wyman     psu.analyze();
14026710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
14036710ba2cSBrandon Wyman }
140496893a46SBrandon Wyman 
1405b10b3be0SBrandon Wyman TEST_F(PowerSupplyTests, HasIoutOCFault)
1406b10b3be0SBrandon Wyman {
1407b10b3be0SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1408b10b3be0SBrandon Wyman 
1409c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1410c3324424SBrandon Wyman                     0x6d, "ibm-cffps",      PSUGPIOLineName};
1411b10b3be0SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
1412b10b3be0SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1413b10b3be0SBrandon Wyman     // Always return 1 to indicate present.
1414b10b3be0SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1415b10b3be0SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1416391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1417ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1418ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1419ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1420ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1421ae35ac5dSBrandon Wyman         .Times(1)
1422ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
1423b10b3be0SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1424b10b3be0SBrandon Wyman     PMBusExpectations expectations;
1425b10b3be0SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
142682affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
142782affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
142882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
142982affd94SBrandon Wyman         .Times(1)
143082affd94SBrandon Wyman         .WillOnce(Return("203100"));
1431b10b3be0SBrandon Wyman     psu.analyze();
1432b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
1433b10b3be0SBrandon Wyman     // Turn fault on.
1434b10b3be0SBrandon Wyman     expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1435b10b3be0SBrandon Wyman     // STATUS_IOUT fault bit(s)
1436b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0x88;
1437c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1438c2906f47SBrandon Wyman     {
1439b10b3be0SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
144082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
144182affd94SBrandon Wyman             .Times(1)
144282affd94SBrandon Wyman             .WillOnce(Return("203200"));
14430975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
14440975eaf4SMatt Spinler         {
14450975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
14460975eaf4SMatt Spinler         }
1447b10b3be0SBrandon Wyman         psu.analyze();
1448c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1449c2906f47SBrandon Wyman     }
1450b10b3be0SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1451b10b3be0SBrandon Wyman     expectations.statusWordValue = 0;
1452b10b3be0SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
145382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
145482affd94SBrandon Wyman         .Times(1)
145582affd94SBrandon Wyman         .WillOnce(Return("203300"));
14560975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1457b10b3be0SBrandon Wyman     psu.analyze();
1458b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
1459b10b3be0SBrandon Wyman }
1460b10b3be0SBrandon Wyman 
14612cf46945SBrandon Wyman TEST_F(PowerSupplyTests, HasVoutUVFault)
14622cf46945SBrandon Wyman {
14632cf46945SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
14642cf46945SBrandon Wyman 
1465c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1466c3324424SBrandon Wyman                     0x6a, "ibm-cffps",      PSUGPIOLineName};
14672cf46945SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
14682cf46945SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
14692cf46945SBrandon Wyman     // Always return 1 to indicate present.
14702cf46945SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
14712cf46945SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1472391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1473ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1474ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1475ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1476ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1477ae35ac5dSBrandon Wyman         .Times(1)
1478ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
1479391a0690SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
14802cf46945SBrandon Wyman     PMBusExpectations expectations;
14812cf46945SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
148282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
148382affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
148482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
148582affd94SBrandon Wyman         .Times(1)
148682affd94SBrandon Wyman         .WillOnce(Return("204100"));
14872cf46945SBrandon Wyman     psu.analyze();
14882cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
14892cf46945SBrandon Wyman     // Turn fault on.
14902cf46945SBrandon Wyman     expectations.statusWordValue = (status_word::VOUT_FAULT);
14912cf46945SBrandon Wyman     // STATUS_VOUT fault bit(s)
14922cf46945SBrandon Wyman     expectations.statusVOUTValue = 0x30;
1493c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1494c2906f47SBrandon Wyman     {
14952cf46945SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
149682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
149782affd94SBrandon Wyman             .Times(1)
149882affd94SBrandon Wyman             .WillOnce(Return("204200"));
14992cf46945SBrandon Wyman         psu.analyze();
1500c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1501c2906f47SBrandon Wyman     }
15022cf46945SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
15032cf46945SBrandon Wyman     expectations.statusWordValue = 0;
15042cf46945SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
150582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
150682affd94SBrandon Wyman         .Times(1)
150782affd94SBrandon Wyman         .WillOnce(Return("204300"));
15082cf46945SBrandon Wyman     psu.analyze();
15092cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
15102cf46945SBrandon Wyman }
15112cf46945SBrandon Wyman 
15127ee4d7e4SBrandon Wyman TEST_F(PowerSupplyTests, HasFanFault)
15137ee4d7e4SBrandon Wyman {
15147ee4d7e4SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
15157ee4d7e4SBrandon Wyman 
15160975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
15170975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
15180975eaf4SMatt Spinler 
1519c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1520c3324424SBrandon Wyman                     0x6d, "ibm-cffps",      PSUGPIOLineName};
15217ee4d7e4SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
15227ee4d7e4SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
15237ee4d7e4SBrandon Wyman     // Always return 1 to indicate present.
15247ee4d7e4SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
15257ee4d7e4SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1526391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1527ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1528ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1529ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1530ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1531ae35ac5dSBrandon Wyman         .Times(1)
1532ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
15337ee4d7e4SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
15347ee4d7e4SBrandon Wyman     PMBusExpectations expectations;
15357ee4d7e4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
153682affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
153782affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
153882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
153982affd94SBrandon Wyman         .Times(1)
154082affd94SBrandon Wyman         .WillOnce(Return("205100"));
15417ee4d7e4SBrandon Wyman     psu.analyze();
15427ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
15437ee4d7e4SBrandon Wyman     // Turn fault on.
15447ee4d7e4SBrandon Wyman     expectations.statusWordValue = (status_word::FAN_FAULT);
15457ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
15467ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0x80;
1547c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1548c2906f47SBrandon Wyman     {
15497ee4d7e4SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
155082affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
155182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
155282affd94SBrandon Wyman             .Times(1)
155382affd94SBrandon Wyman             .WillOnce(Return("205200"));
15547ee4d7e4SBrandon Wyman         psu.analyze();
1555c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1556c2906f47SBrandon Wyman     }
15577ee4d7e4SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
15587ee4d7e4SBrandon Wyman     expectations.statusWordValue = 0;
15597ee4d7e4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
156082affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
156182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
156282affd94SBrandon Wyman         .Times(1)
156382affd94SBrandon Wyman         .WillOnce(Return("205300"));
15647ee4d7e4SBrandon Wyman     psu.analyze();
15657ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
15667ee4d7e4SBrandon Wyman }
15677ee4d7e4SBrandon Wyman 
156896893a46SBrandon Wyman TEST_F(PowerSupplyTests, HasTempFault)
156996893a46SBrandon Wyman {
157096893a46SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
157196893a46SBrandon Wyman 
15720975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
15730975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
15740975eaf4SMatt Spinler 
1575c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1576c3324424SBrandon Wyman                     0x6a, "ibm-cffps",      PSUGPIOLineName};
157796893a46SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
157896893a46SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
157996893a46SBrandon Wyman     // Always return 1 to indicate present.
158096893a46SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
158196893a46SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1582391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1583ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1584ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1585ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1586ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1587ae35ac5dSBrandon Wyman         .Times(1)
1588ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
158996893a46SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
159096893a46SBrandon Wyman     PMBusExpectations expectations;
159196893a46SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
159282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
159382affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
159482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
159582affd94SBrandon Wyman         .Times(1)
159682affd94SBrandon Wyman         .WillOnce(Return("206100"));
159796893a46SBrandon Wyman     psu.analyze();
159896893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
159996893a46SBrandon Wyman     // Turn fault on.
160096893a46SBrandon Wyman     expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
160196893a46SBrandon Wyman     // STATUS_TEMPERATURE fault bit on (OT Fault)
160296893a46SBrandon Wyman     expectations.statusTempValue = 0x80;
1603c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1604c2906f47SBrandon Wyman     {
160596893a46SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
160682affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
160782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
160882affd94SBrandon Wyman             .Times(1)
160982affd94SBrandon Wyman             .WillOnce(Return("206200"));
161096893a46SBrandon Wyman         psu.analyze();
1611c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1612c2906f47SBrandon Wyman     }
161396893a46SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
161496893a46SBrandon Wyman     expectations.statusWordValue = 0;
161596893a46SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
161682affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
161782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
161882affd94SBrandon Wyman         .Times(1)
161982affd94SBrandon Wyman         .WillOnce(Return("206300"));
162096893a46SBrandon Wyman     psu.analyze();
162196893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
162296893a46SBrandon Wyman }
16232916ea52SBrandon Wyman 
16242916ea52SBrandon Wyman TEST_F(PowerSupplyTests, HasPgoodFault)
16252916ea52SBrandon Wyman {
16262916ea52SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
16272916ea52SBrandon Wyman 
1628c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1629c3324424SBrandon Wyman                     0x6b, "ibm-cffps",      PSUGPIOLineName};
16302916ea52SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
16312916ea52SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
16322916ea52SBrandon Wyman     // Always return 1 to indicate present.
16332916ea52SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
16342916ea52SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1635391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1636ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1637ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1638ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1639ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1640ae35ac5dSBrandon Wyman         .Times(1)
1641ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
16422916ea52SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
16432916ea52SBrandon Wyman     PMBusExpectations expectations;
16442916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
164582affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
164682affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
164782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
164882affd94SBrandon Wyman         .Times(1)
164982affd94SBrandon Wyman         .WillOnce(Return("207100"));
16502916ea52SBrandon Wyman     psu.analyze();
16512916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
1652391a0690SBrandon Wyman     // Setup another expectation of no faults.
1653391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
165482affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
165582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
165682affd94SBrandon Wyman         .Times(1)
165782affd94SBrandon Wyman         .WillOnce(Return("207200"));
165882affd94SBrandon Wyman     psu.analyze();
165982affd94SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
166082affd94SBrandon Wyman     // Setup another expectation of no faults.
166182affd94SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
166282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
166382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
166482affd94SBrandon Wyman         .Times(1)
166582affd94SBrandon Wyman         .WillOnce(Return("207300"));
1666391a0690SBrandon Wyman     psu.analyze();
1667391a0690SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
16682916ea52SBrandon Wyman     // Turn PGOOD# off (fault on).
16692916ea52SBrandon Wyman     expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
16702916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
167182affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
167282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
167382affd94SBrandon Wyman         .Times(1)
167482affd94SBrandon Wyman         .WillOnce(Return("207400"));
16752916ea52SBrandon Wyman     psu.analyze();
1676*6d469fd4SBrandon Wyman     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 1
167706ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
167806ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
167982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
168082affd94SBrandon Wyman         .Times(1)
168182affd94SBrandon Wyman         .WillOnce(Return("207500"));
168206ca4590SBrandon Wyman     psu.analyze();
1683*6d469fd4SBrandon Wyman     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 2
168406ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
168506ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
168682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
168782affd94SBrandon Wyman         .Times(1)
168882affd94SBrandon Wyman         .WillOnce(Return("207600"));
168906ca4590SBrandon Wyman     psu.analyze();
1690*6d469fd4SBrandon Wyman     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 3
1691*6d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
1692*6d469fd4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
1693*6d469fd4SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1694*6d469fd4SBrandon Wyman         .Times(1)
1695*6d469fd4SBrandon Wyman         .WillOnce(Return("207700"));
1696*6d469fd4SBrandon Wyman     psu.analyze();
1697*6d469fd4SBrandon Wyman     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 4
1698*6d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
1699*6d469fd4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
1700*6d469fd4SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1701*6d469fd4SBrandon Wyman         .Times(1)
1702*6d469fd4SBrandon Wyman         .WillOnce(Return("207800"));
1703*6d469fd4SBrandon Wyman     psu.analyze();
1704*6d469fd4SBrandon Wyman     // Expect true. PGOOD_DEGLITCH_LIMIT @ 5
17052916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
17062916ea52SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
17072916ea52SBrandon Wyman     expectations.statusWordValue = 0;
17082916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
170982affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
171082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
171182affd94SBrandon Wyman         .Times(1)
171282affd94SBrandon Wyman         .WillOnce(Return("207700"));
17132916ea52SBrandon Wyman     psu.analyze();
17142916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
171582affd94SBrandon Wyman 
17162916ea52SBrandon Wyman     // Turn OFF bit on
17172916ea52SBrandon Wyman     expectations.statusWordValue = (status_word::UNIT_IS_OFF);
17182916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
171982affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
172082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
172182affd94SBrandon Wyman         .Times(1)
172282affd94SBrandon Wyman         .WillOnce(Return("208100"));
17232916ea52SBrandon Wyman     psu.analyze();
172406ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
172506ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
172682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
172782affd94SBrandon Wyman         .Times(1)
172882affd94SBrandon Wyman         .WillOnce(Return("208200"));
172906ca4590SBrandon Wyman     psu.analyze();
173006ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
173106ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
173282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
173382affd94SBrandon Wyman         .Times(1)
173482affd94SBrandon Wyman         .WillOnce(Return("208300"));
173506ca4590SBrandon Wyman     psu.analyze();
1736*6d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
1737*6d469fd4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
1738*6d469fd4SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1739*6d469fd4SBrandon Wyman         .Times(1)
1740*6d469fd4SBrandon Wyman         .WillOnce(Return("208400"));
1741*6d469fd4SBrandon Wyman     psu.analyze();
1742*6d469fd4SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
1743*6d469fd4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
1744*6d469fd4SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1745*6d469fd4SBrandon Wyman         .Times(1)
1746*6d469fd4SBrandon Wyman         .WillOnce(Return("208500"));
1747*6d469fd4SBrandon Wyman     psu.analyze();
17482916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
17492916ea52SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
17502916ea52SBrandon Wyman     expectations.statusWordValue = 0;
17512916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
175282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
175382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
175482affd94SBrandon Wyman         .Times(1)
1755*6d469fd4SBrandon Wyman         .WillOnce(Return("208000"));
17562916ea52SBrandon Wyman     psu.analyze();
17572916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
17582916ea52SBrandon Wyman }
175939ea02bcSBrandon Wyman 
176039ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPSKillFault)
176139ea02bcSBrandon Wyman {
176239ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1763c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 4,
1764c3324424SBrandon Wyman                     0x6d, "ibm-cffps",      PSUGPIOLineName};
176539ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
176639ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
176739ea02bcSBrandon Wyman     // Always return 1 to indicate present.
176839ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
176939ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
177082affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1771ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1772ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1773ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1774ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1775ae35ac5dSBrandon Wyman         .Times(1)
1776ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
177739ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
177839ea02bcSBrandon Wyman     PMBusExpectations expectations;
177939ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
178082affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
178182affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
178282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
178382affd94SBrandon Wyman         .Times(1)
178482affd94SBrandon Wyman         .WillOnce(Return("208100"));
178539ea02bcSBrandon Wyman     psu.analyze();
178639ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
178739ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
178839ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
178939ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
179039ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1791c2906f47SBrandon Wyman 
1792c2906f47SBrandon Wyman     // Deglitching faults, false until read the fault bits on up to the limit.
1793c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1794c2906f47SBrandon Wyman     {
179539ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
179682affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
179782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
179882affd94SBrandon Wyman             .Times(1)
179982affd94SBrandon Wyman             .WillOnce(Return("208200"));
18000975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
18010975eaf4SMatt Spinler         {
18020975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
18030975eaf4SMatt Spinler         }
180439ea02bcSBrandon Wyman         psu.analyze();
1805c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1806c2906f47SBrandon Wyman     }
1807c2906f47SBrandon Wyman 
180839ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
180939ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
181039ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
181182affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
181282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
181382affd94SBrandon Wyman         .Times(1)
181482affd94SBrandon Wyman         .WillOnce(Return("208300"));
18150975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
181639ea02bcSBrandon Wyman     psu.analyze();
181739ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
181839ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
181939ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
182039ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 4 on.
182139ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x10;
1822c2906f47SBrandon Wyman 
1823c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1824c2906f47SBrandon Wyman     {
182539ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
182682affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
182782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
182882affd94SBrandon Wyman             .Times(1)
182982affd94SBrandon Wyman             .WillOnce(Return("208400"));
18300975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
18310975eaf4SMatt Spinler         {
18320975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
18330975eaf4SMatt Spinler         }
183439ea02bcSBrandon Wyman         psu.analyze();
1835c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1836c2906f47SBrandon Wyman     }
1837c2906f47SBrandon Wyman 
183839ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
183939ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
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("208500"));
18450975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
184639ea02bcSBrandon Wyman     psu.analyze();
184739ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
184839ea02bcSBrandon Wyman }
184939ea02bcSBrandon Wyman 
185039ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPS12VcsFault)
185139ea02bcSBrandon Wyman {
185239ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1853c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 5,
1854c3324424SBrandon Wyman                     0x6e, "ibm-cffps",      PSUGPIOLineName};
185539ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
185639ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
185739ea02bcSBrandon Wyman     // Always return 1 to indicate present.
185839ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
185939ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
186082affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1861ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1862ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1863ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1864ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1865ae35ac5dSBrandon Wyman         .Times(1)
1866ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
186739ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
186839ea02bcSBrandon Wyman     PMBusExpectations expectations;
186939ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
187082affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
187182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
187282affd94SBrandon Wyman         .Times(1)
187382affd94SBrandon Wyman         .WillOnce(Return("209100"));
187439ea02bcSBrandon Wyman     psu.analyze();
187539ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
187639ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
187739ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
187839ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
187939ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1880c2906f47SBrandon Wyman 
1881c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1882c2906f47SBrandon Wyman     {
188339ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
188482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
188582affd94SBrandon Wyman             .Times(1)
188682affd94SBrandon Wyman             .WillOnce(Return("209200"));
188739ea02bcSBrandon Wyman         psu.analyze();
1888c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1889c2906f47SBrandon Wyman     }
1890c2906f47SBrandon Wyman 
189139ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
189239ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
189339ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
189482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
189582affd94SBrandon Wyman         .Times(1)
189682affd94SBrandon Wyman         .WillOnce(Return("209300"));
189739ea02bcSBrandon Wyman     psu.analyze();
189839ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
189939ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
190039ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
190139ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 6 on.
190239ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x40;
1903c2906f47SBrandon Wyman 
1904c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1905c2906f47SBrandon Wyman     {
190639ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
190782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
190882affd94SBrandon Wyman             .Times(1)
190982affd94SBrandon Wyman             .WillOnce(Return("209400"));
191039ea02bcSBrandon Wyman         psu.analyze();
1911c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1912c2906f47SBrandon Wyman     }
1913c2906f47SBrandon Wyman 
191439ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
191539ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
191639ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
191782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
191882affd94SBrandon Wyman         .Times(1)
191982affd94SBrandon Wyman         .WillOnce(Return("209500"));
192039ea02bcSBrandon Wyman     psu.analyze();
192139ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
192239ea02bcSBrandon Wyman }
192339ea02bcSBrandon Wyman 
192439ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPSCS12VFault)
192539ea02bcSBrandon Wyman {
192639ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1927c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 6,
1928c3324424SBrandon Wyman                     0x6f, "ibm-cffps",      PSUGPIOLineName};
192939ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
193039ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
193139ea02bcSBrandon Wyman     // Always return 1 to indicate present.
193239ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
193339ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
193482affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1935ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1936ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
1937ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
1938ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1939ae35ac5dSBrandon Wyman         .Times(1)
1940ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
194139ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
194239ea02bcSBrandon Wyman     PMBusExpectations expectations;
194339ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
194482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
194582affd94SBrandon Wyman         .Times(1)
194682affd94SBrandon Wyman         .WillOnce(Return("209100"));
194739ea02bcSBrandon Wyman     psu.analyze();
194839ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
194939ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
195039ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
195139ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
195239ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1953c2906f47SBrandon Wyman 
1954c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1955c2906f47SBrandon Wyman     {
195639ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
195782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
195882affd94SBrandon Wyman             .Times(1)
195982affd94SBrandon Wyman             .WillOnce(Return("209200"));
196039ea02bcSBrandon Wyman         psu.analyze();
1961c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1962c2906f47SBrandon Wyman     }
1963c2906f47SBrandon Wyman 
196439ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
196539ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
196639ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
196782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
196882affd94SBrandon Wyman         .Times(1)
196982affd94SBrandon Wyman         .WillOnce(Return("209300"));
197039ea02bcSBrandon Wyman     psu.analyze();
197139ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
197239ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
197339ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
197439ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 7 on.
197539ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x80;
1976c2906f47SBrandon Wyman 
1977c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1978c2906f47SBrandon Wyman     {
197939ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
198082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
198182affd94SBrandon Wyman             .Times(1)
198282affd94SBrandon Wyman             .WillOnce(Return("209400"));
198339ea02bcSBrandon Wyman         psu.analyze();
1984c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1985c2906f47SBrandon Wyman     }
1986c2906f47SBrandon Wyman 
198739ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
198839ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
198939ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
199082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
199182affd94SBrandon Wyman         .Times(1)
199282affd94SBrandon Wyman         .WillOnce(Return("209500"));
199339ea02bcSBrandon Wyman     psu.analyze();
199439ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
199539ea02bcSBrandon Wyman }
1996c3324424SBrandon Wyman 
1997c3324424SBrandon Wyman TEST_F(PowerSupplyTests, SetupInputHistory)
1998c3324424SBrandon Wyman {
1999c3324424SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
2000c3324424SBrandon Wyman     {
2001c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 6,
2002c3324424SBrandon Wyman                         0x6f, "ibm-cffps",      PSUGPIOLineName};
2003c3324424SBrandon Wyman         // Defaults to not present due to constructor and mock ordering.
2004c3324424SBrandon Wyman         psu.setupInputHistory();
2005c3324424SBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
2006c3324424SBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
2007c3324424SBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2008ae35ac5dSBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2009c3324424SBrandon Wyman         // Always return 1 to indicate present.
2010c3324424SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2011ae35ac5dSBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
2012ae35ac5dSBrandon Wyman         PMBusExpectations expectations;
2013ae35ac5dSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
2014ae35ac5dSBrandon Wyman         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
2015ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2016ae35ac5dSBrandon Wyman             .Times(1)
2017ae35ac5dSBrandon Wyman             .WillOnce(Return("206000"));
2018ae35ac5dSBrandon Wyman         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2019ae35ac5dSBrandon Wyman         // for INPUT_HISTORY will check max_power_out to see if it is
2020ae35ac5dSBrandon Wyman         // old/unsupported power supply. Indicate good value, supported.
2021ae35ac5dSBrandon Wyman         /// Also called when I redo setupInputHistory().
2022ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2023ae35ac5dSBrandon Wyman             .Times(2)
2024ae35ac5dSBrandon Wyman             .WillRepeatedly(Return("2000"));
2025ae35ac5dSBrandon Wyman         // Call to analyze() and above expectations to get missing/present and
2026ae35ac5dSBrandon Wyman         // good status.
2027c3324424SBrandon Wyman         psu.analyze();
2028c3324424SBrandon Wyman         psu.setupInputHistory();
2029c3324424SBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), true);
2030c3324424SBrandon Wyman     }
2031c3324424SBrandon Wyman     {
2032ae35ac5dSBrandon Wyman         // Workaround - Disable INPUT_HISTORY collection if 1400W
2033ae35ac5dSBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 3,
2034ae35ac5dSBrandon Wyman                         0x68, "ibm-cffps",      PSUGPIOLineName};
2035ae35ac5dSBrandon Wyman         // Defaults to not present due to constructor and mock ordering.
2036ae35ac5dSBrandon Wyman         psu.setupInputHistory();
2037ae35ac5dSBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
2038ae35ac5dSBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
2039ae35ac5dSBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2040ae35ac5dSBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2041ae35ac5dSBrandon Wyman         // Always return 1 to indicate present.
2042ae35ac5dSBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2043ae35ac5dSBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
2044ae35ac5dSBrandon Wyman         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2045ae35ac5dSBrandon Wyman         // for INPUT_HISTORY will check max_power_out to see if it is
2046ae35ac5dSBrandon Wyman         // old/unsupported power supply. Indicate 1400W IBM value, unsupported.
2047ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2048ae35ac5dSBrandon Wyman             .Times(2)
2049ae35ac5dSBrandon Wyman             .WillRepeatedly(Return("30725"));
2050ae35ac5dSBrandon Wyman         PMBusExpectations expectations;
2051ae35ac5dSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
2052ae35ac5dSBrandon Wyman         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
2053ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2054ae35ac5dSBrandon Wyman             .Times(1)
2055ae35ac5dSBrandon Wyman             .WillOnce(Return("206000"));
2056ae35ac5dSBrandon Wyman         // Call to analyze() and above expectations to get missing/present and
2057ae35ac5dSBrandon Wyman         // good status.
2058ae35ac5dSBrandon Wyman         psu.analyze();
2059ae35ac5dSBrandon Wyman         psu.setupInputHistory();
2060ae35ac5dSBrandon Wyman         // After updating to present, and retrying setup, expect ibm-cffps with
2061ae35ac5dSBrandon Wyman         // 1400W to still not support INPUT_HISTORY.
2062ae35ac5dSBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
2063ae35ac5dSBrandon Wyman     }
2064ae35ac5dSBrandon Wyman     {
2065c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 11,
2066c3324424SBrandon Wyman                         0x58, "inspur-ipsps",   PSUGPIOLineName};
2067c3324424SBrandon Wyman         // Defaults to not present due to constructor and mock ordering.
2068c3324424SBrandon Wyman         psu.setupInputHistory();
2069c3324424SBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
2070c3324424SBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
2071c3324424SBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2072ae35ac5dSBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2073c3324424SBrandon Wyman         // Always return 1 to indicate present.
2074c3324424SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2075ae35ac5dSBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
2076ae35ac5dSBrandon Wyman         PMBusExpectations expectations;
2077ae35ac5dSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
2078ae35ac5dSBrandon Wyman         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
2079ae35ac5dSBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2080ae35ac5dSBrandon Wyman             .Times(1)
2081ae35ac5dSBrandon Wyman             .WillOnce(Return("206000"));
2082ae35ac5dSBrandon Wyman         // Call to analyze() and above expectations to get missing/present and
2083ae35ac5dSBrandon Wyman         // good status.
2084c3324424SBrandon Wyman         psu.analyze();
2085c3324424SBrandon Wyman         psu.setupInputHistory();
2086c3324424SBrandon Wyman         // After updating to present, and retrying setup, expect inspur-ipsps to
2087c3324424SBrandon Wyman         // still not support INPUT_HISTORY.
2088c3324424SBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
2089c3324424SBrandon Wyman     }
2090c3324424SBrandon Wyman }
2091c3324424SBrandon Wyman 
2092c3324424SBrandon Wyman TEST_F(PowerSupplyTests, UpdateHistory)
2093c3324424SBrandon Wyman {
2094c3324424SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
2095c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 7,
2096c3324424SBrandon Wyman                     0x6e, "ibm-cffps",      PSUGPIOLineName};
2097c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), false);
2098c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
2099c3324424SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
2100c3324424SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2101c3324424SBrandon Wyman     // Always return 1 to indicate present.
2102c3324424SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2103c3324424SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2104c3324424SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
2105ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2106ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
2107ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
2108ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2109ae35ac5dSBrandon Wyman         .Times(1)
2110ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
2111c3324424SBrandon Wyman     PMBusExpectations expectations;
2112c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2113c3324424SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2114c3324424SBrandon Wyman         .Times(6)
2115c3324424SBrandon Wyman         .WillRepeatedly(Return("205000"));
2116c3324424SBrandon Wyman     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
2117c3324424SBrandon Wyman     // First read after missing/present will have no data.
2118c3324424SBrandon Wyman     std::vector<uint8_t> emptyHistory{};
2119c3324424SBrandon Wyman     // Second read, after about 30 seconds, should have a record. 5-bytes.
2120c3324424SBrandon Wyman     // Sequence Number: 0x00, Average: 0x50 0xf3 (212), Maximum: 0x54 0xf3 (213)
2121c3324424SBrandon Wyman     std::vector<uint8_t> firstHistory{0x00, 0x50, 0xf3, 0x54, 0xf3};
2122c3324424SBrandon Wyman     // Third read, after about 60 seconds, should have two records, 10-bytes,
2123c3324424SBrandon Wyman     // but only reading 5 bytes, so make sure new/next sequence number
2124c3324424SBrandon Wyman     std::vector<uint8_t> secondHistory{0x01, 0x54, 0xf3, 0x58, 0xf3};
2125c3324424SBrandon Wyman     // Fourth read, 3rd sequence number (0x02).
2126c3324424SBrandon Wyman     std::vector<uint8_t> thirdHistory{0x02, 0x54, 0xf3, 0x58, 0xf3};
2127c3324424SBrandon Wyman     // Fifth read, out of sequence, clear and insert this one?
2128c3324424SBrandon Wyman     std::vector<uint8_t> outseqHistory{0xff, 0x5c, 0xf3, 0x60, 0xf3};
2129c3324424SBrandon Wyman     EXPECT_CALL(
2130c3324424SBrandon Wyman         mockPMBus,
2131c3324424SBrandon Wyman         readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug,
2132c3324424SBrandon Wyman                    phosphor::power::history::RecordManager::RAW_RECORD_SIZE))
2133c3324424SBrandon Wyman         .Times(6)
2134c3324424SBrandon Wyman         .WillOnce(Return(emptyHistory))
2135c3324424SBrandon Wyman         .WillOnce(Return(firstHistory))
2136c3324424SBrandon Wyman         .WillOnce(Return(secondHistory))
2137c3324424SBrandon Wyman         .WillOnce(Return(thirdHistory))
2138c3324424SBrandon Wyman         .WillOnce(Return(outseqHistory))
2139c3324424SBrandon Wyman         .WillOnce(Return(emptyHistory));
2140c3324424SBrandon Wyman     // Calling analyze will update the presence, which will setup the input
2141c3324424SBrandon Wyman     // history if the power supply went from missing to present.
2142c3324424SBrandon Wyman     psu.analyze();
2143c3324424SBrandon Wyman     // The ibm-cffps power supply should support input history
2144c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2145c3324424SBrandon Wyman     // Usually should have empty buffer right after missing to present.
2146c3324424SBrandon Wyman     // Faked that out above with mocked readBinary with emptyHistory data.
2147c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
2148c3324424SBrandon Wyman     // Second run through...
2149c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2150c3324424SBrandon Wyman     psu.analyze();
2151c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2152c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 1);
2153c3324424SBrandon Wyman     // Third run through
2154c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2155c3324424SBrandon Wyman     psu.analyze();
2156c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2157c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 2);
2158c3324424SBrandon Wyman     // Fourth run through. Up to 3 records now?
2159c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2160c3324424SBrandon Wyman     psu.analyze();
2161c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2162c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 3);
2163c3324424SBrandon Wyman     // Out of sequencer, reset, insert new one.
2164c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2165c3324424SBrandon Wyman     psu.analyze();
2166c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2167c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 1);
2168c3324424SBrandon Wyman     // Empty one after last one good. Reset/clear.
2169c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
2170c3324424SBrandon Wyman     psu.analyze();
2171c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
2172c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
2173c3324424SBrandon Wyman }
217418a24d92SBrandon Wyman 
217518a24d92SBrandon Wyman TEST_F(PowerSupplyTests, IsSyncHistoryRequired)
217618a24d92SBrandon Wyman {
217718a24d92SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
217818a24d92SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 8,
217918a24d92SBrandon Wyman                     0x6f, "ibm-cffps",      PSUGPIOLineName};
218018a24d92SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), false);
218118a24d92SBrandon Wyman     EXPECT_EQ(psu.isSyncHistoryRequired(), false);
218218a24d92SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
218318a24d92SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
218418a24d92SBrandon Wyman     // Always return 1 to indicate present.
218518a24d92SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
218618a24d92SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
218718a24d92SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
2188ae35ac5dSBrandon Wyman     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2189ae35ac5dSBrandon Wyman     // for INPUT_HISTORY will check max_power_out to see if it is
2190ae35ac5dSBrandon Wyman     // old/unsupported power supply. Indicate good value, supported.
2191ae35ac5dSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2192ae35ac5dSBrandon Wyman         .Times(1)
2193ae35ac5dSBrandon Wyman         .WillOnce(Return("2000"));
219418a24d92SBrandon Wyman     PMBusExpectations expectations;
219518a24d92SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
219618a24d92SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
219718a24d92SBrandon Wyman         .Times(1)
219818a24d92SBrandon Wyman         .WillRepeatedly(Return("205000"));
219918a24d92SBrandon Wyman     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
220018a24d92SBrandon Wyman     psu.analyze();
220118a24d92SBrandon Wyman     // The ibm-cffps power supply should support input history
220218a24d92SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
220318a24d92SBrandon Wyman     // Missing -> Present requires history sync
220418a24d92SBrandon Wyman     EXPECT_EQ(psu.isSyncHistoryRequired(), true);
220518a24d92SBrandon Wyman     psu.clearSyncHistoryRequired();
220618a24d92SBrandon Wyman     EXPECT_EQ(psu.isSyncHistoryRequired(), false);
220718a24d92SBrandon Wyman }
2208