blob: 88caee88c2e158b73865b2d8ef26ebe9043ff9ff [file] [log] [blame]
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001#include "../power_supply.hpp"
Brandon Wymanc3324422022-03-24 20:30:57 +00002#include "../record_manager.hpp"
Brandon Wyman3f1242f2020-01-28 13:11:25 -06003#include "mock.hpp"
4
5#include <xyz/openbmc_project/Common/Device/error.hpp>
6#include <xyz/openbmc_project/Common/error.hpp>
7
8#include <gmock/gmock.h>
9#include <gtest/gtest.h>
10
11using namespace phosphor::power::psu;
12using namespace phosphor::pmbus;
13
14using ::testing::_;
Brandon Wyman59a35792020-06-04 12:37:40 -050015using ::testing::Args;
Brandon Wyman3f1242f2020-01-28 13:11:25 -060016using ::testing::Assign;
17using ::testing::DoAll;
Brandon Wyman59a35792020-06-04 12:37:40 -050018using ::testing::ElementsAre;
19using ::testing::NotNull;
Brandon Wyman3f1242f2020-01-28 13:11:25 -060020using ::testing::Return;
21using ::testing::StrEq;
22
23static auto PSUInventoryPath = "/xyz/bmc/inv/sys/chassis/board/powersupply0";
B. J. Wyman681b2a32021-04-20 22:31:22 +000024static auto PSUGPIOLineName = "presence-ps0";
Brandon Wyman3f1242f2020-01-28 13:11:25 -060025
Brandon Wymanb654c612021-11-05 23:24:51 +000026struct PMBusExpectations
27{
28 uint16_t statusWordValue{0x0000};
29 uint8_t statusInputValue{0x00};
30 uint8_t statusMFRValue{0x00};
31 uint8_t statusCMLValue{0x00};
32 uint8_t statusVOUTValue{0x00};
Brandon Wymanb10b3be2021-11-09 22:12:15 +000033 uint8_t statusIOUTValue{0x00};
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +000034 uint8_t statusFans12Value{0x00};
Brandon Wyman96893a42021-11-05 19:56:57 +000035 uint8_t statusTempValue{0x00};
Brandon Wymanb654c612021-11-05 23:24:51 +000036};
37
Brandon Wyman8da35c52021-10-28 22:45:08 +000038// Helper function to setup expectations for various STATUS_* commands
Brandon Wymanb654c612021-11-05 23:24:51 +000039void setPMBusExpectations(MockedPMBus& mockPMBus,
40 const PMBusExpectations& expectations)
Brandon Wyman8da35c52021-10-28 22:45:08 +000041{
Brandon Wyman32453e92021-12-15 19:00:14 +000042 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000043 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000044 .WillOnce(Return(expectations.statusWordValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000045
Brandon Wymanb654c612021-11-05 23:24:51 +000046 if (expectations.statusWordValue != 0)
Brandon Wyman8da35c52021-10-28 22:45:08 +000047 {
48 // If fault bits are on in STATUS_WORD, there will also be a read of
Brandon Wyman96893a42021-11-05 19:56:57 +000049 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and
50 // STATUS_TEMPERATURE.
Brandon Wyman32453e92021-12-15 19:00:14 +000051 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000052 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000053 .WillOnce(Return(expectations.statusInputValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000054 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000055 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000056 .WillOnce(Return(expectations.statusMFRValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000057 EXPECT_CALL(mockPMBus, read(STATUS_CML, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000058 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000059 .WillOnce(Return(expectations.statusCMLValue));
Brandon Wyman6710ba22021-10-27 17:39:31 +000060 // Page will need to be set to 0 to read STATUS_VOUT.
61 EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0))
62 .Times(1)
63 .WillOnce(Return("status0_vout"));
Brandon Wyman32453e92021-12-15 19:00:14 +000064 EXPECT_CALL(mockPMBus, read("status0_vout", _, _))
Brandon Wyman6710ba22021-10-27 17:39:31 +000065 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000066 .WillOnce(Return(expectations.statusVOUTValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000067 EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _, _))
Brandon Wymanb10b3be2021-11-09 22:12:15 +000068 .Times(1)
69 .WillOnce(Return(expectations.statusIOUTValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000070 EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _, _))
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +000071 .Times(1)
72 .WillOnce(Return(expectations.statusFans12Value));
Brandon Wyman32453e92021-12-15 19:00:14 +000073 EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _, _))
Brandon Wyman96893a42021-11-05 19:56:57 +000074 .Times(1)
75 .WillOnce(Return(expectations.statusTempValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000076 }
77}
78
Brandon Wyman3f1242f2020-01-28 13:11:25 -060079class PowerSupplyTests : public ::testing::Test
80{
81 public:
82 PowerSupplyTests() :
83 mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
84 {
85 ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
86 }
87
88 ~PowerSupplyTests() override
89 {
90 freeUtils();
91 }
92
93 const MockedUtil& mockedUtil;
94};
95
Brandon Wyman391a0692021-12-08 23:28:18 +000096// Helper function for when a power supply goes from missing to present.
97void setMissingToPresentExpects(MockedPMBus& pmbus, const MockedUtil& util)
98{
99 // Call to analyze() will update to present, that will trigger updating
100 // to the correct/latest HWMON directory, in case it changes.
101 EXPECT_CALL(pmbus, findHwmonDir());
102 // Presence change from missing to present will trigger write to
103 // ON_OFF_CONFIG.
104 EXPECT_CALL(pmbus, writeBinary(ON_OFF_CONFIG, _, _));
105 // Presence change from missing to present will trigger in1_input read
106 // in an attempt to get CLEAR_FAULTS called.
Brandon Wyman82affd92021-11-24 19:12:49 +0000107 // This READ_VIN for CLEAR_FAULTS does not check the returned value.
Brandon Wyman3225a452022-03-18 18:51:49 +0000108 EXPECT_CALL(pmbus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
109 // The call for clearing faults includes clearing VIN_UV fault.
110 // The voltage defaults to 0, the first call to analyze should update the
111 // voltage to the current reading, triggering clearing VIN_UV fault(s)
112 // due to below minimum to within range voltage.
113 EXPECT_CALL(pmbus, read("in1_lcrit_alarm", _, _))
Brandon Wyman82affd92021-11-24 19:12:49 +0000114 .Times(2)
Brandon Wyman3225a452022-03-18 18:51:49 +0000115 .WillRepeatedly(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +0000116 // Missing/present call will update Presence in inventory.
Brandon Wyman391a0692021-12-08 23:28:18 +0000117 EXPECT_CALL(util, setPresence(_, _, true, _));
118}
119
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600120TEST_F(PowerSupplyTests, Constructor)
121{
122 /**
123 * @param[in] invpath - String for inventory path to use
124 * @param[in] i2cbus - The bus number this power supply is on
125 * @param[in] i2caddr - The 16-bit I2C address of the power supply
B. J. Wyman681b2a32021-04-20 22:31:22 +0000126 * @param[in] gpioLineName - The string for the gpio-line-name to read for
127 * presence.
128 * @param[in] bindDelay - Time in milliseconds to delay binding the device
129 * driver after seeing the presence line go active.
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600130 */
131 auto bus = sdbusplus::bus::new_default();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600132
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500133 // Try where inventory path is empty, constructor should fail.
134 try
135 {
Brandon Wymanc3324422022-03-24 20:30:57 +0000136 auto psu = std::make_unique<PowerSupply>(bus, "", 3, 0x68, "ibm-cffps",
137 PSUGPIOLineName);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500138 ADD_FAILURE() << "Should not have reached this line.";
139 }
140 catch (const std::invalid_argument& e)
141 {
142 EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
143 }
144 catch (...)
145 {
146 ADD_FAILURE() << "Should not have caught exception.";
147 }
148
B. J. Wyman681b2a32021-04-20 22:31:22 +0000149 // TODO: Try invalid i2c address?
150
151 // Try where gpioLineName is empty.
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500152 try
153 {
Brandon Wymanc3324422022-03-24 20:30:57 +0000154 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
155 "ibm-cffps", "");
B. J. Wyman681b2a32021-04-20 22:31:22 +0000156 ADD_FAILURE()
157 << "Should not have reached this line. Invalid gpioLineName.";
158 }
159 catch (const std::invalid_argument& e)
160 {
161 EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
162 }
163 catch (...)
164 {
165 ADD_FAILURE() << "Should not have caught exception.";
166 }
167
168 // Test with valid arguments
169 // NOT using D-Bus inventory path for presence.
170 try
171 {
172 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
Brandon Wymanc3324422022-03-24 20:30:57 +0000173 "ibm-cffps", PSUGPIOLineName);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500174
175 EXPECT_EQ(psu->isPresent(), false);
176 EXPECT_EQ(psu->isFaulted(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000177 EXPECT_EQ(psu->hasCommFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500178 EXPECT_EQ(psu->hasInputFault(), false);
179 EXPECT_EQ(psu->hasMFRFault(), false);
180 EXPECT_EQ(psu->hasVINUVFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000181 EXPECT_EQ(psu->hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000182 EXPECT_EQ(psu->hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000183 EXPECT_EQ(psu->hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000184 EXPECT_EQ(psu->hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000185 EXPECT_EQ(psu->hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000186 EXPECT_EQ(psu->hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000187 EXPECT_EQ(psu->hasPSKillFault(), false);
188 EXPECT_EQ(psu->hasPS12VcsFault(), false);
189 EXPECT_EQ(psu->hasPSCS12VFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500190 }
191 catch (...)
192 {
193 ADD_FAILURE() << "Should not have caught exception.";
194 }
B. J. Wyman681b2a32021-04-20 22:31:22 +0000195
196 // Test with valid arguments
197 // TODO: Using D-Bus inventory path for presence.
198 try
199 {
200 // FIXME: How do I get that presenceGPIO.read() in the startup to throw
201 // an exception?
202
203 // EXPECT_CALL(mockedUtil, getPresence(_,
204 // StrEq(PSUInventoryPath)))
205 // .Times(1);
206 }
207 catch (...)
208 {
209 ADD_FAILURE() << "Should not have caught exception.";
210 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600211}
212
213TEST_F(PowerSupplyTests, Analyze)
214{
215 auto bus = sdbusplus::bus::new_default();
216
Brandon Wymanb654c612021-11-05 23:24:51 +0000217 {
218 // If I default to reading the GPIO, I will NOT expect a call to
219 // getPresence().
B. J. Wyman681b2a32021-04-20 22:31:22 +0000220
Brandon Wymanc3324422022-03-24 20:30:57 +0000221 PowerSupply psu{bus, PSUInventoryPath, 4,
222 0x69, "ibm-cffps", PSUGPIOLineName};
Brandon Wymanb654c612021-11-05 23:24:51 +0000223 MockedGPIOInterface* mockPresenceGPIO =
224 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
225 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000226
Brandon Wymanb654c612021-11-05 23:24:51 +0000227 psu.analyze();
228 // By default, nothing should change.
229 EXPECT_EQ(psu.isPresent(), false);
230 EXPECT_EQ(psu.isFaulted(), false);
231 EXPECT_EQ(psu.hasInputFault(), false);
232 EXPECT_EQ(psu.hasMFRFault(), false);
233 EXPECT_EQ(psu.hasVINUVFault(), false);
234 EXPECT_EQ(psu.hasCommFault(), false);
235 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000236 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000237 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000238 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000239 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000240 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000241 EXPECT_EQ(psu.hasPSKillFault(), false);
242 EXPECT_EQ(psu.hasPS12VcsFault(), false);
243 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000244 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600245
Brandon Wymanc3324422022-03-24 20:30:57 +0000246 PowerSupply psu2{bus, PSUInventoryPath, 5,
247 0x6a, "ibm-cffps", PSUGPIOLineName};
B. J. Wyman681b2a32021-04-20 22:31:22 +0000248 // In order to get the various faults tested, the power supply needs to
249 // be present in order to read from the PMBus device(s).
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000250 MockedGPIOInterface* mockPresenceGPIO2 =
251 static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000252 // Always return 1 to indicate present.
253 // Each analyze() call will trigger a read of the presence GPIO.
254 EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000255 EXPECT_EQ(psu2.isPresent(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600256
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600257 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000258 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600259
Brandon Wymanb654c612021-11-05 23:24:51 +0000260 // STATUS_WORD INPUT fault.
261 {
262 // Start with STATUS_WORD 0x0000. Powered on, no faults.
263 // Set expectations for a no fault
264 PMBusExpectations expectations;
265 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000266 // After reading STATUS_WORD, etc., there will be a READ_VIN check.
267 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
268 .Times(1)
269 .WillOnce(Return("206000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000270 psu2.analyze();
271 EXPECT_EQ(psu2.isPresent(), true);
272 EXPECT_EQ(psu2.isFaulted(), false);
273 EXPECT_EQ(psu2.hasInputFault(), false);
274 EXPECT_EQ(psu2.hasMFRFault(), false);
275 EXPECT_EQ(psu2.hasVINUVFault(), false);
276 EXPECT_EQ(psu2.hasCommFault(), false);
277 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000278 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000279 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000280 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000281 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000282 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000283 EXPECT_EQ(psu2.hasPSKillFault(), false);
284 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
285 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000286
287 // Update expectations for STATUS_WORD input fault/warn
Brandon Wyman96893a42021-11-05 19:56:57 +0000288 // STATUS_INPUT fault bits ... on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000289 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wyman3225a452022-03-18 18:51:49 +0000290 // IIN_OC fault.
291 expectations.statusInputValue = 0x04;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000292
293 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
294 {
295 setPMBusExpectations(mockPMBus, expectations);
296 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
297 .Times(1)
298 .WillOnce(Return("207000"));
299 psu2.analyze();
300 EXPECT_EQ(psu2.isPresent(), true);
301 // Should not be faulted until it reaches the deglitch limit.
302 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
303 EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
304 EXPECT_EQ(psu2.hasMFRFault(), false);
305 EXPECT_EQ(psu2.hasVINUVFault(), false);
306 EXPECT_EQ(psu2.hasCommFault(), false);
307 EXPECT_EQ(psu2.hasVoutOVFault(), false);
308 EXPECT_EQ(psu2.hasIoutOCFault(), false);
309 EXPECT_EQ(psu2.hasVoutUVFault(), false);
310 EXPECT_EQ(psu2.hasFanFault(), false);
311 EXPECT_EQ(psu2.hasTempFault(), false);
312 EXPECT_EQ(psu2.hasPgoodFault(), false);
313 EXPECT_EQ(psu2.hasPSKillFault(), false);
314 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
315 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
316 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000317 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600318
Brandon Wyman32453e92021-12-15 19:00:14 +0000319 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000320 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
321 .Times(1)
322 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000323 psu2.clearFaults();
324
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600325 // STATUS_WORD INPUT/UV fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000326 {
327 // First need it to return good status, then the fault
328 PMBusExpectations expectations;
329 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000330 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
331 .Times(1)
332 .WillOnce(Return("208000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000333 psu2.analyze();
Brandon Wymanc2906f42021-12-21 20:14:56 +0000334 EXPECT_EQ(psu2.isFaulted(), false);
335 EXPECT_EQ(psu2.hasInputFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000336 // Now set fault bits in STATUS_WORD
337 expectations.statusWordValue =
338 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
339 // STATUS_INPUT fault bits ... on.
Brandon Wyman3225a452022-03-18 18:51:49 +0000340 expectations.statusInputValue = 0x18;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000341 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
342 {
343 setPMBusExpectations(mockPMBus, expectations);
344 // Input/UV fault, so voltage should read back low.
345 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
346 .Times(1)
347 .WillOnce(Return("19123"));
348 psu2.analyze();
349 EXPECT_EQ(psu2.isPresent(), true);
350 // Only faulted if hit deglitch limit
351 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
352 EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
353 EXPECT_EQ(psu2.hasVINUVFault(), x >= DEGLITCH_LIMIT);
354 EXPECT_EQ(psu2.hasMFRFault(), false);
355 EXPECT_EQ(psu2.hasCommFault(), false);
356 EXPECT_EQ(psu2.hasVoutOVFault(), false);
357 EXPECT_EQ(psu2.hasIoutOCFault(), false);
358 EXPECT_EQ(psu2.hasVoutUVFault(), false);
359 EXPECT_EQ(psu2.hasFanFault(), false);
360 EXPECT_EQ(psu2.hasTempFault(), false);
361 EXPECT_EQ(psu2.hasPgoodFault(), false);
362 EXPECT_EQ(psu2.hasPSKillFault(), false);
363 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
364 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
365 }
Brandon Wyman82affd92021-11-24 19:12:49 +0000366 // Turning VIN_UV fault off causes clearing of faults, causing read of
367 // in1_input as an attempt to get CLEAR_FAULTS called.
368 expectations.statusWordValue = 0;
369 setPMBusExpectations(mockPMBus, expectations);
370 // The call to read the voltage
371 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
372 .Times(1)
373 .WillOnce(Return("209000"));
Brandon Wyman3225a452022-03-18 18:51:49 +0000374 // The call to clear VIN_UV/Off fault(s)
375 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
Brandon Wyman32453e92021-12-15 19:00:14 +0000376 .Times(1)
Brandon Wyman3225a452022-03-18 18:51:49 +0000377 .WillOnce(Return(1));
Brandon Wyman82affd92021-11-24 19:12:49 +0000378 psu2.analyze();
379 // Should remain present, no longer be faulted, no input fault, no
380 // VIN_UV fault. Nothing else should change.
381 EXPECT_EQ(psu2.isPresent(), true);
382 EXPECT_EQ(psu2.isFaulted(), false);
383 EXPECT_EQ(psu2.hasInputFault(), false);
384 EXPECT_EQ(psu2.hasVINUVFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000385 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600386
Brandon Wyman32453e92021-12-15 19:00:14 +0000387 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000388 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
389 .Times(1)
390 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000391 psu2.clearFaults();
392
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600393 // STATUS_WORD MFR fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000394 {
395 // First need it to return good status, then the fault
396 PMBusExpectations expectations;
397 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000398 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
399 .Times(1)
400 .WillOnce(Return("210000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000401 psu2.analyze();
402 // Now STATUS_WORD with MFR fault bit on.
403 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
404 // STATUS_MFR bits on.
405 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000406
407 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
408 {
409 setPMBusExpectations(mockPMBus, expectations);
410 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
411 .Times(1)
412 .WillOnce(Return("211000"));
413 psu2.analyze();
414 EXPECT_EQ(psu2.isPresent(), true);
415 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
416 EXPECT_EQ(psu2.hasInputFault(), false);
417 EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT);
418 EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT);
419 EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
420 EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
421 EXPECT_EQ(psu2.hasVINUVFault(), false);
422 EXPECT_EQ(psu2.hasCommFault(), false);
423 EXPECT_EQ(psu2.hasVoutOVFault(), false);
424 EXPECT_EQ(psu2.hasIoutOCFault(), false);
425 EXPECT_EQ(psu2.hasVoutUVFault(), false);
426 EXPECT_EQ(psu2.hasFanFault(), false);
427 EXPECT_EQ(psu2.hasTempFault(), false);
428 EXPECT_EQ(psu2.hasPgoodFault(), false);
429 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000430 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600431
Brandon Wyman32453e92021-12-15 19:00:14 +0000432 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000433 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
434 .Times(1)
435 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000436 psu2.clearFaults();
Brandon Wyman3225a452022-03-18 18:51:49 +0000437
Brandon Wyman96893a42021-11-05 19:56:57 +0000438 // Temperature fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000439 {
440 // First STATUS_WORD with no bits set, then with temperature fault.
441 PMBusExpectations expectations;
442 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000443 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
444 .Times(1)
445 .WillOnce(Return("212000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000446 psu2.analyze();
447 // STATUS_WORD with temperature fault bit on.
448 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
Brandon Wyman96893a42021-11-05 19:56:57 +0000449 // STATUS_TEMPERATURE with fault bit(s) on.
450 expectations.statusTempValue = 0x10;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000451 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
452 {
453 setPMBusExpectations(mockPMBus, expectations);
454 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
455 .Times(1)
456 .WillOnce(Return("213000"));
457 psu2.analyze();
458 EXPECT_EQ(psu2.isPresent(), true);
459 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
460 EXPECT_EQ(psu2.hasInputFault(), false);
461 EXPECT_EQ(psu2.hasMFRFault(), false);
462 EXPECT_EQ(psu2.hasVINUVFault(), false);
463 EXPECT_EQ(psu2.hasCommFault(), false);
464 EXPECT_EQ(psu2.hasVoutOVFault(), false);
465 EXPECT_EQ(psu2.hasIoutOCFault(), false);
466 EXPECT_EQ(psu2.hasVoutUVFault(), false);
467 EXPECT_EQ(psu2.hasFanFault(), false);
468 EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT);
469 EXPECT_EQ(psu2.hasPgoodFault(), false);
470 EXPECT_EQ(psu2.hasPSKillFault(), false);
471 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
472 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
473 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000474 }
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000475
Brandon Wyman32453e92021-12-15 19:00:14 +0000476 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000477 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
478 .Times(1)
479 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000480 psu2.clearFaults();
Brandon Wyman3225a452022-03-18 18:51:49 +0000481
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000482 // CML fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000483 {
484 // First STATUS_WORD wit no bits set, then with CML fault.
485 PMBusExpectations expectations;
486 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000487 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
488 .Times(1)
489 .WillOnce(Return("214000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000490 psu2.analyze();
491 // STATUS_WORD with CML fault bit on.
492 expectations.statusWordValue = (status_word::CML_FAULT);
493 // Turn on STATUS_CML fault bit(s)
494 expectations.statusCMLValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000495 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
496 {
497 setPMBusExpectations(mockPMBus, expectations);
498 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
499 .Times(1)
500 .WillOnce(Return("215000"));
501 psu2.analyze();
502 EXPECT_EQ(psu2.isPresent(), true);
503 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
504 EXPECT_EQ(psu2.hasCommFault(), x >= DEGLITCH_LIMIT);
505 EXPECT_EQ(psu2.hasInputFault(), false);
506 EXPECT_EQ(psu2.hasMFRFault(), false);
507 EXPECT_EQ(psu2.hasVINUVFault(), false);
508 EXPECT_EQ(psu2.hasVoutOVFault(), false);
509 EXPECT_EQ(psu2.hasIoutOCFault(), false);
510 EXPECT_EQ(psu2.hasVoutUVFault(), false);
511 EXPECT_EQ(psu2.hasFanFault(), false);
512 EXPECT_EQ(psu2.hasTempFault(), false);
513 EXPECT_EQ(psu2.hasPgoodFault(), false);
514 EXPECT_EQ(psu2.hasPSKillFault(), false);
515 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
516 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
517 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000518 }
Brandon Wyman6710ba22021-10-27 17:39:31 +0000519
Brandon Wyman32453e92021-12-15 19:00:14 +0000520 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000521 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
522 .Times(1)
523 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000524 psu2.clearFaults();
Brandon Wyman3225a452022-03-18 18:51:49 +0000525
Brandon Wyman6710ba22021-10-27 17:39:31 +0000526 // VOUT_OV_FAULT fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000527 {
528 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
529 PMBusExpectations expectations;
530 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000531 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
532 .Times(1)
533 .WillOnce(Return("216000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000534 psu2.analyze();
535 // STATUS_WORD with VOUT/VOUT_OV fault.
536 expectations.statusWordValue =
537 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
538 // Turn on STATUS_VOUT fault bit(s)
539 expectations.statusVOUTValue = 0xA0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000540 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
541 {
542 // STATUS_TEMPERATURE don't care (default)
543 setPMBusExpectations(mockPMBus, expectations);
544 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
545 .Times(1)
546 .WillOnce(Return("217000"));
547 psu2.analyze();
548 EXPECT_EQ(psu2.isPresent(), true);
549 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
550 EXPECT_EQ(psu2.hasInputFault(), false);
551 EXPECT_EQ(psu2.hasMFRFault(), false);
552 EXPECT_EQ(psu2.hasVINUVFault(), false);
553 EXPECT_EQ(psu2.hasCommFault(), false);
554 EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
555 EXPECT_EQ(psu2.hasVoutUVFault(), false);
556 EXPECT_EQ(psu2.hasIoutOCFault(), false);
557 EXPECT_EQ(psu2.hasFanFault(), false);
558 EXPECT_EQ(psu2.hasTempFault(), false);
559 EXPECT_EQ(psu2.hasPgoodFault(), false);
560 EXPECT_EQ(psu2.hasPSKillFault(), false);
561 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
562 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
563 }
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000564 }
565
566 // IOUT_OC_FAULT fault
567 {
568 // First STATUS_WORD with no bits set, then with IOUT_OC fault.
569 PMBusExpectations expectations;
570 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000571 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
572 .Times(1)
573 .WillOnce(Return("218000"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000574 psu2.analyze();
575 // STATUS_WORD with IOUT_OC fault.
576 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
577 // Turn on STATUS_IOUT fault bit(s)
578 expectations.statusIOUTValue = 0x88;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000579 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
580 {
581 setPMBusExpectations(mockPMBus, expectations);
582 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
583 .Times(1)
584 .WillOnce(Return("219000"));
585 psu2.analyze();
586 EXPECT_EQ(psu2.isPresent(), true);
587 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
588 EXPECT_EQ(psu2.hasInputFault(), false);
589 EXPECT_EQ(psu2.hasMFRFault(), false);
590 EXPECT_EQ(psu2.hasVINUVFault(), false);
591 EXPECT_EQ(psu2.hasCommFault(), false);
592 EXPECT_EQ(psu2.hasVoutOVFault(), false);
593 EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
594 EXPECT_EQ(psu2.hasVoutUVFault(), false);
595 EXPECT_EQ(psu2.hasFanFault(), false);
596 EXPECT_EQ(psu2.hasTempFault(), false);
597 EXPECT_EQ(psu2.hasPgoodFault(), false);
598 EXPECT_EQ(psu2.hasPSKillFault(), false);
599 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
600 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
601 }
Brandon Wyman2cf46942021-10-28 19:09:16 +0000602 }
603
604 // VOUT_UV_FAULT
605 {
606 // First STATUS_WORD with no bits set, then with VOUT fault.
607 PMBusExpectations expectations;
608 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000609 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
610 .Times(1)
611 .WillOnce(Return("220000"));
Brandon Wyman2cf46942021-10-28 19:09:16 +0000612 psu2.analyze();
613 // Change STATUS_WORD to indicate VOUT fault.
614 expectations.statusWordValue = (status_word::VOUT_FAULT);
615 // Turn on STATUS_VOUT fault bit(s)
616 expectations.statusVOUTValue = 0x30;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000617 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
618 {
619 setPMBusExpectations(mockPMBus, expectations);
620 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
621 .Times(1)
622 .WillOnce(Return("221000"));
623 psu2.analyze();
624 EXPECT_EQ(psu2.isPresent(), true);
625 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
626 EXPECT_EQ(psu2.hasInputFault(), false);
627 EXPECT_EQ(psu2.hasMFRFault(), false);
628 EXPECT_EQ(psu2.hasVINUVFault(), false);
629 EXPECT_EQ(psu2.hasCommFault(), false);
630 EXPECT_EQ(psu2.hasVoutOVFault(), false);
631 EXPECT_EQ(psu2.hasIoutOCFault(), false);
632 EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
633 EXPECT_EQ(psu2.hasFanFault(), false);
634 EXPECT_EQ(psu2.hasTempFault(), false);
635 EXPECT_EQ(psu2.hasPgoodFault(), false);
636 EXPECT_EQ(psu2.hasPSKillFault(), false);
637 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
638 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
639 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000640 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600641
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000642 // Fan fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000643 {
644 // First STATUS_WORD with no bits set, then with fan fault.
645 PMBusExpectations expectations;
646 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000647 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
648 .Times(1)
649 .WillOnce(Return("222000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000650 psu2.analyze();
651 expectations.statusWordValue = (status_word::FAN_FAULT);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000652 // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
653 expectations.statusFans12Value = 0xA0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000654
655 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
656 {
657 setPMBusExpectations(mockPMBus, expectations);
658 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
659 .Times(1)
660 .WillOnce(Return("223000"));
661 psu2.analyze();
662 EXPECT_EQ(psu2.isPresent(), true);
663 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
664 EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT);
665 EXPECT_EQ(psu2.hasInputFault(), false);
666 EXPECT_EQ(psu2.hasMFRFault(), false);
667 EXPECT_EQ(psu2.hasVINUVFault(), false);
668 EXPECT_EQ(psu2.hasCommFault(), false);
669 EXPECT_EQ(psu2.hasVoutOVFault(), false);
670 EXPECT_EQ(psu2.hasIoutOCFault(), false);
671 EXPECT_EQ(psu2.hasVoutUVFault(), false);
672 EXPECT_EQ(psu2.hasTempFault(), false);
673 EXPECT_EQ(psu2.hasPgoodFault(), false);
674 EXPECT_EQ(psu2.hasPSKillFault(), false);
675 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
676 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
677 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000678 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000679
Brandon Wyman06ca4592021-12-06 22:52:23 +0000680 // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000681 {
Brandon Wyman2916ea52021-11-06 03:31:18 +0000682 // First STATUS_WORD with no bits set.
683 PMBusExpectations expectations;
684 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000685 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
686 .Times(1)
687 .WillOnce(Return("123000"));
Brandon Wyman2916ea52021-11-06 03:31:18 +0000688 psu2.analyze();
689 EXPECT_EQ(psu2.isFaulted(), false);
690 // POWER_GOOD# inactive, and OFF bit on.
691 expectations.statusWordValue =
692 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
Brandon Wyman06ca4592021-12-06 22:52:23 +0000693 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
694 {
695 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
696 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
697 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000698 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
699 .Times(1)
700 .WillOnce(Return("124000"));
Brandon Wyman06ca4592021-12-06 22:52:23 +0000701 psu2.analyze();
702 EXPECT_EQ(psu2.isPresent(), true);
Brandon Wymanc2906f42021-12-21 20:14:56 +0000703 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
Brandon Wyman06ca4592021-12-06 22:52:23 +0000704 EXPECT_EQ(psu2.hasInputFault(), false);
705 EXPECT_EQ(psu2.hasMFRFault(), false);
706 EXPECT_EQ(psu2.hasVINUVFault(), false);
707 EXPECT_EQ(psu2.hasCommFault(), false);
708 EXPECT_EQ(psu2.hasVoutOVFault(), false);
709 EXPECT_EQ(psu2.hasVoutUVFault(), false);
710 EXPECT_EQ(psu2.hasIoutOCFault(), false);
711 EXPECT_EQ(psu2.hasFanFault(), false);
712 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman32453e92021-12-15 19:00:14 +0000713 EXPECT_EQ(psu2.hasPgoodFault(), x >= DEGLITCH_LIMIT);
Brandon Wyman06ca4592021-12-06 22:52:23 +0000714 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000715 }
716
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600717 // TODO: ReadFailure
718}
719
Brandon Wyman59a35792020-06-04 12:37:40 -0500720TEST_F(PowerSupplyTests, OnOffConfig)
721{
722 auto bus = sdbusplus::bus::new_default();
723 uint8_t data = 0x15;
724
725 // Test where PSU is NOT present
726 try
727 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000728 // Assume GPIO presence, not inventory presence?
Matt Spinler0975eaf2022-02-14 15:38:30 -0600729 EXPECT_CALL(mockedUtil, setAvailable(_, _, _)).Times(0);
Brandon Wymanc3324422022-03-24 20:30:57 +0000730 PowerSupply psu{bus, PSUInventoryPath, 4,
731 0x69, "ibm-cffps", PSUGPIOLineName};
B. J. Wyman681b2a32021-04-20 22:31:22 +0000732
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000733 MockedGPIOInterface* mockPresenceGPIO =
734 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000735 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
Brandon Wyman59a35792020-06-04 12:37:40 -0500736 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000737 // Constructor should set initial presence, default read returns 0.
Brandon Wyman59a35792020-06-04 12:37:40 -0500738 // If it is not present, I should not be trying to write to it.
739 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
740 psu.onOffConfig(data);
741 }
742 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000743 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500744
745 // Test where PSU is present
746 try
747 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000748 // Assume GPIO presence, not inventory presence?
Matt Spinler0975eaf2022-02-14 15:38:30 -0600749 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wymanc3324422022-03-24 20:30:57 +0000750 PowerSupply psu{bus, PSUInventoryPath, 5,
751 0x6a, "ibm-cffps", PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000752 MockedGPIOInterface* mockPresenceGPIO =
753 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman391a0692021-12-08 23:28:18 +0000754 // There will potentially be multiple calls, we want it to continue
755 // returning 1 for the GPIO read to keep the power supply present.
756 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman59a35792020-06-04 12:37:40 -0500757 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000758 setMissingToPresentExpects(mockPMBus, mockedUtil);
759 // If I am calling analyze(), I should probably give it good data.
760 // STATUS_WORD 0x0000 is powered on, no faults.
761 PMBusExpectations expectations;
762 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000763 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
764 .Times(1)
765 .WillOnce(Return("205000"));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000766 psu.analyze();
Brandon Wyman391a0692021-12-08 23:28:18 +0000767 // I definitely should be writting ON_OFF_CONFIG if I call the function
768 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
769 Type::HwmonDeviceDebug))
Brandon Wyman59a35792020-06-04 12:37:40 -0500770 .Times(1);
771 psu.onOffConfig(data);
772 }
773 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000774 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500775}
776
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600777TEST_F(PowerSupplyTests, ClearFaults)
778{
779 auto bus = sdbusplus::bus::new_default();
Brandon Wymanc3324422022-03-24 20:30:57 +0000780 PowerSupply psu{bus, PSUInventoryPath, 13,
781 0x68, "ibm-cffps", PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000782 MockedGPIOInterface* mockPresenceGPIO =
783 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000784 // Always return 1 to indicate present.
785 // Each analyze() call will trigger a read of the presence GPIO.
786 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000787 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000788 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000789 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000790 PMBusExpectations expectations;
791 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000792 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
793 .Times(1)
794 .WillOnce(Return("207000"));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000795 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600796 EXPECT_EQ(psu.isPresent(), true);
797 EXPECT_EQ(psu.isFaulted(), false);
798 EXPECT_EQ(psu.hasInputFault(), false);
799 EXPECT_EQ(psu.hasMFRFault(), false);
800 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000801 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000802 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000803 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000804 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000805 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000806 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000807 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000808 EXPECT_EQ(psu.hasPSKillFault(), false);
809 EXPECT_EQ(psu.hasPS12VcsFault(), false);
810 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000811
Brandon Wymanf07bc792021-10-12 19:00:35 +0000812 // STATUS_WORD with fault bits galore!
Brandon Wymanb654c612021-11-05 23:24:51 +0000813 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000814 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000815 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000816 // STATUS_MFR_SPEFIC with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000817 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000818 // STATUS_CML with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000819 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000820 // STATUS_VOUT with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000821 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000822 // STATUS_IOUT with bits on.
823 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000824 // STATUS_FANS_1_2 with bits on.
825 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000826 // STATUS_TEMPERATURE with bits on.
827 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000828
829 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
830 {
831 setPMBusExpectations(mockPMBus, expectations);
832 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
833 .Times(1)
834 .WillOnce(Return("0"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600835 if (x == DEGLITCH_LIMIT)
836 {
837 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
838 }
Brandon Wymanc2906f42021-12-21 20:14:56 +0000839 psu.analyze();
840 EXPECT_EQ(psu.isPresent(), true);
841 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
842 // Rely on HasVoutUVFault() to verify this sets and clears.
843 EXPECT_EQ(psu.hasVoutUVFault(), false);
844 // All faults are deglitched up to DEGLITCH_LIMIT
845 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
846 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
847 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
848 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
849 EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT);
850 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
851 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
852 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
853 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
854 EXPECT_EQ(psu.hasPgoodFault(), x >= DEGLITCH_LIMIT);
855 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
856 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
857 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
858 }
859
Brandon Wyman32453e92021-12-15 19:00:14 +0000860 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _))
861 .Times(1)
862 .WillOnce(Return(207000));
Brandon Wyman3225a452022-03-18 18:51:49 +0000863 // Clearing VIN_UV fault via in1_lcrit_alarm
864 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
865 .Times(1)
866 .WillOnce(Return(1));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600867 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600868 psu.clearFaults();
869 EXPECT_EQ(psu.isPresent(), true);
870 EXPECT_EQ(psu.isFaulted(), false);
871 EXPECT_EQ(psu.hasInputFault(), false);
872 EXPECT_EQ(psu.hasMFRFault(), false);
873 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000874 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000875 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000876 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000877 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000878 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000879 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000880 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000881 EXPECT_EQ(psu.hasPSKillFault(), false);
882 EXPECT_EQ(psu.hasPS12VcsFault(), false);
883 EXPECT_EQ(psu.hasPSCS12VFault(), false);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000884
Brandon Wyman82affd92021-11-24 19:12:49 +0000885 // Faults clear on READ_VIN 0 -> !0
886 // STATUS_WORD with fault bits galore!
887 expectations.statusWordValue = 0xFFFF;
888 // STATUS_INPUT with fault bits on.
889 expectations.statusInputValue = 0xFF;
890 // STATUS_MFR_SPEFIC with bits on.
891 expectations.statusMFRValue = 0xFF;
892 // STATUS_CML with bits on.
893 expectations.statusCMLValue = 0xFF;
894 // STATUS_VOUT with bits on.
895 expectations.statusVOUTValue = 0xFF;
896 // STATUS_IOUT with bits on.
897 expectations.statusIOUTValue = 0xFF;
898 // STATUS_FANS_1_2 with bits on.
899 expectations.statusFans12Value = 0xFF;
900 // STATUS_TEMPERATURE with bits on.
901 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000902
903 // All faults degltiched now. Check for false before limit above.
904 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
905 {
906 setPMBusExpectations(mockPMBus, expectations);
907 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
908 .Times(1)
909 .WillOnce(Return("0"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600910 if (x == DEGLITCH_LIMIT)
911 {
912 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
913 }
Brandon Wymanc2906f42021-12-21 20:14:56 +0000914 psu.analyze();
915 }
916
Brandon Wyman82affd92021-11-24 19:12:49 +0000917 EXPECT_EQ(psu.isPresent(), true);
918 EXPECT_EQ(psu.isFaulted(), true);
919 EXPECT_EQ(psu.hasInputFault(), true);
920 EXPECT_EQ(psu.hasMFRFault(), true);
921 EXPECT_EQ(psu.hasVINUVFault(), true);
922 // True due to CML fault bits on
923 EXPECT_EQ(psu.hasCommFault(), true);
924 EXPECT_EQ(psu.hasVoutOVFault(), true);
925 EXPECT_EQ(psu.hasIoutOCFault(), true);
926 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
927 // Rely on HasVoutUVFault() to verify this sets and clears.
928 EXPECT_EQ(psu.hasVoutUVFault(), false);
929 EXPECT_EQ(psu.hasFanFault(), true);
930 EXPECT_EQ(psu.hasTempFault(), true);
Brandon Wymanc2906f42021-12-21 20:14:56 +0000931 EXPECT_EQ(psu.hasPgoodFault(), true);
Brandon Wyman82affd92021-11-24 19:12:49 +0000932 EXPECT_EQ(psu.hasPSKillFault(), true);
933 EXPECT_EQ(psu.hasPS12VcsFault(), true);
934 EXPECT_EQ(psu.hasPSCS12VFault(), true);
935 // STATUS_WORD with INPUT/VIN_UV fault bits off.
936 expectations.statusWordValue = 0xDFF7;
937 // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
938 // Insufficient Input Voltage bits off.
939 expectations.statusInputValue = 0xC7;
940 setPMBusExpectations(mockPMBus, expectations);
941 // READ_VIN back in range.
942 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
943 .Times(1)
944 .WillOnce(Return("206000"));
Brandon Wyman3225a452022-03-18 18:51:49 +0000945 // VIN_UV cleared via in1_lcrit_alarm when voltage back in range.
946 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
947 .Times(1)
948 .WillOnce(Return(1));
949 psu.analyze();
950 // We only cleared the VIN_UV and OFF faults.
951 EXPECT_EQ(psu.isPresent(), true);
952 EXPECT_EQ(psu.isFaulted(), true);
953 EXPECT_EQ(psu.hasInputFault(), false);
954 EXPECT_EQ(psu.hasMFRFault(), true);
955 EXPECT_EQ(psu.hasVINUVFault(), false);
956 EXPECT_EQ(psu.hasCommFault(), true);
957 EXPECT_EQ(psu.hasVoutOVFault(), true);
958 EXPECT_EQ(psu.hasIoutOCFault(), true);
959 EXPECT_EQ(psu.hasVoutUVFault(), false);
960 EXPECT_EQ(psu.hasFanFault(), true);
961 EXPECT_EQ(psu.hasTempFault(), true);
962 EXPECT_EQ(psu.hasPgoodFault(), true);
963 EXPECT_EQ(psu.hasPSKillFault(), true);
964 EXPECT_EQ(psu.hasPS12VcsFault(), true);
965 EXPECT_EQ(psu.hasPSCS12VFault(), true);
966
967 // All faults cleared
968 expectations = {0};
969 setPMBusExpectations(mockPMBus, expectations);
970 // READ_VIN back in range.
971 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
972 .Times(1)
973 .WillOnce(Return("206000"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600974 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman82affd92021-11-24 19:12:49 +0000975 psu.analyze();
976 EXPECT_EQ(psu.isPresent(), true);
977 EXPECT_EQ(psu.isFaulted(), false);
978 EXPECT_EQ(psu.hasInputFault(), false);
979 EXPECT_EQ(psu.hasMFRFault(), false);
980 EXPECT_EQ(psu.hasVINUVFault(), false);
981 EXPECT_EQ(psu.hasCommFault(), false);
982 EXPECT_EQ(psu.hasVoutOVFault(), false);
983 EXPECT_EQ(psu.hasIoutOCFault(), false);
984 EXPECT_EQ(psu.hasVoutUVFault(), false);
985 EXPECT_EQ(psu.hasFanFault(), false);
986 EXPECT_EQ(psu.hasTempFault(), false);
987 EXPECT_EQ(psu.hasPgoodFault(), false);
988 EXPECT_EQ(psu.hasPSKillFault(), false);
989 EXPECT_EQ(psu.hasPS12VcsFault(), false);
990 EXPECT_EQ(psu.hasPSCS12VFault(), false);
991
B. J. Wyman681b2a32021-04-20 22:31:22 +0000992 // TODO: Faults clear on missing/present?
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600993}
994
995TEST_F(PowerSupplyTests, UpdateInventory)
996{
997 auto bus = sdbusplus::bus::new_default();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500998
999 try
1000 {
Brandon Wymanc3324422022-03-24 20:30:57 +00001001 PowerSupply psu{bus, PSUInventoryPath, 3,
1002 0x68, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001003 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1004 // If it is not present, I should not be trying to read a string
1005 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
1006 psu.updateInventory();
1007 }
1008 catch (...)
1009 {
1010 ADD_FAILURE() << "Should not have caught exception.";
1011 }
1012
1013 try
1014 {
Brandon Wymanc3324422022-03-24 20:30:57 +00001015 PowerSupply psu{bus, PSUInventoryPath, 13,
1016 0x69, "ibm-cffps", PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001017 MockedGPIOInterface* mockPresenceGPIO =
1018 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001019 // GPIO read return 1 to indicate present.
1020 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001021 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001022 setMissingToPresentExpects(mockPMBus, mockedUtil);
1023 // STATUS_WORD 0x0000 is powered on, no faults.
1024 PMBusExpectations expectations;
1025 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001026 // Call to analyze will read voltage, trigger clear faults for 0 to
1027 // within range.
1028 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1029 .Times(1)
1030 .WillOnce(Return("123456"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001031 psu.analyze();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001032 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
1033 psu.updateInventory();
1034
Brandon Wyman3c530fb2021-04-13 13:13:22 -05001035#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001036 EXPECT_CALL(mockPMBus, readString(_, _))
1037 .WillOnce(Return("CCIN"))
1038 .WillOnce(Return("PN3456"))
1039 .WillOnce(Return("FN3456"))
1040 .WillOnce(Return("HEADER"))
1041 .WillOnce(Return("SN3456"))
1042 .WillOnce(Return("FW3456"));
Brandon Wyman3c530fb2021-04-13 13:13:22 -05001043#endif
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001044 psu.updateInventory();
1045 // TODO: D-Bus mocking to verify values stored on D-Bus (???)
1046 }
1047 catch (...)
1048 {
1049 ADD_FAILURE() << "Should not have caught exception.";
1050 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001051}
1052
1053TEST_F(PowerSupplyTests, IsPresent)
1054{
1055 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001056
Brandon Wymanc3324422022-03-24 20:30:57 +00001057 PowerSupply psu{bus, PSUInventoryPath, 3,
1058 0x68, "ibm-cffps", PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001059 MockedGPIOInterface* mockPresenceGPIO =
1060 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001061 EXPECT_EQ(psu.isPresent(), false);
1062
B. J. Wyman681b2a32021-04-20 22:31:22 +00001063 // Change GPIO read to return 1 to indicate present.
1064 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +00001065 // Call to analyze() will update to present, that will trigger updating
1066 // to the correct/latest HWMON directory, in case it changes.
1067 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1068 setMissingToPresentExpects(mockPMBus, mockedUtil);
1069 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1070 // Default expectations will be on, no faults.
1071 PMBusExpectations expectations;
1072 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001073 // Give it an input voltage in the 100-volt range.
1074 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1075 .Times(1)
1076 .WillOnce(Return("123456"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001077 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
B. J. Wyman681b2a32021-04-20 22:31:22 +00001078 psu.analyze();
1079 EXPECT_EQ(psu.isPresent(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001080}
1081
1082TEST_F(PowerSupplyTests, IsFaulted)
1083{
1084 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001085
Brandon Wymanc3324422022-03-24 20:30:57 +00001086 PowerSupply psu{bus, PSUInventoryPath, 11,
1087 0x6f, "ibm-cffps", PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001088 MockedGPIOInterface* mockPresenceGPIO =
1089 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001090 // Always return 1 to indicate present.
1091 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +00001092 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1093 setMissingToPresentExpects(mockPMBus, mockedUtil);
1094 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1095 // Default expectations will be on, no faults.
1096 PMBusExpectations expectations;
1097 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001098 // Give it an input voltage in the 100-volt range.
1099 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1100 .Times(1)
1101 .WillOnce(Return("124680"));
B. J. Wyman681b2a32021-04-20 22:31:22 +00001102 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001103 EXPECT_EQ(psu.isFaulted(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001104 // STATUS_WORD with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001105 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +00001106 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001107 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +00001108 // STATUS_MFR_SPECIFIC with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001109 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +00001110 // STATUS_CML with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001111 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +00001112 // STATUS_VOUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001113 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001114 // STATUS_IOUT with fault bits on.
1115 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001116 // STATUS_FANS_1_2 with bits on.
1117 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +00001118 // STATUS_TEMPERATURE with fault bits on.
1119 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001120 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1121 {
1122 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman4fc191f2022-03-10 23:07:13 +00001123 // Also get another read of READ_VIN, faulted, so not in 100-volt range
Brandon Wymanc2906f42021-12-21 20:14:56 +00001124 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1125 .Times(1)
Brandon Wyman4fc191f2022-03-10 23:07:13 +00001126 .WillOnce(Return("19000"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001127 if (x == DEGLITCH_LIMIT)
1128 {
1129 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1130 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001131 psu.analyze();
1132 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
1133 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001134}
1135
1136TEST_F(PowerSupplyTests, HasInputFault)
1137{
1138 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001139
Brandon Wymanc3324422022-03-24 20:30:57 +00001140 PowerSupply psu{bus, PSUInventoryPath, 3,
1141 0x68, "ibm-cffps", PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001142 MockedGPIOInterface* mockPresenceGPIO =
1143 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001144 // Always return 1 to indicate present.
1145 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001146 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001147 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman8da35c52021-10-28 22:45:08 +00001148 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001149 PMBusExpectations expectations;
1150 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001151 // Analyze call will also need good READ_VIN value to check.
1152 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1153 .Times(1)
1154 .WillOnce(Return("201100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001155 psu.analyze();
1156 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001157 // STATUS_WORD with input fault/warn on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001158 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001159 // STATUS_INPUT with an input fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001160 expectations.statusInputValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001161 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1162 {
1163 setPMBusExpectations(mockPMBus, expectations);
1164 // Analyze call will also need good READ_VIN value to check.
1165 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1166 .Times(1)
1167 .WillOnce(Return("201200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001168 if (x == DEGLITCH_LIMIT)
1169 {
1170 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1171 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001172 psu.analyze();
1173 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
1174 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001175 // STATUS_WORD with no bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001176 expectations.statusWordValue = 0;
1177 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001178 // Analyze call will also need good READ_VIN value to check.
1179 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1180 .Times(1)
1181 .WillOnce(Return("201300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001182 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001183 psu.analyze();
1184 EXPECT_EQ(psu.hasInputFault(), false);
1185}
1186
1187TEST_F(PowerSupplyTests, HasMFRFault)
1188{
1189 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001190
Brandon Wymanc3324422022-03-24 20:30:57 +00001191 PowerSupply psu{bus, PSUInventoryPath, 3,
1192 0x68, "ibm-cffps", PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001193 MockedGPIOInterface* mockPresenceGPIO =
1194 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001195 // Always return 1 to indicate present.
1196 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001197 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001198 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001199 // First return STATUS_WORD with no bits on.
Brandon Wyman8da35c52021-10-28 22:45:08 +00001200 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001201 PMBusExpectations expectations;
1202 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001203 // Analyze call will also need good READ_VIN value to check.
1204 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1205 .Times(1)
1206 .WillOnce(Return("202100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001207 psu.analyze();
1208 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001209 // Next return STATUS_WORD with MFR fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001210 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001211 // STATUS_MFR_SPEFIC with bit(s) on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001212 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001213 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1214 {
1215 setPMBusExpectations(mockPMBus, expectations);
1216 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1217 .Times(1)
1218 .WillOnce(Return("202200"));
1219 psu.analyze();
1220 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1221 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001222 // Back to no bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001223 expectations.statusWordValue = 0;
1224 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001225 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1226 .Times(1)
1227 .WillOnce(Return("202300"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001228 psu.analyze();
1229 EXPECT_EQ(psu.hasMFRFault(), false);
1230}
1231
1232TEST_F(PowerSupplyTests, HasVINUVFault)
1233{
1234 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001235
Brandon Wymanc3324422022-03-24 20:30:57 +00001236 PowerSupply psu{bus, PSUInventoryPath, 3,
1237 0x68, "ibm-cffps", PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001238 MockedGPIOInterface* mockPresenceGPIO =
1239 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001240 // Always return 1 to indicate present.
1241 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001242 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001243 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman82affd92021-11-24 19:12:49 +00001244
1245 // Presence change from missing to present will trigger in1_input read in
1246 // an attempt to get CLEAR_FAULTS called. Return value ignored.
1247 // Zero to non-zero voltage, for missing/present change, triggers clear
1248 // faults call again. Return value ignored.
1249 // Fault (low voltage) to not faulted (voltage in range) triggers clear
1250 // faults call a third time.
1251
Brandon Wyman8da35c52021-10-28 22:45:08 +00001252 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001253 PMBusExpectations expectations;
1254 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001255 // Analyze call will also need good READ_VIN value to check.
1256 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1257 .Times(1)
1258 .WillOnce(Return("201100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001259 psu.analyze();
1260 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001261 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001262 expectations.statusWordValue = (status_word::VIN_UV_FAULT);
Brandon Wyman85c7bf42021-10-19 22:28:48 +00001263 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
1264 // Figure 16, and assume bits on in STATUS_INPUT.
Brandon Wymanb654c612021-11-05 23:24:51 +00001265 expectations.statusInputValue = 0x18;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001266 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1267 {
1268 setPMBusExpectations(mockPMBus, expectations);
1269 // If there is a VIN_UV fault, fake reading voltage of less than 20V
1270 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1271 .Times(1)
1272 .WillOnce(Return("19876"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001273 if (x == DEGLITCH_LIMIT)
1274 {
1275 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1276 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001277 psu.analyze();
1278 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1279 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001280 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001281 expectations.statusWordValue = 0;
1282 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001283 // Updates now result in clearing faults if read voltage goes from below the
1284 // minimum, to within a valid range.
1285 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1286 .Times(1)
1287 .WillOnce(Return("201300"));
Brandon Wyman3225a452022-03-18 18:51:49 +00001288 // Went from below minimum to within range, expect clearVinUVFault().
1289 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
1290 .Times(1)
1291 .WillOnce(Return(1));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001292 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001293 psu.analyze();
1294 EXPECT_EQ(psu.hasVINUVFault(), false);
1295}
Brandon Wyman6710ba22021-10-27 17:39:31 +00001296
1297TEST_F(PowerSupplyTests, HasVoutOVFault)
1298{
1299 auto bus = sdbusplus::bus::new_default();
1300
Brandon Wymanc3324422022-03-24 20:30:57 +00001301 PowerSupply psu{bus, PSUInventoryPath, 3,
1302 0x69, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman6710ba22021-10-27 17:39:31 +00001303 MockedGPIOInterface* mockPresenceGPIO =
1304 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1305 // Always return 1 to indicate present.
1306 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001307 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001308 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman6710ba22021-10-27 17:39:31 +00001309 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001310 PMBusExpectations expectations;
1311 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001312 // Call to analyze will trigger read of "in1_input" to check voltage.
1313 // Initial value would be 0, so this read updates it to non-zero.
1314 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1315 .Times(1)
1316 .WillOnce(Return("202100"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001317 psu.analyze();
1318 EXPECT_EQ(psu.hasVoutOVFault(), false);
1319 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001320 expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
Brandon Wyman6710ba22021-10-27 17:39:31 +00001321 // STATUS_VOUT fault bit(s)
Brandon Wymanb654c612021-11-05 23:24:51 +00001322 expectations.statusVOUTValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001323 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1324 {
1325 setPMBusExpectations(mockPMBus, expectations);
1326 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1327 .Times(1)
1328 .WillOnce(Return("202200"));
1329 psu.analyze();
1330 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1331 }
Brandon Wyman6710ba22021-10-27 17:39:31 +00001332 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001333 expectations.statusWordValue = 0;
1334 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001335 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1336 .Times(1)
1337 .WillOnce(Return("202300"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001338 psu.analyze();
1339 EXPECT_EQ(psu.hasVoutOVFault(), false);
1340}
Brandon Wyman96893a42021-11-05 19:56:57 +00001341
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001342TEST_F(PowerSupplyTests, HasIoutOCFault)
1343{
1344 auto bus = sdbusplus::bus::new_default();
1345
Brandon Wymanc3324422022-03-24 20:30:57 +00001346 PowerSupply psu{bus, PSUInventoryPath, 3,
1347 0x6d, "ibm-cffps", PSUGPIOLineName};
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001348 MockedGPIOInterface* mockPresenceGPIO =
1349 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1350 // Always return 1 to indicate present.
1351 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001352 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001353 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001354 // STATUS_WORD 0x0000 is powered on, no faults.
1355 PMBusExpectations expectations;
1356 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001357 // Call to analyze will trigger read of "in1_input" to check voltage.
1358 // Initial value would be 0, so this read updates it to non-zero.
1359 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1360 .Times(1)
1361 .WillOnce(Return("203100"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001362 psu.analyze();
1363 EXPECT_EQ(psu.hasIoutOCFault(), false);
1364 // Turn fault on.
1365 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1366 // STATUS_IOUT fault bit(s)
1367 expectations.statusIOUTValue = 0x88;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001368 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1369 {
1370 setPMBusExpectations(mockPMBus, expectations);
1371 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1372 .Times(1)
1373 .WillOnce(Return("203200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001374 if (x == DEGLITCH_LIMIT)
1375 {
1376 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1377 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001378 psu.analyze();
1379 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1380 }
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001381 // Back to no fault bits on in STATUS_WORD
1382 expectations.statusWordValue = 0;
1383 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001384 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1385 .Times(1)
1386 .WillOnce(Return("203300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001387 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001388 psu.analyze();
1389 EXPECT_EQ(psu.hasIoutOCFault(), false);
1390}
1391
Brandon Wyman2cf46942021-10-28 19:09:16 +00001392TEST_F(PowerSupplyTests, HasVoutUVFault)
1393{
1394 auto bus = sdbusplus::bus::new_default();
1395
Brandon Wymanc3324422022-03-24 20:30:57 +00001396 PowerSupply psu{bus, PSUInventoryPath, 3,
1397 0x6a, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman2cf46942021-10-28 19:09:16 +00001398 MockedGPIOInterface* mockPresenceGPIO =
1399 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1400 // Always return 1 to indicate present.
1401 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001402 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001403 setMissingToPresentExpects(mockPMBus, mockedUtil);
1404 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wyman2cf46942021-10-28 19:09:16 +00001405 PMBusExpectations expectations;
1406 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001407 // Call to analyze will trigger read of "in1_input" to check voltage.
1408 // Initial value would be 0, so this read updates it to non-zero.
1409 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1410 .Times(1)
1411 .WillOnce(Return("204100"));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001412 psu.analyze();
1413 EXPECT_EQ(psu.hasVoutUVFault(), false);
1414 // Turn fault on.
1415 expectations.statusWordValue = (status_word::VOUT_FAULT);
1416 // STATUS_VOUT fault bit(s)
1417 expectations.statusVOUTValue = 0x30;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001418 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1419 {
1420 setPMBusExpectations(mockPMBus, expectations);
1421 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1422 .Times(1)
1423 .WillOnce(Return("204200"));
1424 psu.analyze();
1425 EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1426 }
Brandon Wyman2cf46942021-10-28 19:09:16 +00001427 // Back to no fault bits on in STATUS_WORD
1428 expectations.statusWordValue = 0;
1429 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001430 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1431 .Times(1)
1432 .WillOnce(Return("204300"));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001433 psu.analyze();
1434 EXPECT_EQ(psu.hasVoutUVFault(), false);
1435}
1436
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001437TEST_F(PowerSupplyTests, HasFanFault)
1438{
1439 auto bus = sdbusplus::bus::new_default();
1440
Matt Spinler0975eaf2022-02-14 15:38:30 -06001441 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
1442 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
1443
Brandon Wymanc3324422022-03-24 20:30:57 +00001444 PowerSupply psu{bus, PSUInventoryPath, 3,
1445 0x6d, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001446 MockedGPIOInterface* mockPresenceGPIO =
1447 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1448 // Always return 1 to indicate present.
1449 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001450 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001451 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001452 // STATUS_WORD 0x0000 is powered on, no faults.
1453 PMBusExpectations expectations;
1454 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001455 // Call to analyze will trigger read of "in1_input" to check voltage.
1456 // Initial value would be 0, so this read updates it to non-zero.
1457 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1458 .Times(1)
1459 .WillOnce(Return("205100"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001460 psu.analyze();
1461 EXPECT_EQ(psu.hasFanFault(), false);
1462 // Turn fault on.
1463 expectations.statusWordValue = (status_word::FAN_FAULT);
1464 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
1465 expectations.statusFans12Value = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001466 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1467 {
1468 setPMBusExpectations(mockPMBus, expectations);
1469 // Call to analyze will trigger read of "in1_input" to check voltage.
1470 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1471 .Times(1)
1472 .WillOnce(Return("205200"));
1473 psu.analyze();
1474 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1475 }
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001476 // Back to no fault bits on in STATUS_WORD
1477 expectations.statusWordValue = 0;
1478 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001479 // Call to analyze will trigger read of "in1_input" to check voltage.
1480 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1481 .Times(1)
1482 .WillOnce(Return("205300"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001483 psu.analyze();
1484 EXPECT_EQ(psu.hasFanFault(), false);
1485}
1486
Brandon Wyman96893a42021-11-05 19:56:57 +00001487TEST_F(PowerSupplyTests, HasTempFault)
1488{
1489 auto bus = sdbusplus::bus::new_default();
1490
Matt Spinler0975eaf2022-02-14 15:38:30 -06001491 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
1492 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
1493
Brandon Wymanc3324422022-03-24 20:30:57 +00001494 PowerSupply psu{bus, PSUInventoryPath, 3,
1495 0x6a, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman96893a42021-11-05 19:56:57 +00001496 MockedGPIOInterface* mockPresenceGPIO =
1497 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1498 // Always return 1 to indicate present.
1499 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman96893a42021-11-05 19:56:57 +00001500 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001501 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman96893a42021-11-05 19:56:57 +00001502 // STATUS_WORD 0x0000 is powered on, no faults.
1503 PMBusExpectations expectations;
1504 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001505 // Call to analyze will trigger read of "in1_input" to check voltage.
1506 // Initial value would be 0, so this read updates it to non-zero.
1507 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1508 .Times(1)
1509 .WillOnce(Return("206100"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001510 psu.analyze();
1511 EXPECT_EQ(psu.hasTempFault(), false);
1512 // Turn fault on.
1513 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
1514 // STATUS_TEMPERATURE fault bit on (OT Fault)
1515 expectations.statusTempValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001516 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1517 {
1518 setPMBusExpectations(mockPMBus, expectations);
1519 // Call to analyze will trigger read of "in1_input" to check voltage.
1520 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1521 .Times(1)
1522 .WillOnce(Return("206200"));
1523 psu.analyze();
1524 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1525 }
Brandon Wyman96893a42021-11-05 19:56:57 +00001526 // Back to no fault bits on in STATUS_WORD
1527 expectations.statusWordValue = 0;
1528 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001529 // Call to analyze will trigger read of "in1_input" to check voltage.
1530 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1531 .Times(1)
1532 .WillOnce(Return("206300"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001533 psu.analyze();
1534 EXPECT_EQ(psu.hasTempFault(), false);
1535}
Brandon Wyman2916ea52021-11-06 03:31:18 +00001536
1537TEST_F(PowerSupplyTests, HasPgoodFault)
1538{
1539 auto bus = sdbusplus::bus::new_default();
1540
Brandon Wymanc3324422022-03-24 20:30:57 +00001541 PowerSupply psu{bus, PSUInventoryPath, 3,
1542 0x6b, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman2916ea52021-11-06 03:31:18 +00001543 MockedGPIOInterface* mockPresenceGPIO =
1544 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1545 // Always return 1 to indicate present.
1546 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001547 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001548 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman2916ea52021-11-06 03:31:18 +00001549 // STATUS_WORD 0x0000 is powered on, no faults.
1550 PMBusExpectations expectations;
1551 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001552 // Call to analyze will trigger read of "in1_input" to check voltage.
1553 // Initial value would be 0, so this read updates it to non-zero.
1554 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1555 .Times(1)
1556 .WillOnce(Return("207100"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001557 psu.analyze();
1558 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman391a0692021-12-08 23:28:18 +00001559 // Setup another expectation of no faults.
1560 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001561 // Call to analyze will trigger read of "in1_input" to check voltage.
1562 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1563 .Times(1)
1564 .WillOnce(Return("207200"));
1565 psu.analyze();
1566 EXPECT_EQ(psu.hasPgoodFault(), false);
1567 // Setup another expectation of no faults.
1568 setPMBusExpectations(mockPMBus, expectations);
1569 // Call to analyze will trigger read of "in1_input" to check voltage.
1570 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1571 .Times(1)
1572 .WillOnce(Return("207300"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001573 psu.analyze();
1574 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +00001575 // Turn PGOOD# off (fault on).
1576 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
1577 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001578 // Call to analyze will trigger read of "in1_input" to check voltage.
1579 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1580 .Times(1)
1581 .WillOnce(Return("207400"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001582 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001583 // Expect false until reaches DEGLITCH_LIMIT
1584 EXPECT_EQ(psu.hasPgoodFault(), false);
1585 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001586 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1587 .Times(1)
1588 .WillOnce(Return("207500"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001589 psu.analyze();
1590 // Expect false until reaches DEGLITCH_LIMIT
1591 EXPECT_EQ(psu.hasPgoodFault(), false);
1592 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001593 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1594 .Times(1)
1595 .WillOnce(Return("207600"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001596 psu.analyze();
1597 // DEGLITCH_LIMIT reached, expect true.
Brandon Wyman2916ea52021-11-06 03:31:18 +00001598 EXPECT_EQ(psu.hasPgoodFault(), true);
1599 // Back to no fault bits on in STATUS_WORD
1600 expectations.statusWordValue = 0;
1601 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001602 // Call to analyze will trigger read of "in1_input" to check voltage.
1603 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1604 .Times(1)
1605 .WillOnce(Return("207700"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001606 psu.analyze();
1607 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman82affd92021-11-24 19:12:49 +00001608
Brandon Wyman2916ea52021-11-06 03:31:18 +00001609 // Turn OFF bit on
1610 expectations.statusWordValue = (status_word::UNIT_IS_OFF);
1611 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001612 // Call to analyze will trigger read of "in1_input" to check voltage.
1613 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1614 .Times(1)
1615 .WillOnce(Return("208100"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001616 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001617 EXPECT_EQ(psu.hasPgoodFault(), false);
1618 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001619 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1620 .Times(1)
1621 .WillOnce(Return("208200"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001622 psu.analyze();
1623 EXPECT_EQ(psu.hasPgoodFault(), false);
1624 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001625 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1626 .Times(1)
1627 .WillOnce(Return("208300"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001628 psu.analyze();
Brandon Wyman2916ea52021-11-06 03:31:18 +00001629 EXPECT_EQ(psu.hasPgoodFault(), true);
1630 // Back to no fault bits on in STATUS_WORD
1631 expectations.statusWordValue = 0;
1632 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001633 // Call to analyze will trigger read of "in1_input" to check voltage.
1634 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1635 .Times(1)
1636 .WillOnce(Return("208400"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001637 psu.analyze();
1638 EXPECT_EQ(psu.hasPgoodFault(), false);
1639}
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001640
1641TEST_F(PowerSupplyTests, HasPSKillFault)
1642{
1643 auto bus = sdbusplus::bus::new_default();
Brandon Wymanc3324422022-03-24 20:30:57 +00001644 PowerSupply psu{bus, PSUInventoryPath, 4,
1645 0x6d, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001646 MockedGPIOInterface* mockPresenceGPIO =
1647 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1648 // Always return 1 to indicate present.
1649 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001650 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001651 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001652 // STATUS_WORD 0x0000 is powered on, no faults.
1653 PMBusExpectations expectations;
1654 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001655 // Call to analyze will trigger read of "in1_input" to check voltage.
1656 // Initial value would be 0, so this read updates it to non-zero.
1657 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1658 .Times(1)
1659 .WillOnce(Return("208100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001660 psu.analyze();
1661 EXPECT_EQ(psu.hasPSKillFault(), false);
1662 // Next return STATUS_WORD with MFR fault bit on.
1663 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1664 // STATUS_MFR_SPEFIC with bit(s) on.
1665 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001666
1667 // Deglitching faults, false until read the fault bits on up to the limit.
1668 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1669 {
1670 setPMBusExpectations(mockPMBus, expectations);
1671 // Call to analyze will trigger read of "in1_input" to check voltage.
1672 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1673 .Times(1)
1674 .WillOnce(Return("208200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001675 if (x == DEGLITCH_LIMIT)
1676 {
1677 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1678 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001679 psu.analyze();
1680 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1681 }
1682
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001683 // Back to no bits on in STATUS_WORD
1684 expectations.statusWordValue = 0;
1685 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001686 // Call to analyze will trigger read of "in1_input" to check voltage.
1687 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1688 .Times(1)
1689 .WillOnce(Return("208300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001690 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001691 psu.analyze();
1692 EXPECT_EQ(psu.hasPSKillFault(), false);
1693 // Next return STATUS_WORD with MFR fault bit on.
1694 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1695 // STATUS_MFR_SPEFIC with bit 4 on.
1696 expectations.statusMFRValue = 0x10;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001697
1698 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1699 {
1700 setPMBusExpectations(mockPMBus, expectations);
1701 // Call to analyze will trigger read of "in1_input" to check voltage.
1702 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1703 .Times(1)
1704 .WillOnce(Return("208400"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001705 if (x == DEGLITCH_LIMIT)
1706 {
1707 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1708 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001709 psu.analyze();
1710 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1711 }
1712
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001713 // Back to no bits on in STATUS_WORD
1714 expectations.statusWordValue = 0;
1715 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001716 // Call to analyze will trigger read of "in1_input" to check voltage.
1717 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1718 .Times(1)
1719 .WillOnce(Return("208500"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001720 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001721 psu.analyze();
1722 EXPECT_EQ(psu.hasPSKillFault(), false);
1723}
1724
1725TEST_F(PowerSupplyTests, HasPS12VcsFault)
1726{
1727 auto bus = sdbusplus::bus::new_default();
Brandon Wymanc3324422022-03-24 20:30:57 +00001728 PowerSupply psu{bus, PSUInventoryPath, 5,
1729 0x6e, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001730 MockedGPIOInterface* mockPresenceGPIO =
1731 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1732 // Always return 1 to indicate present.
1733 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001734 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001735 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001736 // STATUS_WORD 0x0000 is powered on, no faults.
1737 PMBusExpectations expectations;
1738 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001739 // Call to analyze will trigger read of "in1_input" to check voltage.
1740 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1741 .Times(1)
1742 .WillOnce(Return("209100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001743 psu.analyze();
1744 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1745 // Next return STATUS_WORD with MFR fault bit on.
1746 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1747 // STATUS_MFR_SPEFIC with bit(s) on.
1748 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001749
1750 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1751 {
1752 setPMBusExpectations(mockPMBus, expectations);
1753 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1754 .Times(1)
1755 .WillOnce(Return("209200"));
1756 psu.analyze();
1757 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1758 }
1759
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001760 // Back to no bits on in STATUS_WORD
1761 expectations.statusWordValue = 0;
1762 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001763 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1764 .Times(1)
1765 .WillOnce(Return("209300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001766 psu.analyze();
1767 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1768 // Next return STATUS_WORD with MFR fault bit on.
1769 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1770 // STATUS_MFR_SPEFIC with bit 6 on.
1771 expectations.statusMFRValue = 0x40;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001772
1773 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1774 {
1775 setPMBusExpectations(mockPMBus, expectations);
1776 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1777 .Times(1)
1778 .WillOnce(Return("209400"));
1779 psu.analyze();
1780 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1781 }
1782
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001783 // Back to no bits on in STATUS_WORD
1784 expectations.statusWordValue = 0;
1785 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001786 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1787 .Times(1)
1788 .WillOnce(Return("209500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001789 psu.analyze();
1790 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1791}
1792
1793TEST_F(PowerSupplyTests, HasPSCS12VFault)
1794{
1795 auto bus = sdbusplus::bus::new_default();
Brandon Wymanc3324422022-03-24 20:30:57 +00001796 PowerSupply psu{bus, PSUInventoryPath, 6,
1797 0x6f, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001798 MockedGPIOInterface* mockPresenceGPIO =
1799 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1800 // Always return 1 to indicate present.
1801 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001802 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001803 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001804 // STATUS_WORD 0x0000 is powered on, no faults.
1805 PMBusExpectations expectations;
1806 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001807 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1808 .Times(1)
1809 .WillOnce(Return("209100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001810 psu.analyze();
1811 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1812 // Next return STATUS_WORD with MFR fault bit on.
1813 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1814 // STATUS_MFR_SPEFIC with bit(s) on.
1815 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001816
1817 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1818 {
1819 setPMBusExpectations(mockPMBus, expectations);
1820 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1821 .Times(1)
1822 .WillOnce(Return("209200"));
1823 psu.analyze();
1824 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1825 }
1826
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001827 // Back to no bits on in STATUS_WORD
1828 expectations.statusWordValue = 0;
1829 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001830 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1831 .Times(1)
1832 .WillOnce(Return("209300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001833 psu.analyze();
1834 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1835 // Next return STATUS_WORD with MFR fault bit on.
1836 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1837 // STATUS_MFR_SPEFIC with bit 7 on.
1838 expectations.statusMFRValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001839
1840 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1841 {
1842 setPMBusExpectations(mockPMBus, expectations);
1843 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1844 .Times(1)
1845 .WillOnce(Return("209400"));
1846 psu.analyze();
1847 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1848 }
1849
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001850 // Back to no bits on in STATUS_WORD
1851 expectations.statusWordValue = 0;
1852 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001853 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1854 .Times(1)
1855 .WillOnce(Return("209500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001856 psu.analyze();
1857 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1858}
Brandon Wymanc3324422022-03-24 20:30:57 +00001859
1860TEST_F(PowerSupplyTests, SetupInputHistory)
1861{
1862 auto bus = sdbusplus::bus::new_default();
1863 {
1864 PowerSupply psu{bus, PSUInventoryPath, 6,
1865 0x6f, "ibm-cffps", PSUGPIOLineName};
1866 // Defaults to not present due to constructor and mock ordering.
1867 psu.setupInputHistory();
1868 EXPECT_EQ(psu.hasInputHistory(), false);
1869 MockedGPIOInterface* mockPresenceGPIO =
1870 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1871 // Always return 1 to indicate present.
1872 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1873 psu.analyze();
1874 psu.setupInputHistory();
1875 EXPECT_EQ(psu.hasInputHistory(), true);
1876 }
1877 {
1878 PowerSupply psu{bus, PSUInventoryPath, 11,
1879 0x58, "inspur-ipsps", PSUGPIOLineName};
1880 // Defaults to not present due to constructor and mock ordering.
1881 psu.setupInputHistory();
1882 EXPECT_EQ(psu.hasInputHistory(), false);
1883 MockedGPIOInterface* mockPresenceGPIO =
1884 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1885 // Always return 1 to indicate present.
1886 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1887 psu.analyze();
1888 psu.setupInputHistory();
1889 // After updating to present, and retrying setup, expect inspur-ipsps to
1890 // still not support INPUT_HISTORY.
1891 EXPECT_EQ(psu.hasInputHistory(), false);
1892 }
1893}
1894
1895TEST_F(PowerSupplyTests, UpdateHistory)
1896{
1897 auto bus = sdbusplus::bus::new_default();
1898 PowerSupply psu{bus, PSUInventoryPath, 7,
1899 0x6e, "ibm-cffps", PSUGPIOLineName};
1900 EXPECT_EQ(psu.hasInputHistory(), false);
1901 EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
1902 MockedGPIOInterface* mockPresenceGPIO =
1903 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1904 // Always return 1 to indicate present.
1905 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1906 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1907 setMissingToPresentExpects(mockPMBus, mockedUtil);
1908 PMBusExpectations expectations;
1909 setPMBusExpectations(mockPMBus, expectations);
1910 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1911 .Times(6)
1912 .WillRepeatedly(Return("205000"));
1913 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
1914 // First read after missing/present will have no data.
1915 std::vector<uint8_t> emptyHistory{};
1916 // Second read, after about 30 seconds, should have a record. 5-bytes.
1917 // Sequence Number: 0x00, Average: 0x50 0xf3 (212), Maximum: 0x54 0xf3 (213)
1918 std::vector<uint8_t> firstHistory{0x00, 0x50, 0xf3, 0x54, 0xf3};
1919 // Third read, after about 60 seconds, should have two records, 10-bytes,
1920 // but only reading 5 bytes, so make sure new/next sequence number
1921 std::vector<uint8_t> secondHistory{0x01, 0x54, 0xf3, 0x58, 0xf3};
1922 // Fourth read, 3rd sequence number (0x02).
1923 std::vector<uint8_t> thirdHistory{0x02, 0x54, 0xf3, 0x58, 0xf3};
1924 // Fifth read, out of sequence, clear and insert this one?
1925 std::vector<uint8_t> outseqHistory{0xff, 0x5c, 0xf3, 0x60, 0xf3};
1926 EXPECT_CALL(
1927 mockPMBus,
1928 readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug,
1929 phosphor::power::history::RecordManager::RAW_RECORD_SIZE))
1930 .Times(6)
1931 .WillOnce(Return(emptyHistory))
1932 .WillOnce(Return(firstHistory))
1933 .WillOnce(Return(secondHistory))
1934 .WillOnce(Return(thirdHistory))
1935 .WillOnce(Return(outseqHistory))
1936 .WillOnce(Return(emptyHistory));
1937 // Calling analyze will update the presence, which will setup the input
1938 // history if the power supply went from missing to present.
1939 psu.analyze();
1940 // The ibm-cffps power supply should support input history
1941 EXPECT_EQ(psu.hasInputHistory(), true);
1942 // Usually should have empty buffer right after missing to present.
1943 // Faked that out above with mocked readBinary with emptyHistory data.
1944 EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
1945 // Second run through...
1946 setPMBusExpectations(mockPMBus, expectations);
1947 psu.analyze();
1948 EXPECT_EQ(psu.hasInputHistory(), true);
1949 EXPECT_EQ(psu.getNumInputHistoryRecords(), 1);
1950 // Third run through
1951 setPMBusExpectations(mockPMBus, expectations);
1952 psu.analyze();
1953 EXPECT_EQ(psu.hasInputHistory(), true);
1954 EXPECT_EQ(psu.getNumInputHistoryRecords(), 2);
1955 // Fourth run through. Up to 3 records now?
1956 setPMBusExpectations(mockPMBus, expectations);
1957 psu.analyze();
1958 EXPECT_EQ(psu.hasInputHistory(), true);
1959 EXPECT_EQ(psu.getNumInputHistoryRecords(), 3);
1960 // Out of sequencer, reset, insert new one.
1961 setPMBusExpectations(mockPMBus, expectations);
1962 psu.analyze();
1963 EXPECT_EQ(psu.hasInputHistory(), true);
1964 EXPECT_EQ(psu.getNumInputHistoryRecords(), 1);
1965 // Empty one after last one good. Reset/clear.
1966 setPMBusExpectations(mockPMBus, expectations);
1967 psu.analyze();
1968 EXPECT_EQ(psu.hasInputHistory(), true);
1969 EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
1970}