13f1242f3SBrandon Wyman #include "../power_supply.hpp"
23f1242f3SBrandon Wyman #include "mock.hpp"
33f1242f3SBrandon Wyman 
43f1242f3SBrandon Wyman #include <xyz/openbmc_project/Common/Device/error.hpp>
53f1242f3SBrandon Wyman #include <xyz/openbmc_project/Common/error.hpp>
63f1242f3SBrandon Wyman 
73f1242f3SBrandon Wyman #include <gmock/gmock.h>
83f1242f3SBrandon Wyman #include <gtest/gtest.h>
93f1242f3SBrandon Wyman 
103f1242f3SBrandon Wyman using namespace phosphor::power::psu;
113f1242f3SBrandon Wyman using namespace phosphor::pmbus;
123f1242f3SBrandon Wyman 
133f1242f3SBrandon Wyman using ::testing::_;
1459a35793SBrandon Wyman using ::testing::Args;
153f1242f3SBrandon Wyman using ::testing::Assign;
163f1242f3SBrandon Wyman using ::testing::DoAll;
1759a35793SBrandon Wyman using ::testing::ElementsAre;
1859a35793SBrandon Wyman using ::testing::NotNull;
193f1242f3SBrandon Wyman using ::testing::Return;
203f1242f3SBrandon Wyman using ::testing::StrEq;
213f1242f3SBrandon Wyman 
223f1242f3SBrandon Wyman static auto PSUInventoryPath = "/xyz/bmc/inv/sys/chassis/board/powersupply0";
23681b2a36SB. J. Wyman static auto PSUGPIOLineName = "presence-ps0";
243f1242f3SBrandon Wyman 
25b654c619SBrandon Wyman struct PMBusExpectations
26b654c619SBrandon Wyman {
27b654c619SBrandon Wyman     uint16_t statusWordValue{0x0000};
28b654c619SBrandon Wyman     uint8_t statusInputValue{0x00};
29b654c619SBrandon Wyman     uint8_t statusMFRValue{0x00};
30b654c619SBrandon Wyman     uint8_t statusCMLValue{0x00};
31b654c619SBrandon Wyman     uint8_t statusVOUTValue{0x00};
32b10b3be0SBrandon Wyman     uint8_t statusIOUTValue{0x00};
337ee4d7e4SBrandon Wyman     uint8_t statusFans12Value{0x00};
3496893a46SBrandon Wyman     uint8_t statusTempValue{0x00};
35b654c619SBrandon Wyman };
36b654c619SBrandon Wyman 
378da35c51SBrandon Wyman // Helper function to setup expectations for various STATUS_* commands
38b654c619SBrandon Wyman void setPMBusExpectations(MockedPMBus& mockPMBus,
39b654c619SBrandon Wyman                           const PMBusExpectations& expectations)
408da35c51SBrandon Wyman {
4132453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _, _))
428da35c51SBrandon Wyman         .Times(1)
43b654c619SBrandon Wyman         .WillOnce(Return(expectations.statusWordValue));
448da35c51SBrandon Wyman 
45b654c619SBrandon Wyman     if (expectations.statusWordValue != 0)
468da35c51SBrandon Wyman     {
478da35c51SBrandon Wyman         // If fault bits are on in STATUS_WORD, there will also be a read of
4896893a46SBrandon Wyman         // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and
4996893a46SBrandon Wyman         // STATUS_TEMPERATURE.
5032453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _, _))
518da35c51SBrandon Wyman             .Times(1)
52b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusInputValue));
5332453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_MFR, _, _))
548da35c51SBrandon Wyman             .Times(1)
55b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusMFRValue));
5632453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_CML, _, _))
578da35c51SBrandon Wyman             .Times(1)
58b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusCMLValue));
596710ba2cSBrandon Wyman         // Page will need to be set to 0 to read STATUS_VOUT.
606710ba2cSBrandon Wyman         EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0))
616710ba2cSBrandon Wyman             .Times(1)
626710ba2cSBrandon Wyman             .WillOnce(Return("status0_vout"));
6332453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read("status0_vout", _, _))
646710ba2cSBrandon Wyman             .Times(1)
65b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusVOUTValue));
6632453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _, _))
67b10b3be0SBrandon Wyman             .Times(1)
68b10b3be0SBrandon Wyman             .WillOnce(Return(expectations.statusIOUTValue));
6932453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _, _))
707ee4d7e4SBrandon Wyman             .Times(1)
717ee4d7e4SBrandon Wyman             .WillOnce(Return(expectations.statusFans12Value));
7232453e9bSBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _, _))
7396893a46SBrandon Wyman             .Times(1)
7496893a46SBrandon Wyman             .WillOnce(Return(expectations.statusTempValue));
758da35c51SBrandon Wyman     }
768da35c51SBrandon Wyman }
778da35c51SBrandon Wyman 
783f1242f3SBrandon Wyman class PowerSupplyTests : public ::testing::Test
793f1242f3SBrandon Wyman {
803f1242f3SBrandon Wyman   public:
813f1242f3SBrandon Wyman     PowerSupplyTests() :
823f1242f3SBrandon Wyman         mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
833f1242f3SBrandon Wyman     {
843f1242f3SBrandon Wyman         ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
853f1242f3SBrandon Wyman     }
863f1242f3SBrandon Wyman 
873f1242f3SBrandon Wyman     ~PowerSupplyTests() override
883f1242f3SBrandon Wyman     {
893f1242f3SBrandon Wyman         freeUtils();
903f1242f3SBrandon Wyman     }
913f1242f3SBrandon Wyman 
923f1242f3SBrandon Wyman     const MockedUtil& mockedUtil;
933f1242f3SBrandon Wyman };
943f1242f3SBrandon Wyman 
95391a0690SBrandon Wyman // Helper function for when a power supply goes from missing to present.
96391a0690SBrandon Wyman void setMissingToPresentExpects(MockedPMBus& pmbus, const MockedUtil& util)
97391a0690SBrandon Wyman {
98391a0690SBrandon Wyman     // Call to analyze() will update to present, that will trigger updating
99391a0690SBrandon Wyman     // to the correct/latest HWMON directory, in case it changes.
100391a0690SBrandon Wyman     EXPECT_CALL(pmbus, findHwmonDir());
101391a0690SBrandon Wyman     // Presence change from missing to present will trigger write to
102391a0690SBrandon Wyman     // ON_OFF_CONFIG.
103391a0690SBrandon Wyman     EXPECT_CALL(pmbus, writeBinary(ON_OFF_CONFIG, _, _));
104391a0690SBrandon Wyman     // Presence change from missing to present will trigger in1_input read
105391a0690SBrandon Wyman     // in an attempt to get CLEAR_FAULTS called.
10682affd94SBrandon Wyman     // This READ_VIN for CLEAR_FAULTS does not check the returned value.
107*3225a45cSBrandon Wyman     EXPECT_CALL(pmbus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
108*3225a45cSBrandon Wyman     // The call for clearing faults includes clearing VIN_UV fault.
109*3225a45cSBrandon Wyman     // The voltage defaults to 0, the first call to analyze should update the
110*3225a45cSBrandon Wyman     // voltage to the current reading, triggering clearing VIN_UV fault(s)
111*3225a45cSBrandon Wyman     // due to below minimum to within range voltage.
112*3225a45cSBrandon Wyman     EXPECT_CALL(pmbus, read("in1_lcrit_alarm", _, _))
11382affd94SBrandon Wyman         .Times(2)
114*3225a45cSBrandon Wyman         .WillRepeatedly(Return(1));
115391a0690SBrandon Wyman     // Missing/present call will update Presence in inventory.
116391a0690SBrandon Wyman     EXPECT_CALL(util, setPresence(_, _, true, _));
117391a0690SBrandon Wyman }
118391a0690SBrandon Wyman 
1193f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Constructor)
1203f1242f3SBrandon Wyman {
1213f1242f3SBrandon Wyman     /**
1223f1242f3SBrandon Wyman      * @param[in] invpath - String for inventory path to use
1233f1242f3SBrandon Wyman      * @param[in] i2cbus - The bus number this power supply is on
1243f1242f3SBrandon Wyman      * @param[in] i2caddr - The 16-bit I2C address of the power supply
125681b2a36SB. J. Wyman      * @param[in] gpioLineName - The string for the gpio-line-name to read for
126681b2a36SB. J. Wyman      * presence.
127681b2a36SB. J. Wyman      * @param[in] bindDelay - Time in milliseconds to delay binding the device
128681b2a36SB. J. Wyman      * driver after seeing the presence line go active.
1293f1242f3SBrandon Wyman      */
1303f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1311d7a7df8SBrandon Wyman 
1321d7a7df8SBrandon Wyman     // Try where inventory path is empty, constructor should fail.
1331d7a7df8SBrandon Wyman     try
1341d7a7df8SBrandon Wyman     {
135681b2a36SB. J. Wyman         auto psu =
136681b2a36SB. J. Wyman             std::make_unique<PowerSupply>(bus, "", 3, 0x68, PSUGPIOLineName);
1371d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have reached this line.";
1381d7a7df8SBrandon Wyman     }
1391d7a7df8SBrandon Wyman     catch (const std::invalid_argument& e)
1401d7a7df8SBrandon Wyman     {
1411d7a7df8SBrandon Wyman         EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
1421d7a7df8SBrandon Wyman     }
1431d7a7df8SBrandon Wyman     catch (...)
1441d7a7df8SBrandon Wyman     {
1451d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
1461d7a7df8SBrandon Wyman     }
1471d7a7df8SBrandon Wyman 
148681b2a36SB. J. Wyman     // TODO: Try invalid i2c address?
149681b2a36SB. J. Wyman 
150681b2a36SB. J. Wyman     // Try where gpioLineName is empty.
1511d7a7df8SBrandon Wyman     try
1521d7a7df8SBrandon Wyman     {
1531d7a7df8SBrandon Wyman         auto psu =
154681b2a36SB. J. Wyman             std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, "");
155681b2a36SB. J. Wyman         ADD_FAILURE()
156681b2a36SB. J. Wyman             << "Should not have reached this line. Invalid gpioLineName.";
157681b2a36SB. J. Wyman     }
158681b2a36SB. J. Wyman     catch (const std::invalid_argument& e)
159681b2a36SB. J. Wyman     {
160681b2a36SB. J. Wyman         EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
161681b2a36SB. J. Wyman     }
162681b2a36SB. J. Wyman     catch (...)
163681b2a36SB. J. Wyman     {
164681b2a36SB. J. Wyman         ADD_FAILURE() << "Should not have caught exception.";
165681b2a36SB. J. Wyman     }
166681b2a36SB. J. Wyman 
167681b2a36SB. J. Wyman     // Test with valid arguments
168681b2a36SB. J. Wyman     // NOT using D-Bus inventory path for presence.
169681b2a36SB. J. Wyman     try
170681b2a36SB. J. Wyman     {
171681b2a36SB. J. Wyman         auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
172681b2a36SB. J. Wyman                                                  PSUGPIOLineName);
1733f1242f3SBrandon Wyman 
1743f1242f3SBrandon Wyman         EXPECT_EQ(psu->isPresent(), false);
1753f1242f3SBrandon Wyman         EXPECT_EQ(psu->isFaulted(), false);
1768da35c51SBrandon Wyman         EXPECT_EQ(psu->hasCommFault(), false);
1773f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasInputFault(), false);
1783f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasMFRFault(), false);
1793f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasVINUVFault(), false);
1806710ba2cSBrandon Wyman         EXPECT_EQ(psu->hasVoutOVFault(), false);
181b10b3be0SBrandon Wyman         EXPECT_EQ(psu->hasIoutOCFault(), false);
1822cf46945SBrandon Wyman         EXPECT_EQ(psu->hasVoutUVFault(), false);
1837ee4d7e4SBrandon Wyman         EXPECT_EQ(psu->hasFanFault(), false);
18496893a46SBrandon Wyman         EXPECT_EQ(psu->hasTempFault(), false);
1852916ea52SBrandon Wyman         EXPECT_EQ(psu->hasPgoodFault(), false);
18639ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPSKillFault(), false);
18739ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPS12VcsFault(), false);
18839ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPSCS12VFault(), false);
1893f1242f3SBrandon Wyman     }
1901d7a7df8SBrandon Wyman     catch (...)
1911d7a7df8SBrandon Wyman     {
1921d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
1931d7a7df8SBrandon Wyman     }
194681b2a36SB. J. Wyman 
195681b2a36SB. J. Wyman     // Test with valid arguments
196681b2a36SB. J. Wyman     // TODO: Using D-Bus inventory path for presence.
197681b2a36SB. J. Wyman     try
198681b2a36SB. J. Wyman     {
199681b2a36SB. J. Wyman         // FIXME: How do I get that presenceGPIO.read() in the startup to throw
200681b2a36SB. J. Wyman         // an exception?
201681b2a36SB. J. Wyman 
202681b2a36SB. J. Wyman         // EXPECT_CALL(mockedUtil, getPresence(_,
203681b2a36SB. J. Wyman         // StrEq(PSUInventoryPath)))
204681b2a36SB. J. Wyman         //    .Times(1);
205681b2a36SB. J. Wyman     }
206681b2a36SB. J. Wyman     catch (...)
207681b2a36SB. J. Wyman     {
208681b2a36SB. J. Wyman         ADD_FAILURE() << "Should not have caught exception.";
209681b2a36SB. J. Wyman     }
2101d7a7df8SBrandon Wyman }
2113f1242f3SBrandon Wyman 
2123f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Analyze)
2133f1242f3SBrandon Wyman {
2143f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
2153f1242f3SBrandon Wyman 
216b654c619SBrandon Wyman     {
217681b2a36SB. J. Wyman         // If I default to reading the GPIO, I will NOT expect a call to
218681b2a36SB. J. Wyman         // getPresence().
219681b2a36SB. J. Wyman 
220681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
2213ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
2223ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
223681b2a36SB. J. Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
224681b2a36SB. J. Wyman 
2253f1242f3SBrandon Wyman         psu.analyze();
2263f1242f3SBrandon Wyman         // By default, nothing should change.
2273f1242f3SBrandon Wyman         EXPECT_EQ(psu.isPresent(), false);
2283f1242f3SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), false);
2293f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), false);
2303f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), false);
2313f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), false);
23285c7bf41SBrandon Wyman         EXPECT_EQ(psu.hasCommFault(), false);
2336710ba2cSBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), false);
234b10b3be0SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), false);
2352cf46945SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), false);
2367ee4d7e4SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), false);
23796893a46SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), false);
2382916ea52SBrandon Wyman         EXPECT_EQ(psu.hasPgoodFault(), false);
23939ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), false);
24039ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), false);
24139ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), false);
242b654c619SBrandon Wyman     }
2433f1242f3SBrandon Wyman 
244681b2a36SB. J. Wyman     PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
245681b2a36SB. J. Wyman     // In order to get the various faults tested, the power supply needs to
246681b2a36SB. J. Wyman     // be present in order to read from the PMBus device(s).
2473ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO2 =
2483ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
24906ca4590SBrandon Wyman     // Always return 1 to indicate present.
25006ca4590SBrandon Wyman     // Each analyze() call will trigger a read of the presence GPIO.
25106ca4590SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1));
252681b2a36SB. J. Wyman     EXPECT_EQ(psu2.isPresent(), false);
2533f1242f3SBrandon Wyman 
2543f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
255391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
256b654c619SBrandon Wyman 
257b654c619SBrandon Wyman     // STATUS_WORD INPUT fault.
258b654c619SBrandon Wyman     {
259b654c619SBrandon Wyman         // Start with STATUS_WORD 0x0000. Powered on, no faults.
260b654c619SBrandon Wyman         // Set expectations for a no fault
261b654c619SBrandon Wyman         PMBusExpectations expectations;
262b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
26382affd94SBrandon Wyman         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
26482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
26582affd94SBrandon Wyman             .Times(1)
26682affd94SBrandon Wyman             .WillOnce(Return("206000"));
2673f1242f3SBrandon Wyman         psu2.analyze();
2683f1242f3SBrandon Wyman         EXPECT_EQ(psu2.isPresent(), true);
2693f1242f3SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
2703f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
2713f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasMFRFault(), false);
2723f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasVINUVFault(), false);
27385c7bf41SBrandon Wyman         EXPECT_EQ(psu2.hasCommFault(), false);
2746710ba2cSBrandon Wyman         EXPECT_EQ(psu2.hasVoutOVFault(), false);
275b10b3be0SBrandon Wyman         EXPECT_EQ(psu2.hasIoutOCFault(), false);
2762cf46945SBrandon Wyman         EXPECT_EQ(psu2.hasVoutUVFault(), false);
2777ee4d7e4SBrandon Wyman         EXPECT_EQ(psu2.hasFanFault(), false);
27896893a46SBrandon Wyman         EXPECT_EQ(psu2.hasTempFault(), false);
2792916ea52SBrandon Wyman         EXPECT_EQ(psu2.hasPgoodFault(), false);
28039ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPSKillFault(), false);
28139ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPS12VcsFault(), false);
28239ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPSCS12VFault(), false);
2833f1242f3SBrandon Wyman 
284b654c619SBrandon Wyman         // Update expectations for STATUS_WORD input fault/warn
28596893a46SBrandon Wyman         // STATUS_INPUT fault bits ... on.
286b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
287*3225a45cSBrandon Wyman         // IIN_OC fault.
288*3225a45cSBrandon Wyman         expectations.statusInputValue = 0x04;
289c2906f47SBrandon Wyman 
290c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
291c2906f47SBrandon Wyman         {
292b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
29382affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
29482affd94SBrandon Wyman                 .Times(1)
29582affd94SBrandon Wyman                 .WillOnce(Return("207000"));
2963f1242f3SBrandon Wyman             psu2.analyze();
2973f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
298c2906f47SBrandon Wyman             // Should not be faulted until it reaches the deglitch limit.
299c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
300c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
3013f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
3023f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
30385c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
3046710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
305b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
3062cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
3077ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
30896893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
3092916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
31039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
31139ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
31239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
313b654c619SBrandon Wyman         }
314c2906f47SBrandon Wyman     }
315c2906f47SBrandon Wyman 
31632453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
317*3225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
318*3225a45cSBrandon Wyman         .Times(1)
319*3225a45cSBrandon Wyman         .WillOnce(Return(1));
320c2906f47SBrandon Wyman     psu2.clearFaults();
3213f1242f3SBrandon Wyman 
3223f1242f3SBrandon Wyman     // STATUS_WORD INPUT/UV fault.
323b654c619SBrandon Wyman     {
3243f1242f3SBrandon Wyman         // First need it to return good status, then the fault
325b654c619SBrandon Wyman         PMBusExpectations expectations;
326b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
32782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
32882affd94SBrandon Wyman             .Times(1)
32982affd94SBrandon Wyman             .WillOnce(Return("208000"));
3303f1242f3SBrandon Wyman         psu2.analyze();
331c2906f47SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
332c2906f47SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
3338da35c51SBrandon Wyman         // Now set fault bits in STATUS_WORD
334b654c619SBrandon Wyman         expectations.statusWordValue =
3358da35c51SBrandon Wyman             (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
3368da35c51SBrandon Wyman         // STATUS_INPUT fault bits ... on.
337*3225a45cSBrandon Wyman         expectations.statusInputValue = 0x18;
338c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
339c2906f47SBrandon Wyman         {
340b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
34182affd94SBrandon Wyman             // Input/UV fault, so voltage should read back low.
34282affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
34382affd94SBrandon Wyman                 .Times(1)
34482affd94SBrandon Wyman                 .WillOnce(Return("19123"));
3453f1242f3SBrandon Wyman             psu2.analyze();
3463f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
347c2906f47SBrandon Wyman             // Only faulted if hit deglitch limit
348c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
349c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
350c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), x >= DEGLITCH_LIMIT);
3513f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
35285c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
3536710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
354b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
3552cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
3567ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
35796893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
3582916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
35939ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
36039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
36139ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
362c2906f47SBrandon Wyman         }
36382affd94SBrandon Wyman         // Turning VIN_UV fault off causes clearing of faults, causing read of
36482affd94SBrandon Wyman         // in1_input as an attempt to get CLEAR_FAULTS called.
36582affd94SBrandon Wyman         expectations.statusWordValue = 0;
36682affd94SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
36782affd94SBrandon Wyman         // The call to read the voltage
36882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
36982affd94SBrandon Wyman             .Times(1)
37082affd94SBrandon Wyman             .WillOnce(Return("209000"));
371*3225a45cSBrandon Wyman         // The call to clear VIN_UV/Off fault(s)
372*3225a45cSBrandon Wyman         EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
37332453e9bSBrandon Wyman             .Times(1)
374*3225a45cSBrandon Wyman             .WillOnce(Return(1));
37582affd94SBrandon Wyman         psu2.analyze();
37682affd94SBrandon Wyman         // Should remain present, no longer be faulted, no input fault, no
37782affd94SBrandon Wyman         // VIN_UV fault. Nothing else should change.
37882affd94SBrandon Wyman         EXPECT_EQ(psu2.isPresent(), true);
37982affd94SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
38082affd94SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
38182affd94SBrandon Wyman         EXPECT_EQ(psu2.hasVINUVFault(), false);
382b654c619SBrandon Wyman     }
3833f1242f3SBrandon Wyman 
38432453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
385*3225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
386*3225a45cSBrandon Wyman         .Times(1)
387*3225a45cSBrandon Wyman         .WillOnce(Return(1));
388c2906f47SBrandon Wyman     psu2.clearFaults();
389c2906f47SBrandon Wyman 
3903f1242f3SBrandon Wyman     // STATUS_WORD MFR fault.
391b654c619SBrandon Wyman     {
392f07bc797SBrandon Wyman         // First need it to return good status, then the fault
393b654c619SBrandon Wyman         PMBusExpectations expectations;
394b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
39582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
39682affd94SBrandon Wyman             .Times(1)
39782affd94SBrandon Wyman             .WillOnce(Return("210000"));
3983f1242f3SBrandon Wyman         psu2.analyze();
3998da35c51SBrandon Wyman         // Now STATUS_WORD with MFR fault bit on.
400b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
4018da35c51SBrandon Wyman         // STATUS_MFR bits on.
402b654c619SBrandon Wyman         expectations.statusMFRValue = 0xFF;
403c2906f47SBrandon Wyman 
404c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
405c2906f47SBrandon Wyman         {
406b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
40782affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
40882affd94SBrandon Wyman                 .Times(1)
40982affd94SBrandon Wyman                 .WillOnce(Return("211000"));
4103f1242f3SBrandon Wyman             psu2.analyze();
4113f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
412c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
4133f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
414c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT);
415c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT);
416c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
417c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
4183f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
41985c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
4206710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
421b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
4222cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
4237ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
42496893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
4252916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
426c2906f47SBrandon Wyman         }
427b654c619SBrandon Wyman     }
4283f1242f3SBrandon Wyman 
42932453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
430*3225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
431*3225a45cSBrandon Wyman         .Times(1)
432*3225a45cSBrandon Wyman         .WillOnce(Return(1));
433c2906f47SBrandon Wyman     psu2.clearFaults();
434*3225a45cSBrandon Wyman 
43596893a46SBrandon Wyman     // Temperature fault.
436b654c619SBrandon Wyman     {
437f07bc797SBrandon Wyman         // First STATUS_WORD with no bits set, then with temperature fault.
438b654c619SBrandon Wyman         PMBusExpectations expectations;
439b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
44082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
44182affd94SBrandon Wyman             .Times(1)
44282affd94SBrandon Wyman             .WillOnce(Return("212000"));
4433f1242f3SBrandon Wyman         psu2.analyze();
4448da35c51SBrandon Wyman         // STATUS_WORD with temperature fault bit on.
445b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
44696893a46SBrandon Wyman         // STATUS_TEMPERATURE with fault bit(s) on.
44796893a46SBrandon Wyman         expectations.statusTempValue = 0x10;
448c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
449c2906f47SBrandon Wyman         {
450b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
45182affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
45282affd94SBrandon Wyman                 .Times(1)
45382affd94SBrandon Wyman                 .WillOnce(Return("213000"));
4543f1242f3SBrandon Wyman             psu2.analyze();
4553f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
456c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
4573f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
4583f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
4593f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
46085c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
4616710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
462b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
4632cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
4647ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
465c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT);
4662916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
46739ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
46839ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
46939ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
470b654c619SBrandon Wyman         }
471c2906f47SBrandon Wyman     }
47285c7bf41SBrandon Wyman 
47332453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
474*3225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
475*3225a45cSBrandon Wyman         .Times(1)
476*3225a45cSBrandon Wyman         .WillOnce(Return(1));
477c2906f47SBrandon Wyman     psu2.clearFaults();
478*3225a45cSBrandon Wyman 
47985c7bf41SBrandon Wyman     // CML fault
480b654c619SBrandon Wyman     {
48185c7bf41SBrandon Wyman         // First STATUS_WORD wit no bits set, then with CML fault.
482b654c619SBrandon Wyman         PMBusExpectations expectations;
483b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
48482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
48582affd94SBrandon Wyman             .Times(1)
48682affd94SBrandon Wyman             .WillOnce(Return("214000"));
48785c7bf41SBrandon Wyman         psu2.analyze();
4888da35c51SBrandon Wyman         // STATUS_WORD with CML fault bit on.
489b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::CML_FAULT);
49085c7bf41SBrandon Wyman         // Turn on STATUS_CML fault bit(s)
491b654c619SBrandon Wyman         expectations.statusCMLValue = 0xFF;
492c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
493c2906f47SBrandon Wyman         {
494b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
49582affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
49682affd94SBrandon Wyman                 .Times(1)
49782affd94SBrandon Wyman                 .WillOnce(Return("215000"));
49885c7bf41SBrandon Wyman             psu2.analyze();
49985c7bf41SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
500c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
501c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), x >= DEGLITCH_LIMIT);
50285c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
50385c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
50485c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
5056710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
506b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
5072cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
5087ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
50996893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
5102916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
51139ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
51239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
51339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
514b654c619SBrandon Wyman         }
515c2906f47SBrandon Wyman     }
5166710ba2cSBrandon Wyman 
51732453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
518*3225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
519*3225a45cSBrandon Wyman         .Times(1)
520*3225a45cSBrandon Wyman         .WillOnce(Return(1));
521c2906f47SBrandon Wyman     psu2.clearFaults();
522*3225a45cSBrandon Wyman 
5236710ba2cSBrandon Wyman     // VOUT_OV_FAULT fault
524b654c619SBrandon Wyman     {
5256710ba2cSBrandon Wyman         // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
526b654c619SBrandon Wyman         PMBusExpectations expectations;
527b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
52882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
52982affd94SBrandon Wyman             .Times(1)
53082affd94SBrandon Wyman             .WillOnce(Return("216000"));
5316710ba2cSBrandon Wyman         psu2.analyze();
5326710ba2cSBrandon Wyman         // STATUS_WORD with VOUT/VOUT_OV fault.
533b654c619SBrandon Wyman         expectations.statusWordValue =
5346710ba2cSBrandon Wyman             ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
5356710ba2cSBrandon Wyman         // Turn on STATUS_VOUT fault bit(s)
536b654c619SBrandon Wyman         expectations.statusVOUTValue = 0xA0;
537c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
538c2906f47SBrandon Wyman         {
53996893a46SBrandon Wyman             // STATUS_TEMPERATURE don't care (default)
540b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
54182affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
54282affd94SBrandon Wyman                 .Times(1)
54382affd94SBrandon Wyman                 .WillOnce(Return("217000"));
5446710ba2cSBrandon Wyman             psu2.analyze();
5456710ba2cSBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
546c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
5476710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
5486710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
5496710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
5506710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
551c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
5522cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
553b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
5547ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
555b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
556b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
55739ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
55839ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
55939ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
560b10b3be0SBrandon Wyman         }
561c2906f47SBrandon Wyman     }
562b10b3be0SBrandon Wyman 
563b10b3be0SBrandon Wyman     // IOUT_OC_FAULT fault
564b10b3be0SBrandon Wyman     {
565b10b3be0SBrandon Wyman         // First STATUS_WORD with no bits set, then with IOUT_OC fault.
566b10b3be0SBrandon Wyman         PMBusExpectations expectations;
567b10b3be0SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
56882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
56982affd94SBrandon Wyman             .Times(1)
57082affd94SBrandon Wyman             .WillOnce(Return("218000"));
571b10b3be0SBrandon Wyman         psu2.analyze();
572b10b3be0SBrandon Wyman         // STATUS_WORD with IOUT_OC fault.
573b10b3be0SBrandon Wyman         expectations.statusWordValue = status_word::IOUT_OC_FAULT;
574b10b3be0SBrandon Wyman         // Turn on STATUS_IOUT fault bit(s)
575b10b3be0SBrandon Wyman         expectations.statusIOUTValue = 0x88;
576c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
577c2906f47SBrandon Wyman         {
578b10b3be0SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
57982affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
58082affd94SBrandon Wyman                 .Times(1)
58182affd94SBrandon Wyman                 .WillOnce(Return("219000"));
582b10b3be0SBrandon Wyman             psu2.analyze();
583b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
584c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
585b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
586b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
587b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
588b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
589b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
590c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
5912cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
5927ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
5932cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
5942cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
59539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
59639ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
59739ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
5982cf46945SBrandon Wyman         }
599c2906f47SBrandon Wyman     }
6002cf46945SBrandon Wyman 
6012cf46945SBrandon Wyman     // VOUT_UV_FAULT
6022cf46945SBrandon Wyman     {
6032cf46945SBrandon Wyman         // First STATUS_WORD with no bits set, then with VOUT fault.
6042cf46945SBrandon Wyman         PMBusExpectations expectations;
6052cf46945SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
60682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
60782affd94SBrandon Wyman             .Times(1)
60882affd94SBrandon Wyman             .WillOnce(Return("220000"));
6092cf46945SBrandon Wyman         psu2.analyze();
6102cf46945SBrandon Wyman         // Change STATUS_WORD to indicate VOUT fault.
6112cf46945SBrandon Wyman         expectations.statusWordValue = (status_word::VOUT_FAULT);
6122cf46945SBrandon Wyman         // Turn on STATUS_VOUT fault bit(s)
6132cf46945SBrandon Wyman         expectations.statusVOUTValue = 0x30;
614c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
615c2906f47SBrandon Wyman         {
6162cf46945SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
61782affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
61882affd94SBrandon Wyman                 .Times(1)
61982affd94SBrandon Wyman                 .WillOnce(Return("221000"));
6202cf46945SBrandon Wyman             psu2.analyze();
6212cf46945SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
622c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
6232cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
6242cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
6252cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
6262cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
6272cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
6282cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
629c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
6307ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
63196893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6322916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
63339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
63439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
63539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
636b654c619SBrandon Wyman         }
637c2906f47SBrandon Wyman     }
6383f1242f3SBrandon Wyman 
6397ee4d7e4SBrandon Wyman     // Fan fault
640b654c619SBrandon Wyman     {
641b654c619SBrandon Wyman         // First STATUS_WORD with no bits set, then with fan fault.
642b654c619SBrandon Wyman         PMBusExpectations expectations;
643b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
64482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
64582affd94SBrandon Wyman             .Times(1)
64682affd94SBrandon Wyman             .WillOnce(Return("222000"));
6473f1242f3SBrandon Wyman         psu2.analyze();
648b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::FAN_FAULT);
6497ee4d7e4SBrandon Wyman         // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
6507ee4d7e4SBrandon Wyman         expectations.statusFans12Value = 0xA0;
651c2906f47SBrandon Wyman 
652c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
653c2906f47SBrandon Wyman         {
654b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
65582affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
65682affd94SBrandon Wyman                 .Times(1)
65782affd94SBrandon Wyman                 .WillOnce(Return("223000"));
6583f1242f3SBrandon Wyman             psu2.analyze();
6593f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
660c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
661c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT);
6623f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
6633f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
6643f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
66585c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
6666710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
667b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
6682cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
66996893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6702916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
67139ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
67239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
67339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
674b654c619SBrandon Wyman         }
675c2906f47SBrandon Wyman     }
6762916ea52SBrandon Wyman 
67706ca4590SBrandon Wyman     // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
6782cf46945SBrandon Wyman     {
6792916ea52SBrandon Wyman         // First STATUS_WORD with no bits set.
6802916ea52SBrandon Wyman         PMBusExpectations expectations;
6812916ea52SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
68282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
68382affd94SBrandon Wyman             .Times(1)
68482affd94SBrandon Wyman             .WillOnce(Return("123000"));
6852916ea52SBrandon Wyman         psu2.analyze();
6862916ea52SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
6872916ea52SBrandon Wyman         // POWER_GOOD# inactive, and OFF bit on.
6882916ea52SBrandon Wyman         expectations.statusWordValue =
6892916ea52SBrandon Wyman             ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
69006ca4590SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
69106ca4590SBrandon Wyman         {
6922916ea52SBrandon Wyman             // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
6932916ea52SBrandon Wyman             // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
6942916ea52SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
69582affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
69682affd94SBrandon Wyman                 .Times(1)
69782affd94SBrandon Wyman                 .WillOnce(Return("124000"));
6982916ea52SBrandon Wyman             psu2.analyze();
6992916ea52SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
700c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
7012916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
7022916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
7032916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
7042916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
7052916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
7062cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
707b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
7087ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
7092916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
71032453e9bSBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), x >= DEGLITCH_LIMIT);
71106ca4590SBrandon Wyman         }
71206ca4590SBrandon Wyman     }
7132916ea52SBrandon Wyman 
7143f1242f3SBrandon Wyman     // TODO: ReadFailure
7153f1242f3SBrandon Wyman }
7163f1242f3SBrandon Wyman 
71759a35793SBrandon Wyman TEST_F(PowerSupplyTests, OnOffConfig)
71859a35793SBrandon Wyman {
71959a35793SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
72059a35793SBrandon Wyman     uint8_t data = 0x15;
72159a35793SBrandon Wyman 
72259a35793SBrandon Wyman     // Test where PSU is NOT present
72359a35793SBrandon Wyman     try
72459a35793SBrandon Wyman     {
725681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
7260975eaf4SMatt Spinler         EXPECT_CALL(mockedUtil, setAvailable(_, _, _)).Times(0);
727681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
728681b2a36SB. J. Wyman 
7293ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
7303ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
731681b2a36SB. J. Wyman         ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
73259a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
733681b2a36SB. J. Wyman         // Constructor should set initial presence, default read returns 0.
73459a35793SBrandon Wyman         // If it is not present, I should not be trying to write to it.
73559a35793SBrandon Wyman         EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
73659a35793SBrandon Wyman         psu.onOffConfig(data);
73759a35793SBrandon Wyman     }
73859a35793SBrandon Wyman     catch (...)
7390c9a33d6SAdriana Kobylak     {}
74059a35793SBrandon Wyman 
74159a35793SBrandon Wyman     // Test where PSU is present
74259a35793SBrandon Wyman     try
74359a35793SBrandon Wyman     {
744681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
7450975eaf4SMatt Spinler         EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
746681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
7473ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
7483ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
749391a0690SBrandon Wyman         // There will potentially be multiple calls, we want it to continue
750391a0690SBrandon Wyman         // returning 1 for the GPIO read to keep the power supply present.
751391a0690SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
75259a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
753391a0690SBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
754391a0690SBrandon Wyman         // If I am calling analyze(), I should probably give it good data.
755391a0690SBrandon Wyman         // STATUS_WORD 0x0000 is powered on, no faults.
756391a0690SBrandon Wyman         PMBusExpectations expectations;
757391a0690SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
75882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
75982affd94SBrandon Wyman             .Times(1)
76082affd94SBrandon Wyman             .WillOnce(Return("205000"));
761681b2a36SB. J. Wyman         psu.analyze();
762391a0690SBrandon Wyman         // I definitely should be writting ON_OFF_CONFIG if I call the function
763391a0690SBrandon Wyman         EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
764391a0690SBrandon Wyman                                            Type::HwmonDeviceDebug))
76559a35793SBrandon Wyman             .Times(1);
76659a35793SBrandon Wyman         psu.onOffConfig(data);
76759a35793SBrandon Wyman     }
76859a35793SBrandon Wyman     catch (...)
7690c9a33d6SAdriana Kobylak     {}
77059a35793SBrandon Wyman }
77159a35793SBrandon Wyman 
7723f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, ClearFaults)
7733f1242f3SBrandon Wyman {
7743f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
775681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName};
7763ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
7773ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
77806ca4590SBrandon Wyman     // Always return 1 to indicate present.
77906ca4590SBrandon Wyman     // Each analyze() call will trigger a read of the presence GPIO.
78006ca4590SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
781681b2a36SB. J. Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
782391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
7838da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
784b654c619SBrandon Wyman     PMBusExpectations expectations;
785b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
78682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
78782affd94SBrandon Wyman         .Times(1)
78882affd94SBrandon Wyman         .WillOnce(Return("207000"));
789681b2a36SB. J. Wyman     psu.analyze();
7903f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
7913f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
7923f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
7933f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
7943f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
79585c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
7966710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
797b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
7982cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
7997ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
80096893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
8012916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
80239ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
80339ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
80439ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
805b654c619SBrandon Wyman 
806f07bc797SBrandon Wyman     // STATUS_WORD with fault bits galore!
807b654c619SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
808f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
809b654c619SBrandon Wyman     expectations.statusInputValue = 0xFF;
810f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
811b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
81285c7bf41SBrandon Wyman     // STATUS_CML with bits on.
813b654c619SBrandon Wyman     expectations.statusCMLValue = 0xFF;
8146710ba2cSBrandon Wyman     // STATUS_VOUT with bits on.
815b654c619SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
816b10b3be0SBrandon Wyman     // STATUS_IOUT with bits on.
817b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
8187ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
8197ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0xFF;
82096893a46SBrandon Wyman     // STATUS_TEMPERATURE with bits on.
82196893a46SBrandon Wyman     expectations.statusTempValue = 0xFF;
822c2906f47SBrandon Wyman 
823c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
824c2906f47SBrandon Wyman     {
825b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
82682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
82782affd94SBrandon Wyman             .Times(1)
82882affd94SBrandon Wyman             .WillOnce(Return("0"));
8290975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
8300975eaf4SMatt Spinler         {
8310975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
8320975eaf4SMatt Spinler         }
8333f1242f3SBrandon Wyman         psu.analyze();
8343f1242f3SBrandon Wyman         EXPECT_EQ(psu.isPresent(), true);
8352cf46945SBrandon Wyman         // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
8362cf46945SBrandon Wyman         // Rely on HasVoutUVFault() to verify this sets and clears.
8372cf46945SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), false);
838c2906f47SBrandon Wyman         // All faults are deglitched up to DEGLITCH_LIMIT
839c2906f47SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
840c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
841c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
842c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
843c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT);
844c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
845c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
846c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
847c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
848c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPgoodFault(), x >= DEGLITCH_LIMIT);
849c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
850c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
851c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
852c2906f47SBrandon Wyman     }
853c2906f47SBrandon Wyman 
85432453e9bSBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _))
85532453e9bSBrandon Wyman         .Times(1)
85632453e9bSBrandon Wyman         .WillOnce(Return(207000));
857*3225a45cSBrandon Wyman     // Clearing VIN_UV fault via in1_lcrit_alarm
858*3225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
859*3225a45cSBrandon Wyman         .Times(1)
860*3225a45cSBrandon Wyman         .WillOnce(Return(1));
8610975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
8623f1242f3SBrandon Wyman     psu.clearFaults();
8633f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
8643f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
8653f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
8663f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
8673f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
86885c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
8696710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
870b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
8712cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
8727ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
87396893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
8742916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
87539ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
87639ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
87739ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
878681b2a36SB. J. Wyman 
87982affd94SBrandon Wyman     // Faults clear on READ_VIN 0 -> !0
88082affd94SBrandon Wyman     // STATUS_WORD with fault bits galore!
88182affd94SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
88282affd94SBrandon Wyman     // STATUS_INPUT with fault bits on.
88382affd94SBrandon Wyman     expectations.statusInputValue = 0xFF;
88482affd94SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
88582affd94SBrandon Wyman     expectations.statusMFRValue = 0xFF;
88682affd94SBrandon Wyman     // STATUS_CML with bits on.
88782affd94SBrandon Wyman     expectations.statusCMLValue = 0xFF;
88882affd94SBrandon Wyman     // STATUS_VOUT with bits on.
88982affd94SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
89082affd94SBrandon Wyman     // STATUS_IOUT with bits on.
89182affd94SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
89282affd94SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
89382affd94SBrandon Wyman     expectations.statusFans12Value = 0xFF;
89482affd94SBrandon Wyman     // STATUS_TEMPERATURE with bits on.
89582affd94SBrandon Wyman     expectations.statusTempValue = 0xFF;
896c2906f47SBrandon Wyman 
897c2906f47SBrandon Wyman     // All faults degltiched now. Check for false before limit above.
898c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
899c2906f47SBrandon Wyman     {
90082affd94SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
90182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
90282affd94SBrandon Wyman             .Times(1)
90382affd94SBrandon Wyman             .WillOnce(Return("0"));
9040975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
9050975eaf4SMatt Spinler         {
9060975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
9070975eaf4SMatt Spinler         }
90882affd94SBrandon Wyman         psu.analyze();
909c2906f47SBrandon Wyman     }
910c2906f47SBrandon Wyman 
91182affd94SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
91282affd94SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
91382affd94SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), true);
91482affd94SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
91582affd94SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), true);
91682affd94SBrandon Wyman     // True due to CML fault bits on
91782affd94SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), true);
91882affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
91982affd94SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), true);
92082affd94SBrandon Wyman     // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
92182affd94SBrandon Wyman     // Rely on HasVoutUVFault() to verify this sets and clears.
92282affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
92382affd94SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), true);
92482affd94SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), true);
925c2906f47SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
92682affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), true);
92782affd94SBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), true);
92882affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), true);
92982affd94SBrandon Wyman     // STATUS_WORD with INPUT/VIN_UV fault bits off.
93082affd94SBrandon Wyman     expectations.statusWordValue = 0xDFF7;
93182affd94SBrandon Wyman     // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
93282affd94SBrandon Wyman     // Insufficient Input Voltage bits off.
93382affd94SBrandon Wyman     expectations.statusInputValue = 0xC7;
93482affd94SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
93582affd94SBrandon Wyman     // READ_VIN back in range.
93682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
93782affd94SBrandon Wyman         .Times(1)
93882affd94SBrandon Wyman         .WillOnce(Return("206000"));
939*3225a45cSBrandon Wyman     // VIN_UV cleared via in1_lcrit_alarm when voltage back in range.
940*3225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
941*3225a45cSBrandon Wyman         .Times(1)
942*3225a45cSBrandon Wyman         .WillOnce(Return(1));
943*3225a45cSBrandon Wyman     psu.analyze();
944*3225a45cSBrandon Wyman     // We only cleared the VIN_UV and OFF faults.
945*3225a45cSBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
946*3225a45cSBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
947*3225a45cSBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
948*3225a45cSBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
949*3225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
950*3225a45cSBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), true);
951*3225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
952*3225a45cSBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), true);
953*3225a45cSBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
954*3225a45cSBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), true);
955*3225a45cSBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), true);
956*3225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
957*3225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), true);
958*3225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), true);
959*3225a45cSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), true);
960*3225a45cSBrandon Wyman 
961*3225a45cSBrandon Wyman     // All faults cleared
962*3225a45cSBrandon Wyman     expectations = {0};
963*3225a45cSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
964*3225a45cSBrandon Wyman     // READ_VIN back in range.
965*3225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
966*3225a45cSBrandon Wyman         .Times(1)
967*3225a45cSBrandon Wyman         .WillOnce(Return("206000"));
9680975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
96982affd94SBrandon Wyman     psu.analyze();
97082affd94SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
97182affd94SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
97282affd94SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
97382affd94SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
97482affd94SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
97582affd94SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
97682affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
97782affd94SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
97882affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
97982affd94SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
98082affd94SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
98182affd94SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
98282affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
98382affd94SBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
98482affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
98582affd94SBrandon Wyman 
986681b2a36SB. J. Wyman     // TODO: Faults clear on missing/present?
9873f1242f3SBrandon Wyman }
9883f1242f3SBrandon Wyman 
9893f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, UpdateInventory)
9903f1242f3SBrandon Wyman {
9913f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
9921d7a7df8SBrandon Wyman 
9931d7a7df8SBrandon Wyman     try
9941d7a7df8SBrandon Wyman     {
995681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
9961d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
9971d7a7df8SBrandon Wyman         // If it is not present, I should not be trying to read a string
9981d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
9991d7a7df8SBrandon Wyman         psu.updateInventory();
10001d7a7df8SBrandon Wyman     }
10011d7a7df8SBrandon Wyman     catch (...)
10021d7a7df8SBrandon Wyman     {
10031d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
10041d7a7df8SBrandon Wyman     }
10051d7a7df8SBrandon Wyman 
10061d7a7df8SBrandon Wyman     try
10071d7a7df8SBrandon Wyman     {
1008681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName};
10093ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
10103ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1011681b2a36SB. J. Wyman         // GPIO read return 1 to indicate present.
1012681b2a36SB. J. Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
10131d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1014391a0690SBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
1015391a0690SBrandon Wyman         // STATUS_WORD 0x0000 is powered on, no faults.
1016391a0690SBrandon Wyman         PMBusExpectations expectations;
1017391a0690SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
101882affd94SBrandon Wyman         // Call to analyze will read voltage, trigger clear faults for 0 to
101982affd94SBrandon Wyman         // within range.
102082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
102182affd94SBrandon Wyman             .Times(1)
102282affd94SBrandon Wyman             .WillOnce(Return("123456"));
1023391a0690SBrandon Wyman         psu.analyze();
10241d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
10253f1242f3SBrandon Wyman         psu.updateInventory();
10261d7a7df8SBrandon Wyman 
10273c530fbdSBrandon Wyman #if IBM_VPD
10281d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _))
10291d7a7df8SBrandon Wyman             .WillOnce(Return("CCIN"))
10301d7a7df8SBrandon Wyman             .WillOnce(Return("PN3456"))
10311d7a7df8SBrandon Wyman             .WillOnce(Return("FN3456"))
10321d7a7df8SBrandon Wyman             .WillOnce(Return("HEADER"))
10331d7a7df8SBrandon Wyman             .WillOnce(Return("SN3456"))
10341d7a7df8SBrandon Wyman             .WillOnce(Return("FW3456"));
10353c530fbdSBrandon Wyman #endif
10361d7a7df8SBrandon Wyman         psu.updateInventory();
10371d7a7df8SBrandon Wyman         // TODO: D-Bus mocking to verify values stored on D-Bus (???)
10381d7a7df8SBrandon Wyman     }
10391d7a7df8SBrandon Wyman     catch (...)
10401d7a7df8SBrandon Wyman     {
10411d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
10421d7a7df8SBrandon Wyman     }
10433f1242f3SBrandon Wyman }
10443f1242f3SBrandon Wyman 
10453f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsPresent)
10463f1242f3SBrandon Wyman {
10473f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1048681b2a36SB. J. Wyman 
1049681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
10503ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
10513ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
10523f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), false);
10533f1242f3SBrandon Wyman 
1054681b2a36SB. J. Wyman     // Change GPIO read to return 1 to indicate present.
1055681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
1056391a0690SBrandon Wyman     // Call to analyze() will update to present, that will trigger updating
1057391a0690SBrandon Wyman     // to the correct/latest HWMON directory, in case it changes.
1058391a0690SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1059391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1060391a0690SBrandon Wyman     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1061391a0690SBrandon Wyman     // Default expectations will be on, no faults.
1062391a0690SBrandon Wyman     PMBusExpectations expectations;
1063391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
106482affd94SBrandon Wyman     // Give it an input voltage in the 100-volt range.
106582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
106682affd94SBrandon Wyman         .Times(1)
106782affd94SBrandon Wyman         .WillOnce(Return("123456"));
10680975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1069681b2a36SB. J. Wyman     psu.analyze();
1070681b2a36SB. J. Wyman     EXPECT_EQ(psu.isPresent(), true);
10713f1242f3SBrandon Wyman }
10723f1242f3SBrandon Wyman 
10733f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsFaulted)
10743f1242f3SBrandon Wyman {
10753f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1076681b2a36SB. J. Wyman 
1077681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName};
10783ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
10793ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1080681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1081681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1082391a0690SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1083391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1084391a0690SBrandon Wyman     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1085391a0690SBrandon Wyman     // Default expectations will be on, no faults.
1086391a0690SBrandon Wyman     PMBusExpectations expectations;
1087391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
108882affd94SBrandon Wyman     // Give it an input voltage in the 100-volt range.
108982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
109082affd94SBrandon Wyman         .Times(1)
109182affd94SBrandon Wyman         .WillOnce(Return("124680"));
1092681b2a36SB. J. Wyman     psu.analyze();
10933f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
1094f07bc797SBrandon Wyman     // STATUS_WORD with fault bits on.
1095b654c619SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
1096f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
1097b654c619SBrandon Wyman     expectations.statusInputValue = 0xFF;
1098f07bc797SBrandon Wyman     // STATUS_MFR_SPECIFIC with faults bits on.
1099b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
110085c7bf41SBrandon Wyman     // STATUS_CML with faults bits on.
1101b654c619SBrandon Wyman     expectations.statusCMLValue = 0xFF;
11026710ba2cSBrandon Wyman     // STATUS_VOUT with fault bits on.
1103b654c619SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
1104b10b3be0SBrandon Wyman     // STATUS_IOUT with fault bits on.
1105b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
11067ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
11077ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0xFF;
110896893a46SBrandon Wyman     // STATUS_TEMPERATURE with fault bits on.
110996893a46SBrandon Wyman     expectations.statusTempValue = 0xFF;
1110c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1111c2906f47SBrandon Wyman     {
1112b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
11134fc191f0SBrandon Wyman         // Also get another read of READ_VIN, faulted, so not in 100-volt range
111482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
111582affd94SBrandon Wyman             .Times(1)
11164fc191f0SBrandon Wyman             .WillOnce(Return("19000"));
11170975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
11180975eaf4SMatt Spinler         {
11190975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
11200975eaf4SMatt Spinler         }
11213f1242f3SBrandon Wyman         psu.analyze();
1122c2906f47SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
1123c2906f47SBrandon Wyman     }
11243f1242f3SBrandon Wyman }
11253f1242f3SBrandon Wyman 
11263f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasInputFault)
11273f1242f3SBrandon Wyman {
11283f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1129681b2a36SB. J. Wyman 
1130681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
11313ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
11323ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1133681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1134681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
11353f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1136391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
11378da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1138b654c619SBrandon Wyman     PMBusExpectations expectations;
1139b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
114082affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
114182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
114282affd94SBrandon Wyman         .Times(1)
114382affd94SBrandon Wyman         .WillOnce(Return("201100"));
11443f1242f3SBrandon Wyman     psu.analyze();
11453f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
1146f07bc797SBrandon Wyman     // STATUS_WORD with input fault/warn on.
1147b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
1148f07bc797SBrandon Wyman     // STATUS_INPUT with an input fault bit on.
1149b654c619SBrandon Wyman     expectations.statusInputValue = 0x80;
1150c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1151c2906f47SBrandon Wyman     {
1152b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
115382affd94SBrandon Wyman         // Analyze call will also need good READ_VIN value to check.
115482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
115582affd94SBrandon Wyman             .Times(1)
115682affd94SBrandon Wyman             .WillOnce(Return("201200"));
11570975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
11580975eaf4SMatt Spinler         {
11590975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
11600975eaf4SMatt Spinler         }
11613f1242f3SBrandon Wyman         psu.analyze();
1162c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
1163c2906f47SBrandon Wyman     }
1164f07bc797SBrandon Wyman     // STATUS_WORD with no bits on.
1165b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1166b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
116782affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
116882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
116982affd94SBrandon Wyman         .Times(1)
117082affd94SBrandon Wyman         .WillOnce(Return("201300"));
11710975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
11723f1242f3SBrandon Wyman     psu.analyze();
11733f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
11743f1242f3SBrandon Wyman }
11753f1242f3SBrandon Wyman 
11763f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasMFRFault)
11773f1242f3SBrandon Wyman {
11783f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1179681b2a36SB. J. Wyman 
1180681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
11813ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
11823ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1183681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1184681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
11853f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1186391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1187f07bc797SBrandon Wyman     // First return STATUS_WORD with no bits on.
11888da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1189b654c619SBrandon Wyman     PMBusExpectations expectations;
1190b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
119182affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
119282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
119382affd94SBrandon Wyman         .Times(1)
119482affd94SBrandon Wyman         .WillOnce(Return("202100"));
11953f1242f3SBrandon Wyman     psu.analyze();
11963f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
1197f07bc797SBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
1198b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1199f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
1200b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
1201c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1202c2906f47SBrandon Wyman     {
1203b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
120482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
120582affd94SBrandon Wyman             .Times(1)
120682affd94SBrandon Wyman             .WillOnce(Return("202200"));
12073f1242f3SBrandon Wyman         psu.analyze();
1208c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1209c2906f47SBrandon Wyman     }
1210f07bc797SBrandon Wyman     // Back to no bits on in STATUS_WORD
1211b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1212b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
121382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
121482affd94SBrandon Wyman         .Times(1)
121582affd94SBrandon Wyman         .WillOnce(Return("202300"));
12163f1242f3SBrandon Wyman     psu.analyze();
12173f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
12183f1242f3SBrandon Wyman }
12193f1242f3SBrandon Wyman 
12203f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasVINUVFault)
12213f1242f3SBrandon Wyman {
12223f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1223681b2a36SB. J. Wyman 
1224681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
12253ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
12263ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1227681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1228681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
12293f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1230391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
123182affd94SBrandon Wyman 
123282affd94SBrandon Wyman     // Presence change from missing to present will trigger in1_input read in
123382affd94SBrandon Wyman     // an attempt to get CLEAR_FAULTS called. Return value ignored.
123482affd94SBrandon Wyman     // Zero to non-zero voltage, for missing/present change, triggers clear
123582affd94SBrandon Wyman     // faults call again. Return value ignored.
123682affd94SBrandon Wyman     // Fault (low voltage) to not faulted (voltage in range) triggers clear
123782affd94SBrandon Wyman     // faults call a third time.
123882affd94SBrandon Wyman 
12398da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1240b654c619SBrandon Wyman     PMBusExpectations expectations;
1241b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
124282affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
124382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
124482affd94SBrandon Wyman         .Times(1)
124582affd94SBrandon Wyman         .WillOnce(Return("201100"));
12463f1242f3SBrandon Wyman     psu.analyze();
12473f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
1248f07bc797SBrandon Wyman     // Turn fault on.
1249b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::VIN_UV_FAULT);
125085c7bf41SBrandon Wyman     // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
125185c7bf41SBrandon Wyman     // Figure 16, and assume bits on in STATUS_INPUT.
1252b654c619SBrandon Wyman     expectations.statusInputValue = 0x18;
1253c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1254c2906f47SBrandon Wyman     {
1255b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
125682affd94SBrandon Wyman         // If there is a VIN_UV fault, fake reading voltage of less than 20V
125782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
125882affd94SBrandon Wyman             .Times(1)
125982affd94SBrandon Wyman             .WillOnce(Return("19876"));
12600975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
12610975eaf4SMatt Spinler         {
12620975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
12630975eaf4SMatt Spinler         }
12643f1242f3SBrandon Wyman         psu.analyze();
1265c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1266c2906f47SBrandon Wyman     }
1267f07bc797SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1268b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1269b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
127082affd94SBrandon Wyman     // Updates now result in clearing faults if read voltage goes from below the
127182affd94SBrandon Wyman     // minimum, to within a valid range.
127282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
127382affd94SBrandon Wyman         .Times(1)
127482affd94SBrandon Wyman         .WillOnce(Return("201300"));
1275*3225a45cSBrandon Wyman     // Went from below minimum to within range, expect clearVinUVFault().
1276*3225a45cSBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
1277*3225a45cSBrandon Wyman         .Times(1)
1278*3225a45cSBrandon Wyman         .WillOnce(Return(1));
12790975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
12803f1242f3SBrandon Wyman     psu.analyze();
12813f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
12823f1242f3SBrandon Wyman }
12836710ba2cSBrandon Wyman 
12846710ba2cSBrandon Wyman TEST_F(PowerSupplyTests, HasVoutOVFault)
12856710ba2cSBrandon Wyman {
12866710ba2cSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
12876710ba2cSBrandon Wyman 
12886710ba2cSBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName};
12896710ba2cSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
12906710ba2cSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
12916710ba2cSBrandon Wyman     // Always return 1 to indicate present.
12926710ba2cSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
12936710ba2cSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1294391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
12956710ba2cSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1296b654c619SBrandon Wyman     PMBusExpectations expectations;
1297b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
129882affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
129982affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
130082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
130182affd94SBrandon Wyman         .Times(1)
130282affd94SBrandon Wyman         .WillOnce(Return("202100"));
13036710ba2cSBrandon Wyman     psu.analyze();
13046710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
13056710ba2cSBrandon Wyman     // Turn fault on.
1306b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
13076710ba2cSBrandon Wyman     // STATUS_VOUT fault bit(s)
1308b654c619SBrandon Wyman     expectations.statusVOUTValue = 0x80;
1309c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1310c2906f47SBrandon Wyman     {
1311b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
131282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
131382affd94SBrandon Wyman             .Times(1)
131482affd94SBrandon Wyman             .WillOnce(Return("202200"));
13156710ba2cSBrandon Wyman         psu.analyze();
1316c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1317c2906f47SBrandon Wyman     }
13186710ba2cSBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1319b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1320b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
132182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
132282affd94SBrandon Wyman         .Times(1)
132382affd94SBrandon Wyman         .WillOnce(Return("202300"));
13246710ba2cSBrandon Wyman     psu.analyze();
13256710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
13266710ba2cSBrandon Wyman }
132796893a46SBrandon Wyman 
1328b10b3be0SBrandon Wyman TEST_F(PowerSupplyTests, HasIoutOCFault)
1329b10b3be0SBrandon Wyman {
1330b10b3be0SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1331b10b3be0SBrandon Wyman 
1332b10b3be0SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
1333b10b3be0SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
1334b10b3be0SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1335b10b3be0SBrandon Wyman     // Always return 1 to indicate present.
1336b10b3be0SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1337b10b3be0SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1338391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1339b10b3be0SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1340b10b3be0SBrandon Wyman     PMBusExpectations expectations;
1341b10b3be0SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
134282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
134382affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
134482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
134582affd94SBrandon Wyman         .Times(1)
134682affd94SBrandon Wyman         .WillOnce(Return("203100"));
1347b10b3be0SBrandon Wyman     psu.analyze();
1348b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
1349b10b3be0SBrandon Wyman     // Turn fault on.
1350b10b3be0SBrandon Wyman     expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1351b10b3be0SBrandon Wyman     // STATUS_IOUT fault bit(s)
1352b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0x88;
1353c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1354c2906f47SBrandon Wyman     {
1355b10b3be0SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
135682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
135782affd94SBrandon Wyman             .Times(1)
135882affd94SBrandon Wyman             .WillOnce(Return("203200"));
13590975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
13600975eaf4SMatt Spinler         {
13610975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
13620975eaf4SMatt Spinler         }
1363b10b3be0SBrandon Wyman         psu.analyze();
1364c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1365c2906f47SBrandon Wyman     }
1366b10b3be0SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1367b10b3be0SBrandon Wyman     expectations.statusWordValue = 0;
1368b10b3be0SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
136982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
137082affd94SBrandon Wyman         .Times(1)
137182affd94SBrandon Wyman         .WillOnce(Return("203300"));
13720975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1373b10b3be0SBrandon Wyman     psu.analyze();
1374b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
1375b10b3be0SBrandon Wyman }
1376b10b3be0SBrandon Wyman 
13772cf46945SBrandon Wyman TEST_F(PowerSupplyTests, HasVoutUVFault)
13782cf46945SBrandon Wyman {
13792cf46945SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
13802cf46945SBrandon Wyman 
13812cf46945SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
13822cf46945SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
13832cf46945SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
13842cf46945SBrandon Wyman     // Always return 1 to indicate present.
13852cf46945SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
13862cf46945SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1387391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1388391a0690SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
13892cf46945SBrandon Wyman     PMBusExpectations expectations;
13902cf46945SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
139182affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
139282affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
139382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
139482affd94SBrandon Wyman         .Times(1)
139582affd94SBrandon Wyman         .WillOnce(Return("204100"));
13962cf46945SBrandon Wyman     psu.analyze();
13972cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
13982cf46945SBrandon Wyman     // Turn fault on.
13992cf46945SBrandon Wyman     expectations.statusWordValue = (status_word::VOUT_FAULT);
14002cf46945SBrandon Wyman     // STATUS_VOUT fault bit(s)
14012cf46945SBrandon Wyman     expectations.statusVOUTValue = 0x30;
1402c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1403c2906f47SBrandon Wyman     {
14042cf46945SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
140582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
140682affd94SBrandon Wyman             .Times(1)
140782affd94SBrandon Wyman             .WillOnce(Return("204200"));
14082cf46945SBrandon Wyman         psu.analyze();
1409c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1410c2906f47SBrandon Wyman     }
14112cf46945SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
14122cf46945SBrandon Wyman     expectations.statusWordValue = 0;
14132cf46945SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
141482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
141582affd94SBrandon Wyman         .Times(1)
141682affd94SBrandon Wyman         .WillOnce(Return("204300"));
14172cf46945SBrandon Wyman     psu.analyze();
14182cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
14192cf46945SBrandon Wyman }
14202cf46945SBrandon Wyman 
14217ee4d7e4SBrandon Wyman TEST_F(PowerSupplyTests, HasFanFault)
14227ee4d7e4SBrandon Wyman {
14237ee4d7e4SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
14247ee4d7e4SBrandon Wyman 
14250975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
14260975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
14270975eaf4SMatt Spinler 
14287ee4d7e4SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
14297ee4d7e4SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
14307ee4d7e4SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
14317ee4d7e4SBrandon Wyman     // Always return 1 to indicate present.
14327ee4d7e4SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
14337ee4d7e4SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1434391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
14357ee4d7e4SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
14367ee4d7e4SBrandon Wyman     PMBusExpectations expectations;
14377ee4d7e4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
143882affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
143982affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
144082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
144182affd94SBrandon Wyman         .Times(1)
144282affd94SBrandon Wyman         .WillOnce(Return("205100"));
14437ee4d7e4SBrandon Wyman     psu.analyze();
14447ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
14457ee4d7e4SBrandon Wyman     // Turn fault on.
14467ee4d7e4SBrandon Wyman     expectations.statusWordValue = (status_word::FAN_FAULT);
14477ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
14487ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0x80;
1449c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1450c2906f47SBrandon Wyman     {
14517ee4d7e4SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
145282affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
145382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
145482affd94SBrandon Wyman             .Times(1)
145582affd94SBrandon Wyman             .WillOnce(Return("205200"));
14567ee4d7e4SBrandon Wyman         psu.analyze();
1457c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1458c2906f47SBrandon Wyman     }
14597ee4d7e4SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
14607ee4d7e4SBrandon Wyman     expectations.statusWordValue = 0;
14617ee4d7e4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
146282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
146382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
146482affd94SBrandon Wyman         .Times(1)
146582affd94SBrandon Wyman         .WillOnce(Return("205300"));
14667ee4d7e4SBrandon Wyman     psu.analyze();
14677ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
14687ee4d7e4SBrandon Wyman }
14697ee4d7e4SBrandon Wyman 
147096893a46SBrandon Wyman TEST_F(PowerSupplyTests, HasTempFault)
147196893a46SBrandon Wyman {
147296893a46SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
147396893a46SBrandon Wyman 
14740975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
14750975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
14760975eaf4SMatt Spinler 
147796893a46SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
147896893a46SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
147996893a46SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
148096893a46SBrandon Wyman     // Always return 1 to indicate present.
148196893a46SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
148296893a46SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1483391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
148496893a46SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
148596893a46SBrandon Wyman     PMBusExpectations expectations;
148696893a46SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
148782affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
148882affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
148982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
149082affd94SBrandon Wyman         .Times(1)
149182affd94SBrandon Wyman         .WillOnce(Return("206100"));
149296893a46SBrandon Wyman     psu.analyze();
149396893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
149496893a46SBrandon Wyman     // Turn fault on.
149596893a46SBrandon Wyman     expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
149696893a46SBrandon Wyman     // STATUS_TEMPERATURE fault bit on (OT Fault)
149796893a46SBrandon Wyman     expectations.statusTempValue = 0x80;
1498c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1499c2906f47SBrandon Wyman     {
150096893a46SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
150182affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
150282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
150382affd94SBrandon Wyman             .Times(1)
150482affd94SBrandon Wyman             .WillOnce(Return("206200"));
150596893a46SBrandon Wyman         psu.analyze();
1506c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1507c2906f47SBrandon Wyman     }
150896893a46SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
150996893a46SBrandon Wyman     expectations.statusWordValue = 0;
151096893a46SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
151182affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
151282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
151382affd94SBrandon Wyman         .Times(1)
151482affd94SBrandon Wyman         .WillOnce(Return("206300"));
151596893a46SBrandon Wyman     psu.analyze();
151696893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
151796893a46SBrandon Wyman }
15182916ea52SBrandon Wyman 
15192916ea52SBrandon Wyman TEST_F(PowerSupplyTests, HasPgoodFault)
15202916ea52SBrandon Wyman {
15212916ea52SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
15222916ea52SBrandon Wyman 
15232916ea52SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, PSUGPIOLineName};
15242916ea52SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
15252916ea52SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
15262916ea52SBrandon Wyman     // Always return 1 to indicate present.
15272916ea52SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
15282916ea52SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1529391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
15302916ea52SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
15312916ea52SBrandon Wyman     PMBusExpectations expectations;
15322916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
153382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
153482affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
153582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
153682affd94SBrandon Wyman         .Times(1)
153782affd94SBrandon Wyman         .WillOnce(Return("207100"));
15382916ea52SBrandon Wyman     psu.analyze();
15392916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
1540391a0690SBrandon Wyman     // Setup another expectation of no faults.
1541391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
154282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
154382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
154482affd94SBrandon Wyman         .Times(1)
154582affd94SBrandon Wyman         .WillOnce(Return("207200"));
154682affd94SBrandon Wyman     psu.analyze();
154782affd94SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
154882affd94SBrandon Wyman     // Setup another expectation of no faults.
154982affd94SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
155082affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
155182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
155282affd94SBrandon Wyman         .Times(1)
155382affd94SBrandon Wyman         .WillOnce(Return("207300"));
1554391a0690SBrandon Wyman     psu.analyze();
1555391a0690SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
15562916ea52SBrandon Wyman     // Turn PGOOD# off (fault on).
15572916ea52SBrandon Wyman     expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
15582916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
155982affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
156082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
156182affd94SBrandon Wyman         .Times(1)
156282affd94SBrandon Wyman         .WillOnce(Return("207400"));
15632916ea52SBrandon Wyman     psu.analyze();
156406ca4590SBrandon Wyman     // Expect false until reaches DEGLITCH_LIMIT
156506ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
156606ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
156782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
156882affd94SBrandon Wyman         .Times(1)
156982affd94SBrandon Wyman         .WillOnce(Return("207500"));
157006ca4590SBrandon Wyman     psu.analyze();
157106ca4590SBrandon Wyman     // Expect false until reaches DEGLITCH_LIMIT
157206ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
157306ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
157482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
157582affd94SBrandon Wyman         .Times(1)
157682affd94SBrandon Wyman         .WillOnce(Return("207600"));
157706ca4590SBrandon Wyman     psu.analyze();
157806ca4590SBrandon Wyman     // DEGLITCH_LIMIT reached, expect true.
15792916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
15802916ea52SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
15812916ea52SBrandon Wyman     expectations.statusWordValue = 0;
15822916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
158382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
158482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
158582affd94SBrandon Wyman         .Times(1)
158682affd94SBrandon Wyman         .WillOnce(Return("207700"));
15872916ea52SBrandon Wyman     psu.analyze();
15882916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
158982affd94SBrandon Wyman 
15902916ea52SBrandon Wyman     // Turn OFF bit on
15912916ea52SBrandon Wyman     expectations.statusWordValue = (status_word::UNIT_IS_OFF);
15922916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
159382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
159482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
159582affd94SBrandon Wyman         .Times(1)
159682affd94SBrandon Wyman         .WillOnce(Return("208100"));
15972916ea52SBrandon Wyman     psu.analyze();
159806ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
159906ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
160082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
160182affd94SBrandon Wyman         .Times(1)
160282affd94SBrandon Wyman         .WillOnce(Return("208200"));
160306ca4590SBrandon Wyman     psu.analyze();
160406ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
160506ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
160682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
160782affd94SBrandon Wyman         .Times(1)
160882affd94SBrandon Wyman         .WillOnce(Return("208300"));
160906ca4590SBrandon Wyman     psu.analyze();
16102916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
16112916ea52SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
16122916ea52SBrandon Wyman     expectations.statusWordValue = 0;
16132916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
161482affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
161582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
161682affd94SBrandon Wyman         .Times(1)
161782affd94SBrandon Wyman         .WillOnce(Return("208400"));
16182916ea52SBrandon Wyman     psu.analyze();
16192916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
16202916ea52SBrandon Wyman }
162139ea02bcSBrandon Wyman 
162239ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPSKillFault)
162339ea02bcSBrandon Wyman {
162439ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
162539ea02bcSBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 4, 0x6d, PSUGPIOLineName};
162639ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
162739ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
162839ea02bcSBrandon Wyman     // Always return 1 to indicate present.
162939ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
163039ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
163182affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
163239ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
163339ea02bcSBrandon Wyman     PMBusExpectations expectations;
163439ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
163582affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
163682affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
163782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
163882affd94SBrandon Wyman         .Times(1)
163982affd94SBrandon Wyman         .WillOnce(Return("208100"));
164039ea02bcSBrandon Wyman     psu.analyze();
164139ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
164239ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
164339ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
164439ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
164539ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1646c2906f47SBrandon Wyman 
1647c2906f47SBrandon Wyman     // Deglitching faults, false until read the fault bits on up to the limit.
1648c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1649c2906f47SBrandon Wyman     {
165039ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
165182affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
165282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
165382affd94SBrandon Wyman             .Times(1)
165482affd94SBrandon Wyman             .WillOnce(Return("208200"));
16550975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
16560975eaf4SMatt Spinler         {
16570975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
16580975eaf4SMatt Spinler         }
165939ea02bcSBrandon Wyman         psu.analyze();
1660c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1661c2906f47SBrandon Wyman     }
1662c2906f47SBrandon Wyman 
166339ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
166439ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
166539ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
166682affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
166782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
166882affd94SBrandon Wyman         .Times(1)
166982affd94SBrandon Wyman         .WillOnce(Return("208300"));
16700975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
167139ea02bcSBrandon Wyman     psu.analyze();
167239ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
167339ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
167439ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
167539ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 4 on.
167639ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x10;
1677c2906f47SBrandon Wyman 
1678c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1679c2906f47SBrandon Wyman     {
168039ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
168182affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
168282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
168382affd94SBrandon Wyman             .Times(1)
168482affd94SBrandon Wyman             .WillOnce(Return("208400"));
16850975eaf4SMatt Spinler         if (x == DEGLITCH_LIMIT)
16860975eaf4SMatt Spinler         {
16870975eaf4SMatt Spinler             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
16880975eaf4SMatt Spinler         }
168939ea02bcSBrandon Wyman         psu.analyze();
1690c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1691c2906f47SBrandon Wyman     }
1692c2906f47SBrandon Wyman 
169339ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
169439ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
169539ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
169682affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
169782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
169882affd94SBrandon Wyman         .Times(1)
169982affd94SBrandon Wyman         .WillOnce(Return("208500"));
17000975eaf4SMatt Spinler     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
170139ea02bcSBrandon Wyman     psu.analyze();
170239ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
170339ea02bcSBrandon Wyman }
170439ea02bcSBrandon Wyman 
170539ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPS12VcsFault)
170639ea02bcSBrandon Wyman {
170739ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
170839ea02bcSBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 5, 0x6e, PSUGPIOLineName};
170939ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
171039ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
171139ea02bcSBrandon Wyman     // Always return 1 to indicate present.
171239ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
171339ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
171482affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
171539ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
171639ea02bcSBrandon Wyman     PMBusExpectations expectations;
171739ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
171882affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
171982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
172082affd94SBrandon Wyman         .Times(1)
172182affd94SBrandon Wyman         .WillOnce(Return("209100"));
172239ea02bcSBrandon Wyman     psu.analyze();
172339ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
172439ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
172539ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
172639ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
172739ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1728c2906f47SBrandon Wyman 
1729c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1730c2906f47SBrandon Wyman     {
173139ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
173282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
173382affd94SBrandon Wyman             .Times(1)
173482affd94SBrandon Wyman             .WillOnce(Return("209200"));
173539ea02bcSBrandon Wyman         psu.analyze();
1736c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1737c2906f47SBrandon Wyman     }
1738c2906f47SBrandon Wyman 
173939ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
174039ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
174139ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
174282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
174382affd94SBrandon Wyman         .Times(1)
174482affd94SBrandon Wyman         .WillOnce(Return("209300"));
174539ea02bcSBrandon Wyman     psu.analyze();
174639ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
174739ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
174839ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
174939ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 6 on.
175039ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x40;
1751c2906f47SBrandon Wyman 
1752c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1753c2906f47SBrandon Wyman     {
175439ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
175582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
175682affd94SBrandon Wyman             .Times(1)
175782affd94SBrandon Wyman             .WillOnce(Return("209400"));
175839ea02bcSBrandon Wyman         psu.analyze();
1759c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1760c2906f47SBrandon Wyman     }
1761c2906f47SBrandon Wyman 
176239ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
176339ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
176439ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
176582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
176682affd94SBrandon Wyman         .Times(1)
176782affd94SBrandon Wyman         .WillOnce(Return("209500"));
176839ea02bcSBrandon Wyman     psu.analyze();
176939ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
177039ea02bcSBrandon Wyman }
177139ea02bcSBrandon Wyman 
177239ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPSCS12VFault)
177339ea02bcSBrandon Wyman {
177439ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
177539ea02bcSBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f, PSUGPIOLineName};
177639ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
177739ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
177839ea02bcSBrandon Wyman     // Always return 1 to indicate present.
177939ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
178039ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
178182affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
178239ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
178339ea02bcSBrandon Wyman     PMBusExpectations expectations;
178439ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
178582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
178682affd94SBrandon Wyman         .Times(1)
178782affd94SBrandon Wyman         .WillOnce(Return("209100"));
178839ea02bcSBrandon Wyman     psu.analyze();
178939ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
179039ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
179139ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
179239ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
179339ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1794c2906f47SBrandon Wyman 
1795c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1796c2906f47SBrandon Wyman     {
179739ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
179882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
179982affd94SBrandon Wyman             .Times(1)
180082affd94SBrandon Wyman             .WillOnce(Return("209200"));
180139ea02bcSBrandon Wyman         psu.analyze();
1802c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1803c2906f47SBrandon Wyman     }
1804c2906f47SBrandon Wyman 
180539ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
180639ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
180739ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
180882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
180982affd94SBrandon Wyman         .Times(1)
181082affd94SBrandon Wyman         .WillOnce(Return("209300"));
181139ea02bcSBrandon Wyman     psu.analyze();
181239ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
181339ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
181439ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
181539ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 7 on.
181639ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x80;
1817c2906f47SBrandon Wyman 
1818c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1819c2906f47SBrandon Wyman     {
182039ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
182182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
182282affd94SBrandon Wyman             .Times(1)
182382affd94SBrandon Wyman             .WillOnce(Return("209400"));
182439ea02bcSBrandon Wyman         psu.analyze();
1825c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1826c2906f47SBrandon Wyman     }
1827c2906f47SBrandon Wyman 
182839ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
182939ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
183039ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
183182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
183282affd94SBrandon Wyman         .Times(1)
183382affd94SBrandon Wyman         .WillOnce(Return("209500"));
183439ea02bcSBrandon Wyman     psu.analyze();
183539ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
183639ea02bcSBrandon Wyman }
1837