blob: b340449457b07c736410e72a76173c0933a01703 [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 Wyman2cf46942021-10-28 19:09:16 +0000154 EXPECT_EQ(psu->hasVoutUVFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000155 EXPECT_EQ(psu->hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000156 EXPECT_EQ(psu->hasPgoodFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500157 }
158 catch (...)
159 {
160 ADD_FAILURE() << "Should not have caught exception.";
161 }
B. J. Wyman681b2a32021-04-20 22:31:22 +0000162
163 // Test with valid arguments
164 // TODO: Using D-Bus inventory path for presence.
165 try
166 {
167 // FIXME: How do I get that presenceGPIO.read() in the startup to throw
168 // an exception?
169
170 // EXPECT_CALL(mockedUtil, getPresence(_,
171 // StrEq(PSUInventoryPath)))
172 // .Times(1);
173 }
174 catch (...)
175 {
176 ADD_FAILURE() << "Should not have caught exception.";
177 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600178}
179
180TEST_F(PowerSupplyTests, Analyze)
181{
182 auto bus = sdbusplus::bus::new_default();
183
Brandon Wymanb654c612021-11-05 23:24:51 +0000184 {
185 // If I default to reading the GPIO, I will NOT expect a call to
186 // getPresence().
B. J. Wyman681b2a32021-04-20 22:31:22 +0000187
Brandon Wymanb654c612021-11-05 23:24:51 +0000188 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
189 MockedGPIOInterface* mockPresenceGPIO =
190 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
191 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000192
Brandon Wymanb654c612021-11-05 23:24:51 +0000193 psu.analyze();
194 // By default, nothing should change.
195 EXPECT_EQ(psu.isPresent(), false);
196 EXPECT_EQ(psu.isFaulted(), false);
197 EXPECT_EQ(psu.hasInputFault(), false);
198 EXPECT_EQ(psu.hasMFRFault(), false);
199 EXPECT_EQ(psu.hasVINUVFault(), false);
200 EXPECT_EQ(psu.hasCommFault(), false);
201 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000202 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000203 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000204 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000205 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000206 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600207
B. J. Wyman681b2a32021-04-20 22:31:22 +0000208 PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
209 // In order to get the various faults tested, the power supply needs to
210 // be present in order to read from the PMBus device(s).
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000211 MockedGPIOInterface* mockPresenceGPIO2 =
212 static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000213 ON_CALL(*mockPresenceGPIO2, read()).WillByDefault(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000214 EXPECT_EQ(psu2.isPresent(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600215
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600216 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
Brandon Wyman8da35c52021-10-28 22:45:08 +0000217 // Presence change from missing to present will trigger write to
218 // ON_OFF_CONFIG.
219 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, _, _));
Brandon Wymanb654c612021-11-05 23:24:51 +0000220 // Presence change from missing to present will trigger in1_input read
221 // in an attempt to get CLEAR_FAULTS called.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000222 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600223
Brandon Wymanb654c612021-11-05 23:24:51 +0000224 // STATUS_WORD INPUT fault.
225 {
226 // Start with STATUS_WORD 0x0000. Powered on, no faults.
227 // Set expectations for a no fault
228 PMBusExpectations expectations;
229 setPMBusExpectations(mockPMBus, expectations);
230 psu2.analyze();
231 EXPECT_EQ(psu2.isPresent(), true);
232 EXPECT_EQ(psu2.isFaulted(), false);
233 EXPECT_EQ(psu2.hasInputFault(), false);
234 EXPECT_EQ(psu2.hasMFRFault(), false);
235 EXPECT_EQ(psu2.hasVINUVFault(), false);
236 EXPECT_EQ(psu2.hasCommFault(), false);
237 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000238 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000239 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000240 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000241 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000242
243 // Update expectations for STATUS_WORD input fault/warn
Brandon Wyman96893a42021-11-05 19:56:57 +0000244 // STATUS_INPUT fault bits ... on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000245 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
246 expectations.statusInputValue = 0x38;
247 setPMBusExpectations(mockPMBus, expectations);
248 psu2.analyze();
249 EXPECT_EQ(psu2.isPresent(), true);
250 EXPECT_EQ(psu2.isFaulted(), true);
251 EXPECT_EQ(psu2.hasInputFault(), true);
252 EXPECT_EQ(psu2.hasMFRFault(), false);
253 EXPECT_EQ(psu2.hasVINUVFault(), false);
254 EXPECT_EQ(psu2.hasCommFault(), false);
255 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000256 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000257 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000258 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000259 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000260 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600261
262 // STATUS_WORD INPUT/UV fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000263 {
264 // First need it to return good status, then the fault
265 PMBusExpectations expectations;
266 setPMBusExpectations(mockPMBus, expectations);
267 psu2.analyze();
268 // Now set fault bits in STATUS_WORD
269 expectations.statusWordValue =
270 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
271 // STATUS_INPUT fault bits ... on.
272 expectations.statusInputValue = 0x38;
273 setPMBusExpectations(mockPMBus, expectations);
274 psu2.analyze();
275 EXPECT_EQ(psu2.isPresent(), true);
276 EXPECT_EQ(psu2.isFaulted(), true);
277 EXPECT_EQ(psu2.hasInputFault(), true);
278 EXPECT_EQ(psu2.hasMFRFault(), false);
279 EXPECT_EQ(psu2.hasVINUVFault(), true);
280 EXPECT_EQ(psu2.hasCommFault(), false);
281 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000282 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000283 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000284 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000285 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000286 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600287
288 // STATUS_WORD MFR fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000289 {
290 // First need it to return good status, then the fault
291 PMBusExpectations expectations;
292 setPMBusExpectations(mockPMBus, expectations);
293 psu2.analyze();
294 // Now STATUS_WORD with MFR fault bit on.
295 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
296 // STATUS_MFR bits on.
297 expectations.statusMFRValue = 0xFF;
298 setPMBusExpectations(mockPMBus, expectations);
299 psu2.analyze();
300 EXPECT_EQ(psu2.isPresent(), true);
301 EXPECT_EQ(psu2.isFaulted(), true);
302 EXPECT_EQ(psu2.hasInputFault(), false);
303 EXPECT_EQ(psu2.hasMFRFault(), true);
304 EXPECT_EQ(psu2.hasVINUVFault(), false);
305 EXPECT_EQ(psu2.hasCommFault(), false);
306 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000307 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000308 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000309 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000310 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000311 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600312
Brandon Wyman96893a42021-11-05 19:56:57 +0000313 // Temperature fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000314 {
315 // First STATUS_WORD with no bits set, then with temperature fault.
316 PMBusExpectations expectations;
317 setPMBusExpectations(mockPMBus, expectations);
318 psu2.analyze();
319 // STATUS_WORD with temperature fault bit on.
320 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
Brandon Wyman96893a42021-11-05 19:56:57 +0000321 // STATUS_TEMPERATURE with fault bit(s) on.
322 expectations.statusTempValue = 0x10;
Brandon Wymanb654c612021-11-05 23:24:51 +0000323 setPMBusExpectations(mockPMBus, expectations);
324 psu2.analyze();
325 EXPECT_EQ(psu2.isPresent(), true);
Brandon Wyman96893a42021-11-05 19:56:57 +0000326 EXPECT_EQ(psu2.isFaulted(), true);
Brandon Wymanb654c612021-11-05 23:24:51 +0000327 EXPECT_EQ(psu2.hasInputFault(), false);
328 EXPECT_EQ(psu2.hasMFRFault(), false);
329 EXPECT_EQ(psu2.hasVINUVFault(), false);
330 EXPECT_EQ(psu2.hasCommFault(), false);
331 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000332 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000333 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000334 EXPECT_EQ(psu2.hasTempFault(), true);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000335 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000336 }
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000337
338 // CML fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000339 {
340 // First STATUS_WORD wit no bits set, then with CML fault.
341 PMBusExpectations expectations;
342 setPMBusExpectations(mockPMBus, expectations);
343 psu2.analyze();
344 // STATUS_WORD with CML fault bit on.
345 expectations.statusWordValue = (status_word::CML_FAULT);
346 // Turn on STATUS_CML fault bit(s)
347 expectations.statusCMLValue = 0xFF;
348 setPMBusExpectations(mockPMBus, expectations);
349 psu2.analyze();
350 EXPECT_EQ(psu2.isPresent(), true);
351 EXPECT_EQ(psu2.isFaulted(), true);
352 EXPECT_EQ(psu2.hasInputFault(), false);
353 EXPECT_EQ(psu2.hasMFRFault(), false);
354 EXPECT_EQ(psu2.hasVINUVFault(), false);
355 EXPECT_EQ(psu2.hasCommFault(), true);
356 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000357 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000358 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000359 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000360 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000361 }
Brandon Wyman6710ba22021-10-27 17:39:31 +0000362
363 // VOUT_OV_FAULT fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000364 {
365 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
366 PMBusExpectations expectations;
367 setPMBusExpectations(mockPMBus, expectations);
368 psu2.analyze();
369 // STATUS_WORD with VOUT/VOUT_OV fault.
370 expectations.statusWordValue =
371 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
372 // Turn on STATUS_VOUT fault bit(s)
373 expectations.statusVOUTValue = 0xA0;
Brandon Wyman96893a42021-11-05 19:56:57 +0000374 // STATUS_TEMPERATURE don't care (default)
Brandon Wymanb654c612021-11-05 23:24:51 +0000375 setPMBusExpectations(mockPMBus, expectations);
376 psu2.analyze();
377 EXPECT_EQ(psu2.isPresent(), true);
378 EXPECT_EQ(psu2.isFaulted(), true);
379 EXPECT_EQ(psu2.hasInputFault(), false);
380 EXPECT_EQ(psu2.hasMFRFault(), false);
381 EXPECT_EQ(psu2.hasVINUVFault(), false);
382 EXPECT_EQ(psu2.hasCommFault(), false);
383 EXPECT_EQ(psu2.hasVoutOVFault(), true);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000384 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000385 EXPECT_EQ(psu2.hasIoutOCFault(), false);
386 EXPECT_EQ(psu2.hasTempFault(), false);
387 EXPECT_EQ(psu2.hasPgoodFault(), false);
388 }
389
390 // IOUT_OC_FAULT fault
391 {
392 // First STATUS_WORD with no bits set, then with IOUT_OC fault.
393 PMBusExpectations expectations;
394 setPMBusExpectations(mockPMBus, expectations);
395 psu2.analyze();
396 // STATUS_WORD with IOUT_OC fault.
397 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
398 // Turn on STATUS_IOUT fault bit(s)
399 expectations.statusIOUTValue = 0x88;
400 setPMBusExpectations(mockPMBus, expectations);
401 psu2.analyze();
402 EXPECT_EQ(psu2.isPresent(), true);
403 EXPECT_EQ(psu2.isFaulted(), true);
404 EXPECT_EQ(psu2.hasInputFault(), false);
405 EXPECT_EQ(psu2.hasMFRFault(), false);
406 EXPECT_EQ(psu2.hasVINUVFault(), false);
407 EXPECT_EQ(psu2.hasCommFault(), false);
408 EXPECT_EQ(psu2.hasVoutOVFault(), false);
409 EXPECT_EQ(psu2.hasIoutOCFault(), true);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000410 EXPECT_EQ(psu2.hasVoutUVFault(), false);
411 EXPECT_EQ(psu2.hasTempFault(), false);
412 EXPECT_EQ(psu2.hasPgoodFault(), false);
413 }
414
415 // VOUT_UV_FAULT
416 {
417 // First STATUS_WORD with no bits set, then with VOUT fault.
418 PMBusExpectations expectations;
419 setPMBusExpectations(mockPMBus, expectations);
420 psu2.analyze();
421 // Change STATUS_WORD to indicate VOUT fault.
422 expectations.statusWordValue = (status_word::VOUT_FAULT);
423 // Turn on STATUS_VOUT fault bit(s)
424 expectations.statusVOUTValue = 0x30;
425 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(), false);
434 EXPECT_EQ(psu2.hasIoutOCFault(), false);
435 EXPECT_EQ(psu2.hasVoutUVFault(), true);
Brandon Wyman96893a42021-11-05 19:56:57 +0000436 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000437 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000438 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600439
440 // Ignore fan fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000441 {
442 // First STATUS_WORD with no bits set, then with fan fault.
443 PMBusExpectations expectations;
444 setPMBusExpectations(mockPMBus, expectations);
445 psu2.analyze();
446 expectations.statusWordValue = (status_word::FAN_FAULT);
447 setPMBusExpectations(mockPMBus, expectations);
448 psu2.analyze();
449 EXPECT_EQ(psu2.isPresent(), true);
450 EXPECT_EQ(psu2.isFaulted(), false);
451 EXPECT_EQ(psu2.hasInputFault(), false);
452 EXPECT_EQ(psu2.hasMFRFault(), false);
453 EXPECT_EQ(psu2.hasVINUVFault(), false);
454 EXPECT_EQ(psu2.hasCommFault(), false);
455 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000456 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000457 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000458 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000459 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000460 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000461
Brandon Wyman2cf46942021-10-28 19:09:16 +0000462 // PGOOD/OFF fault.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000463 {
Brandon Wyman2916ea52021-11-06 03:31:18 +0000464 // First STATUS_WORD with no bits set.
465 PMBusExpectations expectations;
466 setPMBusExpectations(mockPMBus, expectations);
467 psu2.analyze();
468 EXPECT_EQ(psu2.isFaulted(), false);
469 // POWER_GOOD# inactive, and OFF bit on.
470 expectations.statusWordValue =
471 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
472 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
473 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
474 setPMBusExpectations(mockPMBus, expectations);
475 psu2.analyze();
476 EXPECT_EQ(psu2.isPresent(), true);
477 EXPECT_EQ(psu2.isFaulted(), true);
478 EXPECT_EQ(psu2.hasInputFault(), false);
479 EXPECT_EQ(psu2.hasMFRFault(), false);
480 EXPECT_EQ(psu2.hasVINUVFault(), false);
481 EXPECT_EQ(psu2.hasCommFault(), false);
482 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000483 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000484 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000485 EXPECT_EQ(psu2.hasTempFault(), false);
486 EXPECT_EQ(psu2.hasPgoodFault(), true);
487 }
488
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600489 // TODO: ReadFailure
490}
491
Brandon Wyman59a35792020-06-04 12:37:40 -0500492TEST_F(PowerSupplyTests, OnOffConfig)
493{
494 auto bus = sdbusplus::bus::new_default();
495 uint8_t data = 0x15;
496
497 // Test where PSU is NOT present
498 try
499 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000500 // Assume GPIO presence, not inventory presence?
501 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
502
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000503 MockedGPIOInterface* mockPresenceGPIO =
504 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000505 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
Brandon Wyman59a35792020-06-04 12:37:40 -0500506 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000507 // Constructor should set initial presence, default read returns 0.
Brandon Wyman59a35792020-06-04 12:37:40 -0500508 // If it is not present, I should not be trying to write to it.
509 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
510 psu.onOffConfig(data);
511 }
512 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000513 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500514
515 // Test where PSU is present
516 try
517 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000518 // Assume GPIO presence, not inventory presence?
519 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000520 MockedGPIOInterface* mockPresenceGPIO =
521 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000522 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1));
Brandon Wyman59a35792020-06-04 12:37:40 -0500523 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000524 // TODO: expect setPresence call?
525 // updatePresence() private function reads gpio, called by analyze().
526 psu.analyze();
Brandon Wyman59a35792020-06-04 12:37:40 -0500527 // TODO: ???should I check the filename?
528 EXPECT_CALL(mockPMBus,
529 writeBinary(_, ElementsAre(0x15), Type::HwmonDeviceDebug))
530 .Times(1);
531 psu.onOffConfig(data);
532 }
533 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000534 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500535}
536
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600537TEST_F(PowerSupplyTests, ClearFaults)
538{
539 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000540 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000541 MockedGPIOInterface* mockPresenceGPIO =
542 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000543 // GPIO read return 1 to indicate present.
544 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1));
545 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman8da35c52021-10-28 22:45:08 +0000546 // Presence change from missing to present will trigger in1_input read in
547 // an attempt to get CLEAR_FAULTS called.
548 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000));
549 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000550 PMBusExpectations expectations;
551 setPMBusExpectations(mockPMBus, expectations);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000552 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600553 EXPECT_EQ(psu.isPresent(), true);
554 EXPECT_EQ(psu.isFaulted(), false);
555 EXPECT_EQ(psu.hasInputFault(), false);
556 EXPECT_EQ(psu.hasMFRFault(), false);
557 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000558 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000559 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000560 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000561 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000562 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000563 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000564
Brandon Wymanf07bc792021-10-12 19:00:35 +0000565 // STATUS_WORD with fault bits galore!
Brandon Wymanb654c612021-11-05 23:24:51 +0000566 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000567 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000568 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000569 // STATUS_MFR_SPEFIC with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000570 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000571 // STATUS_CML with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000572 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000573 // STATUS_VOUT with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000574 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000575 // STATUS_IOUT with bits on.
576 expectations.statusIOUTValue = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000577 // STATUS_TEMPERATURE with bits on.
578 expectations.statusTempValue = 0xFF;
Brandon Wymanb654c612021-11-05 23:24:51 +0000579 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600580 psu.analyze();
581 EXPECT_EQ(psu.isPresent(), true);
582 EXPECT_EQ(psu.isFaulted(), true);
583 EXPECT_EQ(psu.hasInputFault(), true);
584 EXPECT_EQ(psu.hasMFRFault(), true);
585 EXPECT_EQ(psu.hasVINUVFault(), true);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000586 EXPECT_EQ(psu.hasCommFault(), true);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000587 EXPECT_EQ(psu.hasVoutOVFault(), true);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000588 EXPECT_EQ(psu.hasIoutOCFault(), true);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000589 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
590 // Rely on HasVoutUVFault() to verify this sets and clears.
591 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000592 EXPECT_EQ(psu.hasTempFault(), true);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000593 EXPECT_EQ(psu.hasPgoodFault(), true);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000594
Brandon Wyman3c208462020-05-13 16:25:58 -0500595 EXPECT_CALL(mockPMBus, read("in1_input", _))
596 .Times(1)
597 .WillOnce(Return(209000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600598 psu.clearFaults();
599 EXPECT_EQ(psu.isPresent(), true);
600 EXPECT_EQ(psu.isFaulted(), false);
601 EXPECT_EQ(psu.hasInputFault(), false);
602 EXPECT_EQ(psu.hasMFRFault(), false);
603 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000604 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000605 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000606 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000607 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000608 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000609 EXPECT_EQ(psu.hasPgoodFault(), false);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000610
611 // TODO: Faults clear on missing/present?
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600612}
613
614TEST_F(PowerSupplyTests, UpdateInventory)
615{
616 auto bus = sdbusplus::bus::new_default();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500617
618 try
619 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000620 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500621 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
622 // If it is not present, I should not be trying to read a string
623 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
624 psu.updateInventory();
625 }
626 catch (...)
627 {
628 ADD_FAILURE() << "Should not have caught exception.";
629 }
630
631 try
632 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000633 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000634 MockedGPIOInterface* mockPresenceGPIO =
635 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000636 // GPIO read return 1 to indicate present.
637 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
638 psu.analyze();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500639 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
640 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
641 psu.updateInventory();
642
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500643#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500644 EXPECT_CALL(mockPMBus, readString(_, _))
645 .WillOnce(Return("CCIN"))
646 .WillOnce(Return("PN3456"))
647 .WillOnce(Return("FN3456"))
648 .WillOnce(Return("HEADER"))
649 .WillOnce(Return("SN3456"))
650 .WillOnce(Return("FW3456"));
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500651#endif
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500652 psu.updateInventory();
653 // TODO: D-Bus mocking to verify values stored on D-Bus (???)
654 }
655 catch (...)
656 {
657 ADD_FAILURE() << "Should not have caught exception.";
658 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600659}
660
661TEST_F(PowerSupplyTests, IsPresent)
662{
663 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000664
665 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000666 MockedGPIOInterface* mockPresenceGPIO =
667 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600668 EXPECT_EQ(psu.isPresent(), false);
669
B. J. Wyman681b2a32021-04-20 22:31:22 +0000670 // Change GPIO read to return 1 to indicate present.
671 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
672 psu.analyze();
673 EXPECT_EQ(psu.isPresent(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600674}
675
676TEST_F(PowerSupplyTests, IsFaulted)
677{
678 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000679
680 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000681 MockedGPIOInterface* mockPresenceGPIO =
682 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000683 // Always return 1 to indicate present.
684 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
685 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600686 EXPECT_EQ(psu.isFaulted(), false);
687 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wymanb654c612021-11-05 23:24:51 +0000688 PMBusExpectations expectations;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000689 // STATUS_WORD with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000690 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000691 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000692 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000693 // STATUS_MFR_SPECIFIC with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000694 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000695 // STATUS_CML with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000696 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000697 // STATUS_VOUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000698 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000699 // STATUS_IOUT with fault bits on.
700 expectations.statusIOUTValue = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000701 // STATUS_TEMPERATURE with fault bits on.
702 expectations.statusTempValue = 0xFF;
Brandon Wymanb654c612021-11-05 23:24:51 +0000703 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600704 psu.analyze();
705 EXPECT_EQ(psu.isFaulted(), true);
706}
707
708TEST_F(PowerSupplyTests, HasInputFault)
709{
710 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000711
712 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000713 MockedGPIOInterface* mockPresenceGPIO =
714 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000715 // Always return 1 to indicate present.
716 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
717 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600718 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
719 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000720 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000721 PMBusExpectations expectations;
722 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600723 psu.analyze();
724 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000725 // STATUS_WORD with input fault/warn on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000726 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000727 // STATUS_INPUT with an input fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000728 expectations.statusInputValue = 0x80;
729 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600730 psu.analyze();
731 EXPECT_EQ(psu.hasInputFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000732 // STATUS_WORD with no bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000733 expectations.statusWordValue = 0;
734 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600735 psu.analyze();
736 EXPECT_EQ(psu.hasInputFault(), false);
737}
738
739TEST_F(PowerSupplyTests, HasMFRFault)
740{
741 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000742
743 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, 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 // Always return 1 to indicate present.
747 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
748 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600749 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
750 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000751 // First return STATUS_WORD with no bits on.
Brandon Wyman8da35c52021-10-28 22:45:08 +0000752 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000753 PMBusExpectations expectations;
754 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600755 psu.analyze();
756 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000757 // Next return STATUS_WORD with MFR fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000758 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000759 // STATUS_MFR_SPEFIC with bit(s) on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000760 expectations.statusMFRValue = 0xFF;
761 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600762 psu.analyze();
763 EXPECT_EQ(psu.hasMFRFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000764 // Back to no bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +0000765 expectations.statusWordValue = 0;
766 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600767 psu.analyze();
768 EXPECT_EQ(psu.hasMFRFault(), false);
769}
770
771TEST_F(PowerSupplyTests, HasVINUVFault)
772{
773 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000774
775 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000776 MockedGPIOInterface* mockPresenceGPIO =
777 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000778 // Always return 1 to indicate present.
779 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
780 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600781 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
782 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000783 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000784 PMBusExpectations expectations;
785 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600786 psu.analyze();
787 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000788 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000789 expectations.statusWordValue = (status_word::VIN_UV_FAULT);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000790 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
791 // Figure 16, and assume bits on in STATUS_INPUT.
Brandon Wymanb654c612021-11-05 23:24:51 +0000792 expectations.statusInputValue = 0x18;
793 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600794 psu.analyze();
795 EXPECT_EQ(psu.hasVINUVFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000796 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +0000797 expectations.statusWordValue = 0;
798 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600799 psu.analyze();
800 EXPECT_EQ(psu.hasVINUVFault(), false);
801}
Brandon Wyman6710ba22021-10-27 17:39:31 +0000802
803TEST_F(PowerSupplyTests, HasVoutOVFault)
804{
805 auto bus = sdbusplus::bus::new_default();
806
807 PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName};
808 MockedGPIOInterface* mockPresenceGPIO =
809 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
810 // Always return 1 to indicate present.
811 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
812 psu.analyze();
813 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
814 EXPECT_EQ(psu.hasVoutOVFault(), false);
815 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000816 PMBusExpectations expectations;
817 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000818 psu.analyze();
819 EXPECT_EQ(psu.hasVoutOVFault(), false);
820 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000821 expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000822 // STATUS_VOUT fault bit(s)
Brandon Wymanb654c612021-11-05 23:24:51 +0000823 expectations.statusVOUTValue = 0x80;
Brandon Wyman96893a42021-11-05 19:56:57 +0000824 // STATUS_TEMPERATURE default.
Brandon Wymanb654c612021-11-05 23:24:51 +0000825 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000826 psu.analyze();
827 EXPECT_EQ(psu.hasVoutOVFault(), true);
828 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +0000829 expectations.statusWordValue = 0;
830 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000831 psu.analyze();
832 EXPECT_EQ(psu.hasVoutOVFault(), false);
833}
Brandon Wyman96893a42021-11-05 19:56:57 +0000834
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000835TEST_F(PowerSupplyTests, HasIoutOCFault)
836{
837 auto bus = sdbusplus::bus::new_default();
838
839 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
840 MockedGPIOInterface* mockPresenceGPIO =
841 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
842 // Always return 1 to indicate present.
843 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
844 psu.analyze();
845 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
846 EXPECT_EQ(psu.hasIoutOCFault(), false);
847 // STATUS_WORD 0x0000 is powered on, no faults.
848 PMBusExpectations expectations;
849 setPMBusExpectations(mockPMBus, expectations);
850 psu.analyze();
851 EXPECT_EQ(psu.hasIoutOCFault(), false);
852 // Turn fault on.
853 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
854 // STATUS_IOUT fault bit(s)
855 expectations.statusIOUTValue = 0x88;
856 setPMBusExpectations(mockPMBus, expectations);
857 psu.analyze();
858 EXPECT_EQ(psu.hasIoutOCFault(), true);
859 // Back to no fault bits on in STATUS_WORD
860 expectations.statusWordValue = 0;
861 setPMBusExpectations(mockPMBus, expectations);
862 psu.analyze();
863 EXPECT_EQ(psu.hasIoutOCFault(), false);
864}
865
Brandon Wyman2cf46942021-10-28 19:09:16 +0000866TEST_F(PowerSupplyTests, HasVoutUVFault)
867{
868 auto bus = sdbusplus::bus::new_default();
869
870 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
871 MockedGPIOInterface* mockPresenceGPIO =
872 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
873 // Always return 1 to indicate present.
874 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
875 psu.analyze();
876 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
877 EXPECT_EQ(psu.hasVoutUVFault(), false);
878 PMBusExpectations expectations;
879 setPMBusExpectations(mockPMBus, expectations);
880 psu.analyze();
881 EXPECT_EQ(psu.hasVoutUVFault(), false);
882 // Turn fault on.
883 expectations.statusWordValue = (status_word::VOUT_FAULT);
884 // STATUS_VOUT fault bit(s)
885 expectations.statusVOUTValue = 0x30;
886 setPMBusExpectations(mockPMBus, expectations);
887 psu.analyze();
888 EXPECT_EQ(psu.hasVoutUVFault(), true);
889 // Back to no fault bits on in STATUS_WORD
890 expectations.statusWordValue = 0;
891 setPMBusExpectations(mockPMBus, expectations);
892 psu.analyze();
893 EXPECT_EQ(psu.hasVoutUVFault(), false);
894}
895
Brandon Wyman96893a42021-11-05 19:56:57 +0000896TEST_F(PowerSupplyTests, HasTempFault)
897{
898 auto bus = sdbusplus::bus::new_default();
899
900 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
901 MockedGPIOInterface* mockPresenceGPIO =
902 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
903 // Always return 1 to indicate present.
904 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
905 psu.analyze();
906 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
907 EXPECT_EQ(psu.hasTempFault(), false);
908 // STATUS_WORD 0x0000 is powered on, no faults.
909 PMBusExpectations expectations;
910 setPMBusExpectations(mockPMBus, expectations);
911 psu.analyze();
912 EXPECT_EQ(psu.hasTempFault(), false);
913 // Turn fault on.
914 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
915 // STATUS_TEMPERATURE fault bit on (OT Fault)
916 expectations.statusTempValue = 0x80;
917 setPMBusExpectations(mockPMBus, expectations);
918 psu.analyze();
919 EXPECT_EQ(psu.hasTempFault(), true);
920 // Back to no fault bits on in STATUS_WORD
921 expectations.statusWordValue = 0;
922 setPMBusExpectations(mockPMBus, expectations);
923 psu.analyze();
924 EXPECT_EQ(psu.hasTempFault(), false);
925}
Brandon Wyman2916ea52021-11-06 03:31:18 +0000926
927TEST_F(PowerSupplyTests, HasPgoodFault)
928{
929 auto bus = sdbusplus::bus::new_default();
930
931 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, PSUGPIOLineName};
932 MockedGPIOInterface* mockPresenceGPIO =
933 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
934 // Always return 1 to indicate present.
935 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
936 psu.analyze();
937 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
938 EXPECT_EQ(psu.hasPgoodFault(), false);
939 // STATUS_WORD 0x0000 is powered on, no faults.
940 PMBusExpectations expectations;
941 setPMBusExpectations(mockPMBus, expectations);
942 psu.analyze();
943 EXPECT_EQ(psu.hasPgoodFault(), false);
944 // Turn PGOOD# off (fault on).
945 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
946 setPMBusExpectations(mockPMBus, expectations);
947 psu.analyze();
948 EXPECT_EQ(psu.hasPgoodFault(), true);
949 // Back to no fault bits on in STATUS_WORD
950 expectations.statusWordValue = 0;
951 setPMBusExpectations(mockPMBus, expectations);
952 psu.analyze();
953 EXPECT_EQ(psu.hasPgoodFault(), false);
954 // Turn OFF bit on
955 expectations.statusWordValue = (status_word::UNIT_IS_OFF);
956 setPMBusExpectations(mockPMBus, expectations);
957 psu.analyze();
958 EXPECT_EQ(psu.hasPgoodFault(), true);
959 // Back to no fault bits on in STATUS_WORD
960 expectations.statusWordValue = 0;
961 setPMBusExpectations(mockPMBus, expectations);
962 psu.analyze();
963 EXPECT_EQ(psu.hasPgoodFault(), false);
964}