13f1242f3SBrandon Wyman #include "../power_supply.hpp"
2*c3324424SBrandon 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     {
136*c3324424SBrandon Wyman         auto psu = std::make_unique<PowerSupply>(bus, "", 3, 0x68, "ibm-cffps",
137*c3324424SBrandon 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     {
154*c3324424SBrandon Wyman         auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
155*c3324424SBrandon 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,
173*c3324424SBrandon 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 
221*c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 4,
222*c3324424SBrandon 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 
246*c3324424SBrandon Wyman     PowerSupply psu2{bus,  PSUInventoryPath, 5,
247*c3324424SBrandon 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);
259b654c619SBrandon Wyman 
260b654c619SBrandon Wyman     // STATUS_WORD INPUT fault.
261b654c619SBrandon Wyman     {
262b654c619SBrandon Wyman         // Start with STATUS_WORD 0x0000. Powered on, no faults.
263b654c619SBrandon Wyman         // Set expectations for a no fault
264b654c619SBrandon Wyman         PMBusExpectations expectations;
265b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
26682affd94SBrandon Wyman         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
26782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
26882affd94SBrandon Wyman             .Times(1)
26982affd94SBrandon Wyman             .WillOnce(Return("206000"));
2703f1242f3SBrandon Wyman         psu2.analyze();
2713f1242f3SBrandon Wyman         EXPECT_EQ(psu2.isPresent(), true);
2723f1242f3SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
2733f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
2743f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasMFRFault(), false);
2753f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasVINUVFault(), false);
27685c7bf41SBrandon Wyman         EXPECT_EQ(psu2.hasCommFault(), false);
2776710ba2cSBrandon Wyman         EXPECT_EQ(psu2.hasVoutOVFault(), false);
278b10b3be0SBrandon Wyman         EXPECT_EQ(psu2.hasIoutOCFault(), false);
2792cf46945SBrandon Wyman         EXPECT_EQ(psu2.hasVoutUVFault(), false);
2807ee4d7e4SBrandon Wyman         EXPECT_EQ(psu2.hasFanFault(), false);
28196893a46SBrandon Wyman         EXPECT_EQ(psu2.hasTempFault(), false);
2822916ea52SBrandon Wyman         EXPECT_EQ(psu2.hasPgoodFault(), false);
28339ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPSKillFault(), false);
28439ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPS12VcsFault(), false);
28539ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPSCS12VFault(), false);
2863f1242f3SBrandon Wyman 
287b654c619SBrandon Wyman         // Update expectations for STATUS_WORD input fault/warn
28896893a46SBrandon Wyman         // STATUS_INPUT fault bits ... on.
289b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
2903225a45cSBrandon Wyman         // IIN_OC fault.
2913225a45cSBrandon Wyman         expectations.statusInputValue = 0x04;
292c2906f47SBrandon Wyman 
293c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
294c2906f47SBrandon Wyman         {
295b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
29682affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
29782affd94SBrandon Wyman                 .Times(1)
29882affd94SBrandon Wyman                 .WillOnce(Return("207000"));
2993f1242f3SBrandon Wyman             psu2.analyze();
3003f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
301c2906f47SBrandon Wyman             // Should not be faulted until it reaches the deglitch limit.
302c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
303c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
3043f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
3053f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
30685c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
3076710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
308b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
3092cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
3107ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
31196893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
3122916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
31339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
31439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
31539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
316b654c619SBrandon Wyman         }
317c2906f47SBrandon Wyman     }
318c2906f47SBrandon Wyman 
31932453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
3203225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
3213225a45cSBrandon Wyman         .Times(1)
3223225a45cSBrandon Wyman         .WillOnce(Return(1));
323c2906f47SBrandon Wyman     psu2.clearFaults();
3243f1242f3SBrandon Wyman 
3253f1242f3SBrandon Wyman     // STATUS_WORD INPUT/UV fault.
326b654c619SBrandon Wyman     {
3273f1242f3SBrandon Wyman         // First need it to return good status, then the fault
328b654c619SBrandon Wyman         PMBusExpectations expectations;
329b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
33082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
33182affd94SBrandon Wyman             .Times(1)
33282affd94SBrandon Wyman             .WillOnce(Return("208000"));
3333f1242f3SBrandon Wyman         psu2.analyze();
334c2906f47SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
335c2906f47SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
3368da35c51SBrandon Wyman         // Now set fault bits in STATUS_WORD
337b654c619SBrandon Wyman         expectations.statusWordValue =
3388da35c51SBrandon Wyman             (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
3398da35c51SBrandon Wyman         // STATUS_INPUT fault bits ... on.
3403225a45cSBrandon Wyman         expectations.statusInputValue = 0x18;
341c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
342c2906f47SBrandon Wyman         {
343b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
34482affd94SBrandon Wyman             // Input/UV fault, so voltage should read back low.
34582affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
34682affd94SBrandon Wyman                 .Times(1)
34782affd94SBrandon Wyman                 .WillOnce(Return("19123"));
3483f1242f3SBrandon Wyman             psu2.analyze();
3493f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
350c2906f47SBrandon Wyman             // Only faulted if hit deglitch limit
351c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
352c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
353c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), x >= DEGLITCH_LIMIT);
3543f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
35585c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
3566710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
357b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
3582cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
3597ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
36096893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
3612916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
36239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
36339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
36439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
365c2906f47SBrandon Wyman         }
36682affd94SBrandon Wyman         // Turning VIN_UV fault off causes clearing of faults, causing read of
36782affd94SBrandon Wyman         // in1_input as an attempt to get CLEAR_FAULTS called.
36882affd94SBrandon Wyman         expectations.statusWordValue = 0;
36982affd94SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
37082affd94SBrandon Wyman         // The call to read the voltage
37182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
37282affd94SBrandon Wyman             .Times(1)
37382affd94SBrandon Wyman             .WillOnce(Return("209000"));
3743225a45cSBrandon Wyman         // The call to clear VIN_UV/Off fault(s)
3753225a45cSBrandon Wyman         EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
37632453e9bSBrandon Wyman             .Times(1)
3773225a45cSBrandon Wyman             .WillOnce(Return(1));
37882affd94SBrandon Wyman         psu2.analyze();
37982affd94SBrandon Wyman         // Should remain present, no longer be faulted, no input fault, no
38082affd94SBrandon Wyman         // VIN_UV fault. Nothing else should change.
38182affd94SBrandon Wyman         EXPECT_EQ(psu2.isPresent(), true);
38282affd94SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
38382affd94SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
38482affd94SBrandon Wyman         EXPECT_EQ(psu2.hasVINUVFault(), false);
385b654c619SBrandon Wyman     }
3863f1242f3SBrandon Wyman 
38732453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
3883225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
3893225a45cSBrandon Wyman         .Times(1)
3903225a45cSBrandon Wyman         .WillOnce(Return(1));
391c2906f47SBrandon Wyman     psu2.clearFaults();
392c2906f47SBrandon Wyman 
3933f1242f3SBrandon Wyman     // STATUS_WORD MFR fault.
394b654c619SBrandon Wyman     {
395f07bc797SBrandon Wyman         // First need it to return good status, then the fault
396b654c619SBrandon Wyman         PMBusExpectations expectations;
397b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
39882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
39982affd94SBrandon Wyman             .Times(1)
40082affd94SBrandon Wyman             .WillOnce(Return("210000"));
4013f1242f3SBrandon Wyman         psu2.analyze();
4028da35c51SBrandon Wyman         // Now STATUS_WORD with MFR fault bit on.
403b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
4048da35c51SBrandon Wyman         // STATUS_MFR bits on.
405b654c619SBrandon Wyman         expectations.statusMFRValue = 0xFF;
406c2906f47SBrandon Wyman 
407c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
408c2906f47SBrandon Wyman         {
409b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
41082affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
41182affd94SBrandon Wyman                 .Times(1)
41282affd94SBrandon Wyman                 .WillOnce(Return("211000"));
4133f1242f3SBrandon Wyman             psu2.analyze();
4143f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
415c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
4163f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
417c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT);
418c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT);
419c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
420c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
4213f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
42285c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
4236710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
424b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
4252cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
4267ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
42796893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
4282916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
429c2906f47SBrandon Wyman         }
430b654c619SBrandon Wyman     }
4313f1242f3SBrandon Wyman 
43232453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
4333225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
4343225a45cSBrandon Wyman         .Times(1)
4353225a45cSBrandon Wyman         .WillOnce(Return(1));
436c2906f47SBrandon Wyman     psu2.clearFaults();
4373225a45cSBrandon Wyman 
43896893a46SBrandon Wyman     // Temperature fault.
439b654c619SBrandon Wyman     {
440f07bc797SBrandon Wyman         // First STATUS_WORD with no bits set, then with temperature fault.
441b654c619SBrandon Wyman         PMBusExpectations expectations;
442b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
44382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
44482affd94SBrandon Wyman             .Times(1)
44582affd94SBrandon Wyman             .WillOnce(Return("212000"));
4463f1242f3SBrandon Wyman         psu2.analyze();
4478da35c51SBrandon Wyman         // STATUS_WORD with temperature fault bit on.
448b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
44996893a46SBrandon Wyman         // STATUS_TEMPERATURE with fault bit(s) on.
45096893a46SBrandon Wyman         expectations.statusTempValue = 0x10;
451c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
452c2906f47SBrandon Wyman         {
453b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
45482affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
45582affd94SBrandon Wyman                 .Times(1)
45682affd94SBrandon Wyman                 .WillOnce(Return("213000"));
4573f1242f3SBrandon Wyman             psu2.analyze();
4583f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
459c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
4603f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
4613f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
4623f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
46385c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
4646710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
465b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
4662cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
4677ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
468c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT);
4692916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
47039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
47139ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
47239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
473b654c619SBrandon Wyman         }
474c2906f47SBrandon Wyman     }
47585c7bf41SBrandon Wyman 
47632453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
4773225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
4783225a45cSBrandon Wyman         .Times(1)
4793225a45cSBrandon Wyman         .WillOnce(Return(1));
480c2906f47SBrandon Wyman     psu2.clearFaults();
4813225a45cSBrandon Wyman 
48285c7bf41SBrandon Wyman     // CML fault
483b654c619SBrandon Wyman     {
48485c7bf41SBrandon Wyman         // First STATUS_WORD wit no bits set, then with CML fault.
485b654c619SBrandon Wyman         PMBusExpectations expectations;
486b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
48782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
48882affd94SBrandon Wyman             .Times(1)
48982affd94SBrandon Wyman             .WillOnce(Return("214000"));
49085c7bf41SBrandon Wyman         psu2.analyze();
4918da35c51SBrandon Wyman         // STATUS_WORD with CML fault bit on.
492b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::CML_FAULT);
49385c7bf41SBrandon Wyman         // Turn on STATUS_CML fault bit(s)
494b654c619SBrandon Wyman         expectations.statusCMLValue = 0xFF;
495c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
496c2906f47SBrandon Wyman         {
497b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
49882affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
49982affd94SBrandon Wyman                 .Times(1)
50082affd94SBrandon Wyman                 .WillOnce(Return("215000"));
50185c7bf41SBrandon Wyman             psu2.analyze();
50285c7bf41SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
503c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
504c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), x >= DEGLITCH_LIMIT);
50585c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
50685c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
50785c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
5086710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
509b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
5102cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
5117ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
51296893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
5132916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
51439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
51539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
51639ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
517b654c619SBrandon Wyman         }
518c2906f47SBrandon Wyman     }
5196710ba2cSBrandon Wyman 
52032453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
5213225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
5223225a45cSBrandon Wyman         .Times(1)
5233225a45cSBrandon Wyman         .WillOnce(Return(1));
524c2906f47SBrandon Wyman     psu2.clearFaults();
5253225a45cSBrandon Wyman 
5266710ba2cSBrandon Wyman     // VOUT_OV_FAULT fault
527b654c619SBrandon Wyman     {
5286710ba2cSBrandon Wyman         // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
529b654c619SBrandon Wyman         PMBusExpectations expectations;
530b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
53182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
53282affd94SBrandon Wyman             .Times(1)
53382affd94SBrandon Wyman             .WillOnce(Return("216000"));
5346710ba2cSBrandon Wyman         psu2.analyze();
5356710ba2cSBrandon Wyman         // STATUS_WORD with VOUT/VOUT_OV fault.
536b654c619SBrandon Wyman         expectations.statusWordValue =
5376710ba2cSBrandon Wyman             ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
5386710ba2cSBrandon Wyman         // Turn on STATUS_VOUT fault bit(s)
539b654c619SBrandon Wyman         expectations.statusVOUTValue = 0xA0;
540c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
541c2906f47SBrandon Wyman         {
54296893a46SBrandon Wyman             // STATUS_TEMPERATURE don't care (default)
543b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
54482affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
54582affd94SBrandon Wyman                 .Times(1)
54682affd94SBrandon Wyman                 .WillOnce(Return("217000"));
5476710ba2cSBrandon Wyman             psu2.analyze();
5486710ba2cSBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
549c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
5506710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
5516710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
5526710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
5536710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
554c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
5552cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
556b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
5577ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
558b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
559b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
56039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
56139ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
56239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
563b10b3be0SBrandon Wyman         }
564c2906f47SBrandon Wyman     }
565b10b3be0SBrandon Wyman 
566b10b3be0SBrandon Wyman     // IOUT_OC_FAULT fault
567b10b3be0SBrandon Wyman     {
568b10b3be0SBrandon Wyman         // First STATUS_WORD with no bits set, then with IOUT_OC fault.
569b10b3be0SBrandon Wyman         PMBusExpectations expectations;
570b10b3be0SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
57182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
57282affd94SBrandon Wyman             .Times(1)
57382affd94SBrandon Wyman             .WillOnce(Return("218000"));
574b10b3be0SBrandon Wyman         psu2.analyze();
575b10b3be0SBrandon Wyman         // STATUS_WORD with IOUT_OC fault.
576b10b3be0SBrandon Wyman         expectations.statusWordValue = status_word::IOUT_OC_FAULT;
577b10b3be0SBrandon Wyman         // Turn on STATUS_IOUT fault bit(s)
578b10b3be0SBrandon Wyman         expectations.statusIOUTValue = 0x88;
579c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
580c2906f47SBrandon Wyman         {
581b10b3be0SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
58282affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
58382affd94SBrandon Wyman                 .Times(1)
58482affd94SBrandon Wyman                 .WillOnce(Return("219000"));
585b10b3be0SBrandon Wyman             psu2.analyze();
586b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
587c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
588b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
589b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
590b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
591b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
592b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
593c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
5942cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
5957ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
5962cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
5972cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
59839ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
59939ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
60039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
6012cf46945SBrandon Wyman         }
602c2906f47SBrandon Wyman     }
6032cf46945SBrandon Wyman 
6042cf46945SBrandon Wyman     // VOUT_UV_FAULT
6052cf46945SBrandon Wyman     {
6062cf46945SBrandon Wyman         // First STATUS_WORD with no bits set, then with VOUT fault.
6072cf46945SBrandon Wyman         PMBusExpectations expectations;
6082cf46945SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
60982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
61082affd94SBrandon Wyman             .Times(1)
61182affd94SBrandon Wyman             .WillOnce(Return("220000"));
6122cf46945SBrandon Wyman         psu2.analyze();
6132cf46945SBrandon Wyman         // Change STATUS_WORD to indicate VOUT fault.
6142cf46945SBrandon Wyman         expectations.statusWordValue = (status_word::VOUT_FAULT);
6152cf46945SBrandon Wyman         // Turn on STATUS_VOUT fault bit(s)
6162cf46945SBrandon Wyman         expectations.statusVOUTValue = 0x30;
617c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
618c2906f47SBrandon Wyman         {
6192cf46945SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
62082affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
62182affd94SBrandon Wyman                 .Times(1)
62282affd94SBrandon Wyman                 .WillOnce(Return("221000"));
6232cf46945SBrandon Wyman             psu2.analyze();
6242cf46945SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
625c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
6262cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
6272cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
6282cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
6292cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
6302cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
6312cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
632c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
6337ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
63496893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6352916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
63639ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
63739ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
63839ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
639b654c619SBrandon Wyman         }
640c2906f47SBrandon Wyman     }
6413f1242f3SBrandon Wyman 
6427ee4d7e4SBrandon Wyman     // Fan fault
643b654c619SBrandon Wyman     {
644b654c619SBrandon Wyman         // First STATUS_WORD with no bits set, then with fan fault.
645b654c619SBrandon Wyman         PMBusExpectations expectations;
646b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
64782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
64882affd94SBrandon Wyman             .Times(1)
64982affd94SBrandon Wyman             .WillOnce(Return("222000"));
6503f1242f3SBrandon Wyman         psu2.analyze();
651b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::FAN_FAULT);
6527ee4d7e4SBrandon Wyman         // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
6537ee4d7e4SBrandon Wyman         expectations.statusFans12Value = 0xA0;
654c2906f47SBrandon Wyman 
655c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
656c2906f47SBrandon Wyman         {
657b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
65882affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
65982affd94SBrandon Wyman                 .Times(1)
66082affd94SBrandon Wyman                 .WillOnce(Return("223000"));
6613f1242f3SBrandon Wyman             psu2.analyze();
6623f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
663c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
664c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT);
6653f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
6663f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
6673f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
66885c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
6696710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
670b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
6712cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
67296893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6732916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
67439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
67539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
67639ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
677b654c619SBrandon Wyman         }
678c2906f47SBrandon Wyman     }
6792916ea52SBrandon Wyman 
68006ca4590SBrandon Wyman     // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
6812cf46945SBrandon Wyman     {
6822916ea52SBrandon Wyman         // First STATUS_WORD with no bits set.
6832916ea52SBrandon Wyman         PMBusExpectations expectations;
6842916ea52SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
68582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
68682affd94SBrandon Wyman             .Times(1)
68782affd94SBrandon Wyman             .WillOnce(Return("123000"));
6882916ea52SBrandon Wyman         psu2.analyze();
6892916ea52SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
6902916ea52SBrandon Wyman         // POWER_GOOD# inactive, and OFF bit on.
6912916ea52SBrandon Wyman         expectations.statusWordValue =
6922916ea52SBrandon Wyman             ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
69306ca4590SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
69406ca4590SBrandon Wyman         {
6952916ea52SBrandon Wyman             // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
6962916ea52SBrandon Wyman             // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
6972916ea52SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
69882affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
69982affd94SBrandon Wyman                 .Times(1)
70082affd94SBrandon Wyman                 .WillOnce(Return("124000"));
7012916ea52SBrandon Wyman             psu2.analyze();
7022916ea52SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
703c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
7042916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
7052916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
7062916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
7072916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
7082916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
7092cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
710b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
7117ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
7122916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
71332453e9bSBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), x >= DEGLITCH_LIMIT);
71406ca4590SBrandon Wyman         }
71506ca4590SBrandon Wyman     }
7162916ea52SBrandon Wyman 
7173f1242f3SBrandon Wyman     // TODO: ReadFailure
7183f1242f3SBrandon Wyman }
7193f1242f3SBrandon Wyman 
72059a35793SBrandon Wyman TEST_F(PowerSupplyTests, OnOffConfig)
72159a35793SBrandon Wyman {
72259a35793SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
72359a35793SBrandon Wyman     uint8_t data = 0x15;
72459a35793SBrandon Wyman 
72559a35793SBrandon Wyman     // Test where PSU is NOT present
72659a35793SBrandon Wyman     try
72759a35793SBrandon Wyman     {
728681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
7290975eaf4SMatt Spinler         EXPECT_CALL(mockedUtil, setAvailable(_, _, _)).Times(0);
730*c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 4,
731*c3324424SBrandon Wyman                         0x69, "ibm-cffps",      PSUGPIOLineName};
732681b2a36SB. J. Wyman 
7333ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
7343ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
735681b2a36SB. J. Wyman         ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
73659a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
737681b2a36SB. J. Wyman         // Constructor should set initial presence, default read returns 0.
73859a35793SBrandon Wyman         // If it is not present, I should not be trying to write to it.
73959a35793SBrandon Wyman         EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
74059a35793SBrandon Wyman         psu.onOffConfig(data);
74159a35793SBrandon Wyman     }
74259a35793SBrandon Wyman     catch (...)
7430c9a33d6SAdriana Kobylak     {}
74459a35793SBrandon Wyman 
74559a35793SBrandon Wyman     // Test where PSU is present
74659a35793SBrandon Wyman     try
74759a35793SBrandon Wyman     {
748681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
7490975eaf4SMatt Spinler         EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
750*c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 5,
751*c3324424SBrandon Wyman                         0x6a, "ibm-cffps",      PSUGPIOLineName};
7523ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
7533ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
754391a0690SBrandon Wyman         // There will potentially be multiple calls, we want it to continue
755391a0690SBrandon Wyman         // returning 1 for the GPIO read to keep the power supply present.
756391a0690SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
75759a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
758391a0690SBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
759391a0690SBrandon Wyman         // If I am calling analyze(), I should probably give it good data.
760391a0690SBrandon Wyman         // STATUS_WORD 0x0000 is powered on, no faults.
761391a0690SBrandon Wyman         PMBusExpectations expectations;
762391a0690SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
76382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
76482affd94SBrandon Wyman             .Times(1)
76582affd94SBrandon Wyman             .WillOnce(Return("205000"));
766681b2a36SB. J. Wyman         psu.analyze();
767391a0690SBrandon Wyman         // I definitely should be writting ON_OFF_CONFIG if I call the function
768391a0690SBrandon Wyman         EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
769391a0690SBrandon Wyman                                            Type::HwmonDeviceDebug))
77059a35793SBrandon Wyman             .Times(1);
77159a35793SBrandon Wyman         psu.onOffConfig(data);
77259a35793SBrandon Wyman     }
77359a35793SBrandon Wyman     catch (...)
7740c9a33d6SAdriana Kobylak     {}
77559a35793SBrandon Wyman }
77659a35793SBrandon Wyman 
7773f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, ClearFaults)
7783f1242f3SBrandon Wyman {
7793f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
780*c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 13,
781*c3324424SBrandon Wyman                     0x68, "ibm-cffps",      PSUGPIOLineName};
7823ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
7833ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
78406ca4590SBrandon Wyman     // Always return 1 to indicate present.
78506ca4590SBrandon Wyman     // Each analyze() call will trigger a read of the presence GPIO.
78606ca4590SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
787681b2a36SB. J. Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
788391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
7898da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
790b654c619SBrandon Wyman     PMBusExpectations expectations;
791b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
79282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
79382affd94SBrandon Wyman         .Times(1)
79482affd94SBrandon Wyman         .WillOnce(Return("207000"));
795681b2a36SB. J. Wyman     psu.analyze();
7963f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
7973f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
7983f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
7993f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
8003f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
80185c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
8026710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
803b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
8042cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
8057ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
80696893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
8072916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
80839ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
80939ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
81039ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
811b654c619SBrandon Wyman 
812f07bc797SBrandon Wyman     // STATUS_WORD with fault bits galore!
813b654c619SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
814f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
815b654c619SBrandon Wyman     expectations.statusInputValue = 0xFF;
816f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
817b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
81885c7bf41SBrandon Wyman     // STATUS_CML with bits on.
819b654c619SBrandon Wyman     expectations.statusCMLValue = 0xFF;
8206710ba2cSBrandon Wyman     // STATUS_VOUT with bits on.
821b654c619SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
822b10b3be0SBrandon Wyman     // STATUS_IOUT with bits on.
823b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
8247ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
8257ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0xFF;
82696893a46SBrandon Wyman     // STATUS_TEMPERATURE with bits on.
82796893a46SBrandon Wyman     expectations.statusTempValue = 0xFF;
828c2906f47SBrandon Wyman 
829c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
830c2906f47SBrandon Wyman     {
831b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
83282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
83382affd94SBrandon Wyman             .Times(1)
83482affd94SBrandon Wyman             .WillOnce(Return("0"));
8350975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
8360975eaf4SMatt Spinler         {
8370975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
8380975eaf4SMatt Spinler         }
8393f1242f3SBrandon Wyman         psu.analyze();
8403f1242f3SBrandon Wyman         EXPECT_EQ(psu.isPresent(), true);
8412cf46945SBrandon Wyman         // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
8422cf46945SBrandon Wyman         // Rely on HasVoutUVFault() to verify this sets and clears.
8432cf46945SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), false);
844c2906f47SBrandon Wyman         // All faults are deglitched up to DEGLITCH_LIMIT
845c2906f47SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
846c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
847c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
848c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
849c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT);
850c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
851c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
852c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
853c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
854c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPgoodFault(), x >= DEGLITCH_LIMIT);
855c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
856c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
857c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
858c2906f47SBrandon Wyman     }
859c2906f47SBrandon Wyman 
86032453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _))
86132453e9bSBrandon Wyman         .Times(1)
86232453e9bSBrandon Wyman         .WillOnce(Return(207000));
8633225a45cSBrandon Wyman     // Clearing VIN_UV fault via in1_lcrit_alarm
8643225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
8653225a45cSBrandon Wyman         .Times(1)
8663225a45cSBrandon Wyman         .WillOnce(Return(1));
8670975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
8683f1242f3SBrandon Wyman     psu.clearFaults();
8693f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
8703f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
8713f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
8723f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
8733f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
87485c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
8756710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
876b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
8772cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
8787ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
87996893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
8802916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
88139ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
88239ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
88339ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
884681b2a36SB. J. Wyman 
88582affd94SBrandon Wyman     // Faults clear on READ_VIN 0 -> !0
88682affd94SBrandon Wyman     // STATUS_WORD with fault bits galore!
88782affd94SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
88882affd94SBrandon Wyman     // STATUS_INPUT with fault bits on.
88982affd94SBrandon Wyman     expectations.statusInputValue = 0xFF;
89082affd94SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
89182affd94SBrandon Wyman     expectations.statusMFRValue = 0xFF;
89282affd94SBrandon Wyman     // STATUS_CML with bits on.
89382affd94SBrandon Wyman     expectations.statusCMLValue = 0xFF;
89482affd94SBrandon Wyman     // STATUS_VOUT with bits on.
89582affd94SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
89682affd94SBrandon Wyman     // STATUS_IOUT with bits on.
89782affd94SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
89882affd94SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
89982affd94SBrandon Wyman     expectations.statusFans12Value = 0xFF;
90082affd94SBrandon Wyman     // STATUS_TEMPERATURE with bits on.
90182affd94SBrandon Wyman     expectations.statusTempValue = 0xFF;
902c2906f47SBrandon Wyman 
903c2906f47SBrandon Wyman     // All faults degltiched now. Check for false before limit above.
904c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
905c2906f47SBrandon Wyman     {
90682affd94SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
90782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
90882affd94SBrandon Wyman             .Times(1)
90982affd94SBrandon Wyman             .WillOnce(Return("0"));
9100975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
9110975eaf4SMatt Spinler         {
9120975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
9130975eaf4SMatt Spinler         }
91482affd94SBrandon Wyman         psu.analyze();
915c2906f47SBrandon Wyman     }
916c2906f47SBrandon Wyman 
91782affd94SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
91882affd94SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
91982affd94SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), true);
92082affd94SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
92182affd94SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), true);
92282affd94SBrandon Wyman     // True due to CML fault bits on
92382affd94SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), true);
92482affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
92582affd94SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), true);
92682affd94SBrandon Wyman     // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
92782affd94SBrandon Wyman     // Rely on HasVoutUVFault() to verify this sets and clears.
92882affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
92982affd94SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), true);
93082affd94SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), true);
931c2906f47SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
93282affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), true);
93382affd94SBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), true);
93482affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), true);
93582affd94SBrandon Wyman     // STATUS_WORD with INPUT/VIN_UV fault bits off.
93682affd94SBrandon Wyman     expectations.statusWordValue = 0xDFF7;
93782affd94SBrandon Wyman     // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
93882affd94SBrandon Wyman     // Insufficient Input Voltage bits off.
93982affd94SBrandon Wyman     expectations.statusInputValue = 0xC7;
94082affd94SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
94182affd94SBrandon Wyman     // READ_VIN back in range.
94282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
94382affd94SBrandon Wyman         .Times(1)
94482affd94SBrandon Wyman         .WillOnce(Return("206000"));
9453225a45cSBrandon Wyman     // VIN_UV cleared via in1_lcrit_alarm when voltage back in range.
9463225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
9473225a45cSBrandon Wyman         .Times(1)
9483225a45cSBrandon Wyman         .WillOnce(Return(1));
9493225a45cSBrandon Wyman     psu.analyze();
9503225a45cSBrandon Wyman     // We only cleared the VIN_UV and OFF faults.
9513225a45cSBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
9523225a45cSBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
9533225a45cSBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
9543225a45cSBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
9553225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
9563225a45cSBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), true);
9573225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
9583225a45cSBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), true);
9593225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
9603225a45cSBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), true);
9613225a45cSBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), true);
9623225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
9633225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), true);
9643225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), true);
9653225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), true);
9663225a45cSBrandon Wyman 
9673225a45cSBrandon Wyman     // All faults cleared
9683225a45cSBrandon Wyman     expectations = {0};
9693225a45cSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
9703225a45cSBrandon Wyman     // READ_VIN back in range.
9713225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
9723225a45cSBrandon Wyman         .Times(1)
9733225a45cSBrandon Wyman         .WillOnce(Return("206000"));
9740975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
97582affd94SBrandon Wyman     psu.analyze();
97682affd94SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
97782affd94SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
97882affd94SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
97982affd94SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
98082affd94SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
98182affd94SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
98282affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
98382affd94SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
98482affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
98582affd94SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
98682affd94SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
98782affd94SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
98882affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
98982affd94SBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
99082affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
99182affd94SBrandon Wyman 
992681b2a36SB. J. Wyman     // TODO: Faults clear on missing/present?
9933f1242f3SBrandon Wyman }
9943f1242f3SBrandon Wyman 
9953f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, UpdateInventory)
9963f1242f3SBrandon Wyman {
9973f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
9981d7a7df8SBrandon Wyman 
9991d7a7df8SBrandon Wyman     try
10001d7a7df8SBrandon Wyman     {
1001*c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 3,
1002*c3324424SBrandon Wyman                         0x68, "ibm-cffps",      PSUGPIOLineName};
10031d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
10041d7a7df8SBrandon Wyman         // If it is not present, I should not be trying to read a string
10051d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
10061d7a7df8SBrandon Wyman         psu.updateInventory();
10071d7a7df8SBrandon Wyman     }
10081d7a7df8SBrandon Wyman     catch (...)
10091d7a7df8SBrandon Wyman     {
10101d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
10111d7a7df8SBrandon Wyman     }
10121d7a7df8SBrandon Wyman 
10131d7a7df8SBrandon Wyman     try
10141d7a7df8SBrandon Wyman     {
1015*c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 13,
1016*c3324424SBrandon Wyman                         0x69, "ibm-cffps",      PSUGPIOLineName};
10173ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
10183ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1019681b2a36SB. J. Wyman         // GPIO read return 1 to indicate present.
1020681b2a36SB. J. Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
10211d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1022391a0690SBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
1023391a0690SBrandon Wyman         // STATUS_WORD 0x0000 is powered on, no faults.
1024391a0690SBrandon Wyman         PMBusExpectations expectations;
1025391a0690SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
102682affd94SBrandon Wyman         // Call to analyze will read voltage, trigger clear faults for 0 to
102782affd94SBrandon Wyman         // within range.
102882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
102982affd94SBrandon Wyman             .Times(1)
103082affd94SBrandon Wyman             .WillOnce(Return("123456"));
1031391a0690SBrandon Wyman         psu.analyze();
10321d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
10333f1242f3SBrandon Wyman         psu.updateInventory();
10341d7a7df8SBrandon Wyman 
10353c530fbdSBrandon Wyman #if IBM_VPD
10361d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _))
10371d7a7df8SBrandon Wyman             .WillOnce(Return("CCIN"))
10381d7a7df8SBrandon Wyman             .WillOnce(Return("PN3456"))
10391d7a7df8SBrandon Wyman             .WillOnce(Return("FN3456"))
10401d7a7df8SBrandon Wyman             .WillOnce(Return("HEADER"))
10411d7a7df8SBrandon Wyman             .WillOnce(Return("SN3456"))
10421d7a7df8SBrandon Wyman             .WillOnce(Return("FW3456"));
10433c530fbdSBrandon Wyman #endif
10441d7a7df8SBrandon Wyman         psu.updateInventory();
10451d7a7df8SBrandon Wyman         // TODO: D-Bus mocking to verify values stored on D-Bus (???)
10461d7a7df8SBrandon Wyman     }
10471d7a7df8SBrandon Wyman     catch (...)
10481d7a7df8SBrandon Wyman     {
10491d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
10501d7a7df8SBrandon Wyman     }
10513f1242f3SBrandon Wyman }
10523f1242f3SBrandon Wyman 
10533f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsPresent)
10543f1242f3SBrandon Wyman {
10553f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1056681b2a36SB. J. Wyman 
1057*c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1058*c3324424SBrandon Wyman                     0x68, "ibm-cffps",      PSUGPIOLineName};
10593ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
10603ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
10613f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), false);
10623f1242f3SBrandon Wyman 
1063681b2a36SB. J. Wyman     // Change GPIO read to return 1 to indicate present.
1064681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
1065391a0690SBrandon Wyman     // Call to analyze() will update to present, that will trigger updating
1066391a0690SBrandon Wyman     // to the correct/latest HWMON directory, in case it changes.
1067391a0690SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1068391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1069391a0690SBrandon Wyman     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1070391a0690SBrandon Wyman     // Default expectations will be on, no faults.
1071391a0690SBrandon Wyman     PMBusExpectations expectations;
1072391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
107382affd94SBrandon Wyman     // Give it an input voltage in the 100-volt range.
107482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
107582affd94SBrandon Wyman         .Times(1)
107682affd94SBrandon Wyman         .WillOnce(Return("123456"));
10770975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1078681b2a36SB. J. Wyman     psu.analyze();
1079681b2a36SB. J. Wyman     EXPECT_EQ(psu.isPresent(), true);
10803f1242f3SBrandon Wyman }
10813f1242f3SBrandon Wyman 
10823f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsFaulted)
10833f1242f3SBrandon Wyman {
10843f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1085681b2a36SB. J. Wyman 
1086*c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 11,
1087*c3324424SBrandon Wyman                     0x6f, "ibm-cffps",      PSUGPIOLineName};
10883ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
10893ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1090681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1091681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1092391a0690SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1093391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1094391a0690SBrandon Wyman     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1095391a0690SBrandon Wyman     // Default expectations will be on, no faults.
1096391a0690SBrandon Wyman     PMBusExpectations expectations;
1097391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
109882affd94SBrandon Wyman     // Give it an input voltage in the 100-volt range.
109982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
110082affd94SBrandon Wyman         .Times(1)
110182affd94SBrandon Wyman         .WillOnce(Return("124680"));
1102681b2a36SB. J. Wyman     psu.analyze();
11033f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
1104f07bc797SBrandon Wyman     // STATUS_WORD with fault bits on.
1105b654c619SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
1106f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
1107b654c619SBrandon Wyman     expectations.statusInputValue = 0xFF;
1108f07bc797SBrandon Wyman     // STATUS_MFR_SPECIFIC with faults bits on.
1109b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
111085c7bf41SBrandon Wyman     // STATUS_CML with faults bits on.
1111b654c619SBrandon Wyman     expectations.statusCMLValue = 0xFF;
11126710ba2cSBrandon Wyman     // STATUS_VOUT with fault bits on.
1113b654c619SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
1114b10b3be0SBrandon Wyman     // STATUS_IOUT with fault bits on.
1115b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
11167ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
11177ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0xFF;
111896893a46SBrandon Wyman     // STATUS_TEMPERATURE with fault bits on.
111996893a46SBrandon Wyman     expectations.statusTempValue = 0xFF;
1120c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1121c2906f47SBrandon Wyman     {
1122b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
11234fc191f0SBrandon Wyman         // Also get another read of READ_VIN, faulted, so not in 100-volt range
112482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
112582affd94SBrandon Wyman             .Times(1)
11264fc191f0SBrandon Wyman             .WillOnce(Return("19000"));
11270975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
11280975eaf4SMatt Spinler         {
11290975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
11300975eaf4SMatt Spinler         }
11313f1242f3SBrandon Wyman         psu.analyze();
1132c2906f47SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
1133c2906f47SBrandon Wyman     }
11343f1242f3SBrandon Wyman }
11353f1242f3SBrandon Wyman 
11363f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasInputFault)
11373f1242f3SBrandon Wyman {
11383f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1139681b2a36SB. J. Wyman 
1140*c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1141*c3324424SBrandon Wyman                     0x68, "ibm-cffps",      PSUGPIOLineName};
11423ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
11433ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1144681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1145681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
11463f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1147391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
11488da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1149b654c619SBrandon Wyman     PMBusExpectations expectations;
1150b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
115182affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
115282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
115382affd94SBrandon Wyman         .Times(1)
115482affd94SBrandon Wyman         .WillOnce(Return("201100"));
11553f1242f3SBrandon Wyman     psu.analyze();
11563f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
1157f07bc797SBrandon Wyman     // STATUS_WORD with input fault/warn on.
1158b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
1159f07bc797SBrandon Wyman     // STATUS_INPUT with an input fault bit on.
1160b654c619SBrandon Wyman     expectations.statusInputValue = 0x80;
1161c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1162c2906f47SBrandon Wyman     {
1163b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
116482affd94SBrandon Wyman         // Analyze call will also need good READ_VIN value to check.
116582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
116682affd94SBrandon Wyman             .Times(1)
116782affd94SBrandon Wyman             .WillOnce(Return("201200"));
11680975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
11690975eaf4SMatt Spinler         {
11700975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
11710975eaf4SMatt Spinler         }
11723f1242f3SBrandon Wyman         psu.analyze();
1173c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
1174c2906f47SBrandon Wyman     }
1175f07bc797SBrandon Wyman     // STATUS_WORD with no bits on.
1176b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1177b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
117882affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
117982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
118082affd94SBrandon Wyman         .Times(1)
118182affd94SBrandon Wyman         .WillOnce(Return("201300"));
11820975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
11833f1242f3SBrandon Wyman     psu.analyze();
11843f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
11853f1242f3SBrandon Wyman }
11863f1242f3SBrandon Wyman 
11873f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasMFRFault)
11883f1242f3SBrandon Wyman {
11893f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1190681b2a36SB. J. Wyman 
1191*c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1192*c3324424SBrandon Wyman                     0x68, "ibm-cffps",      PSUGPIOLineName};
11933ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
11943ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1195681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1196681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
11973f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1198391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1199f07bc797SBrandon Wyman     // First return STATUS_WORD with no bits on.
12008da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1201b654c619SBrandon Wyman     PMBusExpectations expectations;
1202b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
120382affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
120482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
120582affd94SBrandon Wyman         .Times(1)
120682affd94SBrandon Wyman         .WillOnce(Return("202100"));
12073f1242f3SBrandon Wyman     psu.analyze();
12083f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
1209f07bc797SBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
1210b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1211f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
1212b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
1213c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1214c2906f47SBrandon Wyman     {
1215b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
121682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
121782affd94SBrandon Wyman             .Times(1)
121882affd94SBrandon Wyman             .WillOnce(Return("202200"));
12193f1242f3SBrandon Wyman         psu.analyze();
1220c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1221c2906f47SBrandon Wyman     }
1222f07bc797SBrandon Wyman     // Back to no bits on in STATUS_WORD
1223b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1224b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
122582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
122682affd94SBrandon Wyman         .Times(1)
122782affd94SBrandon Wyman         .WillOnce(Return("202300"));
12283f1242f3SBrandon Wyman     psu.analyze();
12293f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
12303f1242f3SBrandon Wyman }
12313f1242f3SBrandon Wyman 
12323f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasVINUVFault)
12333f1242f3SBrandon Wyman {
12343f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1235681b2a36SB. J. Wyman 
1236*c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1237*c3324424SBrandon 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);
124482affd94SBrandon Wyman 
124582affd94SBrandon Wyman     // Presence change from missing to present will trigger in1_input read in
124682affd94SBrandon Wyman     // an attempt to get CLEAR_FAULTS called. Return value ignored.
124782affd94SBrandon Wyman     // Zero to non-zero voltage, for missing/present change, triggers clear
124882affd94SBrandon Wyman     // faults call again. Return value ignored.
124982affd94SBrandon Wyman     // Fault (low voltage) to not faulted (voltage in range) triggers clear
125082affd94SBrandon Wyman     // faults call a third time.
125182affd94SBrandon Wyman 
12528da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1253b654c619SBrandon Wyman     PMBusExpectations expectations;
1254b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
125582affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
125682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
125782affd94SBrandon Wyman         .Times(1)
125882affd94SBrandon Wyman         .WillOnce(Return("201100"));
12593f1242f3SBrandon Wyman     psu.analyze();
12603f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
1261f07bc797SBrandon Wyman     // Turn fault on.
1262b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::VIN_UV_FAULT);
126385c7bf41SBrandon Wyman     // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
126485c7bf41SBrandon Wyman     // Figure 16, and assume bits on in STATUS_INPUT.
1265b654c619SBrandon Wyman     expectations.statusInputValue = 0x18;
1266c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1267c2906f47SBrandon Wyman     {
1268b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
126982affd94SBrandon Wyman         // If there is a VIN_UV fault, fake reading voltage of less than 20V
127082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
127182affd94SBrandon Wyman             .Times(1)
127282affd94SBrandon Wyman             .WillOnce(Return("19876"));
12730975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
12740975eaf4SMatt Spinler         {
12750975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
12760975eaf4SMatt Spinler         }
12773f1242f3SBrandon Wyman         psu.analyze();
1278c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1279c2906f47SBrandon Wyman     }
1280f07bc797SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1281b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1282b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
128382affd94SBrandon Wyman     // Updates now result in clearing faults if read voltage goes from below the
128482affd94SBrandon Wyman     // minimum, to within a valid range.
128582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
128682affd94SBrandon Wyman         .Times(1)
128782affd94SBrandon Wyman         .WillOnce(Return("201300"));
12883225a45cSBrandon Wyman     // Went from below minimum to within range, expect clearVinUVFault().
12893225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
12903225a45cSBrandon Wyman         .Times(1)
12913225a45cSBrandon Wyman         .WillOnce(Return(1));
12920975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
12933f1242f3SBrandon Wyman     psu.analyze();
12943f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
12953f1242f3SBrandon Wyman }
12966710ba2cSBrandon Wyman 
12976710ba2cSBrandon Wyman TEST_F(PowerSupplyTests, HasVoutOVFault)
12986710ba2cSBrandon Wyman {
12996710ba2cSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
13006710ba2cSBrandon Wyman 
1301*c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1302*c3324424SBrandon Wyman                     0x69, "ibm-cffps",      PSUGPIOLineName};
13036710ba2cSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
13046710ba2cSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
13056710ba2cSBrandon Wyman     // Always return 1 to indicate present.
13066710ba2cSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
13076710ba2cSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1308391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
13096710ba2cSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1310b654c619SBrandon Wyman     PMBusExpectations expectations;
1311b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
131282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
131382affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
131482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
131582affd94SBrandon Wyman         .Times(1)
131682affd94SBrandon Wyman         .WillOnce(Return("202100"));
13176710ba2cSBrandon Wyman     psu.analyze();
13186710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
13196710ba2cSBrandon Wyman     // Turn fault on.
1320b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
13216710ba2cSBrandon Wyman     // STATUS_VOUT fault bit(s)
1322b654c619SBrandon Wyman     expectations.statusVOUTValue = 0x80;
1323c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1324c2906f47SBrandon Wyman     {
1325b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
132682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
132782affd94SBrandon Wyman             .Times(1)
132882affd94SBrandon Wyman             .WillOnce(Return("202200"));
13296710ba2cSBrandon Wyman         psu.analyze();
1330c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1331c2906f47SBrandon Wyman     }
13326710ba2cSBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1333b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1334b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
133582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
133682affd94SBrandon Wyman         .Times(1)
133782affd94SBrandon Wyman         .WillOnce(Return("202300"));
13386710ba2cSBrandon Wyman     psu.analyze();
13396710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
13406710ba2cSBrandon Wyman }
134196893a46SBrandon Wyman 
1342b10b3be0SBrandon Wyman TEST_F(PowerSupplyTests, HasIoutOCFault)
1343b10b3be0SBrandon Wyman {
1344b10b3be0SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1345b10b3be0SBrandon Wyman 
1346*c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1347*c3324424SBrandon Wyman                     0x6d, "ibm-cffps",      PSUGPIOLineName};
1348b10b3be0SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
1349b10b3be0SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1350b10b3be0SBrandon Wyman     // Always return 1 to indicate present.
1351b10b3be0SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1352b10b3be0SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1353391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1354b10b3be0SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1355b10b3be0SBrandon Wyman     PMBusExpectations expectations;
1356b10b3be0SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
135782affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
135882affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
135982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
136082affd94SBrandon Wyman         .Times(1)
136182affd94SBrandon Wyman         .WillOnce(Return("203100"));
1362b10b3be0SBrandon Wyman     psu.analyze();
1363b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
1364b10b3be0SBrandon Wyman     // Turn fault on.
1365b10b3be0SBrandon Wyman     expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1366b10b3be0SBrandon Wyman     // STATUS_IOUT fault bit(s)
1367b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0x88;
1368c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1369c2906f47SBrandon Wyman     {
1370b10b3be0SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
137182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
137282affd94SBrandon Wyman             .Times(1)
137382affd94SBrandon Wyman             .WillOnce(Return("203200"));
13740975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
13750975eaf4SMatt Spinler         {
13760975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
13770975eaf4SMatt Spinler         }
1378b10b3be0SBrandon Wyman         psu.analyze();
1379c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1380c2906f47SBrandon Wyman     }
1381b10b3be0SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1382b10b3be0SBrandon Wyman     expectations.statusWordValue = 0;
1383b10b3be0SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
138482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
138582affd94SBrandon Wyman         .Times(1)
138682affd94SBrandon Wyman         .WillOnce(Return("203300"));
13870975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1388b10b3be0SBrandon Wyman     psu.analyze();
1389b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
1390b10b3be0SBrandon Wyman }
1391b10b3be0SBrandon Wyman 
13922cf46945SBrandon Wyman TEST_F(PowerSupplyTests, HasVoutUVFault)
13932cf46945SBrandon Wyman {
13942cf46945SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
13952cf46945SBrandon Wyman 
1396*c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1397*c3324424SBrandon Wyman                     0x6a, "ibm-cffps",      PSUGPIOLineName};
13982cf46945SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
13992cf46945SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
14002cf46945SBrandon Wyman     // Always return 1 to indicate present.
14012cf46945SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
14022cf46945SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1403391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1404391a0690SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
14052cf46945SBrandon Wyman     PMBusExpectations expectations;
14062cf46945SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
140782affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
140882affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
140982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
141082affd94SBrandon Wyman         .Times(1)
141182affd94SBrandon Wyman         .WillOnce(Return("204100"));
14122cf46945SBrandon Wyman     psu.analyze();
14132cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
14142cf46945SBrandon Wyman     // Turn fault on.
14152cf46945SBrandon Wyman     expectations.statusWordValue = (status_word::VOUT_FAULT);
14162cf46945SBrandon Wyman     // STATUS_VOUT fault bit(s)
14172cf46945SBrandon Wyman     expectations.statusVOUTValue = 0x30;
1418c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1419c2906f47SBrandon Wyman     {
14202cf46945SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
142182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
142282affd94SBrandon Wyman             .Times(1)
142382affd94SBrandon Wyman             .WillOnce(Return("204200"));
14242cf46945SBrandon Wyman         psu.analyze();
1425c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1426c2906f47SBrandon Wyman     }
14272cf46945SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
14282cf46945SBrandon Wyman     expectations.statusWordValue = 0;
14292cf46945SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
143082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
143182affd94SBrandon Wyman         .Times(1)
143282affd94SBrandon Wyman         .WillOnce(Return("204300"));
14332cf46945SBrandon Wyman     psu.analyze();
14342cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
14352cf46945SBrandon Wyman }
14362cf46945SBrandon Wyman 
14377ee4d7e4SBrandon Wyman TEST_F(PowerSupplyTests, HasFanFault)
14387ee4d7e4SBrandon Wyman {
14397ee4d7e4SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
14407ee4d7e4SBrandon Wyman 
14410975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
14420975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
14430975eaf4SMatt Spinler 
1444*c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1445*c3324424SBrandon Wyman                     0x6d, "ibm-cffps",      PSUGPIOLineName};
14467ee4d7e4SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
14477ee4d7e4SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
14487ee4d7e4SBrandon Wyman     // Always return 1 to indicate present.
14497ee4d7e4SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
14507ee4d7e4SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1451391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
14527ee4d7e4SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
14537ee4d7e4SBrandon Wyman     PMBusExpectations expectations;
14547ee4d7e4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
145582affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
145682affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
145782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
145882affd94SBrandon Wyman         .Times(1)
145982affd94SBrandon Wyman         .WillOnce(Return("205100"));
14607ee4d7e4SBrandon Wyman     psu.analyze();
14617ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
14627ee4d7e4SBrandon Wyman     // Turn fault on.
14637ee4d7e4SBrandon Wyman     expectations.statusWordValue = (status_word::FAN_FAULT);
14647ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
14657ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0x80;
1466c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1467c2906f47SBrandon Wyman     {
14687ee4d7e4SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
146982affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
147082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
147182affd94SBrandon Wyman             .Times(1)
147282affd94SBrandon Wyman             .WillOnce(Return("205200"));
14737ee4d7e4SBrandon Wyman         psu.analyze();
1474c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1475c2906f47SBrandon Wyman     }
14767ee4d7e4SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
14777ee4d7e4SBrandon Wyman     expectations.statusWordValue = 0;
14787ee4d7e4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
147982affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
148082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
148182affd94SBrandon Wyman         .Times(1)
148282affd94SBrandon Wyman         .WillOnce(Return("205300"));
14837ee4d7e4SBrandon Wyman     psu.analyze();
14847ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
14857ee4d7e4SBrandon Wyman }
14867ee4d7e4SBrandon Wyman 
148796893a46SBrandon Wyman TEST_F(PowerSupplyTests, HasTempFault)
148896893a46SBrandon Wyman {
148996893a46SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
149096893a46SBrandon Wyman 
14910975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
14920975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
14930975eaf4SMatt Spinler 
1494*c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1495*c3324424SBrandon Wyman                     0x6a, "ibm-cffps",      PSUGPIOLineName};
149696893a46SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
149796893a46SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
149896893a46SBrandon Wyman     // Always return 1 to indicate present.
149996893a46SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
150096893a46SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1501391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
150296893a46SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
150396893a46SBrandon Wyman     PMBusExpectations expectations;
150496893a46SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
150582affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
150682affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
150782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
150882affd94SBrandon Wyman         .Times(1)
150982affd94SBrandon Wyman         .WillOnce(Return("206100"));
151096893a46SBrandon Wyman     psu.analyze();
151196893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
151296893a46SBrandon Wyman     // Turn fault on.
151396893a46SBrandon Wyman     expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
151496893a46SBrandon Wyman     // STATUS_TEMPERATURE fault bit on (OT Fault)
151596893a46SBrandon Wyman     expectations.statusTempValue = 0x80;
1516c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1517c2906f47SBrandon Wyman     {
151896893a46SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
151982affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
152082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
152182affd94SBrandon Wyman             .Times(1)
152282affd94SBrandon Wyman             .WillOnce(Return("206200"));
152396893a46SBrandon Wyman         psu.analyze();
1524c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1525c2906f47SBrandon Wyman     }
152696893a46SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
152796893a46SBrandon Wyman     expectations.statusWordValue = 0;
152896893a46SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
152982affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
153082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
153182affd94SBrandon Wyman         .Times(1)
153282affd94SBrandon Wyman         .WillOnce(Return("206300"));
153396893a46SBrandon Wyman     psu.analyze();
153496893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
153596893a46SBrandon Wyman }
15362916ea52SBrandon Wyman 
15372916ea52SBrandon Wyman TEST_F(PowerSupplyTests, HasPgoodFault)
15382916ea52SBrandon Wyman {
15392916ea52SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
15402916ea52SBrandon Wyman 
1541*c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 3,
1542*c3324424SBrandon Wyman                     0x6b, "ibm-cffps",      PSUGPIOLineName};
15432916ea52SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
15442916ea52SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
15452916ea52SBrandon Wyman     // Always return 1 to indicate present.
15462916ea52SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
15472916ea52SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1548391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
15492916ea52SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
15502916ea52SBrandon Wyman     PMBusExpectations expectations;
15512916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
155282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
155382affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
155482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
155582affd94SBrandon Wyman         .Times(1)
155682affd94SBrandon Wyman         .WillOnce(Return("207100"));
15572916ea52SBrandon Wyman     psu.analyze();
15582916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
1559391a0690SBrandon Wyman     // Setup another expectation of no faults.
1560391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
156182affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
156282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
156382affd94SBrandon Wyman         .Times(1)
156482affd94SBrandon Wyman         .WillOnce(Return("207200"));
156582affd94SBrandon Wyman     psu.analyze();
156682affd94SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
156782affd94SBrandon Wyman     // Setup another expectation of no faults.
156882affd94SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
156982affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
157082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
157182affd94SBrandon Wyman         .Times(1)
157282affd94SBrandon Wyman         .WillOnce(Return("207300"));
1573391a0690SBrandon Wyman     psu.analyze();
1574391a0690SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
15752916ea52SBrandon Wyman     // Turn PGOOD# off (fault on).
15762916ea52SBrandon Wyman     expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
15772916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
157882affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
157982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
158082affd94SBrandon Wyman         .Times(1)
158182affd94SBrandon Wyman         .WillOnce(Return("207400"));
15822916ea52SBrandon Wyman     psu.analyze();
158306ca4590SBrandon Wyman     // Expect false until reaches DEGLITCH_LIMIT
158406ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
158506ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
158682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
158782affd94SBrandon Wyman         .Times(1)
158882affd94SBrandon Wyman         .WillOnce(Return("207500"));
158906ca4590SBrandon Wyman     psu.analyze();
159006ca4590SBrandon Wyman     // Expect false until reaches DEGLITCH_LIMIT
159106ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
159206ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
159382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
159482affd94SBrandon Wyman         .Times(1)
159582affd94SBrandon Wyman         .WillOnce(Return("207600"));
159606ca4590SBrandon Wyman     psu.analyze();
159706ca4590SBrandon Wyman     // DEGLITCH_LIMIT reached, expect true.
15982916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
15992916ea52SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
16002916ea52SBrandon Wyman     expectations.statusWordValue = 0;
16012916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
160282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
160382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
160482affd94SBrandon Wyman         .Times(1)
160582affd94SBrandon Wyman         .WillOnce(Return("207700"));
16062916ea52SBrandon Wyman     psu.analyze();
16072916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
160882affd94SBrandon Wyman 
16092916ea52SBrandon Wyman     // Turn OFF bit on
16102916ea52SBrandon Wyman     expectations.statusWordValue = (status_word::UNIT_IS_OFF);
16112916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
161282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
161382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
161482affd94SBrandon Wyman         .Times(1)
161582affd94SBrandon Wyman         .WillOnce(Return("208100"));
16162916ea52SBrandon Wyman     psu.analyze();
161706ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
161806ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
161982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
162082affd94SBrandon Wyman         .Times(1)
162182affd94SBrandon Wyman         .WillOnce(Return("208200"));
162206ca4590SBrandon Wyman     psu.analyze();
162306ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
162406ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
162582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
162682affd94SBrandon Wyman         .Times(1)
162782affd94SBrandon Wyman         .WillOnce(Return("208300"));
162806ca4590SBrandon Wyman     psu.analyze();
16292916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
16302916ea52SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
16312916ea52SBrandon Wyman     expectations.statusWordValue = 0;
16322916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
163382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
163482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
163582affd94SBrandon Wyman         .Times(1)
163682affd94SBrandon Wyman         .WillOnce(Return("208400"));
16372916ea52SBrandon Wyman     psu.analyze();
16382916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
16392916ea52SBrandon Wyman }
164039ea02bcSBrandon Wyman 
164139ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPSKillFault)
164239ea02bcSBrandon Wyman {
164339ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1644*c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 4,
1645*c3324424SBrandon Wyman                     0x6d, "ibm-cffps",      PSUGPIOLineName};
164639ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
164739ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
164839ea02bcSBrandon Wyman     // Always return 1 to indicate present.
164939ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
165039ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
165182affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
165239ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
165339ea02bcSBrandon Wyman     PMBusExpectations expectations;
165439ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
165582affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
165682affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
165782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
165882affd94SBrandon Wyman         .Times(1)
165982affd94SBrandon Wyman         .WillOnce(Return("208100"));
166039ea02bcSBrandon Wyman     psu.analyze();
166139ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
166239ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
166339ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
166439ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
166539ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1666c2906f47SBrandon Wyman 
1667c2906f47SBrandon Wyman     // Deglitching faults, false until read the fault bits on up to the limit.
1668c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1669c2906f47SBrandon Wyman     {
167039ea02bcSBrandon 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("208200"));
16750975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
16760975eaf4SMatt Spinler         {
16770975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
16780975eaf4SMatt Spinler         }
167939ea02bcSBrandon Wyman         psu.analyze();
1680c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1681c2906f47SBrandon Wyman     }
1682c2906f47SBrandon Wyman 
168339ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
168439ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
168539ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
168682affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
168782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
168882affd94SBrandon Wyman         .Times(1)
168982affd94SBrandon Wyman         .WillOnce(Return("208300"));
16900975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
169139ea02bcSBrandon Wyman     psu.analyze();
169239ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
169339ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
169439ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
169539ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 4 on.
169639ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x10;
1697c2906f47SBrandon Wyman 
1698c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1699c2906f47SBrandon Wyman     {
170039ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
170182affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
170282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
170382affd94SBrandon Wyman             .Times(1)
170482affd94SBrandon Wyman             .WillOnce(Return("208400"));
17050975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
17060975eaf4SMatt Spinler         {
17070975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
17080975eaf4SMatt Spinler         }
170939ea02bcSBrandon Wyman         psu.analyze();
1710c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1711c2906f47SBrandon Wyman     }
1712c2906f47SBrandon Wyman 
171339ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
171439ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
171539ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
171682affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
171782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
171882affd94SBrandon Wyman         .Times(1)
171982affd94SBrandon Wyman         .WillOnce(Return("208500"));
17200975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
172139ea02bcSBrandon Wyman     psu.analyze();
172239ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
172339ea02bcSBrandon Wyman }
172439ea02bcSBrandon Wyman 
172539ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPS12VcsFault)
172639ea02bcSBrandon Wyman {
172739ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1728*c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 5,
1729*c3324424SBrandon Wyman                     0x6e, "ibm-cffps",      PSUGPIOLineName};
173039ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
173139ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
173239ea02bcSBrandon Wyman     // Always return 1 to indicate present.
173339ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
173439ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
173582affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
173639ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
173739ea02bcSBrandon Wyman     PMBusExpectations expectations;
173839ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
173982affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
174082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
174182affd94SBrandon Wyman         .Times(1)
174282affd94SBrandon Wyman         .WillOnce(Return("209100"));
174339ea02bcSBrandon Wyman     psu.analyze();
174439ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
174539ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
174639ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
174739ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
174839ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1749c2906f47SBrandon Wyman 
1750c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1751c2906f47SBrandon Wyman     {
175239ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
175382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
175482affd94SBrandon Wyman             .Times(1)
175582affd94SBrandon Wyman             .WillOnce(Return("209200"));
175639ea02bcSBrandon Wyman         psu.analyze();
1757c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1758c2906f47SBrandon Wyman     }
1759c2906f47SBrandon Wyman 
176039ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
176139ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
176239ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
176382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
176482affd94SBrandon Wyman         .Times(1)
176582affd94SBrandon Wyman         .WillOnce(Return("209300"));
176639ea02bcSBrandon Wyman     psu.analyze();
176739ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
176839ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
176939ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
177039ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 6 on.
177139ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x40;
1772c2906f47SBrandon Wyman 
1773c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1774c2906f47SBrandon Wyman     {
177539ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
177682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
177782affd94SBrandon Wyman             .Times(1)
177882affd94SBrandon Wyman             .WillOnce(Return("209400"));
177939ea02bcSBrandon Wyman         psu.analyze();
1780c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1781c2906f47SBrandon Wyman     }
1782c2906f47SBrandon Wyman 
178339ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
178439ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
178539ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
178682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
178782affd94SBrandon Wyman         .Times(1)
178882affd94SBrandon Wyman         .WillOnce(Return("209500"));
178939ea02bcSBrandon Wyman     psu.analyze();
179039ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
179139ea02bcSBrandon Wyman }
179239ea02bcSBrandon Wyman 
179339ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPSCS12VFault)
179439ea02bcSBrandon Wyman {
179539ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1796*c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 6,
1797*c3324424SBrandon Wyman                     0x6f, "ibm-cffps",      PSUGPIOLineName};
179839ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
179939ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
180039ea02bcSBrandon Wyman     // Always return 1 to indicate present.
180139ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
180239ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
180382affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
180439ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
180539ea02bcSBrandon Wyman     PMBusExpectations expectations;
180639ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
180782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
180882affd94SBrandon Wyman         .Times(1)
180982affd94SBrandon Wyman         .WillOnce(Return("209100"));
181039ea02bcSBrandon Wyman     psu.analyze();
181139ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
181239ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
181339ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
181439ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
181539ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1816c2906f47SBrandon Wyman 
1817c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1818c2906f47SBrandon Wyman     {
181939ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
182082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
182182affd94SBrandon Wyman             .Times(1)
182282affd94SBrandon Wyman             .WillOnce(Return("209200"));
182339ea02bcSBrandon Wyman         psu.analyze();
1824c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1825c2906f47SBrandon Wyman     }
1826c2906f47SBrandon Wyman 
182739ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
182839ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
182939ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
183082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
183182affd94SBrandon Wyman         .Times(1)
183282affd94SBrandon Wyman         .WillOnce(Return("209300"));
183339ea02bcSBrandon Wyman     psu.analyze();
183439ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
183539ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
183639ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
183739ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 7 on.
183839ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x80;
1839c2906f47SBrandon Wyman 
1840c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1841c2906f47SBrandon Wyman     {
184239ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
184382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
184482affd94SBrandon Wyman             .Times(1)
184582affd94SBrandon Wyman             .WillOnce(Return("209400"));
184639ea02bcSBrandon Wyman         psu.analyze();
1847c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1848c2906f47SBrandon Wyman     }
1849c2906f47SBrandon Wyman 
185039ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
185139ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
185239ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
185382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
185482affd94SBrandon Wyman         .Times(1)
185582affd94SBrandon Wyman         .WillOnce(Return("209500"));
185639ea02bcSBrandon Wyman     psu.analyze();
185739ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
185839ea02bcSBrandon Wyman }
1859*c3324424SBrandon Wyman 
1860*c3324424SBrandon Wyman TEST_F(PowerSupplyTests, SetupInputHistory)
1861*c3324424SBrandon Wyman {
1862*c3324424SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1863*c3324424SBrandon Wyman     {
1864*c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 6,
1865*c3324424SBrandon Wyman                         0x6f, "ibm-cffps",      PSUGPIOLineName};
1866*c3324424SBrandon Wyman         // Defaults to not present due to constructor and mock ordering.
1867*c3324424SBrandon Wyman         psu.setupInputHistory();
1868*c3324424SBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
1869*c3324424SBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
1870*c3324424SBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1871*c3324424SBrandon Wyman         // Always return 1 to indicate present.
1872*c3324424SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1873*c3324424SBrandon Wyman         psu.analyze();
1874*c3324424SBrandon Wyman         psu.setupInputHistory();
1875*c3324424SBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), true);
1876*c3324424SBrandon Wyman     }
1877*c3324424SBrandon Wyman     {
1878*c3324424SBrandon Wyman         PowerSupply psu{bus,  PSUInventoryPath, 11,
1879*c3324424SBrandon Wyman                         0x58, "inspur-ipsps",   PSUGPIOLineName};
1880*c3324424SBrandon Wyman         // Defaults to not present due to constructor and mock ordering.
1881*c3324424SBrandon Wyman         psu.setupInputHistory();
1882*c3324424SBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
1883*c3324424SBrandon Wyman         MockedGPIOInterface* mockPresenceGPIO =
1884*c3324424SBrandon Wyman             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1885*c3324424SBrandon Wyman         // Always return 1 to indicate present.
1886*c3324424SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1887*c3324424SBrandon Wyman         psu.analyze();
1888*c3324424SBrandon Wyman         psu.setupInputHistory();
1889*c3324424SBrandon Wyman         // After updating to present, and retrying setup, expect inspur-ipsps to
1890*c3324424SBrandon Wyman         // still not support INPUT_HISTORY.
1891*c3324424SBrandon Wyman         EXPECT_EQ(psu.hasInputHistory(), false);
1892*c3324424SBrandon Wyman     }
1893*c3324424SBrandon Wyman }
1894*c3324424SBrandon Wyman 
1895*c3324424SBrandon Wyman TEST_F(PowerSupplyTests, UpdateHistory)
1896*c3324424SBrandon Wyman {
1897*c3324424SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1898*c3324424SBrandon Wyman     PowerSupply psu{bus,  PSUInventoryPath, 7,
1899*c3324424SBrandon Wyman                     0x6e, "ibm-cffps",      PSUGPIOLineName};
1900*c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), false);
1901*c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
1902*c3324424SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
1903*c3324424SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1904*c3324424SBrandon Wyman     // Always return 1 to indicate present.
1905*c3324424SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1906*c3324424SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1907*c3324424SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1908*c3324424SBrandon Wyman     PMBusExpectations expectations;
1909*c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
1910*c3324424SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1911*c3324424SBrandon Wyman         .Times(6)
1912*c3324424SBrandon Wyman         .WillRepeatedly(Return("205000"));
1913*c3324424SBrandon Wyman     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1914*c3324424SBrandon Wyman     // First read after missing/present will have no data.
1915*c3324424SBrandon Wyman     std::vector<uint8_t> emptyHistory{};
1916*c3324424SBrandon Wyman     // Second read, after about 30 seconds, should have a record. 5-bytes.
1917*c3324424SBrandon Wyman     // Sequence Number: 0x00, Average: 0x50 0xf3 (212), Maximum: 0x54 0xf3 (213)
1918*c3324424SBrandon Wyman     std::vector<uint8_t> firstHistory{0x00, 0x50, 0xf3, 0x54, 0xf3};
1919*c3324424SBrandon Wyman     // Third read, after about 60 seconds, should have two records, 10-bytes,
1920*c3324424SBrandon Wyman     // but only reading 5 bytes, so make sure new/next sequence number
1921*c3324424SBrandon Wyman     std::vector<uint8_t> secondHistory{0x01, 0x54, 0xf3, 0x58, 0xf3};
1922*c3324424SBrandon Wyman     // Fourth read, 3rd sequence number (0x02).
1923*c3324424SBrandon Wyman     std::vector<uint8_t> thirdHistory{0x02, 0x54, 0xf3, 0x58, 0xf3};
1924*c3324424SBrandon Wyman     // Fifth read, out of sequence, clear and insert this one?
1925*c3324424SBrandon Wyman     std::vector<uint8_t> outseqHistory{0xff, 0x5c, 0xf3, 0x60, 0xf3};
1926*c3324424SBrandon Wyman     EXPECT_CALL(
1927*c3324424SBrandon Wyman         mockPMBus,
1928*c3324424SBrandon Wyman         readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug,
1929*c3324424SBrandon Wyman                    phosphor::power::history::RecordManager::RAW_RECORD_SIZE))
1930*c3324424SBrandon Wyman         .Times(6)
1931*c3324424SBrandon Wyman         .WillOnce(Return(emptyHistory))
1932*c3324424SBrandon Wyman         .WillOnce(Return(firstHistory))
1933*c3324424SBrandon Wyman         .WillOnce(Return(secondHistory))
1934*c3324424SBrandon Wyman         .WillOnce(Return(thirdHistory))
1935*c3324424SBrandon Wyman         .WillOnce(Return(outseqHistory))
1936*c3324424SBrandon Wyman         .WillOnce(Return(emptyHistory));
1937*c3324424SBrandon Wyman     // Calling analyze will update the presence, which will setup the input
1938*c3324424SBrandon Wyman     // history if the power supply went from missing to present.
1939*c3324424SBrandon Wyman     psu.analyze();
1940*c3324424SBrandon Wyman     // The ibm-cffps power supply should support input history
1941*c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
1942*c3324424SBrandon Wyman     // Usually should have empty buffer right after missing to present.
1943*c3324424SBrandon Wyman     // Faked that out above with mocked readBinary with emptyHistory data.
1944*c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
1945*c3324424SBrandon Wyman     // Second run through...
1946*c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
1947*c3324424SBrandon Wyman     psu.analyze();
1948*c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
1949*c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 1);
1950*c3324424SBrandon Wyman     // Third run through
1951*c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
1952*c3324424SBrandon Wyman     psu.analyze();
1953*c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
1954*c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 2);
1955*c3324424SBrandon Wyman     // Fourth run through. Up to 3 records now?
1956*c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
1957*c3324424SBrandon Wyman     psu.analyze();
1958*c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
1959*c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 3);
1960*c3324424SBrandon Wyman     // Out of sequencer, reset, insert new one.
1961*c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
1962*c3324424SBrandon Wyman     psu.analyze();
1963*c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
1964*c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 1);
1965*c3324424SBrandon Wyman     // Empty one after last one good. Reset/clear.
1966*c3324424SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
1967*c3324424SBrandon Wyman     psu.analyze();
1968*c3324424SBrandon Wyman     EXPECT_EQ(psu.hasInputHistory(), true);
1969*c3324424SBrandon Wyman     EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
1970*c3324424SBrandon Wyman }
1971