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