blob: 539f2fba685f18b70716f5b61a2c1972b0caa501 [file] [log] [blame]
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001#include "../power_supply.hpp"
2#include "mock.hpp"
3
4#include <xyz/openbmc_project/Common/Device/error.hpp>
5#include <xyz/openbmc_project/Common/error.hpp>
6
7#include <gmock/gmock.h>
8#include <gtest/gtest.h>
9
10using namespace phosphor::power::psu;
11using namespace phosphor::pmbus;
12
13using ::testing::_;
Brandon Wyman59a35792020-06-04 12:37:40 -050014using ::testing::Args;
Brandon Wyman3f1242f2020-01-28 13:11:25 -060015using ::testing::Assign;
16using ::testing::DoAll;
Brandon Wyman59a35792020-06-04 12:37:40 -050017using ::testing::ElementsAre;
18using ::testing::NotNull;
Brandon Wyman3f1242f2020-01-28 13:11:25 -060019using ::testing::Return;
20using ::testing::StrEq;
21
22static auto PSUInventoryPath = "/xyz/bmc/inv/sys/chassis/board/powersupply0";
B. J. Wyman681b2a32021-04-20 22:31:22 +000023static auto PSUGPIOLineName = "presence-ps0";
Brandon Wyman3f1242f2020-01-28 13:11:25 -060024
Brandon Wymanb654c612021-11-05 23:24:51 +000025struct PMBusExpectations
26{
27 uint16_t statusWordValue{0x0000};
28 uint8_t statusInputValue{0x00};
29 uint8_t statusMFRValue{0x00};
30 uint8_t statusCMLValue{0x00};
31 uint8_t statusVOUTValue{0x00};
Brandon Wymanb10b3be2021-11-09 22:12:15 +000032 uint8_t statusIOUTValue{0x00};
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +000033 uint8_t statusFans12Value{0x00};
Brandon Wyman96893a42021-11-05 19:56:57 +000034 uint8_t statusTempValue{0x00};
Brandon Wymanb654c612021-11-05 23:24:51 +000035};
36
Brandon Wyman8da35c52021-10-28 22:45:08 +000037// Helper function to setup expectations for various STATUS_* commands
Brandon Wymanb654c612021-11-05 23:24:51 +000038void setPMBusExpectations(MockedPMBus& mockPMBus,
39 const PMBusExpectations& expectations)
Brandon Wyman8da35c52021-10-28 22:45:08 +000040{
41 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
42 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000043 .WillOnce(Return(expectations.statusWordValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000044
Brandon Wymanb654c612021-11-05 23:24:51 +000045 if (expectations.statusWordValue != 0)
Brandon Wyman8da35c52021-10-28 22:45:08 +000046 {
47 // If fault bits are on in STATUS_WORD, there will also be a read of
Brandon Wyman96893a42021-11-05 19:56:57 +000048 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and
49 // STATUS_TEMPERATURE.
Brandon Wyman8da35c52021-10-28 22:45:08 +000050 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
51 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000052 .WillOnce(Return(expectations.statusInputValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000053 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _))
54 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000055 .WillOnce(Return(expectations.statusMFRValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000056 EXPECT_CALL(mockPMBus, read(STATUS_CML, _))
57 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000058 .WillOnce(Return(expectations.statusCMLValue));
Brandon Wyman6710ba22021-10-27 17:39:31 +000059 // Page will need to be set to 0 to read STATUS_VOUT.
60 EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0))
61 .Times(1)
62 .WillOnce(Return("status0_vout"));
63 EXPECT_CALL(mockPMBus, read("status0_vout", _))
64 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000065 .WillOnce(Return(expectations.statusVOUTValue));
Brandon Wymanb10b3be2021-11-09 22:12:15 +000066 EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _))
67 .Times(1)
68 .WillOnce(Return(expectations.statusIOUTValue));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +000069 EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _))
70 .Times(1)
71 .WillOnce(Return(expectations.statusFans12Value));
Brandon Wyman96893a42021-11-05 19:56:57 +000072 EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _))
73 .Times(1)
74 .WillOnce(Return(expectations.statusTempValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000075 }
76}
77
Brandon Wyman3f1242f2020-01-28 13:11:25 -060078class PowerSupplyTests : public ::testing::Test
79{
80 public:
81 PowerSupplyTests() :
82 mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
83 {
84 ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
85 }
86
87 ~PowerSupplyTests() override
88 {
89 freeUtils();
90 }
91
92 const MockedUtil& mockedUtil;
93};
94
Brandon Wyman391a0692021-12-08 23:28:18 +000095// Helper function for when a power supply goes from missing to present.
96void setMissingToPresentExpects(MockedPMBus& pmbus, const MockedUtil& util)
97{
98 // Call to analyze() will update to present, that will trigger updating
99 // to the correct/latest HWMON directory, in case it changes.
100 EXPECT_CALL(pmbus, findHwmonDir());
101 // Presence change from missing to present will trigger write to
102 // ON_OFF_CONFIG.
103 EXPECT_CALL(pmbus, writeBinary(ON_OFF_CONFIG, _, _));
104 // Presence change from missing to present will trigger in1_input read
105 // in an attempt to get CLEAR_FAULTS called.
106 EXPECT_CALL(pmbus, read(READ_VIN, _)).Times(1).WillOnce(Return(1));
107 // Missing/present call will update Presence in inventory.
108 // EXPECT_CALL(mockedUtil, setPresence(_, _, true, _));
109 EXPECT_CALL(util, setPresence(_, _, true, _));
110}
111
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600112TEST_F(PowerSupplyTests, Constructor)
113{
114 /**
115 * @param[in] invpath - String for inventory path to use
116 * @param[in] i2cbus - The bus number this power supply is on
117 * @param[in] i2caddr - The 16-bit I2C address of the power supply
B. J. Wyman681b2a32021-04-20 22:31:22 +0000118 * @param[in] gpioLineName - The string for the gpio-line-name to read for
119 * presence.
120 * @param[in] bindDelay - Time in milliseconds to delay binding the device
121 * driver after seeing the presence line go active.
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600122 */
123 auto bus = sdbusplus::bus::new_default();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600124
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500125 // Try where inventory path is empty, constructor should fail.
126 try
127 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000128 auto psu =
129 std::make_unique<PowerSupply>(bus, "", 3, 0x68, PSUGPIOLineName);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500130 ADD_FAILURE() << "Should not have reached this line.";
131 }
132 catch (const std::invalid_argument& e)
133 {
134 EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
135 }
136 catch (...)
137 {
138 ADD_FAILURE() << "Should not have caught exception.";
139 }
140
B. J. Wyman681b2a32021-04-20 22:31:22 +0000141 // TODO: Try invalid i2c address?
142
143 // Try where gpioLineName is empty.
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500144 try
145 {
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500146 auto psu =
B. J. Wyman681b2a32021-04-20 22:31:22 +0000147 std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, "");
148 ADD_FAILURE()
149 << "Should not have reached this line. Invalid gpioLineName.";
150 }
151 catch (const std::invalid_argument& e)
152 {
153 EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
154 }
155 catch (...)
156 {
157 ADD_FAILURE() << "Should not have caught exception.";
158 }
159
160 // Test with valid arguments
161 // NOT using D-Bus inventory path for presence.
162 try
163 {
164 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
165 PSUGPIOLineName);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500166
167 EXPECT_EQ(psu->isPresent(), false);
168 EXPECT_EQ(psu->isFaulted(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000169 EXPECT_EQ(psu->hasCommFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500170 EXPECT_EQ(psu->hasInputFault(), false);
171 EXPECT_EQ(psu->hasMFRFault(), false);
172 EXPECT_EQ(psu->hasVINUVFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000173 EXPECT_EQ(psu->hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000174 EXPECT_EQ(psu->hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000175 EXPECT_EQ(psu->hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000176 EXPECT_EQ(psu->hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000177 EXPECT_EQ(psu->hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000178 EXPECT_EQ(psu->hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000179 EXPECT_EQ(psu->hasPSKillFault(), false);
180 EXPECT_EQ(psu->hasPS12VcsFault(), false);
181 EXPECT_EQ(psu->hasPSCS12VFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500182 }
183 catch (...)
184 {
185 ADD_FAILURE() << "Should not have caught exception.";
186 }
B. J. Wyman681b2a32021-04-20 22:31:22 +0000187
188 // Test with valid arguments
189 // TODO: Using D-Bus inventory path for presence.
190 try
191 {
192 // FIXME: How do I get that presenceGPIO.read() in the startup to throw
193 // an exception?
194
195 // EXPECT_CALL(mockedUtil, getPresence(_,
196 // StrEq(PSUInventoryPath)))
197 // .Times(1);
198 }
199 catch (...)
200 {
201 ADD_FAILURE() << "Should not have caught exception.";
202 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600203}
204
205TEST_F(PowerSupplyTests, Analyze)
206{
207 auto bus = sdbusplus::bus::new_default();
208
Brandon Wymanb654c612021-11-05 23:24:51 +0000209 {
210 // If I default to reading the GPIO, I will NOT expect a call to
211 // getPresence().
B. J. Wyman681b2a32021-04-20 22:31:22 +0000212
Brandon Wymanb654c612021-11-05 23:24:51 +0000213 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
214 MockedGPIOInterface* mockPresenceGPIO =
215 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
216 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000217
Brandon Wymanb654c612021-11-05 23:24:51 +0000218 psu.analyze();
219 // By default, nothing should change.
220 EXPECT_EQ(psu.isPresent(), false);
221 EXPECT_EQ(psu.isFaulted(), false);
222 EXPECT_EQ(psu.hasInputFault(), false);
223 EXPECT_EQ(psu.hasMFRFault(), false);
224 EXPECT_EQ(psu.hasVINUVFault(), false);
225 EXPECT_EQ(psu.hasCommFault(), false);
226 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000227 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000228 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000229 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000230 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000231 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000232 EXPECT_EQ(psu.hasPSKillFault(), false);
233 EXPECT_EQ(psu.hasPS12VcsFault(), false);
234 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000235 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600236
B. J. Wyman681b2a32021-04-20 22:31:22 +0000237 PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
238 // In order to get the various faults tested, the power supply needs to
239 // be present in order to read from the PMBus device(s).
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000240 MockedGPIOInterface* mockPresenceGPIO2 =
241 static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000242 // Always return 1 to indicate present.
243 // Each analyze() call will trigger a read of the presence GPIO.
244 EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000245 EXPECT_EQ(psu2.isPresent(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600246
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600247 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000248 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600249
Brandon Wymanb654c612021-11-05 23:24:51 +0000250 // STATUS_WORD INPUT fault.
251 {
252 // Start with STATUS_WORD 0x0000. Powered on, no faults.
253 // Set expectations for a no fault
254 PMBusExpectations expectations;
255 setPMBusExpectations(mockPMBus, expectations);
256 psu2.analyze();
257 EXPECT_EQ(psu2.isPresent(), true);
258 EXPECT_EQ(psu2.isFaulted(), false);
259 EXPECT_EQ(psu2.hasInputFault(), false);
260 EXPECT_EQ(psu2.hasMFRFault(), false);
261 EXPECT_EQ(psu2.hasVINUVFault(), false);
262 EXPECT_EQ(psu2.hasCommFault(), false);
263 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000264 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000265 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000266 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000267 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000268 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000269 EXPECT_EQ(psu2.hasPSKillFault(), false);
270 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
271 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000272
273 // Update expectations for STATUS_WORD input fault/warn
Brandon Wyman96893a42021-11-05 19:56:57 +0000274 // STATUS_INPUT fault bits ... on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000275 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
276 expectations.statusInputValue = 0x38;
277 setPMBusExpectations(mockPMBus, expectations);
278 psu2.analyze();
279 EXPECT_EQ(psu2.isPresent(), true);
280 EXPECT_EQ(psu2.isFaulted(), true);
281 EXPECT_EQ(psu2.hasInputFault(), true);
282 EXPECT_EQ(psu2.hasMFRFault(), false);
283 EXPECT_EQ(psu2.hasVINUVFault(), false);
284 EXPECT_EQ(psu2.hasCommFault(), false);
285 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000286 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000287 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000288 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000289 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000290 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000291 EXPECT_EQ(psu2.hasPSKillFault(), false);
292 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
293 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000294 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600295
296 // STATUS_WORD INPUT/UV fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000297 {
298 // First need it to return good status, then the fault
299 PMBusExpectations expectations;
300 setPMBusExpectations(mockPMBus, expectations);
301 psu2.analyze();
302 // Now set fault bits in STATUS_WORD
303 expectations.statusWordValue =
304 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
305 // STATUS_INPUT fault bits ... on.
306 expectations.statusInputValue = 0x38;
307 setPMBusExpectations(mockPMBus, expectations);
308 psu2.analyze();
309 EXPECT_EQ(psu2.isPresent(), true);
310 EXPECT_EQ(psu2.isFaulted(), true);
311 EXPECT_EQ(psu2.hasInputFault(), true);
312 EXPECT_EQ(psu2.hasMFRFault(), false);
313 EXPECT_EQ(psu2.hasVINUVFault(), true);
314 EXPECT_EQ(psu2.hasCommFault(), false);
315 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000316 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000317 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000318 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000319 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000320 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000321 EXPECT_EQ(psu2.hasPSKillFault(), false);
322 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
323 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000324 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600325
326 // STATUS_WORD MFR fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000327 {
328 // First need it to return good status, then the fault
329 PMBusExpectations expectations;
330 setPMBusExpectations(mockPMBus, expectations);
331 psu2.analyze();
332 // Now STATUS_WORD with MFR fault bit on.
333 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
334 // STATUS_MFR bits on.
335 expectations.statusMFRValue = 0xFF;
336 setPMBusExpectations(mockPMBus, expectations);
337 psu2.analyze();
338 EXPECT_EQ(psu2.isPresent(), true);
339 EXPECT_EQ(psu2.isFaulted(), true);
340 EXPECT_EQ(psu2.hasInputFault(), false);
341 EXPECT_EQ(psu2.hasMFRFault(), true);
342 EXPECT_EQ(psu2.hasVINUVFault(), false);
343 EXPECT_EQ(psu2.hasCommFault(), false);
344 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000345 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000346 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000347 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000348 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000349 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000350 EXPECT_EQ(psu2.hasPSKillFault(), true);
351 EXPECT_EQ(psu2.hasPS12VcsFault(), true);
352 EXPECT_EQ(psu2.hasPSCS12VFault(), true);
Brandon Wymanb654c612021-11-05 23:24:51 +0000353 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600354
Brandon Wyman96893a42021-11-05 19:56:57 +0000355 // Temperature fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000356 {
357 // First STATUS_WORD with no bits set, then with temperature fault.
358 PMBusExpectations expectations;
359 setPMBusExpectations(mockPMBus, expectations);
360 psu2.analyze();
361 // STATUS_WORD with temperature fault bit on.
362 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
Brandon Wyman96893a42021-11-05 19:56:57 +0000363 // STATUS_TEMPERATURE with fault bit(s) on.
364 expectations.statusTempValue = 0x10;
Brandon Wymanb654c612021-11-05 23:24:51 +0000365 setPMBusExpectations(mockPMBus, expectations);
366 psu2.analyze();
367 EXPECT_EQ(psu2.isPresent(), true);
Brandon Wyman96893a42021-11-05 19:56:57 +0000368 EXPECT_EQ(psu2.isFaulted(), true);
Brandon Wymanb654c612021-11-05 23:24:51 +0000369 EXPECT_EQ(psu2.hasInputFault(), false);
370 EXPECT_EQ(psu2.hasMFRFault(), false);
371 EXPECT_EQ(psu2.hasVINUVFault(), false);
372 EXPECT_EQ(psu2.hasCommFault(), false);
373 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000374 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000375 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000376 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000377 EXPECT_EQ(psu2.hasTempFault(), true);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000378 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000379 EXPECT_EQ(psu2.hasPSKillFault(), false);
380 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
381 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000382 }
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000383
384 // CML fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000385 {
386 // First STATUS_WORD wit no bits set, then with CML fault.
387 PMBusExpectations expectations;
388 setPMBusExpectations(mockPMBus, expectations);
389 psu2.analyze();
390 // STATUS_WORD with CML fault bit on.
391 expectations.statusWordValue = (status_word::CML_FAULT);
392 // Turn on STATUS_CML fault bit(s)
393 expectations.statusCMLValue = 0xFF;
394 setPMBusExpectations(mockPMBus, expectations);
395 psu2.analyze();
396 EXPECT_EQ(psu2.isPresent(), true);
397 EXPECT_EQ(psu2.isFaulted(), true);
398 EXPECT_EQ(psu2.hasInputFault(), false);
399 EXPECT_EQ(psu2.hasMFRFault(), false);
400 EXPECT_EQ(psu2.hasVINUVFault(), false);
401 EXPECT_EQ(psu2.hasCommFault(), true);
402 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000403 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000404 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000405 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000406 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000407 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000408 EXPECT_EQ(psu2.hasPSKillFault(), false);
409 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
410 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000411 }
Brandon Wyman6710ba22021-10-27 17:39:31 +0000412
413 // VOUT_OV_FAULT fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000414 {
415 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
416 PMBusExpectations expectations;
417 setPMBusExpectations(mockPMBus, expectations);
418 psu2.analyze();
419 // STATUS_WORD with VOUT/VOUT_OV fault.
420 expectations.statusWordValue =
421 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
422 // Turn on STATUS_VOUT fault bit(s)
423 expectations.statusVOUTValue = 0xA0;
Brandon Wyman96893a42021-11-05 19:56:57 +0000424 // STATUS_TEMPERATURE don't care (default)
Brandon Wymanb654c612021-11-05 23:24:51 +0000425 setPMBusExpectations(mockPMBus, expectations);
426 psu2.analyze();
427 EXPECT_EQ(psu2.isPresent(), true);
428 EXPECT_EQ(psu2.isFaulted(), true);
429 EXPECT_EQ(psu2.hasInputFault(), false);
430 EXPECT_EQ(psu2.hasMFRFault(), false);
431 EXPECT_EQ(psu2.hasVINUVFault(), false);
432 EXPECT_EQ(psu2.hasCommFault(), false);
433 EXPECT_EQ(psu2.hasVoutOVFault(), true);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000434 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000435 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000436 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000437 EXPECT_EQ(psu2.hasTempFault(), false);
438 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000439 EXPECT_EQ(psu2.hasPSKillFault(), false);
440 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
441 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000442 }
443
444 // IOUT_OC_FAULT fault
445 {
446 // First STATUS_WORD with no bits set, then with IOUT_OC fault.
447 PMBusExpectations expectations;
448 setPMBusExpectations(mockPMBus, expectations);
449 psu2.analyze();
450 // STATUS_WORD with IOUT_OC fault.
451 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
452 // Turn on STATUS_IOUT fault bit(s)
453 expectations.statusIOUTValue = 0x88;
454 setPMBusExpectations(mockPMBus, expectations);
455 psu2.analyze();
456 EXPECT_EQ(psu2.isPresent(), true);
457 EXPECT_EQ(psu2.isFaulted(), true);
458 EXPECT_EQ(psu2.hasInputFault(), false);
459 EXPECT_EQ(psu2.hasMFRFault(), false);
460 EXPECT_EQ(psu2.hasVINUVFault(), false);
461 EXPECT_EQ(psu2.hasCommFault(), false);
462 EXPECT_EQ(psu2.hasVoutOVFault(), false);
463 EXPECT_EQ(psu2.hasIoutOCFault(), true);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000464 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000465 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000466 EXPECT_EQ(psu2.hasTempFault(), false);
467 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000468 EXPECT_EQ(psu2.hasPSKillFault(), false);
469 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
470 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000471 }
472
473 // VOUT_UV_FAULT
474 {
475 // First STATUS_WORD with no bits set, then with VOUT fault.
476 PMBusExpectations expectations;
477 setPMBusExpectations(mockPMBus, expectations);
478 psu2.analyze();
479 // Change STATUS_WORD to indicate VOUT fault.
480 expectations.statusWordValue = (status_word::VOUT_FAULT);
481 // Turn on STATUS_VOUT fault bit(s)
482 expectations.statusVOUTValue = 0x30;
483 setPMBusExpectations(mockPMBus, expectations);
484 psu2.analyze();
485 EXPECT_EQ(psu2.isPresent(), true);
486 EXPECT_EQ(psu2.isFaulted(), true);
487 EXPECT_EQ(psu2.hasInputFault(), false);
488 EXPECT_EQ(psu2.hasMFRFault(), false);
489 EXPECT_EQ(psu2.hasVINUVFault(), false);
490 EXPECT_EQ(psu2.hasCommFault(), false);
491 EXPECT_EQ(psu2.hasVoutOVFault(), false);
492 EXPECT_EQ(psu2.hasIoutOCFault(), false);
493 EXPECT_EQ(psu2.hasVoutUVFault(), true);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000494 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000495 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000496 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000497 EXPECT_EQ(psu2.hasPSKillFault(), false);
498 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
499 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000500 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600501
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000502 // Fan fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000503 {
504 // First STATUS_WORD with no bits set, then with fan fault.
505 PMBusExpectations expectations;
506 setPMBusExpectations(mockPMBus, expectations);
507 psu2.analyze();
508 expectations.statusWordValue = (status_word::FAN_FAULT);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000509 // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
510 expectations.statusFans12Value = 0xA0;
Brandon Wymanb654c612021-11-05 23:24:51 +0000511 setPMBusExpectations(mockPMBus, expectations);
512 psu2.analyze();
513 EXPECT_EQ(psu2.isPresent(), true);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000514 EXPECT_EQ(psu2.isFaulted(), true);
Brandon Wymanb654c612021-11-05 23:24:51 +0000515 EXPECT_EQ(psu2.hasInputFault(), false);
516 EXPECT_EQ(psu2.hasMFRFault(), false);
517 EXPECT_EQ(psu2.hasVINUVFault(), false);
518 EXPECT_EQ(psu2.hasCommFault(), false);
519 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000520 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000521 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000522 EXPECT_EQ(psu2.hasFanFault(), true);
Brandon Wyman96893a42021-11-05 19:56:57 +0000523 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000524 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000525 EXPECT_EQ(psu2.hasPSKillFault(), false);
526 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
527 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000528 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000529
Brandon Wyman06ca4592021-12-06 22:52:23 +0000530 // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000531 {
Brandon Wyman2916ea52021-11-06 03:31:18 +0000532 // First STATUS_WORD with no bits set.
533 PMBusExpectations expectations;
534 setPMBusExpectations(mockPMBus, expectations);
535 psu2.analyze();
536 EXPECT_EQ(psu2.isFaulted(), false);
537 // POWER_GOOD# inactive, and OFF bit on.
538 expectations.statusWordValue =
539 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
Brandon Wyman06ca4592021-12-06 22:52:23 +0000540 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
541 {
542 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
543 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
544 setPMBusExpectations(mockPMBus, expectations);
545 psu2.analyze();
546 EXPECT_EQ(psu2.isPresent(), true);
547 if (x < DEGLITCH_LIMIT)
548 {
549 EXPECT_EQ(psu2.isFaulted(), false);
550 }
551 else
552 {
553 EXPECT_EQ(psu2.isFaulted(), true);
554 }
555 EXPECT_EQ(psu2.hasInputFault(), false);
556 EXPECT_EQ(psu2.hasMFRFault(), false);
557 EXPECT_EQ(psu2.hasVINUVFault(), false);
558 EXPECT_EQ(psu2.hasCommFault(), false);
559 EXPECT_EQ(psu2.hasVoutOVFault(), false);
560 EXPECT_EQ(psu2.hasVoutUVFault(), false);
561 EXPECT_EQ(psu2.hasIoutOCFault(), false);
562 EXPECT_EQ(psu2.hasFanFault(), false);
563 EXPECT_EQ(psu2.hasTempFault(), false);
564 if (x < DEGLITCH_LIMIT)
565 {
566 EXPECT_EQ(psu2.hasPgoodFault(), false);
567 }
568 else
569 {
570 EXPECT_EQ(psu2.hasPgoodFault(), true);
571 }
572 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000573 }
574
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600575 // TODO: ReadFailure
576}
577
Brandon Wyman59a35792020-06-04 12:37:40 -0500578TEST_F(PowerSupplyTests, OnOffConfig)
579{
580 auto bus = sdbusplus::bus::new_default();
581 uint8_t data = 0x15;
582
583 // Test where PSU is NOT present
584 try
585 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000586 // Assume GPIO presence, not inventory presence?
587 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
588
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000589 MockedGPIOInterface* mockPresenceGPIO =
590 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000591 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
Brandon Wyman59a35792020-06-04 12:37:40 -0500592 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000593 // Constructor should set initial presence, default read returns 0.
Brandon Wyman59a35792020-06-04 12:37:40 -0500594 // If it is not present, I should not be trying to write to it.
595 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
596 psu.onOffConfig(data);
597 }
598 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000599 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500600
601 // Test where PSU is present
602 try
603 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000604 // Assume GPIO presence, not inventory presence?
605 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000606 MockedGPIOInterface* mockPresenceGPIO =
607 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman391a0692021-12-08 23:28:18 +0000608 // There will potentially be multiple calls, we want it to continue
609 // returning 1 for the GPIO read to keep the power supply present.
610 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman59a35792020-06-04 12:37:40 -0500611 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000612 setMissingToPresentExpects(mockPMBus, mockedUtil);
613 // If I am calling analyze(), I should probably give it good data.
614 // STATUS_WORD 0x0000 is powered on, no faults.
615 PMBusExpectations expectations;
616 setPMBusExpectations(mockPMBus, expectations);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000617 psu.analyze();
Brandon Wyman391a0692021-12-08 23:28:18 +0000618 // I definitely should be writting ON_OFF_CONFIG if I call the function
619 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
620 Type::HwmonDeviceDebug))
Brandon Wyman59a35792020-06-04 12:37:40 -0500621 .Times(1);
622 psu.onOffConfig(data);
623 }
624 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000625 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500626}
627
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600628TEST_F(PowerSupplyTests, ClearFaults)
629{
630 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000631 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000632 MockedGPIOInterface* mockPresenceGPIO =
633 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000634 // Always return 1 to indicate present.
635 // Each analyze() call will trigger a read of the presence GPIO.
636 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000637 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000638 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000639 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000640 PMBusExpectations expectations;
641 setPMBusExpectations(mockPMBus, expectations);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000642 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600643 EXPECT_EQ(psu.isPresent(), true);
644 EXPECT_EQ(psu.isFaulted(), false);
645 EXPECT_EQ(psu.hasInputFault(), false);
646 EXPECT_EQ(psu.hasMFRFault(), false);
647 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000648 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000649 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000650 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000651 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000652 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000653 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000654 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000655 EXPECT_EQ(psu.hasPSKillFault(), false);
656 EXPECT_EQ(psu.hasPS12VcsFault(), false);
657 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000658
Brandon Wymanf07bc792021-10-12 19:00:35 +0000659 // STATUS_WORD with fault bits galore!
Brandon Wymanb654c612021-11-05 23:24:51 +0000660 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000661 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000662 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000663 // STATUS_MFR_SPEFIC with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000664 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000665 // STATUS_CML with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000666 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000667 // STATUS_VOUT with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000668 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000669 // STATUS_IOUT with bits on.
670 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000671 // STATUS_FANS_1_2 with bits on.
672 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000673 // STATUS_TEMPERATURE with bits on.
674 expectations.statusTempValue = 0xFF;
Brandon Wymanb654c612021-11-05 23:24:51 +0000675 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600676 psu.analyze();
677 EXPECT_EQ(psu.isPresent(), true);
678 EXPECT_EQ(psu.isFaulted(), true);
679 EXPECT_EQ(psu.hasInputFault(), true);
680 EXPECT_EQ(psu.hasMFRFault(), true);
681 EXPECT_EQ(psu.hasVINUVFault(), true);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000682 EXPECT_EQ(psu.hasCommFault(), true);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000683 EXPECT_EQ(psu.hasVoutOVFault(), true);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000684 EXPECT_EQ(psu.hasIoutOCFault(), true);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000685 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
686 // Rely on HasVoutUVFault() to verify this sets and clears.
687 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000688 EXPECT_EQ(psu.hasFanFault(), true);
Brandon Wyman96893a42021-11-05 19:56:57 +0000689 EXPECT_EQ(psu.hasTempFault(), true);
Brandon Wyman06ca4592021-12-06 22:52:23 +0000690 // pgoodFault is deglitched up to DEGLITCH_LIMIT
691 EXPECT_EQ(psu.hasPgoodFault(), false);
692 setPMBusExpectations(mockPMBus, expectations);
693 psu.analyze();
694 EXPECT_EQ(psu.hasPgoodFault(), false);
695 setPMBusExpectations(mockPMBus, expectations);
696 psu.analyze();
697 // DEGLITCH_LIMIT reached for pgoodFault
Brandon Wyman2916ea52021-11-06 03:31:18 +0000698 EXPECT_EQ(psu.hasPgoodFault(), true);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000699 EXPECT_EQ(psu.hasPSKillFault(), true);
700 EXPECT_EQ(psu.hasPS12VcsFault(), true);
701 EXPECT_EQ(psu.hasPSCS12VFault(), true);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000702
Brandon Wyman391a0692021-12-08 23:28:18 +0000703 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(207000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600704 psu.clearFaults();
705 EXPECT_EQ(psu.isPresent(), true);
706 EXPECT_EQ(psu.isFaulted(), false);
707 EXPECT_EQ(psu.hasInputFault(), false);
708 EXPECT_EQ(psu.hasMFRFault(), false);
709 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000710 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000711 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000712 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000713 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000714 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000715 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000716 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000717 EXPECT_EQ(psu.hasPSKillFault(), false);
718 EXPECT_EQ(psu.hasPS12VcsFault(), false);
719 EXPECT_EQ(psu.hasPSCS12VFault(), false);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000720
721 // TODO: Faults clear on missing/present?
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600722}
723
724TEST_F(PowerSupplyTests, UpdateInventory)
725{
726 auto bus = sdbusplus::bus::new_default();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500727
728 try
729 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000730 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500731 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
732 // If it is not present, I should not be trying to read a string
733 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
734 psu.updateInventory();
735 }
736 catch (...)
737 {
738 ADD_FAILURE() << "Should not have caught exception.";
739 }
740
741 try
742 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000743 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000744 MockedGPIOInterface* mockPresenceGPIO =
745 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000746 // GPIO read return 1 to indicate present.
747 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500748 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000749 setMissingToPresentExpects(mockPMBus, mockedUtil);
750 // STATUS_WORD 0x0000 is powered on, no faults.
751 PMBusExpectations expectations;
752 setPMBusExpectations(mockPMBus, expectations);
753 // Need analyze call to update power supply from missing to present.
754 psu.analyze();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500755 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
756 psu.updateInventory();
757
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500758#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500759 EXPECT_CALL(mockPMBus, readString(_, _))
760 .WillOnce(Return("CCIN"))
761 .WillOnce(Return("PN3456"))
762 .WillOnce(Return("FN3456"))
763 .WillOnce(Return("HEADER"))
764 .WillOnce(Return("SN3456"))
765 .WillOnce(Return("FW3456"));
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500766#endif
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500767 psu.updateInventory();
768 // TODO: D-Bus mocking to verify values stored on D-Bus (???)
769 }
770 catch (...)
771 {
772 ADD_FAILURE() << "Should not have caught exception.";
773 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600774}
775
776TEST_F(PowerSupplyTests, IsPresent)
777{
778 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000779
780 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000781 MockedGPIOInterface* mockPresenceGPIO =
782 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600783 EXPECT_EQ(psu.isPresent(), false);
784
B. J. Wyman681b2a32021-04-20 22:31:22 +0000785 // Change GPIO read to return 1 to indicate present.
786 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +0000787 // Call to analyze() will update to present, that will trigger updating
788 // to the correct/latest HWMON directory, in case it changes.
789 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
790 setMissingToPresentExpects(mockPMBus, mockedUtil);
791 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
792 // Default expectations will be on, no faults.
793 PMBusExpectations expectations;
794 setPMBusExpectations(mockPMBus, expectations);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000795 psu.analyze();
796 EXPECT_EQ(psu.isPresent(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600797}
798
799TEST_F(PowerSupplyTests, IsFaulted)
800{
801 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000802
803 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000804 MockedGPIOInterface* mockPresenceGPIO =
805 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000806 // Always return 1 to indicate present.
807 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +0000808 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
809 setMissingToPresentExpects(mockPMBus, mockedUtil);
810 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
811 // Default expectations will be on, no faults.
812 PMBusExpectations expectations;
813 setPMBusExpectations(mockPMBus, expectations);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000814 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600815 EXPECT_EQ(psu.isFaulted(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000816 // STATUS_WORD with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000817 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000818 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000819 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000820 // STATUS_MFR_SPECIFIC with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000821 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000822 // STATUS_CML with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000823 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000824 // STATUS_VOUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000825 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000826 // STATUS_IOUT with fault bits on.
827 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000828 // STATUS_FANS_1_2 with bits on.
829 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000830 // STATUS_TEMPERATURE with fault bits on.
831 expectations.statusTempValue = 0xFF;
Brandon Wymanb654c612021-11-05 23:24:51 +0000832 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600833 psu.analyze();
834 EXPECT_EQ(psu.isFaulted(), true);
835}
836
837TEST_F(PowerSupplyTests, HasInputFault)
838{
839 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000840
841 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000842 MockedGPIOInterface* mockPresenceGPIO =
843 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000844 // Always return 1 to indicate present.
845 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600846 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000847 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000848 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000849 PMBusExpectations expectations;
850 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600851 psu.analyze();
852 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000853 // STATUS_WORD with input fault/warn on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000854 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000855 // STATUS_INPUT with an input fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000856 expectations.statusInputValue = 0x80;
857 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600858 psu.analyze();
859 EXPECT_EQ(psu.hasInputFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000860 // STATUS_WORD with no bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000861 expectations.statusWordValue = 0;
862 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600863 psu.analyze();
864 EXPECT_EQ(psu.hasInputFault(), false);
865}
866
867TEST_F(PowerSupplyTests, HasMFRFault)
868{
869 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000870
871 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000872 MockedGPIOInterface* mockPresenceGPIO =
873 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000874 // Always return 1 to indicate present.
875 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600876 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000877 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000878 // First return STATUS_WORD with no bits on.
Brandon Wyman8da35c52021-10-28 22:45:08 +0000879 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000880 PMBusExpectations expectations;
881 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600882 psu.analyze();
883 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000884 // Next return STATUS_WORD with MFR fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000885 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000886 // STATUS_MFR_SPEFIC with bit(s) on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000887 expectations.statusMFRValue = 0xFF;
888 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600889 psu.analyze();
890 EXPECT_EQ(psu.hasMFRFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000891 // Back to no bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +0000892 expectations.statusWordValue = 0;
893 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600894 psu.analyze();
895 EXPECT_EQ(psu.hasMFRFault(), false);
896}
897
898TEST_F(PowerSupplyTests, HasVINUVFault)
899{
900 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000901
902 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000903 MockedGPIOInterface* mockPresenceGPIO =
904 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000905 // Always return 1 to indicate present.
906 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600907 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000908 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000909 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000910 PMBusExpectations expectations;
911 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600912 psu.analyze();
913 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000914 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000915 expectations.statusWordValue = (status_word::VIN_UV_FAULT);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000916 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
917 // Figure 16, and assume bits on in STATUS_INPUT.
Brandon Wymanb654c612021-11-05 23:24:51 +0000918 expectations.statusInputValue = 0x18;
919 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600920 psu.analyze();
921 EXPECT_EQ(psu.hasVINUVFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000922 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +0000923 expectations.statusWordValue = 0;
924 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600925 psu.analyze();
926 EXPECT_EQ(psu.hasVINUVFault(), false);
927}
Brandon Wyman6710ba22021-10-27 17:39:31 +0000928
929TEST_F(PowerSupplyTests, HasVoutOVFault)
930{
931 auto bus = sdbusplus::bus::new_default();
932
933 PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName};
934 MockedGPIOInterface* mockPresenceGPIO =
935 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
936 // Always return 1 to indicate present.
937 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman6710ba22021-10-27 17:39:31 +0000938 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000939 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000940 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000941 PMBusExpectations expectations;
942 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000943 psu.analyze();
944 EXPECT_EQ(psu.hasVoutOVFault(), false);
945 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000946 expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000947 // STATUS_VOUT fault bit(s)
Brandon Wymanb654c612021-11-05 23:24:51 +0000948 expectations.statusVOUTValue = 0x80;
Brandon Wyman96893a42021-11-05 19:56:57 +0000949 // STATUS_TEMPERATURE default.
Brandon Wymanb654c612021-11-05 23:24:51 +0000950 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000951 psu.analyze();
952 EXPECT_EQ(psu.hasVoutOVFault(), true);
953 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +0000954 expectations.statusWordValue = 0;
955 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000956 psu.analyze();
957 EXPECT_EQ(psu.hasVoutOVFault(), false);
958}
Brandon Wyman96893a42021-11-05 19:56:57 +0000959
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000960TEST_F(PowerSupplyTests, HasIoutOCFault)
961{
962 auto bus = sdbusplus::bus::new_default();
963
964 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
965 MockedGPIOInterface* mockPresenceGPIO =
966 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
967 // Always return 1 to indicate present.
968 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000969 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000970 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000971 // STATUS_WORD 0x0000 is powered on, no faults.
972 PMBusExpectations expectations;
973 setPMBusExpectations(mockPMBus, expectations);
974 psu.analyze();
975 EXPECT_EQ(psu.hasIoutOCFault(), false);
976 // Turn fault on.
977 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
978 // STATUS_IOUT fault bit(s)
979 expectations.statusIOUTValue = 0x88;
980 setPMBusExpectations(mockPMBus, expectations);
981 psu.analyze();
982 EXPECT_EQ(psu.hasIoutOCFault(), true);
983 // Back to no fault bits on in STATUS_WORD
984 expectations.statusWordValue = 0;
985 setPMBusExpectations(mockPMBus, expectations);
986 psu.analyze();
987 EXPECT_EQ(psu.hasIoutOCFault(), false);
988}
989
Brandon Wyman2cf46942021-10-28 19:09:16 +0000990TEST_F(PowerSupplyTests, HasVoutUVFault)
991{
992 auto bus = sdbusplus::bus::new_default();
993
994 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
995 MockedGPIOInterface* mockPresenceGPIO =
996 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
997 // Always return 1 to indicate present.
998 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2cf46942021-10-28 19:09:16 +0000999 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001000 setMissingToPresentExpects(mockPMBus, mockedUtil);
1001 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wyman2cf46942021-10-28 19:09:16 +00001002 PMBusExpectations expectations;
1003 setPMBusExpectations(mockPMBus, expectations);
1004 psu.analyze();
1005 EXPECT_EQ(psu.hasVoutUVFault(), false);
1006 // Turn fault on.
1007 expectations.statusWordValue = (status_word::VOUT_FAULT);
1008 // STATUS_VOUT fault bit(s)
1009 expectations.statusVOUTValue = 0x30;
1010 setPMBusExpectations(mockPMBus, expectations);
1011 psu.analyze();
1012 EXPECT_EQ(psu.hasVoutUVFault(), true);
1013 // Back to no fault bits on in STATUS_WORD
1014 expectations.statusWordValue = 0;
1015 setPMBusExpectations(mockPMBus, expectations);
1016 psu.analyze();
1017 EXPECT_EQ(psu.hasVoutUVFault(), false);
1018}
1019
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001020TEST_F(PowerSupplyTests, HasFanFault)
1021{
1022 auto bus = sdbusplus::bus::new_default();
1023
1024 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
1025 MockedGPIOInterface* mockPresenceGPIO =
1026 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1027 // Always return 1 to indicate present.
1028 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001029 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001030 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001031 // STATUS_WORD 0x0000 is powered on, no faults.
1032 PMBusExpectations expectations;
1033 setPMBusExpectations(mockPMBus, expectations);
1034 psu.analyze();
1035 EXPECT_EQ(psu.hasFanFault(), false);
1036 // Turn fault on.
1037 expectations.statusWordValue = (status_word::FAN_FAULT);
1038 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
1039 expectations.statusFans12Value = 0x80;
1040 setPMBusExpectations(mockPMBus, expectations);
1041 psu.analyze();
1042 EXPECT_EQ(psu.hasFanFault(), true);
1043 // Back to no fault bits on in STATUS_WORD
1044 expectations.statusWordValue = 0;
1045 setPMBusExpectations(mockPMBus, expectations);
1046 psu.analyze();
1047 EXPECT_EQ(psu.hasFanFault(), false);
1048}
1049
Brandon Wyman96893a42021-11-05 19:56:57 +00001050TEST_F(PowerSupplyTests, HasTempFault)
1051{
1052 auto bus = sdbusplus::bus::new_default();
1053
1054 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
1055 MockedGPIOInterface* mockPresenceGPIO =
1056 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1057 // Always return 1 to indicate present.
1058 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman96893a42021-11-05 19:56:57 +00001059 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001060 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman96893a42021-11-05 19:56:57 +00001061 // STATUS_WORD 0x0000 is powered on, no faults.
1062 PMBusExpectations expectations;
1063 setPMBusExpectations(mockPMBus, expectations);
1064 psu.analyze();
1065 EXPECT_EQ(psu.hasTempFault(), false);
1066 // Turn fault on.
1067 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
1068 // STATUS_TEMPERATURE fault bit on (OT Fault)
1069 expectations.statusTempValue = 0x80;
1070 setPMBusExpectations(mockPMBus, expectations);
1071 psu.analyze();
1072 EXPECT_EQ(psu.hasTempFault(), true);
1073 // Back to no fault bits on in STATUS_WORD
1074 expectations.statusWordValue = 0;
1075 setPMBusExpectations(mockPMBus, expectations);
1076 psu.analyze();
1077 EXPECT_EQ(psu.hasTempFault(), false);
1078}
Brandon Wyman2916ea52021-11-06 03:31:18 +00001079
1080TEST_F(PowerSupplyTests, HasPgoodFault)
1081{
1082 auto bus = sdbusplus::bus::new_default();
1083
1084 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, PSUGPIOLineName};
1085 MockedGPIOInterface* mockPresenceGPIO =
1086 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1087 // Always return 1 to indicate present.
1088 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001089 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001090 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wyman2916ea52021-11-06 03:31:18 +00001091 // STATUS_WORD 0x0000 is powered on, no faults.
1092 PMBusExpectations expectations;
1093 setPMBusExpectations(mockPMBus, expectations);
1094 psu.analyze();
1095 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman391a0692021-12-08 23:28:18 +00001096 // Setup another expectation of no faults.
1097 setPMBusExpectations(mockPMBus, expectations);
1098 psu.analyze();
1099 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +00001100 // Turn PGOOD# off (fault on).
1101 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
1102 setPMBusExpectations(mockPMBus, expectations);
1103 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001104 // Expect false until reaches DEGLITCH_LIMIT
1105 EXPECT_EQ(psu.hasPgoodFault(), false);
1106 setPMBusExpectations(mockPMBus, expectations);
1107 psu.analyze();
1108 // Expect false until reaches DEGLITCH_LIMIT
1109 EXPECT_EQ(psu.hasPgoodFault(), false);
1110 setPMBusExpectations(mockPMBus, expectations);
1111 psu.analyze();
1112 // DEGLITCH_LIMIT reached, expect true.
Brandon Wyman2916ea52021-11-06 03:31:18 +00001113 EXPECT_EQ(psu.hasPgoodFault(), true);
1114 // Back to no fault bits on in STATUS_WORD
1115 expectations.statusWordValue = 0;
1116 setPMBusExpectations(mockPMBus, expectations);
1117 psu.analyze();
1118 EXPECT_EQ(psu.hasPgoodFault(), false);
1119 // Turn OFF bit on
1120 expectations.statusWordValue = (status_word::UNIT_IS_OFF);
1121 setPMBusExpectations(mockPMBus, expectations);
1122 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001123 EXPECT_EQ(psu.hasPgoodFault(), false);
1124 setPMBusExpectations(mockPMBus, expectations);
1125 psu.analyze();
1126 EXPECT_EQ(psu.hasPgoodFault(), false);
1127 setPMBusExpectations(mockPMBus, expectations);
1128 psu.analyze();
Brandon Wyman2916ea52021-11-06 03:31:18 +00001129 EXPECT_EQ(psu.hasPgoodFault(), true);
1130 // Back to no fault bits on in STATUS_WORD
1131 expectations.statusWordValue = 0;
1132 setPMBusExpectations(mockPMBus, expectations);
1133 psu.analyze();
1134 EXPECT_EQ(psu.hasPgoodFault(), false);
1135}
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001136
1137TEST_F(PowerSupplyTests, HasPSKillFault)
1138{
1139 auto bus = sdbusplus::bus::new_default();
1140 PowerSupply psu{bus, PSUInventoryPath, 4, 0x6d, PSUGPIOLineName};
1141 MockedGPIOInterface* mockPresenceGPIO =
1142 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1143 // Always return 1 to indicate present.
1144 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1145 psu.analyze();
1146 EXPECT_EQ(psu.hasPSKillFault(), false);
1147 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1148 // STATUS_WORD 0x0000 is powered on, no faults.
1149 PMBusExpectations expectations;
1150 setPMBusExpectations(mockPMBus, expectations);
1151 psu.analyze();
1152 EXPECT_EQ(psu.hasPSKillFault(), false);
1153 // Next return STATUS_WORD with MFR fault bit on.
1154 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1155 // STATUS_MFR_SPEFIC with bit(s) on.
1156 expectations.statusMFRValue = 0xFF;
1157 setPMBusExpectations(mockPMBus, expectations);
1158 psu.analyze();
1159 EXPECT_EQ(psu.hasPSKillFault(), true);
1160 // Back to no bits on in STATUS_WORD
1161 expectations.statusWordValue = 0;
1162 setPMBusExpectations(mockPMBus, expectations);
1163 psu.analyze();
1164 EXPECT_EQ(psu.hasPSKillFault(), false);
1165 // Next return STATUS_WORD with MFR fault bit on.
1166 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1167 // STATUS_MFR_SPEFIC with bit 4 on.
1168 expectations.statusMFRValue = 0x10;
1169 setPMBusExpectations(mockPMBus, expectations);
1170 psu.analyze();
1171 EXPECT_EQ(psu.hasPSKillFault(), true);
1172 // Back to no bits on in STATUS_WORD
1173 expectations.statusWordValue = 0;
1174 setPMBusExpectations(mockPMBus, expectations);
1175 psu.analyze();
1176 EXPECT_EQ(psu.hasPSKillFault(), false);
1177}
1178
1179TEST_F(PowerSupplyTests, HasPS12VcsFault)
1180{
1181 auto bus = sdbusplus::bus::new_default();
1182 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6e, PSUGPIOLineName};
1183 MockedGPIOInterface* mockPresenceGPIO =
1184 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1185 // Always return 1 to indicate present.
1186 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1187 psu.analyze();
1188 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1189 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1190 // STATUS_WORD 0x0000 is powered on, no faults.
1191 PMBusExpectations expectations;
1192 setPMBusExpectations(mockPMBus, expectations);
1193 psu.analyze();
1194 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1195 // Next return STATUS_WORD with MFR fault bit on.
1196 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1197 // STATUS_MFR_SPEFIC with bit(s) on.
1198 expectations.statusMFRValue = 0xFF;
1199 setPMBusExpectations(mockPMBus, expectations);
1200 psu.analyze();
1201 EXPECT_EQ(psu.hasPS12VcsFault(), true);
1202 // Back to no bits on in STATUS_WORD
1203 expectations.statusWordValue = 0;
1204 setPMBusExpectations(mockPMBus, expectations);
1205 psu.analyze();
1206 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1207 // Next return STATUS_WORD with MFR fault bit on.
1208 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1209 // STATUS_MFR_SPEFIC with bit 6 on.
1210 expectations.statusMFRValue = 0x40;
1211 setPMBusExpectations(mockPMBus, expectations);
1212 psu.analyze();
1213 EXPECT_EQ(psu.hasPS12VcsFault(), true);
1214 // Back to no bits on in STATUS_WORD
1215 expectations.statusWordValue = 0;
1216 setPMBusExpectations(mockPMBus, expectations);
1217 psu.analyze();
1218 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1219}
1220
1221TEST_F(PowerSupplyTests, HasPSCS12VFault)
1222{
1223 auto bus = sdbusplus::bus::new_default();
1224 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f, PSUGPIOLineName};
1225 MockedGPIOInterface* mockPresenceGPIO =
1226 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1227 // Always return 1 to indicate present.
1228 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1229 psu.analyze();
1230 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1231 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1232 // STATUS_WORD 0x0000 is powered on, no faults.
1233 PMBusExpectations expectations;
1234 setPMBusExpectations(mockPMBus, expectations);
1235 psu.analyze();
1236 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1237 // Next return STATUS_WORD with MFR fault bit on.
1238 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1239 // STATUS_MFR_SPEFIC with bit(s) on.
1240 expectations.statusMFRValue = 0xFF;
1241 setPMBusExpectations(mockPMBus, expectations);
1242 psu.analyze();
1243 EXPECT_EQ(psu.hasPSCS12VFault(), true);
1244 // Back to no bits on in STATUS_WORD
1245 expectations.statusWordValue = 0;
1246 setPMBusExpectations(mockPMBus, expectations);
1247 psu.analyze();
1248 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1249 // Next return STATUS_WORD with MFR fault bit on.
1250 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1251 // STATUS_MFR_SPEFIC with bit 7 on.
1252 expectations.statusMFRValue = 0x80;
1253 setPMBusExpectations(mockPMBus, expectations);
1254 psu.analyze();
1255 EXPECT_EQ(psu.hasPSCS12VFault(), true);
1256 // Back to no bits on in STATUS_WORD
1257 expectations.statusWordValue = 0;
1258 setPMBusExpectations(mockPMBus, expectations);
1259 psu.analyze();
1260 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1261}