blob: 309e6dfdc1b8510ee2e06bcf9bb468493c20b97f [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 Wyman96893a42021-11-05 19:56:57 +000033 uint8_t statusTempValue{0x00};
Brandon Wymanb654c612021-11-05 23:24:51 +000034};
35
Brandon Wyman8da35c52021-10-28 22:45:08 +000036// Helper function to setup expectations for various STATUS_* commands
Brandon Wymanb654c612021-11-05 23:24:51 +000037void setPMBusExpectations(MockedPMBus& mockPMBus,
38 const PMBusExpectations& expectations)
Brandon Wyman8da35c52021-10-28 22:45:08 +000039{
40 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
41 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000042 .WillOnce(Return(expectations.statusWordValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000043
Brandon Wymanb654c612021-11-05 23:24:51 +000044 if (expectations.statusWordValue != 0)
Brandon Wyman8da35c52021-10-28 22:45:08 +000045 {
46 // If fault bits are on in STATUS_WORD, there will also be a read of
Brandon Wyman96893a42021-11-05 19:56:57 +000047 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and
48 // STATUS_TEMPERATURE.
Brandon Wyman8da35c52021-10-28 22:45:08 +000049 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
50 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000051 .WillOnce(Return(expectations.statusInputValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000052 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _))
53 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000054 .WillOnce(Return(expectations.statusMFRValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000055 EXPECT_CALL(mockPMBus, read(STATUS_CML, _))
56 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000057 .WillOnce(Return(expectations.statusCMLValue));
Brandon Wyman6710ba22021-10-27 17:39:31 +000058 // Page will need to be set to 0 to read STATUS_VOUT.
59 EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0))
60 .Times(1)
61 .WillOnce(Return("status0_vout"));
62 EXPECT_CALL(mockPMBus, read("status0_vout", _))
63 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000064 .WillOnce(Return(expectations.statusVOUTValue));
Brandon Wymanb10b3be2021-11-09 22:12:15 +000065 EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _))
66 .Times(1)
67 .WillOnce(Return(expectations.statusIOUTValue));
Brandon Wyman96893a42021-11-05 19:56:57 +000068 EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _))
69 .Times(1)
70 .WillOnce(Return(expectations.statusTempValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000071 }
72}
73
Brandon Wyman3f1242f2020-01-28 13:11:25 -060074class PowerSupplyTests : public ::testing::Test
75{
76 public:
77 PowerSupplyTests() :
78 mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
79 {
80 ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
81 }
82
83 ~PowerSupplyTests() override
84 {
85 freeUtils();
86 }
87
88 const MockedUtil& mockedUtil;
89};
90
91TEST_F(PowerSupplyTests, Constructor)
92{
93 /**
94 * @param[in] invpath - String for inventory path to use
95 * @param[in] i2cbus - The bus number this power supply is on
96 * @param[in] i2caddr - The 16-bit I2C address of the power supply
B. J. Wyman681b2a32021-04-20 22:31:22 +000097 * @param[in] gpioLineName - The string for the gpio-line-name to read for
98 * presence.
99 * @param[in] bindDelay - Time in milliseconds to delay binding the device
100 * driver after seeing the presence line go active.
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600101 */
102 auto bus = sdbusplus::bus::new_default();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600103
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500104 // Try where inventory path is empty, constructor should fail.
105 try
106 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000107 auto psu =
108 std::make_unique<PowerSupply>(bus, "", 3, 0x68, PSUGPIOLineName);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500109 ADD_FAILURE() << "Should not have reached this line.";
110 }
111 catch (const std::invalid_argument& e)
112 {
113 EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
114 }
115 catch (...)
116 {
117 ADD_FAILURE() << "Should not have caught exception.";
118 }
119
B. J. Wyman681b2a32021-04-20 22:31:22 +0000120 // TODO: Try invalid i2c address?
121
122 // Try where gpioLineName is empty.
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500123 try
124 {
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500125 auto psu =
B. J. Wyman681b2a32021-04-20 22:31:22 +0000126 std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, "");
127 ADD_FAILURE()
128 << "Should not have reached this line. Invalid gpioLineName.";
129 }
130 catch (const std::invalid_argument& e)
131 {
132 EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
133 }
134 catch (...)
135 {
136 ADD_FAILURE() << "Should not have caught exception.";
137 }
138
139 // Test with valid arguments
140 // NOT using D-Bus inventory path for presence.
141 try
142 {
143 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
144 PSUGPIOLineName);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500145
146 EXPECT_EQ(psu->isPresent(), false);
147 EXPECT_EQ(psu->isFaulted(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000148 EXPECT_EQ(psu->hasCommFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500149 EXPECT_EQ(psu->hasInputFault(), false);
150 EXPECT_EQ(psu->hasMFRFault(), false);
151 EXPECT_EQ(psu->hasVINUVFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000152 EXPECT_EQ(psu->hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000153 EXPECT_EQ(psu->hasIoutOCFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000154 EXPECT_EQ(psu->hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000155 EXPECT_EQ(psu->hasPgoodFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500156 }
157 catch (...)
158 {
159 ADD_FAILURE() << "Should not have caught exception.";
160 }
B. J. Wyman681b2a32021-04-20 22:31:22 +0000161
162 // Test with valid arguments
163 // TODO: Using D-Bus inventory path for presence.
164 try
165 {
166 // FIXME: How do I get that presenceGPIO.read() in the startup to throw
167 // an exception?
168
169 // EXPECT_CALL(mockedUtil, getPresence(_,
170 // StrEq(PSUInventoryPath)))
171 // .Times(1);
172 }
173 catch (...)
174 {
175 ADD_FAILURE() << "Should not have caught exception.";
176 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600177}
178
179TEST_F(PowerSupplyTests, Analyze)
180{
181 auto bus = sdbusplus::bus::new_default();
182
Brandon Wymanb654c612021-11-05 23:24:51 +0000183 {
184 // If I default to reading the GPIO, I will NOT expect a call to
185 // getPresence().
B. J. Wyman681b2a32021-04-20 22:31:22 +0000186
Brandon Wymanb654c612021-11-05 23:24:51 +0000187 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
188 MockedGPIOInterface* mockPresenceGPIO =
189 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
190 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000191
Brandon Wymanb654c612021-11-05 23:24:51 +0000192 psu.analyze();
193 // By default, nothing should change.
194 EXPECT_EQ(psu.isPresent(), false);
195 EXPECT_EQ(psu.isFaulted(), false);
196 EXPECT_EQ(psu.hasInputFault(), false);
197 EXPECT_EQ(psu.hasMFRFault(), false);
198 EXPECT_EQ(psu.hasVINUVFault(), false);
199 EXPECT_EQ(psu.hasCommFault(), false);
200 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000201 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000202 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000203 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000204 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600205
B. J. Wyman681b2a32021-04-20 22:31:22 +0000206 PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
207 // In order to get the various faults tested, the power supply needs to
208 // be present in order to read from the PMBus device(s).
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000209 MockedGPIOInterface* mockPresenceGPIO2 =
210 static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000211 ON_CALL(*mockPresenceGPIO2, read()).WillByDefault(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000212 EXPECT_EQ(psu2.isPresent(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600213
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600214 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
Brandon Wyman8da35c52021-10-28 22:45:08 +0000215 // Presence change from missing to present will trigger write to
216 // ON_OFF_CONFIG.
217 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, _, _));
Brandon Wymanb654c612021-11-05 23:24:51 +0000218 // Presence change from missing to present will trigger in1_input read
219 // in an attempt to get CLEAR_FAULTS called.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000220 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600221
Brandon Wymanb654c612021-11-05 23:24:51 +0000222 // STATUS_WORD INPUT fault.
223 {
224 // Start with STATUS_WORD 0x0000. Powered on, no faults.
225 // Set expectations for a no fault
226 PMBusExpectations expectations;
227 setPMBusExpectations(mockPMBus, expectations);
228 psu2.analyze();
229 EXPECT_EQ(psu2.isPresent(), true);
230 EXPECT_EQ(psu2.isFaulted(), false);
231 EXPECT_EQ(psu2.hasInputFault(), false);
232 EXPECT_EQ(psu2.hasMFRFault(), false);
233 EXPECT_EQ(psu2.hasVINUVFault(), false);
234 EXPECT_EQ(psu2.hasCommFault(), false);
235 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000236 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000237 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000238 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000239
240 // Update expectations for STATUS_WORD input fault/warn
Brandon Wyman96893a42021-11-05 19:56:57 +0000241 // STATUS_INPUT fault bits ... on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000242 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
243 expectations.statusInputValue = 0x38;
244 setPMBusExpectations(mockPMBus, expectations);
245 psu2.analyze();
246 EXPECT_EQ(psu2.isPresent(), true);
247 EXPECT_EQ(psu2.isFaulted(), true);
248 EXPECT_EQ(psu2.hasInputFault(), true);
249 EXPECT_EQ(psu2.hasMFRFault(), false);
250 EXPECT_EQ(psu2.hasVINUVFault(), false);
251 EXPECT_EQ(psu2.hasCommFault(), false);
252 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000253 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000254 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000255 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000256 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600257
258 // STATUS_WORD INPUT/UV fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000259 {
260 // First need it to return good status, then the fault
261 PMBusExpectations expectations;
262 setPMBusExpectations(mockPMBus, expectations);
263 psu2.analyze();
264 // Now set fault bits in STATUS_WORD
265 expectations.statusWordValue =
266 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
267 // STATUS_INPUT fault bits ... on.
268 expectations.statusInputValue = 0x38;
269 setPMBusExpectations(mockPMBus, expectations);
270 psu2.analyze();
271 EXPECT_EQ(psu2.isPresent(), true);
272 EXPECT_EQ(psu2.isFaulted(), true);
273 EXPECT_EQ(psu2.hasInputFault(), true);
274 EXPECT_EQ(psu2.hasMFRFault(), false);
275 EXPECT_EQ(psu2.hasVINUVFault(), true);
276 EXPECT_EQ(psu2.hasCommFault(), false);
277 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000278 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000279 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000280 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000281 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600282
283 // STATUS_WORD MFR fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000284 {
285 // First need it to return good status, then the fault
286 PMBusExpectations expectations;
287 setPMBusExpectations(mockPMBus, expectations);
288 psu2.analyze();
289 // Now STATUS_WORD with MFR fault bit on.
290 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
291 // STATUS_MFR bits on.
292 expectations.statusMFRValue = 0xFF;
293 setPMBusExpectations(mockPMBus, expectations);
294 psu2.analyze();
295 EXPECT_EQ(psu2.isPresent(), true);
296 EXPECT_EQ(psu2.isFaulted(), true);
297 EXPECT_EQ(psu2.hasInputFault(), false);
298 EXPECT_EQ(psu2.hasMFRFault(), true);
299 EXPECT_EQ(psu2.hasVINUVFault(), false);
300 EXPECT_EQ(psu2.hasCommFault(), false);
301 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000302 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000303 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000304 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000305 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600306
Brandon Wyman96893a42021-11-05 19:56:57 +0000307 // Temperature fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000308 {
309 // First STATUS_WORD with no bits set, then with temperature fault.
310 PMBusExpectations expectations;
311 setPMBusExpectations(mockPMBus, expectations);
312 psu2.analyze();
313 // STATUS_WORD with temperature fault bit on.
314 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
Brandon Wyman96893a42021-11-05 19:56:57 +0000315 // STATUS_TEMPERATURE with fault bit(s) on.
316 expectations.statusTempValue = 0x10;
Brandon Wymanb654c612021-11-05 23:24:51 +0000317 setPMBusExpectations(mockPMBus, expectations);
318 psu2.analyze();
319 EXPECT_EQ(psu2.isPresent(), true);
Brandon Wyman96893a42021-11-05 19:56:57 +0000320 EXPECT_EQ(psu2.isFaulted(), true);
Brandon Wymanb654c612021-11-05 23:24:51 +0000321 EXPECT_EQ(psu2.hasInputFault(), false);
322 EXPECT_EQ(psu2.hasMFRFault(), false);
323 EXPECT_EQ(psu2.hasVINUVFault(), false);
324 EXPECT_EQ(psu2.hasCommFault(), false);
325 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000326 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000327 EXPECT_EQ(psu2.hasTempFault(), true);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000328 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000329 }
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000330
331 // CML fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000332 {
333 // First STATUS_WORD wit no bits set, then with CML fault.
334 PMBusExpectations expectations;
335 setPMBusExpectations(mockPMBus, expectations);
336 psu2.analyze();
337 // STATUS_WORD with CML fault bit on.
338 expectations.statusWordValue = (status_word::CML_FAULT);
339 // Turn on STATUS_CML fault bit(s)
340 expectations.statusCMLValue = 0xFF;
341 setPMBusExpectations(mockPMBus, expectations);
342 psu2.analyze();
343 EXPECT_EQ(psu2.isPresent(), true);
344 EXPECT_EQ(psu2.isFaulted(), true);
345 EXPECT_EQ(psu2.hasInputFault(), false);
346 EXPECT_EQ(psu2.hasMFRFault(), false);
347 EXPECT_EQ(psu2.hasVINUVFault(), false);
348 EXPECT_EQ(psu2.hasCommFault(), true);
349 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000350 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000351 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000352 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000353 }
Brandon Wyman6710ba22021-10-27 17:39:31 +0000354
355 // VOUT_OV_FAULT fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000356 {
357 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
358 PMBusExpectations expectations;
359 setPMBusExpectations(mockPMBus, expectations);
360 psu2.analyze();
361 // STATUS_WORD with VOUT/VOUT_OV fault.
362 expectations.statusWordValue =
363 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
364 // Turn on STATUS_VOUT fault bit(s)
365 expectations.statusVOUTValue = 0xA0;
Brandon Wyman96893a42021-11-05 19:56:57 +0000366 // STATUS_TEMPERATURE don't care (default)
Brandon Wymanb654c612021-11-05 23:24:51 +0000367 setPMBusExpectations(mockPMBus, expectations);
368 psu2.analyze();
369 EXPECT_EQ(psu2.isPresent(), true);
370 EXPECT_EQ(psu2.isFaulted(), true);
371 EXPECT_EQ(psu2.hasInputFault(), false);
372 EXPECT_EQ(psu2.hasMFRFault(), false);
373 EXPECT_EQ(psu2.hasVINUVFault(), false);
374 EXPECT_EQ(psu2.hasCommFault(), false);
375 EXPECT_EQ(psu2.hasVoutOVFault(), true);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000376 EXPECT_EQ(psu2.hasIoutOCFault(), false);
377 EXPECT_EQ(psu2.hasTempFault(), false);
378 EXPECT_EQ(psu2.hasPgoodFault(), false);
379 }
380
381 // IOUT_OC_FAULT fault
382 {
383 // First STATUS_WORD with no bits set, then with IOUT_OC fault.
384 PMBusExpectations expectations;
385 setPMBusExpectations(mockPMBus, expectations);
386 psu2.analyze();
387 // STATUS_WORD with IOUT_OC fault.
388 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
389 // Turn on STATUS_IOUT fault bit(s)
390 expectations.statusIOUTValue = 0x88;
391 setPMBusExpectations(mockPMBus, expectations);
392 psu2.analyze();
393 EXPECT_EQ(psu2.isPresent(), true);
394 EXPECT_EQ(psu2.isFaulted(), true);
395 EXPECT_EQ(psu2.hasInputFault(), false);
396 EXPECT_EQ(psu2.hasMFRFault(), false);
397 EXPECT_EQ(psu2.hasVINUVFault(), false);
398 EXPECT_EQ(psu2.hasCommFault(), false);
399 EXPECT_EQ(psu2.hasVoutOVFault(), false);
400 EXPECT_EQ(psu2.hasIoutOCFault(), true);
Brandon Wyman96893a42021-11-05 19:56:57 +0000401 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000402 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000403 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600404
405 // Ignore fan fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000406 {
407 // First STATUS_WORD with no bits set, then with fan fault.
408 PMBusExpectations expectations;
409 setPMBusExpectations(mockPMBus, expectations);
410 psu2.analyze();
411 expectations.statusWordValue = (status_word::FAN_FAULT);
412 setPMBusExpectations(mockPMBus, expectations);
413 psu2.analyze();
414 EXPECT_EQ(psu2.isPresent(), true);
415 EXPECT_EQ(psu2.isFaulted(), false);
416 EXPECT_EQ(psu2.hasInputFault(), false);
417 EXPECT_EQ(psu2.hasMFRFault(), false);
418 EXPECT_EQ(psu2.hasVINUVFault(), false);
419 EXPECT_EQ(psu2.hasCommFault(), false);
420 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000421 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000422 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000423 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000424 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000425
426 {
427 // PGOOD/OFF fault.
428 // First STATUS_WORD with no bits set.
429 PMBusExpectations expectations;
430 setPMBusExpectations(mockPMBus, expectations);
431 psu2.analyze();
432 EXPECT_EQ(psu2.isFaulted(), false);
433 // POWER_GOOD# inactive, and OFF bit on.
434 expectations.statusWordValue =
435 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
436 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
437 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
438 setPMBusExpectations(mockPMBus, expectations);
439 psu2.analyze();
440 EXPECT_EQ(psu2.isPresent(), true);
441 EXPECT_EQ(psu2.isFaulted(), true);
442 EXPECT_EQ(psu2.hasInputFault(), false);
443 EXPECT_EQ(psu2.hasMFRFault(), false);
444 EXPECT_EQ(psu2.hasVINUVFault(), false);
445 EXPECT_EQ(psu2.hasCommFault(), false);
446 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000447 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000448 EXPECT_EQ(psu2.hasTempFault(), false);
449 EXPECT_EQ(psu2.hasPgoodFault(), true);
450 }
451
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600452 // TODO: ReadFailure
453}
454
Brandon Wyman59a35792020-06-04 12:37:40 -0500455TEST_F(PowerSupplyTests, OnOffConfig)
456{
457 auto bus = sdbusplus::bus::new_default();
458 uint8_t data = 0x15;
459
460 // Test where PSU is NOT present
461 try
462 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000463 // Assume GPIO presence, not inventory presence?
464 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
465
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000466 MockedGPIOInterface* mockPresenceGPIO =
467 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000468 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
Brandon Wyman59a35792020-06-04 12:37:40 -0500469 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000470 // Constructor should set initial presence, default read returns 0.
Brandon Wyman59a35792020-06-04 12:37:40 -0500471 // If it is not present, I should not be trying to write to it.
472 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
473 psu.onOffConfig(data);
474 }
475 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000476 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500477
478 // Test where PSU is present
479 try
480 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000481 // Assume GPIO presence, not inventory presence?
482 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000483 MockedGPIOInterface* mockPresenceGPIO =
484 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000485 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1));
Brandon Wyman59a35792020-06-04 12:37:40 -0500486 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000487 // TODO: expect setPresence call?
488 // updatePresence() private function reads gpio, called by analyze().
489 psu.analyze();
Brandon Wyman59a35792020-06-04 12:37:40 -0500490 // TODO: ???should I check the filename?
491 EXPECT_CALL(mockPMBus,
492 writeBinary(_, ElementsAre(0x15), Type::HwmonDeviceDebug))
493 .Times(1);
494 psu.onOffConfig(data);
495 }
496 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000497 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500498}
499
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600500TEST_F(PowerSupplyTests, ClearFaults)
501{
502 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000503 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000504 MockedGPIOInterface* mockPresenceGPIO =
505 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000506 // GPIO read return 1 to indicate present.
507 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1));
508 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman8da35c52021-10-28 22:45:08 +0000509 // Presence change from missing to present will trigger in1_input read in
510 // an attempt to get CLEAR_FAULTS called.
511 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000));
512 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000513 PMBusExpectations expectations;
514 setPMBusExpectations(mockPMBus, expectations);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000515 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600516 EXPECT_EQ(psu.isPresent(), true);
517 EXPECT_EQ(psu.isFaulted(), false);
518 EXPECT_EQ(psu.hasInputFault(), false);
519 EXPECT_EQ(psu.hasMFRFault(), false);
520 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000521 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000522 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000523 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000524 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000525 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000526
Brandon Wymanf07bc792021-10-12 19:00:35 +0000527 // STATUS_WORD with fault bits galore!
Brandon Wymanb654c612021-11-05 23:24:51 +0000528 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000529 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000530 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000531 // STATUS_MFR_SPEFIC with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000532 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000533 // STATUS_CML with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000534 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000535 // STATUS_VOUT with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000536 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000537 // STATUS_IOUT with bits on.
538 expectations.statusIOUTValue = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000539 // STATUS_TEMPERATURE with bits on.
540 expectations.statusTempValue = 0xFF;
Brandon Wymanb654c612021-11-05 23:24:51 +0000541 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600542 psu.analyze();
543 EXPECT_EQ(psu.isPresent(), true);
544 EXPECT_EQ(psu.isFaulted(), true);
545 EXPECT_EQ(psu.hasInputFault(), true);
546 EXPECT_EQ(psu.hasMFRFault(), true);
547 EXPECT_EQ(psu.hasVINUVFault(), true);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000548 EXPECT_EQ(psu.hasCommFault(), true);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000549 EXPECT_EQ(psu.hasVoutOVFault(), true);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000550 EXPECT_EQ(psu.hasIoutOCFault(), true);
Brandon Wyman96893a42021-11-05 19:56:57 +0000551 EXPECT_EQ(psu.hasTempFault(), true);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000552 EXPECT_EQ(psu.hasPgoodFault(), true);
Brandon Wyman3c208462020-05-13 16:25:58 -0500553 EXPECT_CALL(mockPMBus, read("in1_input", _))
554 .Times(1)
555 .WillOnce(Return(209000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600556 psu.clearFaults();
557 EXPECT_EQ(psu.isPresent(), true);
558 EXPECT_EQ(psu.isFaulted(), false);
559 EXPECT_EQ(psu.hasInputFault(), false);
560 EXPECT_EQ(psu.hasMFRFault(), false);
561 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000562 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000563 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000564 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000565 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000566 EXPECT_EQ(psu.hasPgoodFault(), false);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000567
568 // TODO: Faults clear on missing/present?
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600569}
570
571TEST_F(PowerSupplyTests, UpdateInventory)
572{
573 auto bus = sdbusplus::bus::new_default();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500574
575 try
576 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000577 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500578 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
579 // If it is not present, I should not be trying to read a string
580 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
581 psu.updateInventory();
582 }
583 catch (...)
584 {
585 ADD_FAILURE() << "Should not have caught exception.";
586 }
587
588 try
589 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000590 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000591 MockedGPIOInterface* mockPresenceGPIO =
592 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000593 // GPIO read return 1 to indicate present.
594 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
595 psu.analyze();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500596 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
597 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
598 psu.updateInventory();
599
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500600#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500601 EXPECT_CALL(mockPMBus, readString(_, _))
602 .WillOnce(Return("CCIN"))
603 .WillOnce(Return("PN3456"))
604 .WillOnce(Return("FN3456"))
605 .WillOnce(Return("HEADER"))
606 .WillOnce(Return("SN3456"))
607 .WillOnce(Return("FW3456"));
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500608#endif
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500609 psu.updateInventory();
610 // TODO: D-Bus mocking to verify values stored on D-Bus (???)
611 }
612 catch (...)
613 {
614 ADD_FAILURE() << "Should not have caught exception.";
615 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600616}
617
618TEST_F(PowerSupplyTests, IsPresent)
619{
620 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000621
622 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000623 MockedGPIOInterface* mockPresenceGPIO =
624 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600625 EXPECT_EQ(psu.isPresent(), false);
626
B. J. Wyman681b2a32021-04-20 22:31:22 +0000627 // Change GPIO read to return 1 to indicate present.
628 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
629 psu.analyze();
630 EXPECT_EQ(psu.isPresent(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600631}
632
633TEST_F(PowerSupplyTests, IsFaulted)
634{
635 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000636
637 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000638 MockedGPIOInterface* mockPresenceGPIO =
639 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000640 // Always return 1 to indicate present.
641 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
642 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600643 EXPECT_EQ(psu.isFaulted(), false);
644 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wymanb654c612021-11-05 23:24:51 +0000645 PMBusExpectations expectations;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000646 // STATUS_WORD with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000647 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000648 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000649 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000650 // STATUS_MFR_SPECIFIC with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000651 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000652 // STATUS_CML with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000653 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000654 // STATUS_VOUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000655 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000656 // STATUS_IOUT with fault bits on.
657 expectations.statusIOUTValue = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000658 // STATUS_TEMPERATURE with fault bits on.
659 expectations.statusTempValue = 0xFF;
Brandon Wymanb654c612021-11-05 23:24:51 +0000660 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600661 psu.analyze();
662 EXPECT_EQ(psu.isFaulted(), true);
663}
664
665TEST_F(PowerSupplyTests, HasInputFault)
666{
667 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000668
669 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000670 MockedGPIOInterface* mockPresenceGPIO =
671 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000672 // Always return 1 to indicate present.
673 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
674 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600675 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
676 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000677 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000678 PMBusExpectations expectations;
679 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600680 psu.analyze();
681 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000682 // STATUS_WORD with input fault/warn on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000683 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000684 // STATUS_INPUT with an input fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000685 expectations.statusInputValue = 0x80;
686 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600687 psu.analyze();
688 EXPECT_EQ(psu.hasInputFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000689 // STATUS_WORD with no bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000690 expectations.statusWordValue = 0;
691 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600692 psu.analyze();
693 EXPECT_EQ(psu.hasInputFault(), false);
694}
695
696TEST_F(PowerSupplyTests, HasMFRFault)
697{
698 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000699
700 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000701 MockedGPIOInterface* mockPresenceGPIO =
702 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000703 // Always return 1 to indicate present.
704 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
705 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600706 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
707 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000708 // First return STATUS_WORD with no bits on.
Brandon Wyman8da35c52021-10-28 22:45:08 +0000709 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000710 PMBusExpectations expectations;
711 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600712 psu.analyze();
713 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000714 // Next return STATUS_WORD with MFR fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000715 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000716 // STATUS_MFR_SPEFIC with bit(s) on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000717 expectations.statusMFRValue = 0xFF;
718 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600719 psu.analyze();
720 EXPECT_EQ(psu.hasMFRFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000721 // Back to no bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +0000722 expectations.statusWordValue = 0;
723 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600724 psu.analyze();
725 EXPECT_EQ(psu.hasMFRFault(), false);
726}
727
728TEST_F(PowerSupplyTests, HasVINUVFault)
729{
730 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000731
732 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000733 MockedGPIOInterface* mockPresenceGPIO =
734 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000735 // Always return 1 to indicate present.
736 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
737 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600738 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
739 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000740 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000741 PMBusExpectations expectations;
742 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600743 psu.analyze();
744 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000745 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000746 expectations.statusWordValue = (status_word::VIN_UV_FAULT);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000747 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
748 // Figure 16, and assume bits on in STATUS_INPUT.
Brandon Wymanb654c612021-11-05 23:24:51 +0000749 expectations.statusInputValue = 0x18;
750 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600751 psu.analyze();
752 EXPECT_EQ(psu.hasVINUVFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000753 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +0000754 expectations.statusWordValue = 0;
755 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600756 psu.analyze();
757 EXPECT_EQ(psu.hasVINUVFault(), false);
758}
Brandon Wyman6710ba22021-10-27 17:39:31 +0000759
760TEST_F(PowerSupplyTests, HasVoutOVFault)
761{
762 auto bus = sdbusplus::bus::new_default();
763
764 PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName};
765 MockedGPIOInterface* mockPresenceGPIO =
766 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
767 // Always return 1 to indicate present.
768 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
769 psu.analyze();
770 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
771 EXPECT_EQ(psu.hasVoutOVFault(), false);
772 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000773 PMBusExpectations expectations;
774 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000775 psu.analyze();
776 EXPECT_EQ(psu.hasVoutOVFault(), false);
777 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000778 expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000779 // STATUS_VOUT fault bit(s)
Brandon Wymanb654c612021-11-05 23:24:51 +0000780 expectations.statusVOUTValue = 0x80;
Brandon Wyman96893a42021-11-05 19:56:57 +0000781 // STATUS_TEMPERATURE default.
Brandon Wymanb654c612021-11-05 23:24:51 +0000782 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000783 psu.analyze();
784 EXPECT_EQ(psu.hasVoutOVFault(), true);
785 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +0000786 expectations.statusWordValue = 0;
787 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000788 psu.analyze();
789 EXPECT_EQ(psu.hasVoutOVFault(), false);
790}
Brandon Wyman96893a42021-11-05 19:56:57 +0000791
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000792TEST_F(PowerSupplyTests, HasIoutOCFault)
793{
794 auto bus = sdbusplus::bus::new_default();
795
796 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
797 MockedGPIOInterface* mockPresenceGPIO =
798 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
799 // Always return 1 to indicate present.
800 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
801 psu.analyze();
802 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
803 EXPECT_EQ(psu.hasIoutOCFault(), false);
804 // STATUS_WORD 0x0000 is powered on, no faults.
805 PMBusExpectations expectations;
806 setPMBusExpectations(mockPMBus, expectations);
807 psu.analyze();
808 EXPECT_EQ(psu.hasIoutOCFault(), false);
809 // Turn fault on.
810 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
811 // STATUS_IOUT fault bit(s)
812 expectations.statusIOUTValue = 0x88;
813 setPMBusExpectations(mockPMBus, expectations);
814 psu.analyze();
815 EXPECT_EQ(psu.hasIoutOCFault(), true);
816 // Back to no fault bits on in STATUS_WORD
817 expectations.statusWordValue = 0;
818 setPMBusExpectations(mockPMBus, expectations);
819 psu.analyze();
820 EXPECT_EQ(psu.hasIoutOCFault(), false);
821}
822
Brandon Wyman96893a42021-11-05 19:56:57 +0000823TEST_F(PowerSupplyTests, HasTempFault)
824{
825 auto bus = sdbusplus::bus::new_default();
826
827 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
828 MockedGPIOInterface* mockPresenceGPIO =
829 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
830 // Always return 1 to indicate present.
831 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
832 psu.analyze();
833 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
834 EXPECT_EQ(psu.hasTempFault(), false);
835 // STATUS_WORD 0x0000 is powered on, no faults.
836 PMBusExpectations expectations;
837 setPMBusExpectations(mockPMBus, expectations);
838 psu.analyze();
839 EXPECT_EQ(psu.hasTempFault(), false);
840 // Turn fault on.
841 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
842 // STATUS_TEMPERATURE fault bit on (OT Fault)
843 expectations.statusTempValue = 0x80;
844 setPMBusExpectations(mockPMBus, expectations);
845 psu.analyze();
846 EXPECT_EQ(psu.hasTempFault(), true);
847 // Back to no fault bits on in STATUS_WORD
848 expectations.statusWordValue = 0;
849 setPMBusExpectations(mockPMBus, expectations);
850 psu.analyze();
851 EXPECT_EQ(psu.hasTempFault(), false);
852}
Brandon Wyman2916ea52021-11-06 03:31:18 +0000853
854TEST_F(PowerSupplyTests, HasPgoodFault)
855{
856 auto bus = sdbusplus::bus::new_default();
857
858 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, PSUGPIOLineName};
859 MockedGPIOInterface* mockPresenceGPIO =
860 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
861 // Always return 1 to indicate present.
862 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
863 psu.analyze();
864 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
865 EXPECT_EQ(psu.hasPgoodFault(), false);
866 // STATUS_WORD 0x0000 is powered on, no faults.
867 PMBusExpectations expectations;
868 setPMBusExpectations(mockPMBus, expectations);
869 psu.analyze();
870 EXPECT_EQ(psu.hasPgoodFault(), false);
871 // Turn PGOOD# off (fault on).
872 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
873 setPMBusExpectations(mockPMBus, expectations);
874 psu.analyze();
875 EXPECT_EQ(psu.hasPgoodFault(), true);
876 // Back to no fault bits on in STATUS_WORD
877 expectations.statusWordValue = 0;
878 setPMBusExpectations(mockPMBus, expectations);
879 psu.analyze();
880 EXPECT_EQ(psu.hasPgoodFault(), false);
881 // Turn OFF bit on
882 expectations.statusWordValue = (status_word::UNIT_IS_OFF);
883 setPMBusExpectations(mockPMBus, expectations);
884 psu.analyze();
885 EXPECT_EQ(psu.hasPgoodFault(), true);
886 // Back to no fault bits on in STATUS_WORD
887 expectations.statusWordValue = 0;
888 setPMBusExpectations(mockPMBus, expectations);
889 psu.analyze();
890 EXPECT_EQ(psu.hasPgoodFault(), false);
891}