blob: 451e1372f1cdac88e4890246fb5f3a7b18cbd41b [file] [log] [blame]
Shawn McCarney8a3afd72020-03-12 14:28:44 -05001/**
2 * Copyright © 2020 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Shawn McCarney525e20c2020-04-14 11:05:39 -050016#include "action.hpp"
Shawn McCarney8a3afd72020-03-12 14:28:44 -050017#include "chassis.hpp"
Shawn McCarney525e20c2020-04-14 11:05:39 -050018#include "configuration.hpp"
Shawn McCarney8a3afd72020-03-12 14:28:44 -050019#include "device.hpp"
20#include "i2c_interface.hpp"
Shawn McCarneydb0b8332020-04-06 14:13:04 -050021#include "id_map.hpp"
Shawn McCarney525e20c2020-04-14 11:05:39 -050022#include "mock_journal.hpp"
Bob King23243f82020-07-29 10:38:57 +080023#include "mock_services.hpp"
Shawn McCarney050531f2020-06-02 14:17:12 -050024#include "mocked_i2c_interface.hpp"
Bob Kinga2c81a62020-07-08 13:31:16 +080025#include "pmbus_read_sensor_action.hpp"
Shawn McCarney525e20c2020-04-14 11:05:39 -050026#include "presence_detection.hpp"
27#include "rail.hpp"
28#include "rule.hpp"
29#include "system.hpp"
Shawn McCarney8a3afd72020-03-12 14:28:44 -050030#include "test_utils.hpp"
31
32#include <memory>
33#include <stdexcept>
Shawn McCarney525e20c2020-04-14 11:05:39 -050034#include <string>
Shawn McCarney8a3afd72020-03-12 14:28:44 -050035#include <utility>
36#include <vector>
37
Bob Kinga2c81a62020-07-08 13:31:16 +080038#include <gmock/gmock.h>
Shawn McCarney8a3afd72020-03-12 14:28:44 -050039#include <gtest/gtest.h>
40
41using namespace phosphor::power::regulators;
42using namespace phosphor::power::regulators::test_utils;
43
Bob Kinga2c81a62020-07-08 13:31:16 +080044using ::testing::A;
Shawn McCarney050531f2020-06-02 14:17:12 -050045using ::testing::Return;
Bob Kinga2c81a62020-07-08 13:31:16 +080046using ::testing::TypedEq;
Shawn McCarney050531f2020-06-02 14:17:12 -050047
Shawn McCarney8a3afd72020-03-12 14:28:44 -050048TEST(ChassisTests, Constructor)
49{
50 // Test where works: Only required parameters are specified
51 {
52 Chassis chassis{2};
53 EXPECT_EQ(chassis.getNumber(), 2);
54 EXPECT_EQ(chassis.getDevices().size(), 0);
55 }
56
57 // Test where works: All parameters are specified
58 {
59 // Create vector of Device objects
60 std::vector<std::unique_ptr<Device>> devices{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -050061 devices.emplace_back(createDevice("vdd_reg1"));
62 devices.emplace_back(createDevice("vdd_reg2"));
Shawn McCarney8a3afd72020-03-12 14:28:44 -050063
64 // Create Chassis
65 Chassis chassis{1, std::move(devices)};
66 EXPECT_EQ(chassis.getNumber(), 1);
67 EXPECT_EQ(chassis.getDevices().size(), 2);
68 }
69
70 // Test where fails: Invalid chassis number < 1
71 try
72 {
73 Chassis chassis{0};
74 ADD_FAILURE() << "Should not have reached this line.";
75 }
76 catch (const std::invalid_argument& e)
77 {
78 EXPECT_STREQ(e.what(), "Invalid chassis number: 0");
79 }
80 catch (...)
81 {
82 ADD_FAILURE() << "Should not have caught exception.";
83 }
84}
85
Shawn McCarneydb0b8332020-04-06 14:13:04 -050086TEST(ChassisTests, AddToIDMap)
87{
88 // Create vector of Device objects
89 std::vector<std::unique_ptr<Device>> devices{};
90 devices.emplace_back(createDevice("reg1", {"rail1"}));
91 devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"}));
92 devices.emplace_back(createDevice("reg3"));
93
94 // Create Chassis
95 Chassis chassis{1, std::move(devices)};
96
97 // Add Device and Rail objects within the Chassis to an IDMap
98 IDMap idMap{};
99 chassis.addToIDMap(idMap);
100
101 // Verify all Devices are in the IDMap
102 EXPECT_NO_THROW(idMap.getDevice("reg1"));
103 EXPECT_NO_THROW(idMap.getDevice("reg2"));
104 EXPECT_NO_THROW(idMap.getDevice("reg3"));
105 EXPECT_THROW(idMap.getDevice("reg4"), std::invalid_argument);
106
107 // Verify all Rails are in the IDMap
108 EXPECT_NO_THROW(idMap.getRail("rail1"));
109 EXPECT_NO_THROW(idMap.getRail("rail2a"));
110 EXPECT_NO_THROW(idMap.getRail("rail2b"));
111 EXPECT_THROW(idMap.getRail("rail3"), std::invalid_argument);
112}
113
Shawn McCarney050531f2020-06-02 14:17:12 -0500114TEST(ChassisTests, CloseDevices)
115{
116 // Test where no devices were specified in constructor
117 {
Bob Kingd692d6d2020-09-14 13:42:57 +0800118 // Create mock services. Expect logDebug() to be called.
119 MockServices services{};
120 MockJournal& journal = services.getMockJournal();
121 EXPECT_CALL(journal, logDebug("Closing devices in chassis 2")).Times(1);
122
Shawn McCarney050531f2020-06-02 14:17:12 -0500123 // Create Chassis
124 Chassis chassis{2};
125
126 // Call closeDevices()
Bob Kingd692d6d2020-09-14 13:42:57 +0800127 chassis.closeDevices(services);
Shawn McCarney050531f2020-06-02 14:17:12 -0500128 }
129
130 // Test where devices were specified in constructor
131 {
132 std::vector<std::unique_ptr<Device>> devices{};
133
Bob Kingd692d6d2020-09-14 13:42:57 +0800134 // Create mock services. Expect logDebug() to be called.
135 MockServices services{};
136 MockJournal& journal = services.getMockJournal();
137 EXPECT_CALL(journal, logDebug("Closing devices in chassis 1")).Times(1);
138
Shawn McCarney050531f2020-06-02 14:17:12 -0500139 // Create Device vdd0_reg
140 {
141 // Create mock I2CInterface: isOpen() and close() should be called
142 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
143 std::make_unique<i2c::MockedI2CInterface>();
144 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
145 EXPECT_CALL(*i2cInterface, close).Times(1);
146
147 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800148 std::unique_ptr<Device> device =
149 std::make_unique<Device>("vdd0_reg", true,
150 "/xyz/openbmc_project/inventory/"
151 "system/chassis/motherboard/vdd0_reg",
152 std::move(i2cInterface));
Shawn McCarney050531f2020-06-02 14:17:12 -0500153 devices.emplace_back(std::move(device));
154 }
155
156 // Create Device vdd1_reg
157 {
158 // Create mock I2CInterface: isOpen() and close() should be called
159 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
160 std::make_unique<i2c::MockedI2CInterface>();
161 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
162 EXPECT_CALL(*i2cInterface, close).Times(1);
163
164 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800165 std::unique_ptr<Device> device =
166 std::make_unique<Device>("vdd1_reg", true,
167 "/xyz/openbmc_project/inventory/"
168 "system/chassis/motherboard/vdd1_reg",
169 std::move(i2cInterface));
Shawn McCarney050531f2020-06-02 14:17:12 -0500170 devices.emplace_back(std::move(device));
171 }
172
173 // Create Chassis
174 Chassis chassis{1, std::move(devices)};
175
176 // Call closeDevices()
Bob Kingd692d6d2020-09-14 13:42:57 +0800177 chassis.closeDevices(services);
Shawn McCarney050531f2020-06-02 14:17:12 -0500178 }
179}
180
Shawn McCarney525e20c2020-04-14 11:05:39 -0500181TEST(ChassisTests, Configure)
182{
183 // Test where no devices were specified in constructor
184 {
Bob King5cfe5102020-07-30 16:26:18 +0800185 // Create mock services. Expect logInfo() to be called.
Bob King23243f82020-07-29 10:38:57 +0800186 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800187 MockJournal& journal = services.getMockJournal();
188 EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1);
189 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
190 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800191
Shawn McCarney525e20c2020-04-14 11:05:39 -0500192 // Create Chassis
193 std::unique_ptr<Chassis> chassis = std::make_unique<Chassis>(1);
194 Chassis* chassisPtr = chassis.get();
195
196 // Create System that contains Chassis
197 std::vector<std::unique_ptr<Rule>> rules{};
198 std::vector<std::unique_ptr<Chassis>> chassisVec{};
199 chassisVec.emplace_back(std::move(chassis));
200 System system{std::move(rules), std::move(chassisVec)};
201
202 // Call configure()
Bob King23243f82020-07-29 10:38:57 +0800203 chassisPtr->configure(services, system);
Shawn McCarney525e20c2020-04-14 11:05:39 -0500204 }
205
206 // Test where devices were specified in constructor
207 {
208 std::vector<std::unique_ptr<Device>> devices{};
209
Bob King5cfe5102020-07-30 16:26:18 +0800210 // Create mock services. Expect logInfo() and logDebug() to be called.
211 MockServices services{};
212 MockJournal& journal = services.getMockJournal();
213 EXPECT_CALL(journal, logInfo("Configuring chassis 2")).Times(1);
214 EXPECT_CALL(journal, logDebug("Configuring vdd0_reg: volts=1.300000"))
215 .Times(1);
216 EXPECT_CALL(journal, logDebug("Configuring vdd1_reg: volts=1.200000"))
217 .Times(1);
218 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
219
Shawn McCarney525e20c2020-04-14 11:05:39 -0500220 // Create Device vdd0_reg
221 {
222 // Create Configuration
223 std::vector<std::unique_ptr<Action>> actions{};
224 std::unique_ptr<Configuration> configuration =
225 std::make_unique<Configuration>(1.3, std::move(actions));
226
227 // Create Device
228 std::unique_ptr<i2c::I2CInterface> i2cInterface =
229 createI2CInterface();
230 std::unique_ptr<PresenceDetection> presenceDetection{};
231 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800232 "vdd0_reg", true,
233 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
234 "vdd0_reg",
Shawn McCarney525e20c2020-04-14 11:05:39 -0500235 std::move(i2cInterface), std::move(presenceDetection),
236 std::move(configuration));
237 devices.emplace_back(std::move(device));
238 }
239
240 // Create Device vdd1_reg
241 {
242 // Create Configuration
243 std::vector<std::unique_ptr<Action>> actions{};
244 std::unique_ptr<Configuration> configuration =
245 std::make_unique<Configuration>(1.2, std::move(actions));
246
247 // Create Device
248 std::unique_ptr<i2c::I2CInterface> i2cInterface =
249 createI2CInterface();
250 std::unique_ptr<PresenceDetection> presenceDetection{};
251 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800252 "vdd1_reg", true,
253 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
254 "vdd1_reg",
Shawn McCarney525e20c2020-04-14 11:05:39 -0500255 std::move(i2cInterface), std::move(presenceDetection),
256 std::move(configuration));
257 devices.emplace_back(std::move(device));
258 }
259
260 // Create Chassis
261 std::unique_ptr<Chassis> chassis =
262 std::make_unique<Chassis>(2, std::move(devices));
263 Chassis* chassisPtr = chassis.get();
264
265 // Create System that contains Chassis
266 std::vector<std::unique_ptr<Rule>> rules{};
267 std::vector<std::unique_ptr<Chassis>> chassisVec{};
268 chassisVec.emplace_back(std::move(chassis));
269 System system{std::move(rules), std::move(chassisVec)};
270
271 // Call configure()
Bob King23243f82020-07-29 10:38:57 +0800272 chassisPtr->configure(services, system);
Shawn McCarney525e20c2020-04-14 11:05:39 -0500273 }
274}
275
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500276TEST(ChassisTests, GetDevices)
277{
278 // Test where no devices were specified in constructor
279 {
280 Chassis chassis{2};
281 EXPECT_EQ(chassis.getDevices().size(), 0);
282 }
283
284 // Test where devices were specified in constructor
285 {
286 // Create vector of Device objects
287 std::vector<std::unique_ptr<Device>> devices{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500288 devices.emplace_back(createDevice("vdd_reg1"));
289 devices.emplace_back(createDevice("vdd_reg2"));
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500290
291 // Create Chassis
292 Chassis chassis{1, std::move(devices)};
293 EXPECT_EQ(chassis.getDevices().size(), 2);
294 EXPECT_EQ(chassis.getDevices()[0]->getID(), "vdd_reg1");
295 EXPECT_EQ(chassis.getDevices()[1]->getID(), "vdd_reg2");
296 }
297}
298
299TEST(ChassisTests, GetNumber)
300{
301 Chassis chassis{3};
302 EXPECT_EQ(chassis.getNumber(), 3);
303}
Bob Kinga2c81a62020-07-08 13:31:16 +0800304
305TEST(ChassisTests, MonitorSensors)
306{
307 // Test where no devices were specified in constructor
308 {
Bob King8a552922020-08-05 17:02:31 +0800309 // Create mock services. No logging should occur.
310 MockServices services{};
311 MockJournal& journal = services.getMockJournal();
312 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
313 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
314
Bob Kinga2c81a62020-07-08 13:31:16 +0800315 // Create Chassis
316 std::vector<std::unique_ptr<Device>> devices{};
317 std::unique_ptr<Chassis> chassis =
318 std::make_unique<Chassis>(1, std::move(devices));
319 Chassis* chassisPtr = chassis.get();
320
321 // Create System that contains Chassis
322 std::vector<std::unique_ptr<Rule>> rules{};
323 std::vector<std::unique_ptr<Chassis>> chassisVec{};
324 chassisVec.emplace_back(std::move(chassis));
325 System system{std::move(rules), std::move(chassisVec)};
326
327 // Call monitorSensors(). Should do nothing.
Bob King8a552922020-08-05 17:02:31 +0800328 chassisPtr->monitorSensors(services, system);
Bob Kinga2c81a62020-07-08 13:31:16 +0800329 }
330
331 // Test where devices were specified in constructor
332 {
Bob King8a552922020-08-05 17:02:31 +0800333 // Create mock services. No logging should occur.
334 MockServices services{};
335 MockJournal& journal = services.getMockJournal();
336 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
337 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
338
Bob Kinga2c81a62020-07-08 13:31:16 +0800339 std::vector<std::unique_ptr<Device>> devices{};
340
341 // Create PMBusReadSensorAction
342 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};
343 uint8_t command = 0x8C;
344 pmbus_utils::SensorDataFormat format{
345 pmbus_utils::SensorDataFormat::linear_11};
346 std::optional<int8_t> exponent{};
347 std::unique_ptr<PMBusReadSensorAction> action =
348 std::make_unique<PMBusReadSensorAction>(type, command, format,
349 exponent);
350
351 // Create mock I2CInterface. A two-byte read should occur.
352 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
353 std::make_unique<i2c::MockedI2CInterface>();
354 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
355 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
356 .Times(1);
357
358 // Create SensorMonitoring
359 std::vector<std::unique_ptr<Action>> actions{};
360 actions.emplace_back(std::move(action));
361 std::unique_ptr<SensorMonitoring> sensorMonitoring =
362 std::make_unique<SensorMonitoring>(std::move(actions));
363
364 // Create Rail
365 std::vector<std::unique_ptr<Rail>> rails{};
366 std::unique_ptr<Configuration> configuration{};
367 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
368 "vdd0", std::move(configuration), std::move(sensorMonitoring));
369 rails.emplace_back(std::move(rail));
370
371 // Create Device
372 std::unique_ptr<PresenceDetection> presenceDetection{};
373 std::unique_ptr<Configuration> deviceConfiguration{};
374 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800375 "reg1", true,
376 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob Kinga2c81a62020-07-08 13:31:16 +0800377 std::move(i2cInterface), std::move(presenceDetection),
378 std::move(deviceConfiguration), std::move(rails));
379
380 // Create Chassis
381 devices.emplace_back(std::move(device));
382 std::unique_ptr<Chassis> chassis =
383 std::make_unique<Chassis>(1, std::move(devices));
384 Chassis* chassisPtr = chassis.get();
385
386 // Create System that contains Chassis
387 std::vector<std::unique_ptr<Rule>> rules{};
388 std::vector<std::unique_ptr<Chassis>> chassisVec{};
389 chassisVec.emplace_back(std::move(chassis));
390 System system{std::move(rules), std::move(chassisVec)};
391
392 // Call monitorSensors()
Bob King8a552922020-08-05 17:02:31 +0800393 chassisPtr->monitorSensors(services, system);
Bob Kinga2c81a62020-07-08 13:31:16 +0800394 }
395}