blob: 8bcbf16c704de5ff8b679c030d80e6dbdef16a75 [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?
Matt Spinler0975eaf2022-02-14 15:38:30 -0600706 EXPECT_CALL(mockedUtil, setAvailable(_, _, _)).Times(0);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000707 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
708
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000709 MockedGPIOInterface* mockPresenceGPIO =
710 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000711 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
Brandon Wyman59a35792020-06-04 12:37:40 -0500712 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000713 // Constructor should set initial presence, default read returns 0.
Brandon Wyman59a35792020-06-04 12:37:40 -0500714 // If it is not present, I should not be trying to write to it.
715 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
716 psu.onOffConfig(data);
717 }
718 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000719 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500720
721 // Test where PSU is present
722 try
723 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000724 // Assume GPIO presence, not inventory presence?
Matt Spinler0975eaf2022-02-14 15:38:30 -0600725 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000726 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000727 MockedGPIOInterface* mockPresenceGPIO =
728 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman391a0692021-12-08 23:28:18 +0000729 // There will potentially be multiple calls, we want it to continue
730 // returning 1 for the GPIO read to keep the power supply present.
731 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman59a35792020-06-04 12:37:40 -0500732 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000733 setMissingToPresentExpects(mockPMBus, mockedUtil);
734 // If I am calling analyze(), I should probably give it good data.
735 // STATUS_WORD 0x0000 is powered on, no faults.
736 PMBusExpectations expectations;
737 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000738 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
739 .Times(1)
740 .WillOnce(Return("205000"));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000741 psu.analyze();
Brandon Wyman391a0692021-12-08 23:28:18 +0000742 // I definitely should be writting ON_OFF_CONFIG if I call the function
743 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
744 Type::HwmonDeviceDebug))
Brandon Wyman59a35792020-06-04 12:37:40 -0500745 .Times(1);
746 psu.onOffConfig(data);
747 }
748 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000749 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500750}
751
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600752TEST_F(PowerSupplyTests, ClearFaults)
753{
754 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000755 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000756 MockedGPIOInterface* mockPresenceGPIO =
757 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000758 // Always return 1 to indicate present.
759 // Each analyze() call will trigger a read of the presence GPIO.
760 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000761 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000762 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000763 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000764 PMBusExpectations expectations;
765 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000766 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
767 .Times(1)
768 .WillOnce(Return("207000"));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000769 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600770 EXPECT_EQ(psu.isPresent(), true);
771 EXPECT_EQ(psu.isFaulted(), false);
772 EXPECT_EQ(psu.hasInputFault(), false);
773 EXPECT_EQ(psu.hasMFRFault(), false);
774 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000775 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000776 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000777 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000778 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000779 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000780 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000781 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000782 EXPECT_EQ(psu.hasPSKillFault(), false);
783 EXPECT_EQ(psu.hasPS12VcsFault(), false);
784 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000785
Brandon Wymanf07bc792021-10-12 19:00:35 +0000786 // STATUS_WORD with fault bits galore!
Brandon Wymanb654c612021-11-05 23:24:51 +0000787 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000788 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000789 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000790 // STATUS_MFR_SPEFIC with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000791 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000792 // STATUS_CML with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000793 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000794 // STATUS_VOUT with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000795 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000796 // STATUS_IOUT with bits on.
797 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000798 // STATUS_FANS_1_2 with bits on.
799 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000800 // STATUS_TEMPERATURE with bits on.
801 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000802
803 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
804 {
805 setPMBusExpectations(mockPMBus, expectations);
806 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
807 .Times(1)
808 .WillOnce(Return("0"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600809 if (x == DEGLITCH_LIMIT)
810 {
811 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
812 }
Brandon Wymanc2906f42021-12-21 20:14:56 +0000813 psu.analyze();
814 EXPECT_EQ(psu.isPresent(), true);
815 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
816 // Rely on HasVoutUVFault() to verify this sets and clears.
817 EXPECT_EQ(psu.hasVoutUVFault(), false);
818 // All faults are deglitched up to DEGLITCH_LIMIT
819 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
820 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
821 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
822 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
823 EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT);
824 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
825 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
826 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
827 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
828 EXPECT_EQ(psu.hasPgoodFault(), x >= DEGLITCH_LIMIT);
829 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
830 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
831 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
832 }
833
Brandon Wyman32453e92021-12-15 19:00:14 +0000834 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _))
835 .Times(1)
836 .WillOnce(Return(207000));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600837 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600838 psu.clearFaults();
839 EXPECT_EQ(psu.isPresent(), true);
840 EXPECT_EQ(psu.isFaulted(), false);
841 EXPECT_EQ(psu.hasInputFault(), false);
842 EXPECT_EQ(psu.hasMFRFault(), false);
843 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000844 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000845 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000846 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000847 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000848 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000849 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000850 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000851 EXPECT_EQ(psu.hasPSKillFault(), false);
852 EXPECT_EQ(psu.hasPS12VcsFault(), false);
853 EXPECT_EQ(psu.hasPSCS12VFault(), false);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000854
Brandon Wyman82affd92021-11-24 19:12:49 +0000855 // Faults clear on READ_VIN 0 -> !0
856 // STATUS_WORD with fault bits galore!
857 expectations.statusWordValue = 0xFFFF;
858 // STATUS_INPUT with fault bits on.
859 expectations.statusInputValue = 0xFF;
860 // STATUS_MFR_SPEFIC with bits on.
861 expectations.statusMFRValue = 0xFF;
862 // STATUS_CML with bits on.
863 expectations.statusCMLValue = 0xFF;
864 // STATUS_VOUT with bits on.
865 expectations.statusVOUTValue = 0xFF;
866 // STATUS_IOUT with bits on.
867 expectations.statusIOUTValue = 0xFF;
868 // STATUS_FANS_1_2 with bits on.
869 expectations.statusFans12Value = 0xFF;
870 // STATUS_TEMPERATURE with bits on.
871 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000872
873 // All faults degltiched now. Check for false before limit above.
874 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
875 {
876 setPMBusExpectations(mockPMBus, expectations);
877 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
878 .Times(1)
879 .WillOnce(Return("0"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600880 if (x == DEGLITCH_LIMIT)
881 {
882 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
883 }
Brandon Wymanc2906f42021-12-21 20:14:56 +0000884 psu.analyze();
885 }
886
Brandon Wyman82affd92021-11-24 19:12:49 +0000887 EXPECT_EQ(psu.isPresent(), true);
888 EXPECT_EQ(psu.isFaulted(), true);
889 EXPECT_EQ(psu.hasInputFault(), true);
890 EXPECT_EQ(psu.hasMFRFault(), true);
891 EXPECT_EQ(psu.hasVINUVFault(), true);
892 // True due to CML fault bits on
893 EXPECT_EQ(psu.hasCommFault(), true);
894 EXPECT_EQ(psu.hasVoutOVFault(), true);
895 EXPECT_EQ(psu.hasIoutOCFault(), true);
896 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
897 // Rely on HasVoutUVFault() to verify this sets and clears.
898 EXPECT_EQ(psu.hasVoutUVFault(), false);
899 EXPECT_EQ(psu.hasFanFault(), true);
900 EXPECT_EQ(psu.hasTempFault(), true);
Brandon Wymanc2906f42021-12-21 20:14:56 +0000901 EXPECT_EQ(psu.hasPgoodFault(), true);
Brandon Wyman82affd92021-11-24 19:12:49 +0000902 EXPECT_EQ(psu.hasPSKillFault(), true);
903 EXPECT_EQ(psu.hasPS12VcsFault(), true);
904 EXPECT_EQ(psu.hasPSCS12VFault(), true);
905 // STATUS_WORD with INPUT/VIN_UV fault bits off.
906 expectations.statusWordValue = 0xDFF7;
907 // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
908 // Insufficient Input Voltage bits off.
909 expectations.statusInputValue = 0xC7;
910 setPMBusExpectations(mockPMBus, expectations);
911 // READ_VIN back in range.
912 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
913 .Times(1)
914 .WillOnce(Return("206000"));
Brandon Wyman32453e92021-12-15 19:00:14 +0000915 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(0));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600916 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman82affd92021-11-24 19:12:49 +0000917 psu.analyze();
918 EXPECT_EQ(psu.isPresent(), true);
919 EXPECT_EQ(psu.isFaulted(), false);
920 EXPECT_EQ(psu.hasInputFault(), false);
921 EXPECT_EQ(psu.hasMFRFault(), false);
922 EXPECT_EQ(psu.hasVINUVFault(), false);
923 EXPECT_EQ(psu.hasCommFault(), false);
924 EXPECT_EQ(psu.hasVoutOVFault(), false);
925 EXPECT_EQ(psu.hasIoutOCFault(), false);
926 EXPECT_EQ(psu.hasVoutUVFault(), false);
927 EXPECT_EQ(psu.hasFanFault(), false);
928 EXPECT_EQ(psu.hasTempFault(), false);
929 EXPECT_EQ(psu.hasPgoodFault(), false);
930 EXPECT_EQ(psu.hasPSKillFault(), false);
931 EXPECT_EQ(psu.hasPS12VcsFault(), false);
932 EXPECT_EQ(psu.hasPSCS12VFault(), false);
933
B. J. Wyman681b2a32021-04-20 22:31:22 +0000934 // TODO: Faults clear on missing/present?
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600935}
936
937TEST_F(PowerSupplyTests, UpdateInventory)
938{
939 auto bus = sdbusplus::bus::new_default();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500940
941 try
942 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000943 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500944 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
945 // If it is not present, I should not be trying to read a string
946 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
947 psu.updateInventory();
948 }
949 catch (...)
950 {
951 ADD_FAILURE() << "Should not have caught exception.";
952 }
953
954 try
955 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000956 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000957 MockedGPIOInterface* mockPresenceGPIO =
958 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000959 // GPIO read return 1 to indicate present.
960 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500961 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000962 setMissingToPresentExpects(mockPMBus, mockedUtil);
963 // STATUS_WORD 0x0000 is powered on, no faults.
964 PMBusExpectations expectations;
965 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000966 // Call to analyze will read voltage, trigger clear faults for 0 to
967 // within range.
968 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
969 .Times(1)
970 .WillOnce(Return("123456"));
Brandon Wyman391a0692021-12-08 23:28:18 +0000971 psu.analyze();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500972 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
973 psu.updateInventory();
974
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500975#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500976 EXPECT_CALL(mockPMBus, readString(_, _))
977 .WillOnce(Return("CCIN"))
978 .WillOnce(Return("PN3456"))
979 .WillOnce(Return("FN3456"))
980 .WillOnce(Return("HEADER"))
981 .WillOnce(Return("SN3456"))
982 .WillOnce(Return("FW3456"));
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500983#endif
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500984 psu.updateInventory();
985 // TODO: D-Bus mocking to verify values stored on D-Bus (???)
986 }
987 catch (...)
988 {
989 ADD_FAILURE() << "Should not have caught exception.";
990 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600991}
992
993TEST_F(PowerSupplyTests, IsPresent)
994{
995 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000996
997 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000998 MockedGPIOInterface* mockPresenceGPIO =
999 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001000 EXPECT_EQ(psu.isPresent(), false);
1001
B. J. Wyman681b2a32021-04-20 22:31:22 +00001002 // Change GPIO read to return 1 to indicate present.
1003 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +00001004 // Call to analyze() will update to present, that will trigger updating
1005 // to the correct/latest HWMON directory, in case it changes.
1006 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1007 setMissingToPresentExpects(mockPMBus, mockedUtil);
1008 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1009 // Default expectations will be on, no faults.
1010 PMBusExpectations expectations;
1011 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001012 // Give it an input voltage in the 100-volt range.
1013 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1014 .Times(1)
1015 .WillOnce(Return("123456"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001016 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
B. J. Wyman681b2a32021-04-20 22:31:22 +00001017 psu.analyze();
1018 EXPECT_EQ(psu.isPresent(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001019}
1020
1021TEST_F(PowerSupplyTests, IsFaulted)
1022{
1023 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001024
1025 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001026 MockedGPIOInterface* mockPresenceGPIO =
1027 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001028 // Always return 1 to indicate present.
1029 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +00001030 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1031 setMissingToPresentExpects(mockPMBus, mockedUtil);
1032 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1033 // Default expectations will be on, no faults.
1034 PMBusExpectations expectations;
1035 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001036 // Give it an input voltage in the 100-volt range.
1037 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1038 .Times(1)
1039 .WillOnce(Return("124680"));
B. J. Wyman681b2a32021-04-20 22:31:22 +00001040 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001041 EXPECT_EQ(psu.isFaulted(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001042 // STATUS_WORD with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001043 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +00001044 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001045 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +00001046 // STATUS_MFR_SPECIFIC with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001047 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +00001048 // STATUS_CML with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001049 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +00001050 // STATUS_VOUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001051 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001052 // STATUS_IOUT with fault bits on.
1053 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001054 // STATUS_FANS_1_2 with bits on.
1055 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +00001056 // STATUS_TEMPERATURE with fault bits on.
1057 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001058 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1059 {
1060 setPMBusExpectations(mockPMBus, expectations);
1061 // Also get another read of READ_VIN.
1062 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1063 .Times(1)
1064 .WillOnce(Return("125790"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001065 if (x == DEGLITCH_LIMIT)
1066 {
1067 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1068 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001069 psu.analyze();
1070 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
1071 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001072}
1073
1074TEST_F(PowerSupplyTests, HasInputFault)
1075{
1076 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001077
1078 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001079 MockedGPIOInterface* mockPresenceGPIO =
1080 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001081 // Always return 1 to indicate present.
1082 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001083 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001084 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman8da35c52021-10-28 22:45:08 +00001085 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001086 PMBusExpectations expectations;
1087 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001088 // Analyze call will also need good READ_VIN value to check.
1089 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1090 .Times(1)
1091 .WillOnce(Return("201100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001092 psu.analyze();
1093 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001094 // STATUS_WORD with input fault/warn on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001095 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001096 // STATUS_INPUT with an input fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001097 expectations.statusInputValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001098 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1099 {
1100 setPMBusExpectations(mockPMBus, expectations);
1101 // Analyze call will also need good READ_VIN value to check.
1102 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1103 .Times(1)
1104 .WillOnce(Return("201200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001105 if (x == DEGLITCH_LIMIT)
1106 {
1107 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1108 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001109 psu.analyze();
1110 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
1111 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001112 // STATUS_WORD with no bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001113 expectations.statusWordValue = 0;
1114 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001115 // Analyze call will also need good READ_VIN value to check.
1116 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1117 .Times(1)
1118 .WillOnce(Return("201300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001119 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001120 psu.analyze();
1121 EXPECT_EQ(psu.hasInputFault(), false);
1122}
1123
1124TEST_F(PowerSupplyTests, HasMFRFault)
1125{
1126 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001127
1128 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001129 MockedGPIOInterface* mockPresenceGPIO =
1130 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001131 // Always return 1 to indicate present.
1132 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001133 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001134 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001135 // First return STATUS_WORD with no bits on.
Brandon Wyman8da35c52021-10-28 22:45:08 +00001136 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001137 PMBusExpectations expectations;
1138 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001139 // Analyze call will also need good READ_VIN value to check.
1140 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1141 .Times(1)
1142 .WillOnce(Return("202100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001143 psu.analyze();
1144 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001145 // Next return STATUS_WORD with MFR fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001146 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001147 // STATUS_MFR_SPEFIC with bit(s) on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001148 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001149 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1150 {
1151 setPMBusExpectations(mockPMBus, expectations);
1152 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1153 .Times(1)
1154 .WillOnce(Return("202200"));
1155 psu.analyze();
1156 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1157 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001158 // Back to no bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001159 expectations.statusWordValue = 0;
1160 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001161 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1162 .Times(1)
1163 .WillOnce(Return("202300"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001164 psu.analyze();
1165 EXPECT_EQ(psu.hasMFRFault(), false);
1166}
1167
1168TEST_F(PowerSupplyTests, HasVINUVFault)
1169{
1170 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001171
1172 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001173 MockedGPIOInterface* mockPresenceGPIO =
1174 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001175 // Always return 1 to indicate present.
1176 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001177 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001178 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman82affd92021-11-24 19:12:49 +00001179
1180 // Presence change from missing to present will trigger in1_input read in
1181 // an attempt to get CLEAR_FAULTS called. Return value ignored.
1182 // Zero to non-zero voltage, for missing/present change, triggers clear
1183 // faults call again. Return value ignored.
1184 // Fault (low voltage) to not faulted (voltage in range) triggers clear
1185 // faults call a third time.
1186
Brandon Wyman8da35c52021-10-28 22:45:08 +00001187 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001188 PMBusExpectations expectations;
1189 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001190 // Analyze call will also need good READ_VIN value to check.
1191 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1192 .Times(1)
1193 .WillOnce(Return("201100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001194 psu.analyze();
1195 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001196 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001197 expectations.statusWordValue = (status_word::VIN_UV_FAULT);
Brandon Wyman85c7bf42021-10-19 22:28:48 +00001198 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
1199 // Figure 16, and assume bits on in STATUS_INPUT.
Brandon Wymanb654c612021-11-05 23:24:51 +00001200 expectations.statusInputValue = 0x18;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001201 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1202 {
1203 setPMBusExpectations(mockPMBus, expectations);
1204 // If there is a VIN_UV fault, fake reading voltage of less than 20V
1205 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1206 .Times(1)
1207 .WillOnce(Return("19876"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001208 if (x == DEGLITCH_LIMIT)
1209 {
1210 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1211 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001212 psu.analyze();
1213 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1214 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001215 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001216 expectations.statusWordValue = 0;
1217 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001218 // Updates now result in clearing faults if read voltage goes from below the
1219 // minimum, to within a valid range.
1220 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1221 .Times(1)
1222 .WillOnce(Return("201300"));
1223 // Went from below minimum to within range, expect CLEAR_FAULTS.
Brandon Wyman32453e92021-12-15 19:00:14 +00001224 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(3));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001225 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001226 psu.analyze();
1227 EXPECT_EQ(psu.hasVINUVFault(), false);
1228}
Brandon Wyman6710ba22021-10-27 17:39:31 +00001229
1230TEST_F(PowerSupplyTests, HasVoutOVFault)
1231{
1232 auto bus = sdbusplus::bus::new_default();
1233
1234 PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName};
1235 MockedGPIOInterface* mockPresenceGPIO =
1236 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1237 // Always return 1 to indicate present.
1238 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001239 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001240 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman6710ba22021-10-27 17:39:31 +00001241 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001242 PMBusExpectations expectations;
1243 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001244 // Call to analyze will trigger read of "in1_input" to check voltage.
1245 // Initial value would be 0, so this read updates it to non-zero.
1246 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1247 .Times(1)
1248 .WillOnce(Return("202100"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001249 psu.analyze();
1250 EXPECT_EQ(psu.hasVoutOVFault(), false);
1251 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001252 expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
Brandon Wyman6710ba22021-10-27 17:39:31 +00001253 // STATUS_VOUT fault bit(s)
Brandon Wymanb654c612021-11-05 23:24:51 +00001254 expectations.statusVOUTValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001255 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1256 {
1257 setPMBusExpectations(mockPMBus, expectations);
1258 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1259 .Times(1)
1260 .WillOnce(Return("202200"));
1261 psu.analyze();
1262 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1263 }
Brandon Wyman6710ba22021-10-27 17:39:31 +00001264 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001265 expectations.statusWordValue = 0;
1266 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001267 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1268 .Times(1)
1269 .WillOnce(Return("202300"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001270 psu.analyze();
1271 EXPECT_EQ(psu.hasVoutOVFault(), false);
1272}
Brandon Wyman96893a42021-11-05 19:56:57 +00001273
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001274TEST_F(PowerSupplyTests, HasIoutOCFault)
1275{
1276 auto bus = sdbusplus::bus::new_default();
1277
1278 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
1279 MockedGPIOInterface* mockPresenceGPIO =
1280 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1281 // Always return 1 to indicate present.
1282 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001283 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001284 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001285 // STATUS_WORD 0x0000 is powered on, no faults.
1286 PMBusExpectations expectations;
1287 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001288 // Call to analyze will trigger read of "in1_input" to check voltage.
1289 // Initial value would be 0, so this read updates it to non-zero.
1290 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1291 .Times(1)
1292 .WillOnce(Return("203100"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001293 psu.analyze();
1294 EXPECT_EQ(psu.hasIoutOCFault(), false);
1295 // Turn fault on.
1296 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1297 // STATUS_IOUT fault bit(s)
1298 expectations.statusIOUTValue = 0x88;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001299 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1300 {
1301 setPMBusExpectations(mockPMBus, expectations);
1302 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1303 .Times(1)
1304 .WillOnce(Return("203200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001305 if (x == DEGLITCH_LIMIT)
1306 {
1307 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1308 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001309 psu.analyze();
1310 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1311 }
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001312 // Back to no fault bits on in STATUS_WORD
1313 expectations.statusWordValue = 0;
1314 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001315 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1316 .Times(1)
1317 .WillOnce(Return("203300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001318 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001319 psu.analyze();
1320 EXPECT_EQ(psu.hasIoutOCFault(), false);
1321}
1322
Brandon Wyman2cf46942021-10-28 19:09:16 +00001323TEST_F(PowerSupplyTests, HasVoutUVFault)
1324{
1325 auto bus = sdbusplus::bus::new_default();
1326
1327 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
1328 MockedGPIOInterface* mockPresenceGPIO =
1329 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1330 // Always return 1 to indicate present.
1331 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001332 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001333 setMissingToPresentExpects(mockPMBus, mockedUtil);
1334 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wyman2cf46942021-10-28 19:09:16 +00001335 PMBusExpectations expectations;
1336 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001337 // Call to analyze will trigger read of "in1_input" to check voltage.
1338 // Initial value would be 0, so this read updates it to non-zero.
1339 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1340 .Times(1)
1341 .WillOnce(Return("204100"));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001342 psu.analyze();
1343 EXPECT_EQ(psu.hasVoutUVFault(), false);
1344 // Turn fault on.
1345 expectations.statusWordValue = (status_word::VOUT_FAULT);
1346 // STATUS_VOUT fault bit(s)
1347 expectations.statusVOUTValue = 0x30;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001348 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1349 {
1350 setPMBusExpectations(mockPMBus, expectations);
1351 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1352 .Times(1)
1353 .WillOnce(Return("204200"));
1354 psu.analyze();
1355 EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1356 }
Brandon Wyman2cf46942021-10-28 19:09:16 +00001357 // Back to no fault bits on in STATUS_WORD
1358 expectations.statusWordValue = 0;
1359 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001360 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1361 .Times(1)
1362 .WillOnce(Return("204300"));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001363 psu.analyze();
1364 EXPECT_EQ(psu.hasVoutUVFault(), false);
1365}
1366
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001367TEST_F(PowerSupplyTests, HasFanFault)
1368{
1369 auto bus = sdbusplus::bus::new_default();
1370
Matt Spinler0975eaf2022-02-14 15:38:30 -06001371 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
1372 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
1373
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001374 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
1375 MockedGPIOInterface* mockPresenceGPIO =
1376 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1377 // Always return 1 to indicate present.
1378 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001379 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001380 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001381 // STATUS_WORD 0x0000 is powered on, no faults.
1382 PMBusExpectations expectations;
1383 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001384 // Call to analyze will trigger read of "in1_input" to check voltage.
1385 // Initial value would be 0, so this read updates it to non-zero.
1386 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1387 .Times(1)
1388 .WillOnce(Return("205100"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001389 psu.analyze();
1390 EXPECT_EQ(psu.hasFanFault(), false);
1391 // Turn fault on.
1392 expectations.statusWordValue = (status_word::FAN_FAULT);
1393 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
1394 expectations.statusFans12Value = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001395 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1396 {
1397 setPMBusExpectations(mockPMBus, expectations);
1398 // Call to analyze will trigger read of "in1_input" to check voltage.
1399 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1400 .Times(1)
1401 .WillOnce(Return("205200"));
1402 psu.analyze();
1403 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1404 }
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001405 // Back to no fault bits on in STATUS_WORD
1406 expectations.statusWordValue = 0;
1407 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001408 // Call to analyze will trigger read of "in1_input" to check voltage.
1409 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1410 .Times(1)
1411 .WillOnce(Return("205300"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001412 psu.analyze();
1413 EXPECT_EQ(psu.hasFanFault(), false);
1414}
1415
Brandon Wyman96893a42021-11-05 19:56:57 +00001416TEST_F(PowerSupplyTests, HasTempFault)
1417{
1418 auto bus = sdbusplus::bus::new_default();
1419
Matt Spinler0975eaf2022-02-14 15:38:30 -06001420 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
1421 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
1422
Brandon Wyman96893a42021-11-05 19:56:57 +00001423 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
1424 MockedGPIOInterface* mockPresenceGPIO =
1425 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1426 // Always return 1 to indicate present.
1427 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman96893a42021-11-05 19:56:57 +00001428 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001429 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman96893a42021-11-05 19:56:57 +00001430 // STATUS_WORD 0x0000 is powered on, no faults.
1431 PMBusExpectations expectations;
1432 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001433 // Call to analyze will trigger read of "in1_input" to check voltage.
1434 // Initial value would be 0, so this read updates it to non-zero.
1435 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1436 .Times(1)
1437 .WillOnce(Return("206100"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001438 psu.analyze();
1439 EXPECT_EQ(psu.hasTempFault(), false);
1440 // Turn fault on.
1441 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
1442 // STATUS_TEMPERATURE fault bit on (OT Fault)
1443 expectations.statusTempValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001444 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1445 {
1446 setPMBusExpectations(mockPMBus, expectations);
1447 // Call to analyze will trigger read of "in1_input" to check voltage.
1448 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1449 .Times(1)
1450 .WillOnce(Return("206200"));
1451 psu.analyze();
1452 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1453 }
Brandon Wyman96893a42021-11-05 19:56:57 +00001454 // Back to no fault bits on in STATUS_WORD
1455 expectations.statusWordValue = 0;
1456 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001457 // Call to analyze will trigger read of "in1_input" to check voltage.
1458 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1459 .Times(1)
1460 .WillOnce(Return("206300"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001461 psu.analyze();
1462 EXPECT_EQ(psu.hasTempFault(), false);
1463}
Brandon Wyman2916ea52021-11-06 03:31:18 +00001464
1465TEST_F(PowerSupplyTests, HasPgoodFault)
1466{
1467 auto bus = sdbusplus::bus::new_default();
1468
1469 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, PSUGPIOLineName};
1470 MockedGPIOInterface* mockPresenceGPIO =
1471 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1472 // Always return 1 to indicate present.
1473 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001474 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001475 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman2916ea52021-11-06 03:31:18 +00001476 // STATUS_WORD 0x0000 is powered on, no faults.
1477 PMBusExpectations expectations;
1478 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001479 // Call to analyze will trigger read of "in1_input" to check voltage.
1480 // Initial value would be 0, so this read updates it to non-zero.
1481 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1482 .Times(1)
1483 .WillOnce(Return("207100"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001484 psu.analyze();
1485 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman391a0692021-12-08 23:28:18 +00001486 // Setup another expectation of no faults.
1487 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001488 // Call to analyze will trigger read of "in1_input" to check voltage.
1489 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1490 .Times(1)
1491 .WillOnce(Return("207200"));
1492 psu.analyze();
1493 EXPECT_EQ(psu.hasPgoodFault(), false);
1494 // Setup another expectation of no faults.
1495 setPMBusExpectations(mockPMBus, expectations);
1496 // Call to analyze will trigger read of "in1_input" to check voltage.
1497 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1498 .Times(1)
1499 .WillOnce(Return("207300"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001500 psu.analyze();
1501 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +00001502 // Turn PGOOD# off (fault on).
1503 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
1504 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001505 // Call to analyze will trigger read of "in1_input" to check voltage.
1506 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1507 .Times(1)
1508 .WillOnce(Return("207400"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001509 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001510 // Expect false until reaches DEGLITCH_LIMIT
1511 EXPECT_EQ(psu.hasPgoodFault(), false);
1512 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001513 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1514 .Times(1)
1515 .WillOnce(Return("207500"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001516 psu.analyze();
1517 // Expect false until reaches DEGLITCH_LIMIT
1518 EXPECT_EQ(psu.hasPgoodFault(), false);
1519 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001520 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1521 .Times(1)
1522 .WillOnce(Return("207600"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001523 psu.analyze();
1524 // DEGLITCH_LIMIT reached, expect true.
Brandon Wyman2916ea52021-11-06 03:31:18 +00001525 EXPECT_EQ(psu.hasPgoodFault(), true);
1526 // Back to no fault bits on in STATUS_WORD
1527 expectations.statusWordValue = 0;
1528 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001529 // Call to analyze will trigger read of "in1_input" to check voltage.
1530 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1531 .Times(1)
1532 .WillOnce(Return("207700"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001533 psu.analyze();
1534 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman82affd92021-11-24 19:12:49 +00001535
Brandon Wyman2916ea52021-11-06 03:31:18 +00001536 // Turn OFF bit on
1537 expectations.statusWordValue = (status_word::UNIT_IS_OFF);
1538 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001539 // Call to analyze will trigger read of "in1_input" to check voltage.
1540 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1541 .Times(1)
1542 .WillOnce(Return("208100"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001543 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001544 EXPECT_EQ(psu.hasPgoodFault(), false);
1545 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001546 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1547 .Times(1)
1548 .WillOnce(Return("208200"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001549 psu.analyze();
1550 EXPECT_EQ(psu.hasPgoodFault(), false);
1551 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001552 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1553 .Times(1)
1554 .WillOnce(Return("208300"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001555 psu.analyze();
Brandon Wyman2916ea52021-11-06 03:31:18 +00001556 EXPECT_EQ(psu.hasPgoodFault(), true);
1557 // Back to no fault bits on in STATUS_WORD
1558 expectations.statusWordValue = 0;
1559 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001560 // Call to analyze will trigger read of "in1_input" to check voltage.
1561 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1562 .Times(1)
1563 .WillOnce(Return("208400"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001564 psu.analyze();
1565 EXPECT_EQ(psu.hasPgoodFault(), false);
1566}
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001567
1568TEST_F(PowerSupplyTests, HasPSKillFault)
1569{
1570 auto bus = sdbusplus::bus::new_default();
1571 PowerSupply psu{bus, PSUInventoryPath, 4, 0x6d, PSUGPIOLineName};
1572 MockedGPIOInterface* mockPresenceGPIO =
1573 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1574 // Always return 1 to indicate present.
1575 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001576 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001577 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001578 // STATUS_WORD 0x0000 is powered on, no faults.
1579 PMBusExpectations expectations;
1580 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001581 // Call to analyze will trigger read of "in1_input" to check voltage.
1582 // Initial value would be 0, so this read updates it to non-zero.
1583 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1584 .Times(1)
1585 .WillOnce(Return("208100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001586 psu.analyze();
1587 EXPECT_EQ(psu.hasPSKillFault(), false);
1588 // Next return STATUS_WORD with MFR fault bit on.
1589 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1590 // STATUS_MFR_SPEFIC with bit(s) on.
1591 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001592
1593 // Deglitching faults, false until read the fault bits on up to the limit.
1594 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1595 {
1596 setPMBusExpectations(mockPMBus, expectations);
1597 // Call to analyze will trigger read of "in1_input" to check voltage.
1598 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1599 .Times(1)
1600 .WillOnce(Return("208200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001601 if (x == DEGLITCH_LIMIT)
1602 {
1603 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1604 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001605 psu.analyze();
1606 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1607 }
1608
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001609 // Back to no bits on in STATUS_WORD
1610 expectations.statusWordValue = 0;
1611 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001612 // Call to analyze will trigger read of "in1_input" to check voltage.
1613 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1614 .Times(1)
1615 .WillOnce(Return("208300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001616 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001617 psu.analyze();
1618 EXPECT_EQ(psu.hasPSKillFault(), false);
1619 // Next return STATUS_WORD with MFR fault bit on.
1620 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1621 // STATUS_MFR_SPEFIC with bit 4 on.
1622 expectations.statusMFRValue = 0x10;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001623
1624 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1625 {
1626 setPMBusExpectations(mockPMBus, expectations);
1627 // Call to analyze will trigger read of "in1_input" to check voltage.
1628 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1629 .Times(1)
1630 .WillOnce(Return("208400"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001631 if (x == DEGLITCH_LIMIT)
1632 {
1633 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1634 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001635 psu.analyze();
1636 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1637 }
1638
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001639 // Back to no bits on in STATUS_WORD
1640 expectations.statusWordValue = 0;
1641 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001642 // Call to analyze will trigger read of "in1_input" to check voltage.
1643 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1644 .Times(1)
1645 .WillOnce(Return("208500"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001646 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001647 psu.analyze();
1648 EXPECT_EQ(psu.hasPSKillFault(), false);
1649}
1650
1651TEST_F(PowerSupplyTests, HasPS12VcsFault)
1652{
1653 auto bus = sdbusplus::bus::new_default();
1654 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6e, PSUGPIOLineName};
1655 MockedGPIOInterface* mockPresenceGPIO =
1656 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1657 // Always return 1 to indicate present.
1658 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001659 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001660 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001661 // STATUS_WORD 0x0000 is powered on, no faults.
1662 PMBusExpectations expectations;
1663 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001664 // Call to analyze will trigger read of "in1_input" to check voltage.
1665 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1666 .Times(1)
1667 .WillOnce(Return("209100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001668 psu.analyze();
1669 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1670 // Next return STATUS_WORD with MFR fault bit on.
1671 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1672 // STATUS_MFR_SPEFIC with bit(s) on.
1673 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001674
1675 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1676 {
1677 setPMBusExpectations(mockPMBus, expectations);
1678 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1679 .Times(1)
1680 .WillOnce(Return("209200"));
1681 psu.analyze();
1682 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1683 }
1684
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001685 // Back to no bits on in STATUS_WORD
1686 expectations.statusWordValue = 0;
1687 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001688 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1689 .Times(1)
1690 .WillOnce(Return("209300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001691 psu.analyze();
1692 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1693 // Next return STATUS_WORD with MFR fault bit on.
1694 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1695 // STATUS_MFR_SPEFIC with bit 6 on.
1696 expectations.statusMFRValue = 0x40;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001697
1698 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1699 {
1700 setPMBusExpectations(mockPMBus, expectations);
1701 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1702 .Times(1)
1703 .WillOnce(Return("209400"));
1704 psu.analyze();
1705 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1706 }
1707
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001708 // Back to no bits on in STATUS_WORD
1709 expectations.statusWordValue = 0;
1710 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001711 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1712 .Times(1)
1713 .WillOnce(Return("209500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001714 psu.analyze();
1715 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1716}
1717
1718TEST_F(PowerSupplyTests, HasPSCS12VFault)
1719{
1720 auto bus = sdbusplus::bus::new_default();
1721 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f, PSUGPIOLineName};
1722 MockedGPIOInterface* mockPresenceGPIO =
1723 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1724 // Always return 1 to indicate present.
1725 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001726 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001727 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001728 // STATUS_WORD 0x0000 is powered on, no faults.
1729 PMBusExpectations expectations;
1730 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001731 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1732 .Times(1)
1733 .WillOnce(Return("209100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001734 psu.analyze();
1735 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1736 // Next return STATUS_WORD with MFR fault bit on.
1737 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1738 // STATUS_MFR_SPEFIC with bit(s) on.
1739 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001740
1741 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1742 {
1743 setPMBusExpectations(mockPMBus, expectations);
1744 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1745 .Times(1)
1746 .WillOnce(Return("209200"));
1747 psu.analyze();
1748 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1749 }
1750
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001751 // Back to no bits on in STATUS_WORD
1752 expectations.statusWordValue = 0;
1753 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001754 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1755 .Times(1)
1756 .WillOnce(Return("209300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001757 psu.analyze();
1758 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1759 // Next return STATUS_WORD with MFR fault bit on.
1760 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1761 // STATUS_MFR_SPEFIC with bit 7 on.
1762 expectations.statusMFRValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001763
1764 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1765 {
1766 setPMBusExpectations(mockPMBus, expectations);
1767 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1768 .Times(1)
1769 .WillOnce(Return("209400"));
1770 psu.analyze();
1771 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1772 }
1773
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001774 // Back to no bits on in STATUS_WORD
1775 expectations.statusWordValue = 0;
1776 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001777 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1778 .Times(1)
1779 .WillOnce(Return("209500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001780 psu.analyze();
1781 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1782}