blob: 5eb4b3e75ac151c000893ba91913db1b86c4d40a [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";
23
24class PowerSupplyTests : public ::testing::Test
25{
26 public:
27 PowerSupplyTests() :
28 mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
29 {
30 ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
31 }
32
33 ~PowerSupplyTests() override
34 {
35 freeUtils();
36 }
37
38 const MockedUtil& mockedUtil;
39};
40
41TEST_F(PowerSupplyTests, Constructor)
42{
43 /**
44 * @param[in] invpath - String for inventory path to use
45 * @param[in] i2cbus - The bus number this power supply is on
46 * @param[in] i2caddr - The 16-bit I2C address of the power supply
47 */
48 auto bus = sdbusplus::bus::new_default();
49 EXPECT_CALL(mockedUtil, getPresence(_, StrEq(PSUInventoryPath))).Times(1);
50 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, "0068");
51
52 EXPECT_EQ(psu->isPresent(), false);
53 EXPECT_EQ(psu->isFaulted(), false);
54 EXPECT_EQ(psu->hasInputFault(), false);
55 EXPECT_EQ(psu->hasMFRFault(), false);
56 EXPECT_EQ(psu->hasVINUVFault(), false);
57}
58
59TEST_F(PowerSupplyTests, Analyze)
60{
61 auto bus = sdbusplus::bus::new_default();
62
63 EXPECT_CALL(mockedUtil, getPresence(_, StrEq(PSUInventoryPath))).Times(1);
64 PowerSupply psu{bus, PSUInventoryPath, 4, "0069"};
65 psu.analyze();
66 // By default, nothing should change.
67 EXPECT_EQ(psu.isPresent(), false);
68 EXPECT_EQ(psu.isFaulted(), false);
69 EXPECT_EQ(psu.hasInputFault(), false);
70 EXPECT_EQ(psu.hasMFRFault(), false);
71 EXPECT_EQ(psu.hasVINUVFault(), false);
72
73 // In order to get the various faults tested, the power supply needs to be
74 // present in order to read from the PMBus device(s).
75 EXPECT_CALL(mockedUtil, getPresence(_, StrEq(PSUInventoryPath)))
76 .Times(1)
77 .WillOnce(Return(true)); // present
78 PowerSupply psu2{bus, PSUInventoryPath, 5, "006a"};
79 EXPECT_EQ(psu2.isPresent(), true);
80
81 // STATUS_WORD 0x0000 is powered on, no faults.
82 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
83 EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
84 psu2.analyze();
85 EXPECT_EQ(psu2.isPresent(), true);
86 EXPECT_EQ(psu2.isFaulted(), false);
87 EXPECT_EQ(psu2.hasInputFault(), false);
88 EXPECT_EQ(psu2.hasMFRFault(), false);
89 EXPECT_EQ(psu2.hasVINUVFault(), false);
90
91 // STATUS_WORD input fault/warn
92 EXPECT_CALL(mockPMBus, read(_, _))
93 .Times(1)
94 .WillOnce(Return(status_word::INPUT_FAULT_WARN));
95 psu2.analyze();
96 EXPECT_EQ(psu2.isPresent(), true);
97 EXPECT_EQ(psu2.isFaulted(), true);
98 EXPECT_EQ(psu2.hasInputFault(), true);
99 EXPECT_EQ(psu2.hasMFRFault(), false);
100 EXPECT_EQ(psu2.hasVINUVFault(), false);
101
102 // STATUS_WORD INPUT/UV fault.
103 // First need it to return good status, then the fault
104 EXPECT_CALL(mockPMBus, read(_, _))
105 .WillOnce(Return(0x0000))
106 .WillOnce(Return(status_word::VIN_UV_FAULT));
107 psu2.analyze();
108 psu2.analyze();
109 EXPECT_EQ(psu2.isPresent(), true);
110 EXPECT_EQ(psu2.isFaulted(), true);
111 EXPECT_EQ(psu2.hasInputFault(), false);
112 EXPECT_EQ(psu2.hasMFRFault(), false);
113 EXPECT_EQ(psu2.hasVINUVFault(), true);
114
115 // STATUS_WORD MFR fault.
116 EXPECT_CALL(mockPMBus, read(_, _))
117 .WillOnce(Return(0x0000))
118 .WillOnce(Return(status_word::MFR_SPECIFIC_FAULT));
119 psu2.analyze();
120 psu2.analyze();
121 EXPECT_EQ(psu2.isPresent(), true);
122 EXPECT_EQ(psu2.isFaulted(), true);
123 EXPECT_EQ(psu2.hasInputFault(), false);
124 EXPECT_EQ(psu2.hasMFRFault(), true);
125 EXPECT_EQ(psu2.hasVINUVFault(), false);
126
127 // Ignore Temperature fault.
128 EXPECT_CALL(mockPMBus, read(_, _))
129 .WillOnce(Return(0x0000))
130 .WillOnce(Return(status_word::TEMPERATURE_FAULT_WARN));
131 psu2.analyze();
132 psu2.analyze();
133 EXPECT_EQ(psu2.isPresent(), true);
134 EXPECT_EQ(psu2.isFaulted(), false);
135 EXPECT_EQ(psu2.hasInputFault(), false);
136 EXPECT_EQ(psu2.hasMFRFault(), false);
137 EXPECT_EQ(psu2.hasVINUVFault(), false);
138
139 // Ignore fan fault
140 EXPECT_CALL(mockPMBus, read(_, _))
141 .WillOnce(Return(0x0000))
142 .WillOnce(Return(status_word::FAN_FAULT));
143 psu2.analyze();
144 psu2.analyze();
145 EXPECT_EQ(psu2.isPresent(), true);
146 EXPECT_EQ(psu2.isFaulted(), false);
147 EXPECT_EQ(psu2.hasInputFault(), false);
148 EXPECT_EQ(psu2.hasMFRFault(), false);
149 EXPECT_EQ(psu2.hasVINUVFault(), false);
150
151 // TODO: ReadFailure
152}
153
Brandon Wyman59a35792020-06-04 12:37:40 -0500154TEST_F(PowerSupplyTests, OnOffConfig)
155{
156 auto bus = sdbusplus::bus::new_default();
157 uint8_t data = 0x15;
158
159 // Test where PSU is NOT present
160 try
161 {
162 EXPECT_CALL(mockedUtil, getPresence(_, StrEq(PSUInventoryPath)))
163 .Times(1)
164 .WillOnce(Return(false));
165 PowerSupply psu{bus, PSUInventoryPath, 4, "0069"};
166 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
167 // If it is not present, I should not be trying to write to it.
168 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
169 psu.onOffConfig(data);
170 }
171 catch (...)
172 {
173 }
174
175 // Test where PSU is present
176 try
177 {
178 EXPECT_CALL(mockedUtil, getPresence(_, StrEq(PSUInventoryPath)))
179 .Times(1)
180 .WillOnce(Return(true)); // present
181 PowerSupply psu{bus, PSUInventoryPath, 5, "006a"};
182 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
183 // TODO: ???should I check the filename?
184 EXPECT_CALL(mockPMBus,
185 writeBinary(_, ElementsAre(0x15), Type::HwmonDeviceDebug))
186 .Times(1);
187 psu.onOffConfig(data);
188 }
189 catch (...)
190 {
191 }
192}
193
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600194TEST_F(PowerSupplyTests, ClearFaults)
195{
196 auto bus = sdbusplus::bus::new_default();
197 EXPECT_CALL(mockedUtil, getPresence(_, StrEq(PSUInventoryPath)))
198 .Times(1)
199 .WillOnce(Return(true)); // present
200 PowerSupply psu{bus, PSUInventoryPath, 13, "0068"};
201 EXPECT_EQ(psu.isPresent(), true);
202 EXPECT_EQ(psu.isFaulted(), false);
203 EXPECT_EQ(psu.hasInputFault(), false);
204 EXPECT_EQ(psu.hasMFRFault(), false);
205 EXPECT_EQ(psu.hasVINUVFault(), false);
206 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
207 EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0xFFFF));
208 psu.analyze();
209 EXPECT_EQ(psu.isPresent(), true);
210 EXPECT_EQ(psu.isFaulted(), true);
211 EXPECT_EQ(psu.hasInputFault(), true);
212 EXPECT_EQ(psu.hasMFRFault(), true);
213 EXPECT_EQ(psu.hasVINUVFault(), true);
Brandon Wyman3c208462020-05-13 16:25:58 -0500214 EXPECT_CALL(mockPMBus, read("in1_input", _))
215 .Times(1)
216 .WillOnce(Return(209000));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600217 psu.clearFaults();
218 EXPECT_EQ(psu.isPresent(), true);
219 EXPECT_EQ(psu.isFaulted(), false);
220 EXPECT_EQ(psu.hasInputFault(), false);
221 EXPECT_EQ(psu.hasMFRFault(), false);
222 EXPECT_EQ(psu.hasVINUVFault(), false);
223}
224
225TEST_F(PowerSupplyTests, UpdateInventory)
226{
227 auto bus = sdbusplus::bus::new_default();
228 EXPECT_CALL(mockedUtil, getPresence(_, StrEq(PSUInventoryPath)))
229 .Times(1)
230 .WillOnce(Return(true)); // present
231 PowerSupply psu{bus, PSUInventoryPath, 3, "0068"};
232 psu.updateInventory();
233 // TODO: Checks / Story #921
234}
235
236TEST_F(PowerSupplyTests, IsPresent)
237{
238 auto bus = sdbusplus::bus::new_default();
239 EXPECT_CALL(mockedUtil, getPresence(_, StrEq(PSUInventoryPath))).Times(1);
240 PowerSupply psu{bus, PSUInventoryPath, 3, "0068"};
241 EXPECT_EQ(psu.isPresent(), false);
242
243 EXPECT_CALL(mockedUtil, getPresence(_, _))
244 .WillOnce(Return(true)); // present
245 PowerSupply psu2{bus, PSUInventoryPath, 10, "006b"};
246 EXPECT_EQ(psu2.isPresent(), true);
247}
248
249TEST_F(PowerSupplyTests, IsFaulted)
250{
251 auto bus = sdbusplus::bus::new_default();
252 EXPECT_CALL(mockedUtil, getPresence(_, _))
253 .WillOnce(Return(true)); // present
254 PowerSupply psu{bus, PSUInventoryPath, 11, "006f"};
255 EXPECT_EQ(psu.isFaulted(), false);
256 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
257 EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0xFFFF));
258 psu.analyze();
259 EXPECT_EQ(psu.isFaulted(), true);
260}
261
262TEST_F(PowerSupplyTests, HasInputFault)
263{
264 auto bus = sdbusplus::bus::new_default();
265 EXPECT_CALL(mockedUtil, getPresence(_, _))
266 .WillOnce(Return(true)); // present
267 PowerSupply psu{bus, PSUInventoryPath, 3, "0068"};
268 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
269 EXPECT_EQ(psu.hasInputFault(), false);
270 EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
271 psu.analyze();
272 EXPECT_EQ(psu.hasInputFault(), false);
273 EXPECT_CALL(mockPMBus, read(_, _))
274 .Times(1)
275 .WillOnce(Return(status_word::INPUT_FAULT_WARN));
276 psu.analyze();
277 EXPECT_EQ(psu.hasInputFault(), true);
278 EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
279 psu.analyze();
280 EXPECT_EQ(psu.hasInputFault(), false);
281}
282
283TEST_F(PowerSupplyTests, HasMFRFault)
284{
285 auto bus = sdbusplus::bus::new_default();
286 EXPECT_CALL(mockedUtil, getPresence(_, _))
287 .WillOnce(Return(true)); // present
288 PowerSupply psu{bus, PSUInventoryPath, 3, "0068"};
289 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
290 EXPECT_EQ(psu.hasMFRFault(), false);
291 EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
292 psu.analyze();
293 EXPECT_EQ(psu.hasMFRFault(), false);
294 EXPECT_CALL(mockPMBus, read(_, _))
295 .Times(1)
296 .WillOnce(Return(status_word::MFR_SPECIFIC_FAULT));
297 psu.analyze();
298 EXPECT_EQ(psu.hasMFRFault(), true);
299 EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
300 psu.analyze();
301 EXPECT_EQ(psu.hasMFRFault(), false);
302}
303
304TEST_F(PowerSupplyTests, HasVINUVFault)
305{
306 auto bus = sdbusplus::bus::new_default();
307 EXPECT_CALL(mockedUtil, getPresence(_, _))
308 .WillOnce(Return(true)); // present
309 PowerSupply psu{bus, PSUInventoryPath, 3, "0068"};
310 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
311 EXPECT_EQ(psu.hasVINUVFault(), false);
312 EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
313 psu.analyze();
314 EXPECT_EQ(psu.hasVINUVFault(), false);
315 EXPECT_CALL(mockPMBus, read(_, _))
316 .Times(1)
317 .WillOnce(Return(status_word::VIN_UV_FAULT));
318 psu.analyze();
319 EXPECT_EQ(psu.hasVINUVFault(), true);
320 EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
321 psu.analyze();
322 EXPECT_EQ(psu.hasVINUVFault(), false);
323}