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