blob: 62f8b5dc36122e792aad55fdf1ab7324564fc617 [file] [log] [blame]
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001#include "../power_supply.hpp"
2#include "mock.hpp"
3
4#include <xyz/openbmc_project/Common/Device/error.hpp>
5#include <xyz/openbmc_project/Common/error.hpp>
6
7#include <gmock/gmock.h>
8#include <gtest/gtest.h>
9
10using namespace phosphor::power::psu;
11using namespace phosphor::pmbus;
12
13using ::testing::_;
Brandon Wyman59a35792020-06-04 12:37:40 -050014using ::testing::Args;
Brandon Wyman3f1242f2020-01-28 13:11:25 -060015using ::testing::Assign;
16using ::testing::DoAll;
Brandon Wyman59a35792020-06-04 12:37:40 -050017using ::testing::ElementsAre;
Matt Spinler592bd272023-08-30 11:00:01 -050018using ::testing::IsNan;
Brandon Wyman59a35792020-06-04 12:37:40 -050019using ::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";
George Liu9464c422023-02-27 14:30:27 +080025static auto isPowerOn = []() { return true; };
Brandon Wyman3f1242f2020-01-28 13:11:25 -060026
Brandon Wymanb654c612021-11-05 23:24:51 +000027struct PMBusExpectations
28{
29 uint16_t statusWordValue{0x0000};
30 uint8_t statusInputValue{0x00};
31 uint8_t statusMFRValue{0x00};
32 uint8_t statusCMLValue{0x00};
33 uint8_t statusVOUTValue{0x00};
Brandon Wymanb10b3be2021-11-09 22:12:15 +000034 uint8_t statusIOUTValue{0x00};
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +000035 uint8_t statusFans12Value{0x00};
Brandon Wyman96893a42021-11-05 19:56:57 +000036 uint8_t statusTempValue{0x00};
Brandon Wymanb654c612021-11-05 23:24:51 +000037};
38
Brandon Wyman8da35c52021-10-28 22:45:08 +000039// Helper function to setup expectations for various STATUS_* commands
Brandon Wymanb654c612021-11-05 23:24:51 +000040void setPMBusExpectations(MockedPMBus& mockPMBus,
41 const PMBusExpectations& expectations)
Brandon Wyman8da35c52021-10-28 22:45:08 +000042{
Brandon Wyman32453e92021-12-15 19:00:14 +000043 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000044 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000045 .WillOnce(Return(expectations.statusWordValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000046
Brandon Wymanb654c612021-11-05 23:24:51 +000047 if (expectations.statusWordValue != 0)
Brandon Wyman8da35c52021-10-28 22:45:08 +000048 {
49 // If fault bits are on in STATUS_WORD, there will also be a read of
Brandon Wyman96893a42021-11-05 19:56:57 +000050 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and
51 // STATUS_TEMPERATURE.
Brandon Wyman32453e92021-12-15 19:00:14 +000052 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000053 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000054 .WillOnce(Return(expectations.statusInputValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000055 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000056 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000057 .WillOnce(Return(expectations.statusMFRValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000058 EXPECT_CALL(mockPMBus, read(STATUS_CML, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000059 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000060 .WillOnce(Return(expectations.statusCMLValue));
Brandon Wyman6710ba22021-10-27 17:39:31 +000061 // Page will need to be set to 0 to read STATUS_VOUT.
62 EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0))
63 .Times(1)
64 .WillOnce(Return("status0_vout"));
Brandon Wyman32453e92021-12-15 19:00:14 +000065 EXPECT_CALL(mockPMBus, read("status0_vout", _, _))
Brandon Wyman6710ba22021-10-27 17:39:31 +000066 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000067 .WillOnce(Return(expectations.statusVOUTValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000068 EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _, _))
Brandon Wymanb10b3be2021-11-09 22:12:15 +000069 .Times(1)
70 .WillOnce(Return(expectations.statusIOUTValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000071 EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _, _))
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +000072 .Times(1)
73 .WillOnce(Return(expectations.statusFans12Value));
Brandon Wyman32453e92021-12-15 19:00:14 +000074 EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _, _))
Brandon Wyman96893a42021-11-05 19:56:57 +000075 .Times(1)
76 .WillOnce(Return(expectations.statusTempValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000077 }
Matt Spinler592bd272023-08-30 11:00:01 -050078
79 // Default max/peak is 213W
80 ON_CALL(mockPMBus, readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug, 5))
81 .WillByDefault(
82 Return(std::vector<uint8_t>{0x01, 0x5c, 0xf3, 0x54, 0xf3}));
Brandon Wyman8da35c52021-10-28 22:45:08 +000083}
84
Brandon Wyman3f1242f2020-01-28 13:11:25 -060085class PowerSupplyTests : public ::testing::Test
86{
87 public:
88 PowerSupplyTests() :
89 mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
90 {
91 ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
92 }
93
94 ~PowerSupplyTests() override
95 {
96 freeUtils();
97 }
98
99 const MockedUtil& mockedUtil;
100};
101
Brandon Wyman391a0692021-12-08 23:28:18 +0000102// Helper function for when a power supply goes from missing to present.
103void setMissingToPresentExpects(MockedPMBus& pmbus, const MockedUtil& util)
104{
105 // Call to analyze() will update to present, that will trigger updating
106 // to the correct/latest HWMON directory, in case it changes.
107 EXPECT_CALL(pmbus, findHwmonDir());
108 // Presence change from missing to present will trigger write to
109 // ON_OFF_CONFIG.
110 EXPECT_CALL(pmbus, writeBinary(ON_OFF_CONFIG, _, _));
111 // Presence change from missing to present will trigger in1_input read
112 // in an attempt to get CLEAR_FAULTS called.
Brandon Wyman82affd92021-11-24 19:12:49 +0000113 // This READ_VIN for CLEAR_FAULTS does not check the returned value.
Brandon Wyman3225a452022-03-18 18:51:49 +0000114 EXPECT_CALL(pmbus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
115 // The call for clearing faults includes clearing VIN_UV fault.
116 // The voltage defaults to 0, the first call to analyze should update the
117 // voltage to the current reading, triggering clearing VIN_UV fault(s)
118 // due to below minimum to within range voltage.
119 EXPECT_CALL(pmbus, read("in1_lcrit_alarm", _, _))
Brandon Wyman82affd92021-11-24 19:12:49 +0000120 .Times(2)
Brandon Wyman3225a452022-03-18 18:51:49 +0000121 .WillRepeatedly(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +0000122 // Missing/present call will update Presence in inventory.
Brandon Wyman391a0692021-12-08 23:28:18 +0000123 EXPECT_CALL(util, setPresence(_, _, true, _));
124}
125
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600126TEST_F(PowerSupplyTests, Constructor)
127{
128 /**
129 * @param[in] invpath - String for inventory path to use
130 * @param[in] i2cbus - The bus number this power supply is on
131 * @param[in] i2caddr - The 16-bit I2C address of the power supply
B. J. Wyman681b2a32021-04-20 22:31:22 +0000132 * @param[in] gpioLineName - The string for the gpio-line-name to read for
133 * presence.
134 * @param[in] bindDelay - Time in milliseconds to delay binding the device
135 * driver after seeing the presence line go active.
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600136 */
137 auto bus = sdbusplus::bus::new_default();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600138
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500139 // Try where inventory path is empty, constructor should fail.
140 try
141 {
Brandon Wymanc3324422022-03-24 20:30:57 +0000142 auto psu = std::make_unique<PowerSupply>(bus, "", 3, 0x68, "ibm-cffps",
George Liu9464c422023-02-27 14:30:27 +0800143 PSUGPIOLineName, isPowerOn);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500144 ADD_FAILURE() << "Should not have reached this line.";
145 }
146 catch (const std::invalid_argument& e)
147 {
148 EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
149 }
150 catch (...)
151 {
152 ADD_FAILURE() << "Should not have caught exception.";
153 }
154
B. J. Wyman681b2a32021-04-20 22:31:22 +0000155 // TODO: Try invalid i2c address?
156
157 // Try where gpioLineName is empty.
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500158 try
159 {
Brandon Wymanc3324422022-03-24 20:30:57 +0000160 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
George Liu9464c422023-02-27 14:30:27 +0800161 "ibm-cffps", "", isPowerOn);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000162 ADD_FAILURE()
163 << "Should not have reached this line. Invalid gpioLineName.";
164 }
165 catch (const std::invalid_argument& e)
166 {
167 EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
168 }
169 catch (...)
170 {
171 ADD_FAILURE() << "Should not have caught exception.";
172 }
173
174 // Test with valid arguments
175 // NOT using D-Bus inventory path for presence.
176 try
177 {
178 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
George Liu9464c422023-02-27 14:30:27 +0800179 "ibm-cffps", PSUGPIOLineName,
180 isPowerOn);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500181
182 EXPECT_EQ(psu->isPresent(), false);
183 EXPECT_EQ(psu->isFaulted(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000184 EXPECT_EQ(psu->hasCommFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500185 EXPECT_EQ(psu->hasInputFault(), false);
186 EXPECT_EQ(psu->hasMFRFault(), false);
187 EXPECT_EQ(psu->hasVINUVFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000188 EXPECT_EQ(psu->hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000189 EXPECT_EQ(psu->hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000190 EXPECT_EQ(psu->hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000191 EXPECT_EQ(psu->hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000192 EXPECT_EQ(psu->hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000193 EXPECT_EQ(psu->hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000194 EXPECT_EQ(psu->hasPSKillFault(), false);
195 EXPECT_EQ(psu->hasPS12VcsFault(), false);
196 EXPECT_EQ(psu->hasPSCS12VFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500197 }
198 catch (...)
199 {
200 ADD_FAILURE() << "Should not have caught exception.";
201 }
B. J. Wyman681b2a32021-04-20 22:31:22 +0000202
203 // Test with valid arguments
204 // TODO: Using D-Bus inventory path for presence.
205 try
206 {
207 // FIXME: How do I get that presenceGPIO.read() in the startup to throw
208 // an exception?
209
210 // EXPECT_CALL(mockedUtil, getPresence(_,
211 // StrEq(PSUInventoryPath)))
212 // .Times(1);
213 }
214 catch (...)
215 {
216 ADD_FAILURE() << "Should not have caught exception.";
217 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600218}
219
220TEST_F(PowerSupplyTests, Analyze)
221{
222 auto bus = sdbusplus::bus::new_default();
223
Brandon Wymanb654c612021-11-05 23:24:51 +0000224 {
225 // If I default to reading the GPIO, I will NOT expect a call to
226 // getPresence().
B. J. Wyman681b2a32021-04-20 22:31:22 +0000227
George Liu9464c422023-02-27 14:30:27 +0800228 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69,
229 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wymanb654c612021-11-05 23:24:51 +0000230 MockedGPIOInterface* mockPresenceGPIO =
231 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
232 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000233
Brandon Wymanb654c612021-11-05 23:24:51 +0000234 psu.analyze();
235 // By default, nothing should change.
236 EXPECT_EQ(psu.isPresent(), false);
237 EXPECT_EQ(psu.isFaulted(), false);
238 EXPECT_EQ(psu.hasInputFault(), false);
239 EXPECT_EQ(psu.hasMFRFault(), false);
240 EXPECT_EQ(psu.hasVINUVFault(), false);
241 EXPECT_EQ(psu.hasCommFault(), false);
242 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000243 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000244 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000245 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000246 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000247 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000248 EXPECT_EQ(psu.hasPSKillFault(), false);
249 EXPECT_EQ(psu.hasPS12VcsFault(), false);
250 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000251 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600252
George Liu9464c422023-02-27 14:30:27 +0800253 PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a,
254 "ibm-cffps", PSUGPIOLineName, isPowerOn};
B. J. Wyman681b2a32021-04-20 22:31:22 +0000255 // In order to get the various faults tested, the power supply needs to
256 // be present in order to read from the PMBus device(s).
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000257 MockedGPIOInterface* mockPresenceGPIO2 =
258 static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000259 // Always return 1 to indicate present.
260 // Each analyze() call will trigger a read of the presence GPIO.
261 EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000262 EXPECT_EQ(psu2.isPresent(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600263
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600264 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000265 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +0000266 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
267 // for INPUT_HISTORY will check max_power_out to see if it is
268 // old/unsupported power supply. Indicate good value, supported.
269 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -0500270 .WillRepeatedly(Return("2000"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600271
Brandon Wymanb654c612021-11-05 23:24:51 +0000272 // STATUS_WORD INPUT fault.
273 {
274 // Start with STATUS_WORD 0x0000. Powered on, no faults.
275 // Set expectations for a no fault
276 PMBusExpectations expectations;
277 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000278 // After reading STATUS_WORD, etc., there will be a READ_VIN check.
279 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
280 .Times(1)
281 .WillOnce(Return("206000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000282 psu2.analyze();
283 EXPECT_EQ(psu2.isPresent(), true);
284 EXPECT_EQ(psu2.isFaulted(), false);
285 EXPECT_EQ(psu2.hasInputFault(), false);
286 EXPECT_EQ(psu2.hasMFRFault(), false);
287 EXPECT_EQ(psu2.hasVINUVFault(), false);
288 EXPECT_EQ(psu2.hasCommFault(), false);
289 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000290 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000291 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000292 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000293 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000294 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000295 EXPECT_EQ(psu2.hasPSKillFault(), false);
296 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
297 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000298
299 // Update expectations for STATUS_WORD input fault/warn
Brandon Wyman96893a42021-11-05 19:56:57 +0000300 // STATUS_INPUT fault bits ... on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000301 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wyman3225a452022-03-18 18:51:49 +0000302 // IIN_OC fault.
303 expectations.statusInputValue = 0x04;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000304
305 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
306 {
307 setPMBusExpectations(mockPMBus, expectations);
308 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
309 .Times(1)
310 .WillOnce(Return("207000"));
311 psu2.analyze();
312 EXPECT_EQ(psu2.isPresent(), true);
313 // Should not be faulted until it reaches the deglitch limit.
314 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
315 EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
316 EXPECT_EQ(psu2.hasMFRFault(), false);
317 EXPECT_EQ(psu2.hasVINUVFault(), false);
318 EXPECT_EQ(psu2.hasCommFault(), false);
319 EXPECT_EQ(psu2.hasVoutOVFault(), false);
320 EXPECT_EQ(psu2.hasIoutOCFault(), false);
321 EXPECT_EQ(psu2.hasVoutUVFault(), false);
322 EXPECT_EQ(psu2.hasFanFault(), false);
323 EXPECT_EQ(psu2.hasTempFault(), false);
324 EXPECT_EQ(psu2.hasPgoodFault(), false);
325 EXPECT_EQ(psu2.hasPSKillFault(), false);
326 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
327 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
328 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000329 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600330
Brandon Wyman32453e92021-12-15 19:00:14 +0000331 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000332 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
333 .Times(1)
334 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000335 psu2.clearFaults();
336
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600337 // STATUS_WORD INPUT/UV fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000338 {
339 // First need it to return good status, then the fault
340 PMBusExpectations expectations;
341 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000342 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
343 .Times(1)
344 .WillOnce(Return("208000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000345 psu2.analyze();
Brandon Wymanc2906f42021-12-21 20:14:56 +0000346 EXPECT_EQ(psu2.isFaulted(), false);
347 EXPECT_EQ(psu2.hasInputFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000348 // Now set fault bits in STATUS_WORD
349 expectations.statusWordValue =
350 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
351 // STATUS_INPUT fault bits ... on.
Brandon Wyman3225a452022-03-18 18:51:49 +0000352 expectations.statusInputValue = 0x18;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000353 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
354 {
355 setPMBusExpectations(mockPMBus, expectations);
356 // Input/UV fault, so voltage should read back low.
357 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
358 .Times(1)
359 .WillOnce(Return("19123"));
360 psu2.analyze();
361 EXPECT_EQ(psu2.isPresent(), true);
362 // Only faulted if hit deglitch limit
363 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
364 EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
365 EXPECT_EQ(psu2.hasVINUVFault(), x >= DEGLITCH_LIMIT);
366 EXPECT_EQ(psu2.hasMFRFault(), false);
367 EXPECT_EQ(psu2.hasCommFault(), false);
368 EXPECT_EQ(psu2.hasVoutOVFault(), false);
369 EXPECT_EQ(psu2.hasIoutOCFault(), false);
370 EXPECT_EQ(psu2.hasVoutUVFault(), false);
371 EXPECT_EQ(psu2.hasFanFault(), false);
372 EXPECT_EQ(psu2.hasTempFault(), false);
373 EXPECT_EQ(psu2.hasPgoodFault(), false);
374 EXPECT_EQ(psu2.hasPSKillFault(), false);
375 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
376 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
377 }
Brandon Wyman82affd92021-11-24 19:12:49 +0000378 // Turning VIN_UV fault off causes clearing of faults, causing read of
379 // in1_input as an attempt to get CLEAR_FAULTS called.
380 expectations.statusWordValue = 0;
381 setPMBusExpectations(mockPMBus, expectations);
382 // The call to read the voltage
383 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
384 .Times(1)
385 .WillOnce(Return("209000"));
Brandon Wyman3225a452022-03-18 18:51:49 +0000386 // The call to clear VIN_UV/Off fault(s)
387 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
Brandon Wyman32453e92021-12-15 19:00:14 +0000388 .Times(1)
Brandon Wyman3225a452022-03-18 18:51:49 +0000389 .WillOnce(Return(1));
Brandon Wyman82affd92021-11-24 19:12:49 +0000390 psu2.analyze();
391 // Should remain present, no longer be faulted, no input fault, no
392 // VIN_UV fault. Nothing else should change.
393 EXPECT_EQ(psu2.isPresent(), true);
394 EXPECT_EQ(psu2.isFaulted(), false);
395 EXPECT_EQ(psu2.hasInputFault(), false);
396 EXPECT_EQ(psu2.hasVINUVFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000397 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600398
Brandon Wyman32453e92021-12-15 19:00:14 +0000399 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000400 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
401 .Times(1)
402 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000403 psu2.clearFaults();
404
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600405 // STATUS_WORD MFR fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000406 {
407 // First need it to return good status, then the fault
408 PMBusExpectations expectations;
409 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000410 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
411 .Times(1)
412 .WillOnce(Return("210000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000413 psu2.analyze();
414 // Now STATUS_WORD with MFR fault bit on.
415 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
416 // STATUS_MFR bits on.
417 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000418
419 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
420 {
421 setPMBusExpectations(mockPMBus, expectations);
422 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
423 .Times(1)
424 .WillOnce(Return("211000"));
425 psu2.analyze();
426 EXPECT_EQ(psu2.isPresent(), true);
427 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
428 EXPECT_EQ(psu2.hasInputFault(), false);
429 EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT);
430 EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT);
431 EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
432 EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
433 EXPECT_EQ(psu2.hasVINUVFault(), false);
434 EXPECT_EQ(psu2.hasCommFault(), false);
435 EXPECT_EQ(psu2.hasVoutOVFault(), false);
436 EXPECT_EQ(psu2.hasIoutOCFault(), false);
437 EXPECT_EQ(psu2.hasVoutUVFault(), false);
438 EXPECT_EQ(psu2.hasFanFault(), false);
439 EXPECT_EQ(psu2.hasTempFault(), false);
440 EXPECT_EQ(psu2.hasPgoodFault(), false);
441 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000442 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600443
Brandon Wyman32453e92021-12-15 19:00:14 +0000444 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000445 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
446 .Times(1)
447 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000448 psu2.clearFaults();
Brandon Wyman3225a452022-03-18 18:51:49 +0000449
Brandon Wyman96893a42021-11-05 19:56:57 +0000450 // Temperature fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000451 {
452 // First STATUS_WORD with no bits set, then with temperature fault.
453 PMBusExpectations expectations;
454 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000455 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
456 .Times(1)
457 .WillOnce(Return("212000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000458 psu2.analyze();
459 // STATUS_WORD with temperature fault bit on.
460 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
Brandon Wyman96893a42021-11-05 19:56:57 +0000461 // STATUS_TEMPERATURE with fault bit(s) on.
462 expectations.statusTempValue = 0x10;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000463 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
464 {
465 setPMBusExpectations(mockPMBus, expectations);
466 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
467 .Times(1)
468 .WillOnce(Return("213000"));
469 psu2.analyze();
470 EXPECT_EQ(psu2.isPresent(), true);
471 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
472 EXPECT_EQ(psu2.hasInputFault(), false);
473 EXPECT_EQ(psu2.hasMFRFault(), false);
474 EXPECT_EQ(psu2.hasVINUVFault(), false);
475 EXPECT_EQ(psu2.hasCommFault(), false);
476 EXPECT_EQ(psu2.hasVoutOVFault(), false);
477 EXPECT_EQ(psu2.hasIoutOCFault(), false);
478 EXPECT_EQ(psu2.hasVoutUVFault(), false);
479 EXPECT_EQ(psu2.hasFanFault(), false);
480 EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT);
481 EXPECT_EQ(psu2.hasPgoodFault(), false);
482 EXPECT_EQ(psu2.hasPSKillFault(), false);
483 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
484 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
485 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000486 }
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000487
Brandon Wyman32453e92021-12-15 19:00:14 +0000488 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000489 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
490 .Times(1)
491 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000492 psu2.clearFaults();
Brandon Wyman3225a452022-03-18 18:51:49 +0000493
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000494 // CML fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000495 {
496 // First STATUS_WORD wit no bits set, then with CML fault.
497 PMBusExpectations expectations;
498 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000499 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
500 .Times(1)
501 .WillOnce(Return("214000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000502 psu2.analyze();
503 // STATUS_WORD with CML fault bit on.
504 expectations.statusWordValue = (status_word::CML_FAULT);
505 // Turn on STATUS_CML fault bit(s)
506 expectations.statusCMLValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000507 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
508 {
509 setPMBusExpectations(mockPMBus, expectations);
510 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
511 .Times(1)
512 .WillOnce(Return("215000"));
513 psu2.analyze();
514 EXPECT_EQ(psu2.isPresent(), true);
515 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
516 EXPECT_EQ(psu2.hasCommFault(), x >= DEGLITCH_LIMIT);
517 EXPECT_EQ(psu2.hasInputFault(), false);
518 EXPECT_EQ(psu2.hasMFRFault(), false);
519 EXPECT_EQ(psu2.hasVINUVFault(), false);
520 EXPECT_EQ(psu2.hasVoutOVFault(), false);
521 EXPECT_EQ(psu2.hasIoutOCFault(), false);
522 EXPECT_EQ(psu2.hasVoutUVFault(), false);
523 EXPECT_EQ(psu2.hasFanFault(), false);
524 EXPECT_EQ(psu2.hasTempFault(), false);
525 EXPECT_EQ(psu2.hasPgoodFault(), false);
526 EXPECT_EQ(psu2.hasPSKillFault(), false);
527 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
528 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
529 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000530 }
Brandon Wyman6710ba22021-10-27 17:39:31 +0000531
Brandon Wyman32453e92021-12-15 19:00:14 +0000532 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000533 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
534 .Times(1)
535 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000536 psu2.clearFaults();
Brandon Wyman3225a452022-03-18 18:51:49 +0000537
Brandon Wyman6710ba22021-10-27 17:39:31 +0000538 // VOUT_OV_FAULT fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000539 {
540 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
541 PMBusExpectations expectations;
542 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000543 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
544 .Times(1)
545 .WillOnce(Return("216000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000546 psu2.analyze();
547 // STATUS_WORD with VOUT/VOUT_OV fault.
548 expectations.statusWordValue =
549 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
550 // Turn on STATUS_VOUT fault bit(s)
551 expectations.statusVOUTValue = 0xA0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000552 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
553 {
554 // STATUS_TEMPERATURE don't care (default)
555 setPMBusExpectations(mockPMBus, expectations);
556 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
557 .Times(1)
558 .WillOnce(Return("217000"));
559 psu2.analyze();
560 EXPECT_EQ(psu2.isPresent(), true);
561 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
562 EXPECT_EQ(psu2.hasInputFault(), false);
563 EXPECT_EQ(psu2.hasMFRFault(), false);
564 EXPECT_EQ(psu2.hasVINUVFault(), false);
565 EXPECT_EQ(psu2.hasCommFault(), false);
566 EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
567 EXPECT_EQ(psu2.hasVoutUVFault(), false);
568 EXPECT_EQ(psu2.hasIoutOCFault(), false);
569 EXPECT_EQ(psu2.hasFanFault(), false);
570 EXPECT_EQ(psu2.hasTempFault(), false);
571 EXPECT_EQ(psu2.hasPgoodFault(), false);
572 EXPECT_EQ(psu2.hasPSKillFault(), false);
573 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
574 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
575 }
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000576 }
577
578 // IOUT_OC_FAULT fault
579 {
580 // First STATUS_WORD with no bits set, then with IOUT_OC fault.
581 PMBusExpectations expectations;
582 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000583 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
584 .Times(1)
585 .WillOnce(Return("218000"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000586 psu2.analyze();
587 // STATUS_WORD with IOUT_OC fault.
588 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
589 // Turn on STATUS_IOUT fault bit(s)
590 expectations.statusIOUTValue = 0x88;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000591 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
592 {
593 setPMBusExpectations(mockPMBus, expectations);
594 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
595 .Times(1)
596 .WillOnce(Return("219000"));
597 psu2.analyze();
598 EXPECT_EQ(psu2.isPresent(), true);
599 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
600 EXPECT_EQ(psu2.hasInputFault(), false);
601 EXPECT_EQ(psu2.hasMFRFault(), false);
602 EXPECT_EQ(psu2.hasVINUVFault(), false);
603 EXPECT_EQ(psu2.hasCommFault(), false);
604 EXPECT_EQ(psu2.hasVoutOVFault(), false);
605 EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
606 EXPECT_EQ(psu2.hasVoutUVFault(), false);
607 EXPECT_EQ(psu2.hasFanFault(), false);
608 EXPECT_EQ(psu2.hasTempFault(), false);
609 EXPECT_EQ(psu2.hasPgoodFault(), false);
610 EXPECT_EQ(psu2.hasPSKillFault(), false);
611 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
612 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
613 }
Brandon Wyman2cf46942021-10-28 19:09:16 +0000614 }
615
616 // VOUT_UV_FAULT
617 {
618 // First STATUS_WORD with no bits set, then with VOUT fault.
619 PMBusExpectations expectations;
620 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000621 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
622 .Times(1)
623 .WillOnce(Return("220000"));
Brandon Wyman2cf46942021-10-28 19:09:16 +0000624 psu2.analyze();
625 // Change STATUS_WORD to indicate VOUT fault.
626 expectations.statusWordValue = (status_word::VOUT_FAULT);
627 // Turn on STATUS_VOUT fault bit(s)
628 expectations.statusVOUTValue = 0x30;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000629 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
630 {
631 setPMBusExpectations(mockPMBus, expectations);
632 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
633 .Times(1)
634 .WillOnce(Return("221000"));
635 psu2.analyze();
636 EXPECT_EQ(psu2.isPresent(), true);
637 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
638 EXPECT_EQ(psu2.hasInputFault(), false);
639 EXPECT_EQ(psu2.hasMFRFault(), false);
640 EXPECT_EQ(psu2.hasVINUVFault(), false);
641 EXPECT_EQ(psu2.hasCommFault(), false);
642 EXPECT_EQ(psu2.hasVoutOVFault(), false);
643 EXPECT_EQ(psu2.hasIoutOCFault(), false);
644 EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
645 EXPECT_EQ(psu2.hasFanFault(), false);
646 EXPECT_EQ(psu2.hasTempFault(), false);
647 EXPECT_EQ(psu2.hasPgoodFault(), false);
648 EXPECT_EQ(psu2.hasPSKillFault(), false);
649 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
650 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
651 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000652 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600653
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000654 // Fan fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000655 {
656 // First STATUS_WORD with no bits set, then with fan fault.
657 PMBusExpectations expectations;
658 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000659 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
660 .Times(1)
661 .WillOnce(Return("222000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000662 psu2.analyze();
663 expectations.statusWordValue = (status_word::FAN_FAULT);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000664 // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
665 expectations.statusFans12Value = 0xA0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000666
667 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
668 {
669 setPMBusExpectations(mockPMBus, expectations);
670 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
671 .Times(1)
672 .WillOnce(Return("223000"));
673 psu2.analyze();
674 EXPECT_EQ(psu2.isPresent(), true);
675 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
676 EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT);
677 EXPECT_EQ(psu2.hasInputFault(), false);
678 EXPECT_EQ(psu2.hasMFRFault(), false);
679 EXPECT_EQ(psu2.hasVINUVFault(), false);
680 EXPECT_EQ(psu2.hasCommFault(), false);
681 EXPECT_EQ(psu2.hasVoutOVFault(), false);
682 EXPECT_EQ(psu2.hasIoutOCFault(), false);
683 EXPECT_EQ(psu2.hasVoutUVFault(), false);
684 EXPECT_EQ(psu2.hasTempFault(), false);
685 EXPECT_EQ(psu2.hasPgoodFault(), false);
686 EXPECT_EQ(psu2.hasPSKillFault(), false);
687 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
688 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
689 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000690 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000691
Brandon Wyman06ca4592021-12-06 22:52:23 +0000692 // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000693 {
Brandon Wyman2916ea52021-11-06 03:31:18 +0000694 // First STATUS_WORD with no bits set.
695 PMBusExpectations expectations;
696 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000697 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
698 .Times(1)
699 .WillOnce(Return("123000"));
Brandon Wyman2916ea52021-11-06 03:31:18 +0000700 psu2.analyze();
701 EXPECT_EQ(psu2.isFaulted(), false);
702 // POWER_GOOD# inactive, and OFF bit on.
703 expectations.statusWordValue =
704 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000705 for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++)
Brandon Wyman06ca4592021-12-06 22:52:23 +0000706 {
707 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
708 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
709 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000710 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
711 .Times(1)
712 .WillOnce(Return("124000"));
Brandon Wyman06ca4592021-12-06 22:52:23 +0000713 psu2.analyze();
714 EXPECT_EQ(psu2.isPresent(), true);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000715 EXPECT_EQ(psu2.isFaulted(), x >= PGOOD_DEGLITCH_LIMIT);
Brandon Wyman06ca4592021-12-06 22:52:23 +0000716 EXPECT_EQ(psu2.hasInputFault(), false);
717 EXPECT_EQ(psu2.hasMFRFault(), false);
718 EXPECT_EQ(psu2.hasVINUVFault(), false);
719 EXPECT_EQ(psu2.hasCommFault(), false);
720 EXPECT_EQ(psu2.hasVoutOVFault(), false);
721 EXPECT_EQ(psu2.hasVoutUVFault(), false);
722 EXPECT_EQ(psu2.hasIoutOCFault(), false);
723 EXPECT_EQ(psu2.hasFanFault(), false);
724 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000725 EXPECT_EQ(psu2.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT);
Brandon Wyman06ca4592021-12-06 22:52:23 +0000726 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000727 }
728
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600729 // TODO: ReadFailure
730}
731
Brandon Wyman59a35792020-06-04 12:37:40 -0500732TEST_F(PowerSupplyTests, OnOffConfig)
733{
734 auto bus = sdbusplus::bus::new_default();
735 uint8_t data = 0x15;
736
737 // Test where PSU is NOT present
738 try
739 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000740 // Assume GPIO presence, not inventory presence?
Matt Spinler0975eaf2022-02-14 15:38:30 -0600741 EXPECT_CALL(mockedUtil, setAvailable(_, _, _)).Times(0);
George Liu9464c422023-02-27 14:30:27 +0800742 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69,
743 "ibm-cffps", PSUGPIOLineName, isPowerOn};
B. J. Wyman681b2a32021-04-20 22:31:22 +0000744
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000745 MockedGPIOInterface* mockPresenceGPIO =
746 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000747 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
Brandon Wyman59a35792020-06-04 12:37:40 -0500748 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000749 // Constructor should set initial presence, default read returns 0.
Brandon Wyman59a35792020-06-04 12:37:40 -0500750 // If it is not present, I should not be trying to write to it.
751 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
752 psu.onOffConfig(data);
753 }
754 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000755 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500756
757 // Test where PSU is present
758 try
759 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000760 // Assume GPIO presence, not inventory presence?
Matt Spinler0975eaf2022-02-14 15:38:30 -0600761 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
George Liu9464c422023-02-27 14:30:27 +0800762 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a,
763 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000764 MockedGPIOInterface* mockPresenceGPIO =
765 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman391a0692021-12-08 23:28:18 +0000766 // There will potentially be multiple calls, we want it to continue
767 // returning 1 for the GPIO read to keep the power supply present.
768 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman59a35792020-06-04 12:37:40 -0500769 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000770 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +0000771 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
772 // for INPUT_HISTORY will check max_power_out to see if it is
773 // old/unsupported power supply. Indicate good value, supported.
774 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -0500775 .WillRepeatedly(Return("2000"));
Brandon Wyman391a0692021-12-08 23:28:18 +0000776 // If I am calling analyze(), I should probably give it good data.
777 // STATUS_WORD 0x0000 is powered on, no faults.
778 PMBusExpectations expectations;
779 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000780 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
781 .Times(1)
782 .WillOnce(Return("205000"));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000783 psu.analyze();
Brandon Wyman391a0692021-12-08 23:28:18 +0000784 // I definitely should be writting ON_OFF_CONFIG if I call the function
785 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
786 Type::HwmonDeviceDebug))
Brandon Wyman59a35792020-06-04 12:37:40 -0500787 .Times(1);
788 psu.onOffConfig(data);
789 }
790 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000791 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500792}
793
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600794TEST_F(PowerSupplyTests, ClearFaults)
795{
796 auto bus = sdbusplus::bus::new_default();
George Liu9464c422023-02-27 14:30:27 +0800797 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68,
798 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000799 MockedGPIOInterface* mockPresenceGPIO =
800 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000801 // Always return 1 to indicate present.
802 // Each analyze() call will trigger a read of the presence GPIO.
803 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000804 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000805 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +0000806 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
807 // for INPUT_HISTORY will check max_power_out to see if it is
808 // old/unsupported power supply. Indicate good value, supported.
809 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -0500810 .WillRepeatedly(Return("2000"));
Brandon Wyman8da35c52021-10-28 22:45:08 +0000811 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000812 PMBusExpectations expectations;
813 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000814 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
815 .Times(1)
816 .WillOnce(Return("207000"));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000817 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600818 EXPECT_EQ(psu.isPresent(), true);
819 EXPECT_EQ(psu.isFaulted(), false);
820 EXPECT_EQ(psu.hasInputFault(), false);
821 EXPECT_EQ(psu.hasMFRFault(), false);
822 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000823 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000824 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000825 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000826 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000827 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000828 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000829 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000830 EXPECT_EQ(psu.hasPSKillFault(), false);
831 EXPECT_EQ(psu.hasPS12VcsFault(), false);
832 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000833
Brandon Wymanf07bc792021-10-12 19:00:35 +0000834 // STATUS_WORD with fault bits galore!
Brandon Wymanb654c612021-11-05 23:24:51 +0000835 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000836 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000837 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000838 // STATUS_MFR_SPEFIC with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000839 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000840 // STATUS_CML with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000841 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000842 // STATUS_VOUT with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000843 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000844 // STATUS_IOUT with bits on.
845 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000846 // STATUS_FANS_1_2 with bits on.
847 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000848 // STATUS_TEMPERATURE with bits on.
849 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000850
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000851 for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++)
Brandon Wymanc2906f42021-12-21 20:14:56 +0000852 {
853 setPMBusExpectations(mockPMBus, expectations);
854 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
855 .Times(1)
856 .WillOnce(Return("0"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600857 if (x == DEGLITCH_LIMIT)
858 {
859 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
860 }
Brandon Wymanc2906f42021-12-21 20:14:56 +0000861 psu.analyze();
862 EXPECT_EQ(psu.isPresent(), true);
863 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
864 // Rely on HasVoutUVFault() to verify this sets and clears.
865 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000866 // pgoodFault at PGOOD_DEGLITCH_LIMIT, all other faults are deglitched
867 // up to DEGLITCH_LIMIT
Brandon Wymanc2906f42021-12-21 20:14:56 +0000868 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
869 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
870 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
871 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
872 EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT);
873 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
874 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
875 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
876 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000877 EXPECT_EQ(psu.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT);
Brandon Wymanc2906f42021-12-21 20:14:56 +0000878 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
879 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
880 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
881 }
882
Brandon Wyman32453e92021-12-15 19:00:14 +0000883 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _))
884 .Times(1)
885 .WillOnce(Return(207000));
Brandon Wyman3225a452022-03-18 18:51:49 +0000886 // Clearing VIN_UV fault via in1_lcrit_alarm
887 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
888 .Times(1)
889 .WillOnce(Return(1));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600890 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600891 psu.clearFaults();
892 EXPECT_EQ(psu.isPresent(), true);
893 EXPECT_EQ(psu.isFaulted(), false);
894 EXPECT_EQ(psu.hasInputFault(), false);
895 EXPECT_EQ(psu.hasMFRFault(), false);
896 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000897 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000898 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000899 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000900 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000901 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000902 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000903 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000904 EXPECT_EQ(psu.hasPSKillFault(), false);
905 EXPECT_EQ(psu.hasPS12VcsFault(), false);
906 EXPECT_EQ(psu.hasPSCS12VFault(), false);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000907
Brandon Wyman82affd92021-11-24 19:12:49 +0000908 // Faults clear on READ_VIN 0 -> !0
909 // STATUS_WORD with fault bits galore!
910 expectations.statusWordValue = 0xFFFF;
911 // STATUS_INPUT with fault bits on.
912 expectations.statusInputValue = 0xFF;
913 // STATUS_MFR_SPEFIC with bits on.
914 expectations.statusMFRValue = 0xFF;
915 // STATUS_CML with bits on.
916 expectations.statusCMLValue = 0xFF;
917 // STATUS_VOUT with bits on.
918 expectations.statusVOUTValue = 0xFF;
919 // STATUS_IOUT with bits on.
920 expectations.statusIOUTValue = 0xFF;
921 // STATUS_FANS_1_2 with bits on.
922 expectations.statusFans12Value = 0xFF;
923 // STATUS_TEMPERATURE with bits on.
924 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000925
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000926 // All faults deglitched now. Check for false before limit above.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000927 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
928 {
929 setPMBusExpectations(mockPMBus, expectations);
930 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
931 .Times(1)
932 .WillOnce(Return("0"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600933 if (x == DEGLITCH_LIMIT)
934 {
935 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
936 }
Brandon Wymanc2906f42021-12-21 20:14:56 +0000937 psu.analyze();
938 }
939
Brandon Wyman82affd92021-11-24 19:12:49 +0000940 EXPECT_EQ(psu.isPresent(), true);
941 EXPECT_EQ(psu.isFaulted(), true);
942 EXPECT_EQ(psu.hasInputFault(), true);
943 EXPECT_EQ(psu.hasMFRFault(), true);
944 EXPECT_EQ(psu.hasVINUVFault(), true);
945 // True due to CML fault bits on
946 EXPECT_EQ(psu.hasCommFault(), true);
947 EXPECT_EQ(psu.hasVoutOVFault(), true);
948 EXPECT_EQ(psu.hasIoutOCFault(), true);
949 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
950 // Rely on HasVoutUVFault() to verify this sets and clears.
951 EXPECT_EQ(psu.hasVoutUVFault(), false);
952 EXPECT_EQ(psu.hasFanFault(), true);
953 EXPECT_EQ(psu.hasTempFault(), true);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000954 // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT
955 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman82affd92021-11-24 19:12:49 +0000956 EXPECT_EQ(psu.hasPSKillFault(), true);
957 EXPECT_EQ(psu.hasPS12VcsFault(), true);
958 EXPECT_EQ(psu.hasPSCS12VFault(), true);
959 // STATUS_WORD with INPUT/VIN_UV fault bits off.
960 expectations.statusWordValue = 0xDFF7;
961 // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
962 // Insufficient Input Voltage bits off.
963 expectations.statusInputValue = 0xC7;
964 setPMBusExpectations(mockPMBus, expectations);
965 // READ_VIN back in range.
966 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
967 .Times(1)
968 .WillOnce(Return("206000"));
Brandon Wyman3225a452022-03-18 18:51:49 +0000969 // VIN_UV cleared via in1_lcrit_alarm when voltage back in range.
970 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
971 .Times(1)
972 .WillOnce(Return(1));
973 psu.analyze();
974 // We only cleared the VIN_UV and OFF faults.
975 EXPECT_EQ(psu.isPresent(), true);
976 EXPECT_EQ(psu.isFaulted(), true);
977 EXPECT_EQ(psu.hasInputFault(), false);
978 EXPECT_EQ(psu.hasMFRFault(), true);
979 EXPECT_EQ(psu.hasVINUVFault(), false);
980 EXPECT_EQ(psu.hasCommFault(), true);
981 EXPECT_EQ(psu.hasVoutOVFault(), true);
982 EXPECT_EQ(psu.hasIoutOCFault(), true);
983 EXPECT_EQ(psu.hasVoutUVFault(), false);
984 EXPECT_EQ(psu.hasFanFault(), true);
985 EXPECT_EQ(psu.hasTempFault(), true);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000986 // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT
987 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman3225a452022-03-18 18:51:49 +0000988 EXPECT_EQ(psu.hasPSKillFault(), true);
989 EXPECT_EQ(psu.hasPS12VcsFault(), true);
990 EXPECT_EQ(psu.hasPSCS12VFault(), true);
991
992 // All faults cleared
993 expectations = {0};
994 setPMBusExpectations(mockPMBus, expectations);
995 // READ_VIN back in range.
996 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
997 .Times(1)
998 .WillOnce(Return("206000"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600999 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman82affd92021-11-24 19:12:49 +00001000 psu.analyze();
1001 EXPECT_EQ(psu.isPresent(), true);
1002 EXPECT_EQ(psu.isFaulted(), false);
1003 EXPECT_EQ(psu.hasInputFault(), false);
1004 EXPECT_EQ(psu.hasMFRFault(), false);
1005 EXPECT_EQ(psu.hasVINUVFault(), false);
1006 EXPECT_EQ(psu.hasCommFault(), false);
1007 EXPECT_EQ(psu.hasVoutOVFault(), false);
1008 EXPECT_EQ(psu.hasIoutOCFault(), false);
1009 EXPECT_EQ(psu.hasVoutUVFault(), false);
1010 EXPECT_EQ(psu.hasFanFault(), false);
1011 EXPECT_EQ(psu.hasTempFault(), false);
1012 EXPECT_EQ(psu.hasPgoodFault(), false);
1013 EXPECT_EQ(psu.hasPSKillFault(), false);
1014 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1015 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1016
B. J. Wyman681b2a32021-04-20 22:31:22 +00001017 // TODO: Faults clear on missing/present?
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001018}
1019
1020TEST_F(PowerSupplyTests, UpdateInventory)
1021{
1022 auto bus = sdbusplus::bus::new_default();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001023
1024 try
1025 {
George Liu9464c422023-02-27 14:30:27 +08001026 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68,
1027 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001028 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1029 // If it is not present, I should not be trying to read a string
1030 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
1031 psu.updateInventory();
1032 }
1033 catch (...)
1034 {
1035 ADD_FAILURE() << "Should not have caught exception.";
1036 }
1037
1038 try
1039 {
George Liu9464c422023-02-27 14:30:27 +08001040 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69,
1041 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001042 MockedGPIOInterface* mockPresenceGPIO =
1043 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001044 // GPIO read return 1 to indicate present.
1045 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001046 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001047 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001048 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1049 // for INPUT_HISTORY will check max_power_out to see if it is
1050 // old/unsupported power supply. Indicate good value, supported.
1051 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001052 .WillRepeatedly(Return("2000"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001053 // STATUS_WORD 0x0000 is powered on, no faults.
1054 PMBusExpectations expectations;
1055 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001056 // Call to analyze will read voltage, trigger clear faults for 0 to
1057 // within range.
1058 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1059 .Times(1)
1060 .WillOnce(Return("123456"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001061 psu.analyze();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001062 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
1063 psu.updateInventory();
1064
Brandon Wyman3c530fb2021-04-13 13:13:22 -05001065#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001066 EXPECT_CALL(mockPMBus, readString(_, _))
1067 .WillOnce(Return("CCIN"))
1068 .WillOnce(Return("PN3456"))
1069 .WillOnce(Return("FN3456"))
1070 .WillOnce(Return("HEADER"))
1071 .WillOnce(Return("SN3456"))
1072 .WillOnce(Return("FW3456"));
Brandon Wyman3c530fb2021-04-13 13:13:22 -05001073#endif
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001074 psu.updateInventory();
1075 // TODO: D-Bus mocking to verify values stored on D-Bus (???)
1076 }
1077 catch (...)
1078 {
1079 ADD_FAILURE() << "Should not have caught exception.";
1080 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001081}
1082
1083TEST_F(PowerSupplyTests, IsPresent)
1084{
1085 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001086
George Liu9464c422023-02-27 14:30:27 +08001087 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68,
1088 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001089 MockedGPIOInterface* mockPresenceGPIO =
1090 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001091 EXPECT_EQ(psu.isPresent(), false);
1092
B. J. Wyman681b2a32021-04-20 22:31:22 +00001093 // Change GPIO read to return 1 to indicate present.
1094 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +00001095 // Call to analyze() will update to present, that will trigger updating
1096 // to the correct/latest HWMON directory, in case it changes.
1097 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1098 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001099 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1100 // for INPUT_HISTORY will check max_power_out to see if it is
1101 // old/unsupported power supply. Indicate good value, supported.
1102 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001103 .WillRepeatedly(Return("2000"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001104 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1105 // Default expectations will be on, no faults.
1106 PMBusExpectations expectations;
1107 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001108 // Give it an input voltage in the 100-volt range.
1109 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1110 .Times(1)
1111 .WillOnce(Return("123456"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001112 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
B. J. Wyman681b2a32021-04-20 22:31:22 +00001113 psu.analyze();
1114 EXPECT_EQ(psu.isPresent(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001115}
1116
1117TEST_F(PowerSupplyTests, IsFaulted)
1118{
1119 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001120
George Liu9464c422023-02-27 14:30:27 +08001121 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f,
1122 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001123 MockedGPIOInterface* mockPresenceGPIO =
1124 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001125 // Always return 1 to indicate present.
1126 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +00001127 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1128 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001129 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1130 // for INPUT_HISTORY will check max_power_out to see if it is
1131 // old/unsupported power supply. Indicate good value, supported.
1132 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001133 .WillRepeatedly(Return("2000"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001134 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1135 // Default expectations will be on, no faults.
1136 PMBusExpectations expectations;
1137 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001138 // Give it an input voltage in the 100-volt range.
1139 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1140 .Times(1)
1141 .WillOnce(Return("124680"));
B. J. Wyman681b2a32021-04-20 22:31:22 +00001142 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001143 EXPECT_EQ(psu.isFaulted(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001144 // STATUS_WORD with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001145 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +00001146 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001147 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +00001148 // STATUS_MFR_SPECIFIC with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001149 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +00001150 // STATUS_CML with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001151 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +00001152 // STATUS_VOUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001153 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001154 // STATUS_IOUT with fault bits on.
1155 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001156 // STATUS_FANS_1_2 with bits on.
1157 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +00001158 // STATUS_TEMPERATURE with fault bits on.
1159 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001160 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1161 {
1162 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman4fc191f2022-03-10 23:07:13 +00001163 // Also get another read of READ_VIN, faulted, so not in 100-volt range
Brandon Wymanc2906f42021-12-21 20:14:56 +00001164 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1165 .Times(1)
Brandon Wyman4fc191f2022-03-10 23:07:13 +00001166 .WillOnce(Return("19000"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001167 if (x == DEGLITCH_LIMIT)
1168 {
1169 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1170 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001171 psu.analyze();
1172 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
1173 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001174}
1175
1176TEST_F(PowerSupplyTests, HasInputFault)
1177{
1178 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001179
George Liu9464c422023-02-27 14:30:27 +08001180 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68,
1181 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001182 MockedGPIOInterface* mockPresenceGPIO =
1183 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001184 // Always return 1 to indicate present.
1185 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001186 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001187 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001188 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1189 // for INPUT_HISTORY will check max_power_out to see if it is
1190 // old/unsupported power supply. Indicate good value, supported.
1191 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001192 .WillRepeatedly(Return("2000"));
Brandon Wyman8da35c52021-10-28 22:45:08 +00001193 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001194 PMBusExpectations expectations;
1195 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001196 // Analyze call will also need good READ_VIN value to check.
1197 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1198 .Times(1)
1199 .WillOnce(Return("201100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001200 psu.analyze();
1201 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001202 // STATUS_WORD with input fault/warn on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001203 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001204 // STATUS_INPUT with an input fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001205 expectations.statusInputValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001206 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1207 {
1208 setPMBusExpectations(mockPMBus, expectations);
1209 // Analyze call will also need good READ_VIN value to check.
1210 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1211 .Times(1)
1212 .WillOnce(Return("201200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001213 if (x == DEGLITCH_LIMIT)
1214 {
1215 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1216 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001217 psu.analyze();
1218 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
1219 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001220 // STATUS_WORD with no bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001221 expectations.statusWordValue = 0;
1222 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001223 // Analyze call will also need good READ_VIN value to check.
1224 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1225 .Times(1)
1226 .WillOnce(Return("201300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001227 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001228 psu.analyze();
1229 EXPECT_EQ(psu.hasInputFault(), false);
1230}
1231
1232TEST_F(PowerSupplyTests, HasMFRFault)
1233{
1234 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001235
George Liu9464c422023-02-27 14:30:27 +08001236 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68,
1237 "ibm-cffps", PSUGPIOLineName, isPowerOn};
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 Wymanae35ac52022-05-23 22:33:40 +00001244 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1245 // for INPUT_HISTORY will check max_power_out to see if it is
1246 // old/unsupported power supply. Indicate good value, supported.
1247 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001248 .WillRepeatedly(Return("2000"));
Brandon Wymanf07bc792021-10-12 19:00:35 +00001249 // First return STATUS_WORD with no bits on.
Brandon Wyman8da35c52021-10-28 22:45:08 +00001250 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001251 PMBusExpectations expectations;
1252 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001253 // Analyze call will also need good READ_VIN value to check.
1254 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1255 .Times(1)
1256 .WillOnce(Return("202100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001257 psu.analyze();
1258 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001259 // Next return STATUS_WORD with MFR fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001260 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001261 // STATUS_MFR_SPEFIC with bit(s) on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001262 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001263 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1264 {
1265 setPMBusExpectations(mockPMBus, expectations);
1266 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1267 .Times(1)
1268 .WillOnce(Return("202200"));
1269 psu.analyze();
1270 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1271 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001272 // Back to no bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001273 expectations.statusWordValue = 0;
1274 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001275 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1276 .Times(1)
1277 .WillOnce(Return("202300"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001278 psu.analyze();
1279 EXPECT_EQ(psu.hasMFRFault(), false);
1280}
1281
1282TEST_F(PowerSupplyTests, HasVINUVFault)
1283{
1284 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001285
George Liu9464c422023-02-27 14:30:27 +08001286 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68,
1287 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001288 MockedGPIOInterface* mockPresenceGPIO =
1289 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001290 // Always return 1 to indicate present.
1291 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001292 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001293 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001294 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1295 // for INPUT_HISTORY will check max_power_out to see if it is
1296 // old/unsupported power supply. Indicate good value, supported.
1297 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001298 .WillRepeatedly(Return("2000"));
Brandon Wyman82affd92021-11-24 19:12:49 +00001299
1300 // Presence change from missing to present will trigger in1_input read in
1301 // an attempt to get CLEAR_FAULTS called. Return value ignored.
1302 // Zero to non-zero voltage, for missing/present change, triggers clear
1303 // faults call again. Return value ignored.
1304 // Fault (low voltage) to not faulted (voltage in range) triggers clear
1305 // faults call a third time.
1306
Brandon Wyman8da35c52021-10-28 22:45:08 +00001307 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001308 PMBusExpectations expectations;
1309 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001310 // Analyze call will also need good READ_VIN value to check.
1311 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1312 .Times(1)
1313 .WillOnce(Return("201100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001314 psu.analyze();
1315 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001316 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001317 expectations.statusWordValue = (status_word::VIN_UV_FAULT);
Brandon Wyman85c7bf42021-10-19 22:28:48 +00001318 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
1319 // Figure 16, and assume bits on in STATUS_INPUT.
Brandon Wymanb654c612021-11-05 23:24:51 +00001320 expectations.statusInputValue = 0x18;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001321 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1322 {
1323 setPMBusExpectations(mockPMBus, expectations);
1324 // If there is a VIN_UV fault, fake reading voltage of less than 20V
1325 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1326 .Times(1)
1327 .WillOnce(Return("19876"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001328 if (x == DEGLITCH_LIMIT)
1329 {
1330 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1331 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001332 psu.analyze();
1333 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1334 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001335 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001336 expectations.statusWordValue = 0;
1337 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001338 // Updates now result in clearing faults if read voltage goes from below the
1339 // minimum, to within a valid range.
1340 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1341 .Times(1)
1342 .WillOnce(Return("201300"));
Brandon Wyman3225a452022-03-18 18:51:49 +00001343 // Went from below minimum to within range, expect clearVinUVFault().
1344 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
1345 .Times(1)
1346 .WillOnce(Return(1));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001347 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001348 psu.analyze();
1349 EXPECT_EQ(psu.hasVINUVFault(), false);
1350}
Brandon Wyman6710ba22021-10-27 17:39:31 +00001351
1352TEST_F(PowerSupplyTests, HasVoutOVFault)
1353{
1354 auto bus = sdbusplus::bus::new_default();
1355
George Liu9464c422023-02-27 14:30:27 +08001356 PowerSupply psu{bus, PSUInventoryPath, 3, 0x69,
1357 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman6710ba22021-10-27 17:39:31 +00001358 MockedGPIOInterface* mockPresenceGPIO =
1359 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1360 // Always return 1 to indicate present.
1361 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001362 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001363 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001364 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1365 // for INPUT_HISTORY will check max_power_out to see if it is
1366 // old/unsupported power supply. Indicate good value, supported.
1367 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001368 .WillRepeatedly(Return("2000"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001369 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001370 PMBusExpectations expectations;
1371 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001372 // Call to analyze will trigger read of "in1_input" to check voltage.
1373 // Initial value would be 0, so this read updates it to non-zero.
1374 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1375 .Times(1)
1376 .WillOnce(Return("202100"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001377 psu.analyze();
1378 EXPECT_EQ(psu.hasVoutOVFault(), false);
1379 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001380 expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
Brandon Wyman6710ba22021-10-27 17:39:31 +00001381 // STATUS_VOUT fault bit(s)
Brandon Wymanb654c612021-11-05 23:24:51 +00001382 expectations.statusVOUTValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001383 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1384 {
1385 setPMBusExpectations(mockPMBus, expectations);
1386 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1387 .Times(1)
1388 .WillOnce(Return("202200"));
1389 psu.analyze();
1390 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1391 }
Brandon Wyman6710ba22021-10-27 17:39:31 +00001392 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001393 expectations.statusWordValue = 0;
1394 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001395 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1396 .Times(1)
1397 .WillOnce(Return("202300"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001398 psu.analyze();
1399 EXPECT_EQ(psu.hasVoutOVFault(), false);
1400}
Brandon Wyman96893a42021-11-05 19:56:57 +00001401
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001402TEST_F(PowerSupplyTests, HasIoutOCFault)
1403{
1404 auto bus = sdbusplus::bus::new_default();
1405
George Liu9464c422023-02-27 14:30:27 +08001406 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d,
1407 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001408 MockedGPIOInterface* mockPresenceGPIO =
1409 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1410 // Always return 1 to indicate present.
1411 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001412 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001413 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001414 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1415 // for INPUT_HISTORY will check max_power_out to see if it is
1416 // old/unsupported power supply. Indicate good value, supported.
1417 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001418 .WillRepeatedly(Return("2000"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001419 // STATUS_WORD 0x0000 is powered on, no faults.
1420 PMBusExpectations expectations;
1421 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001422 // Call to analyze will trigger read of "in1_input" to check voltage.
1423 // Initial value would be 0, so this read updates it to non-zero.
1424 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1425 .Times(1)
1426 .WillOnce(Return("203100"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001427 psu.analyze();
1428 EXPECT_EQ(psu.hasIoutOCFault(), false);
1429 // Turn fault on.
1430 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1431 // STATUS_IOUT fault bit(s)
1432 expectations.statusIOUTValue = 0x88;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001433 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1434 {
1435 setPMBusExpectations(mockPMBus, expectations);
1436 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1437 .Times(1)
1438 .WillOnce(Return("203200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001439 if (x == DEGLITCH_LIMIT)
1440 {
1441 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1442 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001443 psu.analyze();
1444 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1445 }
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001446 // Back to no fault bits on in STATUS_WORD
1447 expectations.statusWordValue = 0;
1448 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001449 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1450 .Times(1)
1451 .WillOnce(Return("203300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001452 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001453 psu.analyze();
1454 EXPECT_EQ(psu.hasIoutOCFault(), false);
1455}
1456
Brandon Wyman2cf46942021-10-28 19:09:16 +00001457TEST_F(PowerSupplyTests, HasVoutUVFault)
1458{
1459 auto bus = sdbusplus::bus::new_default();
1460
George Liu9464c422023-02-27 14:30:27 +08001461 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a,
1462 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman2cf46942021-10-28 19:09:16 +00001463 MockedGPIOInterface* mockPresenceGPIO =
1464 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1465 // Always return 1 to indicate present.
1466 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001467 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001468 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001469 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1470 // for INPUT_HISTORY will check max_power_out to see if it is
1471 // old/unsupported power supply. Indicate good value, supported.
1472 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001473 .WillRepeatedly(Return("2000"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001474 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wyman2cf46942021-10-28 19:09:16 +00001475 PMBusExpectations expectations;
1476 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001477 // Call to analyze will trigger read of "in1_input" to check voltage.
1478 // Initial value would be 0, so this read updates it to non-zero.
1479 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1480 .Times(1)
1481 .WillOnce(Return("204100"));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001482 psu.analyze();
1483 EXPECT_EQ(psu.hasVoutUVFault(), false);
1484 // Turn fault on.
1485 expectations.statusWordValue = (status_word::VOUT_FAULT);
1486 // STATUS_VOUT fault bit(s)
1487 expectations.statusVOUTValue = 0x30;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001488 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1489 {
1490 setPMBusExpectations(mockPMBus, expectations);
1491 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1492 .Times(1)
1493 .WillOnce(Return("204200"));
1494 psu.analyze();
1495 EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1496 }
Brandon Wyman2cf46942021-10-28 19:09:16 +00001497 // Back to no fault bits on in STATUS_WORD
1498 expectations.statusWordValue = 0;
1499 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001500 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1501 .Times(1)
1502 .WillOnce(Return("204300"));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001503 psu.analyze();
1504 EXPECT_EQ(psu.hasVoutUVFault(), false);
1505}
1506
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001507TEST_F(PowerSupplyTests, HasFanFault)
1508{
1509 auto bus = sdbusplus::bus::new_default();
1510
Matt Spinler0975eaf2022-02-14 15:38:30 -06001511 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
1512 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
1513
George Liu9464c422023-02-27 14:30:27 +08001514 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d,
1515 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001516 MockedGPIOInterface* mockPresenceGPIO =
1517 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1518 // Always return 1 to indicate present.
1519 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001520 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001521 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001522 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1523 // for INPUT_HISTORY will check max_power_out to see if it is
1524 // old/unsupported power supply. Indicate good value, supported.
1525 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001526 .WillRepeatedly(Return("2000"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001527 // STATUS_WORD 0x0000 is powered on, no faults.
1528 PMBusExpectations expectations;
1529 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001530 // Call to analyze will trigger read of "in1_input" to check voltage.
1531 // Initial value would be 0, so this read updates it to non-zero.
1532 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1533 .Times(1)
1534 .WillOnce(Return("205100"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001535 psu.analyze();
1536 EXPECT_EQ(psu.hasFanFault(), false);
1537 // Turn fault on.
1538 expectations.statusWordValue = (status_word::FAN_FAULT);
1539 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
1540 expectations.statusFans12Value = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001541 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1542 {
1543 setPMBusExpectations(mockPMBus, expectations);
1544 // Call to analyze will trigger read of "in1_input" to check voltage.
1545 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1546 .Times(1)
1547 .WillOnce(Return("205200"));
1548 psu.analyze();
1549 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1550 }
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001551 // Back to no fault bits on in STATUS_WORD
1552 expectations.statusWordValue = 0;
1553 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001554 // Call to analyze will trigger read of "in1_input" to check voltage.
1555 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1556 .Times(1)
1557 .WillOnce(Return("205300"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001558 psu.analyze();
1559 EXPECT_EQ(psu.hasFanFault(), false);
1560}
1561
Brandon Wyman96893a42021-11-05 19:56:57 +00001562TEST_F(PowerSupplyTests, HasTempFault)
1563{
1564 auto bus = sdbusplus::bus::new_default();
1565
Matt Spinler0975eaf2022-02-14 15:38:30 -06001566 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
1567 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
1568
George Liu9464c422023-02-27 14:30:27 +08001569 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a,
1570 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman96893a42021-11-05 19:56:57 +00001571 MockedGPIOInterface* mockPresenceGPIO =
1572 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1573 // Always return 1 to indicate present.
1574 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman96893a42021-11-05 19:56:57 +00001575 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001576 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001577 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1578 // for INPUT_HISTORY will check max_power_out to see if it is
1579 // old/unsupported power supply. Indicate good value, supported.
1580 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001581 .WillRepeatedly(Return("2000"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001582 // STATUS_WORD 0x0000 is powered on, no faults.
1583 PMBusExpectations expectations;
1584 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001585 // Call to analyze will trigger read of "in1_input" to check voltage.
1586 // Initial value would be 0, so this read updates it to non-zero.
1587 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1588 .Times(1)
1589 .WillOnce(Return("206100"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001590 psu.analyze();
1591 EXPECT_EQ(psu.hasTempFault(), false);
1592 // Turn fault on.
1593 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
1594 // STATUS_TEMPERATURE fault bit on (OT Fault)
1595 expectations.statusTempValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001596 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1597 {
1598 setPMBusExpectations(mockPMBus, expectations);
1599 // Call to analyze will trigger read of "in1_input" to check voltage.
1600 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1601 .Times(1)
1602 .WillOnce(Return("206200"));
1603 psu.analyze();
1604 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1605 }
Brandon Wyman96893a42021-11-05 19:56:57 +00001606 // Back to no fault bits on in STATUS_WORD
1607 expectations.statusWordValue = 0;
1608 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001609 // Call to analyze will trigger read of "in1_input" to check voltage.
1610 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1611 .Times(1)
1612 .WillOnce(Return("206300"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001613 psu.analyze();
1614 EXPECT_EQ(psu.hasTempFault(), false);
1615}
Brandon Wyman2916ea52021-11-06 03:31:18 +00001616
1617TEST_F(PowerSupplyTests, HasPgoodFault)
1618{
1619 auto bus = sdbusplus::bus::new_default();
1620
George Liu9464c422023-02-27 14:30:27 +08001621 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b,
1622 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman2916ea52021-11-06 03:31:18 +00001623 MockedGPIOInterface* mockPresenceGPIO =
1624 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1625 // Always return 1 to indicate present.
1626 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001627 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001628 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001629 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1630 // for INPUT_HISTORY will check max_power_out to see if it is
1631 // old/unsupported power supply. Indicate good value, supported.
1632 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001633 .WillRepeatedly(Return("2000"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001634 // STATUS_WORD 0x0000 is powered on, no faults.
1635 PMBusExpectations expectations;
1636 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001637 // Call to analyze will trigger read of "in1_input" to check voltage.
1638 // Initial value would be 0, so this read updates it to non-zero.
1639 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1640 .Times(1)
1641 .WillOnce(Return("207100"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001642 psu.analyze();
1643 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman391a0692021-12-08 23:28:18 +00001644 // Setup another expectation of no faults.
1645 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001646 // Call to analyze will trigger read of "in1_input" to check voltage.
1647 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1648 .Times(1)
1649 .WillOnce(Return("207200"));
1650 psu.analyze();
1651 EXPECT_EQ(psu.hasPgoodFault(), false);
1652 // Setup another expectation of no faults.
1653 setPMBusExpectations(mockPMBus, expectations);
1654 // Call to analyze will trigger read of "in1_input" to check voltage.
1655 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1656 .Times(1)
1657 .WillOnce(Return("207300"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001658 psu.analyze();
1659 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +00001660 // Turn PGOOD# off (fault on).
1661 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
1662 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001663 // Call to analyze will trigger read of "in1_input" to check voltage.
1664 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1665 .Times(1)
1666 .WillOnce(Return("207400"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001667 psu.analyze();
Brandon Wyman6d469fd2022-06-15 16:58:21 +00001668 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 1
Brandon Wyman06ca4592021-12-06 22:52:23 +00001669 EXPECT_EQ(psu.hasPgoodFault(), false);
1670 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001671 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1672 .Times(1)
1673 .WillOnce(Return("207500"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001674 psu.analyze();
Brandon Wyman6d469fd2022-06-15 16:58:21 +00001675 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 2
Brandon Wyman06ca4592021-12-06 22:52:23 +00001676 EXPECT_EQ(psu.hasPgoodFault(), false);
1677 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001678 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1679 .Times(1)
1680 .WillOnce(Return("207600"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001681 psu.analyze();
Brandon Wyman6d469fd2022-06-15 16:58:21 +00001682 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 3
1683 EXPECT_EQ(psu.hasPgoodFault(), false);
1684 setPMBusExpectations(mockPMBus, expectations);
1685 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1686 .Times(1)
1687 .WillOnce(Return("207700"));
1688 psu.analyze();
1689 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 4
1690 EXPECT_EQ(psu.hasPgoodFault(), false);
1691 setPMBusExpectations(mockPMBus, expectations);
1692 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1693 .Times(1)
1694 .WillOnce(Return("207800"));
1695 psu.analyze();
1696 // Expect true. PGOOD_DEGLITCH_LIMIT @ 5
Brandon Wyman2916ea52021-11-06 03:31:18 +00001697 EXPECT_EQ(psu.hasPgoodFault(), true);
1698 // Back to no fault bits on in STATUS_WORD
1699 expectations.statusWordValue = 0;
1700 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001701 // 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("207700"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001705 psu.analyze();
1706 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman82affd92021-11-24 19:12:49 +00001707
Brandon Wyman2916ea52021-11-06 03:31:18 +00001708 // Turn OFF bit on
1709 expectations.statusWordValue = (status_word::UNIT_IS_OFF);
1710 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001711 // Call to analyze will trigger read of "in1_input" to check voltage.
1712 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1713 .Times(1)
1714 .WillOnce(Return("208100"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001715 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001716 EXPECT_EQ(psu.hasPgoodFault(), false);
1717 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001718 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1719 .Times(1)
1720 .WillOnce(Return("208200"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001721 psu.analyze();
1722 EXPECT_EQ(psu.hasPgoodFault(), false);
1723 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001724 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1725 .Times(1)
1726 .WillOnce(Return("208300"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001727 psu.analyze();
Brandon Wyman6d469fd2022-06-15 16:58:21 +00001728 EXPECT_EQ(psu.hasPgoodFault(), false);
1729 setPMBusExpectations(mockPMBus, expectations);
1730 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1731 .Times(1)
1732 .WillOnce(Return("208400"));
1733 psu.analyze();
1734 EXPECT_EQ(psu.hasPgoodFault(), false);
1735 setPMBusExpectations(mockPMBus, expectations);
1736 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1737 .Times(1)
1738 .WillOnce(Return("208500"));
1739 psu.analyze();
Brandon Wyman2916ea52021-11-06 03:31:18 +00001740 EXPECT_EQ(psu.hasPgoodFault(), true);
1741 // Back to no fault bits on in STATUS_WORD
1742 expectations.statusWordValue = 0;
1743 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001744 // Call to analyze will trigger read of "in1_input" to check voltage.
1745 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1746 .Times(1)
Brandon Wyman6d469fd2022-06-15 16:58:21 +00001747 .WillOnce(Return("208000"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001748 psu.analyze();
1749 EXPECT_EQ(psu.hasPgoodFault(), false);
1750}
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001751
1752TEST_F(PowerSupplyTests, HasPSKillFault)
1753{
1754 auto bus = sdbusplus::bus::new_default();
George Liu9464c422023-02-27 14:30:27 +08001755 PowerSupply psu{bus, PSUInventoryPath, 4, 0x6d,
1756 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001757 MockedGPIOInterface* mockPresenceGPIO =
1758 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1759 // Always return 1 to indicate present.
1760 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001761 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001762 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001763 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1764 // for INPUT_HISTORY will check max_power_out to see if it is
1765 // old/unsupported power supply. Indicate good value, supported.
1766 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001767 .WillRepeatedly(Return("2000"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001768 // STATUS_WORD 0x0000 is powered on, no faults.
1769 PMBusExpectations expectations;
1770 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001771 // Call to analyze will trigger read of "in1_input" to check voltage.
1772 // Initial value would be 0, so this read updates it to non-zero.
1773 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1774 .Times(1)
1775 .WillOnce(Return("208100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001776 psu.analyze();
1777 EXPECT_EQ(psu.hasPSKillFault(), false);
1778 // Next return STATUS_WORD with MFR fault bit on.
1779 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1780 // STATUS_MFR_SPEFIC with bit(s) on.
1781 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001782
1783 // Deglitching faults, false until read the fault bits on up to the limit.
1784 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1785 {
1786 setPMBusExpectations(mockPMBus, expectations);
1787 // Call to analyze will trigger read of "in1_input" to check voltage.
1788 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1789 .Times(1)
1790 .WillOnce(Return("208200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001791 if (x == DEGLITCH_LIMIT)
1792 {
1793 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1794 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001795 psu.analyze();
1796 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1797 }
1798
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001799 // Back to no bits on in STATUS_WORD
1800 expectations.statusWordValue = 0;
1801 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001802 // Call to analyze will trigger read of "in1_input" to check voltage.
1803 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1804 .Times(1)
1805 .WillOnce(Return("208300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001806 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001807 psu.analyze();
1808 EXPECT_EQ(psu.hasPSKillFault(), false);
1809 // Next return STATUS_WORD with MFR fault bit on.
1810 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1811 // STATUS_MFR_SPEFIC with bit 4 on.
1812 expectations.statusMFRValue = 0x10;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001813
1814 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1815 {
1816 setPMBusExpectations(mockPMBus, expectations);
1817 // Call to analyze will trigger read of "in1_input" to check voltage.
1818 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1819 .Times(1)
1820 .WillOnce(Return("208400"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001821 if (x == DEGLITCH_LIMIT)
1822 {
1823 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1824 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001825 psu.analyze();
1826 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1827 }
1828
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001829 // Back to no bits on in STATUS_WORD
1830 expectations.statusWordValue = 0;
1831 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001832 // Call to analyze will trigger read of "in1_input" to check voltage.
1833 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1834 .Times(1)
1835 .WillOnce(Return("208500"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001836 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001837 psu.analyze();
1838 EXPECT_EQ(psu.hasPSKillFault(), false);
1839}
1840
1841TEST_F(PowerSupplyTests, HasPS12VcsFault)
1842{
1843 auto bus = sdbusplus::bus::new_default();
George Liu9464c422023-02-27 14:30:27 +08001844 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6e,
1845 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001846 MockedGPIOInterface* mockPresenceGPIO =
1847 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1848 // Always return 1 to indicate present.
1849 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001850 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001851 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001852 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1853 // for INPUT_HISTORY will check max_power_out to see if it is
1854 // old/unsupported power supply. Indicate good value, supported.
1855 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001856 .WillRepeatedly(Return("2000"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001857 // STATUS_WORD 0x0000 is powered on, no faults.
1858 PMBusExpectations expectations;
1859 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001860 // Call to analyze will trigger read of "in1_input" to check voltage.
1861 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1862 .Times(1)
1863 .WillOnce(Return("209100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001864 psu.analyze();
1865 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1866 // Next return STATUS_WORD with MFR fault bit on.
1867 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1868 // STATUS_MFR_SPEFIC with bit(s) on.
1869 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001870
1871 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1872 {
1873 setPMBusExpectations(mockPMBus, expectations);
1874 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1875 .Times(1)
1876 .WillOnce(Return("209200"));
1877 psu.analyze();
1878 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1879 }
1880
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001881 // Back to no bits on in STATUS_WORD
1882 expectations.statusWordValue = 0;
1883 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001884 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1885 .Times(1)
1886 .WillOnce(Return("209300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001887 psu.analyze();
1888 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1889 // Next return STATUS_WORD with MFR fault bit on.
1890 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1891 // STATUS_MFR_SPEFIC with bit 6 on.
1892 expectations.statusMFRValue = 0x40;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001893
1894 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1895 {
1896 setPMBusExpectations(mockPMBus, expectations);
1897 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1898 .Times(1)
1899 .WillOnce(Return("209400"));
1900 psu.analyze();
1901 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1902 }
1903
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001904 // Back to no bits on in STATUS_WORD
1905 expectations.statusWordValue = 0;
1906 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001907 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1908 .Times(1)
1909 .WillOnce(Return("209500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001910 psu.analyze();
1911 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1912}
1913
1914TEST_F(PowerSupplyTests, HasPSCS12VFault)
1915{
1916 auto bus = sdbusplus::bus::new_default();
George Liu9464c422023-02-27 14:30:27 +08001917 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f,
1918 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001919 MockedGPIOInterface* mockPresenceGPIO =
1920 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1921 // Always return 1 to indicate present.
1922 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001923 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001924 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001925 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1926 // for INPUT_HISTORY will check max_power_out to see if it is
1927 // old/unsupported power supply. Indicate good value, supported.
1928 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001929 .WillRepeatedly(Return("2000"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001930 // STATUS_WORD 0x0000 is powered on, no faults.
1931 PMBusExpectations expectations;
1932 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001933 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1934 .Times(1)
1935 .WillOnce(Return("209100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001936 psu.analyze();
1937 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1938 // Next return STATUS_WORD with MFR fault bit on.
1939 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1940 // STATUS_MFR_SPEFIC with bit(s) on.
1941 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001942
1943 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1944 {
1945 setPMBusExpectations(mockPMBus, expectations);
1946 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1947 .Times(1)
1948 .WillOnce(Return("209200"));
1949 psu.analyze();
1950 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1951 }
1952
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001953 // Back to no bits on in STATUS_WORD
1954 expectations.statusWordValue = 0;
1955 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001956 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1957 .Times(1)
1958 .WillOnce(Return("209300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001959 psu.analyze();
1960 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1961 // Next return STATUS_WORD with MFR fault bit on.
1962 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1963 // STATUS_MFR_SPEFIC with bit 7 on.
1964 expectations.statusMFRValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001965
1966 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1967 {
1968 setPMBusExpectations(mockPMBus, expectations);
1969 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1970 .Times(1)
1971 .WillOnce(Return("209400"));
1972 psu.analyze();
1973 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1974 }
1975
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001976 // Back to no bits on in STATUS_WORD
1977 expectations.statusWordValue = 0;
1978 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001979 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1980 .Times(1)
1981 .WillOnce(Return("209500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001982 psu.analyze();
1983 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1984}
Brandon Wymanc3324422022-03-24 20:30:57 +00001985
Matt Spinler592bd272023-08-30 11:00:01 -05001986TEST_F(PowerSupplyTests, PeakInputPowerSensor)
Brandon Wymanc3324422022-03-24 20:30:57 +00001987{
1988 auto bus = sdbusplus::bus::new_default();
1989 {
George Liu9464c422023-02-27 14:30:27 +08001990 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f,
1991 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Matt Spinler592bd272023-08-30 11:00:01 -05001992 EXPECT_EQ(psu.getPeakInputPower(), std::nullopt);
1993
Brandon Wymanc3324422022-03-24 20:30:57 +00001994 MockedGPIOInterface* mockPresenceGPIO =
1995 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wymanae35ac52022-05-23 22:33:40 +00001996 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wymanc3324422022-03-24 20:30:57 +00001997 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Matt Spinler592bd272023-08-30 11:00:01 -05001998
Brandon Wymanae35ac52022-05-23 22:33:40 +00001999 setMissingToPresentExpects(mockPMBus, mockedUtil);
2000 PMBusExpectations expectations;
2001 setPMBusExpectations(mockPMBus, expectations);
Matt Spinler592bd272023-08-30 11:00:01 -05002002
Brandon Wymanae35ac52022-05-23 22:33:40 +00002003 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2004 .Times(1)
2005 .WillOnce(Return("206000"));
Brandon Wymanae35ac52022-05-23 22:33:40 +00002006 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Brandon Wymanae35ac52022-05-23 22:33:40 +00002007 .WillRepeatedly(Return("2000"));
Matt Spinler592bd272023-08-30 11:00:01 -05002008
Brandon Wymanc3324422022-03-24 20:30:57 +00002009 psu.analyze();
Matt Spinler592bd272023-08-30 11:00:01 -05002010 EXPECT_EQ(psu.getPeakInputPower().value_or(0), 213);
Brandon Wymanc3324422022-03-24 20:30:57 +00002011 }
Matt Spinler592bd272023-08-30 11:00:01 -05002012
2013 // Test that there is no peak power sensor on 1400W PSs
Brandon Wymanc3324422022-03-24 20:30:57 +00002014 {
George Liu9464c422023-02-27 14:30:27 +08002015 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68,
2016 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wymanae35ac52022-05-23 22:33:40 +00002017 MockedGPIOInterface* mockPresenceGPIO =
2018 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2019 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Matt Spinler592bd272023-08-30 11:00:01 -05002020
Brandon Wymanae35ac52022-05-23 22:33:40 +00002021 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Matt Spinler592bd272023-08-30 11:00:01 -05002022
Brandon Wymanae35ac52022-05-23 22:33:40 +00002023 setMissingToPresentExpects(mockPMBus, mockedUtil);
Matt Spinler592bd272023-08-30 11:00:01 -05002024
Brandon Wymanae35ac52022-05-23 22:33:40 +00002025 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Brandon Wymanae35ac52022-05-23 22:33:40 +00002026 .WillRepeatedly(Return("30725"));
Matt Spinler592bd272023-08-30 11:00:01 -05002027
Brandon Wymanae35ac52022-05-23 22:33:40 +00002028 PMBusExpectations expectations;
2029 setPMBusExpectations(mockPMBus, expectations);
Matt Spinler592bd272023-08-30 11:00:01 -05002030
Brandon Wymanae35ac52022-05-23 22:33:40 +00002031 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
Matt Spinler592bd272023-08-30 11:00:01 -05002032 .WillRepeatedly(Return("206000"));
Brandon Wymanae35ac52022-05-23 22:33:40 +00002033 psu.analyze();
Matt Spinler592bd272023-08-30 11:00:01 -05002034
2035 EXPECT_EQ(psu.getPeakInputPower(), std::nullopt);
Brandon Wymanae35ac52022-05-23 22:33:40 +00002036 }
Matt Spinler592bd272023-08-30 11:00:01 -05002037
2038 // Test that IPSPS power supplies don't have peak power
Brandon Wymanae35ac52022-05-23 22:33:40 +00002039 {
George Liu9464c422023-02-27 14:30:27 +08002040 PowerSupply psu{bus, PSUInventoryPath, 11,
2041 0x58, "inspur-ipsps", PSUGPIOLineName,
2042 isPowerOn};
Matt Spinler592bd272023-08-30 11:00:01 -05002043
Brandon Wymanc3324422022-03-24 20:30:57 +00002044 MockedGPIOInterface* mockPresenceGPIO =
2045 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Matt Spinler592bd272023-08-30 11:00:01 -05002046
Brandon Wymanae35ac52022-05-23 22:33:40 +00002047 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Matt Spinler592bd272023-08-30 11:00:01 -05002048
Brandon Wymanc3324422022-03-24 20:30:57 +00002049 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Matt Spinler592bd272023-08-30 11:00:01 -05002050
Brandon Wymanae35ac52022-05-23 22:33:40 +00002051 setMissingToPresentExpects(mockPMBus, mockedUtil);
2052 PMBusExpectations expectations;
2053 setPMBusExpectations(mockPMBus, expectations);
Matt Spinler592bd272023-08-30 11:00:01 -05002054
2055 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2056 .WillRepeatedly(Return("206000"));
2057
2058 psu.analyze();
2059
2060 EXPECT_EQ(psu.getPeakInputPower(), std::nullopt);
2061 }
2062
2063 // Test that a bad response from the input_history command leads
2064 // to an NaN value.
2065 {
2066 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f,
2067 "ibm-cffps", PSUGPIOLineName, isPowerOn};
2068
2069 MockedGPIOInterface* mockPresenceGPIO =
2070 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2071 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2072
2073 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2074
2075 setMissingToPresentExpects(mockPMBus, mockedUtil);
2076 PMBusExpectations expectations;
2077 setPMBusExpectations(mockPMBus, expectations);
2078
Brandon Wymanae35ac52022-05-23 22:33:40 +00002079 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2080 .Times(1)
2081 .WillOnce(Return("206000"));
Matt Spinler592bd272023-08-30 11:00:01 -05002082 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2083 .WillRepeatedly(Return("2000"));
Brandon Wymanc3324422022-03-24 20:30:57 +00002084
Matt Spinler592bd272023-08-30 11:00:01 -05002085 // Don't return the full 5 bytes.
2086 EXPECT_CALL(mockPMBus,
2087 readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug, 5))
2088 .WillRepeatedly(Return(std::vector<uint8_t>{0x01, 0x5c}));
2089
2090 psu.analyze();
2091 EXPECT_THAT(psu.getPeakInputPower().value_or(0), IsNan());
2092 }
Brandon Wymanc3324422022-03-24 20:30:57 +00002093}
Brandon Wyman18a24d92022-04-19 22:48:34 +00002094
2095TEST_F(PowerSupplyTests, IsSyncHistoryRequired)
2096{
2097 auto bus = sdbusplus::bus::new_default();
George Liu9464c422023-02-27 14:30:27 +08002098 PowerSupply psu{bus, PSUInventoryPath, 8, 0x6f,
2099 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman18a24d92022-04-19 22:48:34 +00002100 EXPECT_EQ(psu.isSyncHistoryRequired(), false);
2101 MockedGPIOInterface* mockPresenceGPIO =
2102 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2103 // Always return 1 to indicate present.
2104 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2105 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2106 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00002107 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2108 // for INPUT_HISTORY will check max_power_out to see if it is
2109 // old/unsupported power supply. Indicate good value, supported.
2110 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05002111 .WillRepeatedly(Return("2000"));
Brandon Wyman18a24d92022-04-19 22:48:34 +00002112 PMBusExpectations expectations;
2113 setPMBusExpectations(mockPMBus, expectations);
2114 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2115 .Times(1)
2116 .WillRepeatedly(Return("205000"));
2117 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
2118 psu.analyze();
Brandon Wyman18a24d92022-04-19 22:48:34 +00002119 // Missing -> Present requires history sync
2120 EXPECT_EQ(psu.isSyncHistoryRequired(), true);
2121 psu.clearSyncHistoryRequired();
2122 EXPECT_EQ(psu.isSyncHistoryRequired(), false);
2123}
Matt Spinler592bd272023-08-30 11:00:01 -05002124
2125TEST_F(PowerSupplyTests, TestLinearConversions)
2126{
2127 // Mantissa > 0, exponent = 0
2128 EXPECT_EQ(0, PowerSupply::linearToInteger(0));
2129 EXPECT_EQ(1, PowerSupply::linearToInteger(1));
2130 EXPECT_EQ(38, PowerSupply::linearToInteger(0x26));
2131 EXPECT_EQ(1023, PowerSupply::linearToInteger(0x3FF));
2132
2133 // Mantissa < 0, exponent = 0
2134 EXPECT_EQ(-1, PowerSupply::linearToInteger(0x7FF));
2135 EXPECT_EQ(-20, PowerSupply::linearToInteger(0x7EC));
2136 EXPECT_EQ(-769, PowerSupply::linearToInteger(0x4FF));
2137 EXPECT_EQ(-989, PowerSupply::linearToInteger(0x423));
2138 EXPECT_EQ(-1024, PowerSupply::linearToInteger(0x400));
2139
2140 // Mantissa >= 0, exponent > 0
2141 // M = 1, E = 2
2142 EXPECT_EQ(4, PowerSupply::linearToInteger(0x1001));
2143
2144 // M = 1000, E = 10
2145 EXPECT_EQ(1024000, PowerSupply::linearToInteger(0x53E8));
2146
2147 // M = 10, E = 15
2148 EXPECT_EQ(327680, PowerSupply::linearToInteger(0x780A));
2149
2150 // Mantissa >= 0, exponent < 0
2151 // M = 0, E = -1
2152 EXPECT_EQ(0, PowerSupply::linearToInteger(0xF800));
2153
2154 // M = 100, E = -2
2155 EXPECT_EQ(25, PowerSupply::linearToInteger(0xF064));
2156
2157 // Mantissa < 0, exponent < 0
2158 // M = -100, E = -1
2159 EXPECT_EQ(-50, PowerSupply::linearToInteger(0xFF9C));
2160
2161 // M = -1024, E = -7
2162 EXPECT_EQ(-8, PowerSupply::linearToInteger(0xCC00));
2163}