blob: c556f82ce71ea8f7d4b265996e89589794a39f80 [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{
Brandon Wyman32453e92021-12-15 19:00:14 +000041 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000042 .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 Wyman32453e92021-12-15 19:00:14 +000050 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000051 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000052 .WillOnce(Return(expectations.statusInputValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000053 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000054 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000055 .WillOnce(Return(expectations.statusMFRValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000056 EXPECT_CALL(mockPMBus, read(STATUS_CML, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000057 .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"));
Brandon Wyman32453e92021-12-15 19:00:14 +000063 EXPECT_CALL(mockPMBus, read("status0_vout", _, _))
Brandon Wyman6710ba22021-10-27 17:39:31 +000064 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000065 .WillOnce(Return(expectations.statusVOUTValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000066 EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _, _))
Brandon Wymanb10b3be2021-11-09 22:12:15 +000067 .Times(1)
68 .WillOnce(Return(expectations.statusIOUTValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000069 EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _, _))
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +000070 .Times(1)
71 .WillOnce(Return(expectations.statusFans12Value));
Brandon Wyman32453e92021-12-15 19:00:14 +000072 EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _, _))
Brandon Wyman96893a42021-11-05 19:56:57 +000073 .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.
Brandon Wyman32453e92021-12-15 19:00:14 +0000110 EXPECT_CALL(pmbus, read(READ_VIN, _, _))
Brandon Wyman82affd92021-11-24 19:12:49 +0000111 .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 Wyman32453e92021-12-15 19:00:14 +0000314 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000315 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
Brandon Wyman32453e92021-12-15 19:00:14 +0000367 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _))
368 .Times(1)
369 .WillOnce(Return(3));
Brandon Wyman82affd92021-11-24 19:12:49 +0000370 psu2.analyze();
371 // Should remain present, no longer be faulted, no input fault, no
372 // VIN_UV fault. Nothing else should change.
373 EXPECT_EQ(psu2.isPresent(), true);
374 EXPECT_EQ(psu2.isFaulted(), false);
375 EXPECT_EQ(psu2.hasInputFault(), false);
376 EXPECT_EQ(psu2.hasVINUVFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000377 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600378
Brandon Wyman32453e92021-12-15 19:00:14 +0000379 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000380 psu2.clearFaults();
381
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600382 // STATUS_WORD MFR fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000383 {
384 // First need it to return good status, then the fault
385 PMBusExpectations expectations;
386 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000387 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
388 .Times(1)
389 .WillOnce(Return("210000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000390 psu2.analyze();
391 // Now STATUS_WORD with MFR fault bit on.
392 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
393 // STATUS_MFR bits on.
394 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000395
396 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
397 {
398 setPMBusExpectations(mockPMBus, expectations);
399 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
400 .Times(1)
401 .WillOnce(Return("211000"));
402 psu2.analyze();
403 EXPECT_EQ(psu2.isPresent(), true);
404 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
405 EXPECT_EQ(psu2.hasInputFault(), false);
406 EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT);
407 EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT);
408 EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
409 EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
410 EXPECT_EQ(psu2.hasVINUVFault(), false);
411 EXPECT_EQ(psu2.hasCommFault(), false);
412 EXPECT_EQ(psu2.hasVoutOVFault(), false);
413 EXPECT_EQ(psu2.hasIoutOCFault(), false);
414 EXPECT_EQ(psu2.hasVoutUVFault(), false);
415 EXPECT_EQ(psu2.hasFanFault(), false);
416 EXPECT_EQ(psu2.hasTempFault(), false);
417 EXPECT_EQ(psu2.hasPgoodFault(), false);
418 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000419 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600420
Brandon Wyman32453e92021-12-15 19:00:14 +0000421 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000422 psu2.clearFaults();
Brandon Wyman96893a42021-11-05 19:56:57 +0000423 // Temperature fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000424 {
425 // First STATUS_WORD with no bits set, then with temperature fault.
426 PMBusExpectations expectations;
427 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000428 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
429 .Times(1)
430 .WillOnce(Return("212000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000431 psu2.analyze();
432 // STATUS_WORD with temperature fault bit on.
433 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
Brandon Wyman96893a42021-11-05 19:56:57 +0000434 // STATUS_TEMPERATURE with fault bit(s) on.
435 expectations.statusTempValue = 0x10;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000436 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
437 {
438 setPMBusExpectations(mockPMBus, expectations);
439 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
440 .Times(1)
441 .WillOnce(Return("213000"));
442 psu2.analyze();
443 EXPECT_EQ(psu2.isPresent(), true);
444 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
445 EXPECT_EQ(psu2.hasInputFault(), false);
446 EXPECT_EQ(psu2.hasMFRFault(), false);
447 EXPECT_EQ(psu2.hasVINUVFault(), false);
448 EXPECT_EQ(psu2.hasCommFault(), false);
449 EXPECT_EQ(psu2.hasVoutOVFault(), false);
450 EXPECT_EQ(psu2.hasIoutOCFault(), false);
451 EXPECT_EQ(psu2.hasVoutUVFault(), false);
452 EXPECT_EQ(psu2.hasFanFault(), false);
453 EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT);
454 EXPECT_EQ(psu2.hasPgoodFault(), false);
455 EXPECT_EQ(psu2.hasPSKillFault(), false);
456 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
457 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
458 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000459 }
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000460
Brandon Wyman32453e92021-12-15 19:00:14 +0000461 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000462 psu2.clearFaults();
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000463 // CML fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000464 {
465 // First STATUS_WORD wit no bits set, then with CML fault.
466 PMBusExpectations expectations;
467 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000468 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
469 .Times(1)
470 .WillOnce(Return("214000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000471 psu2.analyze();
472 // STATUS_WORD with CML fault bit on.
473 expectations.statusWordValue = (status_word::CML_FAULT);
474 // Turn on STATUS_CML fault bit(s)
475 expectations.statusCMLValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000476 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
477 {
478 setPMBusExpectations(mockPMBus, expectations);
479 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
480 .Times(1)
481 .WillOnce(Return("215000"));
482 psu2.analyze();
483 EXPECT_EQ(psu2.isPresent(), true);
484 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
485 EXPECT_EQ(psu2.hasCommFault(), x >= DEGLITCH_LIMIT);
486 EXPECT_EQ(psu2.hasInputFault(), false);
487 EXPECT_EQ(psu2.hasMFRFault(), false);
488 EXPECT_EQ(psu2.hasVINUVFault(), false);
489 EXPECT_EQ(psu2.hasVoutOVFault(), false);
490 EXPECT_EQ(psu2.hasIoutOCFault(), false);
491 EXPECT_EQ(psu2.hasVoutUVFault(), false);
492 EXPECT_EQ(psu2.hasFanFault(), false);
493 EXPECT_EQ(psu2.hasTempFault(), false);
494 EXPECT_EQ(psu2.hasPgoodFault(), false);
495 EXPECT_EQ(psu2.hasPSKillFault(), false);
496 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
497 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
498 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000499 }
Brandon Wyman6710ba22021-10-27 17:39:31 +0000500
Brandon Wyman32453e92021-12-15 19:00:14 +0000501 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000502 psu2.clearFaults();
Brandon Wyman6710ba22021-10-27 17:39:31 +0000503 // VOUT_OV_FAULT fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000504 {
505 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
506 PMBusExpectations expectations;
507 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000508 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
509 .Times(1)
510 .WillOnce(Return("216000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000511 psu2.analyze();
512 // STATUS_WORD with VOUT/VOUT_OV fault.
513 expectations.statusWordValue =
514 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
515 // Turn on STATUS_VOUT fault bit(s)
516 expectations.statusVOUTValue = 0xA0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000517 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
518 {
519 // STATUS_TEMPERATURE don't care (default)
520 setPMBusExpectations(mockPMBus, expectations);
521 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
522 .Times(1)
523 .WillOnce(Return("217000"));
524 psu2.analyze();
525 EXPECT_EQ(psu2.isPresent(), true);
526 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
527 EXPECT_EQ(psu2.hasInputFault(), false);
528 EXPECT_EQ(psu2.hasMFRFault(), false);
529 EXPECT_EQ(psu2.hasVINUVFault(), false);
530 EXPECT_EQ(psu2.hasCommFault(), false);
531 EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
532 EXPECT_EQ(psu2.hasVoutUVFault(), false);
533 EXPECT_EQ(psu2.hasIoutOCFault(), false);
534 EXPECT_EQ(psu2.hasFanFault(), false);
535 EXPECT_EQ(psu2.hasTempFault(), false);
536 EXPECT_EQ(psu2.hasPgoodFault(), false);
537 EXPECT_EQ(psu2.hasPSKillFault(), false);
538 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
539 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
540 }
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000541 }
542
543 // IOUT_OC_FAULT fault
544 {
545 // First STATUS_WORD with no bits set, then with IOUT_OC fault.
546 PMBusExpectations expectations;
547 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000548 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
549 .Times(1)
550 .WillOnce(Return("218000"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000551 psu2.analyze();
552 // STATUS_WORD with IOUT_OC fault.
553 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
554 // Turn on STATUS_IOUT fault bit(s)
555 expectations.statusIOUTValue = 0x88;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000556 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
557 {
558 setPMBusExpectations(mockPMBus, expectations);
559 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
560 .Times(1)
561 .WillOnce(Return("219000"));
562 psu2.analyze();
563 EXPECT_EQ(psu2.isPresent(), true);
564 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
565 EXPECT_EQ(psu2.hasInputFault(), false);
566 EXPECT_EQ(psu2.hasMFRFault(), false);
567 EXPECT_EQ(psu2.hasVINUVFault(), false);
568 EXPECT_EQ(psu2.hasCommFault(), false);
569 EXPECT_EQ(psu2.hasVoutOVFault(), false);
570 EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
571 EXPECT_EQ(psu2.hasVoutUVFault(), false);
572 EXPECT_EQ(psu2.hasFanFault(), false);
573 EXPECT_EQ(psu2.hasTempFault(), false);
574 EXPECT_EQ(psu2.hasPgoodFault(), false);
575 EXPECT_EQ(psu2.hasPSKillFault(), false);
576 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
577 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
578 }
Brandon Wyman2cf46942021-10-28 19:09:16 +0000579 }
580
581 // VOUT_UV_FAULT
582 {
583 // First STATUS_WORD with no bits set, then with VOUT fault.
584 PMBusExpectations expectations;
585 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000586 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
587 .Times(1)
588 .WillOnce(Return("220000"));
Brandon Wyman2cf46942021-10-28 19:09:16 +0000589 psu2.analyze();
590 // Change STATUS_WORD to indicate VOUT fault.
591 expectations.statusWordValue = (status_word::VOUT_FAULT);
592 // Turn on STATUS_VOUT fault bit(s)
593 expectations.statusVOUTValue = 0x30;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000594 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
595 {
596 setPMBusExpectations(mockPMBus, expectations);
597 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
598 .Times(1)
599 .WillOnce(Return("221000"));
600 psu2.analyze();
601 EXPECT_EQ(psu2.isPresent(), true);
602 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
603 EXPECT_EQ(psu2.hasInputFault(), false);
604 EXPECT_EQ(psu2.hasMFRFault(), false);
605 EXPECT_EQ(psu2.hasVINUVFault(), false);
606 EXPECT_EQ(psu2.hasCommFault(), false);
607 EXPECT_EQ(psu2.hasVoutOVFault(), false);
608 EXPECT_EQ(psu2.hasIoutOCFault(), false);
609 EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
610 EXPECT_EQ(psu2.hasFanFault(), false);
611 EXPECT_EQ(psu2.hasTempFault(), false);
612 EXPECT_EQ(psu2.hasPgoodFault(), false);
613 EXPECT_EQ(psu2.hasPSKillFault(), false);
614 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
615 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
616 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000617 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600618
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000619 // Fan fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000620 {
621 // First STATUS_WORD with no bits set, then with fan fault.
622 PMBusExpectations expectations;
623 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000624 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
625 .Times(1)
626 .WillOnce(Return("222000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000627 psu2.analyze();
628 expectations.statusWordValue = (status_word::FAN_FAULT);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000629 // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
630 expectations.statusFans12Value = 0xA0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000631
632 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
633 {
634 setPMBusExpectations(mockPMBus, expectations);
635 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
636 .Times(1)
637 .WillOnce(Return("223000"));
638 psu2.analyze();
639 EXPECT_EQ(psu2.isPresent(), true);
640 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
641 EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT);
642 EXPECT_EQ(psu2.hasInputFault(), false);
643 EXPECT_EQ(psu2.hasMFRFault(), false);
644 EXPECT_EQ(psu2.hasVINUVFault(), false);
645 EXPECT_EQ(psu2.hasCommFault(), false);
646 EXPECT_EQ(psu2.hasVoutOVFault(), false);
647 EXPECT_EQ(psu2.hasIoutOCFault(), false);
648 EXPECT_EQ(psu2.hasVoutUVFault(), false);
649 EXPECT_EQ(psu2.hasTempFault(), false);
650 EXPECT_EQ(psu2.hasPgoodFault(), false);
651 EXPECT_EQ(psu2.hasPSKillFault(), false);
652 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
653 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
654 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000655 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000656
Brandon Wyman06ca4592021-12-06 22:52:23 +0000657 // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000658 {
Brandon Wyman2916ea52021-11-06 03:31:18 +0000659 // First STATUS_WORD with no bits set.
660 PMBusExpectations expectations;
661 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000662 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
663 .Times(1)
664 .WillOnce(Return("123000"));
Brandon Wyman2916ea52021-11-06 03:31:18 +0000665 psu2.analyze();
666 EXPECT_EQ(psu2.isFaulted(), false);
667 // POWER_GOOD# inactive, and OFF bit on.
668 expectations.statusWordValue =
669 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
Brandon Wyman06ca4592021-12-06 22:52:23 +0000670 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
671 {
672 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
673 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
674 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000675 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
676 .Times(1)
677 .WillOnce(Return("124000"));
Brandon Wyman06ca4592021-12-06 22:52:23 +0000678 psu2.analyze();
679 EXPECT_EQ(psu2.isPresent(), true);
Brandon Wymanc2906f42021-12-21 20:14:56 +0000680 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
Brandon Wyman06ca4592021-12-06 22:52:23 +0000681 EXPECT_EQ(psu2.hasInputFault(), false);
682 EXPECT_EQ(psu2.hasMFRFault(), false);
683 EXPECT_EQ(psu2.hasVINUVFault(), false);
684 EXPECT_EQ(psu2.hasCommFault(), false);
685 EXPECT_EQ(psu2.hasVoutOVFault(), false);
686 EXPECT_EQ(psu2.hasVoutUVFault(), false);
687 EXPECT_EQ(psu2.hasIoutOCFault(), false);
688 EXPECT_EQ(psu2.hasFanFault(), false);
689 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman32453e92021-12-15 19:00:14 +0000690 EXPECT_EQ(psu2.hasPgoodFault(), x >= DEGLITCH_LIMIT);
Brandon Wyman06ca4592021-12-06 22:52:23 +0000691 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000692 }
693
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600694 // TODO: ReadFailure
695}
696
Brandon Wyman59a35792020-06-04 12:37:40 -0500697TEST_F(PowerSupplyTests, OnOffConfig)
698{
699 auto bus = sdbusplus::bus::new_default();
700 uint8_t data = 0x15;
701
702 // Test where PSU is NOT present
703 try
704 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000705 // Assume GPIO presence, not inventory presence?
706 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
707
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000708 MockedGPIOInterface* mockPresenceGPIO =
709 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000710 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
Brandon Wyman59a35792020-06-04 12:37:40 -0500711 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000712 // Constructor should set initial presence, default read returns 0.
Brandon Wyman59a35792020-06-04 12:37:40 -0500713 // If it is not present, I should not be trying to write to it.
714 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
715 psu.onOffConfig(data);
716 }
717 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000718 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500719
720 // Test where PSU is present
721 try
722 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000723 // Assume GPIO presence, not inventory presence?
724 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000725 MockedGPIOInterface* mockPresenceGPIO =
726 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman391a0692021-12-08 23:28:18 +0000727 // There will potentially be multiple calls, we want it to continue
728 // returning 1 for the GPIO read to keep the power supply present.
729 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman59a35792020-06-04 12:37:40 -0500730 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000731 setMissingToPresentExpects(mockPMBus, mockedUtil);
732 // If I am calling analyze(), I should probably give it good data.
733 // STATUS_WORD 0x0000 is powered on, no faults.
734 PMBusExpectations expectations;
735 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000736 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
737 .Times(1)
738 .WillOnce(Return("205000"));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000739 psu.analyze();
Brandon Wyman391a0692021-12-08 23:28:18 +0000740 // I definitely should be writting ON_OFF_CONFIG if I call the function
741 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
742 Type::HwmonDeviceDebug))
Brandon Wyman59a35792020-06-04 12:37:40 -0500743 .Times(1);
744 psu.onOffConfig(data);
745 }
746 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000747 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500748}
749
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600750TEST_F(PowerSupplyTests, ClearFaults)
751{
752 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000753 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000754 MockedGPIOInterface* mockPresenceGPIO =
755 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000756 // Always return 1 to indicate present.
757 // Each analyze() call will trigger a read of the presence GPIO.
758 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000759 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000760 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000761 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000762 PMBusExpectations expectations;
763 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000764 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
765 .Times(1)
766 .WillOnce(Return("207000"));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000767 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600768 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);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000773 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000774 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000775 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000776 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000777 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000778 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000779 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000780 EXPECT_EQ(psu.hasPSKillFault(), false);
781 EXPECT_EQ(psu.hasPS12VcsFault(), false);
782 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000783
Brandon Wymanf07bc792021-10-12 19:00:35 +0000784 // STATUS_WORD with fault bits galore!
Brandon Wymanb654c612021-11-05 23:24:51 +0000785 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000786 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000787 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000788 // STATUS_MFR_SPEFIC with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000789 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000790 // STATUS_CML with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000791 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000792 // STATUS_VOUT with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000793 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000794 // STATUS_IOUT with bits on.
795 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000796 // STATUS_FANS_1_2 with bits on.
797 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000798 // STATUS_TEMPERATURE with bits on.
799 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000800
801 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
802 {
803 setPMBusExpectations(mockPMBus, expectations);
804 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
805 .Times(1)
806 .WillOnce(Return("0"));
807 psu.analyze();
808 EXPECT_EQ(psu.isPresent(), true);
809 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
810 // Rely on HasVoutUVFault() to verify this sets and clears.
811 EXPECT_EQ(psu.hasVoutUVFault(), false);
812 // All faults are deglitched up to DEGLITCH_LIMIT
813 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
814 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
815 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
816 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
817 EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT);
818 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
819 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
820 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
821 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
822 EXPECT_EQ(psu.hasPgoodFault(), x >= DEGLITCH_LIMIT);
823 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
824 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
825 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
826 }
827
Brandon Wyman32453e92021-12-15 19:00:14 +0000828 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _))
829 .Times(1)
830 .WillOnce(Return(207000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600831 psu.clearFaults();
832 EXPECT_EQ(psu.isPresent(), true);
833 EXPECT_EQ(psu.isFaulted(), false);
834 EXPECT_EQ(psu.hasInputFault(), false);
835 EXPECT_EQ(psu.hasMFRFault(), false);
836 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000837 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000838 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000839 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000840 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000841 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000842 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000843 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000844 EXPECT_EQ(psu.hasPSKillFault(), false);
845 EXPECT_EQ(psu.hasPS12VcsFault(), false);
846 EXPECT_EQ(psu.hasPSCS12VFault(), false);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000847
Brandon Wyman82affd92021-11-24 19:12:49 +0000848 // Faults clear on READ_VIN 0 -> !0
849 // STATUS_WORD with fault bits galore!
850 expectations.statusWordValue = 0xFFFF;
851 // STATUS_INPUT with fault bits on.
852 expectations.statusInputValue = 0xFF;
853 // STATUS_MFR_SPEFIC with bits on.
854 expectations.statusMFRValue = 0xFF;
855 // STATUS_CML with bits on.
856 expectations.statusCMLValue = 0xFF;
857 // STATUS_VOUT with bits on.
858 expectations.statusVOUTValue = 0xFF;
859 // STATUS_IOUT with bits on.
860 expectations.statusIOUTValue = 0xFF;
861 // STATUS_FANS_1_2 with bits on.
862 expectations.statusFans12Value = 0xFF;
863 // STATUS_TEMPERATURE with bits on.
864 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000865
866 // All faults degltiched now. Check for false before limit above.
867 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
868 {
869 setPMBusExpectations(mockPMBus, expectations);
870 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
871 .Times(1)
872 .WillOnce(Return("0"));
873 psu.analyze();
874 }
875
Brandon Wyman82affd92021-11-24 19:12:49 +0000876 EXPECT_EQ(psu.isPresent(), true);
877 EXPECT_EQ(psu.isFaulted(), true);
878 EXPECT_EQ(psu.hasInputFault(), true);
879 EXPECT_EQ(psu.hasMFRFault(), true);
880 EXPECT_EQ(psu.hasVINUVFault(), true);
881 // True due to CML fault bits on
882 EXPECT_EQ(psu.hasCommFault(), true);
883 EXPECT_EQ(psu.hasVoutOVFault(), true);
884 EXPECT_EQ(psu.hasIoutOCFault(), true);
885 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
886 // Rely on HasVoutUVFault() to verify this sets and clears.
887 EXPECT_EQ(psu.hasVoutUVFault(), false);
888 EXPECT_EQ(psu.hasFanFault(), true);
889 EXPECT_EQ(psu.hasTempFault(), true);
Brandon Wymanc2906f42021-12-21 20:14:56 +0000890 EXPECT_EQ(psu.hasPgoodFault(), true);
Brandon Wyman82affd92021-11-24 19:12:49 +0000891 EXPECT_EQ(psu.hasPSKillFault(), true);
892 EXPECT_EQ(psu.hasPS12VcsFault(), true);
893 EXPECT_EQ(psu.hasPSCS12VFault(), true);
894 // STATUS_WORD with INPUT/VIN_UV fault bits off.
895 expectations.statusWordValue = 0xDFF7;
896 // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
897 // Insufficient Input Voltage bits off.
898 expectations.statusInputValue = 0xC7;
899 setPMBusExpectations(mockPMBus, expectations);
900 // READ_VIN back in range.
901 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
902 .Times(1)
903 .WillOnce(Return("206000"));
Brandon Wyman32453e92021-12-15 19:00:14 +0000904 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(0));
Brandon Wyman82affd92021-11-24 19:12:49 +0000905 psu.analyze();
906 EXPECT_EQ(psu.isPresent(), true);
907 EXPECT_EQ(psu.isFaulted(), false);
908 EXPECT_EQ(psu.hasInputFault(), false);
909 EXPECT_EQ(psu.hasMFRFault(), false);
910 EXPECT_EQ(psu.hasVINUVFault(), false);
911 EXPECT_EQ(psu.hasCommFault(), false);
912 EXPECT_EQ(psu.hasVoutOVFault(), false);
913 EXPECT_EQ(psu.hasIoutOCFault(), false);
914 EXPECT_EQ(psu.hasVoutUVFault(), false);
915 EXPECT_EQ(psu.hasFanFault(), false);
916 EXPECT_EQ(psu.hasTempFault(), false);
917 EXPECT_EQ(psu.hasPgoodFault(), false);
918 EXPECT_EQ(psu.hasPSKillFault(), false);
919 EXPECT_EQ(psu.hasPS12VcsFault(), false);
920 EXPECT_EQ(psu.hasPSCS12VFault(), false);
921
B. J. Wyman681b2a32021-04-20 22:31:22 +0000922 // TODO: Faults clear on missing/present?
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600923}
924
925TEST_F(PowerSupplyTests, UpdateInventory)
926{
927 auto bus = sdbusplus::bus::new_default();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500928
929 try
930 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000931 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500932 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
933 // If it is not present, I should not be trying to read a string
934 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
935 psu.updateInventory();
936 }
937 catch (...)
938 {
939 ADD_FAILURE() << "Should not have caught exception.";
940 }
941
942 try
943 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000944 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000945 MockedGPIOInterface* mockPresenceGPIO =
946 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000947 // GPIO read return 1 to indicate present.
948 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500949 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000950 setMissingToPresentExpects(mockPMBus, mockedUtil);
951 // STATUS_WORD 0x0000 is powered on, no faults.
952 PMBusExpectations expectations;
953 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000954 // Call to analyze will read voltage, trigger clear faults for 0 to
955 // within range.
956 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
957 .Times(1)
958 .WillOnce(Return("123456"));
Brandon Wyman391a0692021-12-08 23:28:18 +0000959 psu.analyze();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500960 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
961 psu.updateInventory();
962
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500963#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500964 EXPECT_CALL(mockPMBus, readString(_, _))
965 .WillOnce(Return("CCIN"))
966 .WillOnce(Return("PN3456"))
967 .WillOnce(Return("FN3456"))
968 .WillOnce(Return("HEADER"))
969 .WillOnce(Return("SN3456"))
970 .WillOnce(Return("FW3456"));
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500971#endif
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500972 psu.updateInventory();
973 // TODO: D-Bus mocking to verify values stored on D-Bus (???)
974 }
975 catch (...)
976 {
977 ADD_FAILURE() << "Should not have caught exception.";
978 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600979}
980
981TEST_F(PowerSupplyTests, IsPresent)
982{
983 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000984
985 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000986 MockedGPIOInterface* mockPresenceGPIO =
987 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600988 EXPECT_EQ(psu.isPresent(), false);
989
B. J. Wyman681b2a32021-04-20 22:31:22 +0000990 // Change GPIO read to return 1 to indicate present.
991 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +0000992 // Call to analyze() will update to present, that will trigger updating
993 // to the correct/latest HWMON directory, in case it changes.
994 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
995 setMissingToPresentExpects(mockPMBus, mockedUtil);
996 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
997 // Default expectations will be on, no faults.
998 PMBusExpectations expectations;
999 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001000 // Give it an input voltage in the 100-volt range.
1001 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1002 .Times(1)
1003 .WillOnce(Return("123456"));
B. J. Wyman681b2a32021-04-20 22:31:22 +00001004 psu.analyze();
1005 EXPECT_EQ(psu.isPresent(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001006}
1007
1008TEST_F(PowerSupplyTests, IsFaulted)
1009{
1010 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001011
1012 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001013 MockedGPIOInterface* mockPresenceGPIO =
1014 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001015 // Always return 1 to indicate present.
1016 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +00001017 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1018 setMissingToPresentExpects(mockPMBus, mockedUtil);
1019 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1020 // Default expectations will be on, no faults.
1021 PMBusExpectations expectations;
1022 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001023 // Give it an input voltage in the 100-volt range.
1024 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1025 .Times(1)
1026 .WillOnce(Return("124680"));
B. J. Wyman681b2a32021-04-20 22:31:22 +00001027 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001028 EXPECT_EQ(psu.isFaulted(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001029 // STATUS_WORD with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001030 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +00001031 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001032 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +00001033 // STATUS_MFR_SPECIFIC with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001034 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +00001035 // STATUS_CML with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001036 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +00001037 // STATUS_VOUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001038 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001039 // STATUS_IOUT with fault bits on.
1040 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001041 // STATUS_FANS_1_2 with bits on.
1042 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +00001043 // STATUS_TEMPERATURE with fault bits on.
1044 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001045 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1046 {
1047 setPMBusExpectations(mockPMBus, expectations);
1048 // Also get another read of READ_VIN.
1049 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1050 .Times(1)
1051 .WillOnce(Return("125790"));
1052 psu.analyze();
1053 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
1054 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001055}
1056
1057TEST_F(PowerSupplyTests, HasInputFault)
1058{
1059 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001060
1061 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001062 MockedGPIOInterface* mockPresenceGPIO =
1063 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001064 // Always return 1 to indicate present.
1065 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001066 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001067 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman8da35c52021-10-28 22:45:08 +00001068 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001069 PMBusExpectations expectations;
1070 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001071 // Analyze call will also need good READ_VIN value to check.
1072 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1073 .Times(1)
1074 .WillOnce(Return("201100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001075 psu.analyze();
1076 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001077 // STATUS_WORD with input fault/warn on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001078 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001079 // STATUS_INPUT with an input fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001080 expectations.statusInputValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001081 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1082 {
1083 setPMBusExpectations(mockPMBus, expectations);
1084 // Analyze call will also need good READ_VIN value to check.
1085 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1086 .Times(1)
1087 .WillOnce(Return("201200"));
1088 psu.analyze();
1089 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
1090 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001091 // STATUS_WORD with no bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001092 expectations.statusWordValue = 0;
1093 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001094 // Analyze call will also need good READ_VIN value to check.
1095 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1096 .Times(1)
1097 .WillOnce(Return("201300"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001098 psu.analyze();
1099 EXPECT_EQ(psu.hasInputFault(), false);
1100}
1101
1102TEST_F(PowerSupplyTests, HasMFRFault)
1103{
1104 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001105
1106 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001107 MockedGPIOInterface* mockPresenceGPIO =
1108 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001109 // Always return 1 to indicate present.
1110 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001111 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001112 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001113 // First return STATUS_WORD with no bits on.
Brandon Wyman8da35c52021-10-28 22:45:08 +00001114 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001115 PMBusExpectations expectations;
1116 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001117 // Analyze call will also need good READ_VIN value to check.
1118 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1119 .Times(1)
1120 .WillOnce(Return("202100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001121 psu.analyze();
1122 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001123 // Next return STATUS_WORD with MFR fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001124 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001125 // STATUS_MFR_SPEFIC with bit(s) on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001126 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001127 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1128 {
1129 setPMBusExpectations(mockPMBus, expectations);
1130 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1131 .Times(1)
1132 .WillOnce(Return("202200"));
1133 psu.analyze();
1134 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1135 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001136 // Back to no bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001137 expectations.statusWordValue = 0;
1138 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001139 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1140 .Times(1)
1141 .WillOnce(Return("202300"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001142 psu.analyze();
1143 EXPECT_EQ(psu.hasMFRFault(), false);
1144}
1145
1146TEST_F(PowerSupplyTests, HasVINUVFault)
1147{
1148 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001149
1150 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001151 MockedGPIOInterface* mockPresenceGPIO =
1152 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001153 // Always return 1 to indicate present.
1154 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001155 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001156 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman82affd92021-11-24 19:12:49 +00001157
1158 // Presence change from missing to present will trigger in1_input read in
1159 // an attempt to get CLEAR_FAULTS called. Return value ignored.
1160 // Zero to non-zero voltage, for missing/present change, triggers clear
1161 // faults call again. Return value ignored.
1162 // Fault (low voltage) to not faulted (voltage in range) triggers clear
1163 // faults call a third time.
1164
Brandon Wyman8da35c52021-10-28 22:45:08 +00001165 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001166 PMBusExpectations expectations;
1167 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001168 // Analyze call will also need good READ_VIN value to check.
1169 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1170 .Times(1)
1171 .WillOnce(Return("201100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001172 psu.analyze();
1173 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001174 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001175 expectations.statusWordValue = (status_word::VIN_UV_FAULT);
Brandon Wyman85c7bf42021-10-19 22:28:48 +00001176 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
1177 // Figure 16, and assume bits on in STATUS_INPUT.
Brandon Wymanb654c612021-11-05 23:24:51 +00001178 expectations.statusInputValue = 0x18;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001179 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1180 {
1181 setPMBusExpectations(mockPMBus, expectations);
1182 // If there is a VIN_UV fault, fake reading voltage of less than 20V
1183 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1184 .Times(1)
1185 .WillOnce(Return("19876"));
1186 psu.analyze();
1187 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1188 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001189 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001190 expectations.statusWordValue = 0;
1191 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001192 // Updates now result in clearing faults if read voltage goes from below the
1193 // minimum, to within a valid range.
1194 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1195 .Times(1)
1196 .WillOnce(Return("201300"));
1197 // Went from below minimum to within range, expect CLEAR_FAULTS.
Brandon Wyman32453e92021-12-15 19:00:14 +00001198 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(3));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001199 psu.analyze();
1200 EXPECT_EQ(psu.hasVINUVFault(), false);
1201}
Brandon Wyman6710ba22021-10-27 17:39:31 +00001202
1203TEST_F(PowerSupplyTests, HasVoutOVFault)
1204{
1205 auto bus = sdbusplus::bus::new_default();
1206
1207 PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName};
1208 MockedGPIOInterface* mockPresenceGPIO =
1209 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1210 // Always return 1 to indicate present.
1211 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001212 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001213 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman6710ba22021-10-27 17:39:31 +00001214 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001215 PMBusExpectations expectations;
1216 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001217 // Call to analyze will trigger read of "in1_input" to check voltage.
1218 // Initial value would be 0, so this read updates it to non-zero.
1219 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1220 .Times(1)
1221 .WillOnce(Return("202100"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001222 psu.analyze();
1223 EXPECT_EQ(psu.hasVoutOVFault(), false);
1224 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001225 expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
Brandon Wyman6710ba22021-10-27 17:39:31 +00001226 // STATUS_VOUT fault bit(s)
Brandon Wymanb654c612021-11-05 23:24:51 +00001227 expectations.statusVOUTValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001228 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1229 {
1230 setPMBusExpectations(mockPMBus, expectations);
1231 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1232 .Times(1)
1233 .WillOnce(Return("202200"));
1234 psu.analyze();
1235 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1236 }
Brandon Wyman6710ba22021-10-27 17:39:31 +00001237 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001238 expectations.statusWordValue = 0;
1239 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001240 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1241 .Times(1)
1242 .WillOnce(Return("202300"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001243 psu.analyze();
1244 EXPECT_EQ(psu.hasVoutOVFault(), false);
1245}
Brandon Wyman96893a42021-11-05 19:56:57 +00001246
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001247TEST_F(PowerSupplyTests, HasIoutOCFault)
1248{
1249 auto bus = sdbusplus::bus::new_default();
1250
1251 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
1252 MockedGPIOInterface* mockPresenceGPIO =
1253 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1254 // Always return 1 to indicate present.
1255 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001256 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001257 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001258 // STATUS_WORD 0x0000 is powered on, no faults.
1259 PMBusExpectations expectations;
1260 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001261 // Call to analyze will trigger read of "in1_input" to check voltage.
1262 // Initial value would be 0, so this read updates it to non-zero.
1263 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1264 .Times(1)
1265 .WillOnce(Return("203100"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001266 psu.analyze();
1267 EXPECT_EQ(psu.hasIoutOCFault(), false);
1268 // Turn fault on.
1269 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1270 // STATUS_IOUT fault bit(s)
1271 expectations.statusIOUTValue = 0x88;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001272 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1273 {
1274 setPMBusExpectations(mockPMBus, expectations);
1275 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1276 .Times(1)
1277 .WillOnce(Return("203200"));
1278 psu.analyze();
1279 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1280 }
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001281 // Back to no fault bits on in STATUS_WORD
1282 expectations.statusWordValue = 0;
1283 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001284 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1285 .Times(1)
1286 .WillOnce(Return("203300"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001287 psu.analyze();
1288 EXPECT_EQ(psu.hasIoutOCFault(), false);
1289}
1290
Brandon Wyman2cf46942021-10-28 19:09:16 +00001291TEST_F(PowerSupplyTests, HasVoutUVFault)
1292{
1293 auto bus = sdbusplus::bus::new_default();
1294
1295 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
1296 MockedGPIOInterface* mockPresenceGPIO =
1297 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1298 // Always return 1 to indicate present.
1299 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001300 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001301 setMissingToPresentExpects(mockPMBus, mockedUtil);
1302 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wyman2cf46942021-10-28 19:09:16 +00001303 PMBusExpectations expectations;
1304 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001305 // Call to analyze will trigger read of "in1_input" to check voltage.
1306 // Initial value would be 0, so this read updates it to non-zero.
1307 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1308 .Times(1)
1309 .WillOnce(Return("204100"));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001310 psu.analyze();
1311 EXPECT_EQ(psu.hasVoutUVFault(), false);
1312 // Turn fault on.
1313 expectations.statusWordValue = (status_word::VOUT_FAULT);
1314 // STATUS_VOUT fault bit(s)
1315 expectations.statusVOUTValue = 0x30;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001316 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1317 {
1318 setPMBusExpectations(mockPMBus, expectations);
1319 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1320 .Times(1)
1321 .WillOnce(Return("204200"));
1322 psu.analyze();
1323 EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1324 }
Brandon Wyman2cf46942021-10-28 19:09:16 +00001325 // Back to no fault bits on in STATUS_WORD
1326 expectations.statusWordValue = 0;
1327 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001328 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1329 .Times(1)
1330 .WillOnce(Return("204300"));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001331 psu.analyze();
1332 EXPECT_EQ(psu.hasVoutUVFault(), false);
1333}
1334
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001335TEST_F(PowerSupplyTests, HasFanFault)
1336{
1337 auto bus = sdbusplus::bus::new_default();
1338
1339 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
1340 MockedGPIOInterface* mockPresenceGPIO =
1341 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1342 // Always return 1 to indicate present.
1343 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001344 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001345 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001346 // STATUS_WORD 0x0000 is powered on, no faults.
1347 PMBusExpectations expectations;
1348 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001349 // Call to analyze will trigger read of "in1_input" to check voltage.
1350 // Initial value would be 0, so this read updates it to non-zero.
1351 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1352 .Times(1)
1353 .WillOnce(Return("205100"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001354 psu.analyze();
1355 EXPECT_EQ(psu.hasFanFault(), false);
1356 // Turn fault on.
1357 expectations.statusWordValue = (status_word::FAN_FAULT);
1358 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
1359 expectations.statusFans12Value = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001360 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1361 {
1362 setPMBusExpectations(mockPMBus, expectations);
1363 // Call to analyze will trigger read of "in1_input" to check voltage.
1364 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1365 .Times(1)
1366 .WillOnce(Return("205200"));
1367 psu.analyze();
1368 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1369 }
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001370 // Back to no fault bits on in STATUS_WORD
1371 expectations.statusWordValue = 0;
1372 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001373 // Call to analyze will trigger read of "in1_input" to check voltage.
1374 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1375 .Times(1)
1376 .WillOnce(Return("205300"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001377 psu.analyze();
1378 EXPECT_EQ(psu.hasFanFault(), false);
1379}
1380
Brandon Wyman96893a42021-11-05 19:56:57 +00001381TEST_F(PowerSupplyTests, HasTempFault)
1382{
1383 auto bus = sdbusplus::bus::new_default();
1384
1385 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
1386 MockedGPIOInterface* mockPresenceGPIO =
1387 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1388 // Always return 1 to indicate present.
1389 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman96893a42021-11-05 19:56:57 +00001390 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001391 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman96893a42021-11-05 19:56:57 +00001392 // STATUS_WORD 0x0000 is powered on, no faults.
1393 PMBusExpectations expectations;
1394 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001395 // Call to analyze will trigger read of "in1_input" to check voltage.
1396 // Initial value would be 0, so this read updates it to non-zero.
1397 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1398 .Times(1)
1399 .WillOnce(Return("206100"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001400 psu.analyze();
1401 EXPECT_EQ(psu.hasTempFault(), false);
1402 // Turn fault on.
1403 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
1404 // STATUS_TEMPERATURE fault bit on (OT Fault)
1405 expectations.statusTempValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001406 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1407 {
1408 setPMBusExpectations(mockPMBus, expectations);
1409 // Call to analyze will trigger read of "in1_input" to check voltage.
1410 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1411 .Times(1)
1412 .WillOnce(Return("206200"));
1413 psu.analyze();
1414 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1415 }
Brandon Wyman96893a42021-11-05 19:56:57 +00001416 // Back to no fault bits on in STATUS_WORD
1417 expectations.statusWordValue = 0;
1418 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001419 // Call to analyze will trigger read of "in1_input" to check voltage.
1420 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1421 .Times(1)
1422 .WillOnce(Return("206300"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001423 psu.analyze();
1424 EXPECT_EQ(psu.hasTempFault(), false);
1425}
Brandon Wyman2916ea52021-11-06 03:31:18 +00001426
1427TEST_F(PowerSupplyTests, HasPgoodFault)
1428{
1429 auto bus = sdbusplus::bus::new_default();
1430
1431 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, PSUGPIOLineName};
1432 MockedGPIOInterface* mockPresenceGPIO =
1433 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1434 // Always return 1 to indicate present.
1435 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001436 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001437 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman2916ea52021-11-06 03:31:18 +00001438 // STATUS_WORD 0x0000 is powered on, no faults.
1439 PMBusExpectations expectations;
1440 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001441 // Call to analyze will trigger read of "in1_input" to check voltage.
1442 // Initial value would be 0, so this read updates it to non-zero.
1443 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1444 .Times(1)
1445 .WillOnce(Return("207100"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001446 psu.analyze();
1447 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman391a0692021-12-08 23:28:18 +00001448 // Setup another expectation of no faults.
1449 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001450 // Call to analyze will trigger read of "in1_input" to check voltage.
1451 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1452 .Times(1)
1453 .WillOnce(Return("207200"));
1454 psu.analyze();
1455 EXPECT_EQ(psu.hasPgoodFault(), false);
1456 // Setup another expectation of no faults.
1457 setPMBusExpectations(mockPMBus, expectations);
1458 // Call to analyze will trigger read of "in1_input" to check voltage.
1459 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1460 .Times(1)
1461 .WillOnce(Return("207300"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001462 psu.analyze();
1463 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +00001464 // Turn PGOOD# off (fault on).
1465 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
1466 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001467 // Call to analyze will trigger read of "in1_input" to check voltage.
1468 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1469 .Times(1)
1470 .WillOnce(Return("207400"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001471 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001472 // Expect false until reaches DEGLITCH_LIMIT
1473 EXPECT_EQ(psu.hasPgoodFault(), false);
1474 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001475 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1476 .Times(1)
1477 .WillOnce(Return("207500"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001478 psu.analyze();
1479 // Expect false until reaches DEGLITCH_LIMIT
1480 EXPECT_EQ(psu.hasPgoodFault(), false);
1481 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001482 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1483 .Times(1)
1484 .WillOnce(Return("207600"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001485 psu.analyze();
1486 // DEGLITCH_LIMIT reached, expect true.
Brandon Wyman2916ea52021-11-06 03:31:18 +00001487 EXPECT_EQ(psu.hasPgoodFault(), true);
1488 // Back to no fault bits on in STATUS_WORD
1489 expectations.statusWordValue = 0;
1490 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001491 // Call to analyze will trigger read of "in1_input" to check voltage.
1492 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1493 .Times(1)
1494 .WillOnce(Return("207700"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001495 psu.analyze();
1496 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman82affd92021-11-24 19:12:49 +00001497
Brandon Wyman2916ea52021-11-06 03:31:18 +00001498 // Turn OFF bit on
1499 expectations.statusWordValue = (status_word::UNIT_IS_OFF);
1500 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001501 // Call to analyze will trigger read of "in1_input" to check voltage.
1502 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1503 .Times(1)
1504 .WillOnce(Return("208100"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001505 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001506 EXPECT_EQ(psu.hasPgoodFault(), false);
1507 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001508 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1509 .Times(1)
1510 .WillOnce(Return("208200"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001511 psu.analyze();
1512 EXPECT_EQ(psu.hasPgoodFault(), false);
1513 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001514 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1515 .Times(1)
1516 .WillOnce(Return("208300"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001517 psu.analyze();
Brandon Wyman2916ea52021-11-06 03:31:18 +00001518 EXPECT_EQ(psu.hasPgoodFault(), true);
1519 // Back to no fault bits on in STATUS_WORD
1520 expectations.statusWordValue = 0;
1521 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001522 // Call to analyze will trigger read of "in1_input" to check voltage.
1523 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1524 .Times(1)
1525 .WillOnce(Return("208400"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001526 psu.analyze();
1527 EXPECT_EQ(psu.hasPgoodFault(), false);
1528}
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001529
1530TEST_F(PowerSupplyTests, HasPSKillFault)
1531{
1532 auto bus = sdbusplus::bus::new_default();
1533 PowerSupply psu{bus, PSUInventoryPath, 4, 0x6d, PSUGPIOLineName};
1534 MockedGPIOInterface* mockPresenceGPIO =
1535 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1536 // Always return 1 to indicate present.
1537 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001538 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001539 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001540 // STATUS_WORD 0x0000 is powered on, no faults.
1541 PMBusExpectations expectations;
1542 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001543 // Call to analyze will trigger read of "in1_input" to check voltage.
1544 // Initial value would be 0, so this read updates it to non-zero.
1545 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1546 .Times(1)
1547 .WillOnce(Return("208100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001548 psu.analyze();
1549 EXPECT_EQ(psu.hasPSKillFault(), false);
1550 // Next return STATUS_WORD with MFR fault bit on.
1551 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1552 // STATUS_MFR_SPEFIC with bit(s) on.
1553 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001554
1555 // Deglitching faults, false until read the fault bits on up to the limit.
1556 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1557 {
1558 setPMBusExpectations(mockPMBus, expectations);
1559 // Call to analyze will trigger read of "in1_input" to check voltage.
1560 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1561 .Times(1)
1562 .WillOnce(Return("208200"));
1563 psu.analyze();
1564 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1565 }
1566
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001567 // Back to no bits on in STATUS_WORD
1568 expectations.statusWordValue = 0;
1569 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001570 // Call to analyze will trigger read of "in1_input" to check voltage.
1571 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1572 .Times(1)
1573 .WillOnce(Return("208300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001574 psu.analyze();
1575 EXPECT_EQ(psu.hasPSKillFault(), false);
1576 // Next return STATUS_WORD with MFR fault bit on.
1577 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1578 // STATUS_MFR_SPEFIC with bit 4 on.
1579 expectations.statusMFRValue = 0x10;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001580
1581 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1582 {
1583 setPMBusExpectations(mockPMBus, expectations);
1584 // Call to analyze will trigger read of "in1_input" to check voltage.
1585 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1586 .Times(1)
1587 .WillOnce(Return("208400"));
1588 psu.analyze();
1589 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1590 }
1591
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001592 // Back to no bits on in STATUS_WORD
1593 expectations.statusWordValue = 0;
1594 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001595 // Call to analyze will trigger read of "in1_input" to check voltage.
1596 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1597 .Times(1)
1598 .WillOnce(Return("208500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001599 psu.analyze();
1600 EXPECT_EQ(psu.hasPSKillFault(), false);
1601}
1602
1603TEST_F(PowerSupplyTests, HasPS12VcsFault)
1604{
1605 auto bus = sdbusplus::bus::new_default();
1606 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6e, PSUGPIOLineName};
1607 MockedGPIOInterface* mockPresenceGPIO =
1608 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1609 // Always return 1 to indicate present.
1610 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001611 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001612 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001613 // STATUS_WORD 0x0000 is powered on, no faults.
1614 PMBusExpectations expectations;
1615 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001616 // Call to analyze will trigger read of "in1_input" to check voltage.
1617 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1618 .Times(1)
1619 .WillOnce(Return("209100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001620 psu.analyze();
1621 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1622 // Next return STATUS_WORD with MFR fault bit on.
1623 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1624 // STATUS_MFR_SPEFIC with bit(s) on.
1625 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001626
1627 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1628 {
1629 setPMBusExpectations(mockPMBus, expectations);
1630 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1631 .Times(1)
1632 .WillOnce(Return("209200"));
1633 psu.analyze();
1634 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1635 }
1636
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001637 // Back to no bits on in STATUS_WORD
1638 expectations.statusWordValue = 0;
1639 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001640 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1641 .Times(1)
1642 .WillOnce(Return("209300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001643 psu.analyze();
1644 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1645 // Next return STATUS_WORD with MFR fault bit on.
1646 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1647 // STATUS_MFR_SPEFIC with bit 6 on.
1648 expectations.statusMFRValue = 0x40;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001649
1650 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1651 {
1652 setPMBusExpectations(mockPMBus, expectations);
1653 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1654 .Times(1)
1655 .WillOnce(Return("209400"));
1656 psu.analyze();
1657 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1658 }
1659
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001660 // Back to no bits on in STATUS_WORD
1661 expectations.statusWordValue = 0;
1662 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001663 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1664 .Times(1)
1665 .WillOnce(Return("209500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001666 psu.analyze();
1667 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1668}
1669
1670TEST_F(PowerSupplyTests, HasPSCS12VFault)
1671{
1672 auto bus = sdbusplus::bus::new_default();
1673 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f, PSUGPIOLineName};
1674 MockedGPIOInterface* mockPresenceGPIO =
1675 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1676 // Always return 1 to indicate present.
1677 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001678 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001679 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001680 // STATUS_WORD 0x0000 is powered on, no faults.
1681 PMBusExpectations expectations;
1682 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001683 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1684 .Times(1)
1685 .WillOnce(Return("209100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001686 psu.analyze();
1687 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1688 // Next return STATUS_WORD with MFR fault bit on.
1689 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1690 // STATUS_MFR_SPEFIC with bit(s) on.
1691 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001692
1693 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1694 {
1695 setPMBusExpectations(mockPMBus, expectations);
1696 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1697 .Times(1)
1698 .WillOnce(Return("209200"));
1699 psu.analyze();
1700 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1701 }
1702
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001703 // Back to no bits on in STATUS_WORD
1704 expectations.statusWordValue = 0;
1705 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001706 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1707 .Times(1)
1708 .WillOnce(Return("209300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001709 psu.analyze();
1710 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1711 // Next return STATUS_WORD with MFR fault bit on.
1712 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1713 // STATUS_MFR_SPEFIC with bit 7 on.
1714 expectations.statusMFRValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001715
1716 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1717 {
1718 setPMBusExpectations(mockPMBus, expectations);
1719 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1720 .Times(1)
1721 .WillOnce(Return("209400"));
1722 psu.analyze();
1723 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1724 }
1725
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001726 // Back to no bits on in STATUS_WORD
1727 expectations.statusWordValue = 0;
1728 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001729 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1730 .Times(1)
1731 .WillOnce(Return("209500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001732 psu.analyze();
1733 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1734}