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>(
179 bus, PSUInventoryPath, 3, 0x68, "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