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 {
418da35c51SBrandon 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.
508da35c51SBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
518da35c51SBrandon Wyman             .Times(1)
52b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusInputValue));
538da35c51SBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_MFR, _))
548da35c51SBrandon Wyman             .Times(1)
55b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusMFRValue));
568da35c51SBrandon 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"));
636710ba2cSBrandon Wyman         EXPECT_CALL(mockPMBus, read("status0_vout", _))
646710ba2cSBrandon Wyman             .Times(1)
65b654c619SBrandon Wyman             .WillOnce(Return(expectations.statusVOUTValue));
66b10b3be0SBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _))
67b10b3be0SBrandon Wyman             .Times(1)
68b10b3be0SBrandon Wyman             .WillOnce(Return(expectations.statusIOUTValue));
697ee4d7e4SBrandon Wyman         EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _))
707ee4d7e4SBrandon Wyman             .Times(1)
717ee4d7e4SBrandon Wyman             .WillOnce(Return(expectations.statusFans12Value));
7296893a46SBrandon 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     // The voltage defaults to 0, the first call to analyze should update the
10782affd94SBrandon Wyman     // voltage to the current reading, triggering another clearing of faults
10882affd94SBrandon Wyman     // due to below minimum to within range voltage.
10982affd94SBrandon Wyman     // This READ_VIN for CLEAR_FAULTS does not check the returned value.
11082affd94SBrandon Wyman     EXPECT_CALL(pmbus, read(READ_VIN, _))
11182affd94SBrandon Wyman         .Times(2)
11282affd94SBrandon Wyman         .WillOnce(Return(1))
11382affd94SBrandon Wyman         .WillOnce(Return(2));
114391a0690SBrandon Wyman     // Missing/present call will update Presence in inventory.
115391a0690SBrandon Wyman     EXPECT_CALL(util, setPresence(_, _, true, _));
116391a0690SBrandon Wyman }
117391a0690SBrandon Wyman 
1183f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Constructor)
1193f1242f3SBrandon Wyman {
1203f1242f3SBrandon Wyman     /**
1213f1242f3SBrandon Wyman      * @param[in] invpath - String for inventory path to use
1223f1242f3SBrandon Wyman      * @param[in] i2cbus - The bus number this power supply is on
1233f1242f3SBrandon Wyman      * @param[in] i2caddr - The 16-bit I2C address of the power supply
124681b2a36SB. J. Wyman      * @param[in] gpioLineName - The string for the gpio-line-name to read for
125681b2a36SB. J. Wyman      * presence.
126681b2a36SB. J. Wyman      * @param[in] bindDelay - Time in milliseconds to delay binding the device
127681b2a36SB. J. Wyman      * driver after seeing the presence line go active.
1283f1242f3SBrandon Wyman      */
1293f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1301d7a7df8SBrandon Wyman 
1311d7a7df8SBrandon Wyman     // Try where inventory path is empty, constructor should fail.
1321d7a7df8SBrandon Wyman     try
1331d7a7df8SBrandon Wyman     {
134681b2a36SB. J. Wyman         auto psu =
135681b2a36SB. J. Wyman             std::make_unique<PowerSupply>(bus, "", 3, 0x68, PSUGPIOLineName);
1361d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have reached this line.";
1371d7a7df8SBrandon Wyman     }
1381d7a7df8SBrandon Wyman     catch (const std::invalid_argument& e)
1391d7a7df8SBrandon Wyman     {
1401d7a7df8SBrandon Wyman         EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
1411d7a7df8SBrandon Wyman     }
1421d7a7df8SBrandon Wyman     catch (...)
1431d7a7df8SBrandon Wyman     {
1441d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
1451d7a7df8SBrandon Wyman     }
1461d7a7df8SBrandon Wyman 
147681b2a36SB. J. Wyman     // TODO: Try invalid i2c address?
148681b2a36SB. J. Wyman 
149681b2a36SB. J. Wyman     // Try where gpioLineName is empty.
1501d7a7df8SBrandon Wyman     try
1511d7a7df8SBrandon Wyman     {
1521d7a7df8SBrandon Wyman         auto psu =
153681b2a36SB. J. Wyman             std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, "");
154681b2a36SB. J. Wyman         ADD_FAILURE()
155681b2a36SB. J. Wyman             << "Should not have reached this line. Invalid gpioLineName.";
156681b2a36SB. J. Wyman     }
157681b2a36SB. J. Wyman     catch (const std::invalid_argument& e)
158681b2a36SB. J. Wyman     {
159681b2a36SB. J. Wyman         EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
160681b2a36SB. J. Wyman     }
161681b2a36SB. J. Wyman     catch (...)
162681b2a36SB. J. Wyman     {
163681b2a36SB. J. Wyman         ADD_FAILURE() << "Should not have caught exception.";
164681b2a36SB. J. Wyman     }
165681b2a36SB. J. Wyman 
166681b2a36SB. J. Wyman     // Test with valid arguments
167681b2a36SB. J. Wyman     // NOT using D-Bus inventory path for presence.
168681b2a36SB. J. Wyman     try
169681b2a36SB. J. Wyman     {
170681b2a36SB. J. Wyman         auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
171681b2a36SB. J. Wyman                                                  PSUGPIOLineName);
1723f1242f3SBrandon Wyman 
1733f1242f3SBrandon Wyman         EXPECT_EQ(psu->isPresent(), false);
1743f1242f3SBrandon Wyman         EXPECT_EQ(psu->isFaulted(), false);
1758da35c51SBrandon Wyman         EXPECT_EQ(psu->hasCommFault(), false);
1763f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasInputFault(), false);
1773f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasMFRFault(), false);
1783f1242f3SBrandon Wyman         EXPECT_EQ(psu->hasVINUVFault(), false);
1796710ba2cSBrandon Wyman         EXPECT_EQ(psu->hasVoutOVFault(), false);
180b10b3be0SBrandon Wyman         EXPECT_EQ(psu->hasIoutOCFault(), false);
1812cf46945SBrandon Wyman         EXPECT_EQ(psu->hasVoutUVFault(), false);
1827ee4d7e4SBrandon Wyman         EXPECT_EQ(psu->hasFanFault(), false);
18396893a46SBrandon Wyman         EXPECT_EQ(psu->hasTempFault(), false);
1842916ea52SBrandon Wyman         EXPECT_EQ(psu->hasPgoodFault(), false);
18539ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPSKillFault(), false);
18639ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPS12VcsFault(), false);
18739ea02bcSBrandon Wyman         EXPECT_EQ(psu->hasPSCS12VFault(), false);
1883f1242f3SBrandon Wyman     }
1891d7a7df8SBrandon Wyman     catch (...)
1901d7a7df8SBrandon Wyman     {
1911d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
1921d7a7df8SBrandon Wyman     }
193681b2a36SB. J. Wyman 
194681b2a36SB. J. Wyman     // Test with valid arguments
195681b2a36SB. J. Wyman     // TODO: Using D-Bus inventory path for presence.
196681b2a36SB. J. Wyman     try
197681b2a36SB. J. Wyman     {
198681b2a36SB. J. Wyman         // FIXME: How do I get that presenceGPIO.read() in the startup to throw
199681b2a36SB. J. Wyman         // an exception?
200681b2a36SB. J. Wyman 
201681b2a36SB. J. Wyman         // EXPECT_CALL(mockedUtil, getPresence(_,
202681b2a36SB. J. Wyman         // StrEq(PSUInventoryPath)))
203681b2a36SB. J. Wyman         //    .Times(1);
204681b2a36SB. J. Wyman     }
205681b2a36SB. J. Wyman     catch (...)
206681b2a36SB. J. Wyman     {
207681b2a36SB. J. Wyman         ADD_FAILURE() << "Should not have caught exception.";
208681b2a36SB. J. Wyman     }
2091d7a7df8SBrandon Wyman }
2103f1242f3SBrandon Wyman 
2113f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Analyze)
2123f1242f3SBrandon Wyman {
2133f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
2143f1242f3SBrandon Wyman 
215b654c619SBrandon Wyman     {
216681b2a36SB. J. Wyman         // If I default to reading the GPIO, I will NOT expect a call to
217681b2a36SB. J. Wyman         // getPresence().
218681b2a36SB. J. Wyman 
219681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
2203ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
2213ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
222681b2a36SB. J. Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
223681b2a36SB. J. Wyman 
2243f1242f3SBrandon Wyman         psu.analyze();
2253f1242f3SBrandon Wyman         // By default, nothing should change.
2263f1242f3SBrandon Wyman         EXPECT_EQ(psu.isPresent(), false);
2273f1242f3SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), false);
2283f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), false);
2293f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), false);
2303f1242f3SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), false);
23185c7bf41SBrandon Wyman         EXPECT_EQ(psu.hasCommFault(), false);
2326710ba2cSBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), false);
233b10b3be0SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), false);
2342cf46945SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), false);
2357ee4d7e4SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), false);
23696893a46SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), false);
2372916ea52SBrandon Wyman         EXPECT_EQ(psu.hasPgoodFault(), false);
23839ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), false);
23939ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), false);
24039ea02bcSBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), false);
241b654c619SBrandon Wyman     }
2423f1242f3SBrandon Wyman 
243681b2a36SB. J. Wyman     PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
244681b2a36SB. J. Wyman     // In order to get the various faults tested, the power supply needs to
245681b2a36SB. J. Wyman     // be present in order to read from the PMBus device(s).
2463ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO2 =
2473ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
24806ca4590SBrandon Wyman     // Always return 1 to indicate present.
24906ca4590SBrandon Wyman     // Each analyze() call will trigger a read of the presence GPIO.
25006ca4590SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1));
251681b2a36SB. J. Wyman     EXPECT_EQ(psu2.isPresent(), false);
2523f1242f3SBrandon Wyman 
2533f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
254391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
255b654c619SBrandon Wyman 
256b654c619SBrandon Wyman     // STATUS_WORD INPUT fault.
257b654c619SBrandon Wyman     {
258b654c619SBrandon Wyman         // Start with STATUS_WORD 0x0000. Powered on, no faults.
259b654c619SBrandon Wyman         // Set expectations for a no fault
260b654c619SBrandon Wyman         PMBusExpectations expectations;
261b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
26282affd94SBrandon Wyman         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
26382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
26482affd94SBrandon Wyman             .Times(1)
26582affd94SBrandon Wyman             .WillOnce(Return("206000"));
2663f1242f3SBrandon Wyman         psu2.analyze();
2673f1242f3SBrandon Wyman         EXPECT_EQ(psu2.isPresent(), true);
2683f1242f3SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
2693f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
2703f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasMFRFault(), false);
2713f1242f3SBrandon Wyman         EXPECT_EQ(psu2.hasVINUVFault(), false);
27285c7bf41SBrandon Wyman         EXPECT_EQ(psu2.hasCommFault(), false);
2736710ba2cSBrandon Wyman         EXPECT_EQ(psu2.hasVoutOVFault(), false);
274b10b3be0SBrandon Wyman         EXPECT_EQ(psu2.hasIoutOCFault(), false);
2752cf46945SBrandon Wyman         EXPECT_EQ(psu2.hasVoutUVFault(), false);
2767ee4d7e4SBrandon Wyman         EXPECT_EQ(psu2.hasFanFault(), false);
27796893a46SBrandon Wyman         EXPECT_EQ(psu2.hasTempFault(), false);
2782916ea52SBrandon Wyman         EXPECT_EQ(psu2.hasPgoodFault(), false);
27939ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPSKillFault(), false);
28039ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPS12VcsFault(), false);
28139ea02bcSBrandon Wyman         EXPECT_EQ(psu2.hasPSCS12VFault(), false);
2823f1242f3SBrandon Wyman 
283b654c619SBrandon Wyman         // Update expectations for STATUS_WORD input fault/warn
28496893a46SBrandon Wyman         // STATUS_INPUT fault bits ... on.
285b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
286b654c619SBrandon Wyman         expectations.statusInputValue = 0x38;
287*c2906f47SBrandon Wyman 
288*c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
289*c2906f47SBrandon Wyman         {
290b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
29182affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
29282affd94SBrandon Wyman                 .Times(1)
29382affd94SBrandon Wyman                 .WillOnce(Return("207000"));
2943f1242f3SBrandon Wyman             psu2.analyze();
2953f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
296*c2906f47SBrandon Wyman             // Should not be faulted until it reaches the deglitch limit.
297*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
298*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
2993f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
3003f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
30185c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
3026710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
303b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
3042cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
3057ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
30696893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
3072916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
30839ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
30939ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
31039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
311b654c619SBrandon Wyman         }
312*c2906f47SBrandon Wyman     }
313*c2906f47SBrandon Wyman 
314*c2906f47SBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(1));
315*c2906f47SBrandon Wyman     psu2.clearFaults();
3163f1242f3SBrandon Wyman 
3173f1242f3SBrandon Wyman     // STATUS_WORD INPUT/UV fault.
318b654c619SBrandon Wyman     {
3193f1242f3SBrandon Wyman         // First need it to return good status, then the fault
320b654c619SBrandon Wyman         PMBusExpectations expectations;
321b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
32282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
32382affd94SBrandon Wyman             .Times(1)
32482affd94SBrandon Wyman             .WillOnce(Return("208000"));
3253f1242f3SBrandon Wyman         psu2.analyze();
326*c2906f47SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
327*c2906f47SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
3288da35c51SBrandon Wyman         // Now set fault bits in STATUS_WORD
329b654c619SBrandon Wyman         expectations.statusWordValue =
3308da35c51SBrandon Wyman             (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
3318da35c51SBrandon Wyman         // STATUS_INPUT fault bits ... on.
332b654c619SBrandon Wyman         expectations.statusInputValue = 0x38;
333*c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
334*c2906f47SBrandon Wyman         {
335b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
33682affd94SBrandon Wyman             // Input/UV fault, so voltage should read back low.
33782affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
33882affd94SBrandon Wyman                 .Times(1)
33982affd94SBrandon Wyman                 .WillOnce(Return("19123"));
3403f1242f3SBrandon Wyman             psu2.analyze();
3413f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
342*c2906f47SBrandon Wyman             // Only faulted if hit deglitch limit
343*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
344*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
345*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), x >= DEGLITCH_LIMIT);
3463f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
34785c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
3486710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
349b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
3502cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
3517ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
35296893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
3532916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
35439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
35539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
35639ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
357*c2906f47SBrandon Wyman         }
35882affd94SBrandon Wyman         // Turning VIN_UV fault off causes clearing of faults, causing read of
35982affd94SBrandon Wyman         // in1_input as an attempt to get CLEAR_FAULTS called.
36082affd94SBrandon Wyman         expectations.statusWordValue = 0;
36182affd94SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
36282affd94SBrandon Wyman         // The call to read the voltage
36382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
36482affd94SBrandon Wyman             .Times(1)
36582affd94SBrandon Wyman             .WillOnce(Return("209000"));
36682affd94SBrandon Wyman         // The call for CLEAR_FAULTS command
36782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(3));
36882affd94SBrandon Wyman         psu2.analyze();
36982affd94SBrandon Wyman         // Should remain present, no longer be faulted, no input fault, no
37082affd94SBrandon Wyman         // VIN_UV fault. Nothing else should change.
37182affd94SBrandon Wyman         EXPECT_EQ(psu2.isPresent(), true);
37282affd94SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
37382affd94SBrandon Wyman         EXPECT_EQ(psu2.hasInputFault(), false);
37482affd94SBrandon Wyman         EXPECT_EQ(psu2.hasVINUVFault(), false);
375b654c619SBrandon Wyman     }
3763f1242f3SBrandon Wyman 
377*c2906f47SBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(1));
378*c2906f47SBrandon Wyman     psu2.clearFaults();
379*c2906f47SBrandon Wyman 
3803f1242f3SBrandon Wyman     // STATUS_WORD MFR fault.
381b654c619SBrandon Wyman     {
382f07bc797SBrandon Wyman         // First need it to return good status, then the fault
383b654c619SBrandon Wyman         PMBusExpectations expectations;
384b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
38582affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
38682affd94SBrandon Wyman             .Times(1)
38782affd94SBrandon Wyman             .WillOnce(Return("210000"));
3883f1242f3SBrandon Wyman         psu2.analyze();
3898da35c51SBrandon Wyman         // Now STATUS_WORD with MFR fault bit on.
390b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
3918da35c51SBrandon Wyman         // STATUS_MFR bits on.
392b654c619SBrandon Wyman         expectations.statusMFRValue = 0xFF;
393*c2906f47SBrandon Wyman 
394*c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
395*c2906f47SBrandon Wyman         {
396b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
39782affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
39882affd94SBrandon Wyman                 .Times(1)
39982affd94SBrandon Wyman                 .WillOnce(Return("211000"));
4003f1242f3SBrandon Wyman             psu2.analyze();
4013f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
402*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
4033f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
404*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT);
405*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT);
406*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
407*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
4083f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
40985c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
4106710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
411b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
4122cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
4137ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
41496893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
4152916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
416*c2906f47SBrandon Wyman         }
417b654c619SBrandon Wyman     }
4183f1242f3SBrandon Wyman 
419*c2906f47SBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(1));
420*c2906f47SBrandon Wyman     psu2.clearFaults();
42196893a46SBrandon Wyman     // Temperature fault.
422b654c619SBrandon Wyman     {
423f07bc797SBrandon Wyman         // First STATUS_WORD with no bits set, then with temperature fault.
424b654c619SBrandon Wyman         PMBusExpectations expectations;
425b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
42682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
42782affd94SBrandon Wyman             .Times(1)
42882affd94SBrandon Wyman             .WillOnce(Return("212000"));
4293f1242f3SBrandon Wyman         psu2.analyze();
4308da35c51SBrandon Wyman         // STATUS_WORD with temperature fault bit on.
431b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
43296893a46SBrandon Wyman         // STATUS_TEMPERATURE with fault bit(s) on.
43396893a46SBrandon Wyman         expectations.statusTempValue = 0x10;
434*c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
435*c2906f47SBrandon Wyman         {
436b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
43782affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
43882affd94SBrandon Wyman                 .Times(1)
43982affd94SBrandon Wyman                 .WillOnce(Return("213000"));
4403f1242f3SBrandon Wyman             psu2.analyze();
4413f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
442*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
4433f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
4443f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
4453f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
44685c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
4476710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
448b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
4492cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
4507ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
451*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT);
4522916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
45339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
45439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
45539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
456b654c619SBrandon Wyman         }
457*c2906f47SBrandon Wyman     }
45885c7bf41SBrandon Wyman 
459*c2906f47SBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(1));
460*c2906f47SBrandon Wyman     psu2.clearFaults();
46185c7bf41SBrandon Wyman     // CML fault
462b654c619SBrandon Wyman     {
46385c7bf41SBrandon Wyman         // First STATUS_WORD wit no bits set, then with CML fault.
464b654c619SBrandon Wyman         PMBusExpectations expectations;
465b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
46682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
46782affd94SBrandon Wyman             .Times(1)
46882affd94SBrandon Wyman             .WillOnce(Return("214000"));
46985c7bf41SBrandon Wyman         psu2.analyze();
4708da35c51SBrandon Wyman         // STATUS_WORD with CML fault bit on.
471b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::CML_FAULT);
47285c7bf41SBrandon Wyman         // Turn on STATUS_CML fault bit(s)
473b654c619SBrandon Wyman         expectations.statusCMLValue = 0xFF;
474*c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
475*c2906f47SBrandon Wyman         {
476b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
47782affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
47882affd94SBrandon Wyman                 .Times(1)
47982affd94SBrandon Wyman                 .WillOnce(Return("215000"));
48085c7bf41SBrandon Wyman             psu2.analyze();
48185c7bf41SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
482*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
483*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), x >= DEGLITCH_LIMIT);
48485c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
48585c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
48685c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
4876710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
488b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
4892cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
4907ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
49196893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
4922916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
49339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
49439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
49539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
496b654c619SBrandon Wyman         }
497*c2906f47SBrandon Wyman     }
4986710ba2cSBrandon Wyman 
499*c2906f47SBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(1));
500*c2906f47SBrandon Wyman     psu2.clearFaults();
5016710ba2cSBrandon Wyman     // VOUT_OV_FAULT fault
502b654c619SBrandon Wyman     {
5036710ba2cSBrandon Wyman         // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
504b654c619SBrandon Wyman         PMBusExpectations expectations;
505b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
50682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
50782affd94SBrandon Wyman             .Times(1)
50882affd94SBrandon Wyman             .WillOnce(Return("216000"));
5096710ba2cSBrandon Wyman         psu2.analyze();
5106710ba2cSBrandon Wyman         // STATUS_WORD with VOUT/VOUT_OV fault.
511b654c619SBrandon Wyman         expectations.statusWordValue =
5126710ba2cSBrandon Wyman             ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
5136710ba2cSBrandon Wyman         // Turn on STATUS_VOUT fault bit(s)
514b654c619SBrandon Wyman         expectations.statusVOUTValue = 0xA0;
515*c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
516*c2906f47SBrandon Wyman         {
51796893a46SBrandon Wyman             // STATUS_TEMPERATURE don't care (default)
518b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
51982affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
52082affd94SBrandon Wyman                 .Times(1)
52182affd94SBrandon Wyman                 .WillOnce(Return("217000"));
5226710ba2cSBrandon Wyman             psu2.analyze();
5236710ba2cSBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
524*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
5256710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
5266710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
5276710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
5286710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
529*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
5302cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
531b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
5327ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
533b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
534b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
53539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
53639ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
53739ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
538b10b3be0SBrandon Wyman         }
539*c2906f47SBrandon Wyman     }
540b10b3be0SBrandon Wyman 
541b10b3be0SBrandon Wyman     // IOUT_OC_FAULT fault
542b10b3be0SBrandon Wyman     {
543b10b3be0SBrandon Wyman         // First STATUS_WORD with no bits set, then with IOUT_OC fault.
544b10b3be0SBrandon Wyman         PMBusExpectations expectations;
545b10b3be0SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
54682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
54782affd94SBrandon Wyman             .Times(1)
54882affd94SBrandon Wyman             .WillOnce(Return("218000"));
549b10b3be0SBrandon Wyman         psu2.analyze();
550b10b3be0SBrandon Wyman         // STATUS_WORD with IOUT_OC fault.
551b10b3be0SBrandon Wyman         expectations.statusWordValue = status_word::IOUT_OC_FAULT;
552b10b3be0SBrandon Wyman         // Turn on STATUS_IOUT fault bit(s)
553b10b3be0SBrandon Wyman         expectations.statusIOUTValue = 0x88;
554*c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
555*c2906f47SBrandon Wyman         {
556b10b3be0SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
55782affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
55882affd94SBrandon Wyman                 .Times(1)
55982affd94SBrandon Wyman                 .WillOnce(Return("219000"));
560b10b3be0SBrandon Wyman             psu2.analyze();
561b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
562*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
563b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
564b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
565b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
566b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
567b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
568*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
5692cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
5707ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
5712cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
5722cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
57339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
57439ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
57539ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
5762cf46945SBrandon Wyman         }
577*c2906f47SBrandon Wyman     }
5782cf46945SBrandon Wyman 
5792cf46945SBrandon Wyman     // VOUT_UV_FAULT
5802cf46945SBrandon Wyman     {
5812cf46945SBrandon Wyman         // First STATUS_WORD with no bits set, then with VOUT fault.
5822cf46945SBrandon Wyman         PMBusExpectations expectations;
5832cf46945SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
58482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
58582affd94SBrandon Wyman             .Times(1)
58682affd94SBrandon Wyman             .WillOnce(Return("220000"));
5872cf46945SBrandon Wyman         psu2.analyze();
5882cf46945SBrandon Wyman         // Change STATUS_WORD to indicate VOUT fault.
5892cf46945SBrandon Wyman         expectations.statusWordValue = (status_word::VOUT_FAULT);
5902cf46945SBrandon Wyman         // Turn on STATUS_VOUT fault bit(s)
5912cf46945SBrandon Wyman         expectations.statusVOUTValue = 0x30;
592*c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
593*c2906f47SBrandon Wyman         {
5942cf46945SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
59582affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
59682affd94SBrandon Wyman                 .Times(1)
59782affd94SBrandon Wyman                 .WillOnce(Return("221000"));
5982cf46945SBrandon Wyman             psu2.analyze();
5992cf46945SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
600*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
6012cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
6022cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
6032cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
6042cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
6052cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
6062cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
607*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
6087ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
60996893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6102916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
61139ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
61239ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
61339ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
614b654c619SBrandon Wyman         }
615*c2906f47SBrandon Wyman     }
6163f1242f3SBrandon Wyman 
6177ee4d7e4SBrandon Wyman     // Fan fault
618b654c619SBrandon Wyman     {
619b654c619SBrandon Wyman         // First STATUS_WORD with no bits set, then with fan fault.
620b654c619SBrandon Wyman         PMBusExpectations expectations;
621b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
62282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
62382affd94SBrandon Wyman             .Times(1)
62482affd94SBrandon Wyman             .WillOnce(Return("222000"));
6253f1242f3SBrandon Wyman         psu2.analyze();
626b654c619SBrandon Wyman         expectations.statusWordValue = (status_word::FAN_FAULT);
6277ee4d7e4SBrandon Wyman         // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
6287ee4d7e4SBrandon Wyman         expectations.statusFans12Value = 0xA0;
629*c2906f47SBrandon Wyman 
630*c2906f47SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
631*c2906f47SBrandon Wyman         {
632b654c619SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
63382affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
63482affd94SBrandon Wyman                 .Times(1)
63582affd94SBrandon Wyman                 .WillOnce(Return("223000"));
6363f1242f3SBrandon Wyman             psu2.analyze();
6373f1242f3SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
638*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
639*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT);
6403f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
6413f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
6423f1242f3SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
64385c7bf41SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
6446710ba2cSBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
645b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
6462cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
64796893a46SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
6482916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasPgoodFault(), false);
64939ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSKillFault(), false);
65039ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
65139ea02bcSBrandon Wyman             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
652b654c619SBrandon Wyman         }
653*c2906f47SBrandon Wyman     }
6542916ea52SBrandon Wyman 
65506ca4590SBrandon Wyman     // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
6562cf46945SBrandon Wyman     {
6572916ea52SBrandon Wyman         // First STATUS_WORD with no bits set.
6582916ea52SBrandon Wyman         PMBusExpectations expectations;
6592916ea52SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
66082affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
66182affd94SBrandon Wyman             .Times(1)
66282affd94SBrandon Wyman             .WillOnce(Return("123000"));
6632916ea52SBrandon Wyman         psu2.analyze();
6642916ea52SBrandon Wyman         EXPECT_EQ(psu2.isFaulted(), false);
6652916ea52SBrandon Wyman         // POWER_GOOD# inactive, and OFF bit on.
6662916ea52SBrandon Wyman         expectations.statusWordValue =
6672916ea52SBrandon Wyman             ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
66806ca4590SBrandon Wyman         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
66906ca4590SBrandon Wyman         {
6702916ea52SBrandon Wyman             // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
6712916ea52SBrandon Wyman             // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
6722916ea52SBrandon Wyman             setPMBusExpectations(mockPMBus, expectations);
67382affd94SBrandon Wyman             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
67482affd94SBrandon Wyman                 .Times(1)
67582affd94SBrandon Wyman                 .WillOnce(Return("124000"));
6762916ea52SBrandon Wyman             psu2.analyze();
6772916ea52SBrandon Wyman             EXPECT_EQ(psu2.isPresent(), true);
678*c2906f47SBrandon Wyman             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
6792916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasInputFault(), false);
6802916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasMFRFault(), false);
6812916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasVINUVFault(), false);
6822916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasCommFault(), false);
6832916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasVoutOVFault(), false);
6842cf46945SBrandon Wyman             EXPECT_EQ(psu2.hasVoutUVFault(), false);
685b10b3be0SBrandon Wyman             EXPECT_EQ(psu2.hasIoutOCFault(), false);
6867ee4d7e4SBrandon Wyman             EXPECT_EQ(psu2.hasFanFault(), false);
6872916ea52SBrandon Wyman             EXPECT_EQ(psu2.hasTempFault(), false);
68806ca4590SBrandon Wyman             if (x < DEGLITCH_LIMIT)
68906ca4590SBrandon Wyman             {
69006ca4590SBrandon Wyman                 EXPECT_EQ(psu2.hasPgoodFault(), false);
69106ca4590SBrandon Wyman             }
69206ca4590SBrandon Wyman             else
69306ca4590SBrandon Wyman             {
6942916ea52SBrandon Wyman                 EXPECT_EQ(psu2.hasPgoodFault(), true);
6952916ea52SBrandon Wyman             }
69606ca4590SBrandon Wyman         }
69706ca4590SBrandon Wyman     }
6982916ea52SBrandon Wyman 
6993f1242f3SBrandon Wyman     // TODO: ReadFailure
7003f1242f3SBrandon Wyman }
7013f1242f3SBrandon Wyman 
70259a35793SBrandon Wyman TEST_F(PowerSupplyTests, OnOffConfig)
70359a35793SBrandon Wyman {
70459a35793SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
70559a35793SBrandon Wyman     uint8_t data = 0x15;
70659a35793SBrandon Wyman 
70759a35793SBrandon Wyman     // Test where PSU is NOT present
70859a35793SBrandon Wyman     try
70959a35793SBrandon Wyman     {
710681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
711681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
712681b2a36SB. J. Wyman 
7133ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
7143ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
715681b2a36SB. J. Wyman         ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
71659a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
717681b2a36SB. J. Wyman         // Constructor should set initial presence, default read returns 0.
71859a35793SBrandon Wyman         // If it is not present, I should not be trying to write to it.
71959a35793SBrandon Wyman         EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
72059a35793SBrandon Wyman         psu.onOffConfig(data);
72159a35793SBrandon Wyman     }
72259a35793SBrandon Wyman     catch (...)
7230c9a33d6SAdriana Kobylak     {}
72459a35793SBrandon Wyman 
72559a35793SBrandon Wyman     // Test where PSU is present
72659a35793SBrandon Wyman     try
72759a35793SBrandon Wyman     {
728681b2a36SB. J. Wyman         // Assume GPIO presence, not inventory presence?
729681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
7303ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
7313ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
732391a0690SBrandon Wyman         // There will potentially be multiple calls, we want it to continue
733391a0690SBrandon Wyman         // returning 1 for the GPIO read to keep the power supply present.
734391a0690SBrandon Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
73559a35793SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
736391a0690SBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
737391a0690SBrandon Wyman         // If I am calling analyze(), I should probably give it good data.
738391a0690SBrandon Wyman         // STATUS_WORD 0x0000 is powered on, no faults.
739391a0690SBrandon Wyman         PMBusExpectations expectations;
740391a0690SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
74182affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
74282affd94SBrandon Wyman             .Times(1)
74382affd94SBrandon Wyman             .WillOnce(Return("205000"));
744681b2a36SB. J. Wyman         psu.analyze();
745391a0690SBrandon Wyman         // I definitely should be writting ON_OFF_CONFIG if I call the function
746391a0690SBrandon Wyman         EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
747391a0690SBrandon Wyman                                            Type::HwmonDeviceDebug))
74859a35793SBrandon Wyman             .Times(1);
74959a35793SBrandon Wyman         psu.onOffConfig(data);
75059a35793SBrandon Wyman     }
75159a35793SBrandon Wyman     catch (...)
7520c9a33d6SAdriana Kobylak     {}
75359a35793SBrandon Wyman }
75459a35793SBrandon Wyman 
7553f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, ClearFaults)
7563f1242f3SBrandon Wyman {
7573f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
758681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName};
7593ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
7603ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
76106ca4590SBrandon Wyman     // Always return 1 to indicate present.
76206ca4590SBrandon Wyman     // Each analyze() call will trigger a read of the presence GPIO.
76306ca4590SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
764681b2a36SB. J. Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
765391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
7668da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
767b654c619SBrandon Wyman     PMBusExpectations expectations;
768b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
76982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
77082affd94SBrandon Wyman         .Times(1)
77182affd94SBrandon Wyman         .WillOnce(Return("207000"));
772681b2a36SB. J. Wyman     psu.analyze();
7733f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
7743f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
7753f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
7763f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
7773f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
77885c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
7796710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
780b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
7812cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
7827ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
78396893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
7842916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
78539ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
78639ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
78739ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
788b654c619SBrandon Wyman 
789f07bc797SBrandon Wyman     // STATUS_WORD with fault bits galore!
790b654c619SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
791f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
792b654c619SBrandon Wyman     expectations.statusInputValue = 0xFF;
793f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
794b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
79585c7bf41SBrandon Wyman     // STATUS_CML with bits on.
796b654c619SBrandon Wyman     expectations.statusCMLValue = 0xFF;
7976710ba2cSBrandon Wyman     // STATUS_VOUT with bits on.
798b654c619SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
799b10b3be0SBrandon Wyman     // STATUS_IOUT with bits on.
800b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
8017ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
8027ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0xFF;
80396893a46SBrandon Wyman     // STATUS_TEMPERATURE with bits on.
80496893a46SBrandon Wyman     expectations.statusTempValue = 0xFF;
805*c2906f47SBrandon Wyman 
806*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
807*c2906f47SBrandon Wyman     {
808b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
80982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
81082affd94SBrandon Wyman             .Times(1)
81182affd94SBrandon Wyman             .WillOnce(Return("0"));
8123f1242f3SBrandon Wyman         psu.analyze();
8133f1242f3SBrandon Wyman         EXPECT_EQ(psu.isPresent(), true);
8142cf46945SBrandon Wyman         // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
8152cf46945SBrandon Wyman         // Rely on HasVoutUVFault() to verify this sets and clears.
8162cf46945SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), false);
817*c2906f47SBrandon Wyman         // All faults are deglitched up to DEGLITCH_LIMIT
818*c2906f47SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
819*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
820*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
821*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
822*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT);
823*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
824*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
825*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
826*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
827*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPgoodFault(), x >= DEGLITCH_LIMIT);
828*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
829*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
830*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
831*c2906f47SBrandon Wyman     }
832*c2906f47SBrandon Wyman 
833*c2906f47SBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(207000));
8343f1242f3SBrandon Wyman     psu.clearFaults();
8353f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
8363f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
8373f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
8383f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
8393f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
84085c7bf41SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
8416710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
842b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
8432cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
8447ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
84596893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
8462916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
84739ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
84839ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
84939ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
850681b2a36SB. J. Wyman 
85182affd94SBrandon Wyman     // Faults clear on READ_VIN 0 -> !0
85282affd94SBrandon Wyman     // STATUS_WORD with fault bits galore!
85382affd94SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
85482affd94SBrandon Wyman     // STATUS_INPUT with fault bits on.
85582affd94SBrandon Wyman     expectations.statusInputValue = 0xFF;
85682affd94SBrandon Wyman     // STATUS_MFR_SPEFIC with bits on.
85782affd94SBrandon Wyman     expectations.statusMFRValue = 0xFF;
85882affd94SBrandon Wyman     // STATUS_CML with bits on.
85982affd94SBrandon Wyman     expectations.statusCMLValue = 0xFF;
86082affd94SBrandon Wyman     // STATUS_VOUT with bits on.
86182affd94SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
86282affd94SBrandon Wyman     // STATUS_IOUT with bits on.
86382affd94SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
86482affd94SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
86582affd94SBrandon Wyman     expectations.statusFans12Value = 0xFF;
86682affd94SBrandon Wyman     // STATUS_TEMPERATURE with bits on.
86782affd94SBrandon Wyman     expectations.statusTempValue = 0xFF;
868*c2906f47SBrandon Wyman 
869*c2906f47SBrandon Wyman     // All faults degltiched now. Check for false before limit above.
870*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
871*c2906f47SBrandon Wyman     {
87282affd94SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
87382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
87482affd94SBrandon Wyman             .Times(1)
87582affd94SBrandon Wyman             .WillOnce(Return("0"));
87682affd94SBrandon Wyman         psu.analyze();
877*c2906f47SBrandon Wyman     }
878*c2906f47SBrandon Wyman 
87982affd94SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
88082affd94SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
88182affd94SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), true);
88282affd94SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
88382affd94SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), true);
88482affd94SBrandon Wyman     // True due to CML fault bits on
88582affd94SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), true);
88682affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), true);
88782affd94SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), true);
88882affd94SBrandon Wyman     // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
88982affd94SBrandon Wyman     // Rely on HasVoutUVFault() to verify this sets and clears.
89082affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
89182affd94SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), true);
89282affd94SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), true);
893*c2906f47SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
89482affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), true);
89582affd94SBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), true);
89682affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), true);
89782affd94SBrandon Wyman     // STATUS_WORD with INPUT/VIN_UV fault bits off.
89882affd94SBrandon Wyman     expectations.statusWordValue = 0xDFF7;
89982affd94SBrandon Wyman     // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
90082affd94SBrandon Wyman     // Insufficient Input Voltage bits off.
90182affd94SBrandon Wyman     expectations.statusInputValue = 0xC7;
90282affd94SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
90382affd94SBrandon Wyman     // READ_VIN back in range.
90482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
90582affd94SBrandon Wyman         .Times(1)
90682affd94SBrandon Wyman         .WillOnce(Return("206000"));
907*c2906f47SBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(0));
90882affd94SBrandon Wyman     psu.analyze();
90982affd94SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
91082affd94SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
91182affd94SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
91282affd94SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
91382affd94SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
91482affd94SBrandon Wyman     EXPECT_EQ(psu.hasCommFault(), false);
91582affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
91682affd94SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
91782affd94SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
91882affd94SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
91982affd94SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
92082affd94SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
92182affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
92282affd94SBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
92382affd94SBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
92482affd94SBrandon Wyman 
925681b2a36SB. J. Wyman     // TODO: Faults clear on missing/present?
9263f1242f3SBrandon Wyman }
9273f1242f3SBrandon Wyman 
9283f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, UpdateInventory)
9293f1242f3SBrandon Wyman {
9303f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
9311d7a7df8SBrandon Wyman 
9321d7a7df8SBrandon Wyman     try
9331d7a7df8SBrandon Wyman     {
934681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
9351d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
9361d7a7df8SBrandon Wyman         // If it is not present, I should not be trying to read a string
9371d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
9381d7a7df8SBrandon Wyman         psu.updateInventory();
9391d7a7df8SBrandon Wyman     }
9401d7a7df8SBrandon Wyman     catch (...)
9411d7a7df8SBrandon Wyman     {
9421d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
9431d7a7df8SBrandon Wyman     }
9441d7a7df8SBrandon Wyman 
9451d7a7df8SBrandon Wyman     try
9461d7a7df8SBrandon Wyman     {
947681b2a36SB. J. Wyman         PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName};
9483ca062aeSAdriana Kobylak         MockedGPIOInterface* mockPresenceGPIO =
9493ca062aeSAdriana Kobylak             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
950681b2a36SB. J. Wyman         // GPIO read return 1 to indicate present.
951681b2a36SB. J. Wyman         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
9521d7a7df8SBrandon Wyman         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
953391a0690SBrandon Wyman         setMissingToPresentExpects(mockPMBus, mockedUtil);
954391a0690SBrandon Wyman         // STATUS_WORD 0x0000 is powered on, no faults.
955391a0690SBrandon Wyman         PMBusExpectations expectations;
956391a0690SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
95782affd94SBrandon Wyman         // Call to analyze will read voltage, trigger clear faults for 0 to
95882affd94SBrandon Wyman         // within range.
95982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
96082affd94SBrandon Wyman             .Times(1)
96182affd94SBrandon Wyman             .WillOnce(Return("123456"));
962391a0690SBrandon Wyman         psu.analyze();
9631d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
9643f1242f3SBrandon Wyman         psu.updateInventory();
9651d7a7df8SBrandon Wyman 
9663c530fbdSBrandon Wyman #if IBM_VPD
9671d7a7df8SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(_, _))
9681d7a7df8SBrandon Wyman             .WillOnce(Return("CCIN"))
9691d7a7df8SBrandon Wyman             .WillOnce(Return("PN3456"))
9701d7a7df8SBrandon Wyman             .WillOnce(Return("FN3456"))
9711d7a7df8SBrandon Wyman             .WillOnce(Return("HEADER"))
9721d7a7df8SBrandon Wyman             .WillOnce(Return("SN3456"))
9731d7a7df8SBrandon Wyman             .WillOnce(Return("FW3456"));
9743c530fbdSBrandon Wyman #endif
9751d7a7df8SBrandon Wyman         psu.updateInventory();
9761d7a7df8SBrandon Wyman         // TODO: D-Bus mocking to verify values stored on D-Bus (???)
9771d7a7df8SBrandon Wyman     }
9781d7a7df8SBrandon Wyman     catch (...)
9791d7a7df8SBrandon Wyman     {
9801d7a7df8SBrandon Wyman         ADD_FAILURE() << "Should not have caught exception.";
9811d7a7df8SBrandon Wyman     }
9823f1242f3SBrandon Wyman }
9833f1242f3SBrandon Wyman 
9843f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsPresent)
9853f1242f3SBrandon Wyman {
9863f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
987681b2a36SB. J. Wyman 
988681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
9893ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
9903ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
9913f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), false);
9923f1242f3SBrandon Wyman 
993681b2a36SB. J. Wyman     // Change GPIO read to return 1 to indicate present.
994681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
995391a0690SBrandon Wyman     // Call to analyze() will update to present, that will trigger updating
996391a0690SBrandon Wyman     // to the correct/latest HWMON directory, in case it changes.
997391a0690SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
998391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
999391a0690SBrandon Wyman     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1000391a0690SBrandon Wyman     // Default expectations will be on, no faults.
1001391a0690SBrandon Wyman     PMBusExpectations expectations;
1002391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
100382affd94SBrandon Wyman     // Give it an input voltage in the 100-volt range.
100482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
100582affd94SBrandon Wyman         .Times(1)
100682affd94SBrandon Wyman         .WillOnce(Return("123456"));
1007681b2a36SB. J. Wyman     psu.analyze();
1008681b2a36SB. J. Wyman     EXPECT_EQ(psu.isPresent(), true);
10093f1242f3SBrandon Wyman }
10103f1242f3SBrandon Wyman 
10113f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsFaulted)
10123f1242f3SBrandon Wyman {
10133f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1014681b2a36SB. J. Wyman 
1015681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName};
10163ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
10173ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1018681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1019681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1020391a0690SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1021391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1022391a0690SBrandon Wyman     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1023391a0690SBrandon Wyman     // Default expectations will be on, no faults.
1024391a0690SBrandon Wyman     PMBusExpectations expectations;
1025391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
102682affd94SBrandon Wyman     // Give it an input voltage in the 100-volt range.
102782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
102882affd94SBrandon Wyman         .Times(1)
102982affd94SBrandon Wyman         .WillOnce(Return("124680"));
1030681b2a36SB. J. Wyman     psu.analyze();
10313f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
1032f07bc797SBrandon Wyman     // STATUS_WORD with fault bits on.
1033b654c619SBrandon Wyman     expectations.statusWordValue = 0xFFFF;
1034f07bc797SBrandon Wyman     // STATUS_INPUT with fault bits on.
1035b654c619SBrandon Wyman     expectations.statusInputValue = 0xFF;
1036f07bc797SBrandon Wyman     // STATUS_MFR_SPECIFIC with faults bits on.
1037b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
103885c7bf41SBrandon Wyman     // STATUS_CML with faults bits on.
1039b654c619SBrandon Wyman     expectations.statusCMLValue = 0xFF;
10406710ba2cSBrandon Wyman     // STATUS_VOUT with fault bits on.
1041b654c619SBrandon Wyman     expectations.statusVOUTValue = 0xFF;
1042b10b3be0SBrandon Wyman     // STATUS_IOUT with fault bits on.
1043b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0xFF;
10447ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 with bits on.
10457ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0xFF;
104696893a46SBrandon Wyman     // STATUS_TEMPERATURE with fault bits on.
104796893a46SBrandon Wyman     expectations.statusTempValue = 0xFF;
1048*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1049*c2906f47SBrandon Wyman     {
1050b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
105182affd94SBrandon Wyman         // Also get another read of READ_VIN.
105282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
105382affd94SBrandon Wyman             .Times(1)
105482affd94SBrandon Wyman             .WillOnce(Return("125790"));
10553f1242f3SBrandon Wyman         psu.analyze();
1056*c2906f47SBrandon Wyman         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
1057*c2906f47SBrandon Wyman     }
10583f1242f3SBrandon Wyman }
10593f1242f3SBrandon Wyman 
10603f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasInputFault)
10613f1242f3SBrandon Wyman {
10623f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1063681b2a36SB. J. Wyman 
1064681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
10653ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
10663ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1067681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1068681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
10693f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1070391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
10718da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1072b654c619SBrandon Wyman     PMBusExpectations expectations;
1073b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
107482affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
107582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
107682affd94SBrandon Wyman         .Times(1)
107782affd94SBrandon Wyman         .WillOnce(Return("201100"));
10783f1242f3SBrandon Wyman     psu.analyze();
10793f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
1080f07bc797SBrandon Wyman     // STATUS_WORD with input fault/warn on.
1081b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
1082f07bc797SBrandon Wyman     // STATUS_INPUT with an input fault bit on.
1083b654c619SBrandon Wyman     expectations.statusInputValue = 0x80;
1084*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1085*c2906f47SBrandon Wyman     {
1086b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
108782affd94SBrandon Wyman         // Analyze call will also need good READ_VIN value to check.
108882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
108982affd94SBrandon Wyman             .Times(1)
109082affd94SBrandon Wyman             .WillOnce(Return("201200"));
10913f1242f3SBrandon Wyman         psu.analyze();
1092*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
1093*c2906f47SBrandon Wyman     }
1094f07bc797SBrandon Wyman     // STATUS_WORD with no bits on.
1095b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1096b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
109782affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
109882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
109982affd94SBrandon Wyman         .Times(1)
110082affd94SBrandon Wyman         .WillOnce(Return("201300"));
11013f1242f3SBrandon Wyman     psu.analyze();
11023f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
11033f1242f3SBrandon Wyman }
11043f1242f3SBrandon Wyman 
11053f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasMFRFault)
11063f1242f3SBrandon Wyman {
11073f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1108681b2a36SB. J. Wyman 
1109681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
11103ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
11113ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1112681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1113681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
11143f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1115391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1116f07bc797SBrandon Wyman     // First return STATUS_WORD with no bits on.
11178da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1118b654c619SBrandon Wyman     PMBusExpectations expectations;
1119b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
112082affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
112182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
112282affd94SBrandon Wyman         .Times(1)
112382affd94SBrandon Wyman         .WillOnce(Return("202100"));
11243f1242f3SBrandon Wyman     psu.analyze();
11253f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
1126f07bc797SBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
1127b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1128f07bc797SBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
1129b654c619SBrandon Wyman     expectations.statusMFRValue = 0xFF;
1130*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1131*c2906f47SBrandon Wyman     {
1132b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
113382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
113482affd94SBrandon Wyman             .Times(1)
113582affd94SBrandon Wyman             .WillOnce(Return("202200"));
11363f1242f3SBrandon Wyman         psu.analyze();
1137*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1138*c2906f47SBrandon Wyman     }
1139f07bc797SBrandon Wyman     // Back to no bits on in STATUS_WORD
1140b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1141b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
114282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
114382affd94SBrandon Wyman         .Times(1)
114482affd94SBrandon Wyman         .WillOnce(Return("202300"));
11453f1242f3SBrandon Wyman     psu.analyze();
11463f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
11473f1242f3SBrandon Wyman }
11483f1242f3SBrandon Wyman 
11493f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasVINUVFault)
11503f1242f3SBrandon Wyman {
11513f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1152681b2a36SB. J. Wyman 
1153681b2a36SB. J. Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
11543ca062aeSAdriana Kobylak     MockedGPIOInterface* mockPresenceGPIO =
11553ca062aeSAdriana Kobylak         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1156681b2a36SB. J. Wyman     // Always return 1 to indicate present.
1157681b2a36SB. J. Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
11583f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1159391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
116082affd94SBrandon Wyman 
116182affd94SBrandon Wyman     // Presence change from missing to present will trigger in1_input read in
116282affd94SBrandon Wyman     // an attempt to get CLEAR_FAULTS called. Return value ignored.
116382affd94SBrandon Wyman     // Zero to non-zero voltage, for missing/present change, triggers clear
116482affd94SBrandon Wyman     // faults call again. Return value ignored.
116582affd94SBrandon Wyman     // Fault (low voltage) to not faulted (voltage in range) triggers clear
116682affd94SBrandon Wyman     // faults call a third time.
116782affd94SBrandon Wyman 
11688da35c51SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1169b654c619SBrandon Wyman     PMBusExpectations expectations;
1170b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
117182affd94SBrandon Wyman     // Analyze call will also need good READ_VIN value to check.
117282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
117382affd94SBrandon Wyman         .Times(1)
117482affd94SBrandon Wyman         .WillOnce(Return("201100"));
11753f1242f3SBrandon Wyman     psu.analyze();
11763f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
1177f07bc797SBrandon Wyman     // Turn fault on.
1178b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::VIN_UV_FAULT);
117985c7bf41SBrandon Wyman     // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
118085c7bf41SBrandon Wyman     // Figure 16, and assume bits on in STATUS_INPUT.
1181b654c619SBrandon Wyman     expectations.statusInputValue = 0x18;
1182*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1183*c2906f47SBrandon Wyman     {
1184b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
118582affd94SBrandon Wyman         // If there is a VIN_UV fault, fake reading voltage of less than 20V
118682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
118782affd94SBrandon Wyman             .Times(1)
118882affd94SBrandon Wyman             .WillOnce(Return("19876"));
11893f1242f3SBrandon Wyman         psu.analyze();
1190*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1191*c2906f47SBrandon Wyman     }
1192f07bc797SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1193b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1194b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
119582affd94SBrandon Wyman     // Updates now result in clearing faults if read voltage goes from below the
119682affd94SBrandon Wyman     // minimum, to within a valid range.
119782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
119882affd94SBrandon Wyman         .Times(1)
119982affd94SBrandon Wyman         .WillOnce(Return("201300"));
120082affd94SBrandon Wyman     // Went from below minimum to within range, expect CLEAR_FAULTS.
120182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(3));
12023f1242f3SBrandon Wyman     psu.analyze();
12033f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
12043f1242f3SBrandon Wyman }
12056710ba2cSBrandon Wyman 
12066710ba2cSBrandon Wyman TEST_F(PowerSupplyTests, HasVoutOVFault)
12076710ba2cSBrandon Wyman {
12086710ba2cSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
12096710ba2cSBrandon Wyman 
12106710ba2cSBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName};
12116710ba2cSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
12126710ba2cSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
12136710ba2cSBrandon Wyman     // Always return 1 to indicate present.
12146710ba2cSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
12156710ba2cSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1216391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
12176710ba2cSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1218b654c619SBrandon Wyman     PMBusExpectations expectations;
1219b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
122082affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
122182affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
122282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
122382affd94SBrandon Wyman         .Times(1)
122482affd94SBrandon Wyman         .WillOnce(Return("202100"));
12256710ba2cSBrandon Wyman     psu.analyze();
12266710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
12276710ba2cSBrandon Wyman     // Turn fault on.
1228b654c619SBrandon Wyman     expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
12296710ba2cSBrandon Wyman     // STATUS_VOUT fault bit(s)
1230b654c619SBrandon Wyman     expectations.statusVOUTValue = 0x80;
1231*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1232*c2906f47SBrandon Wyman     {
1233b654c619SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
123482affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
123582affd94SBrandon Wyman             .Times(1)
123682affd94SBrandon Wyman             .WillOnce(Return("202200"));
12376710ba2cSBrandon Wyman         psu.analyze();
1238*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1239*c2906f47SBrandon Wyman     }
12406710ba2cSBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1241b654c619SBrandon Wyman     expectations.statusWordValue = 0;
1242b654c619SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
124382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
124482affd94SBrandon Wyman         .Times(1)
124582affd94SBrandon Wyman         .WillOnce(Return("202300"));
12466710ba2cSBrandon Wyman     psu.analyze();
12476710ba2cSBrandon Wyman     EXPECT_EQ(psu.hasVoutOVFault(), false);
12486710ba2cSBrandon Wyman }
124996893a46SBrandon Wyman 
1250b10b3be0SBrandon Wyman TEST_F(PowerSupplyTests, HasIoutOCFault)
1251b10b3be0SBrandon Wyman {
1252b10b3be0SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1253b10b3be0SBrandon Wyman 
1254b10b3be0SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
1255b10b3be0SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
1256b10b3be0SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1257b10b3be0SBrandon Wyman     // Always return 1 to indicate present.
1258b10b3be0SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1259b10b3be0SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1260391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1261b10b3be0SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
1262b10b3be0SBrandon Wyman     PMBusExpectations expectations;
1263b10b3be0SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
126482affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
126582affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
126682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
126782affd94SBrandon Wyman         .Times(1)
126882affd94SBrandon Wyman         .WillOnce(Return("203100"));
1269b10b3be0SBrandon Wyman     psu.analyze();
1270b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
1271b10b3be0SBrandon Wyman     // Turn fault on.
1272b10b3be0SBrandon Wyman     expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1273b10b3be0SBrandon Wyman     // STATUS_IOUT fault bit(s)
1274b10b3be0SBrandon Wyman     expectations.statusIOUTValue = 0x88;
1275*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1276*c2906f47SBrandon Wyman     {
1277b10b3be0SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
127882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
127982affd94SBrandon Wyman             .Times(1)
128082affd94SBrandon Wyman             .WillOnce(Return("203200"));
1281b10b3be0SBrandon Wyman         psu.analyze();
1282*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1283*c2906f47SBrandon Wyman     }
1284b10b3be0SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
1285b10b3be0SBrandon Wyman     expectations.statusWordValue = 0;
1286b10b3be0SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
128782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
128882affd94SBrandon Wyman         .Times(1)
128982affd94SBrandon Wyman         .WillOnce(Return("203300"));
1290b10b3be0SBrandon Wyman     psu.analyze();
1291b10b3be0SBrandon Wyman     EXPECT_EQ(psu.hasIoutOCFault(), false);
1292b10b3be0SBrandon Wyman }
1293b10b3be0SBrandon Wyman 
12942cf46945SBrandon Wyman TEST_F(PowerSupplyTests, HasVoutUVFault)
12952cf46945SBrandon Wyman {
12962cf46945SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
12972cf46945SBrandon Wyman 
12982cf46945SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
12992cf46945SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
13002cf46945SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
13012cf46945SBrandon Wyman     // Always return 1 to indicate present.
13022cf46945SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
13032cf46945SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1304391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
1305391a0690SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
13062cf46945SBrandon Wyman     PMBusExpectations expectations;
13072cf46945SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
130882affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
130982affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
131082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
131182affd94SBrandon Wyman         .Times(1)
131282affd94SBrandon Wyman         .WillOnce(Return("204100"));
13132cf46945SBrandon Wyman     psu.analyze();
13142cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
13152cf46945SBrandon Wyman     // Turn fault on.
13162cf46945SBrandon Wyman     expectations.statusWordValue = (status_word::VOUT_FAULT);
13172cf46945SBrandon Wyman     // STATUS_VOUT fault bit(s)
13182cf46945SBrandon Wyman     expectations.statusVOUTValue = 0x30;
1319*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1320*c2906f47SBrandon Wyman     {
13212cf46945SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
132282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
132382affd94SBrandon Wyman             .Times(1)
132482affd94SBrandon Wyman             .WillOnce(Return("204200"));
13252cf46945SBrandon Wyman         psu.analyze();
1326*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1327*c2906f47SBrandon Wyman     }
13282cf46945SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
13292cf46945SBrandon Wyman     expectations.statusWordValue = 0;
13302cf46945SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
133182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
133282affd94SBrandon Wyman         .Times(1)
133382affd94SBrandon Wyman         .WillOnce(Return("204300"));
13342cf46945SBrandon Wyman     psu.analyze();
13352cf46945SBrandon Wyman     EXPECT_EQ(psu.hasVoutUVFault(), false);
13362cf46945SBrandon Wyman }
13372cf46945SBrandon Wyman 
13387ee4d7e4SBrandon Wyman TEST_F(PowerSupplyTests, HasFanFault)
13397ee4d7e4SBrandon Wyman {
13407ee4d7e4SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
13417ee4d7e4SBrandon Wyman 
13427ee4d7e4SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
13437ee4d7e4SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
13447ee4d7e4SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
13457ee4d7e4SBrandon Wyman     // Always return 1 to indicate present.
13467ee4d7e4SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
13477ee4d7e4SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1348391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
13497ee4d7e4SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
13507ee4d7e4SBrandon Wyman     PMBusExpectations expectations;
13517ee4d7e4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
135282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
135382affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
135482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
135582affd94SBrandon Wyman         .Times(1)
135682affd94SBrandon Wyman         .WillOnce(Return("205100"));
13577ee4d7e4SBrandon Wyman     psu.analyze();
13587ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
13597ee4d7e4SBrandon Wyman     // Turn fault on.
13607ee4d7e4SBrandon Wyman     expectations.statusWordValue = (status_word::FAN_FAULT);
13617ee4d7e4SBrandon Wyman     // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
13627ee4d7e4SBrandon Wyman     expectations.statusFans12Value = 0x80;
1363*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1364*c2906f47SBrandon Wyman     {
13657ee4d7e4SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
136682affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
136782affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
136882affd94SBrandon Wyman             .Times(1)
136982affd94SBrandon Wyman             .WillOnce(Return("205200"));
13707ee4d7e4SBrandon Wyman         psu.analyze();
1371*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1372*c2906f47SBrandon Wyman     }
13737ee4d7e4SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
13747ee4d7e4SBrandon Wyman     expectations.statusWordValue = 0;
13757ee4d7e4SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
137682affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
137782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
137882affd94SBrandon Wyman         .Times(1)
137982affd94SBrandon Wyman         .WillOnce(Return("205300"));
13807ee4d7e4SBrandon Wyman     psu.analyze();
13817ee4d7e4SBrandon Wyman     EXPECT_EQ(psu.hasFanFault(), false);
13827ee4d7e4SBrandon Wyman }
13837ee4d7e4SBrandon Wyman 
138496893a46SBrandon Wyman TEST_F(PowerSupplyTests, HasTempFault)
138596893a46SBrandon Wyman {
138696893a46SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
138796893a46SBrandon Wyman 
138896893a46SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
138996893a46SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
139096893a46SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
139196893a46SBrandon Wyman     // Always return 1 to indicate present.
139296893a46SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
139396893a46SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1394391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
139596893a46SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
139696893a46SBrandon Wyman     PMBusExpectations expectations;
139796893a46SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
139882affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
139982affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
140082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
140182affd94SBrandon Wyman         .Times(1)
140282affd94SBrandon Wyman         .WillOnce(Return("206100"));
140396893a46SBrandon Wyman     psu.analyze();
140496893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
140596893a46SBrandon Wyman     // Turn fault on.
140696893a46SBrandon Wyman     expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
140796893a46SBrandon Wyman     // STATUS_TEMPERATURE fault bit on (OT Fault)
140896893a46SBrandon Wyman     expectations.statusTempValue = 0x80;
1409*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1410*c2906f47SBrandon Wyman     {
141196893a46SBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
141282affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
141382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
141482affd94SBrandon Wyman             .Times(1)
141582affd94SBrandon Wyman             .WillOnce(Return("206200"));
141696893a46SBrandon Wyman         psu.analyze();
1417*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1418*c2906f47SBrandon Wyman     }
141996893a46SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
142096893a46SBrandon Wyman     expectations.statusWordValue = 0;
142196893a46SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
142282affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
142382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
142482affd94SBrandon Wyman         .Times(1)
142582affd94SBrandon Wyman         .WillOnce(Return("206300"));
142696893a46SBrandon Wyman     psu.analyze();
142796893a46SBrandon Wyman     EXPECT_EQ(psu.hasTempFault(), false);
142896893a46SBrandon Wyman }
14292916ea52SBrandon Wyman 
14302916ea52SBrandon Wyman TEST_F(PowerSupplyTests, HasPgoodFault)
14312916ea52SBrandon Wyman {
14322916ea52SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
14332916ea52SBrandon Wyman 
14342916ea52SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, PSUGPIOLineName};
14352916ea52SBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
14362916ea52SBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
14372916ea52SBrandon Wyman     // Always return 1 to indicate present.
14382916ea52SBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
14392916ea52SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1440391a0690SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
14412916ea52SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
14422916ea52SBrandon Wyman     PMBusExpectations expectations;
14432916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
144482affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
144582affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
144682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
144782affd94SBrandon Wyman         .Times(1)
144882affd94SBrandon Wyman         .WillOnce(Return("207100"));
14492916ea52SBrandon Wyman     psu.analyze();
14502916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
1451391a0690SBrandon Wyman     // Setup another expectation of no faults.
1452391a0690SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
145382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
145482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
145582affd94SBrandon Wyman         .Times(1)
145682affd94SBrandon Wyman         .WillOnce(Return("207200"));
145782affd94SBrandon Wyman     psu.analyze();
145882affd94SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
145982affd94SBrandon Wyman     // Setup another expectation of no faults.
146082affd94SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
146182affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
146282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
146382affd94SBrandon Wyman         .Times(1)
146482affd94SBrandon Wyman         .WillOnce(Return("207300"));
1465391a0690SBrandon Wyman     psu.analyze();
1466391a0690SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
14672916ea52SBrandon Wyman     // Turn PGOOD# off (fault on).
14682916ea52SBrandon Wyman     expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
14692916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
147082affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
147182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
147282affd94SBrandon Wyman         .Times(1)
147382affd94SBrandon Wyman         .WillOnce(Return("207400"));
14742916ea52SBrandon Wyman     psu.analyze();
147506ca4590SBrandon Wyman     // Expect false until reaches DEGLITCH_LIMIT
147606ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
147706ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
147882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
147982affd94SBrandon Wyman         .Times(1)
148082affd94SBrandon Wyman         .WillOnce(Return("207500"));
148106ca4590SBrandon Wyman     psu.analyze();
148206ca4590SBrandon Wyman     // Expect false until reaches DEGLITCH_LIMIT
148306ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
148406ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
148582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
148682affd94SBrandon Wyman         .Times(1)
148782affd94SBrandon Wyman         .WillOnce(Return("207600"));
148806ca4590SBrandon Wyman     psu.analyze();
148906ca4590SBrandon Wyman     // DEGLITCH_LIMIT reached, expect true.
14902916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
14912916ea52SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
14922916ea52SBrandon Wyman     expectations.statusWordValue = 0;
14932916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
149482affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
149582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
149682affd94SBrandon Wyman         .Times(1)
149782affd94SBrandon Wyman         .WillOnce(Return("207700"));
14982916ea52SBrandon Wyman     psu.analyze();
14992916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
150082affd94SBrandon Wyman 
15012916ea52SBrandon Wyman     // Turn OFF bit on
15022916ea52SBrandon Wyman     expectations.statusWordValue = (status_word::UNIT_IS_OFF);
15032916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
150482affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
150582affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
150682affd94SBrandon Wyman         .Times(1)
150782affd94SBrandon Wyman         .WillOnce(Return("208100"));
15082916ea52SBrandon Wyman     psu.analyze();
150906ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
151006ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
151182affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
151282affd94SBrandon Wyman         .Times(1)
151382affd94SBrandon Wyman         .WillOnce(Return("208200"));
151406ca4590SBrandon Wyman     psu.analyze();
151506ca4590SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
151606ca4590SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
151782affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
151882affd94SBrandon Wyman         .Times(1)
151982affd94SBrandon Wyman         .WillOnce(Return("208300"));
152006ca4590SBrandon Wyman     psu.analyze();
15212916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), true);
15222916ea52SBrandon Wyman     // Back to no fault bits on in STATUS_WORD
15232916ea52SBrandon Wyman     expectations.statusWordValue = 0;
15242916ea52SBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
152582affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
152682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
152782affd94SBrandon Wyman         .Times(1)
152882affd94SBrandon Wyman         .WillOnce(Return("208400"));
15292916ea52SBrandon Wyman     psu.analyze();
15302916ea52SBrandon Wyman     EXPECT_EQ(psu.hasPgoodFault(), false);
15312916ea52SBrandon Wyman }
153239ea02bcSBrandon Wyman 
153339ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPSKillFault)
153439ea02bcSBrandon Wyman {
153539ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
153639ea02bcSBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 4, 0x6d, PSUGPIOLineName};
153739ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
153839ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
153939ea02bcSBrandon Wyman     // Always return 1 to indicate present.
154039ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
154139ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
154282affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
154339ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
154439ea02bcSBrandon Wyman     PMBusExpectations expectations;
154539ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
154682affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
154782affd94SBrandon Wyman     // Initial value would be 0, so this read updates it to non-zero.
154882affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
154982affd94SBrandon Wyman         .Times(1)
155082affd94SBrandon Wyman         .WillOnce(Return("208100"));
155139ea02bcSBrandon Wyman     psu.analyze();
155239ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
155339ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
155439ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
155539ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
155639ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1557*c2906f47SBrandon Wyman 
1558*c2906f47SBrandon Wyman     // Deglitching faults, false until read the fault bits on up to the limit.
1559*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1560*c2906f47SBrandon Wyman     {
156139ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
156282affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
156382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
156482affd94SBrandon Wyman             .Times(1)
156582affd94SBrandon Wyman             .WillOnce(Return("208200"));
156639ea02bcSBrandon Wyman         psu.analyze();
1567*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1568*c2906f47SBrandon Wyman     }
1569*c2906f47SBrandon Wyman 
157039ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
157139ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
157239ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
157382affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
157482affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
157582affd94SBrandon Wyman         .Times(1)
157682affd94SBrandon Wyman         .WillOnce(Return("208300"));
157739ea02bcSBrandon Wyman     psu.analyze();
157839ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
157939ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
158039ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
158139ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 4 on.
158239ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x10;
1583*c2906f47SBrandon Wyman 
1584*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1585*c2906f47SBrandon Wyman     {
158639ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
158782affd94SBrandon Wyman         // Call to analyze will trigger read of "in1_input" to check voltage.
158882affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
158982affd94SBrandon Wyman             .Times(1)
159082affd94SBrandon Wyman             .WillOnce(Return("208400"));
159139ea02bcSBrandon Wyman         psu.analyze();
1592*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1593*c2906f47SBrandon Wyman     }
1594*c2906f47SBrandon Wyman 
159539ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
159639ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
159739ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
159882affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
159982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
160082affd94SBrandon Wyman         .Times(1)
160182affd94SBrandon Wyman         .WillOnce(Return("208500"));
160239ea02bcSBrandon Wyman     psu.analyze();
160339ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSKillFault(), false);
160439ea02bcSBrandon Wyman }
160539ea02bcSBrandon Wyman 
160639ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPS12VcsFault)
160739ea02bcSBrandon Wyman {
160839ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
160939ea02bcSBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 5, 0x6e, PSUGPIOLineName};
161039ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
161139ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
161239ea02bcSBrandon Wyman     // Always return 1 to indicate present.
161339ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
161439ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
161582affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
161639ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
161739ea02bcSBrandon Wyman     PMBusExpectations expectations;
161839ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
161982affd94SBrandon Wyman     // Call to analyze will trigger read of "in1_input" to check voltage.
162082affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
162182affd94SBrandon Wyman         .Times(1)
162282affd94SBrandon Wyman         .WillOnce(Return("209100"));
162339ea02bcSBrandon Wyman     psu.analyze();
162439ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
162539ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
162639ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
162739ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
162839ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1629*c2906f47SBrandon Wyman 
1630*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1631*c2906f47SBrandon Wyman     {
163239ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
163382affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
163482affd94SBrandon Wyman             .Times(1)
163582affd94SBrandon Wyman             .WillOnce(Return("209200"));
163639ea02bcSBrandon Wyman         psu.analyze();
1637*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1638*c2906f47SBrandon Wyman     }
1639*c2906f47SBrandon Wyman 
164039ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
164139ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
164239ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
164382affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
164482affd94SBrandon Wyman         .Times(1)
164582affd94SBrandon Wyman         .WillOnce(Return("209300"));
164639ea02bcSBrandon Wyman     psu.analyze();
164739ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
164839ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
164939ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
165039ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 6 on.
165139ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x40;
1652*c2906f47SBrandon Wyman 
1653*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1654*c2906f47SBrandon Wyman     {
165539ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
165682affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
165782affd94SBrandon Wyman             .Times(1)
165882affd94SBrandon Wyman             .WillOnce(Return("209400"));
165939ea02bcSBrandon Wyman         psu.analyze();
1660*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1661*c2906f47SBrandon Wyman     }
1662*c2906f47SBrandon Wyman 
166339ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
166439ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
166539ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
166682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
166782affd94SBrandon Wyman         .Times(1)
166882affd94SBrandon Wyman         .WillOnce(Return("209500"));
166939ea02bcSBrandon Wyman     psu.analyze();
167039ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPS12VcsFault(), false);
167139ea02bcSBrandon Wyman }
167239ea02bcSBrandon Wyman 
167339ea02bcSBrandon Wyman TEST_F(PowerSupplyTests, HasPSCS12VFault)
167439ea02bcSBrandon Wyman {
167539ea02bcSBrandon Wyman     auto bus = sdbusplus::bus::new_default();
167639ea02bcSBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f, PSUGPIOLineName};
167739ea02bcSBrandon Wyman     MockedGPIOInterface* mockPresenceGPIO =
167839ea02bcSBrandon Wyman         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
167939ea02bcSBrandon Wyman     // Always return 1 to indicate present.
168039ea02bcSBrandon Wyman     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
168139ea02bcSBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
168282affd94SBrandon Wyman     setMissingToPresentExpects(mockPMBus, mockedUtil);
168339ea02bcSBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
168439ea02bcSBrandon Wyman     PMBusExpectations expectations;
168539ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
168682affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
168782affd94SBrandon Wyman         .Times(1)
168882affd94SBrandon Wyman         .WillOnce(Return("209100"));
168939ea02bcSBrandon Wyman     psu.analyze();
169039ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
169139ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
169239ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
169339ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit(s) on.
169439ea02bcSBrandon Wyman     expectations.statusMFRValue = 0xFF;
1695*c2906f47SBrandon Wyman 
1696*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1697*c2906f47SBrandon Wyman     {
169839ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
169982affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
170082affd94SBrandon Wyman             .Times(1)
170182affd94SBrandon Wyman             .WillOnce(Return("209200"));
170239ea02bcSBrandon Wyman         psu.analyze();
1703*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1704*c2906f47SBrandon Wyman     }
1705*c2906f47SBrandon Wyman 
170639ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
170739ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
170839ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
170982affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
171082affd94SBrandon Wyman         .Times(1)
171182affd94SBrandon Wyman         .WillOnce(Return("209300"));
171239ea02bcSBrandon Wyman     psu.analyze();
171339ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
171439ea02bcSBrandon Wyman     // Next return STATUS_WORD with MFR fault bit on.
171539ea02bcSBrandon Wyman     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
171639ea02bcSBrandon Wyman     // STATUS_MFR_SPEFIC with bit 7 on.
171739ea02bcSBrandon Wyman     expectations.statusMFRValue = 0x80;
1718*c2906f47SBrandon Wyman 
1719*c2906f47SBrandon Wyman     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1720*c2906f47SBrandon Wyman     {
172139ea02bcSBrandon Wyman         setPMBusExpectations(mockPMBus, expectations);
172282affd94SBrandon Wyman         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
172382affd94SBrandon Wyman             .Times(1)
172482affd94SBrandon Wyman             .WillOnce(Return("209400"));
172539ea02bcSBrandon Wyman         psu.analyze();
1726*c2906f47SBrandon Wyman         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1727*c2906f47SBrandon Wyman     }
1728*c2906f47SBrandon Wyman 
172939ea02bcSBrandon Wyman     // Back to no bits on in STATUS_WORD
173039ea02bcSBrandon Wyman     expectations.statusWordValue = 0;
173139ea02bcSBrandon Wyman     setPMBusExpectations(mockPMBus, expectations);
173282affd94SBrandon Wyman     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
173382affd94SBrandon Wyman         .Times(1)
173482affd94SBrandon Wyman         .WillOnce(Return("209500"));
173539ea02bcSBrandon Wyman     psu.analyze();
173639ea02bcSBrandon Wyman     EXPECT_EQ(psu.hasPSCS12VFault(), false);
173739ea02bcSBrandon Wyman }
1738