1 #include "../power_supply.hpp"
2 #include "mock.hpp"
3 
4 #include <xyz/openbmc_project/Common/Device/error.hpp>
5 #include <xyz/openbmc_project/Common/error.hpp>
6 
7 #include <gmock/gmock.h>
8 #include <gtest/gtest.h>
9 
10 using namespace phosphor::power::psu;
11 using namespace phosphor::pmbus;
12 
13 using ::testing::_;
14 using ::testing::Args;
15 using ::testing::Assign;
16 using ::testing::DoAll;
17 using ::testing::ElementsAre;
18 using ::testing::IsNan;
19 using ::testing::NotNull;
20 using ::testing::Return;
21 using ::testing::StrEq;
22 
23 static auto PSUInventoryPath = "/xyz/bmc/inv/sys/chassis/board/powersupply0";
24 static auto PSUGPIOLineName = "presence-ps0";
25 static auto isPowerOn = []() { return true; };
26 
27 struct PMBusExpectations
28 {
29     uint16_t statusWordValue{0x0000};
30     uint8_t statusInputValue{0x00};
31     uint8_t statusMFRValue{0x00};
32     uint8_t statusCMLValue{0x00};
33     uint8_t statusVOUTValue{0x00};
34     uint8_t statusIOUTValue{0x00};
35     uint8_t statusFans12Value{0x00};
36     uint8_t statusTempValue{0x00};
37 };
38 
39 // Helper function to setup expectations for various STATUS_* commands
40 void setPMBusExpectations(MockedPMBus& mockPMBus,
41                           const PMBusExpectations& expectations)
42 {
43     EXPECT_CALL(mockPMBus, read(STATUS_WORD, _, _))
44         .Times(1)
45         .WillOnce(Return(expectations.statusWordValue));
46 
47     if (expectations.statusWordValue != 0)
48     {
49         // If fault bits are on in STATUS_WORD, there will also be a read of
50         // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and
51         // STATUS_TEMPERATURE.
52         EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _, _))
53             .Times(1)
54             .WillOnce(Return(expectations.statusInputValue));
55         EXPECT_CALL(mockPMBus, read(STATUS_MFR, _, _))
56             .Times(1)
57             .WillOnce(Return(expectations.statusMFRValue));
58         EXPECT_CALL(mockPMBus, read(STATUS_CML, _, _))
59             .Times(1)
60             .WillOnce(Return(expectations.statusCMLValue));
61         // Page will need to be set to 0 to read STATUS_VOUT.
62         EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0))
63             .Times(1)
64             .WillOnce(Return("status0_vout"));
65         EXPECT_CALL(mockPMBus, read("status0_vout", _, _))
66             .Times(1)
67             .WillOnce(Return(expectations.statusVOUTValue));
68         EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _, _))
69             .Times(1)
70             .WillOnce(Return(expectations.statusIOUTValue));
71         EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _, _))
72             .Times(1)
73             .WillOnce(Return(expectations.statusFans12Value));
74         EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _, _))
75             .Times(1)
76             .WillOnce(Return(expectations.statusTempValue));
77     }
78 
79     // Default max/peak is 213W
80     ON_CALL(mockPMBus, readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug, 5))
81         .WillByDefault(
82             Return(std::vector<uint8_t>{0x01, 0x5c, 0xf3, 0x54, 0xf3}));
83 }
84 
85 class PowerSupplyTests : public ::testing::Test
86 {
87   public:
88     PowerSupplyTests() :
89         mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
90     {
91         ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
92     }
93 
94     ~PowerSupplyTests() override
95     {
96         freeUtils();
97     }
98 
99     const MockedUtil& mockedUtil;
100 };
101 
102 // Helper function for when a power supply goes from missing to present.
103 void setMissingToPresentExpects(MockedPMBus& pmbus, const MockedUtil& util)
104 {
105     // Call to analyze() will update to present, that will trigger updating
106     // to the correct/latest HWMON directory, in case it changes.
107     EXPECT_CALL(pmbus, findHwmonDir());
108     // Presence change from missing to present will trigger write to
109     // ON_OFF_CONFIG.
110     EXPECT_CALL(pmbus, writeBinary(ON_OFF_CONFIG, _, _));
111     // Presence change from missing to present will trigger in1_input read
112     // in an attempt to get CLEAR_FAULTS called.
113     // This READ_VIN for CLEAR_FAULTS does not check the returned value.
114     EXPECT_CALL(pmbus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
115     // The call for clearing faults includes clearing VIN_UV fault.
116     // The voltage defaults to 0, the first call to analyze should update the
117     // voltage to the current reading, triggering clearing VIN_UV fault(s)
118     // due to below minimum to within range voltage.
119     EXPECT_CALL(pmbus, read("in1_lcrit_alarm", _, _))
120         .Times(2)
121         .WillRepeatedly(Return(1));
122     // Missing/present call will update Presence in inventory.
123     EXPECT_CALL(util, setPresence(_, _, true, _));
124 }
125 
126 TEST_F(PowerSupplyTests, Constructor)
127 {
128     /**
129      * @param[in] invpath - String for inventory path to use
130      * @param[in] i2cbus - The bus number this power supply is on
131      * @param[in] i2caddr - The 16-bit I2C address of the power supply
132      * @param[in] gpioLineName - The string for the gpio-line-name to read for
133      * presence.
134      * @param[in] bindDelay - Time in milliseconds to delay binding the device
135      * driver after seeing the presence line go active.
136      */
137     auto bus = sdbusplus::bus::new_default();
138 
139     // Try where inventory path is empty, constructor should fail.
140     try
141     {
142         auto psu = std::make_unique<PowerSupply>(bus, "", 3, 0x68, "ibm-cffps",
143                                                  PSUGPIOLineName, isPowerOn);
144         ADD_FAILURE() << "Should not have reached this line.";
145     }
146     catch (const std::invalid_argument& e)
147     {
148         EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
149     }
150     catch (...)
151     {
152         ADD_FAILURE() << "Should not have caught exception.";
153     }
154 
155     // TODO: Try invalid i2c address?
156 
157     // Try where gpioLineName is empty.
158     try
159     {
160         auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
161                                                  "ibm-cffps", "", isPowerOn);
162         ADD_FAILURE()
163             << "Should not have reached this line. Invalid gpioLineName.";
164     }
165     catch (const std::invalid_argument& e)
166     {
167         EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
168     }
169     catch (...)
170     {
171         ADD_FAILURE() << "Should not have caught exception.";
172     }
173 
174     // Test with valid arguments
175     // NOT using D-Bus inventory path for presence.
176     try
177     {
178         auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
179                                                  "ibm-cffps", PSUGPIOLineName,
180                                                  isPowerOn);
181 
182         EXPECT_EQ(psu->isPresent(), false);
183         EXPECT_EQ(psu->isFaulted(), false);
184         EXPECT_EQ(psu->hasCommFault(), false);
185         EXPECT_EQ(psu->hasInputFault(), false);
186         EXPECT_EQ(psu->hasMFRFault(), false);
187         EXPECT_EQ(psu->hasVINUVFault(), false);
188         EXPECT_EQ(psu->hasVoutOVFault(), false);
189         EXPECT_EQ(psu->hasIoutOCFault(), false);
190         EXPECT_EQ(psu->hasVoutUVFault(), false);
191         EXPECT_EQ(psu->hasFanFault(), false);
192         EXPECT_EQ(psu->hasTempFault(), false);
193         EXPECT_EQ(psu->hasPgoodFault(), false);
194         EXPECT_EQ(psu->hasPSKillFault(), false);
195         EXPECT_EQ(psu->hasPS12VcsFault(), false);
196         EXPECT_EQ(psu->hasPSCS12VFault(), false);
197     }
198     catch (...)
199     {
200         ADD_FAILURE() << "Should not have caught exception.";
201     }
202 
203     // Test with valid arguments
204     // TODO: Using D-Bus inventory path for presence.
205     try
206     {
207         // FIXME: How do I get that presenceGPIO.read() in the startup to throw
208         // an exception?
209 
210         // EXPECT_CALL(mockedUtil, getPresence(_,
211         // StrEq(PSUInventoryPath)))
212         //    .Times(1);
213     }
214     catch (...)
215     {
216         ADD_FAILURE() << "Should not have caught exception.";
217     }
218 }
219 
220 TEST_F(PowerSupplyTests, Analyze)
221 {
222     auto bus = sdbusplus::bus::new_default();
223 
224     {
225         // If I default to reading the GPIO, I will NOT expect a call to
226         // getPresence().
227 
228         PowerSupply psu{bus,         PSUInventoryPath, 4,        0x69,
229                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
230         MockedGPIOInterface* mockPresenceGPIO =
231             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
232         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
233 
234         psu.analyze();
235         // By default, nothing should change.
236         EXPECT_EQ(psu.isPresent(), false);
237         EXPECT_EQ(psu.isFaulted(), false);
238         EXPECT_EQ(psu.hasInputFault(), false);
239         EXPECT_EQ(psu.hasMFRFault(), false);
240         EXPECT_EQ(psu.hasVINUVFault(), false);
241         EXPECT_EQ(psu.hasCommFault(), false);
242         EXPECT_EQ(psu.hasVoutOVFault(), false);
243         EXPECT_EQ(psu.hasIoutOCFault(), false);
244         EXPECT_EQ(psu.hasVoutUVFault(), false);
245         EXPECT_EQ(psu.hasFanFault(), false);
246         EXPECT_EQ(psu.hasTempFault(), false);
247         EXPECT_EQ(psu.hasPgoodFault(), false);
248         EXPECT_EQ(psu.hasPSKillFault(), false);
249         EXPECT_EQ(psu.hasPS12VcsFault(), false);
250         EXPECT_EQ(psu.hasPSCS12VFault(), false);
251     }
252 
253     PowerSupply psu2{bus,         PSUInventoryPath, 5,        0x6a,
254                      "ibm-cffps", PSUGPIOLineName,  isPowerOn};
255     // In order to get the various faults tested, the power supply needs to
256     // be present in order to read from the PMBus device(s).
257     MockedGPIOInterface* mockPresenceGPIO2 =
258         static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
259     // Always return 1 to indicate present.
260     // Each analyze() call will trigger a read of the presence GPIO.
261     EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1));
262     EXPECT_EQ(psu2.isPresent(), false);
263 
264     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
265     setMissingToPresentExpects(mockPMBus, mockedUtil);
266     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
267     // for INPUT_HISTORY will check max_power_out to see if it is
268     // old/unsupported power supply. Indicate good value, supported.
269     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
270         .WillRepeatedly(Return("2000"));
271 
272     // STATUS_WORD INPUT fault.
273     {
274         // Start with STATUS_WORD 0x0000. Powered on, no faults.
275         // Set expectations for a no fault
276         PMBusExpectations expectations;
277         setPMBusExpectations(mockPMBus, expectations);
278         // After reading STATUS_WORD, etc., there will be a READ_VIN check.
279         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
280             .Times(1)
281             .WillOnce(Return("206000"));
282         psu2.analyze();
283         EXPECT_EQ(psu2.isPresent(), true);
284         EXPECT_EQ(psu2.isFaulted(), false);
285         EXPECT_EQ(psu2.hasInputFault(), false);
286         EXPECT_EQ(psu2.hasMFRFault(), false);
287         EXPECT_EQ(psu2.hasVINUVFault(), false);
288         EXPECT_EQ(psu2.hasCommFault(), false);
289         EXPECT_EQ(psu2.hasVoutOVFault(), false);
290         EXPECT_EQ(psu2.hasIoutOCFault(), false);
291         EXPECT_EQ(psu2.hasVoutUVFault(), false);
292         EXPECT_EQ(psu2.hasFanFault(), false);
293         EXPECT_EQ(psu2.hasTempFault(), false);
294         EXPECT_EQ(psu2.hasPgoodFault(), false);
295         EXPECT_EQ(psu2.hasPSKillFault(), false);
296         EXPECT_EQ(psu2.hasPS12VcsFault(), false);
297         EXPECT_EQ(psu2.hasPSCS12VFault(), false);
298 
299         // Update expectations for STATUS_WORD input fault/warn
300         // STATUS_INPUT fault bits ... on.
301         expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
302         // IIN_OC fault.
303         expectations.statusInputValue = 0x04;
304 
305         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
306         {
307             setPMBusExpectations(mockPMBus, expectations);
308             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
309                 .Times(1)
310                 .WillOnce(Return("207000"));
311             psu2.analyze();
312             EXPECT_EQ(psu2.isPresent(), true);
313             // Should not be faulted until it reaches the deglitch limit.
314             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
315             EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
316             EXPECT_EQ(psu2.hasMFRFault(), false);
317             EXPECT_EQ(psu2.hasVINUVFault(), false);
318             EXPECT_EQ(psu2.hasCommFault(), false);
319             EXPECT_EQ(psu2.hasVoutOVFault(), false);
320             EXPECT_EQ(psu2.hasIoutOCFault(), false);
321             EXPECT_EQ(psu2.hasVoutUVFault(), false);
322             EXPECT_EQ(psu2.hasFanFault(), false);
323             EXPECT_EQ(psu2.hasTempFault(), false);
324             EXPECT_EQ(psu2.hasPgoodFault(), false);
325             EXPECT_EQ(psu2.hasPSKillFault(), false);
326             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
327             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
328         }
329     }
330 
331     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
332     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
333         .Times(1)
334         .WillOnce(Return(1));
335     psu2.clearFaults();
336 
337     // STATUS_WORD INPUT/UV fault.
338     {
339         // First need it to return good status, then the fault
340         PMBusExpectations expectations;
341         setPMBusExpectations(mockPMBus, expectations);
342         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
343             .Times(1)
344             .WillOnce(Return("208000"));
345         psu2.analyze();
346         EXPECT_EQ(psu2.isFaulted(), false);
347         EXPECT_EQ(psu2.hasInputFault(), false);
348         // Now set fault bits in STATUS_WORD
349         expectations.statusWordValue =
350             (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
351         // STATUS_INPUT fault bits ... on.
352         expectations.statusInputValue = 0x18;
353         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
354         {
355             setPMBusExpectations(mockPMBus, expectations);
356             // Input/UV fault, so voltage should read back low.
357             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
358                 .Times(1)
359                 .WillOnce(Return("19123"));
360             psu2.analyze();
361             EXPECT_EQ(psu2.isPresent(), true);
362             // Only faulted if hit deglitch limit
363             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
364             EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
365             EXPECT_EQ(psu2.hasVINUVFault(), x >= DEGLITCH_LIMIT);
366             EXPECT_EQ(psu2.hasMFRFault(), false);
367             EXPECT_EQ(psu2.hasCommFault(), false);
368             EXPECT_EQ(psu2.hasVoutOVFault(), false);
369             EXPECT_EQ(psu2.hasIoutOCFault(), false);
370             EXPECT_EQ(psu2.hasVoutUVFault(), false);
371             EXPECT_EQ(psu2.hasFanFault(), false);
372             EXPECT_EQ(psu2.hasTempFault(), false);
373             EXPECT_EQ(psu2.hasPgoodFault(), false);
374             EXPECT_EQ(psu2.hasPSKillFault(), false);
375             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
376             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
377         }
378         // Turning VIN_UV fault off causes clearing of faults, causing read of
379         // in1_input as an attempt to get CLEAR_FAULTS called.
380         expectations.statusWordValue = 0;
381         setPMBusExpectations(mockPMBus, expectations);
382         // The call to read the voltage
383         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
384             .Times(1)
385             .WillOnce(Return("209000"));
386         // The call to clear VIN_UV/Off fault(s)
387         EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
388             .Times(1)
389             .WillOnce(Return(1));
390         psu2.analyze();
391         // Should remain present, no longer be faulted, no input fault, no
392         // VIN_UV fault. Nothing else should change.
393         EXPECT_EQ(psu2.isPresent(), true);
394         EXPECT_EQ(psu2.isFaulted(), false);
395         EXPECT_EQ(psu2.hasInputFault(), false);
396         EXPECT_EQ(psu2.hasVINUVFault(), false);
397     }
398 
399     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
400     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
401         .Times(1)
402         .WillOnce(Return(1));
403     psu2.clearFaults();
404 
405     // STATUS_WORD MFR fault.
406     {
407         // First need it to return good status, then the fault
408         PMBusExpectations expectations;
409         setPMBusExpectations(mockPMBus, expectations);
410         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
411             .Times(1)
412             .WillOnce(Return("210000"));
413         psu2.analyze();
414         // Now STATUS_WORD with MFR fault bit on.
415         expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
416         // STATUS_MFR bits on.
417         expectations.statusMFRValue = 0xFF;
418 
419         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
420         {
421             setPMBusExpectations(mockPMBus, expectations);
422             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
423                 .Times(1)
424                 .WillOnce(Return("211000"));
425             psu2.analyze();
426             EXPECT_EQ(psu2.isPresent(), true);
427             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
428             EXPECT_EQ(psu2.hasInputFault(), false);
429             EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT);
430             EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT);
431             EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
432             EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
433             EXPECT_EQ(psu2.hasVINUVFault(), false);
434             EXPECT_EQ(psu2.hasCommFault(), false);
435             EXPECT_EQ(psu2.hasVoutOVFault(), false);
436             EXPECT_EQ(psu2.hasIoutOCFault(), false);
437             EXPECT_EQ(psu2.hasVoutUVFault(), false);
438             EXPECT_EQ(psu2.hasFanFault(), false);
439             EXPECT_EQ(psu2.hasTempFault(), false);
440             EXPECT_EQ(psu2.hasPgoodFault(), false);
441         }
442     }
443 
444     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
445     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
446         .Times(1)
447         .WillOnce(Return(1));
448     psu2.clearFaults();
449 
450     // Temperature fault.
451     {
452         // First STATUS_WORD with no bits set, then with temperature fault.
453         PMBusExpectations expectations;
454         setPMBusExpectations(mockPMBus, expectations);
455         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
456             .Times(1)
457             .WillOnce(Return("212000"));
458         psu2.analyze();
459         // STATUS_WORD with temperature fault bit on.
460         expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
461         // STATUS_TEMPERATURE with fault bit(s) on.
462         expectations.statusTempValue = 0x10;
463         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
464         {
465             setPMBusExpectations(mockPMBus, expectations);
466             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
467                 .Times(1)
468                 .WillOnce(Return("213000"));
469             psu2.analyze();
470             EXPECT_EQ(psu2.isPresent(), true);
471             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
472             EXPECT_EQ(psu2.hasInputFault(), false);
473             EXPECT_EQ(psu2.hasMFRFault(), false);
474             EXPECT_EQ(psu2.hasVINUVFault(), false);
475             EXPECT_EQ(psu2.hasCommFault(), false);
476             EXPECT_EQ(psu2.hasVoutOVFault(), false);
477             EXPECT_EQ(psu2.hasIoutOCFault(), false);
478             EXPECT_EQ(psu2.hasVoutUVFault(), false);
479             EXPECT_EQ(psu2.hasFanFault(), false);
480             EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT);
481             EXPECT_EQ(psu2.hasPgoodFault(), false);
482             EXPECT_EQ(psu2.hasPSKillFault(), false);
483             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
484             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
485         }
486     }
487 
488     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
489     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
490         .Times(1)
491         .WillOnce(Return(1));
492     psu2.clearFaults();
493 
494     // CML fault
495     {
496         // First STATUS_WORD wit no bits set, then with CML fault.
497         PMBusExpectations expectations;
498         setPMBusExpectations(mockPMBus, expectations);
499         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
500             .Times(1)
501             .WillOnce(Return("214000"));
502         psu2.analyze();
503         // STATUS_WORD with CML fault bit on.
504         expectations.statusWordValue = (status_word::CML_FAULT);
505         // Turn on STATUS_CML fault bit(s)
506         expectations.statusCMLValue = 0xFF;
507         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
508         {
509             setPMBusExpectations(mockPMBus, expectations);
510             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
511                 .Times(1)
512                 .WillOnce(Return("215000"));
513             psu2.analyze();
514             EXPECT_EQ(psu2.isPresent(), true);
515             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
516             EXPECT_EQ(psu2.hasCommFault(), x >= DEGLITCH_LIMIT);
517             EXPECT_EQ(psu2.hasInputFault(), false);
518             EXPECT_EQ(psu2.hasMFRFault(), false);
519             EXPECT_EQ(psu2.hasVINUVFault(), false);
520             EXPECT_EQ(psu2.hasVoutOVFault(), false);
521             EXPECT_EQ(psu2.hasIoutOCFault(), false);
522             EXPECT_EQ(psu2.hasVoutUVFault(), false);
523             EXPECT_EQ(psu2.hasFanFault(), false);
524             EXPECT_EQ(psu2.hasTempFault(), false);
525             EXPECT_EQ(psu2.hasPgoodFault(), false);
526             EXPECT_EQ(psu2.hasPSKillFault(), false);
527             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
528             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
529         }
530     }
531 
532     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
533     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
534         .Times(1)
535         .WillOnce(Return(1));
536     psu2.clearFaults();
537 
538     // VOUT_OV_FAULT fault
539     {
540         // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
541         PMBusExpectations expectations;
542         setPMBusExpectations(mockPMBus, expectations);
543         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
544             .Times(1)
545             .WillOnce(Return("216000"));
546         psu2.analyze();
547         // STATUS_WORD with VOUT/VOUT_OV fault.
548         expectations.statusWordValue =
549             ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
550         // Turn on STATUS_VOUT fault bit(s)
551         expectations.statusVOUTValue = 0xA0;
552         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
553         {
554             // STATUS_TEMPERATURE don't care (default)
555             setPMBusExpectations(mockPMBus, expectations);
556             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
557                 .Times(1)
558                 .WillOnce(Return("217000"));
559             psu2.analyze();
560             EXPECT_EQ(psu2.isPresent(), true);
561             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
562             EXPECT_EQ(psu2.hasInputFault(), false);
563             EXPECT_EQ(psu2.hasMFRFault(), false);
564             EXPECT_EQ(psu2.hasVINUVFault(), false);
565             EXPECT_EQ(psu2.hasCommFault(), false);
566             EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
567             EXPECT_EQ(psu2.hasVoutUVFault(), false);
568             EXPECT_EQ(psu2.hasIoutOCFault(), false);
569             EXPECT_EQ(psu2.hasFanFault(), false);
570             EXPECT_EQ(psu2.hasTempFault(), false);
571             EXPECT_EQ(psu2.hasPgoodFault(), false);
572             EXPECT_EQ(psu2.hasPSKillFault(), false);
573             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
574             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
575         }
576     }
577 
578     // IOUT_OC_FAULT fault
579     {
580         // First STATUS_WORD with no bits set, then with IOUT_OC fault.
581         PMBusExpectations expectations;
582         setPMBusExpectations(mockPMBus, expectations);
583         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
584             .Times(1)
585             .WillOnce(Return("218000"));
586         psu2.analyze();
587         // STATUS_WORD with IOUT_OC fault.
588         expectations.statusWordValue = status_word::IOUT_OC_FAULT;
589         // Turn on STATUS_IOUT fault bit(s)
590         expectations.statusIOUTValue = 0x88;
591         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
592         {
593             setPMBusExpectations(mockPMBus, expectations);
594             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
595                 .Times(1)
596                 .WillOnce(Return("219000"));
597             psu2.analyze();
598             EXPECT_EQ(psu2.isPresent(), true);
599             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
600             EXPECT_EQ(psu2.hasInputFault(), false);
601             EXPECT_EQ(psu2.hasMFRFault(), false);
602             EXPECT_EQ(psu2.hasVINUVFault(), false);
603             EXPECT_EQ(psu2.hasCommFault(), false);
604             EXPECT_EQ(psu2.hasVoutOVFault(), false);
605             EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
606             EXPECT_EQ(psu2.hasVoutUVFault(), false);
607             EXPECT_EQ(psu2.hasFanFault(), false);
608             EXPECT_EQ(psu2.hasTempFault(), false);
609             EXPECT_EQ(psu2.hasPgoodFault(), false);
610             EXPECT_EQ(psu2.hasPSKillFault(), false);
611             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
612             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
613         }
614     }
615 
616     // VOUT_UV_FAULT
617     {
618         // First STATUS_WORD with no bits set, then with VOUT fault.
619         PMBusExpectations expectations;
620         setPMBusExpectations(mockPMBus, expectations);
621         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
622             .Times(1)
623             .WillOnce(Return("220000"));
624         psu2.analyze();
625         // Change STATUS_WORD to indicate VOUT fault.
626         expectations.statusWordValue = (status_word::VOUT_FAULT);
627         // Turn on STATUS_VOUT fault bit(s)
628         expectations.statusVOUTValue = 0x30;
629         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
630         {
631             setPMBusExpectations(mockPMBus, expectations);
632             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
633                 .Times(1)
634                 .WillOnce(Return("221000"));
635             psu2.analyze();
636             EXPECT_EQ(psu2.isPresent(), true);
637             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
638             EXPECT_EQ(psu2.hasInputFault(), false);
639             EXPECT_EQ(psu2.hasMFRFault(), false);
640             EXPECT_EQ(psu2.hasVINUVFault(), false);
641             EXPECT_EQ(psu2.hasCommFault(), false);
642             EXPECT_EQ(psu2.hasVoutOVFault(), false);
643             EXPECT_EQ(psu2.hasIoutOCFault(), false);
644             EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
645             EXPECT_EQ(psu2.hasFanFault(), false);
646             EXPECT_EQ(psu2.hasTempFault(), false);
647             EXPECT_EQ(psu2.hasPgoodFault(), false);
648             EXPECT_EQ(psu2.hasPSKillFault(), false);
649             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
650             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
651         }
652     }
653 
654     // Fan fault
655     {
656         // First STATUS_WORD with no bits set, then with fan fault.
657         PMBusExpectations expectations;
658         setPMBusExpectations(mockPMBus, expectations);
659         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
660             .Times(1)
661             .WillOnce(Return("222000"));
662         psu2.analyze();
663         expectations.statusWordValue = (status_word::FAN_FAULT);
664         // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
665         expectations.statusFans12Value = 0xA0;
666 
667         for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
668         {
669             setPMBusExpectations(mockPMBus, expectations);
670             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
671                 .Times(1)
672                 .WillOnce(Return("223000"));
673             psu2.analyze();
674             EXPECT_EQ(psu2.isPresent(), true);
675             EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
676             EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT);
677             EXPECT_EQ(psu2.hasInputFault(), false);
678             EXPECT_EQ(psu2.hasMFRFault(), false);
679             EXPECT_EQ(psu2.hasVINUVFault(), false);
680             EXPECT_EQ(psu2.hasCommFault(), false);
681             EXPECT_EQ(psu2.hasVoutOVFault(), false);
682             EXPECT_EQ(psu2.hasIoutOCFault(), false);
683             EXPECT_EQ(psu2.hasVoutUVFault(), false);
684             EXPECT_EQ(psu2.hasTempFault(), false);
685             EXPECT_EQ(psu2.hasPgoodFault(), false);
686             EXPECT_EQ(psu2.hasPSKillFault(), false);
687             EXPECT_EQ(psu2.hasPS12VcsFault(), false);
688             EXPECT_EQ(psu2.hasPSCS12VFault(), false);
689         }
690     }
691 
692     // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
693     {
694         // First STATUS_WORD with no bits set.
695         PMBusExpectations expectations;
696         setPMBusExpectations(mockPMBus, expectations);
697         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
698             .Times(1)
699             .WillOnce(Return("123000"));
700         psu2.analyze();
701         EXPECT_EQ(psu2.isFaulted(), false);
702         // POWER_GOOD# inactive, and OFF bit on.
703         expectations.statusWordValue =
704             ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
705         for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++)
706         {
707             // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
708             // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
709             setPMBusExpectations(mockPMBus, expectations);
710             EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
711                 .Times(1)
712                 .WillOnce(Return("124000"));
713             psu2.analyze();
714             EXPECT_EQ(psu2.isPresent(), true);
715             EXPECT_EQ(psu2.isFaulted(), x >= PGOOD_DEGLITCH_LIMIT);
716             EXPECT_EQ(psu2.hasInputFault(), false);
717             EXPECT_EQ(psu2.hasMFRFault(), false);
718             EXPECT_EQ(psu2.hasVINUVFault(), false);
719             EXPECT_EQ(psu2.hasCommFault(), false);
720             EXPECT_EQ(psu2.hasVoutOVFault(), false);
721             EXPECT_EQ(psu2.hasVoutUVFault(), false);
722             EXPECT_EQ(psu2.hasIoutOCFault(), false);
723             EXPECT_EQ(psu2.hasFanFault(), false);
724             EXPECT_EQ(psu2.hasTempFault(), false);
725             EXPECT_EQ(psu2.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT);
726         }
727     }
728 
729     // TODO: ReadFailure
730 }
731 
732 TEST_F(PowerSupplyTests, OnOffConfig)
733 {
734     auto bus = sdbusplus::bus::new_default();
735     uint8_t data = 0x15;
736 
737     // Test where PSU is NOT present
738     try
739     {
740         // Assume GPIO presence, not inventory presence?
741         EXPECT_CALL(mockedUtil, setAvailable(_, _, _)).Times(0);
742         PowerSupply psu{bus,         PSUInventoryPath, 4,        0x69,
743                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
744 
745         MockedGPIOInterface* mockPresenceGPIO =
746             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
747         ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
748         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
749         // Constructor should set initial presence, default read returns 0.
750         // If it is not present, I should not be trying to write to it.
751         EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
752         psu.onOffConfig(data);
753     }
754     catch (...)
755     {}
756 
757     // Test where PSU is present
758     try
759     {
760         // Assume GPIO presence, not inventory presence?
761         EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
762         PowerSupply psu{bus,         PSUInventoryPath, 5,        0x6a,
763                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
764         MockedGPIOInterface* mockPresenceGPIO =
765             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
766         // There will potentially be multiple calls, we want it to continue
767         // returning 1 for the GPIO read to keep the power supply present.
768         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
769         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
770         setMissingToPresentExpects(mockPMBus, mockedUtil);
771         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
772         // for INPUT_HISTORY will check max_power_out to see if it is
773         // old/unsupported power supply. Indicate good value, supported.
774         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
775             .WillRepeatedly(Return("2000"));
776         // If I am calling analyze(), I should probably give it good data.
777         // STATUS_WORD 0x0000 is powered on, no faults.
778         PMBusExpectations expectations;
779         setPMBusExpectations(mockPMBus, expectations);
780         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
781             .Times(1)
782             .WillOnce(Return("205000"));
783         psu.analyze();
784         // I definitely should be writting ON_OFF_CONFIG if I call the function
785         EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
786                                            Type::HwmonDeviceDebug))
787             .Times(1);
788         psu.onOffConfig(data);
789     }
790     catch (...)
791     {}
792 }
793 
794 TEST_F(PowerSupplyTests, ClearFaults)
795 {
796     auto bus = sdbusplus::bus::new_default();
797     PowerSupply psu{bus,         PSUInventoryPath, 13,       0x68,
798                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
799     MockedGPIOInterface* mockPresenceGPIO =
800         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
801     // Always return 1 to indicate present.
802     // Each analyze() call will trigger a read of the presence GPIO.
803     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
804     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
805     setMissingToPresentExpects(mockPMBus, mockedUtil);
806     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
807     // for INPUT_HISTORY will check max_power_out to see if it is
808     // old/unsupported power supply. Indicate good value, supported.
809     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
810         .WillRepeatedly(Return("2000"));
811     // STATUS_WORD 0x0000 is powered on, no faults.
812     PMBusExpectations expectations;
813     setPMBusExpectations(mockPMBus, expectations);
814     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
815         .Times(1)
816         .WillOnce(Return("207000"));
817     psu.analyze();
818     EXPECT_EQ(psu.isPresent(), true);
819     EXPECT_EQ(psu.isFaulted(), false);
820     EXPECT_EQ(psu.hasInputFault(), false);
821     EXPECT_EQ(psu.hasMFRFault(), false);
822     EXPECT_EQ(psu.hasVINUVFault(), false);
823     EXPECT_EQ(psu.hasCommFault(), false);
824     EXPECT_EQ(psu.hasVoutOVFault(), false);
825     EXPECT_EQ(psu.hasIoutOCFault(), false);
826     EXPECT_EQ(psu.hasVoutUVFault(), false);
827     EXPECT_EQ(psu.hasFanFault(), false);
828     EXPECT_EQ(psu.hasTempFault(), false);
829     EXPECT_EQ(psu.hasPgoodFault(), false);
830     EXPECT_EQ(psu.hasPSKillFault(), false);
831     EXPECT_EQ(psu.hasPS12VcsFault(), false);
832     EXPECT_EQ(psu.hasPSCS12VFault(), false);
833 
834     // STATUS_WORD with fault bits galore!
835     expectations.statusWordValue = 0xFFFF;
836     // STATUS_INPUT with fault bits on.
837     expectations.statusInputValue = 0xFF;
838     // STATUS_MFR_SPEFIC with bits on.
839     expectations.statusMFRValue = 0xFF;
840     // STATUS_CML with bits on.
841     expectations.statusCMLValue = 0xFF;
842     // STATUS_VOUT with bits on.
843     expectations.statusVOUTValue = 0xFF;
844     // STATUS_IOUT with bits on.
845     expectations.statusIOUTValue = 0xFF;
846     // STATUS_FANS_1_2 with bits on.
847     expectations.statusFans12Value = 0xFF;
848     // STATUS_TEMPERATURE with bits on.
849     expectations.statusTempValue = 0xFF;
850 
851     for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++)
852     {
853         setPMBusExpectations(mockPMBus, expectations);
854         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
855             .Times(1)
856             .WillOnce(Return("0"));
857         if (x == DEGLITCH_LIMIT)
858         {
859             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
860         }
861         psu.analyze();
862         EXPECT_EQ(psu.isPresent(), true);
863         // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
864         // Rely on HasVoutUVFault() to verify this sets and clears.
865         EXPECT_EQ(psu.hasVoutUVFault(), false);
866         // pgoodFault at PGOOD_DEGLITCH_LIMIT, all other faults are deglitched
867         // up to DEGLITCH_LIMIT
868         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
869         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
870         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
871         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
872         EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT);
873         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
874         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
875         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
876         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
877         EXPECT_EQ(psu.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT);
878         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
879         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
880         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
881     }
882 
883     EXPECT_CALL(mockPMBus, read(READ_VIN, _, _))
884         .Times(1)
885         .WillOnce(Return(207000));
886     // Clearing VIN_UV fault via in1_lcrit_alarm
887     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
888         .Times(1)
889         .WillOnce(Return(1));
890     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
891     psu.clearFaults();
892     EXPECT_EQ(psu.isPresent(), true);
893     EXPECT_EQ(psu.isFaulted(), false);
894     EXPECT_EQ(psu.hasInputFault(), false);
895     EXPECT_EQ(psu.hasMFRFault(), false);
896     EXPECT_EQ(psu.hasVINUVFault(), false);
897     EXPECT_EQ(psu.hasCommFault(), false);
898     EXPECT_EQ(psu.hasVoutOVFault(), false);
899     EXPECT_EQ(psu.hasIoutOCFault(), false);
900     EXPECT_EQ(psu.hasVoutUVFault(), false);
901     EXPECT_EQ(psu.hasFanFault(), false);
902     EXPECT_EQ(psu.hasTempFault(), false);
903     EXPECT_EQ(psu.hasPgoodFault(), false);
904     EXPECT_EQ(psu.hasPSKillFault(), false);
905     EXPECT_EQ(psu.hasPS12VcsFault(), false);
906     EXPECT_EQ(psu.hasPSCS12VFault(), false);
907 
908     // Faults clear on READ_VIN 0 -> !0
909     // STATUS_WORD with fault bits galore!
910     expectations.statusWordValue = 0xFFFF;
911     // STATUS_INPUT with fault bits on.
912     expectations.statusInputValue = 0xFF;
913     // STATUS_MFR_SPEFIC with bits on.
914     expectations.statusMFRValue = 0xFF;
915     // STATUS_CML with bits on.
916     expectations.statusCMLValue = 0xFF;
917     // STATUS_VOUT with bits on.
918     expectations.statusVOUTValue = 0xFF;
919     // STATUS_IOUT with bits on.
920     expectations.statusIOUTValue = 0xFF;
921     // STATUS_FANS_1_2 with bits on.
922     expectations.statusFans12Value = 0xFF;
923     // STATUS_TEMPERATURE with bits on.
924     expectations.statusTempValue = 0xFF;
925 
926     // All faults deglitched now. Check for false before limit above.
927     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
928     {
929         setPMBusExpectations(mockPMBus, expectations);
930         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
931             .Times(1)
932             .WillOnce(Return("0"));
933         if (x == DEGLITCH_LIMIT)
934         {
935             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
936         }
937         psu.analyze();
938     }
939 
940     EXPECT_EQ(psu.isPresent(), true);
941     EXPECT_EQ(psu.isFaulted(), true);
942     EXPECT_EQ(psu.hasInputFault(), true);
943     EXPECT_EQ(psu.hasMFRFault(), true);
944     EXPECT_EQ(psu.hasVINUVFault(), true);
945     // True due to CML fault bits on
946     EXPECT_EQ(psu.hasCommFault(), true);
947     EXPECT_EQ(psu.hasVoutOVFault(), true);
948     EXPECT_EQ(psu.hasIoutOCFault(), true);
949     // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
950     // Rely on HasVoutUVFault() to verify this sets and clears.
951     EXPECT_EQ(psu.hasVoutUVFault(), false);
952     EXPECT_EQ(psu.hasFanFault(), true);
953     EXPECT_EQ(psu.hasTempFault(), true);
954     // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT
955     EXPECT_EQ(psu.hasPgoodFault(), false);
956     EXPECT_EQ(psu.hasPSKillFault(), true);
957     EXPECT_EQ(psu.hasPS12VcsFault(), true);
958     EXPECT_EQ(psu.hasPSCS12VFault(), true);
959     // STATUS_WORD with INPUT/VIN_UV fault bits off.
960     expectations.statusWordValue = 0xDFF7;
961     // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
962     // Insufficient Input Voltage bits off.
963     expectations.statusInputValue = 0xC7;
964     setPMBusExpectations(mockPMBus, expectations);
965     // READ_VIN back in range.
966     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
967         .Times(1)
968         .WillOnce(Return("206000"));
969     // VIN_UV cleared via in1_lcrit_alarm when voltage back in range.
970     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
971         .Times(1)
972         .WillOnce(Return(1));
973     psu.analyze();
974     // We only cleared the VIN_UV and OFF faults.
975     EXPECT_EQ(psu.isPresent(), true);
976     EXPECT_EQ(psu.isFaulted(), true);
977     EXPECT_EQ(psu.hasInputFault(), false);
978     EXPECT_EQ(psu.hasMFRFault(), true);
979     EXPECT_EQ(psu.hasVINUVFault(), false);
980     EXPECT_EQ(psu.hasCommFault(), true);
981     EXPECT_EQ(psu.hasVoutOVFault(), true);
982     EXPECT_EQ(psu.hasIoutOCFault(), true);
983     EXPECT_EQ(psu.hasVoutUVFault(), false);
984     EXPECT_EQ(psu.hasFanFault(), true);
985     EXPECT_EQ(psu.hasTempFault(), true);
986     // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT
987     EXPECT_EQ(psu.hasPgoodFault(), false);
988     EXPECT_EQ(psu.hasPSKillFault(), true);
989     EXPECT_EQ(psu.hasPS12VcsFault(), true);
990     EXPECT_EQ(psu.hasPSCS12VFault(), true);
991 
992     // All faults cleared
993     expectations = {0};
994     setPMBusExpectations(mockPMBus, expectations);
995     // READ_VIN back in range.
996     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
997         .Times(1)
998         .WillOnce(Return("206000"));
999     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1000     psu.analyze();
1001     EXPECT_EQ(psu.isPresent(), true);
1002     EXPECT_EQ(psu.isFaulted(), false);
1003     EXPECT_EQ(psu.hasInputFault(), false);
1004     EXPECT_EQ(psu.hasMFRFault(), false);
1005     EXPECT_EQ(psu.hasVINUVFault(), false);
1006     EXPECT_EQ(psu.hasCommFault(), false);
1007     EXPECT_EQ(psu.hasVoutOVFault(), false);
1008     EXPECT_EQ(psu.hasIoutOCFault(), false);
1009     EXPECT_EQ(psu.hasVoutUVFault(), false);
1010     EXPECT_EQ(psu.hasFanFault(), false);
1011     EXPECT_EQ(psu.hasTempFault(), false);
1012     EXPECT_EQ(psu.hasPgoodFault(), false);
1013     EXPECT_EQ(psu.hasPSKillFault(), false);
1014     EXPECT_EQ(psu.hasPS12VcsFault(), false);
1015     EXPECT_EQ(psu.hasPSCS12VFault(), false);
1016 
1017     // TODO: Faults clear on missing/present?
1018 }
1019 
1020 TEST_F(PowerSupplyTests, UpdateInventory)
1021 {
1022     auto bus = sdbusplus::bus::new_default();
1023 
1024     try
1025     {
1026         PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
1027                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1028         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1029         // If it is not present, I should not be trying to read a string
1030         EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
1031         psu.updateInventory();
1032     }
1033     catch (...)
1034     {
1035         ADD_FAILURE() << "Should not have caught exception.";
1036     }
1037 
1038     try
1039     {
1040         PowerSupply psu{bus,         PSUInventoryPath, 13,       0x69,
1041                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1042         MockedGPIOInterface* mockPresenceGPIO =
1043             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1044         // GPIO read return 1 to indicate present.
1045         EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
1046         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1047         setMissingToPresentExpects(mockPMBus, mockedUtil);
1048         // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1049         // for INPUT_HISTORY will check max_power_out to see if it is
1050         // old/unsupported power supply. Indicate good value, supported.
1051         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1052             .WillRepeatedly(Return("2000"));
1053         // STATUS_WORD 0x0000 is powered on, no faults.
1054         PMBusExpectations expectations;
1055         setPMBusExpectations(mockPMBus, expectations);
1056         // Call to analyze will read voltage, trigger clear faults for 0 to
1057         // within range.
1058         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1059             .Times(1)
1060             .WillOnce(Return("123456"));
1061         psu.analyze();
1062         EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
1063         psu.updateInventory();
1064 
1065 #if IBM_VPD
1066         EXPECT_CALL(mockPMBus, readString(_, _))
1067             .WillOnce(Return("CCIN"))
1068             .WillOnce(Return("PN3456"))
1069             .WillOnce(Return("FN3456"))
1070             .WillOnce(Return("HEADER"))
1071             .WillOnce(Return("SN3456"))
1072             .WillOnce(Return("FW3456"));
1073 #endif
1074         psu.updateInventory();
1075         // TODO: D-Bus mocking to verify values stored on D-Bus (???)
1076     }
1077     catch (...)
1078     {
1079         ADD_FAILURE() << "Should not have caught exception.";
1080     }
1081 }
1082 
1083 TEST_F(PowerSupplyTests, IsPresent)
1084 {
1085     auto bus = sdbusplus::bus::new_default();
1086 
1087     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
1088                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1089     MockedGPIOInterface* mockPresenceGPIO =
1090         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1091     EXPECT_EQ(psu.isPresent(), false);
1092 
1093     // Change GPIO read to return 1 to indicate present.
1094     EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
1095     // Call to analyze() will update to present, that will trigger updating
1096     // to the correct/latest HWMON directory, in case it changes.
1097     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1098     setMissingToPresentExpects(mockPMBus, mockedUtil);
1099     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1100     // for INPUT_HISTORY will check max_power_out to see if it is
1101     // old/unsupported power supply. Indicate good value, supported.
1102     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1103         .WillRepeatedly(Return("2000"));
1104     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1105     // Default expectations will be on, no faults.
1106     PMBusExpectations expectations;
1107     setPMBusExpectations(mockPMBus, expectations);
1108     // Give it an input voltage in the 100-volt range.
1109     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1110         .Times(1)
1111         .WillOnce(Return("123456"));
1112     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1113     psu.analyze();
1114     EXPECT_EQ(psu.isPresent(), true);
1115 }
1116 
1117 TEST_F(PowerSupplyTests, IsFaulted)
1118 {
1119     auto bus = sdbusplus::bus::new_default();
1120 
1121     PowerSupply psu{bus,         PSUInventoryPath, 11,       0x6f,
1122                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1123     MockedGPIOInterface* mockPresenceGPIO =
1124         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1125     // Always return 1 to indicate present.
1126     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1127     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1128     setMissingToPresentExpects(mockPMBus, mockedUtil);
1129     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1130     // for INPUT_HISTORY will check max_power_out to see if it is
1131     // old/unsupported power supply. Indicate good value, supported.
1132     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1133         .WillRepeatedly(Return("2000"));
1134     // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1135     // Default expectations will be on, no faults.
1136     PMBusExpectations expectations;
1137     setPMBusExpectations(mockPMBus, expectations);
1138     // Give it an input voltage in the 100-volt range.
1139     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1140         .Times(1)
1141         .WillOnce(Return("124680"));
1142     psu.analyze();
1143     EXPECT_EQ(psu.isFaulted(), false);
1144     // STATUS_WORD with fault bits on.
1145     expectations.statusWordValue = 0xFFFF;
1146     // STATUS_INPUT with fault bits on.
1147     expectations.statusInputValue = 0xFF;
1148     // STATUS_MFR_SPECIFIC with faults bits on.
1149     expectations.statusMFRValue = 0xFF;
1150     // STATUS_CML with faults bits on.
1151     expectations.statusCMLValue = 0xFF;
1152     // STATUS_VOUT with fault bits on.
1153     expectations.statusVOUTValue = 0xFF;
1154     // STATUS_IOUT with fault bits on.
1155     expectations.statusIOUTValue = 0xFF;
1156     // STATUS_FANS_1_2 with bits on.
1157     expectations.statusFans12Value = 0xFF;
1158     // STATUS_TEMPERATURE with fault bits on.
1159     expectations.statusTempValue = 0xFF;
1160     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1161     {
1162         setPMBusExpectations(mockPMBus, expectations);
1163         // Also get another read of READ_VIN, faulted, so not in 100-volt range
1164         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1165             .Times(1)
1166             .WillOnce(Return("19000"));
1167         if (x == DEGLITCH_LIMIT)
1168         {
1169             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1170         }
1171         psu.analyze();
1172         EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
1173     }
1174 }
1175 
1176 TEST_F(PowerSupplyTests, HasInputFault)
1177 {
1178     auto bus = sdbusplus::bus::new_default();
1179 
1180     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
1181                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1182     MockedGPIOInterface* mockPresenceGPIO =
1183         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1184     // Always return 1 to indicate present.
1185     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1186     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1187     setMissingToPresentExpects(mockPMBus, mockedUtil);
1188     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1189     // for INPUT_HISTORY will check max_power_out to see if it is
1190     // old/unsupported power supply. Indicate good value, supported.
1191     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1192         .WillRepeatedly(Return("2000"));
1193     // STATUS_WORD 0x0000 is powered on, no faults.
1194     PMBusExpectations expectations;
1195     setPMBusExpectations(mockPMBus, expectations);
1196     // Analyze call will also need good READ_VIN value to check.
1197     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1198         .Times(1)
1199         .WillOnce(Return("201100"));
1200     psu.analyze();
1201     EXPECT_EQ(psu.hasInputFault(), false);
1202     // STATUS_WORD with input fault/warn on.
1203     expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
1204     // STATUS_INPUT with an input fault bit on.
1205     expectations.statusInputValue = 0x80;
1206     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1207     {
1208         setPMBusExpectations(mockPMBus, expectations);
1209         // Analyze call will also need good READ_VIN value to check.
1210         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1211             .Times(1)
1212             .WillOnce(Return("201200"));
1213         if (x == DEGLITCH_LIMIT)
1214         {
1215             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1216         }
1217         psu.analyze();
1218         EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
1219     }
1220     // STATUS_WORD with no bits on.
1221     expectations.statusWordValue = 0;
1222     setPMBusExpectations(mockPMBus, expectations);
1223     // Analyze call will also need good READ_VIN value to check.
1224     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1225         .Times(1)
1226         .WillOnce(Return("201300"));
1227     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1228     psu.analyze();
1229     EXPECT_EQ(psu.hasInputFault(), false);
1230 }
1231 
1232 TEST_F(PowerSupplyTests, HasMFRFault)
1233 {
1234     auto bus = sdbusplus::bus::new_default();
1235 
1236     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
1237                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1238     MockedGPIOInterface* mockPresenceGPIO =
1239         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1240     // Always return 1 to indicate present.
1241     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1242     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1243     setMissingToPresentExpects(mockPMBus, mockedUtil);
1244     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1245     // for INPUT_HISTORY will check max_power_out to see if it is
1246     // old/unsupported power supply. Indicate good value, supported.
1247     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1248         .WillRepeatedly(Return("2000"));
1249     // First return STATUS_WORD with no bits on.
1250     // STATUS_WORD 0x0000 is powered on, no faults.
1251     PMBusExpectations expectations;
1252     setPMBusExpectations(mockPMBus, expectations);
1253     // Analyze call will also need good READ_VIN value to check.
1254     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1255         .Times(1)
1256         .WillOnce(Return("202100"));
1257     psu.analyze();
1258     EXPECT_EQ(psu.hasMFRFault(), false);
1259     // Next return STATUS_WORD with MFR fault bit on.
1260     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1261     // STATUS_MFR_SPEFIC with bit(s) on.
1262     expectations.statusMFRValue = 0xFF;
1263     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1264     {
1265         setPMBusExpectations(mockPMBus, expectations);
1266         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1267             .Times(1)
1268             .WillOnce(Return("202200"));
1269         psu.analyze();
1270         EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1271     }
1272     // Back to no bits on in STATUS_WORD
1273     expectations.statusWordValue = 0;
1274     setPMBusExpectations(mockPMBus, expectations);
1275     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1276         .Times(1)
1277         .WillOnce(Return("202300"));
1278     psu.analyze();
1279     EXPECT_EQ(psu.hasMFRFault(), false);
1280 }
1281 
1282 TEST_F(PowerSupplyTests, HasVINUVFault)
1283 {
1284     auto bus = sdbusplus::bus::new_default();
1285 
1286     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
1287                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1288     MockedGPIOInterface* mockPresenceGPIO =
1289         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1290     // Always return 1 to indicate present.
1291     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1292     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1293     setMissingToPresentExpects(mockPMBus, mockedUtil);
1294     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1295     // for INPUT_HISTORY will check max_power_out to see if it is
1296     // old/unsupported power supply. Indicate good value, supported.
1297     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1298         .WillRepeatedly(Return("2000"));
1299 
1300     // Presence change from missing to present will trigger in1_input read in
1301     // an attempt to get CLEAR_FAULTS called. Return value ignored.
1302     // Zero to non-zero voltage, for missing/present change, triggers clear
1303     // faults call again. Return value ignored.
1304     // Fault (low voltage) to not faulted (voltage in range) triggers clear
1305     // faults call a third time.
1306 
1307     // STATUS_WORD 0x0000 is powered on, no faults.
1308     PMBusExpectations expectations;
1309     setPMBusExpectations(mockPMBus, expectations);
1310     // Analyze call will also need good READ_VIN value to check.
1311     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1312         .Times(1)
1313         .WillOnce(Return("201100"));
1314     psu.analyze();
1315     EXPECT_EQ(psu.hasVINUVFault(), false);
1316     // Turn fault on.
1317     expectations.statusWordValue = (status_word::VIN_UV_FAULT);
1318     // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
1319     // Figure 16, and assume bits on in STATUS_INPUT.
1320     expectations.statusInputValue = 0x18;
1321     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1322     {
1323         setPMBusExpectations(mockPMBus, expectations);
1324         // If there is a VIN_UV fault, fake reading voltage of less than 20V
1325         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1326             .Times(1)
1327             .WillOnce(Return("19876"));
1328         if (x == DEGLITCH_LIMIT)
1329         {
1330             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1331         }
1332         psu.analyze();
1333         EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1334     }
1335     // Back to no fault bits on in STATUS_WORD
1336     expectations.statusWordValue = 0;
1337     setPMBusExpectations(mockPMBus, expectations);
1338     // Updates now result in clearing faults if read voltage goes from below the
1339     // minimum, to within a valid range.
1340     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1341         .Times(1)
1342         .WillOnce(Return("201300"));
1343     // Went from below minimum to within range, expect clearVinUVFault().
1344     EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
1345         .Times(1)
1346         .WillOnce(Return(1));
1347     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1348     psu.analyze();
1349     EXPECT_EQ(psu.hasVINUVFault(), false);
1350 }
1351 
1352 TEST_F(PowerSupplyTests, HasVoutOVFault)
1353 {
1354     auto bus = sdbusplus::bus::new_default();
1355 
1356     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x69,
1357                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1358     MockedGPIOInterface* mockPresenceGPIO =
1359         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1360     // Always return 1 to indicate present.
1361     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1362     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1363     setMissingToPresentExpects(mockPMBus, mockedUtil);
1364     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1365     // for INPUT_HISTORY will check max_power_out to see if it is
1366     // old/unsupported power supply. Indicate good value, supported.
1367     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1368         .WillRepeatedly(Return("2000"));
1369     // STATUS_WORD 0x0000 is powered on, no faults.
1370     PMBusExpectations expectations;
1371     setPMBusExpectations(mockPMBus, expectations);
1372     // Call to analyze will trigger read of "in1_input" to check voltage.
1373     // Initial value would be 0, so this read updates it to non-zero.
1374     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1375         .Times(1)
1376         .WillOnce(Return("202100"));
1377     psu.analyze();
1378     EXPECT_EQ(psu.hasVoutOVFault(), false);
1379     // Turn fault on.
1380     expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
1381     // STATUS_VOUT fault bit(s)
1382     expectations.statusVOUTValue = 0x80;
1383     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1384     {
1385         setPMBusExpectations(mockPMBus, expectations);
1386         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1387             .Times(1)
1388             .WillOnce(Return("202200"));
1389         psu.analyze();
1390         EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1391     }
1392     // Back to no fault bits on in STATUS_WORD
1393     expectations.statusWordValue = 0;
1394     setPMBusExpectations(mockPMBus, expectations);
1395     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1396         .Times(1)
1397         .WillOnce(Return("202300"));
1398     psu.analyze();
1399     EXPECT_EQ(psu.hasVoutOVFault(), false);
1400 }
1401 
1402 TEST_F(PowerSupplyTests, HasIoutOCFault)
1403 {
1404     auto bus = sdbusplus::bus::new_default();
1405 
1406     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6d,
1407                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1408     MockedGPIOInterface* mockPresenceGPIO =
1409         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1410     // Always return 1 to indicate present.
1411     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1412     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1413     setMissingToPresentExpects(mockPMBus, mockedUtil);
1414     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1415     // for INPUT_HISTORY will check max_power_out to see if it is
1416     // old/unsupported power supply. Indicate good value, supported.
1417     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1418         .WillRepeatedly(Return("2000"));
1419     // STATUS_WORD 0x0000 is powered on, no faults.
1420     PMBusExpectations expectations;
1421     setPMBusExpectations(mockPMBus, expectations);
1422     // Call to analyze will trigger read of "in1_input" to check voltage.
1423     // Initial value would be 0, so this read updates it to non-zero.
1424     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1425         .Times(1)
1426         .WillOnce(Return("203100"));
1427     psu.analyze();
1428     EXPECT_EQ(psu.hasIoutOCFault(), false);
1429     // Turn fault on.
1430     expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1431     // STATUS_IOUT fault bit(s)
1432     expectations.statusIOUTValue = 0x88;
1433     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1434     {
1435         setPMBusExpectations(mockPMBus, expectations);
1436         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1437             .Times(1)
1438             .WillOnce(Return("203200"));
1439         if (x == DEGLITCH_LIMIT)
1440         {
1441             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1442         }
1443         psu.analyze();
1444         EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1445     }
1446     // Back to no fault bits on in STATUS_WORD
1447     expectations.statusWordValue = 0;
1448     setPMBusExpectations(mockPMBus, expectations);
1449     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1450         .Times(1)
1451         .WillOnce(Return("203300"));
1452     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1453     psu.analyze();
1454     EXPECT_EQ(psu.hasIoutOCFault(), false);
1455 }
1456 
1457 TEST_F(PowerSupplyTests, HasVoutUVFault)
1458 {
1459     auto bus = sdbusplus::bus::new_default();
1460 
1461     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6a,
1462                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1463     MockedGPIOInterface* mockPresenceGPIO =
1464         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1465     // Always return 1 to indicate present.
1466     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1467     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1468     setMissingToPresentExpects(mockPMBus, mockedUtil);
1469     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1470     // for INPUT_HISTORY will check max_power_out to see if it is
1471     // old/unsupported power supply. Indicate good value, supported.
1472     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1473         .WillRepeatedly(Return("2000"));
1474     // STATUS_WORD 0x0000 is powered on, no faults.
1475     PMBusExpectations expectations;
1476     setPMBusExpectations(mockPMBus, expectations);
1477     // Call to analyze will trigger read of "in1_input" to check voltage.
1478     // Initial value would be 0, so this read updates it to non-zero.
1479     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1480         .Times(1)
1481         .WillOnce(Return("204100"));
1482     psu.analyze();
1483     EXPECT_EQ(psu.hasVoutUVFault(), false);
1484     // Turn fault on.
1485     expectations.statusWordValue = (status_word::VOUT_FAULT);
1486     // STATUS_VOUT fault bit(s)
1487     expectations.statusVOUTValue = 0x30;
1488     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1489     {
1490         setPMBusExpectations(mockPMBus, expectations);
1491         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1492             .Times(1)
1493             .WillOnce(Return("204200"));
1494         psu.analyze();
1495         EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1496     }
1497     // Back to no fault bits on in STATUS_WORD
1498     expectations.statusWordValue = 0;
1499     setPMBusExpectations(mockPMBus, expectations);
1500     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1501         .Times(1)
1502         .WillOnce(Return("204300"));
1503     psu.analyze();
1504     EXPECT_EQ(psu.hasVoutUVFault(), false);
1505 }
1506 
1507 TEST_F(PowerSupplyTests, HasFanFault)
1508 {
1509     auto bus = sdbusplus::bus::new_default();
1510 
1511     EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
1512     EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
1513 
1514     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6d,
1515                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1516     MockedGPIOInterface* mockPresenceGPIO =
1517         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1518     // Always return 1 to indicate present.
1519     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1520     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1521     setMissingToPresentExpects(mockPMBus, mockedUtil);
1522     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1523     // for INPUT_HISTORY will check max_power_out to see if it is
1524     // old/unsupported power supply. Indicate good value, supported.
1525     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1526         .WillRepeatedly(Return("2000"));
1527     // STATUS_WORD 0x0000 is powered on, no faults.
1528     PMBusExpectations expectations;
1529     setPMBusExpectations(mockPMBus, expectations);
1530     // Call to analyze will trigger read of "in1_input" to check voltage.
1531     // Initial value would be 0, so this read updates it to non-zero.
1532     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1533         .Times(1)
1534         .WillOnce(Return("205100"));
1535     psu.analyze();
1536     EXPECT_EQ(psu.hasFanFault(), false);
1537     // Turn fault on.
1538     expectations.statusWordValue = (status_word::FAN_FAULT);
1539     // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
1540     expectations.statusFans12Value = 0x80;
1541     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1542     {
1543         setPMBusExpectations(mockPMBus, expectations);
1544         // Call to analyze will trigger read of "in1_input" to check voltage.
1545         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1546             .Times(1)
1547             .WillOnce(Return("205200"));
1548         psu.analyze();
1549         EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1550     }
1551     // Back to no fault bits on in STATUS_WORD
1552     expectations.statusWordValue = 0;
1553     setPMBusExpectations(mockPMBus, expectations);
1554     // Call to analyze will trigger read of "in1_input" to check voltage.
1555     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1556         .Times(1)
1557         .WillOnce(Return("205300"));
1558     psu.analyze();
1559     EXPECT_EQ(psu.hasFanFault(), false);
1560 }
1561 
1562 TEST_F(PowerSupplyTests, HasTempFault)
1563 {
1564     auto bus = sdbusplus::bus::new_default();
1565 
1566     EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
1567     EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
1568 
1569     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6a,
1570                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1571     MockedGPIOInterface* mockPresenceGPIO =
1572         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1573     // Always return 1 to indicate present.
1574     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1575     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1576     setMissingToPresentExpects(mockPMBus, mockedUtil);
1577     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1578     // for INPUT_HISTORY will check max_power_out to see if it is
1579     // old/unsupported power supply. Indicate good value, supported.
1580     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1581         .WillRepeatedly(Return("2000"));
1582     // STATUS_WORD 0x0000 is powered on, no faults.
1583     PMBusExpectations expectations;
1584     setPMBusExpectations(mockPMBus, expectations);
1585     // Call to analyze will trigger read of "in1_input" to check voltage.
1586     // Initial value would be 0, so this read updates it to non-zero.
1587     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1588         .Times(1)
1589         .WillOnce(Return("206100"));
1590     psu.analyze();
1591     EXPECT_EQ(psu.hasTempFault(), false);
1592     // Turn fault on.
1593     expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
1594     // STATUS_TEMPERATURE fault bit on (OT Fault)
1595     expectations.statusTempValue = 0x80;
1596     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1597     {
1598         setPMBusExpectations(mockPMBus, expectations);
1599         // Call to analyze will trigger read of "in1_input" to check voltage.
1600         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1601             .Times(1)
1602             .WillOnce(Return("206200"));
1603         psu.analyze();
1604         EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1605     }
1606     // Back to no fault bits on in STATUS_WORD
1607     expectations.statusWordValue = 0;
1608     setPMBusExpectations(mockPMBus, expectations);
1609     // Call to analyze will trigger read of "in1_input" to check voltage.
1610     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1611         .Times(1)
1612         .WillOnce(Return("206300"));
1613     psu.analyze();
1614     EXPECT_EQ(psu.hasTempFault(), false);
1615 }
1616 
1617 TEST_F(PowerSupplyTests, HasPgoodFault)
1618 {
1619     auto bus = sdbusplus::bus::new_default();
1620 
1621     PowerSupply psu{bus,         PSUInventoryPath, 3,        0x6b,
1622                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1623     MockedGPIOInterface* mockPresenceGPIO =
1624         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1625     // Always return 1 to indicate present.
1626     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1627     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1628     setMissingToPresentExpects(mockPMBus, mockedUtil);
1629     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1630     // for INPUT_HISTORY will check max_power_out to see if it is
1631     // old/unsupported power supply. Indicate good value, supported.
1632     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1633         .WillRepeatedly(Return("2000"));
1634     // STATUS_WORD 0x0000 is powered on, no faults.
1635     PMBusExpectations expectations;
1636     setPMBusExpectations(mockPMBus, expectations);
1637     // Call to analyze will trigger read of "in1_input" to check voltage.
1638     // Initial value would be 0, so this read updates it to non-zero.
1639     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1640         .Times(1)
1641         .WillOnce(Return("207100"));
1642     psu.analyze();
1643     EXPECT_EQ(psu.hasPgoodFault(), false);
1644     // Setup another expectation of no faults.
1645     setPMBusExpectations(mockPMBus, expectations);
1646     // Call to analyze will trigger read of "in1_input" to check voltage.
1647     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1648         .Times(1)
1649         .WillOnce(Return("207200"));
1650     psu.analyze();
1651     EXPECT_EQ(psu.hasPgoodFault(), false);
1652     // Setup another expectation of no faults.
1653     setPMBusExpectations(mockPMBus, expectations);
1654     // Call to analyze will trigger read of "in1_input" to check voltage.
1655     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1656         .Times(1)
1657         .WillOnce(Return("207300"));
1658     psu.analyze();
1659     EXPECT_EQ(psu.hasPgoodFault(), false);
1660     // Turn PGOOD# off (fault on).
1661     expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
1662     setPMBusExpectations(mockPMBus, expectations);
1663     // Call to analyze will trigger read of "in1_input" to check voltage.
1664     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1665         .Times(1)
1666         .WillOnce(Return("207400"));
1667     psu.analyze();
1668     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 1
1669     EXPECT_EQ(psu.hasPgoodFault(), false);
1670     setPMBusExpectations(mockPMBus, expectations);
1671     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1672         .Times(1)
1673         .WillOnce(Return("207500"));
1674     psu.analyze();
1675     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 2
1676     EXPECT_EQ(psu.hasPgoodFault(), false);
1677     setPMBusExpectations(mockPMBus, expectations);
1678     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1679         .Times(1)
1680         .WillOnce(Return("207600"));
1681     psu.analyze();
1682     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 3
1683     EXPECT_EQ(psu.hasPgoodFault(), false);
1684     setPMBusExpectations(mockPMBus, expectations);
1685     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1686         .Times(1)
1687         .WillOnce(Return("207700"));
1688     psu.analyze();
1689     // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 4
1690     EXPECT_EQ(psu.hasPgoodFault(), false);
1691     setPMBusExpectations(mockPMBus, expectations);
1692     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1693         .Times(1)
1694         .WillOnce(Return("207800"));
1695     psu.analyze();
1696     // Expect true. PGOOD_DEGLITCH_LIMIT @ 5
1697     EXPECT_EQ(psu.hasPgoodFault(), true);
1698     // Back to no fault bits on in STATUS_WORD
1699     expectations.statusWordValue = 0;
1700     setPMBusExpectations(mockPMBus, expectations);
1701     // Call to analyze will trigger read of "in1_input" to check voltage.
1702     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1703         .Times(1)
1704         .WillOnce(Return("207700"));
1705     psu.analyze();
1706     EXPECT_EQ(psu.hasPgoodFault(), false);
1707 
1708     // Turn OFF bit on
1709     expectations.statusWordValue = (status_word::UNIT_IS_OFF);
1710     setPMBusExpectations(mockPMBus, expectations);
1711     // Call to analyze will trigger read of "in1_input" to check voltage.
1712     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1713         .Times(1)
1714         .WillOnce(Return("208100"));
1715     psu.analyze();
1716     EXPECT_EQ(psu.hasPgoodFault(), false);
1717     setPMBusExpectations(mockPMBus, expectations);
1718     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1719         .Times(1)
1720         .WillOnce(Return("208200"));
1721     psu.analyze();
1722     EXPECT_EQ(psu.hasPgoodFault(), false);
1723     setPMBusExpectations(mockPMBus, expectations);
1724     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1725         .Times(1)
1726         .WillOnce(Return("208300"));
1727     psu.analyze();
1728     EXPECT_EQ(psu.hasPgoodFault(), false);
1729     setPMBusExpectations(mockPMBus, expectations);
1730     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1731         .Times(1)
1732         .WillOnce(Return("208400"));
1733     psu.analyze();
1734     EXPECT_EQ(psu.hasPgoodFault(), false);
1735     setPMBusExpectations(mockPMBus, expectations);
1736     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1737         .Times(1)
1738         .WillOnce(Return("208500"));
1739     psu.analyze();
1740     EXPECT_EQ(psu.hasPgoodFault(), true);
1741     // Back to no fault bits on in STATUS_WORD
1742     expectations.statusWordValue = 0;
1743     setPMBusExpectations(mockPMBus, expectations);
1744     // Call to analyze will trigger read of "in1_input" to check voltage.
1745     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1746         .Times(1)
1747         .WillOnce(Return("208000"));
1748     psu.analyze();
1749     EXPECT_EQ(psu.hasPgoodFault(), false);
1750 }
1751 
1752 TEST_F(PowerSupplyTests, HasPSKillFault)
1753 {
1754     auto bus = sdbusplus::bus::new_default();
1755     PowerSupply psu{bus,         PSUInventoryPath, 4,        0x6d,
1756                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1757     MockedGPIOInterface* mockPresenceGPIO =
1758         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1759     // Always return 1 to indicate present.
1760     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1761     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1762     setMissingToPresentExpects(mockPMBus, mockedUtil);
1763     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1764     // for INPUT_HISTORY will check max_power_out to see if it is
1765     // old/unsupported power supply. Indicate good value, supported.
1766     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1767         .WillRepeatedly(Return("2000"));
1768     // STATUS_WORD 0x0000 is powered on, no faults.
1769     PMBusExpectations expectations;
1770     setPMBusExpectations(mockPMBus, expectations);
1771     // Call to analyze will trigger read of "in1_input" to check voltage.
1772     // Initial value would be 0, so this read updates it to non-zero.
1773     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1774         .Times(1)
1775         .WillOnce(Return("208100"));
1776     psu.analyze();
1777     EXPECT_EQ(psu.hasPSKillFault(), false);
1778     // Next return STATUS_WORD with MFR fault bit on.
1779     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1780     // STATUS_MFR_SPEFIC with bit(s) on.
1781     expectations.statusMFRValue = 0xFF;
1782 
1783     // Deglitching faults, false until read the fault bits on up to the limit.
1784     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1785     {
1786         setPMBusExpectations(mockPMBus, expectations);
1787         // Call to analyze will trigger read of "in1_input" to check voltage.
1788         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1789             .Times(1)
1790             .WillOnce(Return("208200"));
1791         if (x == DEGLITCH_LIMIT)
1792         {
1793             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1794         }
1795         psu.analyze();
1796         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1797     }
1798 
1799     // Back to no bits on in STATUS_WORD
1800     expectations.statusWordValue = 0;
1801     setPMBusExpectations(mockPMBus, expectations);
1802     // Call to analyze will trigger read of "in1_input" to check voltage.
1803     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1804         .Times(1)
1805         .WillOnce(Return("208300"));
1806     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1807     psu.analyze();
1808     EXPECT_EQ(psu.hasPSKillFault(), false);
1809     // Next return STATUS_WORD with MFR fault bit on.
1810     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1811     // STATUS_MFR_SPEFIC with bit 4 on.
1812     expectations.statusMFRValue = 0x10;
1813 
1814     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1815     {
1816         setPMBusExpectations(mockPMBus, expectations);
1817         // Call to analyze will trigger read of "in1_input" to check voltage.
1818         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1819             .Times(1)
1820             .WillOnce(Return("208400"));
1821         if (x == DEGLITCH_LIMIT)
1822         {
1823             EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1824         }
1825         psu.analyze();
1826         EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1827     }
1828 
1829     // Back to no bits on in STATUS_WORD
1830     expectations.statusWordValue = 0;
1831     setPMBusExpectations(mockPMBus, expectations);
1832     // Call to analyze will trigger read of "in1_input" to check voltage.
1833     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1834         .Times(1)
1835         .WillOnce(Return("208500"));
1836     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1837     psu.analyze();
1838     EXPECT_EQ(psu.hasPSKillFault(), false);
1839 }
1840 
1841 TEST_F(PowerSupplyTests, HasPS12VcsFault)
1842 {
1843     auto bus = sdbusplus::bus::new_default();
1844     PowerSupply psu{bus,         PSUInventoryPath, 5,        0x6e,
1845                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1846     MockedGPIOInterface* mockPresenceGPIO =
1847         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1848     // Always return 1 to indicate present.
1849     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1850     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1851     setMissingToPresentExpects(mockPMBus, mockedUtil);
1852     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1853     // for INPUT_HISTORY will check max_power_out to see if it is
1854     // old/unsupported power supply. Indicate good value, supported.
1855     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1856         .WillRepeatedly(Return("2000"));
1857     // STATUS_WORD 0x0000 is powered on, no faults.
1858     PMBusExpectations expectations;
1859     setPMBusExpectations(mockPMBus, expectations);
1860     // Call to analyze will trigger read of "in1_input" to check voltage.
1861     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1862         .Times(1)
1863         .WillOnce(Return("209100"));
1864     psu.analyze();
1865     EXPECT_EQ(psu.hasPS12VcsFault(), false);
1866     // Next return STATUS_WORD with MFR fault bit on.
1867     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1868     // STATUS_MFR_SPEFIC with bit(s) on.
1869     expectations.statusMFRValue = 0xFF;
1870 
1871     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1872     {
1873         setPMBusExpectations(mockPMBus, expectations);
1874         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1875             .Times(1)
1876             .WillOnce(Return("209200"));
1877         psu.analyze();
1878         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1879     }
1880 
1881     // Back to no bits on in STATUS_WORD
1882     expectations.statusWordValue = 0;
1883     setPMBusExpectations(mockPMBus, expectations);
1884     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1885         .Times(1)
1886         .WillOnce(Return("209300"));
1887     psu.analyze();
1888     EXPECT_EQ(psu.hasPS12VcsFault(), false);
1889     // Next return STATUS_WORD with MFR fault bit on.
1890     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1891     // STATUS_MFR_SPEFIC with bit 6 on.
1892     expectations.statusMFRValue = 0x40;
1893 
1894     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1895     {
1896         setPMBusExpectations(mockPMBus, expectations);
1897         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1898             .Times(1)
1899             .WillOnce(Return("209400"));
1900         psu.analyze();
1901         EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1902     }
1903 
1904     // Back to no bits on in STATUS_WORD
1905     expectations.statusWordValue = 0;
1906     setPMBusExpectations(mockPMBus, expectations);
1907     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1908         .Times(1)
1909         .WillOnce(Return("209500"));
1910     psu.analyze();
1911     EXPECT_EQ(psu.hasPS12VcsFault(), false);
1912 }
1913 
1914 TEST_F(PowerSupplyTests, HasPSCS12VFault)
1915 {
1916     auto bus = sdbusplus::bus::new_default();
1917     PowerSupply psu{bus,         PSUInventoryPath, 6,        0x6f,
1918                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1919     MockedGPIOInterface* mockPresenceGPIO =
1920         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1921     // Always return 1 to indicate present.
1922     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1923     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1924     setMissingToPresentExpects(mockPMBus, mockedUtil);
1925     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1926     // for INPUT_HISTORY will check max_power_out to see if it is
1927     // old/unsupported power supply. Indicate good value, supported.
1928     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1929         .WillRepeatedly(Return("2000"));
1930     // STATUS_WORD 0x0000 is powered on, no faults.
1931     PMBusExpectations expectations;
1932     setPMBusExpectations(mockPMBus, expectations);
1933     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1934         .Times(1)
1935         .WillOnce(Return("209100"));
1936     psu.analyze();
1937     EXPECT_EQ(psu.hasPSCS12VFault(), false);
1938     // Next return STATUS_WORD with MFR fault bit on.
1939     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1940     // STATUS_MFR_SPEFIC with bit(s) on.
1941     expectations.statusMFRValue = 0xFF;
1942 
1943     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1944     {
1945         setPMBusExpectations(mockPMBus, expectations);
1946         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1947             .Times(1)
1948             .WillOnce(Return("209200"));
1949         psu.analyze();
1950         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1951     }
1952 
1953     // Back to no bits on in STATUS_WORD
1954     expectations.statusWordValue = 0;
1955     setPMBusExpectations(mockPMBus, expectations);
1956     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1957         .Times(1)
1958         .WillOnce(Return("209300"));
1959     psu.analyze();
1960     EXPECT_EQ(psu.hasPSCS12VFault(), false);
1961     // Next return STATUS_WORD with MFR fault bit on.
1962     expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1963     // STATUS_MFR_SPEFIC with bit 7 on.
1964     expectations.statusMFRValue = 0x80;
1965 
1966     for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1967     {
1968         setPMBusExpectations(mockPMBus, expectations);
1969         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1970             .Times(1)
1971             .WillOnce(Return("209400"));
1972         psu.analyze();
1973         EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1974     }
1975 
1976     // Back to no bits on in STATUS_WORD
1977     expectations.statusWordValue = 0;
1978     setPMBusExpectations(mockPMBus, expectations);
1979     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1980         .Times(1)
1981         .WillOnce(Return("209500"));
1982     psu.analyze();
1983     EXPECT_EQ(psu.hasPSCS12VFault(), false);
1984 }
1985 
1986 TEST_F(PowerSupplyTests, PeakInputPowerSensor)
1987 {
1988     auto bus = sdbusplus::bus::new_default();
1989     {
1990         PowerSupply psu{bus,         PSUInventoryPath, 6,        0x6f,
1991                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
1992         EXPECT_EQ(psu.getPeakInputPower(), std::nullopt);
1993 
1994         MockedGPIOInterface* mockPresenceGPIO =
1995             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1996         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1997         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1998 
1999         setMissingToPresentExpects(mockPMBus, mockedUtil);
2000         PMBusExpectations expectations;
2001         setPMBusExpectations(mockPMBus, expectations);
2002 
2003         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2004             .Times(1)
2005             .WillOnce(Return("206000"));
2006         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2007             .WillRepeatedly(Return("2000"));
2008 
2009         psu.analyze();
2010         EXPECT_EQ(psu.getPeakInputPower().value_or(0), 213);
2011     }
2012 
2013     // Test that there is no peak power sensor on 1400W PSs
2014     {
2015         PowerSupply psu{bus,         PSUInventoryPath, 3,        0x68,
2016                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
2017         MockedGPIOInterface* mockPresenceGPIO =
2018             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2019         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2020 
2021         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2022 
2023         setMissingToPresentExpects(mockPMBus, mockedUtil);
2024 
2025         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2026             .WillRepeatedly(Return("30725"));
2027 
2028         PMBusExpectations expectations;
2029         setPMBusExpectations(mockPMBus, expectations);
2030 
2031         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2032             .WillRepeatedly(Return("206000"));
2033         psu.analyze();
2034 
2035         EXPECT_EQ(psu.getPeakInputPower(), std::nullopt);
2036     }
2037 
2038     // Test that IPSPS power supplies don't have peak power
2039     {
2040         PowerSupply psu{bus,      PSUInventoryPath, 11,
2041                         0x58,     "inspur-ipsps",   PSUGPIOLineName,
2042                         isPowerOn};
2043 
2044         MockedGPIOInterface* mockPresenceGPIO =
2045             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2046 
2047         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2048 
2049         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2050 
2051         setMissingToPresentExpects(mockPMBus, mockedUtil);
2052         PMBusExpectations expectations;
2053         setPMBusExpectations(mockPMBus, expectations);
2054 
2055         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2056             .WillRepeatedly(Return("206000"));
2057 
2058         psu.analyze();
2059 
2060         EXPECT_EQ(psu.getPeakInputPower(), std::nullopt);
2061     }
2062 
2063     // Test that a bad response from the input_history command leads
2064     // to an NaN value.
2065     {
2066         PowerSupply psu{bus,         PSUInventoryPath, 6,        0x6f,
2067                         "ibm-cffps", PSUGPIOLineName,  isPowerOn};
2068 
2069         MockedGPIOInterface* mockPresenceGPIO =
2070             static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2071         MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2072 
2073         EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2074 
2075         setMissingToPresentExpects(mockPMBus, mockedUtil);
2076         PMBusExpectations expectations;
2077         setPMBusExpectations(mockPMBus, expectations);
2078 
2079         EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2080             .Times(1)
2081             .WillOnce(Return("206000"));
2082         EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2083             .WillRepeatedly(Return("2000"));
2084 
2085         // Don't return the full 5 bytes.
2086         EXPECT_CALL(mockPMBus,
2087                     readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug, 5))
2088             .WillRepeatedly(Return(std::vector<uint8_t>{0x01, 0x5c}));
2089 
2090         psu.analyze();
2091         EXPECT_THAT(psu.getPeakInputPower().value_or(0), IsNan());
2092     }
2093 }
2094 
2095 TEST_F(PowerSupplyTests, IsSyncHistoryRequired)
2096 {
2097     auto bus = sdbusplus::bus::new_default();
2098     PowerSupply psu{bus,         PSUInventoryPath, 8,        0x6f,
2099                     "ibm-cffps", PSUGPIOLineName,  isPowerOn};
2100     EXPECT_EQ(psu.isSyncHistoryRequired(), false);
2101     MockedGPIOInterface* mockPresenceGPIO =
2102         static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2103     // Always return 1 to indicate present.
2104     EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2105     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2106     setMissingToPresentExpects(mockPMBus, mockedUtil);
2107     // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2108     // for INPUT_HISTORY will check max_power_out to see if it is
2109     // old/unsupported power supply. Indicate good value, supported.
2110     EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2111         .WillRepeatedly(Return("2000"));
2112     PMBusExpectations expectations;
2113     setPMBusExpectations(mockPMBus, expectations);
2114     EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2115         .Times(1)
2116         .WillRepeatedly(Return("205000"));
2117     EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
2118     psu.analyze();
2119     // Missing -> Present requires history sync
2120     EXPECT_EQ(psu.isSyncHistoryRequired(), true);
2121     psu.clearSyncHistoryRequired();
2122     EXPECT_EQ(psu.isSyncHistoryRequired(), false);
2123 }
2124 
2125 TEST_F(PowerSupplyTests, TestLinearConversions)
2126 {
2127     // Mantissa > 0, exponent = 0
2128     EXPECT_EQ(0, PowerSupply::linearToInteger(0));
2129     EXPECT_EQ(1, PowerSupply::linearToInteger(1));
2130     EXPECT_EQ(38, PowerSupply::linearToInteger(0x26));
2131     EXPECT_EQ(1023, PowerSupply::linearToInteger(0x3FF));
2132 
2133     // Mantissa < 0, exponent = 0
2134     EXPECT_EQ(-1, PowerSupply::linearToInteger(0x7FF));
2135     EXPECT_EQ(-20, PowerSupply::linearToInteger(0x7EC));
2136     EXPECT_EQ(-769, PowerSupply::linearToInteger(0x4FF));
2137     EXPECT_EQ(-989, PowerSupply::linearToInteger(0x423));
2138     EXPECT_EQ(-1024, PowerSupply::linearToInteger(0x400));
2139 
2140     // Mantissa >= 0, exponent > 0
2141     // M = 1, E = 2
2142     EXPECT_EQ(4, PowerSupply::linearToInteger(0x1001));
2143 
2144     // M = 1000, E = 10
2145     EXPECT_EQ(1024000, PowerSupply::linearToInteger(0x53E8));
2146 
2147     // M = 10, E = 15
2148     EXPECT_EQ(327680, PowerSupply::linearToInteger(0x780A));
2149 
2150     // Mantissa >= 0, exponent < 0
2151     // M = 0, E = -1
2152     EXPECT_EQ(0, PowerSupply::linearToInteger(0xF800));
2153 
2154     // M = 100, E = -2
2155     EXPECT_EQ(25, PowerSupply::linearToInteger(0xF064));
2156 
2157     // Mantissa < 0, exponent < 0
2158     // M = -100, E = -1
2159     EXPECT_EQ(-50, PowerSupply::linearToInteger(0xFF9C));
2160 
2161     // M = -1024, E = -7
2162     EXPECT_EQ(-8, PowerSupply::linearToInteger(0xCC00));
2163 }
2164