blob: 7411c348ae549b0dfc7d3d72cd48bca69b0e0598 [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
25class PowerSupplyTests : public ::testing::Test
26{
27 public:
28 PowerSupplyTests() :
29 mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
30 {
31 ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
32 }
33
34 ~PowerSupplyTests() override
35 {
36 freeUtils();
37 }
38
39 const MockedUtil& mockedUtil;
40};
41
42TEST_F(PowerSupplyTests, Constructor)
43{
44 /**
45 * @param[in] invpath - String for inventory path to use
46 * @param[in] i2cbus - The bus number this power supply is on
47 * @param[in] i2caddr - The 16-bit I2C address of the power supply
B. J. Wyman681b2a32021-04-20 22:31:22 +000048 * @param[in] gpioLineName - The string for the gpio-line-name to read for
49 * presence.
50 * @param[in] bindDelay - Time in milliseconds to delay binding the device
51 * driver after seeing the presence line go active.
Brandon Wyman3f1242f2020-01-28 13:11:25 -060052 */
53 auto bus = sdbusplus::bus::new_default();
Brandon Wyman3f1242f2020-01-28 13:11:25 -060054
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050055 // Try where inventory path is empty, constructor should fail.
56 try
57 {
B. J. Wyman681b2a32021-04-20 22:31:22 +000058 auto psu =
59 std::make_unique<PowerSupply>(bus, "", 3, 0x68, PSUGPIOLineName);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050060 ADD_FAILURE() << "Should not have reached this line.";
61 }
62 catch (const std::invalid_argument& e)
63 {
64 EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
65 }
66 catch (...)
67 {
68 ADD_FAILURE() << "Should not have caught exception.";
69 }
70
B. J. Wyman681b2a32021-04-20 22:31:22 +000071 // TODO: Try invalid i2c address?
72
73 // Try where gpioLineName is empty.
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050074 try
75 {
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050076 auto psu =
B. J. Wyman681b2a32021-04-20 22:31:22 +000077 std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68, "");
78 ADD_FAILURE()
79 << "Should not have reached this line. Invalid gpioLineName.";
80 }
81 catch (const std::invalid_argument& e)
82 {
83 EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
84 }
85 catch (...)
86 {
87 ADD_FAILURE() << "Should not have caught exception.";
88 }
89
90 // Test with valid arguments
91 // NOT using D-Bus inventory path for presence.
92 try
93 {
94 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
95 PSUGPIOLineName);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050096
97 EXPECT_EQ(psu->isPresent(), false);
98 EXPECT_EQ(psu->isFaulted(), false);
99 EXPECT_EQ(psu->hasInputFault(), false);
100 EXPECT_EQ(psu->hasMFRFault(), false);
101 EXPECT_EQ(psu->hasVINUVFault(), false);
102 }
103 catch (...)
104 {
105 ADD_FAILURE() << "Should not have caught exception.";
106 }
B. J. Wyman681b2a32021-04-20 22:31:22 +0000107
108 // Test with valid arguments
109 // TODO: Using D-Bus inventory path for presence.
110 try
111 {
112 // FIXME: How do I get that presenceGPIO.read() in the startup to throw
113 // an exception?
114
115 // EXPECT_CALL(mockedUtil, getPresence(_,
116 // StrEq(PSUInventoryPath)))
117 // .Times(1);
118 }
119 catch (...)
120 {
121 ADD_FAILURE() << "Should not have caught exception.";
122 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600123}
124
125TEST_F(PowerSupplyTests, Analyze)
126{
127 auto bus = sdbusplus::bus::new_default();
128
B. J. Wyman681b2a32021-04-20 22:31:22 +0000129 // If I default to reading the GPIO, I will NOT expect a call to
130 // getPresence().
131
132 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000133 MockedGPIOInterface* mockPresenceGPIO =
134 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000135 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
136
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600137 psu.analyze();
138 // By default, nothing should change.
139 EXPECT_EQ(psu.isPresent(), false);
140 EXPECT_EQ(psu.isFaulted(), false);
141 EXPECT_EQ(psu.hasInputFault(), false);
142 EXPECT_EQ(psu.hasMFRFault(), false);
143 EXPECT_EQ(psu.hasVINUVFault(), false);
144
B. J. Wyman681b2a32021-04-20 22:31:22 +0000145 PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
146 // In order to get the various faults tested, the power supply needs to
147 // be present in order to read from the PMBus device(s).
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000148 MockedGPIOInterface* mockPresenceGPIO2 =
149 static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000150 ON_CALL(*mockPresenceGPIO2, read()).WillByDefault(Return(1));
151
152 EXPECT_EQ(psu2.isPresent(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600153
Brandon Wymanf07bc792021-10-12 19:00:35 +0000154 // STATUS_WORD 0x0000 is powered on, no faults (0x0000).
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600155 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
Brandon Wymanf07bc792021-10-12 19:00:35 +0000156 // Presence change from missing to present will trigger in1_input read in
157 // an attempt to get CLEAR_FAULTS called.
158 EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000));
159 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
160 .Times(1)
161 .WillOnce(Return(0x0000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600162 psu2.analyze();
163 EXPECT_EQ(psu2.isPresent(), true);
164 EXPECT_EQ(psu2.isFaulted(), false);
165 EXPECT_EQ(psu2.hasInputFault(), false);
166 EXPECT_EQ(psu2.hasMFRFault(), false);
167 EXPECT_EQ(psu2.hasVINUVFault(), false);
168
169 // STATUS_WORD input fault/warn
Brandon Wymanf07bc792021-10-12 19:00:35 +0000170 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
171 .Times(1)
172 .WillOnce(Return(status_word::INPUT_FAULT_WARN));
173 // Due to the fault bit on in STATUS_WORD, there will also be a read of
174 // STATUS_INPUT and STATUS_MFR, so there should be 3 reads total expected.
175 // STATUS_INPUT fault bits ... on.
176 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
177 .Times(1)
178 .WillOnce(Return(0x38));
179 // STATUS_MFR don't care
180 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0));
181
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600182 psu2.analyze();
183 EXPECT_EQ(psu2.isPresent(), true);
184 EXPECT_EQ(psu2.isFaulted(), true);
185 EXPECT_EQ(psu2.hasInputFault(), true);
186 EXPECT_EQ(psu2.hasMFRFault(), false);
187 EXPECT_EQ(psu2.hasVINUVFault(), false);
188
189 // STATUS_WORD INPUT/UV fault.
190 // First need it to return good status, then the fault
Brandon Wymanf07bc792021-10-12 19:00:35 +0000191 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
192 .Times(2)
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600193 .WillOnce(Return(0x0000))
Brandon Wymanf07bc792021-10-12 19:00:35 +0000194 .WillOnce(Return(
195 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT)));
196 // STATUS_INPUT fault bits ... on.
197 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
198 .Times(1)
199 .WillOnce(Return(0x38));
200 // STATUS_MFR don't care
201 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0));
202
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600203 psu2.analyze();
204 psu2.analyze();
205 EXPECT_EQ(psu2.isPresent(), true);
206 EXPECT_EQ(psu2.isFaulted(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000207 EXPECT_EQ(psu2.hasInputFault(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600208 EXPECT_EQ(psu2.hasMFRFault(), false);
209 EXPECT_EQ(psu2.hasVINUVFault(), true);
210
211 // STATUS_WORD MFR fault.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000212 // First need it to return good status, then the fault
213 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
214 .Times(2)
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600215 .WillOnce(Return(0x0000))
Brandon Wymanf07bc792021-10-12 19:00:35 +0000216 .WillOnce(Return(status_word::MFR_SPECIFIC_FAULT));
217 // STATUS_INPUT fault bits ... don't care.
218 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
219 .Times(1)
220 .WillOnce(Return(0x00));
221 // STATUS_MFR bits on.
222 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
223
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600224 psu2.analyze();
225 psu2.analyze();
226 EXPECT_EQ(psu2.isPresent(), true);
227 EXPECT_EQ(psu2.isFaulted(), true);
228 EXPECT_EQ(psu2.hasInputFault(), false);
229 EXPECT_EQ(psu2.hasMFRFault(), true);
230 EXPECT_EQ(psu2.hasVINUVFault(), false);
231
232 // Ignore Temperature fault.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000233 // First STATUS_WORD with no bits set, then with temperature fault.
234 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
235 .Times(2)
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600236 .WillOnce(Return(0x0000))
Brandon Wymanf07bc792021-10-12 19:00:35 +0000237 .WillOnce(Return(status_word::TEMPERATURE_FAULT_WARN));
238 // If STATUS_WORD bits set, should read STATUS_MFR_SPECIFIC and STATUS_INPUT
239 // STATUS_INPUT fault bits ... don't care.
240 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
241 .Times(1)
242 .WillOnce(Return(0x00));
243 // STATUS_MFR don't care
244 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0));
245
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600246 psu2.analyze();
247 psu2.analyze();
248 EXPECT_EQ(psu2.isPresent(), true);
249 EXPECT_EQ(psu2.isFaulted(), false);
250 EXPECT_EQ(psu2.hasInputFault(), false);
251 EXPECT_EQ(psu2.hasMFRFault(), false);
252 EXPECT_EQ(psu2.hasVINUVFault(), false);
253
254 // Ignore fan fault
Brandon Wymanf07bc792021-10-12 19:00:35 +0000255 // First STATUS_WORD with no bits set, then with fan fault.
256 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
257 .Times(2)
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600258 .WillOnce(Return(0x0000))
Brandon Wymanf07bc792021-10-12 19:00:35 +0000259 .WillOnce(Return(status_word::FAN_FAULT));
260 // STATUS_WORD bits set causes read STATUS_MFR_SPECIFIC and STATUS_INPUT.
261 // Don't care if bits set or not.
262 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
263 .Times(1)
264 .WillOnce(Return(0x00));
265 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0));
266
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600267 psu2.analyze();
268 psu2.analyze();
269 EXPECT_EQ(psu2.isPresent(), true);
270 EXPECT_EQ(psu2.isFaulted(), false);
271 EXPECT_EQ(psu2.hasInputFault(), false);
272 EXPECT_EQ(psu2.hasMFRFault(), false);
273 EXPECT_EQ(psu2.hasVINUVFault(), false);
274
275 // TODO: ReadFailure
276}
277
Brandon Wyman59a35792020-06-04 12:37:40 -0500278TEST_F(PowerSupplyTests, OnOffConfig)
279{
280 auto bus = sdbusplus::bus::new_default();
281 uint8_t data = 0x15;
282
283 // Test where PSU is NOT present
284 try
285 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000286 // Assume GPIO presence, not inventory presence?
287 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
288
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000289 MockedGPIOInterface* mockPresenceGPIO =
290 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000291 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
Brandon Wyman59a35792020-06-04 12:37:40 -0500292 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000293 // Constructor should set initial presence, default read returns 0.
Brandon Wyman59a35792020-06-04 12:37:40 -0500294 // If it is not present, I should not be trying to write to it.
295 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
296 psu.onOffConfig(data);
297 }
298 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000299 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500300
301 // Test where PSU is present
302 try
303 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000304 // Assume GPIO presence, not inventory presence?
305 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000306 MockedGPIOInterface* mockPresenceGPIO =
307 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000308 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1));
Brandon Wyman59a35792020-06-04 12:37:40 -0500309 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000310 // TODO: expect setPresence call?
311 // updatePresence() private function reads gpio, called by analyze().
312 psu.analyze();
Brandon Wyman59a35792020-06-04 12:37:40 -0500313 // TODO: ???should I check the filename?
314 EXPECT_CALL(mockPMBus,
315 writeBinary(_, ElementsAre(0x15), Type::HwmonDeviceDebug))
316 .Times(1);
317 psu.onOffConfig(data);
318 }
319 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000320 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500321}
322
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600323TEST_F(PowerSupplyTests, ClearFaults)
324{
325 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000326 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000327 MockedGPIOInterface* mockPresenceGPIO =
328 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000329 // GPIO read return 1 to indicate present.
330 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1));
331 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wymanf07bc792021-10-12 19:00:35 +0000332 ON_CALL(mockPMBus, read(STATUS_WORD, _)).WillByDefault(Return(0));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000333 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600334 EXPECT_EQ(psu.isPresent(), true);
335 EXPECT_EQ(psu.isFaulted(), false);
336 EXPECT_EQ(psu.hasInputFault(), false);
337 EXPECT_EQ(psu.hasMFRFault(), false);
338 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000339 // STATUS_WORD with fault bits galore!
340 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
341 .Times(1)
342 .WillOnce(Return(0xFFFF));
343 // If STATUS_WORD has any fault bits on, STATUS_MFR_SPECIFIC and
344 // STATUS_INPUT will be read.
345 // STATUS_INPUT with fault bits on.
346 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
347 .Times(1)
348 .WillOnce(Return(0xFF));
349 // STATUS_MFR_SPEFIC with bits on.
350 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600351 psu.analyze();
352 EXPECT_EQ(psu.isPresent(), true);
353 EXPECT_EQ(psu.isFaulted(), true);
354 EXPECT_EQ(psu.hasInputFault(), true);
355 EXPECT_EQ(psu.hasMFRFault(), true);
356 EXPECT_EQ(psu.hasVINUVFault(), true);
Brandon Wyman3c208462020-05-13 16:25:58 -0500357 EXPECT_CALL(mockPMBus, read("in1_input", _))
358 .Times(1)
359 .WillOnce(Return(209000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600360 psu.clearFaults();
361 EXPECT_EQ(psu.isPresent(), true);
362 EXPECT_EQ(psu.isFaulted(), false);
363 EXPECT_EQ(psu.hasInputFault(), false);
364 EXPECT_EQ(psu.hasMFRFault(), false);
365 EXPECT_EQ(psu.hasVINUVFault(), false);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000366
367 // TODO: Faults clear on missing/present?
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600368}
369
370TEST_F(PowerSupplyTests, UpdateInventory)
371{
372 auto bus = sdbusplus::bus::new_default();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500373
374 try
375 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000376 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500377 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
378 // If it is not present, I should not be trying to read a string
379 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
380 psu.updateInventory();
381 }
382 catch (...)
383 {
384 ADD_FAILURE() << "Should not have caught exception.";
385 }
386
387 try
388 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000389 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000390 MockedGPIOInterface* mockPresenceGPIO =
391 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000392 // GPIO read return 1 to indicate present.
393 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
394 psu.analyze();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500395 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
396 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
397 psu.updateInventory();
398
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500399#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500400 EXPECT_CALL(mockPMBus, readString(_, _))
401 .WillOnce(Return("CCIN"))
402 .WillOnce(Return("PN3456"))
403 .WillOnce(Return("FN3456"))
404 .WillOnce(Return("HEADER"))
405 .WillOnce(Return("SN3456"))
406 .WillOnce(Return("FW3456"));
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500407#endif
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500408 psu.updateInventory();
409 // TODO: D-Bus mocking to verify values stored on D-Bus (???)
410 }
411 catch (...)
412 {
413 ADD_FAILURE() << "Should not have caught exception.";
414 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600415}
416
417TEST_F(PowerSupplyTests, IsPresent)
418{
419 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000420
421 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000422 MockedGPIOInterface* mockPresenceGPIO =
423 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600424 EXPECT_EQ(psu.isPresent(), false);
425
B. J. Wyman681b2a32021-04-20 22:31:22 +0000426 // Change GPIO read to return 1 to indicate present.
427 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
428 psu.analyze();
429 EXPECT_EQ(psu.isPresent(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600430}
431
432TEST_F(PowerSupplyTests, IsFaulted)
433{
434 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000435
436 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000437 MockedGPIOInterface* mockPresenceGPIO =
438 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000439 // Always return 1 to indicate present.
440 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
441 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600442 EXPECT_EQ(psu.isFaulted(), false);
443 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wymanf07bc792021-10-12 19:00:35 +0000444 // STATUS_WORD with fault bits on.
445 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
446 .Times(1)
447 .WillOnce(Return(0xFFFF));
448 // If STATUS_WORD has bit(s) on, STATUS_MFR_SPECIFIC and STATUS_INPUT read.
449 // STATUS_INPUT with fault bits on.
450 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
451 .Times(1)
452 .WillOnce(Return(0xFF));
453 // STATUS_MFR_SPECIFIC with faults bits on.
454 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600455 psu.analyze();
456 EXPECT_EQ(psu.isFaulted(), true);
457}
458
459TEST_F(PowerSupplyTests, HasInputFault)
460{
461 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000462
463 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000464 MockedGPIOInterface* mockPresenceGPIO =
465 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000466 // Always return 1 to indicate present.
467 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
468 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600469 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
470 EXPECT_EQ(psu.hasInputFault(), false);
471 EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
472 psu.analyze();
473 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000474 // STATUS_WORD with input fault/warn on.
475 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
476 .Times(1)
477 .WillOnce(Return(status_word::INPUT_FAULT_WARN));
478 // If STATUS_WORD has bit(s) on, STATUS_MFR_SPECIFIC and STATUS_INPUT read.
479 // STATUS_INPUT with an input fault bit on.
480 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
481 .Times(1)
482 .WillOnce(Return(0x80));
483 // STATUS_MFR don't care.
484 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0x00));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600485 psu.analyze();
486 EXPECT_EQ(psu.hasInputFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000487 // STATUS_WORD with no bits on.
488 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
489 .Times(1)
490 .WillOnce(Return(0x0000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600491 psu.analyze();
492 EXPECT_EQ(psu.hasInputFault(), false);
493}
494
495TEST_F(PowerSupplyTests, HasMFRFault)
496{
497 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000498
499 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000500 MockedGPIOInterface* mockPresenceGPIO =
501 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000502 // Always return 1 to indicate present.
503 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
504 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600505 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
506 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000507 // First return STATUS_WORD with no bits on.
508 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
509 .Times(1)
510 .WillOnce(Return(0x0000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600511 psu.analyze();
512 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000513 // Next return STATUS_WORD with MFR fault bit on.
514 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
515 .Times(1)
516 .WillOnce(Return(status_word::MFR_SPECIFIC_FAULT));
517 // If STATUS_WORD has bits on, STATUS_MFR_SPECIFIC and STATUS_INPUT read.
518 // STATUS_INPUT don't care
519 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
520 .Times(1)
521 .WillOnce(Return(0x00));
522 // STATUS_MFR_SPEFIC with bit(s) on.
523 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600524 psu.analyze();
525 EXPECT_EQ(psu.hasMFRFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000526 // Back to no bits on in STATUS_WORD
527 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
528 .Times(1)
529 .WillOnce(Return(0x0000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600530 psu.analyze();
531 EXPECT_EQ(psu.hasMFRFault(), false);
532}
533
534TEST_F(PowerSupplyTests, HasVINUVFault)
535{
536 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000537
538 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, 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 // Always return 1 to indicate present.
542 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
543 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600544 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
545 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000546 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
547 .Times(1)
548 .WillOnce(Return(0x0000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600549 psu.analyze();
550 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000551 // Turn fault on.
552 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
553 .Times(1)
554 .WillOnce(Return(status_word::VIN_UV_FAULT));
555 // Fault bits on in STATUS_WORD causes read of STATUS_MFR_SPECIFIC and
556 // STATUS_INPUT.
557 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33.
558 // Go by Figure 16, and assume bits on in STATUS_INPUT.
559 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
560 .Times(1)
561 .WillOnce(Return(0x18));
562 // STATUS_MFR don't care.
563 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0x00));
564
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600565 psu.analyze();
566 EXPECT_EQ(psu.hasVINUVFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000567 // Back to no fault bits on in STATUS_WORD
568 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
569 .Times(1)
570 .WillOnce(Return(0x0000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600571 psu.analyze();
572 EXPECT_EQ(psu.hasVINUVFault(), false);
573}