blob: 1ce91f95bbf020917f2c1c34bd1f8ed5f90f8b60 [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 // This READ_VIN for CLEAR_FAULTS does not check the returned value.
Brandon Wyman3225a452022-03-18 18:51:49 +0000107 EXPECT_CALL(pmbus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
108 // The call for clearing faults includes clearing VIN_UV fault.
109 // The voltage defaults to 0, the first call to analyze should update the
110 // voltage to the current reading, triggering clearing VIN_UV fault(s)
111 // due to below minimum to within range voltage.
112 EXPECT_CALL(pmbus, read("in1_lcrit_alarm", _, _))
Brandon Wyman82affd92021-11-24 19:12:49 +0000113 .Times(2)
Brandon Wyman3225a452022-03-18 18:51:49 +0000114 .WillRepeatedly(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +0000115 // Missing/present call will update Presence in inventory.
Brandon Wyman391a0692021-12-08 23:28:18 +0000116 EXPECT_CALL(util, setPresence(_, _, true, _));
117}
118
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600119TEST_F(PowerSupplyTests, Constructor)
120{
121 /**
122 * @param[in] invpath - String for inventory path to use
123 * @param[in] i2cbus - The bus number this power supply is on
124 * @param[in] i2caddr - The 16-bit I2C address of the power supply
B. J. Wyman681b2a32021-04-20 22:31:22 +0000125 * @param[in] gpioLineName - The string for the gpio-line-name to read for
126 * presence.
127 * @param[in] bindDelay - Time in milliseconds to delay binding the device
128 * driver after seeing the presence line go active.
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600129 */
130 auto bus = sdbusplus::bus::new_default();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600131
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500132 // Try where inventory path is empty, constructor should fail.
133 try
134 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000135 auto psu =
136 std::make_unique<PowerSupply>(bus, "", 3, 0x68, PSUGPIOLineName);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500137 ADD_FAILURE() << "Should not have reached this line.";
138 }
139 catch (const std::invalid_argument& e)
140 {
141 EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
142 }
143 catch (...)
144 {
145 ADD_FAILURE() << "Should not have caught exception.";
146 }
147
B. J. Wyman681b2a32021-04-20 22:31:22 +0000148 // TODO: Try invalid i2c address?
149
150 // Try where gpioLineName is empty.
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500151 try
152 {
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500153 auto psu =
B. J. Wyman681b2a32021-04-20 22:31:22 +0000154 std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, "");
155 ADD_FAILURE()
156 << "Should not have reached this line. Invalid gpioLineName.";
157 }
158 catch (const std::invalid_argument& e)
159 {
160 EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
161 }
162 catch (...)
163 {
164 ADD_FAILURE() << "Should not have caught exception.";
165 }
166
167 // Test with valid arguments
168 // NOT using D-Bus inventory path for presence.
169 try
170 {
171 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
172 PSUGPIOLineName);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500173
174 EXPECT_EQ(psu->isPresent(), false);
175 EXPECT_EQ(psu->isFaulted(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000176 EXPECT_EQ(psu->hasCommFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500177 EXPECT_EQ(psu->hasInputFault(), false);
178 EXPECT_EQ(psu->hasMFRFault(), false);
179 EXPECT_EQ(psu->hasVINUVFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000180 EXPECT_EQ(psu->hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000181 EXPECT_EQ(psu->hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000182 EXPECT_EQ(psu->hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000183 EXPECT_EQ(psu->hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000184 EXPECT_EQ(psu->hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000185 EXPECT_EQ(psu->hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000186 EXPECT_EQ(psu->hasPSKillFault(), false);
187 EXPECT_EQ(psu->hasPS12VcsFault(), false);
188 EXPECT_EQ(psu->hasPSCS12VFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500189 }
190 catch (...)
191 {
192 ADD_FAILURE() << "Should not have caught exception.";
193 }
B. J. Wyman681b2a32021-04-20 22:31:22 +0000194
195 // Test with valid arguments
196 // TODO: Using D-Bus inventory path for presence.
197 try
198 {
199 // FIXME: How do I get that presenceGPIO.read() in the startup to throw
200 // an exception?
201
202 // EXPECT_CALL(mockedUtil, getPresence(_,
203 // StrEq(PSUInventoryPath)))
204 // .Times(1);
205 }
206 catch (...)
207 {
208 ADD_FAILURE() << "Should not have caught exception.";
209 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600210}
211
212TEST_F(PowerSupplyTests, Analyze)
213{
214 auto bus = sdbusplus::bus::new_default();
215
Brandon Wymanb654c612021-11-05 23:24:51 +0000216 {
217 // If I default to reading the GPIO, I will NOT expect a call to
218 // getPresence().
B. J. Wyman681b2a32021-04-20 22:31:22 +0000219
Brandon Wymanb654c612021-11-05 23:24:51 +0000220 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
221 MockedGPIOInterface* mockPresenceGPIO =
222 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
223 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000224
Brandon Wymanb654c612021-11-05 23:24:51 +0000225 psu.analyze();
226 // By default, nothing should change.
227 EXPECT_EQ(psu.isPresent(), false);
228 EXPECT_EQ(psu.isFaulted(), false);
229 EXPECT_EQ(psu.hasInputFault(), false);
230 EXPECT_EQ(psu.hasMFRFault(), false);
231 EXPECT_EQ(psu.hasVINUVFault(), false);
232 EXPECT_EQ(psu.hasCommFault(), false);
233 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000234 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000235 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000236 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000237 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000238 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000239 EXPECT_EQ(psu.hasPSKillFault(), false);
240 EXPECT_EQ(psu.hasPS12VcsFault(), false);
241 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000242 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600243
B. J. Wyman681b2a32021-04-20 22:31:22 +0000244 PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
245 // In order to get the various faults tested, the power supply needs to
246 // be present in order to read from the PMBus device(s).
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000247 MockedGPIOInterface* mockPresenceGPIO2 =
248 static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000249 // Always return 1 to indicate present.
250 // Each analyze() call will trigger a read of the presence GPIO.
251 EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000252 EXPECT_EQ(psu2.isPresent(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600253
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600254 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000255 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600256
Brandon Wymanb654c612021-11-05 23:24:51 +0000257 // STATUS_WORD INPUT fault.
258 {
259 // Start with STATUS_WORD 0x0000. Powered on, no faults.
260 // Set expectations for a no fault
261 PMBusExpectations expectations;
262 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000263 // After reading STATUS_WORD, etc., there will be a READ_VIN check.
264 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
265 .Times(1)
266 .WillOnce(Return("206000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000267 psu2.analyze();
268 EXPECT_EQ(psu2.isPresent(), true);
269 EXPECT_EQ(psu2.isFaulted(), false);
270 EXPECT_EQ(psu2.hasInputFault(), false);
271 EXPECT_EQ(psu2.hasMFRFault(), false);
272 EXPECT_EQ(psu2.hasVINUVFault(), false);
273 EXPECT_EQ(psu2.hasCommFault(), false);
274 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000275 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000276 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000277 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000278 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000279 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000280 EXPECT_EQ(psu2.hasPSKillFault(), false);
281 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
282 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000283
284 // Update expectations for STATUS_WORD input fault/warn
Brandon Wyman96893a42021-11-05 19:56:57 +0000285 // STATUS_INPUT fault bits ... on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000286 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wyman3225a452022-03-18 18:51:49 +0000287 // IIN_OC fault.
288 expectations.statusInputValue = 0x04;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000289
290 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
291 {
292 setPMBusExpectations(mockPMBus, expectations);
293 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
294 .Times(1)
295 .WillOnce(Return("207000"));
296 psu2.analyze();
297 EXPECT_EQ(psu2.isPresent(), true);
298 // Should not be faulted until it reaches the deglitch limit.
299 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
300 EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
301 EXPECT_EQ(psu2.hasMFRFault(), false);
302 EXPECT_EQ(psu2.hasVINUVFault(), false);
303 EXPECT_EQ(psu2.hasCommFault(), false);
304 EXPECT_EQ(psu2.hasVoutOVFault(), false);
305 EXPECT_EQ(psu2.hasIoutOCFault(), false);
306 EXPECT_EQ(psu2.hasVoutUVFault(), false);
307 EXPECT_EQ(psu2.hasFanFault(), false);
308 EXPECT_EQ(psu2.hasTempFault(), false);
309 EXPECT_EQ(psu2.hasPgoodFault(), false);
310 EXPECT_EQ(psu2.hasPSKillFault(), false);
311 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
312 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
313 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000314 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600315
Brandon Wyman32453e92021-12-15 19:00:14 +0000316 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000317 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
318 .Times(1)
319 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000320 psu2.clearFaults();
321
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600322 // STATUS_WORD INPUT/UV fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000323 {
324 // First need it to return good status, then the fault
325 PMBusExpectations expectations;
326 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000327 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
328 .Times(1)
329 .WillOnce(Return("208000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000330 psu2.analyze();
Brandon Wymanc2906f42021-12-21 20:14:56 +0000331 EXPECT_EQ(psu2.isFaulted(), false);
332 EXPECT_EQ(psu2.hasInputFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000333 // Now set fault bits in STATUS_WORD
334 expectations.statusWordValue =
335 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
336 // STATUS_INPUT fault bits ... on.
Brandon Wyman3225a452022-03-18 18:51:49 +0000337 expectations.statusInputValue = 0x18;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000338 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
339 {
340 setPMBusExpectations(mockPMBus, expectations);
341 // Input/UV fault, so voltage should read back low.
342 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
343 .Times(1)
344 .WillOnce(Return("19123"));
345 psu2.analyze();
346 EXPECT_EQ(psu2.isPresent(), true);
347 // Only faulted if hit deglitch limit
348 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
349 EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
350 EXPECT_EQ(psu2.hasVINUVFault(), x >= DEGLITCH_LIMIT);
351 EXPECT_EQ(psu2.hasMFRFault(), false);
352 EXPECT_EQ(psu2.hasCommFault(), false);
353 EXPECT_EQ(psu2.hasVoutOVFault(), false);
354 EXPECT_EQ(psu2.hasIoutOCFault(), false);
355 EXPECT_EQ(psu2.hasVoutUVFault(), false);
356 EXPECT_EQ(psu2.hasFanFault(), false);
357 EXPECT_EQ(psu2.hasTempFault(), false);
358 EXPECT_EQ(psu2.hasPgoodFault(), false);
359 EXPECT_EQ(psu2.hasPSKillFault(), false);
360 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
361 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
362 }
Brandon Wyman82affd92021-11-24 19:12:49 +0000363 // Turning VIN_UV fault off causes clearing of faults, causing read of
364 // in1_input as an attempt to get CLEAR_FAULTS called.
365 expectations.statusWordValue = 0;
366 setPMBusExpectations(mockPMBus, expectations);
367 // The call to read the voltage
368 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
369 .Times(1)
370 .WillOnce(Return("209000"));
Brandon Wyman3225a452022-03-18 18:51:49 +0000371 // The call to clear VIN_UV/Off fault(s)
372 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
Brandon Wyman32453e92021-12-15 19:00:14 +0000373 .Times(1)
Brandon Wyman3225a452022-03-18 18:51:49 +0000374 .WillOnce(Return(1));
Brandon Wyman82affd92021-11-24 19:12:49 +0000375 psu2.analyze();
376 // Should remain present, no longer be faulted, no input fault, no
377 // VIN_UV fault. Nothing else should change.
378 EXPECT_EQ(psu2.isPresent(), true);
379 EXPECT_EQ(psu2.isFaulted(), false);
380 EXPECT_EQ(psu2.hasInputFault(), false);
381 EXPECT_EQ(psu2.hasVINUVFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000382 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600383
Brandon Wyman32453e92021-12-15 19:00:14 +0000384 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000385 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
386 .Times(1)
387 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000388 psu2.clearFaults();
389
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600390 // STATUS_WORD MFR fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000391 {
392 // First need it to return good status, then the fault
393 PMBusExpectations expectations;
394 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000395 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
396 .Times(1)
397 .WillOnce(Return("210000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000398 psu2.analyze();
399 // Now STATUS_WORD with MFR fault bit on.
400 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
401 // STATUS_MFR bits on.
402 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000403
404 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
405 {
406 setPMBusExpectations(mockPMBus, expectations);
407 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
408 .Times(1)
409 .WillOnce(Return("211000"));
410 psu2.analyze();
411 EXPECT_EQ(psu2.isPresent(), true);
412 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
413 EXPECT_EQ(psu2.hasInputFault(), false);
414 EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT);
415 EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT);
416 EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
417 EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
418 EXPECT_EQ(psu2.hasVINUVFault(), false);
419 EXPECT_EQ(psu2.hasCommFault(), false);
420 EXPECT_EQ(psu2.hasVoutOVFault(), false);
421 EXPECT_EQ(psu2.hasIoutOCFault(), false);
422 EXPECT_EQ(psu2.hasVoutUVFault(), false);
423 EXPECT_EQ(psu2.hasFanFault(), false);
424 EXPECT_EQ(psu2.hasTempFault(), false);
425 EXPECT_EQ(psu2.hasPgoodFault(), false);
426 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000427 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600428
Brandon Wyman32453e92021-12-15 19:00:14 +0000429 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000430 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
431 .Times(1)
432 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000433 psu2.clearFaults();
Brandon Wyman3225a452022-03-18 18:51:49 +0000434
Brandon Wyman96893a42021-11-05 19:56:57 +0000435 // Temperature fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000436 {
437 // First STATUS_WORD with no bits set, then with temperature fault.
438 PMBusExpectations expectations;
439 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000440 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
441 .Times(1)
442 .WillOnce(Return("212000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000443 psu2.analyze();
444 // STATUS_WORD with temperature fault bit on.
445 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
Brandon Wyman96893a42021-11-05 19:56:57 +0000446 // STATUS_TEMPERATURE with fault bit(s) on.
447 expectations.statusTempValue = 0x10;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000448 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
449 {
450 setPMBusExpectations(mockPMBus, expectations);
451 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
452 .Times(1)
453 .WillOnce(Return("213000"));
454 psu2.analyze();
455 EXPECT_EQ(psu2.isPresent(), true);
456 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
457 EXPECT_EQ(psu2.hasInputFault(), false);
458 EXPECT_EQ(psu2.hasMFRFault(), false);
459 EXPECT_EQ(psu2.hasVINUVFault(), false);
460 EXPECT_EQ(psu2.hasCommFault(), false);
461 EXPECT_EQ(psu2.hasVoutOVFault(), false);
462 EXPECT_EQ(psu2.hasIoutOCFault(), false);
463 EXPECT_EQ(psu2.hasVoutUVFault(), false);
464 EXPECT_EQ(psu2.hasFanFault(), false);
465 EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT);
466 EXPECT_EQ(psu2.hasPgoodFault(), false);
467 EXPECT_EQ(psu2.hasPSKillFault(), false);
468 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
469 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
470 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000471 }
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000472
Brandon Wyman32453e92021-12-15 19:00:14 +0000473 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000474 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
475 .Times(1)
476 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000477 psu2.clearFaults();
Brandon Wyman3225a452022-03-18 18:51:49 +0000478
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000479 // CML fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000480 {
481 // First STATUS_WORD wit no bits set, then with CML fault.
482 PMBusExpectations expectations;
483 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000484 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
485 .Times(1)
486 .WillOnce(Return("214000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000487 psu2.analyze();
488 // STATUS_WORD with CML fault bit on.
489 expectations.statusWordValue = (status_word::CML_FAULT);
490 // Turn on STATUS_CML fault bit(s)
491 expectations.statusCMLValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000492 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
493 {
494 setPMBusExpectations(mockPMBus, expectations);
495 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
496 .Times(1)
497 .WillOnce(Return("215000"));
498 psu2.analyze();
499 EXPECT_EQ(psu2.isPresent(), true);
500 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
501 EXPECT_EQ(psu2.hasCommFault(), x >= DEGLITCH_LIMIT);
502 EXPECT_EQ(psu2.hasInputFault(), false);
503 EXPECT_EQ(psu2.hasMFRFault(), false);
504 EXPECT_EQ(psu2.hasVINUVFault(), false);
505 EXPECT_EQ(psu2.hasVoutOVFault(), false);
506 EXPECT_EQ(psu2.hasIoutOCFault(), false);
507 EXPECT_EQ(psu2.hasVoutUVFault(), false);
508 EXPECT_EQ(psu2.hasFanFault(), false);
509 EXPECT_EQ(psu2.hasTempFault(), false);
510 EXPECT_EQ(psu2.hasPgoodFault(), false);
511 EXPECT_EQ(psu2.hasPSKillFault(), false);
512 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
513 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
514 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000515 }
Brandon Wyman6710ba22021-10-27 17:39:31 +0000516
Brandon Wyman32453e92021-12-15 19:00:14 +0000517 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000518 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
519 .Times(1)
520 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000521 psu2.clearFaults();
Brandon Wyman3225a452022-03-18 18:51:49 +0000522
Brandon Wyman6710ba22021-10-27 17:39:31 +0000523 // VOUT_OV_FAULT fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000524 {
525 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
526 PMBusExpectations expectations;
527 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000528 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
529 .Times(1)
530 .WillOnce(Return("216000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000531 psu2.analyze();
532 // STATUS_WORD with VOUT/VOUT_OV fault.
533 expectations.statusWordValue =
534 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
535 // Turn on STATUS_VOUT fault bit(s)
536 expectations.statusVOUTValue = 0xA0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000537 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
538 {
539 // STATUS_TEMPERATURE don't care (default)
540 setPMBusExpectations(mockPMBus, expectations);
541 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
542 .Times(1)
543 .WillOnce(Return("217000"));
544 psu2.analyze();
545 EXPECT_EQ(psu2.isPresent(), true);
546 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
547 EXPECT_EQ(psu2.hasInputFault(), false);
548 EXPECT_EQ(psu2.hasMFRFault(), false);
549 EXPECT_EQ(psu2.hasVINUVFault(), false);
550 EXPECT_EQ(psu2.hasCommFault(), false);
551 EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
552 EXPECT_EQ(psu2.hasVoutUVFault(), false);
553 EXPECT_EQ(psu2.hasIoutOCFault(), false);
554 EXPECT_EQ(psu2.hasFanFault(), false);
555 EXPECT_EQ(psu2.hasTempFault(), false);
556 EXPECT_EQ(psu2.hasPgoodFault(), false);
557 EXPECT_EQ(psu2.hasPSKillFault(), false);
558 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
559 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
560 }
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000561 }
562
563 // IOUT_OC_FAULT fault
564 {
565 // First STATUS_WORD with no bits set, then with IOUT_OC fault.
566 PMBusExpectations expectations;
567 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000568 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
569 .Times(1)
570 .WillOnce(Return("218000"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000571 psu2.analyze();
572 // STATUS_WORD with IOUT_OC fault.
573 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
574 // Turn on STATUS_IOUT fault bit(s)
575 expectations.statusIOUTValue = 0x88;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000576 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
577 {
578 setPMBusExpectations(mockPMBus, expectations);
579 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
580 .Times(1)
581 .WillOnce(Return("219000"));
582 psu2.analyze();
583 EXPECT_EQ(psu2.isPresent(), true);
584 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
585 EXPECT_EQ(psu2.hasInputFault(), false);
586 EXPECT_EQ(psu2.hasMFRFault(), false);
587 EXPECT_EQ(psu2.hasVINUVFault(), false);
588 EXPECT_EQ(psu2.hasCommFault(), false);
589 EXPECT_EQ(psu2.hasVoutOVFault(), false);
590 EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
591 EXPECT_EQ(psu2.hasVoutUVFault(), false);
592 EXPECT_EQ(psu2.hasFanFault(), false);
593 EXPECT_EQ(psu2.hasTempFault(), false);
594 EXPECT_EQ(psu2.hasPgoodFault(), false);
595 EXPECT_EQ(psu2.hasPSKillFault(), false);
596 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
597 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
598 }
Brandon Wyman2cf46942021-10-28 19:09:16 +0000599 }
600
601 // VOUT_UV_FAULT
602 {
603 // First STATUS_WORD with no bits set, then with VOUT fault.
604 PMBusExpectations expectations;
605 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000606 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
607 .Times(1)
608 .WillOnce(Return("220000"));
Brandon Wyman2cf46942021-10-28 19:09:16 +0000609 psu2.analyze();
610 // Change STATUS_WORD to indicate VOUT fault.
611 expectations.statusWordValue = (status_word::VOUT_FAULT);
612 // Turn on STATUS_VOUT fault bit(s)
613 expectations.statusVOUTValue = 0x30;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000614 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
615 {
616 setPMBusExpectations(mockPMBus, expectations);
617 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
618 .Times(1)
619 .WillOnce(Return("221000"));
620 psu2.analyze();
621 EXPECT_EQ(psu2.isPresent(), true);
622 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
623 EXPECT_EQ(psu2.hasInputFault(), false);
624 EXPECT_EQ(psu2.hasMFRFault(), false);
625 EXPECT_EQ(psu2.hasVINUVFault(), false);
626 EXPECT_EQ(psu2.hasCommFault(), false);
627 EXPECT_EQ(psu2.hasVoutOVFault(), false);
628 EXPECT_EQ(psu2.hasIoutOCFault(), false);
629 EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
630 EXPECT_EQ(psu2.hasFanFault(), false);
631 EXPECT_EQ(psu2.hasTempFault(), false);
632 EXPECT_EQ(psu2.hasPgoodFault(), false);
633 EXPECT_EQ(psu2.hasPSKillFault(), false);
634 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
635 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
636 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000637 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600638
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000639 // Fan fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000640 {
641 // First STATUS_WORD with no bits set, then with fan fault.
642 PMBusExpectations expectations;
643 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000644 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
645 .Times(1)
646 .WillOnce(Return("222000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000647 psu2.analyze();
648 expectations.statusWordValue = (status_word::FAN_FAULT);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000649 // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
650 expectations.statusFans12Value = 0xA0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000651
652 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
653 {
654 setPMBusExpectations(mockPMBus, expectations);
655 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
656 .Times(1)
657 .WillOnce(Return("223000"));
658 psu2.analyze();
659 EXPECT_EQ(psu2.isPresent(), true);
660 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
661 EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT);
662 EXPECT_EQ(psu2.hasInputFault(), false);
663 EXPECT_EQ(psu2.hasMFRFault(), false);
664 EXPECT_EQ(psu2.hasVINUVFault(), false);
665 EXPECT_EQ(psu2.hasCommFault(), false);
666 EXPECT_EQ(psu2.hasVoutOVFault(), false);
667 EXPECT_EQ(psu2.hasIoutOCFault(), false);
668 EXPECT_EQ(psu2.hasVoutUVFault(), false);
669 EXPECT_EQ(psu2.hasTempFault(), false);
670 EXPECT_EQ(psu2.hasPgoodFault(), false);
671 EXPECT_EQ(psu2.hasPSKillFault(), false);
672 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
673 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
674 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000675 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000676
Brandon Wyman06ca4592021-12-06 22:52:23 +0000677 // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000678 {
Brandon Wyman2916ea52021-11-06 03:31:18 +0000679 // First STATUS_WORD with no bits set.
680 PMBusExpectations expectations;
681 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000682 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
683 .Times(1)
684 .WillOnce(Return("123000"));
Brandon Wyman2916ea52021-11-06 03:31:18 +0000685 psu2.analyze();
686 EXPECT_EQ(psu2.isFaulted(), false);
687 // POWER_GOOD# inactive, and OFF bit on.
688 expectations.statusWordValue =
689 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
Brandon Wyman06ca4592021-12-06 22:52:23 +0000690 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
691 {
692 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
693 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
694 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000695 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
696 .Times(1)
697 .WillOnce(Return("124000"));
Brandon Wyman06ca4592021-12-06 22:52:23 +0000698 psu2.analyze();
699 EXPECT_EQ(psu2.isPresent(), true);
Brandon Wymanc2906f42021-12-21 20:14:56 +0000700 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
Brandon Wyman06ca4592021-12-06 22:52:23 +0000701 EXPECT_EQ(psu2.hasInputFault(), false);
702 EXPECT_EQ(psu2.hasMFRFault(), false);
703 EXPECT_EQ(psu2.hasVINUVFault(), false);
704 EXPECT_EQ(psu2.hasCommFault(), false);
705 EXPECT_EQ(psu2.hasVoutOVFault(), false);
706 EXPECT_EQ(psu2.hasVoutUVFault(), false);
707 EXPECT_EQ(psu2.hasIoutOCFault(), false);
708 EXPECT_EQ(psu2.hasFanFault(), false);
709 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman32453e92021-12-15 19:00:14 +0000710 EXPECT_EQ(psu2.hasPgoodFault(), x >= DEGLITCH_LIMIT);
Brandon Wyman06ca4592021-12-06 22:52:23 +0000711 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000712 }
713
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600714 // TODO: ReadFailure
715}
716
Brandon Wyman59a35792020-06-04 12:37:40 -0500717TEST_F(PowerSupplyTests, OnOffConfig)
718{
719 auto bus = sdbusplus::bus::new_default();
720 uint8_t data = 0x15;
721
722 // Test where PSU is NOT present
723 try
724 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000725 // Assume GPIO presence, not inventory presence?
Matt Spinler0975eaf2022-02-14 15:38:30 -0600726 EXPECT_CALL(mockedUtil, setAvailable(_, _, _)).Times(0);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000727 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
728
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000729 MockedGPIOInterface* mockPresenceGPIO =
730 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000731 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
Brandon Wyman59a35792020-06-04 12:37:40 -0500732 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000733 // Constructor should set initial presence, default read returns 0.
Brandon Wyman59a35792020-06-04 12:37:40 -0500734 // If it is not present, I should not be trying to write to it.
735 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
736 psu.onOffConfig(data);
737 }
738 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000739 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500740
741 // Test where PSU is present
742 try
743 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000744 // Assume GPIO presence, not inventory presence?
Matt Spinler0975eaf2022-02-14 15:38:30 -0600745 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000746 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000747 MockedGPIOInterface* mockPresenceGPIO =
748 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman391a0692021-12-08 23:28:18 +0000749 // There will potentially be multiple calls, we want it to continue
750 // returning 1 for the GPIO read to keep the power supply present.
751 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman59a35792020-06-04 12:37:40 -0500752 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000753 setMissingToPresentExpects(mockPMBus, mockedUtil);
754 // If I am calling analyze(), I should probably give it good data.
755 // STATUS_WORD 0x0000 is powered on, no faults.
756 PMBusExpectations expectations;
757 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000758 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
759 .Times(1)
760 .WillOnce(Return("205000"));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000761 psu.analyze();
Brandon Wyman391a0692021-12-08 23:28:18 +0000762 // I definitely should be writting ON_OFF_CONFIG if I call the function
763 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
764 Type::HwmonDeviceDebug))
Brandon Wyman59a35792020-06-04 12:37:40 -0500765 .Times(1);
766 psu.onOffConfig(data);
767 }
768 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000769 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500770}
771
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600772TEST_F(PowerSupplyTests, ClearFaults)
773{
774 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000775 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000776 MockedGPIOInterface* mockPresenceGPIO =
777 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000778 // Always return 1 to indicate present.
779 // Each analyze() call will trigger a read of the presence GPIO.
780 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000781 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000782 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000783 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000784 PMBusExpectations expectations;
785 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000786 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
787 .Times(1)
788 .WillOnce(Return("207000"));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000789 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600790 EXPECT_EQ(psu.isPresent(), true);
791 EXPECT_EQ(psu.isFaulted(), false);
792 EXPECT_EQ(psu.hasInputFault(), false);
793 EXPECT_EQ(psu.hasMFRFault(), false);
794 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000795 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000796 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000797 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000798 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000799 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000800 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000801 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000802 EXPECT_EQ(psu.hasPSKillFault(), false);
803 EXPECT_EQ(psu.hasPS12VcsFault(), false);
804 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000805
Brandon Wymanf07bc792021-10-12 19:00:35 +0000806 // STATUS_WORD with fault bits galore!
Brandon Wymanb654c612021-11-05 23:24:51 +0000807 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000808 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000809 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000810 // STATUS_MFR_SPEFIC with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000811 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000812 // STATUS_CML with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000813 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000814 // STATUS_VOUT with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000815 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000816 // STATUS_IOUT with bits on.
817 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000818 // STATUS_FANS_1_2 with bits on.
819 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000820 // STATUS_TEMPERATURE with bits on.
821 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000822
823 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
824 {
825 setPMBusExpectations(mockPMBus, expectations);
826 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
827 .Times(1)
828 .WillOnce(Return("0"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600829 if (x == DEGLITCH_LIMIT)
830 {
831 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
832 }
Brandon Wymanc2906f42021-12-21 20:14:56 +0000833 psu.analyze();
834 EXPECT_EQ(psu.isPresent(), true);
835 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
836 // Rely on HasVoutUVFault() to verify this sets and clears.
837 EXPECT_EQ(psu.hasVoutUVFault(), false);
838 // All faults are deglitched up to DEGLITCH_LIMIT
839 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
840 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
841 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
842 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
843 EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT);
844 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
845 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
846 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
847 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
848 EXPECT_EQ(psu.hasPgoodFault(), x >= DEGLITCH_LIMIT);
849 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
850 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
851 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
852 }
853
Brandon Wyman32453e92021-12-15 19:00:14 +0000854 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _))
855 .Times(1)
856 .WillOnce(Return(207000));
Brandon Wyman3225a452022-03-18 18:51:49 +0000857 // Clearing VIN_UV fault via in1_lcrit_alarm
858 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
859 .Times(1)
860 .WillOnce(Return(1));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600861 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600862 psu.clearFaults();
863 EXPECT_EQ(psu.isPresent(), true);
864 EXPECT_EQ(psu.isFaulted(), false);
865 EXPECT_EQ(psu.hasInputFault(), false);
866 EXPECT_EQ(psu.hasMFRFault(), false);
867 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000868 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000869 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000870 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000871 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000872 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000873 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000874 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000875 EXPECT_EQ(psu.hasPSKillFault(), false);
876 EXPECT_EQ(psu.hasPS12VcsFault(), false);
877 EXPECT_EQ(psu.hasPSCS12VFault(), false);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000878
Brandon Wyman82affd92021-11-24 19:12:49 +0000879 // Faults clear on READ_VIN 0 -> !0
880 // STATUS_WORD with fault bits galore!
881 expectations.statusWordValue = 0xFFFF;
882 // STATUS_INPUT with fault bits on.
883 expectations.statusInputValue = 0xFF;
884 // STATUS_MFR_SPEFIC with bits on.
885 expectations.statusMFRValue = 0xFF;
886 // STATUS_CML with bits on.
887 expectations.statusCMLValue = 0xFF;
888 // STATUS_VOUT with bits on.
889 expectations.statusVOUTValue = 0xFF;
890 // STATUS_IOUT with bits on.
891 expectations.statusIOUTValue = 0xFF;
892 // STATUS_FANS_1_2 with bits on.
893 expectations.statusFans12Value = 0xFF;
894 // STATUS_TEMPERATURE with bits on.
895 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000896
897 // All faults degltiched now. Check for false before limit above.
898 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
899 {
900 setPMBusExpectations(mockPMBus, expectations);
901 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
902 .Times(1)
903 .WillOnce(Return("0"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600904 if (x == DEGLITCH_LIMIT)
905 {
906 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
907 }
Brandon Wymanc2906f42021-12-21 20:14:56 +0000908 psu.analyze();
909 }
910
Brandon Wyman82affd92021-11-24 19:12:49 +0000911 EXPECT_EQ(psu.isPresent(), true);
912 EXPECT_EQ(psu.isFaulted(), true);
913 EXPECT_EQ(psu.hasInputFault(), true);
914 EXPECT_EQ(psu.hasMFRFault(), true);
915 EXPECT_EQ(psu.hasVINUVFault(), true);
916 // True due to CML fault bits on
917 EXPECT_EQ(psu.hasCommFault(), true);
918 EXPECT_EQ(psu.hasVoutOVFault(), true);
919 EXPECT_EQ(psu.hasIoutOCFault(), true);
920 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
921 // Rely on HasVoutUVFault() to verify this sets and clears.
922 EXPECT_EQ(psu.hasVoutUVFault(), false);
923 EXPECT_EQ(psu.hasFanFault(), true);
924 EXPECT_EQ(psu.hasTempFault(), true);
Brandon Wymanc2906f42021-12-21 20:14:56 +0000925 EXPECT_EQ(psu.hasPgoodFault(), true);
Brandon Wyman82affd92021-11-24 19:12:49 +0000926 EXPECT_EQ(psu.hasPSKillFault(), true);
927 EXPECT_EQ(psu.hasPS12VcsFault(), true);
928 EXPECT_EQ(psu.hasPSCS12VFault(), true);
929 // STATUS_WORD with INPUT/VIN_UV fault bits off.
930 expectations.statusWordValue = 0xDFF7;
931 // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
932 // Insufficient Input Voltage bits off.
933 expectations.statusInputValue = 0xC7;
934 setPMBusExpectations(mockPMBus, expectations);
935 // READ_VIN back in range.
936 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
937 .Times(1)
938 .WillOnce(Return("206000"));
Brandon Wyman3225a452022-03-18 18:51:49 +0000939 // VIN_UV cleared via in1_lcrit_alarm when voltage back in range.
940 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
941 .Times(1)
942 .WillOnce(Return(1));
943 psu.analyze();
944 // We only cleared the VIN_UV and OFF faults.
945 EXPECT_EQ(psu.isPresent(), true);
946 EXPECT_EQ(psu.isFaulted(), true);
947 EXPECT_EQ(psu.hasInputFault(), false);
948 EXPECT_EQ(psu.hasMFRFault(), true);
949 EXPECT_EQ(psu.hasVINUVFault(), false);
950 EXPECT_EQ(psu.hasCommFault(), true);
951 EXPECT_EQ(psu.hasVoutOVFault(), true);
952 EXPECT_EQ(psu.hasIoutOCFault(), true);
953 EXPECT_EQ(psu.hasVoutUVFault(), false);
954 EXPECT_EQ(psu.hasFanFault(), true);
955 EXPECT_EQ(psu.hasTempFault(), true);
956 EXPECT_EQ(psu.hasPgoodFault(), true);
957 EXPECT_EQ(psu.hasPSKillFault(), true);
958 EXPECT_EQ(psu.hasPS12VcsFault(), true);
959 EXPECT_EQ(psu.hasPSCS12VFault(), true);
960
961 // All faults cleared
962 expectations = {0};
963 setPMBusExpectations(mockPMBus, expectations);
964 // READ_VIN back in range.
965 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
966 .Times(1)
967 .WillOnce(Return("206000"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600968 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman82affd92021-11-24 19:12:49 +0000969 psu.analyze();
970 EXPECT_EQ(psu.isPresent(), true);
971 EXPECT_EQ(psu.isFaulted(), false);
972 EXPECT_EQ(psu.hasInputFault(), false);
973 EXPECT_EQ(psu.hasMFRFault(), false);
974 EXPECT_EQ(psu.hasVINUVFault(), false);
975 EXPECT_EQ(psu.hasCommFault(), false);
976 EXPECT_EQ(psu.hasVoutOVFault(), false);
977 EXPECT_EQ(psu.hasIoutOCFault(), false);
978 EXPECT_EQ(psu.hasVoutUVFault(), false);
979 EXPECT_EQ(psu.hasFanFault(), false);
980 EXPECT_EQ(psu.hasTempFault(), false);
981 EXPECT_EQ(psu.hasPgoodFault(), false);
982 EXPECT_EQ(psu.hasPSKillFault(), false);
983 EXPECT_EQ(psu.hasPS12VcsFault(), false);
984 EXPECT_EQ(psu.hasPSCS12VFault(), false);
985
B. J. Wyman681b2a32021-04-20 22:31:22 +0000986 // TODO: Faults clear on missing/present?
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600987}
988
989TEST_F(PowerSupplyTests, UpdateInventory)
990{
991 auto bus = sdbusplus::bus::new_default();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500992
993 try
994 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000995 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500996 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
997 // If it is not present, I should not be trying to read a string
998 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
999 psu.updateInventory();
1000 }
1001 catch (...)
1002 {
1003 ADD_FAILURE() << "Should not have caught exception.";
1004 }
1005
1006 try
1007 {
B. J. Wyman681b2a32021-04-20 22:31:22 +00001008 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001009 MockedGPIOInterface* mockPresenceGPIO =
1010 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001011 // GPIO read return 1 to indicate present.
1012 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001013 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001014 setMissingToPresentExpects(mockPMBus, mockedUtil);
1015 // STATUS_WORD 0x0000 is powered on, no faults.
1016 PMBusExpectations expectations;
1017 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001018 // Call to analyze will read voltage, trigger clear faults for 0 to
1019 // within range.
1020 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1021 .Times(1)
1022 .WillOnce(Return("123456"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001023 psu.analyze();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001024 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
1025 psu.updateInventory();
1026
Brandon Wyman3c530fb2021-04-13 13:13:22 -05001027#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001028 EXPECT_CALL(mockPMBus, readString(_, _))
1029 .WillOnce(Return("CCIN"))
1030 .WillOnce(Return("PN3456"))
1031 .WillOnce(Return("FN3456"))
1032 .WillOnce(Return("HEADER"))
1033 .WillOnce(Return("SN3456"))
1034 .WillOnce(Return("FW3456"));
Brandon Wyman3c530fb2021-04-13 13:13:22 -05001035#endif
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001036 psu.updateInventory();
1037 // TODO: D-Bus mocking to verify values stored on D-Bus (???)
1038 }
1039 catch (...)
1040 {
1041 ADD_FAILURE() << "Should not have caught exception.";
1042 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001043}
1044
1045TEST_F(PowerSupplyTests, IsPresent)
1046{
1047 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001048
1049 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001050 MockedGPIOInterface* mockPresenceGPIO =
1051 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001052 EXPECT_EQ(psu.isPresent(), false);
1053
B. J. Wyman681b2a32021-04-20 22:31:22 +00001054 // Change GPIO read to return 1 to indicate present.
1055 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +00001056 // Call to analyze() will update to present, that will trigger updating
1057 // to the correct/latest HWMON directory, in case it changes.
1058 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1059 setMissingToPresentExpects(mockPMBus, mockedUtil);
1060 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1061 // Default expectations will be on, no faults.
1062 PMBusExpectations expectations;
1063 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001064 // Give it an input voltage in the 100-volt range.
1065 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1066 .Times(1)
1067 .WillOnce(Return("123456"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001068 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
B. J. Wyman681b2a32021-04-20 22:31:22 +00001069 psu.analyze();
1070 EXPECT_EQ(psu.isPresent(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001071}
1072
1073TEST_F(PowerSupplyTests, IsFaulted)
1074{
1075 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001076
1077 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001078 MockedGPIOInterface* mockPresenceGPIO =
1079 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001080 // Always return 1 to indicate present.
1081 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +00001082 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1083 setMissingToPresentExpects(mockPMBus, mockedUtil);
1084 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1085 // Default expectations will be on, no faults.
1086 PMBusExpectations expectations;
1087 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001088 // Give it an input voltage in the 100-volt range.
1089 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1090 .Times(1)
1091 .WillOnce(Return("124680"));
B. J. Wyman681b2a32021-04-20 22:31:22 +00001092 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001093 EXPECT_EQ(psu.isFaulted(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001094 // STATUS_WORD with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001095 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +00001096 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001097 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +00001098 // STATUS_MFR_SPECIFIC with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001099 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +00001100 // STATUS_CML with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001101 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +00001102 // STATUS_VOUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001103 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001104 // STATUS_IOUT with fault bits on.
1105 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001106 // STATUS_FANS_1_2 with bits on.
1107 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +00001108 // STATUS_TEMPERATURE with fault bits on.
1109 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001110 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1111 {
1112 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman4fc191f2022-03-10 23:07:13 +00001113 // Also get another read of READ_VIN, faulted, so not in 100-volt range
Brandon Wymanc2906f42021-12-21 20:14:56 +00001114 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1115 .Times(1)
Brandon Wyman4fc191f2022-03-10 23:07:13 +00001116 .WillOnce(Return("19000"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001117 if (x == DEGLITCH_LIMIT)
1118 {
1119 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1120 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001121 psu.analyze();
1122 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
1123 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001124}
1125
1126TEST_F(PowerSupplyTests, HasInputFault)
1127{
1128 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001129
1130 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001131 MockedGPIOInterface* mockPresenceGPIO =
1132 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001133 // Always return 1 to indicate present.
1134 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001135 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001136 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman8da35c52021-10-28 22:45:08 +00001137 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001138 PMBusExpectations expectations;
1139 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001140 // Analyze call will also need good READ_VIN value to check.
1141 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1142 .Times(1)
1143 .WillOnce(Return("201100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001144 psu.analyze();
1145 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001146 // STATUS_WORD with input fault/warn on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001147 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001148 // STATUS_INPUT with an input fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001149 expectations.statusInputValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001150 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1151 {
1152 setPMBusExpectations(mockPMBus, expectations);
1153 // Analyze call will also need good READ_VIN value to check.
1154 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1155 .Times(1)
1156 .WillOnce(Return("201200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001157 if (x == DEGLITCH_LIMIT)
1158 {
1159 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1160 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001161 psu.analyze();
1162 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
1163 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001164 // STATUS_WORD with no bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001165 expectations.statusWordValue = 0;
1166 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001167 // Analyze call will also need good READ_VIN value to check.
1168 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1169 .Times(1)
1170 .WillOnce(Return("201300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001171 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001172 psu.analyze();
1173 EXPECT_EQ(psu.hasInputFault(), false);
1174}
1175
1176TEST_F(PowerSupplyTests, HasMFRFault)
1177{
1178 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001179
1180 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001181 MockedGPIOInterface* mockPresenceGPIO =
1182 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001183 // Always return 1 to indicate present.
1184 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001185 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001186 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001187 // First return STATUS_WORD with no bits on.
Brandon Wyman8da35c52021-10-28 22:45:08 +00001188 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001189 PMBusExpectations expectations;
1190 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001191 // Analyze call will also need good READ_VIN value to check.
1192 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1193 .Times(1)
1194 .WillOnce(Return("202100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001195 psu.analyze();
1196 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001197 // Next return STATUS_WORD with MFR fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001198 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001199 // STATUS_MFR_SPEFIC with bit(s) on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001200 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001201 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1202 {
1203 setPMBusExpectations(mockPMBus, expectations);
1204 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1205 .Times(1)
1206 .WillOnce(Return("202200"));
1207 psu.analyze();
1208 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1209 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001210 // Back to no bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001211 expectations.statusWordValue = 0;
1212 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001213 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1214 .Times(1)
1215 .WillOnce(Return("202300"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001216 psu.analyze();
1217 EXPECT_EQ(psu.hasMFRFault(), false);
1218}
1219
1220TEST_F(PowerSupplyTests, HasVINUVFault)
1221{
1222 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001223
1224 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001225 MockedGPIOInterface* mockPresenceGPIO =
1226 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001227 // Always return 1 to indicate present.
1228 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001229 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001230 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman82affd92021-11-24 19:12:49 +00001231
1232 // Presence change from missing to present will trigger in1_input read in
1233 // an attempt to get CLEAR_FAULTS called. Return value ignored.
1234 // Zero to non-zero voltage, for missing/present change, triggers clear
1235 // faults call again. Return value ignored.
1236 // Fault (low voltage) to not faulted (voltage in range) triggers clear
1237 // faults call a third time.
1238
Brandon Wyman8da35c52021-10-28 22:45:08 +00001239 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001240 PMBusExpectations expectations;
1241 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001242 // Analyze call will also need good READ_VIN value to check.
1243 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1244 .Times(1)
1245 .WillOnce(Return("201100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001246 psu.analyze();
1247 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001248 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001249 expectations.statusWordValue = (status_word::VIN_UV_FAULT);
Brandon Wyman85c7bf42021-10-19 22:28:48 +00001250 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
1251 // Figure 16, and assume bits on in STATUS_INPUT.
Brandon Wymanb654c612021-11-05 23:24:51 +00001252 expectations.statusInputValue = 0x18;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001253 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1254 {
1255 setPMBusExpectations(mockPMBus, expectations);
1256 // If there is a VIN_UV fault, fake reading voltage of less than 20V
1257 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1258 .Times(1)
1259 .WillOnce(Return("19876"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001260 if (x == DEGLITCH_LIMIT)
1261 {
1262 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1263 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001264 psu.analyze();
1265 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1266 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001267 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001268 expectations.statusWordValue = 0;
1269 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001270 // Updates now result in clearing faults if read voltage goes from below the
1271 // minimum, to within a valid range.
1272 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1273 .Times(1)
1274 .WillOnce(Return("201300"));
Brandon Wyman3225a452022-03-18 18:51:49 +00001275 // Went from below minimum to within range, expect clearVinUVFault().
1276 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
1277 .Times(1)
1278 .WillOnce(Return(1));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001279 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001280 psu.analyze();
1281 EXPECT_EQ(psu.hasVINUVFault(), false);
1282}
Brandon Wyman6710ba22021-10-27 17:39:31 +00001283
1284TEST_F(PowerSupplyTests, HasVoutOVFault)
1285{
1286 auto bus = sdbusplus::bus::new_default();
1287
1288 PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName};
1289 MockedGPIOInterface* mockPresenceGPIO =
1290 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1291 // Always return 1 to indicate present.
1292 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001293 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001294 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman6710ba22021-10-27 17:39:31 +00001295 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001296 PMBusExpectations expectations;
1297 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001298 // Call to analyze will trigger read of "in1_input" to check voltage.
1299 // Initial value would be 0, so this read updates it to non-zero.
1300 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1301 .Times(1)
1302 .WillOnce(Return("202100"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001303 psu.analyze();
1304 EXPECT_EQ(psu.hasVoutOVFault(), false);
1305 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001306 expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
Brandon Wyman6710ba22021-10-27 17:39:31 +00001307 // STATUS_VOUT fault bit(s)
Brandon Wymanb654c612021-11-05 23:24:51 +00001308 expectations.statusVOUTValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001309 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1310 {
1311 setPMBusExpectations(mockPMBus, expectations);
1312 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1313 .Times(1)
1314 .WillOnce(Return("202200"));
1315 psu.analyze();
1316 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1317 }
Brandon Wyman6710ba22021-10-27 17:39:31 +00001318 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001319 expectations.statusWordValue = 0;
1320 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001321 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1322 .Times(1)
1323 .WillOnce(Return("202300"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001324 psu.analyze();
1325 EXPECT_EQ(psu.hasVoutOVFault(), false);
1326}
Brandon Wyman96893a42021-11-05 19:56:57 +00001327
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001328TEST_F(PowerSupplyTests, HasIoutOCFault)
1329{
1330 auto bus = sdbusplus::bus::new_default();
1331
1332 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
1333 MockedGPIOInterface* mockPresenceGPIO =
1334 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1335 // Always return 1 to indicate present.
1336 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001337 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001338 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001339 // STATUS_WORD 0x0000 is powered on, no faults.
1340 PMBusExpectations expectations;
1341 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001342 // Call to analyze will trigger read of "in1_input" to check voltage.
1343 // Initial value would be 0, so this read updates it to non-zero.
1344 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1345 .Times(1)
1346 .WillOnce(Return("203100"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001347 psu.analyze();
1348 EXPECT_EQ(psu.hasIoutOCFault(), false);
1349 // Turn fault on.
1350 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1351 // STATUS_IOUT fault bit(s)
1352 expectations.statusIOUTValue = 0x88;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001353 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1354 {
1355 setPMBusExpectations(mockPMBus, expectations);
1356 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1357 .Times(1)
1358 .WillOnce(Return("203200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001359 if (x == DEGLITCH_LIMIT)
1360 {
1361 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1362 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001363 psu.analyze();
1364 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1365 }
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001366 // Back to no fault bits on in STATUS_WORD
1367 expectations.statusWordValue = 0;
1368 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001369 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1370 .Times(1)
1371 .WillOnce(Return("203300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001372 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001373 psu.analyze();
1374 EXPECT_EQ(psu.hasIoutOCFault(), false);
1375}
1376
Brandon Wyman2cf46942021-10-28 19:09:16 +00001377TEST_F(PowerSupplyTests, HasVoutUVFault)
1378{
1379 auto bus = sdbusplus::bus::new_default();
1380
1381 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
1382 MockedGPIOInterface* mockPresenceGPIO =
1383 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1384 // Always return 1 to indicate present.
1385 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001386 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001387 setMissingToPresentExpects(mockPMBus, mockedUtil);
1388 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wyman2cf46942021-10-28 19:09:16 +00001389 PMBusExpectations expectations;
1390 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001391 // Call to analyze will trigger read of "in1_input" to check voltage.
1392 // Initial value would be 0, so this read updates it to non-zero.
1393 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1394 .Times(1)
1395 .WillOnce(Return("204100"));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001396 psu.analyze();
1397 EXPECT_EQ(psu.hasVoutUVFault(), false);
1398 // Turn fault on.
1399 expectations.statusWordValue = (status_word::VOUT_FAULT);
1400 // STATUS_VOUT fault bit(s)
1401 expectations.statusVOUTValue = 0x30;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001402 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1403 {
1404 setPMBusExpectations(mockPMBus, expectations);
1405 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1406 .Times(1)
1407 .WillOnce(Return("204200"));
1408 psu.analyze();
1409 EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1410 }
Brandon Wyman2cf46942021-10-28 19:09:16 +00001411 // Back to no fault bits on in STATUS_WORD
1412 expectations.statusWordValue = 0;
1413 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001414 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1415 .Times(1)
1416 .WillOnce(Return("204300"));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001417 psu.analyze();
1418 EXPECT_EQ(psu.hasVoutUVFault(), false);
1419}
1420
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001421TEST_F(PowerSupplyTests, HasFanFault)
1422{
1423 auto bus = sdbusplus::bus::new_default();
1424
Matt Spinler0975eaf2022-02-14 15:38:30 -06001425 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
1426 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
1427
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001428 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
1429 MockedGPIOInterface* mockPresenceGPIO =
1430 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1431 // Always return 1 to indicate present.
1432 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001433 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001434 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001435 // STATUS_WORD 0x0000 is powered on, no faults.
1436 PMBusExpectations expectations;
1437 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001438 // Call to analyze will trigger read of "in1_input" to check voltage.
1439 // Initial value would be 0, so this read updates it to non-zero.
1440 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1441 .Times(1)
1442 .WillOnce(Return("205100"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001443 psu.analyze();
1444 EXPECT_EQ(psu.hasFanFault(), false);
1445 // Turn fault on.
1446 expectations.statusWordValue = (status_word::FAN_FAULT);
1447 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
1448 expectations.statusFans12Value = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001449 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1450 {
1451 setPMBusExpectations(mockPMBus, expectations);
1452 // Call to analyze will trigger read of "in1_input" to check voltage.
1453 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1454 .Times(1)
1455 .WillOnce(Return("205200"));
1456 psu.analyze();
1457 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1458 }
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001459 // Back to no fault bits on in STATUS_WORD
1460 expectations.statusWordValue = 0;
1461 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001462 // Call to analyze will trigger read of "in1_input" to check voltage.
1463 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1464 .Times(1)
1465 .WillOnce(Return("205300"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001466 psu.analyze();
1467 EXPECT_EQ(psu.hasFanFault(), false);
1468}
1469
Brandon Wyman96893a42021-11-05 19:56:57 +00001470TEST_F(PowerSupplyTests, HasTempFault)
1471{
1472 auto bus = sdbusplus::bus::new_default();
1473
Matt Spinler0975eaf2022-02-14 15:38:30 -06001474 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
1475 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
1476
Brandon Wyman96893a42021-11-05 19:56:57 +00001477 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
1478 MockedGPIOInterface* mockPresenceGPIO =
1479 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1480 // Always return 1 to indicate present.
1481 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman96893a42021-11-05 19:56:57 +00001482 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001483 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman96893a42021-11-05 19:56:57 +00001484 // STATUS_WORD 0x0000 is powered on, no faults.
1485 PMBusExpectations expectations;
1486 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001487 // Call to analyze will trigger read of "in1_input" to check voltage.
1488 // Initial value would be 0, so this read updates it to non-zero.
1489 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1490 .Times(1)
1491 .WillOnce(Return("206100"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001492 psu.analyze();
1493 EXPECT_EQ(psu.hasTempFault(), false);
1494 // Turn fault on.
1495 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
1496 // STATUS_TEMPERATURE fault bit on (OT Fault)
1497 expectations.statusTempValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001498 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1499 {
1500 setPMBusExpectations(mockPMBus, expectations);
1501 // 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("206200"));
1505 psu.analyze();
1506 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1507 }
Brandon Wyman96893a42021-11-05 19:56:57 +00001508 // Back to no fault bits on in STATUS_WORD
1509 expectations.statusWordValue = 0;
1510 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001511 // Call to analyze will trigger read of "in1_input" to check voltage.
1512 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1513 .Times(1)
1514 .WillOnce(Return("206300"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001515 psu.analyze();
1516 EXPECT_EQ(psu.hasTempFault(), false);
1517}
Brandon Wyman2916ea52021-11-06 03:31:18 +00001518
1519TEST_F(PowerSupplyTests, HasPgoodFault)
1520{
1521 auto bus = sdbusplus::bus::new_default();
1522
1523 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, PSUGPIOLineName};
1524 MockedGPIOInterface* mockPresenceGPIO =
1525 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1526 // Always return 1 to indicate present.
1527 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001528 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001529 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman2916ea52021-11-06 03:31:18 +00001530 // STATUS_WORD 0x0000 is powered on, no faults.
1531 PMBusExpectations expectations;
1532 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001533 // Call to analyze will trigger read of "in1_input" to check voltage.
1534 // Initial value would be 0, so this read updates it to non-zero.
1535 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1536 .Times(1)
1537 .WillOnce(Return("207100"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001538 psu.analyze();
1539 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman391a0692021-12-08 23:28:18 +00001540 // Setup another expectation of no faults.
1541 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001542 // Call to analyze will trigger read of "in1_input" to check voltage.
1543 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1544 .Times(1)
1545 .WillOnce(Return("207200"));
1546 psu.analyze();
1547 EXPECT_EQ(psu.hasPgoodFault(), false);
1548 // Setup another expectation of no faults.
1549 setPMBusExpectations(mockPMBus, expectations);
1550 // Call to analyze will trigger read of "in1_input" to check voltage.
1551 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1552 .Times(1)
1553 .WillOnce(Return("207300"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001554 psu.analyze();
1555 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +00001556 // Turn PGOOD# off (fault on).
1557 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
1558 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001559 // 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("207400"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001563 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001564 // Expect false until reaches DEGLITCH_LIMIT
1565 EXPECT_EQ(psu.hasPgoodFault(), false);
1566 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001567 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1568 .Times(1)
1569 .WillOnce(Return("207500"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001570 psu.analyze();
1571 // Expect false until reaches DEGLITCH_LIMIT
1572 EXPECT_EQ(psu.hasPgoodFault(), false);
1573 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001574 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1575 .Times(1)
1576 .WillOnce(Return("207600"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001577 psu.analyze();
1578 // DEGLITCH_LIMIT reached, expect true.
Brandon Wyman2916ea52021-11-06 03:31:18 +00001579 EXPECT_EQ(psu.hasPgoodFault(), true);
1580 // Back to no fault bits on in STATUS_WORD
1581 expectations.statusWordValue = 0;
1582 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001583 // Call to analyze will trigger read of "in1_input" to check voltage.
1584 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1585 .Times(1)
1586 .WillOnce(Return("207700"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001587 psu.analyze();
1588 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman82affd92021-11-24 19:12:49 +00001589
Brandon Wyman2916ea52021-11-06 03:31:18 +00001590 // Turn OFF bit on
1591 expectations.statusWordValue = (status_word::UNIT_IS_OFF);
1592 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001593 // Call to analyze will trigger read of "in1_input" to check voltage.
1594 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1595 .Times(1)
1596 .WillOnce(Return("208100"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001597 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001598 EXPECT_EQ(psu.hasPgoodFault(), false);
1599 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001600 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1601 .Times(1)
1602 .WillOnce(Return("208200"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001603 psu.analyze();
1604 EXPECT_EQ(psu.hasPgoodFault(), false);
1605 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001606 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1607 .Times(1)
1608 .WillOnce(Return("208300"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001609 psu.analyze();
Brandon Wyman2916ea52021-11-06 03:31:18 +00001610 EXPECT_EQ(psu.hasPgoodFault(), true);
1611 // Back to no fault bits on in STATUS_WORD
1612 expectations.statusWordValue = 0;
1613 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001614 // Call to analyze will trigger read of "in1_input" to check voltage.
1615 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1616 .Times(1)
1617 .WillOnce(Return("208400"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001618 psu.analyze();
1619 EXPECT_EQ(psu.hasPgoodFault(), false);
1620}
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001621
1622TEST_F(PowerSupplyTests, HasPSKillFault)
1623{
1624 auto bus = sdbusplus::bus::new_default();
1625 PowerSupply psu{bus, PSUInventoryPath, 4, 0x6d, PSUGPIOLineName};
1626 MockedGPIOInterface* mockPresenceGPIO =
1627 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1628 // Always return 1 to indicate present.
1629 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001630 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001631 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001632 // STATUS_WORD 0x0000 is powered on, no faults.
1633 PMBusExpectations expectations;
1634 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001635 // Call to analyze will trigger read of "in1_input" to check voltage.
1636 // Initial value would be 0, so this read updates it to non-zero.
1637 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1638 .Times(1)
1639 .WillOnce(Return("208100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001640 psu.analyze();
1641 EXPECT_EQ(psu.hasPSKillFault(), false);
1642 // Next return STATUS_WORD with MFR fault bit on.
1643 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1644 // STATUS_MFR_SPEFIC with bit(s) on.
1645 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001646
1647 // Deglitching faults, false until read the fault bits on up to the limit.
1648 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1649 {
1650 setPMBusExpectations(mockPMBus, expectations);
1651 // Call to analyze will trigger read of "in1_input" to check voltage.
1652 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1653 .Times(1)
1654 .WillOnce(Return("208200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001655 if (x == DEGLITCH_LIMIT)
1656 {
1657 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1658 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001659 psu.analyze();
1660 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1661 }
1662
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001663 // Back to no bits on in STATUS_WORD
1664 expectations.statusWordValue = 0;
1665 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001666 // Call to analyze will trigger read of "in1_input" to check voltage.
1667 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1668 .Times(1)
1669 .WillOnce(Return("208300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001670 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001671 psu.analyze();
1672 EXPECT_EQ(psu.hasPSKillFault(), false);
1673 // Next return STATUS_WORD with MFR fault bit on.
1674 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1675 // STATUS_MFR_SPEFIC with bit 4 on.
1676 expectations.statusMFRValue = 0x10;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001677
1678 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1679 {
1680 setPMBusExpectations(mockPMBus, expectations);
1681 // Call to analyze will trigger read of "in1_input" to check voltage.
1682 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1683 .Times(1)
1684 .WillOnce(Return("208400"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001685 if (x == DEGLITCH_LIMIT)
1686 {
1687 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1688 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001689 psu.analyze();
1690 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1691 }
1692
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001693 // Back to no bits on in STATUS_WORD
1694 expectations.statusWordValue = 0;
1695 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001696 // Call to analyze will trigger read of "in1_input" to check voltage.
1697 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1698 .Times(1)
1699 .WillOnce(Return("208500"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001700 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001701 psu.analyze();
1702 EXPECT_EQ(psu.hasPSKillFault(), false);
1703}
1704
1705TEST_F(PowerSupplyTests, HasPS12VcsFault)
1706{
1707 auto bus = sdbusplus::bus::new_default();
1708 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6e, PSUGPIOLineName};
1709 MockedGPIOInterface* mockPresenceGPIO =
1710 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1711 // Always return 1 to indicate present.
1712 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001713 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001714 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001715 // STATUS_WORD 0x0000 is powered on, no faults.
1716 PMBusExpectations expectations;
1717 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001718 // Call to analyze will trigger read of "in1_input" to check voltage.
1719 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1720 .Times(1)
1721 .WillOnce(Return("209100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001722 psu.analyze();
1723 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1724 // Next return STATUS_WORD with MFR fault bit on.
1725 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1726 // STATUS_MFR_SPEFIC with bit(s) on.
1727 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001728
1729 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1730 {
1731 setPMBusExpectations(mockPMBus, expectations);
1732 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1733 .Times(1)
1734 .WillOnce(Return("209200"));
1735 psu.analyze();
1736 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1737 }
1738
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001739 // Back to no bits on in STATUS_WORD
1740 expectations.statusWordValue = 0;
1741 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001742 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1743 .Times(1)
1744 .WillOnce(Return("209300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001745 psu.analyze();
1746 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1747 // Next return STATUS_WORD with MFR fault bit on.
1748 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1749 // STATUS_MFR_SPEFIC with bit 6 on.
1750 expectations.statusMFRValue = 0x40;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001751
1752 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1753 {
1754 setPMBusExpectations(mockPMBus, expectations);
1755 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1756 .Times(1)
1757 .WillOnce(Return("209400"));
1758 psu.analyze();
1759 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1760 }
1761
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001762 // Back to no bits on in STATUS_WORD
1763 expectations.statusWordValue = 0;
1764 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001765 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1766 .Times(1)
1767 .WillOnce(Return("209500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001768 psu.analyze();
1769 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1770}
1771
1772TEST_F(PowerSupplyTests, HasPSCS12VFault)
1773{
1774 auto bus = sdbusplus::bus::new_default();
1775 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f, PSUGPIOLineName};
1776 MockedGPIOInterface* mockPresenceGPIO =
1777 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1778 // Always return 1 to indicate present.
1779 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001780 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001781 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001782 // STATUS_WORD 0x0000 is powered on, no faults.
1783 PMBusExpectations expectations;
1784 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001785 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1786 .Times(1)
1787 .WillOnce(Return("209100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001788 psu.analyze();
1789 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1790 // Next return STATUS_WORD with MFR fault bit on.
1791 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1792 // STATUS_MFR_SPEFIC with bit(s) on.
1793 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001794
1795 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1796 {
1797 setPMBusExpectations(mockPMBus, expectations);
1798 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1799 .Times(1)
1800 .WillOnce(Return("209200"));
1801 psu.analyze();
1802 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1803 }
1804
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001805 // Back to no bits on in STATUS_WORD
1806 expectations.statusWordValue = 0;
1807 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001808 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1809 .Times(1)
1810 .WillOnce(Return("209300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001811 psu.analyze();
1812 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1813 // Next return STATUS_WORD with MFR fault bit on.
1814 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1815 // STATUS_MFR_SPEFIC with bit 7 on.
1816 expectations.statusMFRValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001817
1818 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1819 {
1820 setPMBusExpectations(mockPMBus, expectations);
1821 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1822 .Times(1)
1823 .WillOnce(Return("209400"));
1824 psu.analyze();
1825 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1826 }
1827
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001828 // Back to no bits on in STATUS_WORD
1829 expectations.statusWordValue = 0;
1830 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001831 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1832 .Times(1)
1833 .WillOnce(Return("209500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001834 psu.analyze();
1835 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1836}