blob: ef87a1577fb29efc84288a84b676650cdbef5a5d [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);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000144 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600145
B. J. Wyman681b2a32021-04-20 22:31:22 +0000146 PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
147 // In order to get the various faults tested, the power supply needs to
148 // be present in order to read from the PMBus device(s).
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000149 MockedGPIOInterface* mockPresenceGPIO2 =
150 static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000151 ON_CALL(*mockPresenceGPIO2, read()).WillByDefault(Return(1));
152
153 EXPECT_EQ(psu2.isPresent(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600154
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));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000159 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000160 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
161 .Times(1)
162 .WillOnce(Return(0x0000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600163 psu2.analyze();
164 EXPECT_EQ(psu2.isPresent(), true);
165 EXPECT_EQ(psu2.isFaulted(), false);
166 EXPECT_EQ(psu2.hasInputFault(), false);
167 EXPECT_EQ(psu2.hasMFRFault(), false);
168 EXPECT_EQ(psu2.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000169 EXPECT_EQ(psu2.hasCommFault(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600170
171 // STATUS_WORD input fault/warn
Brandon Wymanf07bc792021-10-12 19:00:35 +0000172 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
173 .Times(1)
174 .WillOnce(Return(status_word::INPUT_FAULT_WARN));
175 // Due to the fault bit on in STATUS_WORD, there will also be a read of
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000176 // STATUS_INPUT, STATUS_MFR, and STATUS_CML, so there should be 4 reads
177 // total expected.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000178 // STATUS_INPUT fault bits ... on.
179 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
180 .Times(1)
181 .WillOnce(Return(0x38));
182 // STATUS_MFR don't care
183 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000184 // STATUS_CML don't care
185 EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600186 psu2.analyze();
187 EXPECT_EQ(psu2.isPresent(), true);
188 EXPECT_EQ(psu2.isFaulted(), true);
189 EXPECT_EQ(psu2.hasInputFault(), true);
190 EXPECT_EQ(psu2.hasMFRFault(), false);
191 EXPECT_EQ(psu2.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000192 EXPECT_EQ(psu2.hasCommFault(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600193
194 // STATUS_WORD INPUT/UV fault.
195 // First need it to return good status, then the fault
Brandon Wymanf07bc792021-10-12 19:00:35 +0000196 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
197 .Times(2)
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600198 .WillOnce(Return(0x0000))
Brandon Wymanf07bc792021-10-12 19:00:35 +0000199 .WillOnce(Return(
200 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT)));
201 // STATUS_INPUT fault bits ... on.
202 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
203 .Times(1)
204 .WillOnce(Return(0x38));
205 // STATUS_MFR don't care
206 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000207 // STATUS_CML don't care
208 EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600209 psu2.analyze();
210 psu2.analyze();
211 EXPECT_EQ(psu2.isPresent(), true);
212 EXPECT_EQ(psu2.isFaulted(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000213 EXPECT_EQ(psu2.hasInputFault(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600214 EXPECT_EQ(psu2.hasMFRFault(), false);
215 EXPECT_EQ(psu2.hasVINUVFault(), true);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000216 EXPECT_EQ(psu2.hasCommFault(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600217
218 // STATUS_WORD MFR fault.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000219 // First need it to return good status, then the fault
220 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
221 .Times(2)
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600222 .WillOnce(Return(0x0000))
Brandon Wymanf07bc792021-10-12 19:00:35 +0000223 .WillOnce(Return(status_word::MFR_SPECIFIC_FAULT));
224 // STATUS_INPUT fault bits ... don't care.
225 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
226 .Times(1)
227 .WillOnce(Return(0x00));
228 // STATUS_MFR bits on.
229 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000230 // STATUS_CML don't care
231 EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600232 psu2.analyze();
233 psu2.analyze();
234 EXPECT_EQ(psu2.isPresent(), true);
235 EXPECT_EQ(psu2.isFaulted(), true);
236 EXPECT_EQ(psu2.hasInputFault(), false);
237 EXPECT_EQ(psu2.hasMFRFault(), true);
238 EXPECT_EQ(psu2.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000239 EXPECT_EQ(psu2.hasCommFault(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600240
241 // Ignore Temperature fault.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000242 // First STATUS_WORD with no bits set, then with temperature fault.
243 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
244 .Times(2)
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600245 .WillOnce(Return(0x0000))
Brandon Wymanf07bc792021-10-12 19:00:35 +0000246 .WillOnce(Return(status_word::TEMPERATURE_FAULT_WARN));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000247 // If the STATUS_WORD has bits on, STATUS_MFR_SPECIFIC, STATUS_INPUT, and
248 // STATUS_CML will also be read.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000249 // STATUS_INPUT fault bits ... don't care.
250 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
251 .Times(1)
252 .WillOnce(Return(0x00));
253 // STATUS_MFR don't care
254 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000255 // STATUS_CML don't care
256 EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600257 psu2.analyze();
258 psu2.analyze();
259 EXPECT_EQ(psu2.isPresent(), true);
260 EXPECT_EQ(psu2.isFaulted(), false);
261 EXPECT_EQ(psu2.hasInputFault(), false);
262 EXPECT_EQ(psu2.hasMFRFault(), false);
263 EXPECT_EQ(psu2.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000264 EXPECT_EQ(psu2.hasCommFault(), false);
265
266 // CML fault
267 // First STATUS_WORD wit no bits set, then with CML fault.
268 // STATUS_WORD with CML fault bit on.
269 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
270 .Times(2)
271 .WillOnce(Return(0x0000))
272 .WillOnce(Return(status_word::CML_FAULT));
273 psu2.analyze();
274 // If the STATUS_WORD has bits on, STATUS_MFR_SPECIFIC, STATUS_INPUT, and
275 // STATUS_CML will also be read.
276 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
277 .Times(1)
278 .WillOnce(Return(0x00));
279 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0x00));
280 // Turn on STATUS_CML fault bit(s)
281 EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0xFF));
282 psu2.analyze();
283 EXPECT_EQ(psu2.isPresent(), true);
284 EXPECT_EQ(psu2.isFaulted(), true);
285 EXPECT_EQ(psu2.hasInputFault(), false);
286 EXPECT_EQ(psu2.hasMFRFault(), false);
287 EXPECT_EQ(psu2.hasVINUVFault(), false);
288 EXPECT_EQ(psu2.hasCommFault(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600289
290 // Ignore fan fault
Brandon Wymanf07bc792021-10-12 19:00:35 +0000291 // First STATUS_WORD with no bits set, then with fan fault.
292 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
293 .Times(2)
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600294 .WillOnce(Return(0x0000))
Brandon Wymanf07bc792021-10-12 19:00:35 +0000295 .WillOnce(Return(status_word::FAN_FAULT));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000296 // If the STATUS_WORD has bits on, STATUS_MFR_SPECIFIC, STATUS_INPUT, and
297 // STATUS_CML will also be read.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000298 // Don't care if bits set or not.
299 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
300 .Times(1)
301 .WillOnce(Return(0x00));
302 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000303 EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600304 psu2.analyze();
305 psu2.analyze();
306 EXPECT_EQ(psu2.isPresent(), true);
307 EXPECT_EQ(psu2.isFaulted(), false);
308 EXPECT_EQ(psu2.hasInputFault(), false);
309 EXPECT_EQ(psu2.hasMFRFault(), false);
310 EXPECT_EQ(psu2.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000311 EXPECT_EQ(psu2.hasCommFault(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600312
313 // TODO: ReadFailure
314}
315
Brandon Wyman59a35792020-06-04 12:37:40 -0500316TEST_F(PowerSupplyTests, OnOffConfig)
317{
318 auto bus = sdbusplus::bus::new_default();
319 uint8_t data = 0x15;
320
321 // Test where PSU is NOT present
322 try
323 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000324 // Assume GPIO presence, not inventory presence?
325 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69, PSUGPIOLineName};
326
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 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
Brandon Wyman59a35792020-06-04 12:37:40 -0500330 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000331 // Constructor should set initial presence, default read returns 0.
Brandon Wyman59a35792020-06-04 12:37:40 -0500332 // If it is not present, I should not be trying to write to it.
333 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
334 psu.onOffConfig(data);
335 }
336 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000337 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500338
339 // Test where PSU is present
340 try
341 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000342 // Assume GPIO presence, not inventory presence?
343 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000344 MockedGPIOInterface* mockPresenceGPIO =
345 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000346 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1));
Brandon Wyman59a35792020-06-04 12:37:40 -0500347 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000348 // TODO: expect setPresence call?
349 // updatePresence() private function reads gpio, called by analyze().
350 psu.analyze();
Brandon Wyman59a35792020-06-04 12:37:40 -0500351 // TODO: ???should I check the filename?
352 EXPECT_CALL(mockPMBus,
353 writeBinary(_, ElementsAre(0x15), Type::HwmonDeviceDebug))
354 .Times(1);
355 psu.onOffConfig(data);
356 }
357 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000358 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500359}
360
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600361TEST_F(PowerSupplyTests, ClearFaults)
362{
363 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000364 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000365 MockedGPIOInterface* mockPresenceGPIO =
366 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000367 // GPIO read return 1 to indicate present.
368 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1));
369 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wymanf07bc792021-10-12 19:00:35 +0000370 ON_CALL(mockPMBus, read(STATUS_WORD, _)).WillByDefault(Return(0));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000371 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600372 EXPECT_EQ(psu.isPresent(), true);
373 EXPECT_EQ(psu.isFaulted(), false);
374 EXPECT_EQ(psu.hasInputFault(), false);
375 EXPECT_EQ(psu.hasMFRFault(), false);
376 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000377 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000378 // STATUS_WORD with fault bits galore!
379 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
380 .Times(1)
381 .WillOnce(Return(0xFFFF));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000382 // If STATUS_WORD has any fault bits on, STATUS_MFR_SPECIFIC, STATUS_INPUT
383 // and STATUS_CML will be read.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000384 // STATUS_INPUT with fault bits on.
385 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
386 .Times(1)
387 .WillOnce(Return(0xFF));
388 // STATUS_MFR_SPEFIC with bits on.
389 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000390 // STATUS_CML with bits on.
391 EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0xFF));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600392 psu.analyze();
393 EXPECT_EQ(psu.isPresent(), true);
394 EXPECT_EQ(psu.isFaulted(), true);
395 EXPECT_EQ(psu.hasInputFault(), true);
396 EXPECT_EQ(psu.hasMFRFault(), true);
397 EXPECT_EQ(psu.hasVINUVFault(), true);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000398 EXPECT_EQ(psu.hasCommFault(), true);
Brandon Wyman3c208462020-05-13 16:25:58 -0500399 EXPECT_CALL(mockPMBus, read("in1_input", _))
400 .Times(1)
401 .WillOnce(Return(209000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600402 psu.clearFaults();
403 EXPECT_EQ(psu.isPresent(), true);
404 EXPECT_EQ(psu.isFaulted(), false);
405 EXPECT_EQ(psu.hasInputFault(), false);
406 EXPECT_EQ(psu.hasMFRFault(), false);
407 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000408 EXPECT_EQ(psu.hasCommFault(), false);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000409
410 // TODO: Faults clear on missing/present?
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600411}
412
413TEST_F(PowerSupplyTests, UpdateInventory)
414{
415 auto bus = sdbusplus::bus::new_default();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500416
417 try
418 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000419 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500420 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
421 // If it is not present, I should not be trying to read a string
422 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
423 psu.updateInventory();
424 }
425 catch (...)
426 {
427 ADD_FAILURE() << "Should not have caught exception.";
428 }
429
430 try
431 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000432 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000433 MockedGPIOInterface* mockPresenceGPIO =
434 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000435 // GPIO read return 1 to indicate present.
436 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
437 psu.analyze();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500438 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
439 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
440 psu.updateInventory();
441
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500442#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500443 EXPECT_CALL(mockPMBus, readString(_, _))
444 .WillOnce(Return("CCIN"))
445 .WillOnce(Return("PN3456"))
446 .WillOnce(Return("FN3456"))
447 .WillOnce(Return("HEADER"))
448 .WillOnce(Return("SN3456"))
449 .WillOnce(Return("FW3456"));
Brandon Wyman3c530fb2021-04-13 13:13:22 -0500450#endif
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500451 psu.updateInventory();
452 // TODO: D-Bus mocking to verify values stored on D-Bus (???)
453 }
454 catch (...)
455 {
456 ADD_FAILURE() << "Should not have caught exception.";
457 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600458}
459
460TEST_F(PowerSupplyTests, IsPresent)
461{
462 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000463
464 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000465 MockedGPIOInterface* mockPresenceGPIO =
466 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600467 EXPECT_EQ(psu.isPresent(), false);
468
B. J. Wyman681b2a32021-04-20 22:31:22 +0000469 // Change GPIO read to return 1 to indicate present.
470 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
471 psu.analyze();
472 EXPECT_EQ(psu.isPresent(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600473}
474
475TEST_F(PowerSupplyTests, IsFaulted)
476{
477 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000478
479 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000480 MockedGPIOInterface* mockPresenceGPIO =
481 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000482 // Always return 1 to indicate present.
483 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
484 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600485 EXPECT_EQ(psu.isFaulted(), false);
486 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wymanf07bc792021-10-12 19:00:35 +0000487 // STATUS_WORD with fault bits on.
488 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
489 .Times(1)
490 .WillOnce(Return(0xFFFF));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000491 // Fault bit(s) on in STATUS_WORD causes read of STATUS_MFR_SPECIFIC,
492 // STATUS_INPUT, and STATUS_CML.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000493 // STATUS_INPUT with fault bits on.
494 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
495 .Times(1)
496 .WillOnce(Return(0xFF));
497 // STATUS_MFR_SPECIFIC with faults bits on.
498 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000499 // STATUS_CML with faults bits on.
500 EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0xFF));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600501 psu.analyze();
502 EXPECT_EQ(psu.isFaulted(), true);
503}
504
505TEST_F(PowerSupplyTests, HasInputFault)
506{
507 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000508
509 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000510 MockedGPIOInterface* mockPresenceGPIO =
511 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000512 // Always return 1 to indicate present.
513 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
514 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600515 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
516 EXPECT_EQ(psu.hasInputFault(), false);
517 EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
518 psu.analyze();
519 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000520 // STATUS_WORD with input fault/warn on.
521 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
522 .Times(1)
523 .WillOnce(Return(status_word::INPUT_FAULT_WARN));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000524 // Fault bit(s) on in STATUS_WORD causes read of STATUS_MFR_SPECIFIC,
525 // STATUS_INPUT, and STATUS_CML.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000526 // STATUS_INPUT with an input fault bit on.
527 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
528 .Times(1)
529 .WillOnce(Return(0x80));
530 // STATUS_MFR don't care.
531 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0x00));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000532 // STATUS_CML don't care.
533 EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0x00));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600534 psu.analyze();
535 EXPECT_EQ(psu.hasInputFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000536 // STATUS_WORD with no bits on.
537 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
538 .Times(1)
539 .WillOnce(Return(0x0000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600540 psu.analyze();
541 EXPECT_EQ(psu.hasInputFault(), false);
542}
543
544TEST_F(PowerSupplyTests, HasMFRFault)
545{
546 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000547
548 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000549 MockedGPIOInterface* mockPresenceGPIO =
550 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000551 // Always return 1 to indicate present.
552 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
553 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600554 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
555 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000556 // First return STATUS_WORD with no bits on.
557 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
558 .Times(1)
559 .WillOnce(Return(0x0000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600560 psu.analyze();
561 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000562 // Next return STATUS_WORD with MFR fault bit on.
563 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
564 .Times(1)
565 .WillOnce(Return(status_word::MFR_SPECIFIC_FAULT));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000566 // Fault bit(s) on in STATUS_WORD causes read of STATUS_MFR_SPECIFIC,
567 // STATUS_INPUT, and STATUS_CML.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000568 // STATUS_INPUT don't care
569 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
570 .Times(1)
571 .WillOnce(Return(0x00));
572 // STATUS_MFR_SPEFIC with bit(s) on.
573 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000574 // STATUS_CML don't care.
575 EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0x00));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600576 psu.analyze();
577 EXPECT_EQ(psu.hasMFRFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000578 // Back to no bits on in STATUS_WORD
579 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
580 .Times(1)
581 .WillOnce(Return(0x0000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600582 psu.analyze();
583 EXPECT_EQ(psu.hasMFRFault(), false);
584}
585
586TEST_F(PowerSupplyTests, HasVINUVFault)
587{
588 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +0000589
590 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68, PSUGPIOLineName};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000591 MockedGPIOInterface* mockPresenceGPIO =
592 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000593 // Always return 1 to indicate present.
594 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
595 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600596 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
597 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000598 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
599 .Times(1)
600 .WillOnce(Return(0x0000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600601 psu.analyze();
602 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000603 // Turn fault on.
604 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
605 .Times(1)
606 .WillOnce(Return(status_word::VIN_UV_FAULT));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000607 // Fault bit(s) on in STATUS_WORD causes read of STATUS_MFR_SPECIFIC,
608 // STATUS_INPUT, and STATUS_CML.
609 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
610 // Figure 16, and assume bits on in STATUS_INPUT.
Brandon Wymanf07bc792021-10-12 19:00:35 +0000611 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
612 .Times(1)
613 .WillOnce(Return(0x18));
614 // STATUS_MFR don't care.
615 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0x00));
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000616 // STATUS_CML don't care.
617 EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0x00));
Brandon Wymanf07bc792021-10-12 19:00:35 +0000618
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600619 psu.analyze();
620 EXPECT_EQ(psu.hasVINUVFault(), true);
Brandon Wymanf07bc792021-10-12 19:00:35 +0000621 // Back to no fault bits on in STATUS_WORD
622 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
623 .Times(1)
624 .WillOnce(Return(0x0000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600625 psu.analyze();
626 EXPECT_EQ(psu.hasVINUVFault(), false);
627}