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