blob: 22c15e2fc7cf565e865c9c35eca787807f88a6d3 [file] [log] [blame]
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001#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
10using namespace phosphor::power::psu;
11using namespace phosphor::pmbus;
12
13using ::testing::_;
Brandon Wyman59a35792020-06-04 12:37:40 -050014using ::testing::Args;
Brandon Wyman3f1242f2020-01-28 13:11:25 -060015using ::testing::Assign;
16using ::testing::DoAll;
Brandon Wyman59a35792020-06-04 12:37:40 -050017using ::testing::ElementsAre;
18using ::testing::NotNull;
Brandon Wyman3f1242f2020-01-28 13:11:25 -060019using ::testing::Return;
20using ::testing::StrEq;
21
22static auto PSUInventoryPath = "/xyz/bmc/inv/sys/chassis/board/powersupply0";
B. J. Wyman681b2a32021-04-20 22:31:22 +000023static auto PSUGPIOLineName = "presence-ps0";
Brandon Wyman3f1242f2020-01-28 13:11:25 -060024
Brandon Wymanb654c612021-11-05 23:24:51 +000025struct PMBusExpectations
26{
27 uint16_t statusWordValue{0x0000};
28 uint8_t statusInputValue{0x00};
29 uint8_t statusMFRValue{0x00};
30 uint8_t statusCMLValue{0x00};
31 uint8_t statusVOUTValue{0x00};
Brandon Wymanb10b3be2021-11-09 22:12:15 +000032 uint8_t statusIOUTValue{0x00};
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +000033 uint8_t statusFans12Value{0x00};
Brandon Wyman96893a42021-11-05 19:56:57 +000034 uint8_t statusTempValue{0x00};
Brandon Wymanb654c612021-11-05 23:24:51 +000035};
36
Brandon Wyman8da35c52021-10-28 22:45:08 +000037// Helper function to setup expectations for various STATUS_* commands
Brandon Wymanb654c612021-11-05 23:24:51 +000038void setPMBusExpectations(MockedPMBus& mockPMBus,
39 const PMBusExpectations& expectations)
Brandon Wyman8da35c52021-10-28 22:45:08 +000040{
41 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
42 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000043 .WillOnce(Return(expectations.statusWordValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000044
Brandon Wymanb654c612021-11-05 23:24:51 +000045 if (expectations.statusWordValue != 0)
Brandon Wyman8da35c52021-10-28 22:45:08 +000046 {
47 // If fault bits are on in STATUS_WORD, there will also be a read of
Brandon Wyman96893a42021-11-05 19:56:57 +000048 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and
49 // STATUS_TEMPERATURE.
Brandon Wyman8da35c52021-10-28 22:45:08 +000050 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
51 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000052 .WillOnce(Return(expectations.statusInputValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000053 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _))
54 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000055 .WillOnce(Return(expectations.statusMFRValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000056 EXPECT_CALL(mockPMBus, read(STATUS_CML, _))
57 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000058 .WillOnce(Return(expectations.statusCMLValue));
Brandon Wyman6710ba22021-10-27 17:39:31 +000059 // Page will need to be set to 0 to read STATUS_VOUT.
60 EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0))
61 .Times(1)
62 .WillOnce(Return("status0_vout"));
63 EXPECT_CALL(mockPMBus, read("status0_vout", _))
64 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000065 .WillOnce(Return(expectations.statusVOUTValue));
Brandon Wymanb10b3be2021-11-09 22:12:15 +000066 EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _))
67 .Times(1)
68 .WillOnce(Return(expectations.statusIOUTValue));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +000069 EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _))
70 .Times(1)
71 .WillOnce(Return(expectations.statusFans12Value));
Brandon Wyman96893a42021-11-05 19:56:57 +000072 EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _))
73 .Times(1)
74 .WillOnce(Return(expectations.statusTempValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000075 }
76}
77
Brandon Wyman3f1242f2020-01-28 13:11:25 -060078class PowerSupplyTests : public ::testing::Test
79{
80 public:
81 PowerSupplyTests() :
82 mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
83 {
84 ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
85 }
86
87 ~PowerSupplyTests() override
88 {
89 freeUtils();
90 }
91
92 const MockedUtil& mockedUtil;
93};
94
Brandon Wyman391a0692021-12-08 23:28:18 +000095// Helper function for when a power supply goes from missing to present.
96void setMissingToPresentExpects(MockedPMBus& pmbus, const MockedUtil& util)
97{
98 // Call to analyze() will update to present, that will trigger updating
99 // to the correct/latest HWMON directory, in case it changes.
100 EXPECT_CALL(pmbus, findHwmonDir());
101 // Presence change from missing to present will trigger write to
102 // ON_OFF_CONFIG.
103 EXPECT_CALL(pmbus, writeBinary(ON_OFF_CONFIG, _, _));
104 // Presence change from missing to present will trigger in1_input read
105 // in an attempt to get CLEAR_FAULTS called.
Brandon Wyman82affd92021-11-24 19:12:49 +0000106 // The voltage defaults to 0, the first call to analyze should update the
107 // voltage to the current reading, triggering another clearing of faults
108 // due to below minimum to within range voltage.
109 // This READ_VIN for CLEAR_FAULTS does not check the returned value.
110 EXPECT_CALL(pmbus, read(READ_VIN, _))
111 .Times(2)
112 .WillOnce(Return(1))
113 .WillOnce(Return(2));
Brandon Wyman391a0692021-12-08 23:28:18 +0000114 // Missing/present call will update Presence in inventory.
Brandon Wyman391a0692021-12-08 23:28:18 +0000115 EXPECT_CALL(util, setPresence(_, _, true, _));
116}
117
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600118TEST_F(PowerSupplyTests, Constructor)
119{
120 /**
121 * @param[in] invpath - String for inventory path to use
122 * @param[in] i2cbus - The bus number this power supply is on
123 * @param[in] i2caddr - The 16-bit I2C address of the power supply
B. J. Wyman681b2a32021-04-20 22:31:22 +0000124 * @param[in] gpioLineName - The string for the gpio-line-name to read for
125 * presence.
126 * @param[in] bindDelay - Time in milliseconds to delay binding the device
127 * driver after seeing the presence line go active.
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600128 */
129 auto bus = sdbusplus::bus::new_default();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600130
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500131 // Try where inventory path is empty, constructor should fail.
132 try
133 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000134 auto psu =
135 std::make_unique<PowerSupply>(bus, "", 3, 0x68, PSUGPIOLineName);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500136 ADD_FAILURE() << "Should not have reached this line.";
137 }
138 catch (const std::invalid_argument& e)
139 {
140 EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
141 }
142 catch (...)
143 {
144 ADD_FAILURE() << "Should not have caught exception.";
145 }
146
B. J. Wyman681b2a32021-04-20 22:31:22 +0000147 // TODO: Try invalid i2c address?
148
149 // Try where gpioLineName is empty.
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500150 try
151 {
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500152 auto psu =
B. J. Wyman681b2a32021-04-20 22:31:22 +0000153 std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, "");
154 ADD_FAILURE()
155 << "Should not have reached this line. Invalid gpioLineName.";
156 }
157 catch (const std::invalid_argument& e)
158 {
159 EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
160 }
161 catch (...)
162 {
163 ADD_FAILURE() << "Should not have caught exception.";
164 }
165
166 // Test with valid arguments
167 // NOT using D-Bus inventory path for presence.
168 try
169 {
170 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
171 PSUGPIOLineName);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500172
173 EXPECT_EQ(psu->isPresent(), false);
174 EXPECT_EQ(psu->isFaulted(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000175 EXPECT_EQ(psu->hasCommFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500176 EXPECT_EQ(psu->hasInputFault(), false);
177 EXPECT_EQ(psu->hasMFRFault(), false);
178 EXPECT_EQ(psu->hasVINUVFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000179 EXPECT_EQ(psu->hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000180 EXPECT_EQ(psu->hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000181 EXPECT_EQ(psu->hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000182 EXPECT_EQ(psu->hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000183 EXPECT_EQ(psu->hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000184 EXPECT_EQ(psu->hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000185 EXPECT_EQ(psu->hasPSKillFault(), false);
186 EXPECT_EQ(psu->hasPS12VcsFault(), false);
187 EXPECT_EQ(psu->hasPSCS12VFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500188 }
189 catch (...)
190 {
191 ADD_FAILURE() << "Should not have caught exception.";
192 }
B. J. Wyman681b2a32021-04-20 22:31:22 +0000193
194 // Test with valid arguments
195 // TODO: Using D-Bus inventory path for presence.
196 try
197 {
198 // FIXME: How do I get that presenceGPIO.read() in the startup to throw
199 // an exception?
200
201 // EXPECT_CALL(mockedUtil, getPresence(_,
202 // StrEq(PSUInventoryPath)))
203 // .Times(1);
204 }
205 catch (...)
206 {
207 ADD_FAILURE() << "Should not have caught exception.";
208 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600209}
210
211TEST_F(PowerSupplyTests, Analyze)
212{
213 auto bus = sdbusplus::bus::new_default();
214
Brandon Wymanb654c612021-11-05 23:24:51 +0000215 {
216 // If I default to reading the GPIO, I will NOT expect a call to
217 // getPresence().
B. J. Wyman681b2a32021-04-20 22:31:22 +0000218
Brandon Wymanb654c612021-11-05 23:24:51 +0000219 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
220 MockedGPIOInterface* mockPresenceGPIO =
221 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
222 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000223
Brandon Wymanb654c612021-11-05 23:24:51 +0000224 psu.analyze();
225 // By default, nothing should change.
226 EXPECT_EQ(psu.isPresent(), false);
227 EXPECT_EQ(psu.isFaulted(), false);
228 EXPECT_EQ(psu.hasInputFault(), false);
229 EXPECT_EQ(psu.hasMFRFault(), false);
230 EXPECT_EQ(psu.hasVINUVFault(), false);
231 EXPECT_EQ(psu.hasCommFault(), false);
232 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000233 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000234 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000235 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000236 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000237 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000238 EXPECT_EQ(psu.hasPSKillFault(), false);
239 EXPECT_EQ(psu.hasPS12VcsFault(), false);
240 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000241 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600242
B. J. Wyman681b2a32021-04-20 22:31:22 +0000243 PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
244 // In order to get the various faults tested, the power supply needs to
245 // be present in order to read from the PMBus device(s).
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000246 MockedGPIOInterface* mockPresenceGPIO2 =
247 static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000248 // Always return 1 to indicate present.
249 // Each analyze() call will trigger a read of the presence GPIO.
250 EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000251 EXPECT_EQ(psu2.isPresent(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600252
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600253 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000254 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600255
Brandon Wymanb654c612021-11-05 23:24:51 +0000256 // STATUS_WORD INPUT fault.
257 {
258 // Start with STATUS_WORD 0x0000. Powered on, no faults.
259 // Set expectations for a no fault
260 PMBusExpectations expectations;
261 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000262 // After reading STATUS_WORD, etc., there will be a READ_VIN check.
263 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
264 .Times(1)
265 .WillOnce(Return("206000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000266 psu2.analyze();
267 EXPECT_EQ(psu2.isPresent(), true);
268 EXPECT_EQ(psu2.isFaulted(), false);
269 EXPECT_EQ(psu2.hasInputFault(), false);
270 EXPECT_EQ(psu2.hasMFRFault(), false);
271 EXPECT_EQ(psu2.hasVINUVFault(), false);
272 EXPECT_EQ(psu2.hasCommFault(), false);
273 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000274 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000275 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000276 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000277 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000278 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000279 EXPECT_EQ(psu2.hasPSKillFault(), false);
280 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
281 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000282
283 // Update expectations for STATUS_WORD input fault/warn
Brandon Wyman96893a42021-11-05 19:56:57 +0000284 // STATUS_INPUT fault bits ... on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000285 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
286 expectations.statusInputValue = 0x38;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000287
288 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
289 {
290 setPMBusExpectations(mockPMBus, expectations);
291 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
292 .Times(1)
293 .WillOnce(Return("207000"));
294 psu2.analyze();
295 EXPECT_EQ(psu2.isPresent(), true);
296 // Should not be faulted until it reaches the deglitch limit.
297 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
298 EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
299 EXPECT_EQ(psu2.hasMFRFault(), false);
300 EXPECT_EQ(psu2.hasVINUVFault(), false);
301 EXPECT_EQ(psu2.hasCommFault(), false);
302 EXPECT_EQ(psu2.hasVoutOVFault(), false);
303 EXPECT_EQ(psu2.hasIoutOCFault(), false);
304 EXPECT_EQ(psu2.hasVoutUVFault(), false);
305 EXPECT_EQ(psu2.hasFanFault(), false);
306 EXPECT_EQ(psu2.hasTempFault(), false);
307 EXPECT_EQ(psu2.hasPgoodFault(), false);
308 EXPECT_EQ(psu2.hasPSKillFault(), false);
309 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
310 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
311 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000312 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600313
Brandon Wymanc2906f42021-12-21 20:14:56 +0000314 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(1));
315 psu2.clearFaults();
316
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600317 // STATUS_WORD INPUT/UV fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000318 {
319 // First need it to return good status, then the fault
320 PMBusExpectations expectations;
321 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000322 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
323 .Times(1)
324 .WillOnce(Return("208000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000325 psu2.analyze();
Brandon Wymanc2906f42021-12-21 20:14:56 +0000326 EXPECT_EQ(psu2.isFaulted(), false);
327 EXPECT_EQ(psu2.hasInputFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000328 // Now set fault bits in STATUS_WORD
329 expectations.statusWordValue =
330 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
331 // STATUS_INPUT fault bits ... on.
332 expectations.statusInputValue = 0x38;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000333 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
334 {
335 setPMBusExpectations(mockPMBus, expectations);
336 // Input/UV fault, so voltage should read back low.
337 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
338 .Times(1)
339 .WillOnce(Return("19123"));
340 psu2.analyze();
341 EXPECT_EQ(psu2.isPresent(), true);
342 // Only faulted if hit deglitch limit
343 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
344 EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
345 EXPECT_EQ(psu2.hasVINUVFault(), x >= DEGLITCH_LIMIT);
346 EXPECT_EQ(psu2.hasMFRFault(), false);
347 EXPECT_EQ(psu2.hasCommFault(), false);
348 EXPECT_EQ(psu2.hasVoutOVFault(), false);
349 EXPECT_EQ(psu2.hasIoutOCFault(), false);
350 EXPECT_EQ(psu2.hasVoutUVFault(), false);
351 EXPECT_EQ(psu2.hasFanFault(), false);
352 EXPECT_EQ(psu2.hasTempFault(), false);
353 EXPECT_EQ(psu2.hasPgoodFault(), false);
354 EXPECT_EQ(psu2.hasPSKillFault(), false);
355 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
356 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
357 }
Brandon Wyman82affd92021-11-24 19:12:49 +0000358 // Turning VIN_UV fault off causes clearing of faults, causing read of
359 // in1_input as an attempt to get CLEAR_FAULTS called.
360 expectations.statusWordValue = 0;
361 setPMBusExpectations(mockPMBus, expectations);
362 // The call to read the voltage
363 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
364 .Times(1)
365 .WillOnce(Return("209000"));
366 // The call for CLEAR_FAULTS command
367 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(3));
368 psu2.analyze();
369 // Should remain present, no longer be faulted, no input fault, no
370 // VIN_UV fault. Nothing else should change.
371 EXPECT_EQ(psu2.isPresent(), true);
372 EXPECT_EQ(psu2.isFaulted(), false);
373 EXPECT_EQ(psu2.hasInputFault(), false);
374 EXPECT_EQ(psu2.hasVINUVFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000375 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600376
Brandon Wymanc2906f42021-12-21 20:14:56 +0000377 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(1));
378 psu2.clearFaults();
379
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600380 // STATUS_WORD MFR fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000381 {
382 // First need it to return good status, then the fault
383 PMBusExpectations expectations;
384 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000385 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
386 .Times(1)
387 .WillOnce(Return("210000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000388 psu2.analyze();
389 // Now STATUS_WORD with MFR fault bit on.
390 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
391 // STATUS_MFR bits on.
392 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000393
394 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
395 {
396 setPMBusExpectations(mockPMBus, expectations);
397 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
398 .Times(1)
399 .WillOnce(Return("211000"));
400 psu2.analyze();
401 EXPECT_EQ(psu2.isPresent(), true);
402 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
403 EXPECT_EQ(psu2.hasInputFault(), false);
404 EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT);
405 EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT);
406 EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
407 EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
408 EXPECT_EQ(psu2.hasVINUVFault(), false);
409 EXPECT_EQ(psu2.hasCommFault(), false);
410 EXPECT_EQ(psu2.hasVoutOVFault(), false);
411 EXPECT_EQ(psu2.hasIoutOCFault(), false);
412 EXPECT_EQ(psu2.hasVoutUVFault(), false);
413 EXPECT_EQ(psu2.hasFanFault(), false);
414 EXPECT_EQ(psu2.hasTempFault(), false);
415 EXPECT_EQ(psu2.hasPgoodFault(), false);
416 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000417 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600418
Brandon Wymanc2906f42021-12-21 20:14:56 +0000419 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(1));
420 psu2.clearFaults();
Brandon Wyman96893a42021-11-05 19:56:57 +0000421 // Temperature fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000422 {
423 // First STATUS_WORD with no bits set, then with temperature fault.
424 PMBusExpectations expectations;
425 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000426 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
427 .Times(1)
428 .WillOnce(Return("212000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000429 psu2.analyze();
430 // STATUS_WORD with temperature fault bit on.
431 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
Brandon Wyman96893a42021-11-05 19:56:57 +0000432 // STATUS_TEMPERATURE with fault bit(s) on.
433 expectations.statusTempValue = 0x10;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000434 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
435 {
436 setPMBusExpectations(mockPMBus, expectations);
437 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
438 .Times(1)
439 .WillOnce(Return("213000"));
440 psu2.analyze();
441 EXPECT_EQ(psu2.isPresent(), true);
442 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
443 EXPECT_EQ(psu2.hasInputFault(), false);
444 EXPECT_EQ(psu2.hasMFRFault(), false);
445 EXPECT_EQ(psu2.hasVINUVFault(), false);
446 EXPECT_EQ(psu2.hasCommFault(), false);
447 EXPECT_EQ(psu2.hasVoutOVFault(), false);
448 EXPECT_EQ(psu2.hasIoutOCFault(), false);
449 EXPECT_EQ(psu2.hasVoutUVFault(), false);
450 EXPECT_EQ(psu2.hasFanFault(), false);
451 EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT);
452 EXPECT_EQ(psu2.hasPgoodFault(), false);
453 EXPECT_EQ(psu2.hasPSKillFault(), false);
454 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
455 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
456 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000457 }
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000458
Brandon Wymanc2906f42021-12-21 20:14:56 +0000459 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(1));
460 psu2.clearFaults();
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000461 // CML fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000462 {
463 // First STATUS_WORD wit no bits set, then with CML fault.
464 PMBusExpectations expectations;
465 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000466 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
467 .Times(1)
468 .WillOnce(Return("214000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000469 psu2.analyze();
470 // STATUS_WORD with CML fault bit on.
471 expectations.statusWordValue = (status_word::CML_FAULT);
472 // Turn on STATUS_CML fault bit(s)
473 expectations.statusCMLValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000474 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
475 {
476 setPMBusExpectations(mockPMBus, expectations);
477 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
478 .Times(1)
479 .WillOnce(Return("215000"));
480 psu2.analyze();
481 EXPECT_EQ(psu2.isPresent(), true);
482 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
483 EXPECT_EQ(psu2.hasCommFault(), x >= DEGLITCH_LIMIT);
484 EXPECT_EQ(psu2.hasInputFault(), false);
485 EXPECT_EQ(psu2.hasMFRFault(), false);
486 EXPECT_EQ(psu2.hasVINUVFault(), false);
487 EXPECT_EQ(psu2.hasVoutOVFault(), false);
488 EXPECT_EQ(psu2.hasIoutOCFault(), false);
489 EXPECT_EQ(psu2.hasVoutUVFault(), false);
490 EXPECT_EQ(psu2.hasFanFault(), false);
491 EXPECT_EQ(psu2.hasTempFault(), false);
492 EXPECT_EQ(psu2.hasPgoodFault(), false);
493 EXPECT_EQ(psu2.hasPSKillFault(), false);
494 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
495 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
496 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000497 }
Brandon Wyman6710ba22021-10-27 17:39:31 +0000498
Brandon Wymanc2906f42021-12-21 20:14:56 +0000499 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(1));
500 psu2.clearFaults();
Brandon Wyman6710ba22021-10-27 17:39:31 +0000501 // VOUT_OV_FAULT fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000502 {
503 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
504 PMBusExpectations expectations;
505 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000506 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
507 .Times(1)
508 .WillOnce(Return("216000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000509 psu2.analyze();
510 // STATUS_WORD with VOUT/VOUT_OV fault.
511 expectations.statusWordValue =
512 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
513 // Turn on STATUS_VOUT fault bit(s)
514 expectations.statusVOUTValue = 0xA0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000515 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
516 {
517 // STATUS_TEMPERATURE don't care (default)
518 setPMBusExpectations(mockPMBus, expectations);
519 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
520 .Times(1)
521 .WillOnce(Return("217000"));
522 psu2.analyze();
523 EXPECT_EQ(psu2.isPresent(), true);
524 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
525 EXPECT_EQ(psu2.hasInputFault(), false);
526 EXPECT_EQ(psu2.hasMFRFault(), false);
527 EXPECT_EQ(psu2.hasVINUVFault(), false);
528 EXPECT_EQ(psu2.hasCommFault(), false);
529 EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
530 EXPECT_EQ(psu2.hasVoutUVFault(), false);
531 EXPECT_EQ(psu2.hasIoutOCFault(), false);
532 EXPECT_EQ(psu2.hasFanFault(), false);
533 EXPECT_EQ(psu2.hasTempFault(), false);
534 EXPECT_EQ(psu2.hasPgoodFault(), false);
535 EXPECT_EQ(psu2.hasPSKillFault(), false);
536 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
537 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
538 }
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000539 }
540
541 // IOUT_OC_FAULT fault
542 {
543 // First STATUS_WORD with no bits set, then with IOUT_OC fault.
544 PMBusExpectations expectations;
545 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000546 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
547 .Times(1)
548 .WillOnce(Return("218000"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000549 psu2.analyze();
550 // STATUS_WORD with IOUT_OC fault.
551 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
552 // Turn on STATUS_IOUT fault bit(s)
553 expectations.statusIOUTValue = 0x88;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000554 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
555 {
556 setPMBusExpectations(mockPMBus, expectations);
557 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
558 .Times(1)
559 .WillOnce(Return("219000"));
560 psu2.analyze();
561 EXPECT_EQ(psu2.isPresent(), true);
562 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
563 EXPECT_EQ(psu2.hasInputFault(), false);
564 EXPECT_EQ(psu2.hasMFRFault(), false);
565 EXPECT_EQ(psu2.hasVINUVFault(), false);
566 EXPECT_EQ(psu2.hasCommFault(), false);
567 EXPECT_EQ(psu2.hasVoutOVFault(), false);
568 EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
569 EXPECT_EQ(psu2.hasVoutUVFault(), false);
570 EXPECT_EQ(psu2.hasFanFault(), false);
571 EXPECT_EQ(psu2.hasTempFault(), false);
572 EXPECT_EQ(psu2.hasPgoodFault(), false);
573 EXPECT_EQ(psu2.hasPSKillFault(), false);
574 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
575 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
576 }
Brandon Wyman2cf46942021-10-28 19:09:16 +0000577 }
578
579 // VOUT_UV_FAULT
580 {
581 // First STATUS_WORD with no bits set, then with VOUT fault.
582 PMBusExpectations expectations;
583 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000584 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
585 .Times(1)
586 .WillOnce(Return("220000"));
Brandon Wyman2cf46942021-10-28 19:09:16 +0000587 psu2.analyze();
588 // Change STATUS_WORD to indicate VOUT fault.
589 expectations.statusWordValue = (status_word::VOUT_FAULT);
590 // Turn on STATUS_VOUT fault bit(s)
591 expectations.statusVOUTValue = 0x30;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000592 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
593 {
594 setPMBusExpectations(mockPMBus, expectations);
595 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
596 .Times(1)
597 .WillOnce(Return("221000"));
598 psu2.analyze();
599 EXPECT_EQ(psu2.isPresent(), true);
600 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
601 EXPECT_EQ(psu2.hasInputFault(), false);
602 EXPECT_EQ(psu2.hasMFRFault(), false);
603 EXPECT_EQ(psu2.hasVINUVFault(), false);
604 EXPECT_EQ(psu2.hasCommFault(), false);
605 EXPECT_EQ(psu2.hasVoutOVFault(), false);
606 EXPECT_EQ(psu2.hasIoutOCFault(), false);
607 EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
608 EXPECT_EQ(psu2.hasFanFault(), false);
609 EXPECT_EQ(psu2.hasTempFault(), false);
610 EXPECT_EQ(psu2.hasPgoodFault(), false);
611 EXPECT_EQ(psu2.hasPSKillFault(), false);
612 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
613 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
614 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000615 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600616
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000617 // Fan fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000618 {
619 // First STATUS_WORD with no bits set, then with fan fault.
620 PMBusExpectations expectations;
621 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000622 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
623 .Times(1)
624 .WillOnce(Return("222000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000625 psu2.analyze();
626 expectations.statusWordValue = (status_word::FAN_FAULT);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000627 // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
628 expectations.statusFans12Value = 0xA0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000629
630 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
631 {
632 setPMBusExpectations(mockPMBus, expectations);
633 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
634 .Times(1)
635 .WillOnce(Return("223000"));
636 psu2.analyze();
637 EXPECT_EQ(psu2.isPresent(), true);
638 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
639 EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT);
640 EXPECT_EQ(psu2.hasInputFault(), false);
641 EXPECT_EQ(psu2.hasMFRFault(), false);
642 EXPECT_EQ(psu2.hasVINUVFault(), false);
643 EXPECT_EQ(psu2.hasCommFault(), false);
644 EXPECT_EQ(psu2.hasVoutOVFault(), false);
645 EXPECT_EQ(psu2.hasIoutOCFault(), false);
646 EXPECT_EQ(psu2.hasVoutUVFault(), false);
647 EXPECT_EQ(psu2.hasTempFault(), false);
648 EXPECT_EQ(psu2.hasPgoodFault(), false);
649 EXPECT_EQ(psu2.hasPSKillFault(), false);
650 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
651 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
652 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000653 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000654
Brandon Wyman06ca4592021-12-06 22:52:23 +0000655 // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000656 {
Brandon Wyman2916ea52021-11-06 03:31:18 +0000657 // First STATUS_WORD with no bits set.
658 PMBusExpectations expectations;
659 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000660 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
661 .Times(1)
662 .WillOnce(Return("123000"));
Brandon Wyman2916ea52021-11-06 03:31:18 +0000663 psu2.analyze();
664 EXPECT_EQ(psu2.isFaulted(), false);
665 // POWER_GOOD# inactive, and OFF bit on.
666 expectations.statusWordValue =
667 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
Brandon Wyman06ca4592021-12-06 22:52:23 +0000668 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
669 {
670 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
671 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
672 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000673 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
674 .Times(1)
675 .WillOnce(Return("124000"));
Brandon Wyman06ca4592021-12-06 22:52:23 +0000676 psu2.analyze();
677 EXPECT_EQ(psu2.isPresent(), true);
Brandon Wymanc2906f42021-12-21 20:14:56 +0000678 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
Brandon Wyman06ca4592021-12-06 22:52:23 +0000679 EXPECT_EQ(psu2.hasInputFault(), false);
680 EXPECT_EQ(psu2.hasMFRFault(), false);
681 EXPECT_EQ(psu2.hasVINUVFault(), false);
682 EXPECT_EQ(psu2.hasCommFault(), false);
683 EXPECT_EQ(psu2.hasVoutOVFault(), false);
684 EXPECT_EQ(psu2.hasVoutUVFault(), false);
685 EXPECT_EQ(psu2.hasIoutOCFault(), false);
686 EXPECT_EQ(psu2.hasFanFault(), false);
687 EXPECT_EQ(psu2.hasTempFault(), false);
688 if (x < DEGLITCH_LIMIT)
689 {
690 EXPECT_EQ(psu2.hasPgoodFault(), false);
691 }
692 else
693 {
694 EXPECT_EQ(psu2.hasPgoodFault(), true);
695 }
696 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000697 }
698
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600699 // TODO: ReadFailure
700}
701
Brandon Wyman59a35792020-06-04 12:37:40 -0500702TEST_F(PowerSupplyTests, OnOffConfig)
703{
704 auto bus = sdbusplus::bus::new_default();
705 uint8_t data = 0x15;
706
707 // Test where PSU is NOT present
708 try
709 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000710 // Assume GPIO presence, not inventory presence?
711 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
712
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000713 MockedGPIOInterface* mockPresenceGPIO =
714 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000715 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
Brandon Wyman59a35792020-06-04 12:37:40 -0500716 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000717 // Constructor should set initial presence, default read returns 0.
Brandon Wyman59a35792020-06-04 12:37:40 -0500718 // If it is not present, I should not be trying to write to it.
719 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
720 psu.onOffConfig(data);
721 }
722 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000723 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500724
725 // Test where PSU is present
726 try
727 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000728 // Assume GPIO presence, not inventory presence?
729 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000730 MockedGPIOInterface* mockPresenceGPIO =
731 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman391a0692021-12-08 23:28:18 +0000732 // There will potentially be multiple calls, we want it to continue
733 // returning 1 for the GPIO read to keep the power supply present.
734 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman59a35792020-06-04 12:37:40 -0500735 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000736 setMissingToPresentExpects(mockPMBus, mockedUtil);
737 // If I am calling analyze(), I should probably give it good data.
738 // STATUS_WORD 0x0000 is powered on, no faults.
739 PMBusExpectations expectations;
740 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000741 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
742 .Times(1)
743 .WillOnce(Return("205000"));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000744 psu.analyze();
Brandon Wyman391a0692021-12-08 23:28:18 +0000745 // I definitely should be writting ON_OFF_CONFIG if I call the function
746 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
747 Type::HwmonDeviceDebug))
Brandon Wyman59a35792020-06-04 12:37:40 -0500748 .Times(1);
749 psu.onOffConfig(data);
750 }
751 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000752 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500753}
754
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600755TEST_F(PowerSupplyTests, ClearFaults)
756{
757 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000758 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000759 MockedGPIOInterface* mockPresenceGPIO =
760 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000761 // Always return 1 to indicate present.
762 // Each analyze() call will trigger a read of the presence GPIO.
763 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000764 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000765 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000766 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000767 PMBusExpectations expectations;
768 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000769 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
770 .Times(1)
771 .WillOnce(Return("207000"));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000772 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600773 EXPECT_EQ(psu.isPresent(), true);
774 EXPECT_EQ(psu.isFaulted(), false);
775 EXPECT_EQ(psu.hasInputFault(), false);
776 EXPECT_EQ(psu.hasMFRFault(), false);
777 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000778 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000779 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000780 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000781 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000782 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000783 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000784 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000785 EXPECT_EQ(psu.hasPSKillFault(), false);
786 EXPECT_EQ(psu.hasPS12VcsFault(), false);
787 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000788
Brandon Wymanf07bc792021-10-12 19:00:35 +0000789 // STATUS_WORD with fault bits galore!
Brandon Wymanb654c612021-11-05 23:24:51 +0000790 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000791 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000792 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000793 // STATUS_MFR_SPEFIC with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000794 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000795 // STATUS_CML with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000796 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000797 // STATUS_VOUT with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000798 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000799 // STATUS_IOUT with bits on.
800 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000801 // STATUS_FANS_1_2 with bits on.
802 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000803 // STATUS_TEMPERATURE with bits on.
804 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000805
806 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
807 {
808 setPMBusExpectations(mockPMBus, expectations);
809 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
810 .Times(1)
811 .WillOnce(Return("0"));
812 psu.analyze();
813 EXPECT_EQ(psu.isPresent(), true);
814 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
815 // Rely on HasVoutUVFault() to verify this sets and clears.
816 EXPECT_EQ(psu.hasVoutUVFault(), false);
817 // All faults are deglitched 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.hasCommFault(), x >= DEGLITCH_LIMIT);
823 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
824 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
825 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
826 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
827 EXPECT_EQ(psu.hasPgoodFault(), x >= DEGLITCH_LIMIT);
828 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
829 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
830 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
831 }
832
833 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(207000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600834 psu.clearFaults();
835 EXPECT_EQ(psu.isPresent(), true);
836 EXPECT_EQ(psu.isFaulted(), false);
837 EXPECT_EQ(psu.hasInputFault(), false);
838 EXPECT_EQ(psu.hasMFRFault(), false);
839 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000840 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000841 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000842 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000843 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000844 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000845 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000846 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000847 EXPECT_EQ(psu.hasPSKillFault(), false);
848 EXPECT_EQ(psu.hasPS12VcsFault(), false);
849 EXPECT_EQ(psu.hasPSCS12VFault(), false);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000850
Brandon Wyman82affd92021-11-24 19:12:49 +0000851 // Faults clear on READ_VIN 0 -> !0
852 // STATUS_WORD with fault bits galore!
853 expectations.statusWordValue = 0xFFFF;
854 // STATUS_INPUT with fault bits on.
855 expectations.statusInputValue = 0xFF;
856 // STATUS_MFR_SPEFIC with bits on.
857 expectations.statusMFRValue = 0xFF;
858 // STATUS_CML with bits on.
859 expectations.statusCMLValue = 0xFF;
860 // STATUS_VOUT with bits on.
861 expectations.statusVOUTValue = 0xFF;
862 // STATUS_IOUT with bits on.
863 expectations.statusIOUTValue = 0xFF;
864 // STATUS_FANS_1_2 with bits on.
865 expectations.statusFans12Value = 0xFF;
866 // STATUS_TEMPERATURE with bits on.
867 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000868
869 // All faults degltiched now. Check for false before limit above.
870 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
871 {
872 setPMBusExpectations(mockPMBus, expectations);
873 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
874 .Times(1)
875 .WillOnce(Return("0"));
876 psu.analyze();
877 }
878
Brandon Wyman82affd92021-11-24 19:12:49 +0000879 EXPECT_EQ(psu.isPresent(), true);
880 EXPECT_EQ(psu.isFaulted(), true);
881 EXPECT_EQ(psu.hasInputFault(), true);
882 EXPECT_EQ(psu.hasMFRFault(), true);
883 EXPECT_EQ(psu.hasVINUVFault(), true);
884 // True due to CML fault bits on
885 EXPECT_EQ(psu.hasCommFault(), true);
886 EXPECT_EQ(psu.hasVoutOVFault(), true);
887 EXPECT_EQ(psu.hasIoutOCFault(), true);
888 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
889 // Rely on HasVoutUVFault() to verify this sets and clears.
890 EXPECT_EQ(psu.hasVoutUVFault(), false);
891 EXPECT_EQ(psu.hasFanFault(), true);
892 EXPECT_EQ(psu.hasTempFault(), true);
Brandon Wymanc2906f42021-12-21 20:14:56 +0000893 EXPECT_EQ(psu.hasPgoodFault(), true);
Brandon Wyman82affd92021-11-24 19:12:49 +0000894 EXPECT_EQ(psu.hasPSKillFault(), true);
895 EXPECT_EQ(psu.hasPS12VcsFault(), true);
896 EXPECT_EQ(psu.hasPSCS12VFault(), true);
897 // STATUS_WORD with INPUT/VIN_UV fault bits off.
898 expectations.statusWordValue = 0xDFF7;
899 // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
900 // Insufficient Input Voltage bits off.
901 expectations.statusInputValue = 0xC7;
902 setPMBusExpectations(mockPMBus, expectations);
903 // READ_VIN back in range.
904 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
905 .Times(1)
906 .WillOnce(Return("206000"));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000907 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(0));
Brandon Wyman82affd92021-11-24 19:12:49 +0000908 psu.analyze();
909 EXPECT_EQ(psu.isPresent(), true);
910 EXPECT_EQ(psu.isFaulted(), false);
911 EXPECT_EQ(psu.hasInputFault(), false);
912 EXPECT_EQ(psu.hasMFRFault(), false);
913 EXPECT_EQ(psu.hasVINUVFault(), false);
914 EXPECT_EQ(psu.hasCommFault(), false);
915 EXPECT_EQ(psu.hasVoutOVFault(), false);
916 EXPECT_EQ(psu.hasIoutOCFault(), false);
917 EXPECT_EQ(psu.hasVoutUVFault(), false);
918 EXPECT_EQ(psu.hasFanFault(), false);
919 EXPECT_EQ(psu.hasTempFault(), false);
920 EXPECT_EQ(psu.hasPgoodFault(), false);
921 EXPECT_EQ(psu.hasPSKillFault(), false);
922 EXPECT_EQ(psu.hasPS12VcsFault(), false);
923 EXPECT_EQ(psu.hasPSCS12VFault(), false);
924
B. J. Wyman681b2a32021-04-20 22:31:22 +0000925 // TODO: Faults clear on missing/present?
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600926}
927
928TEST_F(PowerSupplyTests, UpdateInventory)
929{
930 auto bus = sdbusplus::bus::new_default();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500931
932 try
933 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000934 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500935 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
936 // If it is not present, I should not be trying to read a string
937 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
938 psu.updateInventory();
939 }
940 catch (...)
941 {
942 ADD_FAILURE() << "Should not have caught exception.";
943 }
944
945 try
946 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000947 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000948 MockedGPIOInterface* mockPresenceGPIO =
949 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000950 // GPIO read return 1 to indicate present.
951 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500952 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000953 setMissingToPresentExpects(mockPMBus, mockedUtil);
954 // STATUS_WORD 0x0000 is powered on, no faults.
955 PMBusExpectations expectations;
956 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000957 // Call to analyze will read voltage, trigger clear faults for 0 to
958 // within range.
959 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
960 .Times(1)
961 .WillOnce(Return("123456"));
Brandon Wyman391a0692021-12-08 23:28:18 +0000962 psu.analyze();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500963 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
964 psu.updateInventory();
965
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500966#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500967 EXPECT_CALL(mockPMBus, readString(_, _))
968 .WillOnce(Return("CCIN"))
969 .WillOnce(Return("PN3456"))
970 .WillOnce(Return("FN3456"))
971 .WillOnce(Return("HEADER"))
972 .WillOnce(Return("SN3456"))
973 .WillOnce(Return("FW3456"));
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500974#endif
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500975 psu.updateInventory();
976 // TODO: D-Bus mocking to verify values stored on D-Bus (???)
977 }
978 catch (...)
979 {
980 ADD_FAILURE() << "Should not have caught exception.";
981 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600982}
983
984TEST_F(PowerSupplyTests, IsPresent)
985{
986 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000987
988 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000989 MockedGPIOInterface* mockPresenceGPIO =
990 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600991 EXPECT_EQ(psu.isPresent(), false);
992
B. J. Wyman681b2a32021-04-20 22:31:22 +0000993 // Change GPIO read to return 1 to indicate present.
994 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +0000995 // Call to analyze() will update to present, that will trigger updating
996 // to the correct/latest HWMON directory, in case it changes.
997 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
998 setMissingToPresentExpects(mockPMBus, mockedUtil);
999 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1000 // Default expectations will be on, no faults.
1001 PMBusExpectations expectations;
1002 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001003 // Give it an input voltage in the 100-volt range.
1004 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1005 .Times(1)
1006 .WillOnce(Return("123456"));
B. J. Wyman681b2a32021-04-20 22:31:22 +00001007 psu.analyze();
1008 EXPECT_EQ(psu.isPresent(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001009}
1010
1011TEST_F(PowerSupplyTests, IsFaulted)
1012{
1013 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001014
1015 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001016 MockedGPIOInterface* mockPresenceGPIO =
1017 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001018 // Always return 1 to indicate present.
1019 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +00001020 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1021 setMissingToPresentExpects(mockPMBus, mockedUtil);
1022 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1023 // Default expectations will be on, no faults.
1024 PMBusExpectations expectations;
1025 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001026 // Give it an input voltage in the 100-volt range.
1027 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1028 .Times(1)
1029 .WillOnce(Return("124680"));
B. J. Wyman681b2a32021-04-20 22:31:22 +00001030 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001031 EXPECT_EQ(psu.isFaulted(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001032 // STATUS_WORD with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001033 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +00001034 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001035 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +00001036 // STATUS_MFR_SPECIFIC with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001037 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +00001038 // STATUS_CML with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001039 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +00001040 // STATUS_VOUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001041 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001042 // STATUS_IOUT with fault bits on.
1043 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001044 // STATUS_FANS_1_2 with bits on.
1045 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +00001046 // STATUS_TEMPERATURE with fault bits on.
1047 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001048 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1049 {
1050 setPMBusExpectations(mockPMBus, expectations);
1051 // Also get another read of READ_VIN.
1052 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1053 .Times(1)
1054 .WillOnce(Return("125790"));
1055 psu.analyze();
1056 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
1057 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001058}
1059
1060TEST_F(PowerSupplyTests, HasInputFault)
1061{
1062 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001063
1064 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001065 MockedGPIOInterface* mockPresenceGPIO =
1066 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001067 // Always return 1 to indicate present.
1068 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001069 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001070 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman8da35c52021-10-28 22:45:08 +00001071 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001072 PMBusExpectations expectations;
1073 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001074 // Analyze call will also need good READ_VIN value to check.
1075 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1076 .Times(1)
1077 .WillOnce(Return("201100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001078 psu.analyze();
1079 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001080 // STATUS_WORD with input fault/warn on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001081 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001082 // STATUS_INPUT with an input fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001083 expectations.statusInputValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001084 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1085 {
1086 setPMBusExpectations(mockPMBus, expectations);
1087 // Analyze call will also need good READ_VIN value to check.
1088 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1089 .Times(1)
1090 .WillOnce(Return("201200"));
1091 psu.analyze();
1092 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
1093 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001094 // STATUS_WORD with no bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001095 expectations.statusWordValue = 0;
1096 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001097 // Analyze call will also need good READ_VIN value to check.
1098 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1099 .Times(1)
1100 .WillOnce(Return("201300"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001101 psu.analyze();
1102 EXPECT_EQ(psu.hasInputFault(), false);
1103}
1104
1105TEST_F(PowerSupplyTests, HasMFRFault)
1106{
1107 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001108
1109 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001110 MockedGPIOInterface* mockPresenceGPIO =
1111 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001112 // Always return 1 to indicate present.
1113 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001114 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001115 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001116 // First return STATUS_WORD with no bits on.
Brandon Wyman8da35c52021-10-28 22:45:08 +00001117 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001118 PMBusExpectations expectations;
1119 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001120 // Analyze call will also need good READ_VIN value to check.
1121 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1122 .Times(1)
1123 .WillOnce(Return("202100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001124 psu.analyze();
1125 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001126 // Next return STATUS_WORD with MFR fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001127 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001128 // STATUS_MFR_SPEFIC with bit(s) on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001129 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001130 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1131 {
1132 setPMBusExpectations(mockPMBus, expectations);
1133 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1134 .Times(1)
1135 .WillOnce(Return("202200"));
1136 psu.analyze();
1137 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1138 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001139 // Back to no bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001140 expectations.statusWordValue = 0;
1141 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001142 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1143 .Times(1)
1144 .WillOnce(Return("202300"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001145 psu.analyze();
1146 EXPECT_EQ(psu.hasMFRFault(), false);
1147}
1148
1149TEST_F(PowerSupplyTests, HasVINUVFault)
1150{
1151 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001152
1153 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001154 MockedGPIOInterface* mockPresenceGPIO =
1155 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001156 // Always return 1 to indicate present.
1157 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001158 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001159 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman82affd92021-11-24 19:12:49 +00001160
1161 // Presence change from missing to present will trigger in1_input read in
1162 // an attempt to get CLEAR_FAULTS called. Return value ignored.
1163 // Zero to non-zero voltage, for missing/present change, triggers clear
1164 // faults call again. Return value ignored.
1165 // Fault (low voltage) to not faulted (voltage in range) triggers clear
1166 // faults call a third time.
1167
Brandon Wyman8da35c52021-10-28 22:45:08 +00001168 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001169 PMBusExpectations expectations;
1170 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001171 // Analyze call will also need good READ_VIN value to check.
1172 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1173 .Times(1)
1174 .WillOnce(Return("201100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001175 psu.analyze();
1176 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001177 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001178 expectations.statusWordValue = (status_word::VIN_UV_FAULT);
Brandon Wyman85c7bf42021-10-19 22:28:48 +00001179 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
1180 // Figure 16, and assume bits on in STATUS_INPUT.
Brandon Wymanb654c612021-11-05 23:24:51 +00001181 expectations.statusInputValue = 0x18;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001182 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1183 {
1184 setPMBusExpectations(mockPMBus, expectations);
1185 // If there is a VIN_UV fault, fake reading voltage of less than 20V
1186 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1187 .Times(1)
1188 .WillOnce(Return("19876"));
1189 psu.analyze();
1190 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1191 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001192 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001193 expectations.statusWordValue = 0;
1194 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001195 // Updates now result in clearing faults if read voltage goes from below the
1196 // minimum, to within a valid range.
1197 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1198 .Times(1)
1199 .WillOnce(Return("201300"));
1200 // Went from below minimum to within range, expect CLEAR_FAULTS.
1201 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(3));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001202 psu.analyze();
1203 EXPECT_EQ(psu.hasVINUVFault(), false);
1204}
Brandon Wyman6710ba22021-10-27 17:39:31 +00001205
1206TEST_F(PowerSupplyTests, HasVoutOVFault)
1207{
1208 auto bus = sdbusplus::bus::new_default();
1209
1210 PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName};
1211 MockedGPIOInterface* mockPresenceGPIO =
1212 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1213 // Always return 1 to indicate present.
1214 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001215 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001216 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman6710ba22021-10-27 17:39:31 +00001217 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001218 PMBusExpectations expectations;
1219 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001220 // Call to analyze will trigger read of "in1_input" to check voltage.
1221 // Initial value would be 0, so this read updates it to non-zero.
1222 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1223 .Times(1)
1224 .WillOnce(Return("202100"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001225 psu.analyze();
1226 EXPECT_EQ(psu.hasVoutOVFault(), false);
1227 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001228 expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
Brandon Wyman6710ba22021-10-27 17:39:31 +00001229 // STATUS_VOUT fault bit(s)
Brandon Wymanb654c612021-11-05 23:24:51 +00001230 expectations.statusVOUTValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001231 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1232 {
1233 setPMBusExpectations(mockPMBus, expectations);
1234 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1235 .Times(1)
1236 .WillOnce(Return("202200"));
1237 psu.analyze();
1238 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1239 }
Brandon Wyman6710ba22021-10-27 17:39:31 +00001240 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001241 expectations.statusWordValue = 0;
1242 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001243 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1244 .Times(1)
1245 .WillOnce(Return("202300"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001246 psu.analyze();
1247 EXPECT_EQ(psu.hasVoutOVFault(), false);
1248}
Brandon Wyman96893a42021-11-05 19:56:57 +00001249
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001250TEST_F(PowerSupplyTests, HasIoutOCFault)
1251{
1252 auto bus = sdbusplus::bus::new_default();
1253
1254 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
1255 MockedGPIOInterface* mockPresenceGPIO =
1256 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1257 // Always return 1 to indicate present.
1258 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001259 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001260 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001261 // STATUS_WORD 0x0000 is powered on, no faults.
1262 PMBusExpectations expectations;
1263 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001264 // Call to analyze will trigger read of "in1_input" to check voltage.
1265 // Initial value would be 0, so this read updates it to non-zero.
1266 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1267 .Times(1)
1268 .WillOnce(Return("203100"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001269 psu.analyze();
1270 EXPECT_EQ(psu.hasIoutOCFault(), false);
1271 // Turn fault on.
1272 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1273 // STATUS_IOUT fault bit(s)
1274 expectations.statusIOUTValue = 0x88;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001275 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1276 {
1277 setPMBusExpectations(mockPMBus, expectations);
1278 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1279 .Times(1)
1280 .WillOnce(Return("203200"));
1281 psu.analyze();
1282 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1283 }
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001284 // Back to no fault bits on in STATUS_WORD
1285 expectations.statusWordValue = 0;
1286 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001287 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1288 .Times(1)
1289 .WillOnce(Return("203300"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001290 psu.analyze();
1291 EXPECT_EQ(psu.hasIoutOCFault(), false);
1292}
1293
Brandon Wyman2cf46942021-10-28 19:09:16 +00001294TEST_F(PowerSupplyTests, HasVoutUVFault)
1295{
1296 auto bus = sdbusplus::bus::new_default();
1297
1298 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
1299 MockedGPIOInterface* mockPresenceGPIO =
1300 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1301 // Always return 1 to indicate present.
1302 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001303 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001304 setMissingToPresentExpects(mockPMBus, mockedUtil);
1305 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wyman2cf46942021-10-28 19:09:16 +00001306 PMBusExpectations expectations;
1307 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001308 // Call to analyze will trigger read of "in1_input" to check voltage.
1309 // Initial value would be 0, so this read updates it to non-zero.
1310 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1311 .Times(1)
1312 .WillOnce(Return("204100"));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001313 psu.analyze();
1314 EXPECT_EQ(psu.hasVoutUVFault(), false);
1315 // Turn fault on.
1316 expectations.statusWordValue = (status_word::VOUT_FAULT);
1317 // STATUS_VOUT fault bit(s)
1318 expectations.statusVOUTValue = 0x30;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001319 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1320 {
1321 setPMBusExpectations(mockPMBus, expectations);
1322 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1323 .Times(1)
1324 .WillOnce(Return("204200"));
1325 psu.analyze();
1326 EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1327 }
Brandon Wyman2cf46942021-10-28 19:09:16 +00001328 // Back to no fault bits on in STATUS_WORD
1329 expectations.statusWordValue = 0;
1330 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001331 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1332 .Times(1)
1333 .WillOnce(Return("204300"));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001334 psu.analyze();
1335 EXPECT_EQ(psu.hasVoutUVFault(), false);
1336}
1337
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001338TEST_F(PowerSupplyTests, HasFanFault)
1339{
1340 auto bus = sdbusplus::bus::new_default();
1341
1342 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
1343 MockedGPIOInterface* mockPresenceGPIO =
1344 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1345 // Always return 1 to indicate present.
1346 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001347 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001348 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001349 // STATUS_WORD 0x0000 is powered on, no faults.
1350 PMBusExpectations expectations;
1351 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001352 // Call to analyze will trigger read of "in1_input" to check voltage.
1353 // Initial value would be 0, so this read updates it to non-zero.
1354 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1355 .Times(1)
1356 .WillOnce(Return("205100"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001357 psu.analyze();
1358 EXPECT_EQ(psu.hasFanFault(), false);
1359 // Turn fault on.
1360 expectations.statusWordValue = (status_word::FAN_FAULT);
1361 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
1362 expectations.statusFans12Value = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001363 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1364 {
1365 setPMBusExpectations(mockPMBus, expectations);
1366 // Call to analyze will trigger read of "in1_input" to check voltage.
1367 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1368 .Times(1)
1369 .WillOnce(Return("205200"));
1370 psu.analyze();
1371 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1372 }
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001373 // Back to no fault bits on in STATUS_WORD
1374 expectations.statusWordValue = 0;
1375 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001376 // Call to analyze will trigger read of "in1_input" to check voltage.
1377 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1378 .Times(1)
1379 .WillOnce(Return("205300"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001380 psu.analyze();
1381 EXPECT_EQ(psu.hasFanFault(), false);
1382}
1383
Brandon Wyman96893a42021-11-05 19:56:57 +00001384TEST_F(PowerSupplyTests, HasTempFault)
1385{
1386 auto bus = sdbusplus::bus::new_default();
1387
1388 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
1389 MockedGPIOInterface* mockPresenceGPIO =
1390 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1391 // Always return 1 to indicate present.
1392 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman96893a42021-11-05 19:56:57 +00001393 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001394 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman96893a42021-11-05 19:56:57 +00001395 // STATUS_WORD 0x0000 is powered on, no faults.
1396 PMBusExpectations expectations;
1397 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001398 // Call to analyze will trigger read of "in1_input" to check voltage.
1399 // Initial value would be 0, so this read updates it to non-zero.
1400 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1401 .Times(1)
1402 .WillOnce(Return("206100"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001403 psu.analyze();
1404 EXPECT_EQ(psu.hasTempFault(), false);
1405 // Turn fault on.
1406 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
1407 // STATUS_TEMPERATURE fault bit on (OT Fault)
1408 expectations.statusTempValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001409 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1410 {
1411 setPMBusExpectations(mockPMBus, expectations);
1412 // Call to analyze will trigger read of "in1_input" to check voltage.
1413 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1414 .Times(1)
1415 .WillOnce(Return("206200"));
1416 psu.analyze();
1417 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1418 }
Brandon Wyman96893a42021-11-05 19:56:57 +00001419 // Back to no fault bits on in STATUS_WORD
1420 expectations.statusWordValue = 0;
1421 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001422 // Call to analyze will trigger read of "in1_input" to check voltage.
1423 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1424 .Times(1)
1425 .WillOnce(Return("206300"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001426 psu.analyze();
1427 EXPECT_EQ(psu.hasTempFault(), false);
1428}
Brandon Wyman2916ea52021-11-06 03:31:18 +00001429
1430TEST_F(PowerSupplyTests, HasPgoodFault)
1431{
1432 auto bus = sdbusplus::bus::new_default();
1433
1434 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, PSUGPIOLineName};
1435 MockedGPIOInterface* mockPresenceGPIO =
1436 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1437 // Always return 1 to indicate present.
1438 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001439 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001440 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman2916ea52021-11-06 03:31:18 +00001441 // STATUS_WORD 0x0000 is powered on, no faults.
1442 PMBusExpectations expectations;
1443 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001444 // Call to analyze will trigger read of "in1_input" to check voltage.
1445 // Initial value would be 0, so this read updates it to non-zero.
1446 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1447 .Times(1)
1448 .WillOnce(Return("207100"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001449 psu.analyze();
1450 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman391a0692021-12-08 23:28:18 +00001451 // Setup another expectation of no faults.
1452 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001453 // Call to analyze will trigger read of "in1_input" to check voltage.
1454 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1455 .Times(1)
1456 .WillOnce(Return("207200"));
1457 psu.analyze();
1458 EXPECT_EQ(psu.hasPgoodFault(), false);
1459 // Setup another expectation of no faults.
1460 setPMBusExpectations(mockPMBus, expectations);
1461 // Call to analyze will trigger read of "in1_input" to check voltage.
1462 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1463 .Times(1)
1464 .WillOnce(Return("207300"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001465 psu.analyze();
1466 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +00001467 // Turn PGOOD# off (fault on).
1468 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
1469 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001470 // Call to analyze will trigger read of "in1_input" to check voltage.
1471 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1472 .Times(1)
1473 .WillOnce(Return("207400"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001474 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001475 // Expect false until reaches DEGLITCH_LIMIT
1476 EXPECT_EQ(psu.hasPgoodFault(), false);
1477 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001478 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1479 .Times(1)
1480 .WillOnce(Return("207500"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001481 psu.analyze();
1482 // Expect false until reaches DEGLITCH_LIMIT
1483 EXPECT_EQ(psu.hasPgoodFault(), false);
1484 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001485 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1486 .Times(1)
1487 .WillOnce(Return("207600"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001488 psu.analyze();
1489 // DEGLITCH_LIMIT reached, expect true.
Brandon Wyman2916ea52021-11-06 03:31:18 +00001490 EXPECT_EQ(psu.hasPgoodFault(), true);
1491 // Back to no fault bits on in STATUS_WORD
1492 expectations.statusWordValue = 0;
1493 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001494 // Call to analyze will trigger read of "in1_input" to check voltage.
1495 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1496 .Times(1)
1497 .WillOnce(Return("207700"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001498 psu.analyze();
1499 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman82affd92021-11-24 19:12:49 +00001500
Brandon Wyman2916ea52021-11-06 03:31:18 +00001501 // Turn OFF bit on
1502 expectations.statusWordValue = (status_word::UNIT_IS_OFF);
1503 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001504 // Call to analyze will trigger read of "in1_input" to check voltage.
1505 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1506 .Times(1)
1507 .WillOnce(Return("208100"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001508 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001509 EXPECT_EQ(psu.hasPgoodFault(), false);
1510 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001511 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1512 .Times(1)
1513 .WillOnce(Return("208200"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001514 psu.analyze();
1515 EXPECT_EQ(psu.hasPgoodFault(), false);
1516 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001517 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1518 .Times(1)
1519 .WillOnce(Return("208300"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001520 psu.analyze();
Brandon Wyman2916ea52021-11-06 03:31:18 +00001521 EXPECT_EQ(psu.hasPgoodFault(), true);
1522 // Back to no fault bits on in STATUS_WORD
1523 expectations.statusWordValue = 0;
1524 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001525 // Call to analyze will trigger read of "in1_input" to check voltage.
1526 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1527 .Times(1)
1528 .WillOnce(Return("208400"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001529 psu.analyze();
1530 EXPECT_EQ(psu.hasPgoodFault(), false);
1531}
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001532
1533TEST_F(PowerSupplyTests, HasPSKillFault)
1534{
1535 auto bus = sdbusplus::bus::new_default();
1536 PowerSupply psu{bus, PSUInventoryPath, 4, 0x6d, PSUGPIOLineName};
1537 MockedGPIOInterface* mockPresenceGPIO =
1538 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1539 // Always return 1 to indicate present.
1540 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001541 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001542 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001543 // STATUS_WORD 0x0000 is powered on, no faults.
1544 PMBusExpectations expectations;
1545 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001546 // Call to analyze will trigger read of "in1_input" to check voltage.
1547 // Initial value would be 0, so this read updates it to non-zero.
1548 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1549 .Times(1)
1550 .WillOnce(Return("208100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001551 psu.analyze();
1552 EXPECT_EQ(psu.hasPSKillFault(), false);
1553 // Next return STATUS_WORD with MFR fault bit on.
1554 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1555 // STATUS_MFR_SPEFIC with bit(s) on.
1556 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001557
1558 // Deglitching faults, false until read the fault bits on up to the limit.
1559 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1560 {
1561 setPMBusExpectations(mockPMBus, expectations);
1562 // Call to analyze will trigger read of "in1_input" to check voltage.
1563 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1564 .Times(1)
1565 .WillOnce(Return("208200"));
1566 psu.analyze();
1567 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1568 }
1569
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001570 // Back to no bits on in STATUS_WORD
1571 expectations.statusWordValue = 0;
1572 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001573 // Call to analyze will trigger read of "in1_input" to check voltage.
1574 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1575 .Times(1)
1576 .WillOnce(Return("208300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001577 psu.analyze();
1578 EXPECT_EQ(psu.hasPSKillFault(), false);
1579 // Next return STATUS_WORD with MFR fault bit on.
1580 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1581 // STATUS_MFR_SPEFIC with bit 4 on.
1582 expectations.statusMFRValue = 0x10;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001583
1584 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1585 {
1586 setPMBusExpectations(mockPMBus, expectations);
1587 // Call to analyze will trigger read of "in1_input" to check voltage.
1588 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1589 .Times(1)
1590 .WillOnce(Return("208400"));
1591 psu.analyze();
1592 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1593 }
1594
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001595 // Back to no bits on in STATUS_WORD
1596 expectations.statusWordValue = 0;
1597 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001598 // Call to analyze will trigger read of "in1_input" to check voltage.
1599 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1600 .Times(1)
1601 .WillOnce(Return("208500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001602 psu.analyze();
1603 EXPECT_EQ(psu.hasPSKillFault(), false);
1604}
1605
1606TEST_F(PowerSupplyTests, HasPS12VcsFault)
1607{
1608 auto bus = sdbusplus::bus::new_default();
1609 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6e, PSUGPIOLineName};
1610 MockedGPIOInterface* mockPresenceGPIO =
1611 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1612 // Always return 1 to indicate present.
1613 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001614 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001615 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001616 // STATUS_WORD 0x0000 is powered on, no faults.
1617 PMBusExpectations expectations;
1618 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001619 // Call to analyze will trigger read of "in1_input" to check voltage.
1620 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1621 .Times(1)
1622 .WillOnce(Return("209100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001623 psu.analyze();
1624 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1625 // Next return STATUS_WORD with MFR fault bit on.
1626 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1627 // STATUS_MFR_SPEFIC with bit(s) on.
1628 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001629
1630 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1631 {
1632 setPMBusExpectations(mockPMBus, expectations);
1633 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1634 .Times(1)
1635 .WillOnce(Return("209200"));
1636 psu.analyze();
1637 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1638 }
1639
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001640 // Back to no bits on in STATUS_WORD
1641 expectations.statusWordValue = 0;
1642 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001643 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1644 .Times(1)
1645 .WillOnce(Return("209300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001646 psu.analyze();
1647 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1648 // Next return STATUS_WORD with MFR fault bit on.
1649 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1650 // STATUS_MFR_SPEFIC with bit 6 on.
1651 expectations.statusMFRValue = 0x40;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001652
1653 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1654 {
1655 setPMBusExpectations(mockPMBus, expectations);
1656 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1657 .Times(1)
1658 .WillOnce(Return("209400"));
1659 psu.analyze();
1660 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1661 }
1662
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001663 // Back to no bits on in STATUS_WORD
1664 expectations.statusWordValue = 0;
1665 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001666 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1667 .Times(1)
1668 .WillOnce(Return("209500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001669 psu.analyze();
1670 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1671}
1672
1673TEST_F(PowerSupplyTests, HasPSCS12VFault)
1674{
1675 auto bus = sdbusplus::bus::new_default();
1676 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f, PSUGPIOLineName};
1677 MockedGPIOInterface* mockPresenceGPIO =
1678 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1679 // Always return 1 to indicate present.
1680 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001681 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001682 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001683 // STATUS_WORD 0x0000 is powered on, no faults.
1684 PMBusExpectations expectations;
1685 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001686 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1687 .Times(1)
1688 .WillOnce(Return("209100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001689 psu.analyze();
1690 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1691 // Next return STATUS_WORD with MFR fault bit on.
1692 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1693 // STATUS_MFR_SPEFIC with bit(s) on.
1694 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001695
1696 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1697 {
1698 setPMBusExpectations(mockPMBus, expectations);
1699 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1700 .Times(1)
1701 .WillOnce(Return("209200"));
1702 psu.analyze();
1703 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1704 }
1705
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001706 // Back to no bits on in STATUS_WORD
1707 expectations.statusWordValue = 0;
1708 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001709 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1710 .Times(1)
1711 .WillOnce(Return("209300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001712 psu.analyze();
1713 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1714 // Next return STATUS_WORD with MFR fault bit on.
1715 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1716 // STATUS_MFR_SPEFIC with bit 7 on.
1717 expectations.statusMFRValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001718
1719 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1720 {
1721 setPMBusExpectations(mockPMBus, expectations);
1722 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1723 .Times(1)
1724 .WillOnce(Return("209400"));
1725 psu.analyze();
1726 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1727 }
1728
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001729 // Back to no bits on in STATUS_WORD
1730 expectations.statusWordValue = 0;
1731 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001732 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1733 .Times(1)
1734 .WillOnce(Return("209500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001735 psu.analyze();
1736 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1737}