blob: 278326df49f73147e1eb013bcc6942754dbb734a [file] [log] [blame]
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001#include "../power_supply.hpp"
Brandon Wymanc3324422022-03-24 20:30:57 +00002#include "../record_manager.hpp"
Brandon Wyman3f1242f2020-01-28 13:11:25 -06003#include "mock.hpp"
4
5#include <xyz/openbmc_project/Common/Device/error.hpp>
6#include <xyz/openbmc_project/Common/error.hpp>
7
8#include <gmock/gmock.h>
9#include <gtest/gtest.h>
10
11using namespace phosphor::power::psu;
12using namespace phosphor::pmbus;
13
14using ::testing::_;
Brandon Wyman59a35792020-06-04 12:37:40 -050015using ::testing::Args;
Brandon Wyman3f1242f2020-01-28 13:11:25 -060016using ::testing::Assign;
17using ::testing::DoAll;
Brandon Wyman59a35792020-06-04 12:37:40 -050018using ::testing::ElementsAre;
19using ::testing::NotNull;
Brandon Wyman3f1242f2020-01-28 13:11:25 -060020using ::testing::Return;
21using ::testing::StrEq;
22
23static auto PSUInventoryPath = "/xyz/bmc/inv/sys/chassis/board/powersupply0";
B. J. Wyman681b2a32021-04-20 22:31:22 +000024static auto PSUGPIOLineName = "presence-ps0";
Brandon Wyman3f1242f2020-01-28 13:11:25 -060025
Brandon Wymanb654c612021-11-05 23:24:51 +000026struct PMBusExpectations
27{
28 uint16_t statusWordValue{0x0000};
29 uint8_t statusInputValue{0x00};
30 uint8_t statusMFRValue{0x00};
31 uint8_t statusCMLValue{0x00};
32 uint8_t statusVOUTValue{0x00};
Brandon Wymanb10b3be2021-11-09 22:12:15 +000033 uint8_t statusIOUTValue{0x00};
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +000034 uint8_t statusFans12Value{0x00};
Brandon Wyman96893a42021-11-05 19:56:57 +000035 uint8_t statusTempValue{0x00};
Brandon Wymanb654c612021-11-05 23:24:51 +000036};
37
Brandon Wyman8da35c52021-10-28 22:45:08 +000038// Helper function to setup expectations for various STATUS_* commands
Brandon Wymanb654c612021-11-05 23:24:51 +000039void setPMBusExpectations(MockedPMBus& mockPMBus,
40 const PMBusExpectations& expectations)
Brandon Wyman8da35c52021-10-28 22:45:08 +000041{
Brandon Wyman32453e92021-12-15 19:00:14 +000042 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000043 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000044 .WillOnce(Return(expectations.statusWordValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000045
Brandon Wymanb654c612021-11-05 23:24:51 +000046 if (expectations.statusWordValue != 0)
Brandon Wyman8da35c52021-10-28 22:45:08 +000047 {
48 // If fault bits are on in STATUS_WORD, there will also be a read of
Brandon Wyman96893a42021-11-05 19:56:57 +000049 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and
50 // STATUS_TEMPERATURE.
Brandon Wyman32453e92021-12-15 19:00:14 +000051 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000052 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000053 .WillOnce(Return(expectations.statusInputValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000054 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000055 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000056 .WillOnce(Return(expectations.statusMFRValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000057 EXPECT_CALL(mockPMBus, read(STATUS_CML, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000058 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000059 .WillOnce(Return(expectations.statusCMLValue));
Brandon Wyman6710ba22021-10-27 17:39:31 +000060 // Page will need to be set to 0 to read STATUS_VOUT.
61 EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0))
62 .Times(1)
63 .WillOnce(Return("status0_vout"));
Brandon Wyman32453e92021-12-15 19:00:14 +000064 EXPECT_CALL(mockPMBus, read("status0_vout", _, _))
Brandon Wyman6710ba22021-10-27 17:39:31 +000065 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000066 .WillOnce(Return(expectations.statusVOUTValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000067 EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _, _))
Brandon Wymanb10b3be2021-11-09 22:12:15 +000068 .Times(1)
69 .WillOnce(Return(expectations.statusIOUTValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000070 EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _, _))
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +000071 .Times(1)
72 .WillOnce(Return(expectations.statusFans12Value));
Brandon Wyman32453e92021-12-15 19:00:14 +000073 EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _, _))
Brandon Wyman96893a42021-11-05 19:56:57 +000074 .Times(1)
75 .WillOnce(Return(expectations.statusTempValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000076 }
77}
78
Brandon Wyman3f1242f2020-01-28 13:11:25 -060079class PowerSupplyTests : public ::testing::Test
80{
81 public:
82 PowerSupplyTests() :
83 mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
84 {
85 ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
86 }
87
88 ~PowerSupplyTests() override
89 {
90 freeUtils();
91 }
92
93 const MockedUtil& mockedUtil;
94};
95
Brandon Wyman391a0692021-12-08 23:28:18 +000096// Helper function for when a power supply goes from missing to present.
97void setMissingToPresentExpects(MockedPMBus& pmbus, const MockedUtil& util)
98{
99 // Call to analyze() will update to present, that will trigger updating
100 // to the correct/latest HWMON directory, in case it changes.
101 EXPECT_CALL(pmbus, findHwmonDir());
102 // Presence change from missing to present will trigger write to
103 // ON_OFF_CONFIG.
104 EXPECT_CALL(pmbus, writeBinary(ON_OFF_CONFIG, _, _));
105 // Presence change from missing to present will trigger in1_input read
106 // in an attempt to get CLEAR_FAULTS called.
Brandon Wyman82affd92021-11-24 19:12:49 +0000107 // This READ_VIN for CLEAR_FAULTS does not check the returned value.
Brandon Wyman3225a452022-03-18 18:51:49 +0000108 EXPECT_CALL(pmbus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
109 // The call for clearing faults includes clearing VIN_UV fault.
110 // The voltage defaults to 0, the first call to analyze should update the
111 // voltage to the current reading, triggering clearing VIN_UV fault(s)
112 // due to below minimum to within range voltage.
113 EXPECT_CALL(pmbus, read("in1_lcrit_alarm", _, _))
Brandon Wyman82affd92021-11-24 19:12:49 +0000114 .Times(2)
Brandon Wyman3225a452022-03-18 18:51:49 +0000115 .WillRepeatedly(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +0000116 // Missing/present call will update Presence in inventory.
Brandon Wyman391a0692021-12-08 23:28:18 +0000117 EXPECT_CALL(util, setPresence(_, _, true, _));
118}
119
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600120TEST_F(PowerSupplyTests, Constructor)
121{
122 /**
123 * @param[in] invpath - String for inventory path to use
124 * @param[in] i2cbus - The bus number this power supply is on
125 * @param[in] i2caddr - The 16-bit I2C address of the power supply
B. J. Wyman681b2a32021-04-20 22:31:22 +0000126 * @param[in] gpioLineName - The string for the gpio-line-name to read for
127 * presence.
128 * @param[in] bindDelay - Time in milliseconds to delay binding the device
129 * driver after seeing the presence line go active.
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600130 */
131 auto bus = sdbusplus::bus::new_default();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600132
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500133 // Try where inventory path is empty, constructor should fail.
134 try
135 {
Brandon Wymanc3324422022-03-24 20:30:57 +0000136 auto psu = std::make_unique<PowerSupply>(bus, "", 3, 0x68, "ibm-cffps",
137 PSUGPIOLineName);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500138 ADD_FAILURE() << "Should not have reached this line.";
139 }
140 catch (const std::invalid_argument& e)
141 {
142 EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
143 }
144 catch (...)
145 {
146 ADD_FAILURE() << "Should not have caught exception.";
147 }
148
B. J. Wyman681b2a32021-04-20 22:31:22 +0000149 // TODO: Try invalid i2c address?
150
151 // Try where gpioLineName is empty.
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500152 try
153 {
Brandon Wymanc3324422022-03-24 20:30:57 +0000154 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
155 "ibm-cffps", "");
B. J. Wyman681b2a32021-04-20 22:31:22 +0000156 ADD_FAILURE()
157 << "Should not have reached this line. Invalid gpioLineName.";
158 }
159 catch (const std::invalid_argument& e)
160 {
161 EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
162 }
163 catch (...)
164 {
165 ADD_FAILURE() << "Should not have caught exception.";
166 }
167
168 // Test with valid arguments
169 // NOT using D-Bus inventory path for presence.
170 try
171 {
172 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
Brandon Wymanc3324422022-03-24 20:30:57 +0000173 "ibm-cffps", PSUGPIOLineName);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500174
175 EXPECT_EQ(psu->isPresent(), false);
176 EXPECT_EQ(psu->isFaulted(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000177 EXPECT_EQ(psu->hasCommFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500178 EXPECT_EQ(psu->hasInputFault(), false);
179 EXPECT_EQ(psu->hasMFRFault(), false);
180 EXPECT_EQ(psu->hasVINUVFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000181 EXPECT_EQ(psu->hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000182 EXPECT_EQ(psu->hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000183 EXPECT_EQ(psu->hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000184 EXPECT_EQ(psu->hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000185 EXPECT_EQ(psu->hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000186 EXPECT_EQ(psu->hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000187 EXPECT_EQ(psu->hasPSKillFault(), false);
188 EXPECT_EQ(psu->hasPS12VcsFault(), false);
189 EXPECT_EQ(psu->hasPSCS12VFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500190 }
191 catch (...)
192 {
193 ADD_FAILURE() << "Should not have caught exception.";
194 }
B. J. Wyman681b2a32021-04-20 22:31:22 +0000195
196 // Test with valid arguments
197 // TODO: Using D-Bus inventory path for presence.
198 try
199 {
200 // FIXME: How do I get that presenceGPIO.read() in the startup to throw
201 // an exception?
202
203 // EXPECT_CALL(mockedUtil, getPresence(_,
204 // StrEq(PSUInventoryPath)))
205 // .Times(1);
206 }
207 catch (...)
208 {
209 ADD_FAILURE() << "Should not have caught exception.";
210 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600211}
212
213TEST_F(PowerSupplyTests, Analyze)
214{
215 auto bus = sdbusplus::bus::new_default();
216
Brandon Wymanb654c612021-11-05 23:24:51 +0000217 {
218 // If I default to reading the GPIO, I will NOT expect a call to
219 // getPresence().
B. J. Wyman681b2a32021-04-20 22:31:22 +0000220
Brandon Wymanc3324422022-03-24 20:30:57 +0000221 PowerSupply psu{bus, PSUInventoryPath, 4,
222 0x69, "ibm-cffps", PSUGPIOLineName};
Brandon Wymanb654c612021-11-05 23:24:51 +0000223 MockedGPIOInterface* mockPresenceGPIO =
224 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
225 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000226
Brandon Wymanb654c612021-11-05 23:24:51 +0000227 psu.analyze();
228 // By default, nothing should change.
229 EXPECT_EQ(psu.isPresent(), false);
230 EXPECT_EQ(psu.isFaulted(), false);
231 EXPECT_EQ(psu.hasInputFault(), false);
232 EXPECT_EQ(psu.hasMFRFault(), false);
233 EXPECT_EQ(psu.hasVINUVFault(), false);
234 EXPECT_EQ(psu.hasCommFault(), false);
235 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000236 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000237 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000238 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000239 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000240 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000241 EXPECT_EQ(psu.hasPSKillFault(), false);
242 EXPECT_EQ(psu.hasPS12VcsFault(), false);
243 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000244 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600245
Brandon Wymanc3324422022-03-24 20:30:57 +0000246 PowerSupply psu2{bus, PSUInventoryPath, 5,
247 0x6a, "ibm-cffps", PSUGPIOLineName};
B. J. Wyman681b2a32021-04-20 22:31:22 +0000248 // In order to get the various faults tested, the power supply needs to
249 // be present in order to read from the PMBus device(s).
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000250 MockedGPIOInterface* mockPresenceGPIO2 =
251 static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000252 // Always return 1 to indicate present.
253 // Each analyze() call will trigger a read of the presence GPIO.
254 EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000255 EXPECT_EQ(psu2.isPresent(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600256
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600257 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000258 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +0000259 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
260 // for INPUT_HISTORY will check max_power_out to see if it is
261 // old/unsupported power supply. Indicate good value, supported.
262 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
263 .Times(1)
264 .WillOnce(Return("2000"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600265
Brandon Wymanb654c612021-11-05 23:24:51 +0000266 // STATUS_WORD INPUT fault.
267 {
268 // Start with STATUS_WORD 0x0000. Powered on, no faults.
269 // Set expectations for a no fault
270 PMBusExpectations expectations;
271 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000272 // After reading STATUS_WORD, etc., there will be a READ_VIN check.
273 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
274 .Times(1)
275 .WillOnce(Return("206000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000276 psu2.analyze();
277 EXPECT_EQ(psu2.isPresent(), true);
278 EXPECT_EQ(psu2.isFaulted(), false);
279 EXPECT_EQ(psu2.hasInputFault(), false);
280 EXPECT_EQ(psu2.hasMFRFault(), false);
281 EXPECT_EQ(psu2.hasVINUVFault(), false);
282 EXPECT_EQ(psu2.hasCommFault(), false);
283 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000284 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000285 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000286 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000287 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000288 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000289 EXPECT_EQ(psu2.hasPSKillFault(), false);
290 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
291 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000292
293 // Update expectations for STATUS_WORD input fault/warn
Brandon Wyman96893a42021-11-05 19:56:57 +0000294 // STATUS_INPUT fault bits ... on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000295 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wyman3225a452022-03-18 18:51:49 +0000296 // IIN_OC fault.
297 expectations.statusInputValue = 0x04;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000298
299 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
300 {
301 setPMBusExpectations(mockPMBus, expectations);
302 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
303 .Times(1)
304 .WillOnce(Return("207000"));
305 psu2.analyze();
306 EXPECT_EQ(psu2.isPresent(), true);
307 // Should not be faulted until it reaches the deglitch limit.
308 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
309 EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
310 EXPECT_EQ(psu2.hasMFRFault(), false);
311 EXPECT_EQ(psu2.hasVINUVFault(), false);
312 EXPECT_EQ(psu2.hasCommFault(), false);
313 EXPECT_EQ(psu2.hasVoutOVFault(), false);
314 EXPECT_EQ(psu2.hasIoutOCFault(), false);
315 EXPECT_EQ(psu2.hasVoutUVFault(), false);
316 EXPECT_EQ(psu2.hasFanFault(), false);
317 EXPECT_EQ(psu2.hasTempFault(), false);
318 EXPECT_EQ(psu2.hasPgoodFault(), false);
319 EXPECT_EQ(psu2.hasPSKillFault(), false);
320 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
321 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
322 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000323 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600324
Brandon Wyman32453e92021-12-15 19:00:14 +0000325 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000326 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
327 .Times(1)
328 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000329 psu2.clearFaults();
330
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600331 // STATUS_WORD INPUT/UV fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000332 {
333 // First need it to return good status, then the fault
334 PMBusExpectations expectations;
335 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000336 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
337 .Times(1)
338 .WillOnce(Return("208000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000339 psu2.analyze();
Brandon Wymanc2906f42021-12-21 20:14:56 +0000340 EXPECT_EQ(psu2.isFaulted(), false);
341 EXPECT_EQ(psu2.hasInputFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000342 // Now set fault bits in STATUS_WORD
343 expectations.statusWordValue =
344 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
345 // STATUS_INPUT fault bits ... on.
Brandon Wyman3225a452022-03-18 18:51:49 +0000346 expectations.statusInputValue = 0x18;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000347 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
348 {
349 setPMBusExpectations(mockPMBus, expectations);
350 // Input/UV fault, so voltage should read back low.
351 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
352 .Times(1)
353 .WillOnce(Return("19123"));
354 psu2.analyze();
355 EXPECT_EQ(psu2.isPresent(), true);
356 // Only faulted if hit deglitch limit
357 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
358 EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
359 EXPECT_EQ(psu2.hasVINUVFault(), x >= DEGLITCH_LIMIT);
360 EXPECT_EQ(psu2.hasMFRFault(), false);
361 EXPECT_EQ(psu2.hasCommFault(), false);
362 EXPECT_EQ(psu2.hasVoutOVFault(), false);
363 EXPECT_EQ(psu2.hasIoutOCFault(), false);
364 EXPECT_EQ(psu2.hasVoutUVFault(), false);
365 EXPECT_EQ(psu2.hasFanFault(), false);
366 EXPECT_EQ(psu2.hasTempFault(), false);
367 EXPECT_EQ(psu2.hasPgoodFault(), false);
368 EXPECT_EQ(psu2.hasPSKillFault(), false);
369 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
370 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
371 }
Brandon Wyman82affd92021-11-24 19:12:49 +0000372 // Turning VIN_UV fault off causes clearing of faults, causing read of
373 // in1_input as an attempt to get CLEAR_FAULTS called.
374 expectations.statusWordValue = 0;
375 setPMBusExpectations(mockPMBus, expectations);
376 // The call to read the voltage
377 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
378 .Times(1)
379 .WillOnce(Return("209000"));
Brandon Wyman3225a452022-03-18 18:51:49 +0000380 // The call to clear VIN_UV/Off fault(s)
381 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
Brandon Wyman32453e92021-12-15 19:00:14 +0000382 .Times(1)
Brandon Wyman3225a452022-03-18 18:51:49 +0000383 .WillOnce(Return(1));
Brandon Wyman82affd92021-11-24 19:12:49 +0000384 psu2.analyze();
385 // Should remain present, no longer be faulted, no input fault, no
386 // VIN_UV fault. Nothing else should change.
387 EXPECT_EQ(psu2.isPresent(), true);
388 EXPECT_EQ(psu2.isFaulted(), false);
389 EXPECT_EQ(psu2.hasInputFault(), false);
390 EXPECT_EQ(psu2.hasVINUVFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000391 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600392
Brandon Wyman32453e92021-12-15 19:00:14 +0000393 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000394 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
395 .Times(1)
396 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000397 psu2.clearFaults();
398
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600399 // STATUS_WORD MFR fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000400 {
401 // First need it to return good status, then the fault
402 PMBusExpectations expectations;
403 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000404 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
405 .Times(1)
406 .WillOnce(Return("210000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000407 psu2.analyze();
408 // Now STATUS_WORD with MFR fault bit on.
409 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
410 // STATUS_MFR bits on.
411 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000412
413 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
414 {
415 setPMBusExpectations(mockPMBus, expectations);
416 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
417 .Times(1)
418 .WillOnce(Return("211000"));
419 psu2.analyze();
420 EXPECT_EQ(psu2.isPresent(), true);
421 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
422 EXPECT_EQ(psu2.hasInputFault(), false);
423 EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT);
424 EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT);
425 EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
426 EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
427 EXPECT_EQ(psu2.hasVINUVFault(), false);
428 EXPECT_EQ(psu2.hasCommFault(), false);
429 EXPECT_EQ(psu2.hasVoutOVFault(), false);
430 EXPECT_EQ(psu2.hasIoutOCFault(), false);
431 EXPECT_EQ(psu2.hasVoutUVFault(), false);
432 EXPECT_EQ(psu2.hasFanFault(), false);
433 EXPECT_EQ(psu2.hasTempFault(), false);
434 EXPECT_EQ(psu2.hasPgoodFault(), false);
435 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000436 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600437
Brandon Wyman32453e92021-12-15 19:00:14 +0000438 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000439 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
440 .Times(1)
441 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000442 psu2.clearFaults();
Brandon Wyman3225a452022-03-18 18:51:49 +0000443
Brandon Wyman96893a42021-11-05 19:56:57 +0000444 // Temperature fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000445 {
446 // First STATUS_WORD with no bits set, then with temperature fault.
447 PMBusExpectations expectations;
448 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000449 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
450 .Times(1)
451 .WillOnce(Return("212000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000452 psu2.analyze();
453 // STATUS_WORD with temperature fault bit on.
454 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
Brandon Wyman96893a42021-11-05 19:56:57 +0000455 // STATUS_TEMPERATURE with fault bit(s) on.
456 expectations.statusTempValue = 0x10;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000457 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
458 {
459 setPMBusExpectations(mockPMBus, expectations);
460 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
461 .Times(1)
462 .WillOnce(Return("213000"));
463 psu2.analyze();
464 EXPECT_EQ(psu2.isPresent(), true);
465 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
466 EXPECT_EQ(psu2.hasInputFault(), false);
467 EXPECT_EQ(psu2.hasMFRFault(), false);
468 EXPECT_EQ(psu2.hasVINUVFault(), false);
469 EXPECT_EQ(psu2.hasCommFault(), false);
470 EXPECT_EQ(psu2.hasVoutOVFault(), false);
471 EXPECT_EQ(psu2.hasIoutOCFault(), false);
472 EXPECT_EQ(psu2.hasVoutUVFault(), false);
473 EXPECT_EQ(psu2.hasFanFault(), false);
474 EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT);
475 EXPECT_EQ(psu2.hasPgoodFault(), false);
476 EXPECT_EQ(psu2.hasPSKillFault(), false);
477 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
478 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
479 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000480 }
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000481
Brandon Wyman32453e92021-12-15 19:00:14 +0000482 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000483 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
484 .Times(1)
485 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000486 psu2.clearFaults();
Brandon Wyman3225a452022-03-18 18:51:49 +0000487
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000488 // CML fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000489 {
490 // First STATUS_WORD wit no bits set, then with CML fault.
491 PMBusExpectations expectations;
492 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000493 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
494 .Times(1)
495 .WillOnce(Return("214000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000496 psu2.analyze();
497 // STATUS_WORD with CML fault bit on.
498 expectations.statusWordValue = (status_word::CML_FAULT);
499 // Turn on STATUS_CML fault bit(s)
500 expectations.statusCMLValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000501 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
502 {
503 setPMBusExpectations(mockPMBus, expectations);
504 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
505 .Times(1)
506 .WillOnce(Return("215000"));
507 psu2.analyze();
508 EXPECT_EQ(psu2.isPresent(), true);
509 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
510 EXPECT_EQ(psu2.hasCommFault(), x >= DEGLITCH_LIMIT);
511 EXPECT_EQ(psu2.hasInputFault(), false);
512 EXPECT_EQ(psu2.hasMFRFault(), false);
513 EXPECT_EQ(psu2.hasVINUVFault(), false);
514 EXPECT_EQ(psu2.hasVoutOVFault(), false);
515 EXPECT_EQ(psu2.hasIoutOCFault(), false);
516 EXPECT_EQ(psu2.hasVoutUVFault(), false);
517 EXPECT_EQ(psu2.hasFanFault(), false);
518 EXPECT_EQ(psu2.hasTempFault(), false);
519 EXPECT_EQ(psu2.hasPgoodFault(), false);
520 EXPECT_EQ(psu2.hasPSKillFault(), false);
521 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
522 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
523 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000524 }
Brandon Wyman6710ba22021-10-27 17:39:31 +0000525
Brandon Wyman32453e92021-12-15 19:00:14 +0000526 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000527 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
528 .Times(1)
529 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000530 psu2.clearFaults();
Brandon Wyman3225a452022-03-18 18:51:49 +0000531
Brandon Wyman6710ba22021-10-27 17:39:31 +0000532 // VOUT_OV_FAULT fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000533 {
534 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
535 PMBusExpectations expectations;
536 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000537 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
538 .Times(1)
539 .WillOnce(Return("216000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000540 psu2.analyze();
541 // STATUS_WORD with VOUT/VOUT_OV fault.
542 expectations.statusWordValue =
543 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
544 // Turn on STATUS_VOUT fault bit(s)
545 expectations.statusVOUTValue = 0xA0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000546 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
547 {
548 // STATUS_TEMPERATURE don't care (default)
549 setPMBusExpectations(mockPMBus, expectations);
550 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
551 .Times(1)
552 .WillOnce(Return("217000"));
553 psu2.analyze();
554 EXPECT_EQ(psu2.isPresent(), true);
555 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
556 EXPECT_EQ(psu2.hasInputFault(), false);
557 EXPECT_EQ(psu2.hasMFRFault(), false);
558 EXPECT_EQ(psu2.hasVINUVFault(), false);
559 EXPECT_EQ(psu2.hasCommFault(), false);
560 EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
561 EXPECT_EQ(psu2.hasVoutUVFault(), false);
562 EXPECT_EQ(psu2.hasIoutOCFault(), false);
563 EXPECT_EQ(psu2.hasFanFault(), false);
564 EXPECT_EQ(psu2.hasTempFault(), false);
565 EXPECT_EQ(psu2.hasPgoodFault(), false);
566 EXPECT_EQ(psu2.hasPSKillFault(), false);
567 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
568 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
569 }
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000570 }
571
572 // IOUT_OC_FAULT fault
573 {
574 // First STATUS_WORD with no bits set, then with IOUT_OC fault.
575 PMBusExpectations expectations;
576 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000577 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
578 .Times(1)
579 .WillOnce(Return("218000"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000580 psu2.analyze();
581 // STATUS_WORD with IOUT_OC fault.
582 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
583 // Turn on STATUS_IOUT fault bit(s)
584 expectations.statusIOUTValue = 0x88;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000585 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
586 {
587 setPMBusExpectations(mockPMBus, expectations);
588 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
589 .Times(1)
590 .WillOnce(Return("219000"));
591 psu2.analyze();
592 EXPECT_EQ(psu2.isPresent(), true);
593 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
594 EXPECT_EQ(psu2.hasInputFault(), false);
595 EXPECT_EQ(psu2.hasMFRFault(), false);
596 EXPECT_EQ(psu2.hasVINUVFault(), false);
597 EXPECT_EQ(psu2.hasCommFault(), false);
598 EXPECT_EQ(psu2.hasVoutOVFault(), false);
599 EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
600 EXPECT_EQ(psu2.hasVoutUVFault(), false);
601 EXPECT_EQ(psu2.hasFanFault(), false);
602 EXPECT_EQ(psu2.hasTempFault(), false);
603 EXPECT_EQ(psu2.hasPgoodFault(), false);
604 EXPECT_EQ(psu2.hasPSKillFault(), false);
605 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
606 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
607 }
Brandon Wyman2cf46942021-10-28 19:09:16 +0000608 }
609
610 // VOUT_UV_FAULT
611 {
612 // First STATUS_WORD with no bits set, then with VOUT fault.
613 PMBusExpectations expectations;
614 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000615 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
616 .Times(1)
617 .WillOnce(Return("220000"));
Brandon Wyman2cf46942021-10-28 19:09:16 +0000618 psu2.analyze();
619 // Change STATUS_WORD to indicate VOUT fault.
620 expectations.statusWordValue = (status_word::VOUT_FAULT);
621 // Turn on STATUS_VOUT fault bit(s)
622 expectations.statusVOUTValue = 0x30;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000623 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
624 {
625 setPMBusExpectations(mockPMBus, expectations);
626 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
627 .Times(1)
628 .WillOnce(Return("221000"));
629 psu2.analyze();
630 EXPECT_EQ(psu2.isPresent(), true);
631 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
632 EXPECT_EQ(psu2.hasInputFault(), false);
633 EXPECT_EQ(psu2.hasMFRFault(), false);
634 EXPECT_EQ(psu2.hasVINUVFault(), false);
635 EXPECT_EQ(psu2.hasCommFault(), false);
636 EXPECT_EQ(psu2.hasVoutOVFault(), false);
637 EXPECT_EQ(psu2.hasIoutOCFault(), false);
638 EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
639 EXPECT_EQ(psu2.hasFanFault(), false);
640 EXPECT_EQ(psu2.hasTempFault(), false);
641 EXPECT_EQ(psu2.hasPgoodFault(), false);
642 EXPECT_EQ(psu2.hasPSKillFault(), false);
643 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
644 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
645 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000646 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600647
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000648 // Fan fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000649 {
650 // First STATUS_WORD with no bits set, then with fan fault.
651 PMBusExpectations expectations;
652 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000653 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
654 .Times(1)
655 .WillOnce(Return("222000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000656 psu2.analyze();
657 expectations.statusWordValue = (status_word::FAN_FAULT);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000658 // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
659 expectations.statusFans12Value = 0xA0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000660
661 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
662 {
663 setPMBusExpectations(mockPMBus, expectations);
664 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
665 .Times(1)
666 .WillOnce(Return("223000"));
667 psu2.analyze();
668 EXPECT_EQ(psu2.isPresent(), true);
669 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
670 EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT);
671 EXPECT_EQ(psu2.hasInputFault(), false);
672 EXPECT_EQ(psu2.hasMFRFault(), false);
673 EXPECT_EQ(psu2.hasVINUVFault(), false);
674 EXPECT_EQ(psu2.hasCommFault(), false);
675 EXPECT_EQ(psu2.hasVoutOVFault(), false);
676 EXPECT_EQ(psu2.hasIoutOCFault(), false);
677 EXPECT_EQ(psu2.hasVoutUVFault(), false);
678 EXPECT_EQ(psu2.hasTempFault(), false);
679 EXPECT_EQ(psu2.hasPgoodFault(), false);
680 EXPECT_EQ(psu2.hasPSKillFault(), false);
681 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
682 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
683 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000684 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000685
Brandon Wyman06ca4592021-12-06 22:52:23 +0000686 // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000687 {
Brandon Wyman2916ea52021-11-06 03:31:18 +0000688 // First STATUS_WORD with no bits set.
689 PMBusExpectations expectations;
690 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000691 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
692 .Times(1)
693 .WillOnce(Return("123000"));
Brandon Wyman2916ea52021-11-06 03:31:18 +0000694 psu2.analyze();
695 EXPECT_EQ(psu2.isFaulted(), false);
696 // POWER_GOOD# inactive, and OFF bit on.
697 expectations.statusWordValue =
698 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000699 for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++)
Brandon Wyman06ca4592021-12-06 22:52:23 +0000700 {
701 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
702 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
703 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000704 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
705 .Times(1)
706 .WillOnce(Return("124000"));
Brandon Wyman06ca4592021-12-06 22:52:23 +0000707 psu2.analyze();
708 EXPECT_EQ(psu2.isPresent(), true);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000709 EXPECT_EQ(psu2.isFaulted(), x >= PGOOD_DEGLITCH_LIMIT);
Brandon Wyman06ca4592021-12-06 22:52:23 +0000710 EXPECT_EQ(psu2.hasInputFault(), false);
711 EXPECT_EQ(psu2.hasMFRFault(), false);
712 EXPECT_EQ(psu2.hasVINUVFault(), false);
713 EXPECT_EQ(psu2.hasCommFault(), false);
714 EXPECT_EQ(psu2.hasVoutOVFault(), false);
715 EXPECT_EQ(psu2.hasVoutUVFault(), false);
716 EXPECT_EQ(psu2.hasIoutOCFault(), false);
717 EXPECT_EQ(psu2.hasFanFault(), false);
718 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000719 EXPECT_EQ(psu2.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT);
Brandon Wyman06ca4592021-12-06 22:52:23 +0000720 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000721 }
722
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600723 // TODO: ReadFailure
724}
725
Brandon Wyman59a35792020-06-04 12:37:40 -0500726TEST_F(PowerSupplyTests, OnOffConfig)
727{
728 auto bus = sdbusplus::bus::new_default();
729 uint8_t data = 0x15;
730
731 // Test where PSU is NOT present
732 try
733 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000734 // Assume GPIO presence, not inventory presence?
Matt Spinler0975eaf2022-02-14 15:38:30 -0600735 EXPECT_CALL(mockedUtil, setAvailable(_, _, _)).Times(0);
Brandon Wymanc3324422022-03-24 20:30:57 +0000736 PowerSupply psu{bus, PSUInventoryPath, 4,
737 0x69, "ibm-cffps", PSUGPIOLineName};
B. J. Wyman681b2a32021-04-20 22:31:22 +0000738
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000739 MockedGPIOInterface* mockPresenceGPIO =
740 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000741 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
Brandon Wyman59a35792020-06-04 12:37:40 -0500742 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000743 // Constructor should set initial presence, default read returns 0.
Brandon Wyman59a35792020-06-04 12:37:40 -0500744 // If it is not present, I should not be trying to write to it.
745 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
746 psu.onOffConfig(data);
747 }
748 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000749 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500750
751 // Test where PSU is present
752 try
753 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000754 // Assume GPIO presence, not inventory presence?
Matt Spinler0975eaf2022-02-14 15:38:30 -0600755 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wymanc3324422022-03-24 20:30:57 +0000756 PowerSupply psu{bus, PSUInventoryPath, 5,
757 0x6a, "ibm-cffps", PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000758 MockedGPIOInterface* mockPresenceGPIO =
759 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman391a0692021-12-08 23:28:18 +0000760 // There will potentially be multiple calls, we want it to continue
761 // returning 1 for the GPIO read to keep the power supply present.
762 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman59a35792020-06-04 12:37:40 -0500763 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000764 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +0000765 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
766 // for INPUT_HISTORY will check max_power_out to see if it is
767 // old/unsupported power supply. Indicate good value, supported.
768 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
769 .Times(1)
770 .WillOnce(Return("2000"));
Brandon Wyman391a0692021-12-08 23:28:18 +0000771 // If I am calling analyze(), I should probably give it good data.
772 // STATUS_WORD 0x0000 is powered on, no faults.
773 PMBusExpectations expectations;
774 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000775 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
776 .Times(1)
777 .WillOnce(Return("205000"));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000778 psu.analyze();
Brandon Wyman391a0692021-12-08 23:28:18 +0000779 // I definitely should be writting ON_OFF_CONFIG if I call the function
780 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
781 Type::HwmonDeviceDebug))
Brandon Wyman59a35792020-06-04 12:37:40 -0500782 .Times(1);
783 psu.onOffConfig(data);
784 }
785 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000786 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500787}
788
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600789TEST_F(PowerSupplyTests, ClearFaults)
790{
791 auto bus = sdbusplus::bus::new_default();
Brandon Wymanc3324422022-03-24 20:30:57 +0000792 PowerSupply psu{bus, PSUInventoryPath, 13,
793 0x68, "ibm-cffps", PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000794 MockedGPIOInterface* mockPresenceGPIO =
795 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000796 // Always return 1 to indicate present.
797 // Each analyze() call will trigger a read of the presence GPIO.
798 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000799 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000800 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +0000801 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
802 // for INPUT_HISTORY will check max_power_out to see if it is
803 // old/unsupported power supply. Indicate good value, supported.
804 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
805 .Times(1)
806 .WillOnce(Return("2000"));
Brandon Wyman8da35c52021-10-28 22:45:08 +0000807 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000808 PMBusExpectations expectations;
809 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000810 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
811 .Times(1)
812 .WillOnce(Return("207000"));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000813 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600814 EXPECT_EQ(psu.isPresent(), true);
815 EXPECT_EQ(psu.isFaulted(), false);
816 EXPECT_EQ(psu.hasInputFault(), false);
817 EXPECT_EQ(psu.hasMFRFault(), false);
818 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000819 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000820 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000821 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000822 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000823 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000824 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000825 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000826 EXPECT_EQ(psu.hasPSKillFault(), false);
827 EXPECT_EQ(psu.hasPS12VcsFault(), false);
828 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000829
Brandon Wymanf07bc792021-10-12 19:00:35 +0000830 // STATUS_WORD with fault bits galore!
Brandon Wymanb654c612021-11-05 23:24:51 +0000831 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000832 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000833 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000834 // STATUS_MFR_SPEFIC with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000835 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000836 // STATUS_CML with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000837 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000838 // STATUS_VOUT with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000839 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000840 // STATUS_IOUT with bits on.
841 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000842 // STATUS_FANS_1_2 with bits on.
843 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000844 // STATUS_TEMPERATURE with bits on.
845 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000846
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000847 for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++)
Brandon Wymanc2906f42021-12-21 20:14:56 +0000848 {
849 setPMBusExpectations(mockPMBus, expectations);
850 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
851 .Times(1)
852 .WillOnce(Return("0"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600853 if (x == DEGLITCH_LIMIT)
854 {
855 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
856 }
Brandon Wymanc2906f42021-12-21 20:14:56 +0000857 psu.analyze();
858 EXPECT_EQ(psu.isPresent(), true);
859 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
860 // Rely on HasVoutUVFault() to verify this sets and clears.
861 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000862 // pgoodFault at PGOOD_DEGLITCH_LIMIT, all other faults are deglitched
863 // up to DEGLITCH_LIMIT
Brandon Wymanc2906f42021-12-21 20:14:56 +0000864 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
865 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
866 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
867 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
868 EXPECT_EQ(psu.hasCommFault(), x >= DEGLITCH_LIMIT);
869 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
870 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
871 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
872 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000873 EXPECT_EQ(psu.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT);
Brandon Wymanc2906f42021-12-21 20:14:56 +0000874 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
875 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
876 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
877 }
878
Brandon Wyman32453e92021-12-15 19:00:14 +0000879 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _))
880 .Times(1)
881 .WillOnce(Return(207000));
Brandon Wyman3225a452022-03-18 18:51:49 +0000882 // Clearing VIN_UV fault via in1_lcrit_alarm
883 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
884 .Times(1)
885 .WillOnce(Return(1));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600886 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600887 psu.clearFaults();
888 EXPECT_EQ(psu.isPresent(), true);
889 EXPECT_EQ(psu.isFaulted(), false);
890 EXPECT_EQ(psu.hasInputFault(), false);
891 EXPECT_EQ(psu.hasMFRFault(), false);
892 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000893 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000894 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000895 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000896 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000897 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000898 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000899 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000900 EXPECT_EQ(psu.hasPSKillFault(), false);
901 EXPECT_EQ(psu.hasPS12VcsFault(), false);
902 EXPECT_EQ(psu.hasPSCS12VFault(), false);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000903
Brandon Wyman82affd92021-11-24 19:12:49 +0000904 // Faults clear on READ_VIN 0 -> !0
905 // STATUS_WORD with fault bits galore!
906 expectations.statusWordValue = 0xFFFF;
907 // STATUS_INPUT with fault bits on.
908 expectations.statusInputValue = 0xFF;
909 // STATUS_MFR_SPEFIC with bits on.
910 expectations.statusMFRValue = 0xFF;
911 // STATUS_CML with bits on.
912 expectations.statusCMLValue = 0xFF;
913 // STATUS_VOUT with bits on.
914 expectations.statusVOUTValue = 0xFF;
915 // STATUS_IOUT with bits on.
916 expectations.statusIOUTValue = 0xFF;
917 // STATUS_FANS_1_2 with bits on.
918 expectations.statusFans12Value = 0xFF;
919 // STATUS_TEMPERATURE with bits on.
920 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000921
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000922 // All faults deglitched now. Check for false before limit above.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000923 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
924 {
925 setPMBusExpectations(mockPMBus, expectations);
926 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
927 .Times(1)
928 .WillOnce(Return("0"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600929 if (x == DEGLITCH_LIMIT)
930 {
931 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
932 }
Brandon Wymanc2906f42021-12-21 20:14:56 +0000933 psu.analyze();
934 }
935
Brandon Wyman82affd92021-11-24 19:12:49 +0000936 EXPECT_EQ(psu.isPresent(), true);
937 EXPECT_EQ(psu.isFaulted(), true);
938 EXPECT_EQ(psu.hasInputFault(), true);
939 EXPECT_EQ(psu.hasMFRFault(), true);
940 EXPECT_EQ(psu.hasVINUVFault(), true);
941 // True due to CML fault bits on
942 EXPECT_EQ(psu.hasCommFault(), true);
943 EXPECT_EQ(psu.hasVoutOVFault(), true);
944 EXPECT_EQ(psu.hasIoutOCFault(), true);
945 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
946 // Rely on HasVoutUVFault() to verify this sets and clears.
947 EXPECT_EQ(psu.hasVoutUVFault(), false);
948 EXPECT_EQ(psu.hasFanFault(), true);
949 EXPECT_EQ(psu.hasTempFault(), true);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000950 // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT
951 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman82affd92021-11-24 19:12:49 +0000952 EXPECT_EQ(psu.hasPSKillFault(), true);
953 EXPECT_EQ(psu.hasPS12VcsFault(), true);
954 EXPECT_EQ(psu.hasPSCS12VFault(), true);
955 // STATUS_WORD with INPUT/VIN_UV fault bits off.
956 expectations.statusWordValue = 0xDFF7;
957 // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
958 // Insufficient Input Voltage bits off.
959 expectations.statusInputValue = 0xC7;
960 setPMBusExpectations(mockPMBus, expectations);
961 // READ_VIN back in range.
962 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
963 .Times(1)
964 .WillOnce(Return("206000"));
Brandon Wyman3225a452022-03-18 18:51:49 +0000965 // VIN_UV cleared via in1_lcrit_alarm when voltage back in range.
966 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
967 .Times(1)
968 .WillOnce(Return(1));
969 psu.analyze();
970 // We only cleared the VIN_UV and OFF faults.
971 EXPECT_EQ(psu.isPresent(), true);
972 EXPECT_EQ(psu.isFaulted(), true);
973 EXPECT_EQ(psu.hasInputFault(), false);
974 EXPECT_EQ(psu.hasMFRFault(), true);
975 EXPECT_EQ(psu.hasVINUVFault(), false);
976 EXPECT_EQ(psu.hasCommFault(), true);
977 EXPECT_EQ(psu.hasVoutOVFault(), true);
978 EXPECT_EQ(psu.hasIoutOCFault(), true);
979 EXPECT_EQ(psu.hasVoutUVFault(), false);
980 EXPECT_EQ(psu.hasFanFault(), true);
981 EXPECT_EQ(psu.hasTempFault(), true);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000982 // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT
983 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman3225a452022-03-18 18:51:49 +0000984 EXPECT_EQ(psu.hasPSKillFault(), true);
985 EXPECT_EQ(psu.hasPS12VcsFault(), true);
986 EXPECT_EQ(psu.hasPSCS12VFault(), true);
987
988 // All faults cleared
989 expectations = {0};
990 setPMBusExpectations(mockPMBus, expectations);
991 // READ_VIN back in range.
992 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
993 .Times(1)
994 .WillOnce(Return("206000"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600995 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman82affd92021-11-24 19:12:49 +0000996 psu.analyze();
997 EXPECT_EQ(psu.isPresent(), true);
998 EXPECT_EQ(psu.isFaulted(), false);
999 EXPECT_EQ(psu.hasInputFault(), false);
1000 EXPECT_EQ(psu.hasMFRFault(), false);
1001 EXPECT_EQ(psu.hasVINUVFault(), false);
1002 EXPECT_EQ(psu.hasCommFault(), false);
1003 EXPECT_EQ(psu.hasVoutOVFault(), false);
1004 EXPECT_EQ(psu.hasIoutOCFault(), false);
1005 EXPECT_EQ(psu.hasVoutUVFault(), false);
1006 EXPECT_EQ(psu.hasFanFault(), false);
1007 EXPECT_EQ(psu.hasTempFault(), false);
1008 EXPECT_EQ(psu.hasPgoodFault(), false);
1009 EXPECT_EQ(psu.hasPSKillFault(), false);
1010 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1011 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1012
B. J. Wyman681b2a32021-04-20 22:31:22 +00001013 // TODO: Faults clear on missing/present?
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001014}
1015
1016TEST_F(PowerSupplyTests, UpdateInventory)
1017{
1018 auto bus = sdbusplus::bus::new_default();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001019
1020 try
1021 {
Brandon Wymanc3324422022-03-24 20:30:57 +00001022 PowerSupply psu{bus, PSUInventoryPath, 3,
1023 0x68, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001024 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1025 // If it is not present, I should not be trying to read a string
1026 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
1027 psu.updateInventory();
1028 }
1029 catch (...)
1030 {
1031 ADD_FAILURE() << "Should not have caught exception.";
1032 }
1033
1034 try
1035 {
Brandon Wymanc3324422022-03-24 20:30:57 +00001036 PowerSupply psu{bus, PSUInventoryPath, 13,
1037 0x69, "ibm-cffps", PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001038 MockedGPIOInterface* mockPresenceGPIO =
1039 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001040 // GPIO read return 1 to indicate present.
1041 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001042 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001043 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001044 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1045 // for INPUT_HISTORY will check max_power_out to see if it is
1046 // old/unsupported power supply. Indicate good value, supported.
1047 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1048 .Times(1)
1049 .WillOnce(Return("2000"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001050 // STATUS_WORD 0x0000 is powered on, no faults.
1051 PMBusExpectations expectations;
1052 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001053 // Call to analyze will read voltage, trigger clear faults for 0 to
1054 // within range.
1055 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1056 .Times(1)
1057 .WillOnce(Return("123456"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001058 psu.analyze();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001059 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
1060 psu.updateInventory();
1061
Brandon Wyman3c530fb2021-04-13 13:13:22 -05001062#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001063 EXPECT_CALL(mockPMBus, readString(_, _))
1064 .WillOnce(Return("CCIN"))
1065 .WillOnce(Return("PN3456"))
1066 .WillOnce(Return("FN3456"))
1067 .WillOnce(Return("HEADER"))
1068 .WillOnce(Return("SN3456"))
1069 .WillOnce(Return("FW3456"));
Brandon Wyman3c530fb2021-04-13 13:13:22 -05001070#endif
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001071 psu.updateInventory();
1072 // TODO: D-Bus mocking to verify values stored on D-Bus (???)
1073 }
1074 catch (...)
1075 {
1076 ADD_FAILURE() << "Should not have caught exception.";
1077 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001078}
1079
1080TEST_F(PowerSupplyTests, IsPresent)
1081{
1082 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001083
Brandon Wymanc3324422022-03-24 20:30:57 +00001084 PowerSupply psu{bus, PSUInventoryPath, 3,
1085 0x68, "ibm-cffps", PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001086 MockedGPIOInterface* mockPresenceGPIO =
1087 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001088 EXPECT_EQ(psu.isPresent(), false);
1089
B. J. Wyman681b2a32021-04-20 22:31:22 +00001090 // Change GPIO read to return 1 to indicate present.
1091 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +00001092 // Call to analyze() will update to present, that will trigger updating
1093 // to the correct/latest HWMON directory, in case it changes.
1094 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1095 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001096 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1097 // for INPUT_HISTORY will check max_power_out to see if it is
1098 // old/unsupported power supply. Indicate good value, supported.
1099 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1100 .Times(1)
1101 .WillOnce(Return("2000"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001102 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1103 // Default expectations will be on, no faults.
1104 PMBusExpectations expectations;
1105 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001106 // Give it an input voltage in the 100-volt range.
1107 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1108 .Times(1)
1109 .WillOnce(Return("123456"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001110 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
B. J. Wyman681b2a32021-04-20 22:31:22 +00001111 psu.analyze();
1112 EXPECT_EQ(psu.isPresent(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001113}
1114
1115TEST_F(PowerSupplyTests, IsFaulted)
1116{
1117 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001118
Brandon Wymanc3324422022-03-24 20:30:57 +00001119 PowerSupply psu{bus, PSUInventoryPath, 11,
1120 0x6f, "ibm-cffps", PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001121 MockedGPIOInterface* mockPresenceGPIO =
1122 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001123 // Always return 1 to indicate present.
1124 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +00001125 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1126 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001127 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1128 // for INPUT_HISTORY will check max_power_out to see if it is
1129 // old/unsupported power supply. Indicate good value, supported.
1130 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1131 .Times(1)
1132 .WillOnce(Return("2000"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001133 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1134 // Default expectations will be on, no faults.
1135 PMBusExpectations expectations;
1136 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001137 // Give it an input voltage in the 100-volt range.
1138 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1139 .Times(1)
1140 .WillOnce(Return("124680"));
B. J. Wyman681b2a32021-04-20 22:31:22 +00001141 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001142 EXPECT_EQ(psu.isFaulted(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001143 // STATUS_WORD with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001144 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +00001145 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001146 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +00001147 // STATUS_MFR_SPECIFIC with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001148 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +00001149 // STATUS_CML with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001150 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +00001151 // STATUS_VOUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001152 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001153 // STATUS_IOUT with fault bits on.
1154 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001155 // STATUS_FANS_1_2 with bits on.
1156 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +00001157 // STATUS_TEMPERATURE with fault bits on.
1158 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001159 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1160 {
1161 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman4fc191f2022-03-10 23:07:13 +00001162 // Also get another read of READ_VIN, faulted, so not in 100-volt range
Brandon Wymanc2906f42021-12-21 20:14:56 +00001163 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1164 .Times(1)
Brandon Wyman4fc191f2022-03-10 23:07:13 +00001165 .WillOnce(Return("19000"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001166 if (x == DEGLITCH_LIMIT)
1167 {
1168 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1169 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001170 psu.analyze();
1171 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
1172 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001173}
1174
1175TEST_F(PowerSupplyTests, HasInputFault)
1176{
1177 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001178
Brandon Wymanc3324422022-03-24 20:30:57 +00001179 PowerSupply psu{bus, PSUInventoryPath, 3,
1180 0x68, "ibm-cffps", PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001181 MockedGPIOInterface* mockPresenceGPIO =
1182 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001183 // Always return 1 to indicate present.
1184 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001185 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001186 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001187 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1188 // for INPUT_HISTORY will check max_power_out to see if it is
1189 // old/unsupported power supply. Indicate good value, supported.
1190 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1191 .Times(1)
1192 .WillOnce(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
Brandon Wymanc3324422022-03-24 20:30:57 +00001236 PowerSupply psu{bus, PSUInventoryPath, 3,
1237 0x68, "ibm-cffps", PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001238 MockedGPIOInterface* mockPresenceGPIO =
1239 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001240 // Always return 1 to indicate present.
1241 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001242 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001243 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon 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, _))
1248 .Times(1)
1249 .WillOnce(Return("2000"));
Brandon Wymanf07bc792021-10-12 19:00:35 +00001250 // First return STATUS_WORD with no bits on.
Brandon Wyman8da35c52021-10-28 22:45:08 +00001251 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001252 PMBusExpectations expectations;
1253 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001254 // Analyze call will also need good READ_VIN value to check.
1255 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1256 .Times(1)
1257 .WillOnce(Return("202100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001258 psu.analyze();
1259 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001260 // Next return STATUS_WORD with MFR fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001261 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001262 // STATUS_MFR_SPEFIC with bit(s) on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001263 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001264 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1265 {
1266 setPMBusExpectations(mockPMBus, expectations);
1267 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1268 .Times(1)
1269 .WillOnce(Return("202200"));
1270 psu.analyze();
1271 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1272 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001273 // Back to no bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001274 expectations.statusWordValue = 0;
1275 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001276 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1277 .Times(1)
1278 .WillOnce(Return("202300"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001279 psu.analyze();
1280 EXPECT_EQ(psu.hasMFRFault(), false);
1281}
1282
1283TEST_F(PowerSupplyTests, HasVINUVFault)
1284{
1285 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001286
Brandon Wymanc3324422022-03-24 20:30:57 +00001287 PowerSupply psu{bus, PSUInventoryPath, 3,
1288 0x68, "ibm-cffps", PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001289 MockedGPIOInterface* mockPresenceGPIO =
1290 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001291 // Always return 1 to indicate present.
1292 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001293 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001294 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001295 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1296 // for INPUT_HISTORY will check max_power_out to see if it is
1297 // old/unsupported power supply. Indicate good value, supported.
1298 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1299 .Times(1)
1300 .WillOnce(Return("2000"));
Brandon Wyman82affd92021-11-24 19:12:49 +00001301
1302 // Presence change from missing to present will trigger in1_input read in
1303 // an attempt to get CLEAR_FAULTS called. Return value ignored.
1304 // Zero to non-zero voltage, for missing/present change, triggers clear
1305 // faults call again. Return value ignored.
1306 // Fault (low voltage) to not faulted (voltage in range) triggers clear
1307 // faults call a third time.
1308
Brandon Wyman8da35c52021-10-28 22:45:08 +00001309 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001310 PMBusExpectations expectations;
1311 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001312 // Analyze call will also need good READ_VIN value to check.
1313 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1314 .Times(1)
1315 .WillOnce(Return("201100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001316 psu.analyze();
1317 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001318 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001319 expectations.statusWordValue = (status_word::VIN_UV_FAULT);
Brandon Wyman85c7bf42021-10-19 22:28:48 +00001320 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
1321 // Figure 16, and assume bits on in STATUS_INPUT.
Brandon Wymanb654c612021-11-05 23:24:51 +00001322 expectations.statusInputValue = 0x18;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001323 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1324 {
1325 setPMBusExpectations(mockPMBus, expectations);
1326 // If there is a VIN_UV fault, fake reading voltage of less than 20V
1327 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1328 .Times(1)
1329 .WillOnce(Return("19876"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001330 if (x == DEGLITCH_LIMIT)
1331 {
1332 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1333 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001334 psu.analyze();
1335 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1336 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001337 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001338 expectations.statusWordValue = 0;
1339 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001340 // Updates now result in clearing faults if read voltage goes from below the
1341 // minimum, to within a valid range.
1342 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1343 .Times(1)
1344 .WillOnce(Return("201300"));
Brandon Wyman3225a452022-03-18 18:51:49 +00001345 // Went from below minimum to within range, expect clearVinUVFault().
1346 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
1347 .Times(1)
1348 .WillOnce(Return(1));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001349 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001350 psu.analyze();
1351 EXPECT_EQ(psu.hasVINUVFault(), false);
1352}
Brandon Wyman6710ba22021-10-27 17:39:31 +00001353
1354TEST_F(PowerSupplyTests, HasVoutOVFault)
1355{
1356 auto bus = sdbusplus::bus::new_default();
1357
Brandon Wymanc3324422022-03-24 20:30:57 +00001358 PowerSupply psu{bus, PSUInventoryPath, 3,
1359 0x69, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman6710ba22021-10-27 17:39:31 +00001360 MockedGPIOInterface* mockPresenceGPIO =
1361 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1362 // Always return 1 to indicate present.
1363 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001364 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001365 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001366 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1367 // for INPUT_HISTORY will check max_power_out to see if it is
1368 // old/unsupported power supply. Indicate good value, supported.
1369 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1370 .Times(1)
1371 .WillOnce(Return("2000"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001372 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001373 PMBusExpectations expectations;
1374 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001375 // Call to analyze will trigger read of "in1_input" to check voltage.
1376 // Initial value would be 0, so this read updates it to non-zero.
1377 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1378 .Times(1)
1379 .WillOnce(Return("202100"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001380 psu.analyze();
1381 EXPECT_EQ(psu.hasVoutOVFault(), false);
1382 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001383 expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
Brandon Wyman6710ba22021-10-27 17:39:31 +00001384 // STATUS_VOUT fault bit(s)
Brandon Wymanb654c612021-11-05 23:24:51 +00001385 expectations.statusVOUTValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001386 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1387 {
1388 setPMBusExpectations(mockPMBus, expectations);
1389 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1390 .Times(1)
1391 .WillOnce(Return("202200"));
1392 psu.analyze();
1393 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1394 }
Brandon Wyman6710ba22021-10-27 17:39:31 +00001395 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001396 expectations.statusWordValue = 0;
1397 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001398 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1399 .Times(1)
1400 .WillOnce(Return("202300"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001401 psu.analyze();
1402 EXPECT_EQ(psu.hasVoutOVFault(), false);
1403}
Brandon Wyman96893a42021-11-05 19:56:57 +00001404
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001405TEST_F(PowerSupplyTests, HasIoutOCFault)
1406{
1407 auto bus = sdbusplus::bus::new_default();
1408
Brandon Wymanc3324422022-03-24 20:30:57 +00001409 PowerSupply psu{bus, PSUInventoryPath, 3,
1410 0x6d, "ibm-cffps", PSUGPIOLineName};
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001411 MockedGPIOInterface* mockPresenceGPIO =
1412 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1413 // Always return 1 to indicate present.
1414 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001415 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001416 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001417 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1418 // for INPUT_HISTORY will check max_power_out to see if it is
1419 // old/unsupported power supply. Indicate good value, supported.
1420 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1421 .Times(1)
1422 .WillOnce(Return("2000"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001423 // STATUS_WORD 0x0000 is powered on, no faults.
1424 PMBusExpectations expectations;
1425 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001426 // Call to analyze will trigger read of "in1_input" to check voltage.
1427 // Initial value would be 0, so this read updates it to non-zero.
1428 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1429 .Times(1)
1430 .WillOnce(Return("203100"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001431 psu.analyze();
1432 EXPECT_EQ(psu.hasIoutOCFault(), false);
1433 // Turn fault on.
1434 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1435 // STATUS_IOUT fault bit(s)
1436 expectations.statusIOUTValue = 0x88;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001437 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1438 {
1439 setPMBusExpectations(mockPMBus, expectations);
1440 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1441 .Times(1)
1442 .WillOnce(Return("203200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001443 if (x == DEGLITCH_LIMIT)
1444 {
1445 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1446 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001447 psu.analyze();
1448 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1449 }
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001450 // Back to no fault bits on in STATUS_WORD
1451 expectations.statusWordValue = 0;
1452 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001453 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1454 .Times(1)
1455 .WillOnce(Return("203300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001456 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001457 psu.analyze();
1458 EXPECT_EQ(psu.hasIoutOCFault(), false);
1459}
1460
Brandon Wyman2cf46942021-10-28 19:09:16 +00001461TEST_F(PowerSupplyTests, HasVoutUVFault)
1462{
1463 auto bus = sdbusplus::bus::new_default();
1464
Brandon Wymanc3324422022-03-24 20:30:57 +00001465 PowerSupply psu{bus, PSUInventoryPath, 3,
1466 0x6a, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman2cf46942021-10-28 19:09:16 +00001467 MockedGPIOInterface* mockPresenceGPIO =
1468 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1469 // Always return 1 to indicate present.
1470 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001471 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001472 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001473 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1474 // for INPUT_HISTORY will check max_power_out to see if it is
1475 // old/unsupported power supply. Indicate good value, supported.
1476 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1477 .Times(1)
1478 .WillOnce(Return("2000"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001479 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wyman2cf46942021-10-28 19:09:16 +00001480 PMBusExpectations expectations;
1481 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001482 // Call to analyze will trigger read of "in1_input" to check voltage.
1483 // Initial value would be 0, so this read updates it to non-zero.
1484 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1485 .Times(1)
1486 .WillOnce(Return("204100"));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001487 psu.analyze();
1488 EXPECT_EQ(psu.hasVoutUVFault(), false);
1489 // Turn fault on.
1490 expectations.statusWordValue = (status_word::VOUT_FAULT);
1491 // STATUS_VOUT fault bit(s)
1492 expectations.statusVOUTValue = 0x30;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001493 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1494 {
1495 setPMBusExpectations(mockPMBus, expectations);
1496 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1497 .Times(1)
1498 .WillOnce(Return("204200"));
1499 psu.analyze();
1500 EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1501 }
Brandon Wyman2cf46942021-10-28 19:09:16 +00001502 // Back to no fault bits on in STATUS_WORD
1503 expectations.statusWordValue = 0;
1504 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001505 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1506 .Times(1)
1507 .WillOnce(Return("204300"));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001508 psu.analyze();
1509 EXPECT_EQ(psu.hasVoutUVFault(), false);
1510}
1511
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001512TEST_F(PowerSupplyTests, HasFanFault)
1513{
1514 auto bus = sdbusplus::bus::new_default();
1515
Matt Spinler0975eaf2022-02-14 15:38:30 -06001516 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
1517 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
1518
Brandon Wymanc3324422022-03-24 20:30:57 +00001519 PowerSupply psu{bus, PSUInventoryPath, 3,
1520 0x6d, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001521 MockedGPIOInterface* mockPresenceGPIO =
1522 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1523 // Always return 1 to indicate present.
1524 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001525 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001526 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001527 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1528 // for INPUT_HISTORY will check max_power_out to see if it is
1529 // old/unsupported power supply. Indicate good value, supported.
1530 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1531 .Times(1)
1532 .WillOnce(Return("2000"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001533 // STATUS_WORD 0x0000 is powered on, no faults.
1534 PMBusExpectations expectations;
1535 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001536 // Call to analyze will trigger read of "in1_input" to check voltage.
1537 // Initial value would be 0, so this read updates it to non-zero.
1538 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1539 .Times(1)
1540 .WillOnce(Return("205100"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001541 psu.analyze();
1542 EXPECT_EQ(psu.hasFanFault(), false);
1543 // Turn fault on.
1544 expectations.statusWordValue = (status_word::FAN_FAULT);
1545 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
1546 expectations.statusFans12Value = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001547 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1548 {
1549 setPMBusExpectations(mockPMBus, expectations);
1550 // Call to analyze will trigger read of "in1_input" to check voltage.
1551 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1552 .Times(1)
1553 .WillOnce(Return("205200"));
1554 psu.analyze();
1555 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1556 }
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001557 // Back to no fault bits on in STATUS_WORD
1558 expectations.statusWordValue = 0;
1559 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001560 // Call to analyze will trigger read of "in1_input" to check voltage.
1561 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1562 .Times(1)
1563 .WillOnce(Return("205300"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001564 psu.analyze();
1565 EXPECT_EQ(psu.hasFanFault(), false);
1566}
1567
Brandon Wyman96893a42021-11-05 19:56:57 +00001568TEST_F(PowerSupplyTests, HasTempFault)
1569{
1570 auto bus = sdbusplus::bus::new_default();
1571
Matt Spinler0975eaf2022-02-14 15:38:30 -06001572 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
1573 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
1574
Brandon Wymanc3324422022-03-24 20:30:57 +00001575 PowerSupply psu{bus, PSUInventoryPath, 3,
1576 0x6a, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman96893a42021-11-05 19:56:57 +00001577 MockedGPIOInterface* mockPresenceGPIO =
1578 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1579 // Always return 1 to indicate present.
1580 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman96893a42021-11-05 19:56:57 +00001581 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001582 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001583 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1584 // for INPUT_HISTORY will check max_power_out to see if it is
1585 // old/unsupported power supply. Indicate good value, supported.
1586 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1587 .Times(1)
1588 .WillOnce(Return("2000"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001589 // STATUS_WORD 0x0000 is powered on, no faults.
1590 PMBusExpectations expectations;
1591 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001592 // Call to analyze will trigger read of "in1_input" to check voltage.
1593 // Initial value would be 0, so this read updates it to non-zero.
1594 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1595 .Times(1)
1596 .WillOnce(Return("206100"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001597 psu.analyze();
1598 EXPECT_EQ(psu.hasTempFault(), false);
1599 // Turn fault on.
1600 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
1601 // STATUS_TEMPERATURE fault bit on (OT Fault)
1602 expectations.statusTempValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001603 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1604 {
1605 setPMBusExpectations(mockPMBus, expectations);
1606 // Call to analyze will trigger read of "in1_input" to check voltage.
1607 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1608 .Times(1)
1609 .WillOnce(Return("206200"));
1610 psu.analyze();
1611 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1612 }
Brandon Wyman96893a42021-11-05 19:56:57 +00001613 // Back to no fault bits on in STATUS_WORD
1614 expectations.statusWordValue = 0;
1615 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001616 // Call to analyze will trigger read of "in1_input" to check voltage.
1617 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1618 .Times(1)
1619 .WillOnce(Return("206300"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001620 psu.analyze();
1621 EXPECT_EQ(psu.hasTempFault(), false);
1622}
Brandon Wyman2916ea52021-11-06 03:31:18 +00001623
1624TEST_F(PowerSupplyTests, HasPgoodFault)
1625{
1626 auto bus = sdbusplus::bus::new_default();
1627
Brandon Wymanc3324422022-03-24 20:30:57 +00001628 PowerSupply psu{bus, PSUInventoryPath, 3,
1629 0x6b, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman2916ea52021-11-06 03:31:18 +00001630 MockedGPIOInterface* mockPresenceGPIO =
1631 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1632 // Always return 1 to indicate present.
1633 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001634 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001635 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001636 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1637 // for INPUT_HISTORY will check max_power_out to see if it is
1638 // old/unsupported power supply. Indicate good value, supported.
1639 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1640 .Times(1)
1641 .WillOnce(Return("2000"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001642 // STATUS_WORD 0x0000 is powered on, no faults.
1643 PMBusExpectations expectations;
1644 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001645 // Call to analyze will trigger read of "in1_input" to check voltage.
1646 // Initial value would be 0, so this read updates it to non-zero.
1647 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1648 .Times(1)
1649 .WillOnce(Return("207100"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001650 psu.analyze();
1651 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman391a0692021-12-08 23:28:18 +00001652 // Setup another expectation of no faults.
1653 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001654 // 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("207200"));
1658 psu.analyze();
1659 EXPECT_EQ(psu.hasPgoodFault(), false);
1660 // Setup another expectation of no faults.
1661 setPMBusExpectations(mockPMBus, expectations);
1662 // Call to analyze will trigger read of "in1_input" to check voltage.
1663 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1664 .Times(1)
1665 .WillOnce(Return("207300"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001666 psu.analyze();
1667 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +00001668 // Turn PGOOD# off (fault on).
1669 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
1670 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001671 // Call to analyze will trigger read of "in1_input" to check voltage.
1672 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1673 .Times(1)
1674 .WillOnce(Return("207400"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001675 psu.analyze();
Brandon Wyman6d469fd2022-06-15 16:58:21 +00001676 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 1
Brandon Wyman06ca4592021-12-06 22:52:23 +00001677 EXPECT_EQ(psu.hasPgoodFault(), false);
1678 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001679 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1680 .Times(1)
1681 .WillOnce(Return("207500"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001682 psu.analyze();
Brandon Wyman6d469fd2022-06-15 16:58:21 +00001683 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 2
Brandon Wyman06ca4592021-12-06 22:52:23 +00001684 EXPECT_EQ(psu.hasPgoodFault(), false);
1685 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001686 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1687 .Times(1)
1688 .WillOnce(Return("207600"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001689 psu.analyze();
Brandon Wyman6d469fd2022-06-15 16:58:21 +00001690 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 3
1691 EXPECT_EQ(psu.hasPgoodFault(), false);
1692 setPMBusExpectations(mockPMBus, expectations);
1693 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1694 .Times(1)
1695 .WillOnce(Return("207700"));
1696 psu.analyze();
1697 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 4
1698 EXPECT_EQ(psu.hasPgoodFault(), false);
1699 setPMBusExpectations(mockPMBus, expectations);
1700 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1701 .Times(1)
1702 .WillOnce(Return("207800"));
1703 psu.analyze();
1704 // Expect true. PGOOD_DEGLITCH_LIMIT @ 5
Brandon Wyman2916ea52021-11-06 03:31:18 +00001705 EXPECT_EQ(psu.hasPgoodFault(), true);
1706 // Back to no fault bits on in STATUS_WORD
1707 expectations.statusWordValue = 0;
1708 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001709 // Call to analyze will trigger read of "in1_input" to check voltage.
1710 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1711 .Times(1)
1712 .WillOnce(Return("207700"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001713 psu.analyze();
1714 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman82affd92021-11-24 19:12:49 +00001715
Brandon Wyman2916ea52021-11-06 03:31:18 +00001716 // Turn OFF bit on
1717 expectations.statusWordValue = (status_word::UNIT_IS_OFF);
1718 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001719 // Call to analyze will trigger read of "in1_input" to check voltage.
1720 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1721 .Times(1)
1722 .WillOnce(Return("208100"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001723 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001724 EXPECT_EQ(psu.hasPgoodFault(), false);
1725 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001726 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1727 .Times(1)
1728 .WillOnce(Return("208200"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001729 psu.analyze();
1730 EXPECT_EQ(psu.hasPgoodFault(), false);
1731 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001732 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1733 .Times(1)
1734 .WillOnce(Return("208300"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001735 psu.analyze();
Brandon Wyman6d469fd2022-06-15 16:58:21 +00001736 EXPECT_EQ(psu.hasPgoodFault(), false);
1737 setPMBusExpectations(mockPMBus, expectations);
1738 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1739 .Times(1)
1740 .WillOnce(Return("208400"));
1741 psu.analyze();
1742 EXPECT_EQ(psu.hasPgoodFault(), false);
1743 setPMBusExpectations(mockPMBus, expectations);
1744 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1745 .Times(1)
1746 .WillOnce(Return("208500"));
1747 psu.analyze();
Brandon Wyman2916ea52021-11-06 03:31:18 +00001748 EXPECT_EQ(psu.hasPgoodFault(), true);
1749 // Back to no fault bits on in STATUS_WORD
1750 expectations.statusWordValue = 0;
1751 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001752 // Call to analyze will trigger read of "in1_input" to check voltage.
1753 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1754 .Times(1)
Brandon Wyman6d469fd2022-06-15 16:58:21 +00001755 .WillOnce(Return("208000"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001756 psu.analyze();
1757 EXPECT_EQ(psu.hasPgoodFault(), false);
1758}
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001759
1760TEST_F(PowerSupplyTests, HasPSKillFault)
1761{
1762 auto bus = sdbusplus::bus::new_default();
Brandon Wymanc3324422022-03-24 20:30:57 +00001763 PowerSupply psu{bus, PSUInventoryPath, 4,
1764 0x6d, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001765 MockedGPIOInterface* mockPresenceGPIO =
1766 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1767 // Always return 1 to indicate present.
1768 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001769 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001770 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001771 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1772 // for INPUT_HISTORY will check max_power_out to see if it is
1773 // old/unsupported power supply. Indicate good value, supported.
1774 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1775 .Times(1)
1776 .WillOnce(Return("2000"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001777 // STATUS_WORD 0x0000 is powered on, no faults.
1778 PMBusExpectations expectations;
1779 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001780 // Call to analyze will trigger read of "in1_input" to check voltage.
1781 // Initial value would be 0, so this read updates it to non-zero.
1782 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1783 .Times(1)
1784 .WillOnce(Return("208100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001785 psu.analyze();
1786 EXPECT_EQ(psu.hasPSKillFault(), false);
1787 // Next return STATUS_WORD with MFR fault bit on.
1788 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1789 // STATUS_MFR_SPEFIC with bit(s) on.
1790 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001791
1792 // Deglitching faults, false until read the fault bits on up to the limit.
1793 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1794 {
1795 setPMBusExpectations(mockPMBus, expectations);
1796 // Call to analyze will trigger read of "in1_input" to check voltage.
1797 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1798 .Times(1)
1799 .WillOnce(Return("208200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001800 if (x == DEGLITCH_LIMIT)
1801 {
1802 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1803 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001804 psu.analyze();
1805 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1806 }
1807
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001808 // Back to no bits on in STATUS_WORD
1809 expectations.statusWordValue = 0;
1810 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001811 // Call to analyze will trigger read of "in1_input" to check voltage.
1812 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1813 .Times(1)
1814 .WillOnce(Return("208300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001815 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001816 psu.analyze();
1817 EXPECT_EQ(psu.hasPSKillFault(), false);
1818 // Next return STATUS_WORD with MFR fault bit on.
1819 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1820 // STATUS_MFR_SPEFIC with bit 4 on.
1821 expectations.statusMFRValue = 0x10;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001822
1823 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1824 {
1825 setPMBusExpectations(mockPMBus, expectations);
1826 // Call to analyze will trigger read of "in1_input" to check voltage.
1827 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1828 .Times(1)
1829 .WillOnce(Return("208400"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001830 if (x == DEGLITCH_LIMIT)
1831 {
1832 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1833 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001834 psu.analyze();
1835 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1836 }
1837
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001838 // Back to no bits on in STATUS_WORD
1839 expectations.statusWordValue = 0;
1840 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001841 // Call to analyze will trigger read of "in1_input" to check voltage.
1842 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1843 .Times(1)
1844 .WillOnce(Return("208500"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001845 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001846 psu.analyze();
1847 EXPECT_EQ(psu.hasPSKillFault(), false);
1848}
1849
1850TEST_F(PowerSupplyTests, HasPS12VcsFault)
1851{
1852 auto bus = sdbusplus::bus::new_default();
Brandon Wymanc3324422022-03-24 20:30:57 +00001853 PowerSupply psu{bus, PSUInventoryPath, 5,
1854 0x6e, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001855 MockedGPIOInterface* mockPresenceGPIO =
1856 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1857 // Always return 1 to indicate present.
1858 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001859 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001860 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001861 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1862 // for INPUT_HISTORY will check max_power_out to see if it is
1863 // old/unsupported power supply. Indicate good value, supported.
1864 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1865 .Times(1)
1866 .WillOnce(Return("2000"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001867 // STATUS_WORD 0x0000 is powered on, no faults.
1868 PMBusExpectations expectations;
1869 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001870 // Call to analyze will trigger read of "in1_input" to check voltage.
1871 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1872 .Times(1)
1873 .WillOnce(Return("209100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001874 psu.analyze();
1875 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1876 // Next return STATUS_WORD with MFR fault bit on.
1877 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1878 // STATUS_MFR_SPEFIC with bit(s) on.
1879 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001880
1881 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1882 {
1883 setPMBusExpectations(mockPMBus, expectations);
1884 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1885 .Times(1)
1886 .WillOnce(Return("209200"));
1887 psu.analyze();
1888 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1889 }
1890
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001891 // Back to no bits on in STATUS_WORD
1892 expectations.statusWordValue = 0;
1893 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001894 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1895 .Times(1)
1896 .WillOnce(Return("209300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001897 psu.analyze();
1898 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1899 // Next return STATUS_WORD with MFR fault bit on.
1900 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1901 // STATUS_MFR_SPEFIC with bit 6 on.
1902 expectations.statusMFRValue = 0x40;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001903
1904 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1905 {
1906 setPMBusExpectations(mockPMBus, expectations);
1907 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1908 .Times(1)
1909 .WillOnce(Return("209400"));
1910 psu.analyze();
1911 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1912 }
1913
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001914 // Back to no bits on in STATUS_WORD
1915 expectations.statusWordValue = 0;
1916 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001917 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1918 .Times(1)
1919 .WillOnce(Return("209500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001920 psu.analyze();
1921 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1922}
1923
1924TEST_F(PowerSupplyTests, HasPSCS12VFault)
1925{
1926 auto bus = sdbusplus::bus::new_default();
Brandon Wymanc3324422022-03-24 20:30:57 +00001927 PowerSupply psu{bus, PSUInventoryPath, 6,
1928 0x6f, "ibm-cffps", PSUGPIOLineName};
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001929 MockedGPIOInterface* mockPresenceGPIO =
1930 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1931 // Always return 1 to indicate present.
1932 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001933 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001934 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001935 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1936 // for INPUT_HISTORY will check max_power_out to see if it is
1937 // old/unsupported power supply. Indicate good value, supported.
1938 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
1939 .Times(1)
1940 .WillOnce(Return("2000"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001941 // STATUS_WORD 0x0000 is powered on, no faults.
1942 PMBusExpectations expectations;
1943 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001944 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1945 .Times(1)
1946 .WillOnce(Return("209100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001947 psu.analyze();
1948 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1949 // Next return STATUS_WORD with MFR fault bit on.
1950 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1951 // STATUS_MFR_SPEFIC with bit(s) on.
1952 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001953
1954 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1955 {
1956 setPMBusExpectations(mockPMBus, expectations);
1957 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1958 .Times(1)
1959 .WillOnce(Return("209200"));
1960 psu.analyze();
1961 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1962 }
1963
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001964 // Back to no bits on in STATUS_WORD
1965 expectations.statusWordValue = 0;
1966 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001967 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1968 .Times(1)
1969 .WillOnce(Return("209300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001970 psu.analyze();
1971 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1972 // Next return STATUS_WORD with MFR fault bit on.
1973 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1974 // STATUS_MFR_SPEFIC with bit 7 on.
1975 expectations.statusMFRValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001976
1977 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1978 {
1979 setPMBusExpectations(mockPMBus, expectations);
1980 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1981 .Times(1)
1982 .WillOnce(Return("209400"));
1983 psu.analyze();
1984 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1985 }
1986
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001987 // Back to no bits on in STATUS_WORD
1988 expectations.statusWordValue = 0;
1989 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001990 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1991 .Times(1)
1992 .WillOnce(Return("209500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001993 psu.analyze();
1994 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1995}
Brandon Wymanc3324422022-03-24 20:30:57 +00001996
1997TEST_F(PowerSupplyTests, SetupInputHistory)
1998{
1999 auto bus = sdbusplus::bus::new_default();
2000 {
2001 PowerSupply psu{bus, PSUInventoryPath, 6,
2002 0x6f, "ibm-cffps", PSUGPIOLineName};
2003 // Defaults to not present due to constructor and mock ordering.
2004 psu.setupInputHistory();
2005 EXPECT_EQ(psu.hasInputHistory(), false);
2006 MockedGPIOInterface* mockPresenceGPIO =
2007 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wymanae35ac52022-05-23 22:33:40 +00002008 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wymanc3324422022-03-24 20:30:57 +00002009 // Always return 1 to indicate present.
2010 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wymanae35ac52022-05-23 22:33:40 +00002011 setMissingToPresentExpects(mockPMBus, mockedUtil);
2012 PMBusExpectations expectations;
2013 setPMBusExpectations(mockPMBus, expectations);
2014 // After reading STATUS_WORD, etc., there will be a READ_VIN check.
2015 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2016 .Times(1)
2017 .WillOnce(Return("206000"));
2018 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2019 // for INPUT_HISTORY will check max_power_out to see if it is
2020 // old/unsupported power supply. Indicate good value, supported.
2021 /// Also called when I redo setupInputHistory().
2022 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2023 .Times(2)
2024 .WillRepeatedly(Return("2000"));
2025 // Call to analyze() and above expectations to get missing/present and
2026 // good status.
Brandon Wymanc3324422022-03-24 20:30:57 +00002027 psu.analyze();
2028 psu.setupInputHistory();
2029 EXPECT_EQ(psu.hasInputHistory(), true);
2030 }
2031 {
Brandon Wymanae35ac52022-05-23 22:33:40 +00002032 // Workaround - Disable INPUT_HISTORY collection if 1400W
2033 PowerSupply psu{bus, PSUInventoryPath, 3,
2034 0x68, "ibm-cffps", PSUGPIOLineName};
2035 // Defaults to not present due to constructor and mock ordering.
2036 psu.setupInputHistory();
2037 EXPECT_EQ(psu.hasInputHistory(), false);
2038 MockedGPIOInterface* mockPresenceGPIO =
2039 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2040 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2041 // Always return 1 to indicate present.
2042 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2043 setMissingToPresentExpects(mockPMBus, mockedUtil);
2044 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2045 // for INPUT_HISTORY will check max_power_out to see if it is
2046 // old/unsupported power supply. Indicate 1400W IBM value, unsupported.
2047 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2048 .Times(2)
2049 .WillRepeatedly(Return("30725"));
2050 PMBusExpectations expectations;
2051 setPMBusExpectations(mockPMBus, expectations);
2052 // After reading STATUS_WORD, etc., there will be a READ_VIN check.
2053 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2054 .Times(1)
2055 .WillOnce(Return("206000"));
2056 // Call to analyze() and above expectations to get missing/present and
2057 // good status.
2058 psu.analyze();
2059 psu.setupInputHistory();
2060 // After updating to present, and retrying setup, expect ibm-cffps with
2061 // 1400W to still not support INPUT_HISTORY.
2062 EXPECT_EQ(psu.hasInputHistory(), false);
2063 }
2064 {
Brandon Wymanc3324422022-03-24 20:30:57 +00002065 PowerSupply psu{bus, PSUInventoryPath, 11,
2066 0x58, "inspur-ipsps", PSUGPIOLineName};
2067 // Defaults to not present due to constructor and mock ordering.
2068 psu.setupInputHistory();
2069 EXPECT_EQ(psu.hasInputHistory(), false);
2070 MockedGPIOInterface* mockPresenceGPIO =
2071 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wymanae35ac52022-05-23 22:33:40 +00002072 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wymanc3324422022-03-24 20:30:57 +00002073 // Always return 1 to indicate present.
2074 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wymanae35ac52022-05-23 22:33:40 +00002075 setMissingToPresentExpects(mockPMBus, mockedUtil);
2076 PMBusExpectations expectations;
2077 setPMBusExpectations(mockPMBus, expectations);
2078 // After reading STATUS_WORD, etc., there will be a READ_VIN check.
2079 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2080 .Times(1)
2081 .WillOnce(Return("206000"));
2082 // Call to analyze() and above expectations to get missing/present and
2083 // good status.
Brandon Wymanc3324422022-03-24 20:30:57 +00002084 psu.analyze();
2085 psu.setupInputHistory();
2086 // After updating to present, and retrying setup, expect inspur-ipsps to
2087 // still not support INPUT_HISTORY.
2088 EXPECT_EQ(psu.hasInputHistory(), false);
2089 }
2090}
2091
2092TEST_F(PowerSupplyTests, UpdateHistory)
2093{
2094 auto bus = sdbusplus::bus::new_default();
2095 PowerSupply psu{bus, PSUInventoryPath, 7,
2096 0x6e, "ibm-cffps", PSUGPIOLineName};
2097 EXPECT_EQ(psu.hasInputHistory(), false);
2098 EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
2099 MockedGPIOInterface* mockPresenceGPIO =
2100 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2101 // Always return 1 to indicate present.
2102 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2103 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2104 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00002105 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2106 // for INPUT_HISTORY will check max_power_out to see if it is
2107 // old/unsupported power supply. Indicate good value, supported.
2108 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2109 .Times(1)
2110 .WillOnce(Return("2000"));
Brandon Wymanc3324422022-03-24 20:30:57 +00002111 PMBusExpectations expectations;
2112 setPMBusExpectations(mockPMBus, expectations);
2113 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2114 .Times(6)
2115 .WillRepeatedly(Return("205000"));
2116 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
2117 // First read after missing/present will have no data.
2118 std::vector<uint8_t> emptyHistory{};
2119 // Second read, after about 30 seconds, should have a record. 5-bytes.
2120 // Sequence Number: 0x00, Average: 0x50 0xf3 (212), Maximum: 0x54 0xf3 (213)
2121 std::vector<uint8_t> firstHistory{0x00, 0x50, 0xf3, 0x54, 0xf3};
2122 // Third read, after about 60 seconds, should have two records, 10-bytes,
2123 // but only reading 5 bytes, so make sure new/next sequence number
2124 std::vector<uint8_t> secondHistory{0x01, 0x54, 0xf3, 0x58, 0xf3};
2125 // Fourth read, 3rd sequence number (0x02).
2126 std::vector<uint8_t> thirdHistory{0x02, 0x54, 0xf3, 0x58, 0xf3};
2127 // Fifth read, out of sequence, clear and insert this one?
2128 std::vector<uint8_t> outseqHistory{0xff, 0x5c, 0xf3, 0x60, 0xf3};
2129 EXPECT_CALL(
2130 mockPMBus,
2131 readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug,
2132 phosphor::power::history::RecordManager::RAW_RECORD_SIZE))
2133 .Times(6)
2134 .WillOnce(Return(emptyHistory))
2135 .WillOnce(Return(firstHistory))
2136 .WillOnce(Return(secondHistory))
2137 .WillOnce(Return(thirdHistory))
2138 .WillOnce(Return(outseqHistory))
2139 .WillOnce(Return(emptyHistory));
2140 // Calling analyze will update the presence, which will setup the input
2141 // history if the power supply went from missing to present.
2142 psu.analyze();
2143 // The ibm-cffps power supply should support input history
2144 EXPECT_EQ(psu.hasInputHistory(), true);
2145 // Usually should have empty buffer right after missing to present.
2146 // Faked that out above with mocked readBinary with emptyHistory data.
2147 EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
2148 // Second run through...
2149 setPMBusExpectations(mockPMBus, expectations);
2150 psu.analyze();
2151 EXPECT_EQ(psu.hasInputHistory(), true);
2152 EXPECT_EQ(psu.getNumInputHistoryRecords(), 1);
2153 // Third run through
2154 setPMBusExpectations(mockPMBus, expectations);
2155 psu.analyze();
2156 EXPECT_EQ(psu.hasInputHistory(), true);
2157 EXPECT_EQ(psu.getNumInputHistoryRecords(), 2);
2158 // Fourth run through. Up to 3 records now?
2159 setPMBusExpectations(mockPMBus, expectations);
2160 psu.analyze();
2161 EXPECT_EQ(psu.hasInputHistory(), true);
2162 EXPECT_EQ(psu.getNumInputHistoryRecords(), 3);
2163 // Out of sequencer, reset, insert new one.
2164 setPMBusExpectations(mockPMBus, expectations);
2165 psu.analyze();
2166 EXPECT_EQ(psu.hasInputHistory(), true);
2167 EXPECT_EQ(psu.getNumInputHistoryRecords(), 1);
2168 // Empty one after last one good. Reset/clear.
2169 setPMBusExpectations(mockPMBus, expectations);
2170 psu.analyze();
2171 EXPECT_EQ(psu.hasInputHistory(), true);
2172 EXPECT_EQ(psu.getNumInputHistoryRecords(), 0);
2173}
Brandon Wyman18a24d92022-04-19 22:48:34 +00002174
2175TEST_F(PowerSupplyTests, IsSyncHistoryRequired)
2176{
2177 auto bus = sdbusplus::bus::new_default();
2178 PowerSupply psu{bus, PSUInventoryPath, 8,
2179 0x6f, "ibm-cffps", PSUGPIOLineName};
2180 EXPECT_EQ(psu.hasInputHistory(), false);
2181 EXPECT_EQ(psu.isSyncHistoryRequired(), false);
2182 MockedGPIOInterface* mockPresenceGPIO =
2183 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2184 // Always return 1 to indicate present.
2185 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2186 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2187 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00002188 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2189 // for INPUT_HISTORY will check max_power_out to see if it is
2190 // old/unsupported power supply. Indicate good value, supported.
2191 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2192 .Times(1)
2193 .WillOnce(Return("2000"));
Brandon Wyman18a24d92022-04-19 22:48:34 +00002194 PMBusExpectations expectations;
2195 setPMBusExpectations(mockPMBus, expectations);
2196 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2197 .Times(1)
2198 .WillRepeatedly(Return("205000"));
2199 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
2200 psu.analyze();
2201 // The ibm-cffps power supply should support input history
2202 EXPECT_EQ(psu.hasInputHistory(), true);
2203 // Missing -> Present requires history sync
2204 EXPECT_EQ(psu.isSyncHistoryRequired(), true);
2205 psu.clearSyncHistoryRequired();
2206 EXPECT_EQ(psu.isSyncHistoryRequired(), false);
2207}