blob: d42d359d9df8ee6aa497daf302538cafcb225bee [file] [log] [blame]
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001#include "../power_supply.hpp"
2#include "mock.hpp"
3
4#include <xyz/openbmc_project/Common/Device/error.hpp>
5#include <xyz/openbmc_project/Common/error.hpp>
6
7#include <gmock/gmock.h>
8#include <gtest/gtest.h>
9
10using namespace phosphor::power::psu;
11using namespace phosphor::pmbus;
12
13using ::testing::_;
Brandon Wyman59a35792020-06-04 12:37:40 -050014using ::testing::Args;
Brandon Wyman3f1242f2020-01-28 13:11:25 -060015using ::testing::Assign;
16using ::testing::DoAll;
Brandon Wyman59a35792020-06-04 12:37:40 -050017using ::testing::ElementsAre;
18using ::testing::NotNull;
Brandon Wyman3f1242f2020-01-28 13:11:25 -060019using ::testing::Return;
20using ::testing::StrEq;
21
22static auto PSUInventoryPath = "/xyz/bmc/inv/sys/chassis/board/powersupply0";
B. J. Wyman681b2a32021-04-20 22:31:22 +000023static auto PSUGPIOLineName = "presence-ps0";
Brandon Wyman3f1242f2020-01-28 13:11:25 -060024
Brandon Wymanb654c612021-11-05 23:24:51 +000025struct PMBusExpectations
26{
27 uint16_t statusWordValue{0x0000};
28 uint8_t statusInputValue{0x00};
29 uint8_t statusMFRValue{0x00};
30 uint8_t statusCMLValue{0x00};
31 uint8_t statusVOUTValue{0x00};
Brandon Wymanb10b3be2021-11-09 22:12:15 +000032 uint8_t statusIOUTValue{0x00};
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +000033 uint8_t statusFans12Value{0x00};
Brandon Wyman96893a42021-11-05 19:56:57 +000034 uint8_t statusTempValue{0x00};
Brandon Wymanb654c612021-11-05 23:24:51 +000035};
36
Brandon Wyman8da35c52021-10-28 22:45:08 +000037// Helper function to setup expectations for various STATUS_* commands
Brandon Wymanb654c612021-11-05 23:24:51 +000038void setPMBusExpectations(MockedPMBus& mockPMBus,
39 const PMBusExpectations& expectations)
Brandon Wyman8da35c52021-10-28 22:45:08 +000040{
41 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
42 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000043 .WillOnce(Return(expectations.statusWordValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000044
Brandon Wymanb654c612021-11-05 23:24:51 +000045 if (expectations.statusWordValue != 0)
Brandon Wyman8da35c52021-10-28 22:45:08 +000046 {
47 // If fault bits are on in STATUS_WORD, there will also be a read of
Brandon Wyman96893a42021-11-05 19:56:57 +000048 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and
49 // STATUS_TEMPERATURE.
Brandon Wyman8da35c52021-10-28 22:45:08 +000050 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
51 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000052 .WillOnce(Return(expectations.statusInputValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000053 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _))
54 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000055 .WillOnce(Return(expectations.statusMFRValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000056 EXPECT_CALL(mockPMBus, read(STATUS_CML, _))
57 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000058 .WillOnce(Return(expectations.statusCMLValue));
Brandon Wyman6710ba22021-10-27 17:39:31 +000059 // Page will need to be set to 0 to read STATUS_VOUT.
60 EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0))
61 .Times(1)
62 .WillOnce(Return("status0_vout"));
63 EXPECT_CALL(mockPMBus, read("status0_vout", _))
64 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000065 .WillOnce(Return(expectations.statusVOUTValue));
Brandon Wymanb10b3be2021-11-09 22:12:15 +000066 EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _))
67 .Times(1)
68 .WillOnce(Return(expectations.statusIOUTValue));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +000069 EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _))
70 .Times(1)
71 .WillOnce(Return(expectations.statusFans12Value));
Brandon Wyman96893a42021-11-05 19:56:57 +000072 EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _))
73 .Times(1)
74 .WillOnce(Return(expectations.statusTempValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000075 }
76}
77
Brandon Wyman3f1242f2020-01-28 13:11:25 -060078class PowerSupplyTests : public ::testing::Test
79{
80 public:
81 PowerSupplyTests() :
82 mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
83 {
84 ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
85 }
86
87 ~PowerSupplyTests() override
88 {
89 freeUtils();
90 }
91
92 const MockedUtil& mockedUtil;
93};
94
95TEST_F(PowerSupplyTests, Constructor)
96{
97 /**
98 * @param[in] invpath - String for inventory path to use
99 * @param[in] i2cbus - The bus number this power supply is on
100 * @param[in] i2caddr - The 16-bit I2C address of the power supply
B. J. Wyman681b2a32021-04-20 22:31:22 +0000101 * @param[in] gpioLineName - The string for the gpio-line-name to read for
102 * presence.
103 * @param[in] bindDelay - Time in milliseconds to delay binding the device
104 * driver after seeing the presence line go active.
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600105 */
106 auto bus = sdbusplus::bus::new_default();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600107
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500108 // Try where inventory path is empty, constructor should fail.
109 try
110 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000111 auto psu =
112 std::make_unique<PowerSupply>(bus, "", 3, 0x68, PSUGPIOLineName);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500113 ADD_FAILURE() << "Should not have reached this line.";
114 }
115 catch (const std::invalid_argument& e)
116 {
117 EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
118 }
119 catch (...)
120 {
121 ADD_FAILURE() << "Should not have caught exception.";
122 }
123
B. J. Wyman681b2a32021-04-20 22:31:22 +0000124 // TODO: Try invalid i2c address?
125
126 // Try where gpioLineName is empty.
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500127 try
128 {
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500129 auto psu =
B. J. Wyman681b2a32021-04-20 22:31:22 +0000130 std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, "");
131 ADD_FAILURE()
132 << "Should not have reached this line. Invalid gpioLineName.";
133 }
134 catch (const std::invalid_argument& e)
135 {
136 EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
137 }
138 catch (...)
139 {
140 ADD_FAILURE() << "Should not have caught exception.";
141 }
142
143 // Test with valid arguments
144 // NOT using D-Bus inventory path for presence.
145 try
146 {
147 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
148 PSUGPIOLineName);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500149
150 EXPECT_EQ(psu->isPresent(), false);
151 EXPECT_EQ(psu->isFaulted(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000152 EXPECT_EQ(psu->hasCommFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500153 EXPECT_EQ(psu->hasInputFault(), false);
154 EXPECT_EQ(psu->hasMFRFault(), false);
155 EXPECT_EQ(psu->hasVINUVFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000156 EXPECT_EQ(psu->hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000157 EXPECT_EQ(psu->hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000158 EXPECT_EQ(psu->hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000159 EXPECT_EQ(psu->hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000160 EXPECT_EQ(psu->hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000161 EXPECT_EQ(psu->hasPgoodFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500162 }
163 catch (...)
164 {
165 ADD_FAILURE() << "Should not have caught exception.";
166 }
B. J. Wyman681b2a32021-04-20 22:31:22 +0000167
168 // Test with valid arguments
169 // TODO: Using D-Bus inventory path for presence.
170 try
171 {
172 // FIXME: How do I get that presenceGPIO.read() in the startup to throw
173 // an exception?
174
175 // EXPECT_CALL(mockedUtil, getPresence(_,
176 // StrEq(PSUInventoryPath)))
177 // .Times(1);
178 }
179 catch (...)
180 {
181 ADD_FAILURE() << "Should not have caught exception.";
182 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600183}
184
185TEST_F(PowerSupplyTests, Analyze)
186{
187 auto bus = sdbusplus::bus::new_default();
188
Brandon Wymanb654c612021-11-05 23:24:51 +0000189 {
190 // If I default to reading the GPIO, I will NOT expect a call to
191 // getPresence().
B. J. Wyman681b2a32021-04-20 22:31:22 +0000192
Brandon Wymanb654c612021-11-05 23:24:51 +0000193 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
194 MockedGPIOInterface* mockPresenceGPIO =
195 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
196 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000197
Brandon Wymanb654c612021-11-05 23:24:51 +0000198 psu.analyze();
199 // By default, nothing should change.
200 EXPECT_EQ(psu.isPresent(), false);
201 EXPECT_EQ(psu.isFaulted(), false);
202 EXPECT_EQ(psu.hasInputFault(), false);
203 EXPECT_EQ(psu.hasMFRFault(), false);
204 EXPECT_EQ(psu.hasVINUVFault(), false);
205 EXPECT_EQ(psu.hasCommFault(), false);
206 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000207 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000208 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000209 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000210 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000211 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000212 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600213
B. J. Wyman681b2a32021-04-20 22:31:22 +0000214 PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
215 // In order to get the various faults tested, the power supply needs to
216 // be present in order to read from the PMBus device(s).
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000217 MockedGPIOInterface* mockPresenceGPIO2 =
218 static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000219 ON_CALL(*mockPresenceGPIO2, read()).WillByDefault(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000220 EXPECT_EQ(psu2.isPresent(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600221
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600222 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
Brandon Wyman8da35c52021-10-28 22:45:08 +0000223 // Presence change from missing to present will trigger write to
224 // ON_OFF_CONFIG.
225 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, _, _));
Brandon Wymanb654c612021-11-05 23:24:51 +0000226 // Presence change from missing to present will trigger in1_input read
227 // in an attempt to get CLEAR_FAULTS called.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000228 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600229
Brandon Wymanb654c612021-11-05 23:24:51 +0000230 // STATUS_WORD INPUT fault.
231 {
232 // Start with STATUS_WORD 0x0000. Powered on, no faults.
233 // Set expectations for a no fault
234 PMBusExpectations expectations;
235 setPMBusExpectations(mockPMBus, expectations);
236 psu2.analyze();
237 EXPECT_EQ(psu2.isPresent(), true);
238 EXPECT_EQ(psu2.isFaulted(), false);
239 EXPECT_EQ(psu2.hasInputFault(), false);
240 EXPECT_EQ(psu2.hasMFRFault(), false);
241 EXPECT_EQ(psu2.hasVINUVFault(), false);
242 EXPECT_EQ(psu2.hasCommFault(), false);
243 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000244 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000245 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000246 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000247 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000248 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000249
250 // Update expectations for STATUS_WORD input fault/warn
Brandon Wyman96893a42021-11-05 19:56:57 +0000251 // STATUS_INPUT fault bits ... on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000252 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
253 expectations.statusInputValue = 0x38;
254 setPMBusExpectations(mockPMBus, expectations);
255 psu2.analyze();
256 EXPECT_EQ(psu2.isPresent(), true);
257 EXPECT_EQ(psu2.isFaulted(), true);
258 EXPECT_EQ(psu2.hasInputFault(), true);
259 EXPECT_EQ(psu2.hasMFRFault(), false);
260 EXPECT_EQ(psu2.hasVINUVFault(), false);
261 EXPECT_EQ(psu2.hasCommFault(), false);
262 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000263 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000264 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000265 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000266 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000267 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000268 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600269
270 // STATUS_WORD INPUT/UV fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000271 {
272 // First need it to return good status, then the fault
273 PMBusExpectations expectations;
274 setPMBusExpectations(mockPMBus, expectations);
275 psu2.analyze();
276 // Now set fault bits in STATUS_WORD
277 expectations.statusWordValue =
278 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
279 // STATUS_INPUT fault bits ... on.
280 expectations.statusInputValue = 0x38;
281 setPMBusExpectations(mockPMBus, expectations);
282 psu2.analyze();
283 EXPECT_EQ(psu2.isPresent(), true);
284 EXPECT_EQ(psu2.isFaulted(), true);
285 EXPECT_EQ(psu2.hasInputFault(), true);
286 EXPECT_EQ(psu2.hasMFRFault(), false);
287 EXPECT_EQ(psu2.hasVINUVFault(), true);
288 EXPECT_EQ(psu2.hasCommFault(), false);
289 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000290 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000291 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000292 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000293 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000294 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000295 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600296
297 // STATUS_WORD MFR fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000298 {
299 // First need it to return good status, then the fault
300 PMBusExpectations expectations;
301 setPMBusExpectations(mockPMBus, expectations);
302 psu2.analyze();
303 // Now STATUS_WORD with MFR fault bit on.
304 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
305 // STATUS_MFR bits on.
306 expectations.statusMFRValue = 0xFF;
307 setPMBusExpectations(mockPMBus, expectations);
308 psu2.analyze();
309 EXPECT_EQ(psu2.isPresent(), true);
310 EXPECT_EQ(psu2.isFaulted(), true);
311 EXPECT_EQ(psu2.hasInputFault(), false);
312 EXPECT_EQ(psu2.hasMFRFault(), true);
313 EXPECT_EQ(psu2.hasVINUVFault(), false);
314 EXPECT_EQ(psu2.hasCommFault(), false);
315 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000316 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000317 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000318 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000319 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000320 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000321 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600322
Brandon Wyman96893a42021-11-05 19:56:57 +0000323 // Temperature fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000324 {
325 // First STATUS_WORD with no bits set, then with temperature fault.
326 PMBusExpectations expectations;
327 setPMBusExpectations(mockPMBus, expectations);
328 psu2.analyze();
329 // STATUS_WORD with temperature fault bit on.
330 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
Brandon Wyman96893a42021-11-05 19:56:57 +0000331 // STATUS_TEMPERATURE with fault bit(s) on.
332 expectations.statusTempValue = 0x10;
Brandon Wymanb654c612021-11-05 23:24:51 +0000333 setPMBusExpectations(mockPMBus, expectations);
334 psu2.analyze();
335 EXPECT_EQ(psu2.isPresent(), true);
Brandon Wyman96893a42021-11-05 19:56:57 +0000336 EXPECT_EQ(psu2.isFaulted(), true);
Brandon Wymanb654c612021-11-05 23:24:51 +0000337 EXPECT_EQ(psu2.hasInputFault(), false);
338 EXPECT_EQ(psu2.hasMFRFault(), false);
339 EXPECT_EQ(psu2.hasVINUVFault(), false);
340 EXPECT_EQ(psu2.hasCommFault(), false);
341 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000342 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000343 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000344 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000345 EXPECT_EQ(psu2.hasTempFault(), true);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000346 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000347 }
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000348
349 // CML fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000350 {
351 // First STATUS_WORD wit no bits set, then with CML fault.
352 PMBusExpectations expectations;
353 setPMBusExpectations(mockPMBus, expectations);
354 psu2.analyze();
355 // STATUS_WORD with CML fault bit on.
356 expectations.statusWordValue = (status_word::CML_FAULT);
357 // Turn on STATUS_CML fault bit(s)
358 expectations.statusCMLValue = 0xFF;
359 setPMBusExpectations(mockPMBus, expectations);
360 psu2.analyze();
361 EXPECT_EQ(psu2.isPresent(), true);
362 EXPECT_EQ(psu2.isFaulted(), true);
363 EXPECT_EQ(psu2.hasInputFault(), false);
364 EXPECT_EQ(psu2.hasMFRFault(), false);
365 EXPECT_EQ(psu2.hasVINUVFault(), false);
366 EXPECT_EQ(psu2.hasCommFault(), true);
367 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000368 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000369 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000370 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000371 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000372 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000373 }
Brandon Wyman6710ba22021-10-27 17:39:31 +0000374
375 // VOUT_OV_FAULT fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000376 {
377 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
378 PMBusExpectations expectations;
379 setPMBusExpectations(mockPMBus, expectations);
380 psu2.analyze();
381 // STATUS_WORD with VOUT/VOUT_OV fault.
382 expectations.statusWordValue =
383 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
384 // Turn on STATUS_VOUT fault bit(s)
385 expectations.statusVOUTValue = 0xA0;
Brandon Wyman96893a42021-11-05 19:56:57 +0000386 // STATUS_TEMPERATURE don't care (default)
Brandon Wymanb654c612021-11-05 23:24:51 +0000387 setPMBusExpectations(mockPMBus, expectations);
388 psu2.analyze();
389 EXPECT_EQ(psu2.isPresent(), true);
390 EXPECT_EQ(psu2.isFaulted(), true);
391 EXPECT_EQ(psu2.hasInputFault(), false);
392 EXPECT_EQ(psu2.hasMFRFault(), false);
393 EXPECT_EQ(psu2.hasVINUVFault(), false);
394 EXPECT_EQ(psu2.hasCommFault(), false);
395 EXPECT_EQ(psu2.hasVoutOVFault(), true);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000396 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000397 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000398 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000399 EXPECT_EQ(psu2.hasTempFault(), false);
400 EXPECT_EQ(psu2.hasPgoodFault(), false);
401 }
402
403 // IOUT_OC_FAULT fault
404 {
405 // First STATUS_WORD with no bits set, then with IOUT_OC fault.
406 PMBusExpectations expectations;
407 setPMBusExpectations(mockPMBus, expectations);
408 psu2.analyze();
409 // STATUS_WORD with IOUT_OC fault.
410 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
411 // Turn on STATUS_IOUT fault bit(s)
412 expectations.statusIOUTValue = 0x88;
413 setPMBusExpectations(mockPMBus, expectations);
414 psu2.analyze();
415 EXPECT_EQ(psu2.isPresent(), true);
416 EXPECT_EQ(psu2.isFaulted(), true);
417 EXPECT_EQ(psu2.hasInputFault(), false);
418 EXPECT_EQ(psu2.hasMFRFault(), false);
419 EXPECT_EQ(psu2.hasVINUVFault(), false);
420 EXPECT_EQ(psu2.hasCommFault(), false);
421 EXPECT_EQ(psu2.hasVoutOVFault(), false);
422 EXPECT_EQ(psu2.hasIoutOCFault(), true);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000423 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000424 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000425 EXPECT_EQ(psu2.hasTempFault(), false);
426 EXPECT_EQ(psu2.hasPgoodFault(), false);
427 }
428
429 // VOUT_UV_FAULT
430 {
431 // First STATUS_WORD with no bits set, then with VOUT fault.
432 PMBusExpectations expectations;
433 setPMBusExpectations(mockPMBus, expectations);
434 psu2.analyze();
435 // Change STATUS_WORD to indicate VOUT fault.
436 expectations.statusWordValue = (status_word::VOUT_FAULT);
437 // Turn on STATUS_VOUT fault bit(s)
438 expectations.statusVOUTValue = 0x30;
439 setPMBusExpectations(mockPMBus, expectations);
440 psu2.analyze();
441 EXPECT_EQ(psu2.isPresent(), true);
442 EXPECT_EQ(psu2.isFaulted(), true);
443 EXPECT_EQ(psu2.hasInputFault(), false);
444 EXPECT_EQ(psu2.hasMFRFault(), false);
445 EXPECT_EQ(psu2.hasVINUVFault(), false);
446 EXPECT_EQ(psu2.hasCommFault(), false);
447 EXPECT_EQ(psu2.hasVoutOVFault(), false);
448 EXPECT_EQ(psu2.hasIoutOCFault(), false);
449 EXPECT_EQ(psu2.hasVoutUVFault(), true);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000450 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000451 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000452 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000453 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600454
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000455 // Fan fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000456 {
457 // First STATUS_WORD with no bits set, then with fan fault.
458 PMBusExpectations expectations;
459 setPMBusExpectations(mockPMBus, expectations);
460 psu2.analyze();
461 expectations.statusWordValue = (status_word::FAN_FAULT);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000462 // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
463 expectations.statusFans12Value = 0xA0;
Brandon Wymanb654c612021-11-05 23:24:51 +0000464 setPMBusExpectations(mockPMBus, expectations);
465 psu2.analyze();
466 EXPECT_EQ(psu2.isPresent(), true);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000467 EXPECT_EQ(psu2.isFaulted(), true);
Brandon Wymanb654c612021-11-05 23:24:51 +0000468 EXPECT_EQ(psu2.hasInputFault(), false);
469 EXPECT_EQ(psu2.hasMFRFault(), false);
470 EXPECT_EQ(psu2.hasVINUVFault(), false);
471 EXPECT_EQ(psu2.hasCommFault(), false);
472 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000473 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000474 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000475 EXPECT_EQ(psu2.hasFanFault(), true);
Brandon Wyman96893a42021-11-05 19:56:57 +0000476 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000477 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000478 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000479
Brandon Wyman2cf46942021-10-28 19:09:16 +0000480 // PGOOD/OFF fault.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000481 {
Brandon Wyman2916ea52021-11-06 03:31:18 +0000482 // First STATUS_WORD with no bits set.
483 PMBusExpectations expectations;
484 setPMBusExpectations(mockPMBus, expectations);
485 psu2.analyze();
486 EXPECT_EQ(psu2.isFaulted(), false);
487 // POWER_GOOD# inactive, and OFF bit on.
488 expectations.statusWordValue =
489 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
490 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
491 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
492 setPMBusExpectations(mockPMBus, expectations);
493 psu2.analyze();
494 EXPECT_EQ(psu2.isPresent(), true);
495 EXPECT_EQ(psu2.isFaulted(), true);
496 EXPECT_EQ(psu2.hasInputFault(), false);
497 EXPECT_EQ(psu2.hasMFRFault(), false);
498 EXPECT_EQ(psu2.hasVINUVFault(), false);
499 EXPECT_EQ(psu2.hasCommFault(), false);
500 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000501 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000502 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000503 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000504 EXPECT_EQ(psu2.hasTempFault(), false);
505 EXPECT_EQ(psu2.hasPgoodFault(), true);
506 }
507
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600508 // TODO: ReadFailure
509}
510
Brandon Wyman59a35792020-06-04 12:37:40 -0500511TEST_F(PowerSupplyTests, OnOffConfig)
512{
513 auto bus = sdbusplus::bus::new_default();
514 uint8_t data = 0x15;
515
516 // Test where PSU is NOT present
517 try
518 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000519 // Assume GPIO presence, not inventory presence?
520 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
521
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000522 MockedGPIOInterface* mockPresenceGPIO =
523 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000524 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
Brandon Wyman59a35792020-06-04 12:37:40 -0500525 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000526 // Constructor should set initial presence, default read returns 0.
Brandon Wyman59a35792020-06-04 12:37:40 -0500527 // If it is not present, I should not be trying to write to it.
528 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
529 psu.onOffConfig(data);
530 }
531 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000532 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500533
534 // Test where PSU is present
535 try
536 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000537 // Assume GPIO presence, not inventory presence?
538 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000539 MockedGPIOInterface* mockPresenceGPIO =
540 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000541 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1));
Brandon Wyman59a35792020-06-04 12:37:40 -0500542 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000543 // TODO: expect setPresence call?
544 // updatePresence() private function reads gpio, called by analyze().
545 psu.analyze();
Brandon Wyman59a35792020-06-04 12:37:40 -0500546 // TODO: ???should I check the filename?
547 EXPECT_CALL(mockPMBus,
548 writeBinary(_, ElementsAre(0x15), Type::HwmonDeviceDebug))
549 .Times(1);
550 psu.onOffConfig(data);
551 }
552 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000553 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500554}
555
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600556TEST_F(PowerSupplyTests, ClearFaults)
557{
558 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000559 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000560 MockedGPIOInterface* mockPresenceGPIO =
561 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000562 // GPIO read return 1 to indicate present.
563 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1));
564 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman8da35c52021-10-28 22:45:08 +0000565 // Presence change from missing to present will trigger in1_input read in
566 // an attempt to get CLEAR_FAULTS called.
567 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000));
568 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000569 PMBusExpectations expectations;
570 setPMBusExpectations(mockPMBus, expectations);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000571 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600572 EXPECT_EQ(psu.isPresent(), true);
573 EXPECT_EQ(psu.isFaulted(), false);
574 EXPECT_EQ(psu.hasInputFault(), false);
575 EXPECT_EQ(psu.hasMFRFault(), false);
576 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000577 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000578 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000579 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000580 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000581 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000582 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000583 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000584
Brandon Wymanf07bc792021-10-12 19:00:35 +0000585 // STATUS_WORD with fault bits galore!
Brandon Wymanb654c612021-11-05 23:24:51 +0000586 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000587 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000588 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000589 // STATUS_MFR_SPEFIC with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000590 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000591 // STATUS_CML with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000592 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000593 // STATUS_VOUT with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000594 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000595 // STATUS_IOUT with bits on.
596 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000597 // STATUS_FANS_1_2 with bits on.
598 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000599 // STATUS_TEMPERATURE with bits on.
600 expectations.statusTempValue = 0xFF;
Brandon Wymanb654c612021-11-05 23:24:51 +0000601 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600602 psu.analyze();
603 EXPECT_EQ(psu.isPresent(), true);
604 EXPECT_EQ(psu.isFaulted(), true);
605 EXPECT_EQ(psu.hasInputFault(), true);
606 EXPECT_EQ(psu.hasMFRFault(), true);
607 EXPECT_EQ(psu.hasVINUVFault(), true);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000608 EXPECT_EQ(psu.hasCommFault(), true);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000609 EXPECT_EQ(psu.hasVoutOVFault(), true);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000610 EXPECT_EQ(psu.hasIoutOCFault(), true);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000611 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
612 // Rely on HasVoutUVFault() to verify this sets and clears.
613 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000614 EXPECT_EQ(psu.hasFanFault(), true);
Brandon Wyman96893a42021-11-05 19:56:57 +0000615 EXPECT_EQ(psu.hasTempFault(), true);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000616 EXPECT_EQ(psu.hasPgoodFault(), true);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000617
Brandon Wyman3c208462020-05-13 16:25:58 -0500618 EXPECT_CALL(mockPMBus, read("in1_input", _))
619 .Times(1)
620 .WillOnce(Return(209000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600621 psu.clearFaults();
622 EXPECT_EQ(psu.isPresent(), true);
623 EXPECT_EQ(psu.isFaulted(), false);
624 EXPECT_EQ(psu.hasInputFault(), false);
625 EXPECT_EQ(psu.hasMFRFault(), false);
626 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000627 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000628 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000629 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000630 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000631 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000632 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000633 EXPECT_EQ(psu.hasPgoodFault(), false);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000634
635 // TODO: Faults clear on missing/present?
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600636}
637
638TEST_F(PowerSupplyTests, UpdateInventory)
639{
640 auto bus = sdbusplus::bus::new_default();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500641
642 try
643 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000644 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500645 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
646 // If it is not present, I should not be trying to read a string
647 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
648 psu.updateInventory();
649 }
650 catch (...)
651 {
652 ADD_FAILURE() << "Should not have caught exception.";
653 }
654
655 try
656 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000657 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000658 MockedGPIOInterface* mockPresenceGPIO =
659 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000660 // GPIO read return 1 to indicate present.
661 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
662 psu.analyze();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500663 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
664 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
665 psu.updateInventory();
666
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500667#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500668 EXPECT_CALL(mockPMBus, readString(_, _))
669 .WillOnce(Return("CCIN"))
670 .WillOnce(Return("PN3456"))
671 .WillOnce(Return("FN3456"))
672 .WillOnce(Return("HEADER"))
673 .WillOnce(Return("SN3456"))
674 .WillOnce(Return("FW3456"));
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500675#endif
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500676 psu.updateInventory();
677 // TODO: D-Bus mocking to verify values stored on D-Bus (???)
678 }
679 catch (...)
680 {
681 ADD_FAILURE() << "Should not have caught exception.";
682 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600683}
684
685TEST_F(PowerSupplyTests, IsPresent)
686{
687 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000688
689 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000690 MockedGPIOInterface* mockPresenceGPIO =
691 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600692 EXPECT_EQ(psu.isPresent(), false);
693
B. J. Wyman681b2a32021-04-20 22:31:22 +0000694 // Change GPIO read to return 1 to indicate present.
695 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
696 psu.analyze();
697 EXPECT_EQ(psu.isPresent(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600698}
699
700TEST_F(PowerSupplyTests, IsFaulted)
701{
702 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000703
704 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000705 MockedGPIOInterface* mockPresenceGPIO =
706 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000707 // Always return 1 to indicate present.
708 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
709 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600710 EXPECT_EQ(psu.isFaulted(), false);
711 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wymanb654c612021-11-05 23:24:51 +0000712 PMBusExpectations expectations;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000713 // STATUS_WORD with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000714 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000715 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000716 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000717 // STATUS_MFR_SPECIFIC with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000718 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000719 // STATUS_CML with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000720 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000721 // STATUS_VOUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000722 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000723 // STATUS_IOUT with fault bits on.
724 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000725 // STATUS_FANS_1_2 with bits on.
726 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000727 // STATUS_TEMPERATURE with fault bits on.
728 expectations.statusTempValue = 0xFF;
Brandon Wymanb654c612021-11-05 23:24:51 +0000729 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600730 psu.analyze();
731 EXPECT_EQ(psu.isFaulted(), true);
732}
733
734TEST_F(PowerSupplyTests, HasInputFault)
735{
736 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000737
738 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000739 MockedGPIOInterface* mockPresenceGPIO =
740 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000741 // Always return 1 to indicate present.
742 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
743 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600744 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
745 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000746 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000747 PMBusExpectations expectations;
748 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600749 psu.analyze();
750 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000751 // STATUS_WORD with input fault/warn on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000752 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000753 // STATUS_INPUT with an input fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000754 expectations.statusInputValue = 0x80;
755 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600756 psu.analyze();
757 EXPECT_EQ(psu.hasInputFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000758 // STATUS_WORD with no bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000759 expectations.statusWordValue = 0;
760 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600761 psu.analyze();
762 EXPECT_EQ(psu.hasInputFault(), false);
763}
764
765TEST_F(PowerSupplyTests, HasMFRFault)
766{
767 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000768
769 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000770 MockedGPIOInterface* mockPresenceGPIO =
771 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000772 // Always return 1 to indicate present.
773 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
774 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600775 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
776 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000777 // First return STATUS_WORD with no bits on.
Brandon Wyman8da35c52021-10-28 22:45:08 +0000778 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000779 PMBusExpectations expectations;
780 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600781 psu.analyze();
782 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000783 // Next return STATUS_WORD with MFR fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000784 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000785 // STATUS_MFR_SPEFIC with bit(s) on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000786 expectations.statusMFRValue = 0xFF;
787 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600788 psu.analyze();
789 EXPECT_EQ(psu.hasMFRFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000790 // Back to no bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +0000791 expectations.statusWordValue = 0;
792 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600793 psu.analyze();
794 EXPECT_EQ(psu.hasMFRFault(), false);
795}
796
797TEST_F(PowerSupplyTests, HasVINUVFault)
798{
799 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000800
801 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000802 MockedGPIOInterface* mockPresenceGPIO =
803 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000804 // Always return 1 to indicate present.
805 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
806 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600807 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
808 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000809 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000810 PMBusExpectations expectations;
811 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600812 psu.analyze();
813 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000814 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000815 expectations.statusWordValue = (status_word::VIN_UV_FAULT);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000816 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
817 // Figure 16, and assume bits on in STATUS_INPUT.
Brandon Wymanb654c612021-11-05 23:24:51 +0000818 expectations.statusInputValue = 0x18;
819 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600820 psu.analyze();
821 EXPECT_EQ(psu.hasVINUVFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000822 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +0000823 expectations.statusWordValue = 0;
824 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600825 psu.analyze();
826 EXPECT_EQ(psu.hasVINUVFault(), false);
827}
Brandon Wyman6710ba22021-10-27 17:39:31 +0000828
829TEST_F(PowerSupplyTests, HasVoutOVFault)
830{
831 auto bus = sdbusplus::bus::new_default();
832
833 PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName};
834 MockedGPIOInterface* mockPresenceGPIO =
835 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
836 // Always return 1 to indicate present.
837 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
838 psu.analyze();
839 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
840 EXPECT_EQ(psu.hasVoutOVFault(), false);
841 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000842 PMBusExpectations expectations;
843 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000844 psu.analyze();
845 EXPECT_EQ(psu.hasVoutOVFault(), false);
846 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000847 expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000848 // STATUS_VOUT fault bit(s)
Brandon Wymanb654c612021-11-05 23:24:51 +0000849 expectations.statusVOUTValue = 0x80;
Brandon Wyman96893a42021-11-05 19:56:57 +0000850 // STATUS_TEMPERATURE default.
Brandon Wymanb654c612021-11-05 23:24:51 +0000851 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000852 psu.analyze();
853 EXPECT_EQ(psu.hasVoutOVFault(), true);
854 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +0000855 expectations.statusWordValue = 0;
856 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000857 psu.analyze();
858 EXPECT_EQ(psu.hasVoutOVFault(), false);
859}
Brandon Wyman96893a42021-11-05 19:56:57 +0000860
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000861TEST_F(PowerSupplyTests, HasIoutOCFault)
862{
863 auto bus = sdbusplus::bus::new_default();
864
865 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
866 MockedGPIOInterface* mockPresenceGPIO =
867 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
868 // Always return 1 to indicate present.
869 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
870 psu.analyze();
871 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
872 EXPECT_EQ(psu.hasIoutOCFault(), false);
873 // STATUS_WORD 0x0000 is powered on, no faults.
874 PMBusExpectations expectations;
875 setPMBusExpectations(mockPMBus, expectations);
876 psu.analyze();
877 EXPECT_EQ(psu.hasIoutOCFault(), false);
878 // Turn fault on.
879 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
880 // STATUS_IOUT fault bit(s)
881 expectations.statusIOUTValue = 0x88;
882 setPMBusExpectations(mockPMBus, expectations);
883 psu.analyze();
884 EXPECT_EQ(psu.hasIoutOCFault(), true);
885 // Back to no fault bits on in STATUS_WORD
886 expectations.statusWordValue = 0;
887 setPMBusExpectations(mockPMBus, expectations);
888 psu.analyze();
889 EXPECT_EQ(psu.hasIoutOCFault(), false);
890}
891
Brandon Wyman2cf46942021-10-28 19:09:16 +0000892TEST_F(PowerSupplyTests, HasVoutUVFault)
893{
894 auto bus = sdbusplus::bus::new_default();
895
896 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
897 MockedGPIOInterface* mockPresenceGPIO =
898 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
899 // Always return 1 to indicate present.
900 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
901 psu.analyze();
902 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
903 EXPECT_EQ(psu.hasVoutUVFault(), false);
904 PMBusExpectations expectations;
905 setPMBusExpectations(mockPMBus, expectations);
906 psu.analyze();
907 EXPECT_EQ(psu.hasVoutUVFault(), false);
908 // Turn fault on.
909 expectations.statusWordValue = (status_word::VOUT_FAULT);
910 // STATUS_VOUT fault bit(s)
911 expectations.statusVOUTValue = 0x30;
912 setPMBusExpectations(mockPMBus, expectations);
913 psu.analyze();
914 EXPECT_EQ(psu.hasVoutUVFault(), true);
915 // Back to no fault bits on in STATUS_WORD
916 expectations.statusWordValue = 0;
917 setPMBusExpectations(mockPMBus, expectations);
918 psu.analyze();
919 EXPECT_EQ(psu.hasVoutUVFault(), false);
920}
921
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000922TEST_F(PowerSupplyTests, HasFanFault)
923{
924 auto bus = sdbusplus::bus::new_default();
925
926 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
927 MockedGPIOInterface* mockPresenceGPIO =
928 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
929 // Always return 1 to indicate present.
930 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
931 psu.analyze();
932 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
933 EXPECT_EQ(psu.hasFanFault(), false);
934 // STATUS_WORD 0x0000 is powered on, no faults.
935 PMBusExpectations expectations;
936 setPMBusExpectations(mockPMBus, expectations);
937 psu.analyze();
938 EXPECT_EQ(psu.hasFanFault(), false);
939 // Turn fault on.
940 expectations.statusWordValue = (status_word::FAN_FAULT);
941 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
942 expectations.statusFans12Value = 0x80;
943 setPMBusExpectations(mockPMBus, expectations);
944 psu.analyze();
945 EXPECT_EQ(psu.hasFanFault(), true);
946 // Back to no fault bits on in STATUS_WORD
947 expectations.statusWordValue = 0;
948 setPMBusExpectations(mockPMBus, expectations);
949 psu.analyze();
950 EXPECT_EQ(psu.hasFanFault(), false);
951}
952
Brandon Wyman96893a42021-11-05 19:56:57 +0000953TEST_F(PowerSupplyTests, HasTempFault)
954{
955 auto bus = sdbusplus::bus::new_default();
956
957 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
958 MockedGPIOInterface* mockPresenceGPIO =
959 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
960 // Always return 1 to indicate present.
961 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
962 psu.analyze();
963 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
964 EXPECT_EQ(psu.hasTempFault(), false);
965 // STATUS_WORD 0x0000 is powered on, no faults.
966 PMBusExpectations expectations;
967 setPMBusExpectations(mockPMBus, expectations);
968 psu.analyze();
969 EXPECT_EQ(psu.hasTempFault(), false);
970 // Turn fault on.
971 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
972 // STATUS_TEMPERATURE fault bit on (OT Fault)
973 expectations.statusTempValue = 0x80;
974 setPMBusExpectations(mockPMBus, expectations);
975 psu.analyze();
976 EXPECT_EQ(psu.hasTempFault(), true);
977 // Back to no fault bits on in STATUS_WORD
978 expectations.statusWordValue = 0;
979 setPMBusExpectations(mockPMBus, expectations);
980 psu.analyze();
981 EXPECT_EQ(psu.hasTempFault(), false);
982}
Brandon Wyman2916ea52021-11-06 03:31:18 +0000983
984TEST_F(PowerSupplyTests, HasPgoodFault)
985{
986 auto bus = sdbusplus::bus::new_default();
987
988 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, PSUGPIOLineName};
989 MockedGPIOInterface* mockPresenceGPIO =
990 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
991 // Always return 1 to indicate present.
992 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
993 psu.analyze();
994 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
995 EXPECT_EQ(psu.hasPgoodFault(), false);
996 // STATUS_WORD 0x0000 is powered on, no faults.
997 PMBusExpectations expectations;
998 setPMBusExpectations(mockPMBus, expectations);
999 psu.analyze();
1000 EXPECT_EQ(psu.hasPgoodFault(), false);
1001 // Turn PGOOD# off (fault on).
1002 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
1003 setPMBusExpectations(mockPMBus, expectations);
1004 psu.analyze();
1005 EXPECT_EQ(psu.hasPgoodFault(), true);
1006 // Back to no fault bits on in STATUS_WORD
1007 expectations.statusWordValue = 0;
1008 setPMBusExpectations(mockPMBus, expectations);
1009 psu.analyze();
1010 EXPECT_EQ(psu.hasPgoodFault(), false);
1011 // Turn OFF bit on
1012 expectations.statusWordValue = (status_word::UNIT_IS_OFF);
1013 setPMBusExpectations(mockPMBus, expectations);
1014 psu.analyze();
1015 EXPECT_EQ(psu.hasPgoodFault(), true);
1016 // Back to no fault bits on in STATUS_WORD
1017 expectations.statusWordValue = 0;
1018 setPMBusExpectations(mockPMBus, expectations);
1019 psu.analyze();
1020 EXPECT_EQ(psu.hasPgoodFault(), false);
1021}