blob: a762ecbc5c87e9de1bc1c58b6a6961c730a795bf [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 Wyman39ea02b2021-11-23 23:22:23 +0000162 EXPECT_EQ(psu->hasPSKillFault(), false);
163 EXPECT_EQ(psu->hasPS12VcsFault(), false);
164 EXPECT_EQ(psu->hasPSCS12VFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500165 }
166 catch (...)
167 {
168 ADD_FAILURE() << "Should not have caught exception.";
169 }
B. J. Wyman681b2a32021-04-20 22:31:22 +0000170
171 // Test with valid arguments
172 // TODO: Using D-Bus inventory path for presence.
173 try
174 {
175 // FIXME: How do I get that presenceGPIO.read() in the startup to throw
176 // an exception?
177
178 // EXPECT_CALL(mockedUtil, getPresence(_,
179 // StrEq(PSUInventoryPath)))
180 // .Times(1);
181 }
182 catch (...)
183 {
184 ADD_FAILURE() << "Should not have caught exception.";
185 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600186}
187
188TEST_F(PowerSupplyTests, Analyze)
189{
190 auto bus = sdbusplus::bus::new_default();
191
Brandon Wymanb654c612021-11-05 23:24:51 +0000192 {
193 // If I default to reading the GPIO, I will NOT expect a call to
194 // getPresence().
B. J. Wyman681b2a32021-04-20 22:31:22 +0000195
Brandon Wymanb654c612021-11-05 23:24:51 +0000196 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
197 MockedGPIOInterface* mockPresenceGPIO =
198 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
199 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000200
Brandon Wymanb654c612021-11-05 23:24:51 +0000201 psu.analyze();
202 // By default, nothing should change.
203 EXPECT_EQ(psu.isPresent(), false);
204 EXPECT_EQ(psu.isFaulted(), false);
205 EXPECT_EQ(psu.hasInputFault(), false);
206 EXPECT_EQ(psu.hasMFRFault(), false);
207 EXPECT_EQ(psu.hasVINUVFault(), false);
208 EXPECT_EQ(psu.hasCommFault(), false);
209 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000210 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000211 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000212 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000213 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000214 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000215 EXPECT_EQ(psu.hasPSKillFault(), false);
216 EXPECT_EQ(psu.hasPS12VcsFault(), false);
217 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000218 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600219
B. J. Wyman681b2a32021-04-20 22:31:22 +0000220 PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
221 // In order to get the various faults tested, the power supply needs to
222 // be present in order to read from the PMBus device(s).
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000223 MockedGPIOInterface* mockPresenceGPIO2 =
224 static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000225 // Always return 1 to indicate present.
226 // Each analyze() call will trigger a read of the presence GPIO.
227 EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000228 EXPECT_EQ(psu2.isPresent(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600229
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600230 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000231 // First analyze() call will trigger missing to present, requiring update
232 // to find the new HWMON directory.
233 EXPECT_CALL(mockPMBus, findHwmonDir());
Brandon Wyman8da35c52021-10-28 22:45:08 +0000234 // Presence change from missing to present will trigger write to
235 // ON_OFF_CONFIG.
236 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, _, _));
Brandon Wymanb654c612021-11-05 23:24:51 +0000237 // Presence change from missing to present will trigger in1_input read
238 // in an attempt to get CLEAR_FAULTS called.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000239 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000));
Brandon Wyman06ca4592021-12-06 22:52:23 +0000240 // Change from missing to present will trigger call to update Present
241 // property in the inventory
242 EXPECT_CALL(mockedUtil, setPresence(_, _, true, _));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600243
Brandon Wymanb654c612021-11-05 23:24:51 +0000244 // STATUS_WORD INPUT fault.
245 {
246 // Start with STATUS_WORD 0x0000. Powered on, no faults.
247 // Set expectations for a no fault
248 PMBusExpectations expectations;
249 setPMBusExpectations(mockPMBus, expectations);
250 psu2.analyze();
251 EXPECT_EQ(psu2.isPresent(), true);
252 EXPECT_EQ(psu2.isFaulted(), false);
253 EXPECT_EQ(psu2.hasInputFault(), false);
254 EXPECT_EQ(psu2.hasMFRFault(), false);
255 EXPECT_EQ(psu2.hasVINUVFault(), false);
256 EXPECT_EQ(psu2.hasCommFault(), false);
257 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000258 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000259 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000260 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000261 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000262 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000263 EXPECT_EQ(psu2.hasPSKillFault(), false);
264 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
265 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000266
267 // Update expectations for STATUS_WORD input fault/warn
Brandon Wyman96893a42021-11-05 19:56:57 +0000268 // STATUS_INPUT fault bits ... on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000269 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
270 expectations.statusInputValue = 0x38;
271 setPMBusExpectations(mockPMBus, expectations);
272 psu2.analyze();
273 EXPECT_EQ(psu2.isPresent(), true);
274 EXPECT_EQ(psu2.isFaulted(), true);
275 EXPECT_EQ(psu2.hasInputFault(), true);
276 EXPECT_EQ(psu2.hasMFRFault(), false);
277 EXPECT_EQ(psu2.hasVINUVFault(), false);
278 EXPECT_EQ(psu2.hasCommFault(), false);
279 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000280 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000281 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000282 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000283 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000284 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000285 EXPECT_EQ(psu2.hasPSKillFault(), false);
286 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
287 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000288 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600289
290 // STATUS_WORD INPUT/UV fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000291 {
292 // First need it to return good status, then the fault
293 PMBusExpectations expectations;
294 setPMBusExpectations(mockPMBus, expectations);
295 psu2.analyze();
296 // Now set fault bits in STATUS_WORD
297 expectations.statusWordValue =
298 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
299 // STATUS_INPUT fault bits ... on.
300 expectations.statusInputValue = 0x38;
301 setPMBusExpectations(mockPMBus, expectations);
302 psu2.analyze();
303 EXPECT_EQ(psu2.isPresent(), true);
304 EXPECT_EQ(psu2.isFaulted(), true);
305 EXPECT_EQ(psu2.hasInputFault(), true);
306 EXPECT_EQ(psu2.hasMFRFault(), false);
307 EXPECT_EQ(psu2.hasVINUVFault(), true);
308 EXPECT_EQ(psu2.hasCommFault(), false);
309 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000310 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000311 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000312 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000313 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000314 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000315 EXPECT_EQ(psu2.hasPSKillFault(), false);
316 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
317 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000318 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600319
320 // STATUS_WORD MFR fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000321 {
322 // First need it to return good status, then the fault
323 PMBusExpectations expectations;
324 setPMBusExpectations(mockPMBus, expectations);
325 psu2.analyze();
326 // Now STATUS_WORD with MFR fault bit on.
327 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
328 // STATUS_MFR bits on.
329 expectations.statusMFRValue = 0xFF;
330 setPMBusExpectations(mockPMBus, expectations);
331 psu2.analyze();
332 EXPECT_EQ(psu2.isPresent(), true);
333 EXPECT_EQ(psu2.isFaulted(), true);
334 EXPECT_EQ(psu2.hasInputFault(), false);
335 EXPECT_EQ(psu2.hasMFRFault(), true);
336 EXPECT_EQ(psu2.hasVINUVFault(), false);
337 EXPECT_EQ(psu2.hasCommFault(), false);
338 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000339 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000340 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000341 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000342 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000343 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000344 EXPECT_EQ(psu2.hasPSKillFault(), true);
345 EXPECT_EQ(psu2.hasPS12VcsFault(), true);
346 EXPECT_EQ(psu2.hasPSCS12VFault(), true);
Brandon Wymanb654c612021-11-05 23:24:51 +0000347 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600348
Brandon Wyman96893a42021-11-05 19:56:57 +0000349 // Temperature fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000350 {
351 // First STATUS_WORD with no bits set, then with temperature fault.
352 PMBusExpectations expectations;
353 setPMBusExpectations(mockPMBus, expectations);
354 psu2.analyze();
355 // STATUS_WORD with temperature fault bit on.
356 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
Brandon Wyman96893a42021-11-05 19:56:57 +0000357 // STATUS_TEMPERATURE with fault bit(s) on.
358 expectations.statusTempValue = 0x10;
Brandon Wymanb654c612021-11-05 23:24:51 +0000359 setPMBusExpectations(mockPMBus, expectations);
360 psu2.analyze();
361 EXPECT_EQ(psu2.isPresent(), true);
Brandon Wyman96893a42021-11-05 19:56:57 +0000362 EXPECT_EQ(psu2.isFaulted(), true);
Brandon Wymanb654c612021-11-05 23:24:51 +0000363 EXPECT_EQ(psu2.hasInputFault(), false);
364 EXPECT_EQ(psu2.hasMFRFault(), false);
365 EXPECT_EQ(psu2.hasVINUVFault(), false);
366 EXPECT_EQ(psu2.hasCommFault(), false);
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(), true);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000372 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000373 EXPECT_EQ(psu2.hasPSKillFault(), false);
374 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
375 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000376 }
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000377
378 // CML fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000379 {
380 // First STATUS_WORD wit no bits set, then with CML fault.
381 PMBusExpectations expectations;
382 setPMBusExpectations(mockPMBus, expectations);
383 psu2.analyze();
384 // STATUS_WORD with CML fault bit on.
385 expectations.statusWordValue = (status_word::CML_FAULT);
386 // Turn on STATUS_CML fault bit(s)
387 expectations.statusCMLValue = 0xFF;
388 setPMBusExpectations(mockPMBus, expectations);
389 psu2.analyze();
390 EXPECT_EQ(psu2.isPresent(), true);
391 EXPECT_EQ(psu2.isFaulted(), true);
392 EXPECT_EQ(psu2.hasInputFault(), false);
393 EXPECT_EQ(psu2.hasMFRFault(), false);
394 EXPECT_EQ(psu2.hasVINUVFault(), false);
395 EXPECT_EQ(psu2.hasCommFault(), true);
396 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000397 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000398 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000399 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000400 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000401 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000402 EXPECT_EQ(psu2.hasPSKillFault(), false);
403 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
404 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000405 }
Brandon Wyman6710ba22021-10-27 17:39:31 +0000406
407 // VOUT_OV_FAULT fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000408 {
409 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
410 PMBusExpectations expectations;
411 setPMBusExpectations(mockPMBus, expectations);
412 psu2.analyze();
413 // STATUS_WORD with VOUT/VOUT_OV fault.
414 expectations.statusWordValue =
415 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
416 // Turn on STATUS_VOUT fault bit(s)
417 expectations.statusVOUTValue = 0xA0;
Brandon Wyman96893a42021-11-05 19:56:57 +0000418 // STATUS_TEMPERATURE don't care (default)
Brandon Wymanb654c612021-11-05 23:24:51 +0000419 setPMBusExpectations(mockPMBus, expectations);
420 psu2.analyze();
421 EXPECT_EQ(psu2.isPresent(), true);
422 EXPECT_EQ(psu2.isFaulted(), true);
423 EXPECT_EQ(psu2.hasInputFault(), false);
424 EXPECT_EQ(psu2.hasMFRFault(), false);
425 EXPECT_EQ(psu2.hasVINUVFault(), false);
426 EXPECT_EQ(psu2.hasCommFault(), false);
427 EXPECT_EQ(psu2.hasVoutOVFault(), true);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000428 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000429 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000430 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000431 EXPECT_EQ(psu2.hasTempFault(), false);
432 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000433 EXPECT_EQ(psu2.hasPSKillFault(), false);
434 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
435 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000436 }
437
438 // IOUT_OC_FAULT fault
439 {
440 // First STATUS_WORD with no bits set, then with IOUT_OC fault.
441 PMBusExpectations expectations;
442 setPMBusExpectations(mockPMBus, expectations);
443 psu2.analyze();
444 // STATUS_WORD with IOUT_OC fault.
445 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
446 // Turn on STATUS_IOUT fault bit(s)
447 expectations.statusIOUTValue = 0x88;
448 setPMBusExpectations(mockPMBus, expectations);
449 psu2.analyze();
450 EXPECT_EQ(psu2.isPresent(), true);
451 EXPECT_EQ(psu2.isFaulted(), true);
452 EXPECT_EQ(psu2.hasInputFault(), false);
453 EXPECT_EQ(psu2.hasMFRFault(), false);
454 EXPECT_EQ(psu2.hasVINUVFault(), false);
455 EXPECT_EQ(psu2.hasCommFault(), false);
456 EXPECT_EQ(psu2.hasVoutOVFault(), false);
457 EXPECT_EQ(psu2.hasIoutOCFault(), true);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000458 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000459 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000460 EXPECT_EQ(psu2.hasTempFault(), false);
461 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000462 EXPECT_EQ(psu2.hasPSKillFault(), false);
463 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
464 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000465 }
466
467 // VOUT_UV_FAULT
468 {
469 // First STATUS_WORD with no bits set, then with VOUT fault.
470 PMBusExpectations expectations;
471 setPMBusExpectations(mockPMBus, expectations);
472 psu2.analyze();
473 // Change STATUS_WORD to indicate VOUT fault.
474 expectations.statusWordValue = (status_word::VOUT_FAULT);
475 // Turn on STATUS_VOUT fault bit(s)
476 expectations.statusVOUTValue = 0x30;
477 setPMBusExpectations(mockPMBus, expectations);
478 psu2.analyze();
479 EXPECT_EQ(psu2.isPresent(), true);
480 EXPECT_EQ(psu2.isFaulted(), true);
481 EXPECT_EQ(psu2.hasInputFault(), false);
482 EXPECT_EQ(psu2.hasMFRFault(), false);
483 EXPECT_EQ(psu2.hasVINUVFault(), false);
484 EXPECT_EQ(psu2.hasCommFault(), false);
485 EXPECT_EQ(psu2.hasVoutOVFault(), false);
486 EXPECT_EQ(psu2.hasIoutOCFault(), false);
487 EXPECT_EQ(psu2.hasVoutUVFault(), true);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000488 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000489 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000490 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000491 EXPECT_EQ(psu2.hasPSKillFault(), false);
492 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
493 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000494 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600495
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000496 // Fan fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000497 {
498 // First STATUS_WORD with no bits set, then with fan fault.
499 PMBusExpectations expectations;
500 setPMBusExpectations(mockPMBus, expectations);
501 psu2.analyze();
502 expectations.statusWordValue = (status_word::FAN_FAULT);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000503 // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
504 expectations.statusFans12Value = 0xA0;
Brandon Wymanb654c612021-11-05 23:24:51 +0000505 setPMBusExpectations(mockPMBus, expectations);
506 psu2.analyze();
507 EXPECT_EQ(psu2.isPresent(), true);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000508 EXPECT_EQ(psu2.isFaulted(), true);
Brandon Wymanb654c612021-11-05 23:24:51 +0000509 EXPECT_EQ(psu2.hasInputFault(), false);
510 EXPECT_EQ(psu2.hasMFRFault(), false);
511 EXPECT_EQ(psu2.hasVINUVFault(), false);
512 EXPECT_EQ(psu2.hasCommFault(), false);
513 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000514 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000515 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000516 EXPECT_EQ(psu2.hasFanFault(), true);
Brandon Wyman96893a42021-11-05 19:56:57 +0000517 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000518 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000519 EXPECT_EQ(psu2.hasPSKillFault(), false);
520 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
521 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000522 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000523
Brandon Wyman06ca4592021-12-06 22:52:23 +0000524 // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000525 {
Brandon Wyman2916ea52021-11-06 03:31:18 +0000526 // First STATUS_WORD with no bits set.
527 PMBusExpectations expectations;
528 setPMBusExpectations(mockPMBus, expectations);
529 psu2.analyze();
530 EXPECT_EQ(psu2.isFaulted(), false);
531 // POWER_GOOD# inactive, and OFF bit on.
532 expectations.statusWordValue =
533 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
Brandon Wyman06ca4592021-12-06 22:52:23 +0000534 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
535 {
536 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
537 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
538 setPMBusExpectations(mockPMBus, expectations);
539 psu2.analyze();
540 EXPECT_EQ(psu2.isPresent(), true);
541 if (x < DEGLITCH_LIMIT)
542 {
543 EXPECT_EQ(psu2.isFaulted(), false);
544 }
545 else
546 {
547 EXPECT_EQ(psu2.isFaulted(), true);
548 }
549 EXPECT_EQ(psu2.hasInputFault(), false);
550 EXPECT_EQ(psu2.hasMFRFault(), false);
551 EXPECT_EQ(psu2.hasVINUVFault(), false);
552 EXPECT_EQ(psu2.hasCommFault(), false);
553 EXPECT_EQ(psu2.hasVoutOVFault(), false);
554 EXPECT_EQ(psu2.hasVoutUVFault(), false);
555 EXPECT_EQ(psu2.hasIoutOCFault(), false);
556 EXPECT_EQ(psu2.hasFanFault(), false);
557 EXPECT_EQ(psu2.hasTempFault(), false);
558 if (x < DEGLITCH_LIMIT)
559 {
560 EXPECT_EQ(psu2.hasPgoodFault(), false);
561 }
562 else
563 {
564 EXPECT_EQ(psu2.hasPgoodFault(), true);
565 }
566 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000567 }
568
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600569 // TODO: ReadFailure
570}
571
Brandon Wyman59a35792020-06-04 12:37:40 -0500572TEST_F(PowerSupplyTests, OnOffConfig)
573{
574 auto bus = sdbusplus::bus::new_default();
575 uint8_t data = 0x15;
576
577 // Test where PSU is NOT present
578 try
579 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000580 // Assume GPIO presence, not inventory presence?
581 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
582
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000583 MockedGPIOInterface* mockPresenceGPIO =
584 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000585 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
Brandon Wyman59a35792020-06-04 12:37:40 -0500586 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000587 // Constructor should set initial presence, default read returns 0.
Brandon Wyman59a35792020-06-04 12:37:40 -0500588 // If it is not present, I should not be trying to write to it.
589 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
590 psu.onOffConfig(data);
591 }
592 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000593 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500594
595 // Test where PSU is present
596 try
597 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000598 // Assume GPIO presence, not inventory presence?
599 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000600 MockedGPIOInterface* mockPresenceGPIO =
601 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000602 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1));
Brandon Wyman59a35792020-06-04 12:37:40 -0500603 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000604 // TODO: expect setPresence call?
605 // updatePresence() private function reads gpio, called by analyze().
606 psu.analyze();
Brandon Wyman59a35792020-06-04 12:37:40 -0500607 // TODO: ???should I check the filename?
608 EXPECT_CALL(mockPMBus,
609 writeBinary(_, ElementsAre(0x15), Type::HwmonDeviceDebug))
610 .Times(1);
611 psu.onOffConfig(data);
612 }
613 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000614 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500615}
616
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600617TEST_F(PowerSupplyTests, ClearFaults)
618{
619 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000620 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000621 MockedGPIOInterface* mockPresenceGPIO =
622 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000623 // Always return 1 to indicate present.
624 // Each analyze() call will trigger a read of the presence GPIO.
625 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000626 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000627 // Change from missing to present will trigger HWMON directory update.
628 EXPECT_CALL(mockPMBus, findHwmonDir());
629 // Change from missing to present will trigger ON_OFF_CONFIG write.
630 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, _, _));
Brandon Wyman8da35c52021-10-28 22:45:08 +0000631 // Presence change from missing to present will trigger in1_input read in
632 // an attempt to get CLEAR_FAULTS called.
633 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000));
Brandon Wyman06ca4592021-12-06 22:52:23 +0000634 // Missing/present call will update Presence in inventory.
635 EXPECT_CALL(mockedUtil, setPresence(_, _, true, _));
Brandon Wyman8da35c52021-10-28 22:45:08 +0000636 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000637 PMBusExpectations expectations;
638 setPMBusExpectations(mockPMBus, expectations);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000639 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600640 EXPECT_EQ(psu.isPresent(), true);
641 EXPECT_EQ(psu.isFaulted(), false);
642 EXPECT_EQ(psu.hasInputFault(), false);
643 EXPECT_EQ(psu.hasMFRFault(), false);
644 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000645 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000646 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000647 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000648 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000649 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000650 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000651 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000652 EXPECT_EQ(psu.hasPSKillFault(), false);
653 EXPECT_EQ(psu.hasPS12VcsFault(), false);
654 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000655
Brandon Wymanf07bc792021-10-12 19:00:35 +0000656 // STATUS_WORD with fault bits galore!
Brandon Wymanb654c612021-11-05 23:24:51 +0000657 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000658 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000659 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000660 // STATUS_MFR_SPEFIC with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000661 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000662 // STATUS_CML with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000663 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000664 // STATUS_VOUT with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000665 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000666 // STATUS_IOUT with bits on.
667 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000668 // STATUS_FANS_1_2 with bits on.
669 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000670 // STATUS_TEMPERATURE with bits on.
671 expectations.statusTempValue = 0xFF;
Brandon Wymanb654c612021-11-05 23:24:51 +0000672 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600673 psu.analyze();
674 EXPECT_EQ(psu.isPresent(), true);
675 EXPECT_EQ(psu.isFaulted(), true);
676 EXPECT_EQ(psu.hasInputFault(), true);
677 EXPECT_EQ(psu.hasMFRFault(), true);
678 EXPECT_EQ(psu.hasVINUVFault(), true);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000679 EXPECT_EQ(psu.hasCommFault(), true);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000680 EXPECT_EQ(psu.hasVoutOVFault(), true);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000681 EXPECT_EQ(psu.hasIoutOCFault(), true);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000682 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
683 // Rely on HasVoutUVFault() to verify this sets and clears.
684 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000685 EXPECT_EQ(psu.hasFanFault(), true);
Brandon Wyman96893a42021-11-05 19:56:57 +0000686 EXPECT_EQ(psu.hasTempFault(), true);
Brandon Wyman06ca4592021-12-06 22:52:23 +0000687 // pgoodFault is deglitched up to DEGLITCH_LIMIT
688 EXPECT_EQ(psu.hasPgoodFault(), false);
689 setPMBusExpectations(mockPMBus, expectations);
690 psu.analyze();
691 EXPECT_EQ(psu.hasPgoodFault(), false);
692 setPMBusExpectations(mockPMBus, expectations);
693 psu.analyze();
694 // DEGLITCH_LIMIT reached for pgoodFault
Brandon Wyman2916ea52021-11-06 03:31:18 +0000695 EXPECT_EQ(psu.hasPgoodFault(), true);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000696 EXPECT_EQ(psu.hasPSKillFault(), true);
697 EXPECT_EQ(psu.hasPS12VcsFault(), true);
698 EXPECT_EQ(psu.hasPSCS12VFault(), true);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000699
Brandon Wyman3c208462020-05-13 16:25:58 -0500700 EXPECT_CALL(mockPMBus, read("in1_input", _))
701 .Times(1)
702 .WillOnce(Return(209000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600703 psu.clearFaults();
704 EXPECT_EQ(psu.isPresent(), true);
705 EXPECT_EQ(psu.isFaulted(), false);
706 EXPECT_EQ(psu.hasInputFault(), false);
707 EXPECT_EQ(psu.hasMFRFault(), false);
708 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000709 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000710 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000711 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000712 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000713 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000714 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000715 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000716 EXPECT_EQ(psu.hasPSKillFault(), false);
717 EXPECT_EQ(psu.hasPS12VcsFault(), false);
718 EXPECT_EQ(psu.hasPSCS12VFault(), false);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000719
720 // TODO: Faults clear on missing/present?
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600721}
722
723TEST_F(PowerSupplyTests, UpdateInventory)
724{
725 auto bus = sdbusplus::bus::new_default();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500726
727 try
728 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000729 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500730 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
731 // If it is not present, I should not be trying to read a string
732 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
733 psu.updateInventory();
734 }
735 catch (...)
736 {
737 ADD_FAILURE() << "Should not have caught exception.";
738 }
739
740 try
741 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000742 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000743 MockedGPIOInterface* mockPresenceGPIO =
744 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000745 // GPIO read return 1 to indicate present.
746 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
747 psu.analyze();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500748 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
749 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
750 psu.updateInventory();
751
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500752#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500753 EXPECT_CALL(mockPMBus, readString(_, _))
754 .WillOnce(Return("CCIN"))
755 .WillOnce(Return("PN3456"))
756 .WillOnce(Return("FN3456"))
757 .WillOnce(Return("HEADER"))
758 .WillOnce(Return("SN3456"))
759 .WillOnce(Return("FW3456"));
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500760#endif
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500761 psu.updateInventory();
762 // TODO: D-Bus mocking to verify values stored on D-Bus (???)
763 }
764 catch (...)
765 {
766 ADD_FAILURE() << "Should not have caught exception.";
767 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600768}
769
770TEST_F(PowerSupplyTests, IsPresent)
771{
772 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000773
774 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000775 MockedGPIOInterface* mockPresenceGPIO =
776 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600777 EXPECT_EQ(psu.isPresent(), false);
778
B. J. Wyman681b2a32021-04-20 22:31:22 +0000779 // Change GPIO read to return 1 to indicate present.
780 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
781 psu.analyze();
782 EXPECT_EQ(psu.isPresent(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600783}
784
785TEST_F(PowerSupplyTests, IsFaulted)
786{
787 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000788
789 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000790 MockedGPIOInterface* mockPresenceGPIO =
791 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000792 // Always return 1 to indicate present.
793 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
794 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600795 EXPECT_EQ(psu.isFaulted(), false);
796 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wymanb654c612021-11-05 23:24:51 +0000797 PMBusExpectations expectations;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000798 // STATUS_WORD with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000799 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000800 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000801 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000802 // STATUS_MFR_SPECIFIC with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000803 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000804 // STATUS_CML with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000805 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000806 // STATUS_VOUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000807 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000808 // STATUS_IOUT with fault bits on.
809 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000810 // STATUS_FANS_1_2 with bits on.
811 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000812 // STATUS_TEMPERATURE with fault bits on.
813 expectations.statusTempValue = 0xFF;
Brandon Wymanb654c612021-11-05 23:24:51 +0000814 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600815 psu.analyze();
816 EXPECT_EQ(psu.isFaulted(), true);
817}
818
819TEST_F(PowerSupplyTests, HasInputFault)
820{
821 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000822
823 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000824 MockedGPIOInterface* mockPresenceGPIO =
825 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000826 // Always return 1 to indicate present.
827 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
828 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600829 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
830 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000831 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000832 PMBusExpectations expectations;
833 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600834 psu.analyze();
835 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000836 // STATUS_WORD with input fault/warn on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000837 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000838 // STATUS_INPUT with an input fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000839 expectations.statusInputValue = 0x80;
840 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600841 psu.analyze();
842 EXPECT_EQ(psu.hasInputFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000843 // STATUS_WORD with no bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000844 expectations.statusWordValue = 0;
845 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600846 psu.analyze();
847 EXPECT_EQ(psu.hasInputFault(), false);
848}
849
850TEST_F(PowerSupplyTests, HasMFRFault)
851{
852 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000853
854 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000855 MockedGPIOInterface* mockPresenceGPIO =
856 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000857 // Always return 1 to indicate present.
858 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
859 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600860 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
861 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000862 // First return STATUS_WORD with no bits on.
Brandon Wyman8da35c52021-10-28 22:45:08 +0000863 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000864 PMBusExpectations expectations;
865 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600866 psu.analyze();
867 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000868 // Next return STATUS_WORD with MFR fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000869 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000870 // STATUS_MFR_SPEFIC with bit(s) on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000871 expectations.statusMFRValue = 0xFF;
872 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600873 psu.analyze();
874 EXPECT_EQ(psu.hasMFRFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000875 // Back to no bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +0000876 expectations.statusWordValue = 0;
877 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600878 psu.analyze();
879 EXPECT_EQ(psu.hasMFRFault(), false);
880}
881
882TEST_F(PowerSupplyTests, HasVINUVFault)
883{
884 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000885
886 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000887 MockedGPIOInterface* mockPresenceGPIO =
888 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000889 // Always return 1 to indicate present.
890 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
891 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600892 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
893 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000894 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000895 PMBusExpectations expectations;
896 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600897 psu.analyze();
898 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000899 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000900 expectations.statusWordValue = (status_word::VIN_UV_FAULT);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000901 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
902 // Figure 16, and assume bits on in STATUS_INPUT.
Brandon Wymanb654c612021-11-05 23:24:51 +0000903 expectations.statusInputValue = 0x18;
904 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600905 psu.analyze();
906 EXPECT_EQ(psu.hasVINUVFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000907 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +0000908 expectations.statusWordValue = 0;
909 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600910 psu.analyze();
911 EXPECT_EQ(psu.hasVINUVFault(), false);
912}
Brandon Wyman6710ba22021-10-27 17:39:31 +0000913
914TEST_F(PowerSupplyTests, HasVoutOVFault)
915{
916 auto bus = sdbusplus::bus::new_default();
917
918 PowerSupply psu{bus, PSUInventoryPath, 3, 0x69, PSUGPIOLineName};
919 MockedGPIOInterface* mockPresenceGPIO =
920 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
921 // Always return 1 to indicate present.
922 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
923 psu.analyze();
924 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
925 EXPECT_EQ(psu.hasVoutOVFault(), false);
926 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000927 PMBusExpectations expectations;
928 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000929 psu.analyze();
930 EXPECT_EQ(psu.hasVoutOVFault(), false);
931 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000932 expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000933 // STATUS_VOUT fault bit(s)
Brandon Wymanb654c612021-11-05 23:24:51 +0000934 expectations.statusVOUTValue = 0x80;
Brandon Wyman96893a42021-11-05 19:56:57 +0000935 // STATUS_TEMPERATURE default.
Brandon Wymanb654c612021-11-05 23:24:51 +0000936 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000937 psu.analyze();
938 EXPECT_EQ(psu.hasVoutOVFault(), true);
939 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +0000940 expectations.statusWordValue = 0;
941 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000942 psu.analyze();
943 EXPECT_EQ(psu.hasVoutOVFault(), false);
944}
Brandon Wyman96893a42021-11-05 19:56:57 +0000945
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000946TEST_F(PowerSupplyTests, HasIoutOCFault)
947{
948 auto bus = sdbusplus::bus::new_default();
949
950 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
951 MockedGPIOInterface* mockPresenceGPIO =
952 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
953 // Always return 1 to indicate present.
954 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
955 psu.analyze();
956 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
957 EXPECT_EQ(psu.hasIoutOCFault(), false);
958 // STATUS_WORD 0x0000 is powered on, no faults.
959 PMBusExpectations expectations;
960 setPMBusExpectations(mockPMBus, expectations);
961 psu.analyze();
962 EXPECT_EQ(psu.hasIoutOCFault(), false);
963 // Turn fault on.
964 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
965 // STATUS_IOUT fault bit(s)
966 expectations.statusIOUTValue = 0x88;
967 setPMBusExpectations(mockPMBus, expectations);
968 psu.analyze();
969 EXPECT_EQ(psu.hasIoutOCFault(), true);
970 // Back to no fault bits on in STATUS_WORD
971 expectations.statusWordValue = 0;
972 setPMBusExpectations(mockPMBus, expectations);
973 psu.analyze();
974 EXPECT_EQ(psu.hasIoutOCFault(), false);
975}
976
Brandon Wyman2cf46942021-10-28 19:09:16 +0000977TEST_F(PowerSupplyTests, HasVoutUVFault)
978{
979 auto bus = sdbusplus::bus::new_default();
980
981 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
982 MockedGPIOInterface* mockPresenceGPIO =
983 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
984 // Always return 1 to indicate present.
985 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
986 psu.analyze();
987 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
988 EXPECT_EQ(psu.hasVoutUVFault(), false);
989 PMBusExpectations expectations;
990 setPMBusExpectations(mockPMBus, expectations);
991 psu.analyze();
992 EXPECT_EQ(psu.hasVoutUVFault(), false);
993 // Turn fault on.
994 expectations.statusWordValue = (status_word::VOUT_FAULT);
995 // STATUS_VOUT fault bit(s)
996 expectations.statusVOUTValue = 0x30;
997 setPMBusExpectations(mockPMBus, expectations);
998 psu.analyze();
999 EXPECT_EQ(psu.hasVoutUVFault(), true);
1000 // Back to no fault bits on in STATUS_WORD
1001 expectations.statusWordValue = 0;
1002 setPMBusExpectations(mockPMBus, expectations);
1003 psu.analyze();
1004 EXPECT_EQ(psu.hasVoutUVFault(), false);
1005}
1006
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001007TEST_F(PowerSupplyTests, HasFanFault)
1008{
1009 auto bus = sdbusplus::bus::new_default();
1010
1011 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d, PSUGPIOLineName};
1012 MockedGPIOInterface* mockPresenceGPIO =
1013 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1014 // Always return 1 to indicate present.
1015 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1016 psu.analyze();
1017 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1018 EXPECT_EQ(psu.hasFanFault(), false);
1019 // STATUS_WORD 0x0000 is powered on, no faults.
1020 PMBusExpectations expectations;
1021 setPMBusExpectations(mockPMBus, expectations);
1022 psu.analyze();
1023 EXPECT_EQ(psu.hasFanFault(), false);
1024 // Turn fault on.
1025 expectations.statusWordValue = (status_word::FAN_FAULT);
1026 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
1027 expectations.statusFans12Value = 0x80;
1028 setPMBusExpectations(mockPMBus, expectations);
1029 psu.analyze();
1030 EXPECT_EQ(psu.hasFanFault(), true);
1031 // Back to no fault bits on in STATUS_WORD
1032 expectations.statusWordValue = 0;
1033 setPMBusExpectations(mockPMBus, expectations);
1034 psu.analyze();
1035 EXPECT_EQ(psu.hasFanFault(), false);
1036}
1037
Brandon Wyman96893a42021-11-05 19:56:57 +00001038TEST_F(PowerSupplyTests, HasTempFault)
1039{
1040 auto bus = sdbusplus::bus::new_default();
1041
1042 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
1043 MockedGPIOInterface* mockPresenceGPIO =
1044 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1045 // Always return 1 to indicate present.
1046 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1047 psu.analyze();
1048 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1049 EXPECT_EQ(psu.hasTempFault(), false);
1050 // STATUS_WORD 0x0000 is powered on, no faults.
1051 PMBusExpectations expectations;
1052 setPMBusExpectations(mockPMBus, expectations);
1053 psu.analyze();
1054 EXPECT_EQ(psu.hasTempFault(), false);
1055 // Turn fault on.
1056 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
1057 // STATUS_TEMPERATURE fault bit on (OT Fault)
1058 expectations.statusTempValue = 0x80;
1059 setPMBusExpectations(mockPMBus, expectations);
1060 psu.analyze();
1061 EXPECT_EQ(psu.hasTempFault(), true);
1062 // Back to no fault bits on in STATUS_WORD
1063 expectations.statusWordValue = 0;
1064 setPMBusExpectations(mockPMBus, expectations);
1065 psu.analyze();
1066 EXPECT_EQ(psu.hasTempFault(), false);
1067}
Brandon Wyman2916ea52021-11-06 03:31:18 +00001068
1069TEST_F(PowerSupplyTests, HasPgoodFault)
1070{
1071 auto bus = sdbusplus::bus::new_default();
1072
1073 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b, PSUGPIOLineName};
1074 MockedGPIOInterface* mockPresenceGPIO =
1075 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1076 // Always return 1 to indicate present.
1077 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001078 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman06ca4592021-12-06 22:52:23 +00001079 EXPECT_CALL(mockPMBus, findHwmonDir());
1080 // Presence change from missing to present will trigger write to
1081 // ON_OFF_CONFIG.
1082 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, _, _));
1083 // Missing/present will trigger read of "in1_input" to try CLEAR_FAULTS.
1084 EXPECT_CALL(mockPMBus, read("in1_input", _))
1085 .Times(1)
1086 .WillOnce(Return(207000));
1087 // Missing/present call will update Presence in inventory.
1088 EXPECT_CALL(mockedUtil, setPresence(_, _, true, _));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001089 // STATUS_WORD 0x0000 is powered on, no faults.
1090 PMBusExpectations expectations;
1091 setPMBusExpectations(mockPMBus, expectations);
1092 psu.analyze();
1093 EXPECT_EQ(psu.hasPgoodFault(), false);
1094 // Turn PGOOD# off (fault on).
1095 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
1096 setPMBusExpectations(mockPMBus, expectations);
1097 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001098 // Expect false until reaches DEGLITCH_LIMIT
1099 EXPECT_EQ(psu.hasPgoodFault(), false);
1100 setPMBusExpectations(mockPMBus, expectations);
1101 psu.analyze();
1102 // Expect false until reaches DEGLITCH_LIMIT
1103 EXPECT_EQ(psu.hasPgoodFault(), false);
1104 setPMBusExpectations(mockPMBus, expectations);
1105 psu.analyze();
1106 // DEGLITCH_LIMIT reached, expect true.
Brandon Wyman2916ea52021-11-06 03:31:18 +00001107 EXPECT_EQ(psu.hasPgoodFault(), true);
1108 // Back to no fault bits on in STATUS_WORD
1109 expectations.statusWordValue = 0;
1110 setPMBusExpectations(mockPMBus, expectations);
1111 psu.analyze();
1112 EXPECT_EQ(psu.hasPgoodFault(), false);
1113 // Turn OFF bit on
1114 expectations.statusWordValue = (status_word::UNIT_IS_OFF);
1115 setPMBusExpectations(mockPMBus, expectations);
1116 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001117 EXPECT_EQ(psu.hasPgoodFault(), false);
1118 setPMBusExpectations(mockPMBus, expectations);
1119 psu.analyze();
1120 EXPECT_EQ(psu.hasPgoodFault(), false);
1121 setPMBusExpectations(mockPMBus, expectations);
1122 psu.analyze();
Brandon Wyman2916ea52021-11-06 03:31:18 +00001123 EXPECT_EQ(psu.hasPgoodFault(), true);
1124 // Back to no fault bits on in STATUS_WORD
1125 expectations.statusWordValue = 0;
1126 setPMBusExpectations(mockPMBus, expectations);
1127 psu.analyze();
1128 EXPECT_EQ(psu.hasPgoodFault(), false);
1129}
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001130
1131TEST_F(PowerSupplyTests, HasPSKillFault)
1132{
1133 auto bus = sdbusplus::bus::new_default();
1134 PowerSupply psu{bus, PSUInventoryPath, 4, 0x6d, PSUGPIOLineName};
1135 MockedGPIOInterface* mockPresenceGPIO =
1136 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1137 // Always return 1 to indicate present.
1138 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1139 psu.analyze();
1140 EXPECT_EQ(psu.hasPSKillFault(), false);
1141 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1142 // STATUS_WORD 0x0000 is powered on, no faults.
1143 PMBusExpectations expectations;
1144 setPMBusExpectations(mockPMBus, expectations);
1145 psu.analyze();
1146 EXPECT_EQ(psu.hasPSKillFault(), false);
1147 // Next return STATUS_WORD with MFR fault bit on.
1148 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1149 // STATUS_MFR_SPEFIC with bit(s) on.
1150 expectations.statusMFRValue = 0xFF;
1151 setPMBusExpectations(mockPMBus, expectations);
1152 psu.analyze();
1153 EXPECT_EQ(psu.hasPSKillFault(), true);
1154 // Back to no bits on in STATUS_WORD
1155 expectations.statusWordValue = 0;
1156 setPMBusExpectations(mockPMBus, expectations);
1157 psu.analyze();
1158 EXPECT_EQ(psu.hasPSKillFault(), false);
1159 // Next return STATUS_WORD with MFR fault bit on.
1160 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1161 // STATUS_MFR_SPEFIC with bit 4 on.
1162 expectations.statusMFRValue = 0x10;
1163 setPMBusExpectations(mockPMBus, expectations);
1164 psu.analyze();
1165 EXPECT_EQ(psu.hasPSKillFault(), true);
1166 // Back to no bits on in STATUS_WORD
1167 expectations.statusWordValue = 0;
1168 setPMBusExpectations(mockPMBus, expectations);
1169 psu.analyze();
1170 EXPECT_EQ(psu.hasPSKillFault(), false);
1171}
1172
1173TEST_F(PowerSupplyTests, HasPS12VcsFault)
1174{
1175 auto bus = sdbusplus::bus::new_default();
1176 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6e, PSUGPIOLineName};
1177 MockedGPIOInterface* mockPresenceGPIO =
1178 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1179 // Always return 1 to indicate present.
1180 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1181 psu.analyze();
1182 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1183 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1184 // STATUS_WORD 0x0000 is powered on, no faults.
1185 PMBusExpectations expectations;
1186 setPMBusExpectations(mockPMBus, expectations);
1187 psu.analyze();
1188 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1189 // Next return STATUS_WORD with MFR fault bit on.
1190 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1191 // STATUS_MFR_SPEFIC with bit(s) on.
1192 expectations.statusMFRValue = 0xFF;
1193 setPMBusExpectations(mockPMBus, expectations);
1194 psu.analyze();
1195 EXPECT_EQ(psu.hasPS12VcsFault(), true);
1196 // Back to no bits on in STATUS_WORD
1197 expectations.statusWordValue = 0;
1198 setPMBusExpectations(mockPMBus, expectations);
1199 psu.analyze();
1200 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1201 // Next return STATUS_WORD with MFR fault bit on.
1202 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1203 // STATUS_MFR_SPEFIC with bit 6 on.
1204 expectations.statusMFRValue = 0x40;
1205 setPMBusExpectations(mockPMBus, expectations);
1206 psu.analyze();
1207 EXPECT_EQ(psu.hasPS12VcsFault(), true);
1208 // Back to no bits on in STATUS_WORD
1209 expectations.statusWordValue = 0;
1210 setPMBusExpectations(mockPMBus, expectations);
1211 psu.analyze();
1212 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1213}
1214
1215TEST_F(PowerSupplyTests, HasPSCS12VFault)
1216{
1217 auto bus = sdbusplus::bus::new_default();
1218 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f, PSUGPIOLineName};
1219 MockedGPIOInterface* mockPresenceGPIO =
1220 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1221 // Always return 1 to indicate present.
1222 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
1223 psu.analyze();
1224 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1225 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1226 // STATUS_WORD 0x0000 is powered on, no faults.
1227 PMBusExpectations expectations;
1228 setPMBusExpectations(mockPMBus, expectations);
1229 psu.analyze();
1230 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1231 // Next return STATUS_WORD with MFR fault bit on.
1232 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1233 // STATUS_MFR_SPEFIC with bit(s) on.
1234 expectations.statusMFRValue = 0xFF;
1235 setPMBusExpectations(mockPMBus, expectations);
1236 psu.analyze();
1237 EXPECT_EQ(psu.hasPSCS12VFault(), true);
1238 // Back to no bits on in STATUS_WORD
1239 expectations.statusWordValue = 0;
1240 setPMBusExpectations(mockPMBus, expectations);
1241 psu.analyze();
1242 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1243 // Next return STATUS_WORD with MFR fault bit on.
1244 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1245 // STATUS_MFR_SPEFIC with bit 7 on.
1246 expectations.statusMFRValue = 0x80;
1247 setPMBusExpectations(mockPMBus, expectations);
1248 psu.analyze();
1249 EXPECT_EQ(psu.hasPSCS12VFault(), true);
1250 // Back to no bits on in STATUS_WORD
1251 expectations.statusWordValue = 0;
1252 setPMBusExpectations(mockPMBus, expectations);
1253 psu.analyze();
1254 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1255}