blob: 639dc330e8ea97bba5fec382665f347189a5e0a7 [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 "journal.hpp"
23#include "mock_journal.hpp"
Bob King23243f82020-07-29 10:38:57 +080024#include "mock_services.hpp"
Shawn McCarney050531f2020-06-02 14:17:12 -050025#include "mocked_i2c_interface.hpp"
Bob Kinga2c81a62020-07-08 13:31:16 +080026#include "pmbus_read_sensor_action.hpp"
Shawn McCarney525e20c2020-04-14 11:05:39 -050027#include "presence_detection.hpp"
28#include "rail.hpp"
29#include "rule.hpp"
30#include "system.hpp"
Shawn McCarney8a3afd72020-03-12 14:28:44 -050031#include "test_utils.hpp"
32
33#include <memory>
34#include <stdexcept>
Shawn McCarney525e20c2020-04-14 11:05:39 -050035#include <string>
Shawn McCarney8a3afd72020-03-12 14:28:44 -050036#include <utility>
37#include <vector>
38
Bob Kinga2c81a62020-07-08 13:31:16 +080039#include <gmock/gmock.h>
Shawn McCarney8a3afd72020-03-12 14:28:44 -050040#include <gtest/gtest.h>
41
42using namespace phosphor::power::regulators;
43using namespace phosphor::power::regulators::test_utils;
44
Bob Kinga2c81a62020-07-08 13:31:16 +080045using ::testing::A;
Shawn McCarney050531f2020-06-02 14:17:12 -050046using ::testing::Return;
Bob Kinga2c81a62020-07-08 13:31:16 +080047using ::testing::TypedEq;
Shawn McCarney050531f2020-06-02 14:17:12 -050048
Shawn McCarney8a3afd72020-03-12 14:28:44 -050049TEST(ChassisTests, Constructor)
50{
51 // Test where works: Only required parameters are specified
52 {
53 Chassis chassis{2};
54 EXPECT_EQ(chassis.getNumber(), 2);
55 EXPECT_EQ(chassis.getDevices().size(), 0);
56 }
57
58 // Test where works: All parameters are specified
59 {
60 // Create vector of Device objects
61 std::vector<std::unique_ptr<Device>> devices{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -050062 devices.emplace_back(createDevice("vdd_reg1"));
63 devices.emplace_back(createDevice("vdd_reg2"));
Shawn McCarney8a3afd72020-03-12 14:28:44 -050064
65 // Create Chassis
66 Chassis chassis{1, std::move(devices)};
67 EXPECT_EQ(chassis.getNumber(), 1);
68 EXPECT_EQ(chassis.getDevices().size(), 2);
69 }
70
71 // Test where fails: Invalid chassis number < 1
72 try
73 {
74 Chassis chassis{0};
75 ADD_FAILURE() << "Should not have reached this line.";
76 }
77 catch (const std::invalid_argument& e)
78 {
79 EXPECT_STREQ(e.what(), "Invalid chassis number: 0");
80 }
81 catch (...)
82 {
83 ADD_FAILURE() << "Should not have caught exception.";
84 }
85}
86
Shawn McCarneydb0b8332020-04-06 14:13:04 -050087TEST(ChassisTests, AddToIDMap)
88{
89 // Create vector of Device objects
90 std::vector<std::unique_ptr<Device>> devices{};
91 devices.emplace_back(createDevice("reg1", {"rail1"}));
92 devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"}));
93 devices.emplace_back(createDevice("reg3"));
94
95 // Create Chassis
96 Chassis chassis{1, std::move(devices)};
97
98 // Add Device and Rail objects within the Chassis to an IDMap
99 IDMap idMap{};
100 chassis.addToIDMap(idMap);
101
102 // Verify all Devices are in the IDMap
103 EXPECT_NO_THROW(idMap.getDevice("reg1"));
104 EXPECT_NO_THROW(idMap.getDevice("reg2"));
105 EXPECT_NO_THROW(idMap.getDevice("reg3"));
106 EXPECT_THROW(idMap.getDevice("reg4"), std::invalid_argument);
107
108 // Verify all Rails are in the IDMap
109 EXPECT_NO_THROW(idMap.getRail("rail1"));
110 EXPECT_NO_THROW(idMap.getRail("rail2a"));
111 EXPECT_NO_THROW(idMap.getRail("rail2b"));
112 EXPECT_THROW(idMap.getRail("rail3"), std::invalid_argument);
113}
114
Shawn McCarney050531f2020-06-02 14:17:12 -0500115TEST(ChassisTests, CloseDevices)
116{
117 // Test where no devices were specified in constructor
118 {
119 // Create Chassis
120 Chassis chassis{2};
121
122 // Call closeDevices()
123 journal::clear();
124 chassis.closeDevices();
125 EXPECT_EQ(journal::getErrMessages().size(), 0);
126 EXPECT_EQ(journal::getInfoMessages().size(), 0);
127 std::vector<std::string> expectedDebugMessages{
128 "Closing devices in chassis 2"};
129 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
130 }
131
132 // Test where devices were specified in constructor
133 {
134 std::vector<std::unique_ptr<Device>> devices{};
135
136 // Create Device vdd0_reg
137 {
138 // Create mock I2CInterface: isOpen() and close() should be called
139 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
140 std::make_unique<i2c::MockedI2CInterface>();
141 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
142 EXPECT_CALL(*i2cInterface, close).Times(1);
143
144 // Create Device
145 std::unique_ptr<Device> device = std::make_unique<Device>(
146 "vdd0_reg", true, "/system/chassis/motherboard/vdd0_reg",
147 std::move(i2cInterface));
148 devices.emplace_back(std::move(device));
149 }
150
151 // Create Device vdd1_reg
152 {
153 // Create mock I2CInterface: isOpen() and close() should be called
154 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
155 std::make_unique<i2c::MockedI2CInterface>();
156 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
157 EXPECT_CALL(*i2cInterface, close).Times(1);
158
159 // Create Device
160 std::unique_ptr<Device> device = std::make_unique<Device>(
161 "vdd1_reg", true, "/system/chassis/motherboard/vdd1_reg",
162 std::move(i2cInterface));
163 devices.emplace_back(std::move(device));
164 }
165
166 // Create Chassis
167 Chassis chassis{1, std::move(devices)};
168
169 // Call closeDevices()
170 journal::clear();
171 chassis.closeDevices();
172 EXPECT_EQ(journal::getErrMessages().size(), 0);
173 EXPECT_EQ(journal::getInfoMessages().size(), 0);
174 std::vector<std::string> expectedDebugMessages{
175 "Closing devices in chassis 1"};
176 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
177 }
178}
179
Shawn McCarney525e20c2020-04-14 11:05:39 -0500180TEST(ChassisTests, Configure)
181{
182 // Test where no devices were specified in constructor
183 {
Bob King5cfe5102020-07-30 16:26:18 +0800184 // Create mock services. Expect logInfo() to be called.
Bob King23243f82020-07-29 10:38:57 +0800185 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800186 MockJournal& journal = services.getMockJournal();
187 EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1);
188 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
189 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800190
Shawn McCarney525e20c2020-04-14 11:05:39 -0500191 // Create Chassis
192 std::unique_ptr<Chassis> chassis = std::make_unique<Chassis>(1);
193 Chassis* chassisPtr = chassis.get();
194
195 // Create System that contains Chassis
196 std::vector<std::unique_ptr<Rule>> rules{};
197 std::vector<std::unique_ptr<Chassis>> chassisVec{};
198 chassisVec.emplace_back(std::move(chassis));
199 System system{std::move(rules), std::move(chassisVec)};
200
201 // Call configure()
Bob King23243f82020-07-29 10:38:57 +0800202 chassisPtr->configure(services, system);
Shawn McCarney525e20c2020-04-14 11:05:39 -0500203 }
204
205 // Test where devices were specified in constructor
206 {
207 std::vector<std::unique_ptr<Device>> devices{};
208
Bob King5cfe5102020-07-30 16:26:18 +0800209 // Create mock services. Expect logInfo() and logDebug() to be called.
210 MockServices services{};
211 MockJournal& journal = services.getMockJournal();
212 EXPECT_CALL(journal, logInfo("Configuring chassis 2")).Times(1);
213 EXPECT_CALL(journal, logDebug("Configuring vdd0_reg: volts=1.300000"))
214 .Times(1);
215 EXPECT_CALL(journal, logDebug("Configuring vdd1_reg: volts=1.200000"))
216 .Times(1);
217 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
218
Shawn McCarney525e20c2020-04-14 11:05:39 -0500219 // Create Device vdd0_reg
220 {
221 // Create Configuration
222 std::vector<std::unique_ptr<Action>> actions{};
223 std::unique_ptr<Configuration> configuration =
224 std::make_unique<Configuration>(1.3, std::move(actions));
225
226 // Create Device
227 std::unique_ptr<i2c::I2CInterface> i2cInterface =
228 createI2CInterface();
229 std::unique_ptr<PresenceDetection> presenceDetection{};
230 std::unique_ptr<Device> device = std::make_unique<Device>(
231 "vdd0_reg", true, "/system/chassis/motherboard/vdd0_reg",
232 std::move(i2cInterface), std::move(presenceDetection),
233 std::move(configuration));
234 devices.emplace_back(std::move(device));
235 }
236
237 // Create Device vdd1_reg
238 {
239 // Create Configuration
240 std::vector<std::unique_ptr<Action>> actions{};
241 std::unique_ptr<Configuration> configuration =
242 std::make_unique<Configuration>(1.2, std::move(actions));
243
244 // Create Device
245 std::unique_ptr<i2c::I2CInterface> i2cInterface =
246 createI2CInterface();
247 std::unique_ptr<PresenceDetection> presenceDetection{};
248 std::unique_ptr<Device> device = std::make_unique<Device>(
249 "vdd1_reg", true, "/system/chassis/motherboard/vdd1_reg",
250 std::move(i2cInterface), std::move(presenceDetection),
251 std::move(configuration));
252 devices.emplace_back(std::move(device));
253 }
254
255 // Create Chassis
256 std::unique_ptr<Chassis> chassis =
257 std::make_unique<Chassis>(2, std::move(devices));
258 Chassis* chassisPtr = chassis.get();
259
260 // Create System that contains Chassis
261 std::vector<std::unique_ptr<Rule>> rules{};
262 std::vector<std::unique_ptr<Chassis>> chassisVec{};
263 chassisVec.emplace_back(std::move(chassis));
264 System system{std::move(rules), std::move(chassisVec)};
265
266 // Call configure()
Bob King23243f82020-07-29 10:38:57 +0800267 chassisPtr->configure(services, system);
Shawn McCarney525e20c2020-04-14 11:05:39 -0500268 }
269}
270
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500271TEST(ChassisTests, GetDevices)
272{
273 // Test where no devices were specified in constructor
274 {
275 Chassis chassis{2};
276 EXPECT_EQ(chassis.getDevices().size(), 0);
277 }
278
279 // Test where devices were specified in constructor
280 {
281 // Create vector of Device objects
282 std::vector<std::unique_ptr<Device>> devices{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500283 devices.emplace_back(createDevice("vdd_reg1"));
284 devices.emplace_back(createDevice("vdd_reg2"));
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500285
286 // Create Chassis
287 Chassis chassis{1, std::move(devices)};
288 EXPECT_EQ(chassis.getDevices().size(), 2);
289 EXPECT_EQ(chassis.getDevices()[0]->getID(), "vdd_reg1");
290 EXPECT_EQ(chassis.getDevices()[1]->getID(), "vdd_reg2");
291 }
292}
293
294TEST(ChassisTests, GetNumber)
295{
296 Chassis chassis{3};
297 EXPECT_EQ(chassis.getNumber(), 3);
298}
Bob Kinga2c81a62020-07-08 13:31:16 +0800299
300TEST(ChassisTests, MonitorSensors)
301{
302 // Test where no devices were specified in constructor
303 {
304 // Create Chassis
305 std::vector<std::unique_ptr<Device>> devices{};
306 std::unique_ptr<Chassis> chassis =
307 std::make_unique<Chassis>(1, std::move(devices));
308 Chassis* chassisPtr = chassis.get();
309
310 // Create System that contains Chassis
311 std::vector<std::unique_ptr<Rule>> rules{};
312 std::vector<std::unique_ptr<Chassis>> chassisVec{};
313 chassisVec.emplace_back(std::move(chassis));
314 System system{std::move(rules), std::move(chassisVec)};
315
316 // Call monitorSensors(). Should do nothing.
317 journal::clear();
318 chassisPtr->monitorSensors(system);
319 EXPECT_EQ(journal::getDebugMessages().size(), 0);
320 EXPECT_EQ(journal::getErrMessages().size(), 0);
321 }
322
323 // Test where devices were specified in constructor
324 {
325 std::vector<std::unique_ptr<Device>> devices{};
326
327 // Create PMBusReadSensorAction
328 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};
329 uint8_t command = 0x8C;
330 pmbus_utils::SensorDataFormat format{
331 pmbus_utils::SensorDataFormat::linear_11};
332 std::optional<int8_t> exponent{};
333 std::unique_ptr<PMBusReadSensorAction> action =
334 std::make_unique<PMBusReadSensorAction>(type, command, format,
335 exponent);
336
337 // Create mock I2CInterface. A two-byte read should occur.
338 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
339 std::make_unique<i2c::MockedI2CInterface>();
340 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
341 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
342 .Times(1);
343
344 // Create SensorMonitoring
345 std::vector<std::unique_ptr<Action>> actions{};
346 actions.emplace_back(std::move(action));
347 std::unique_ptr<SensorMonitoring> sensorMonitoring =
348 std::make_unique<SensorMonitoring>(std::move(actions));
349
350 // Create Rail
351 std::vector<std::unique_ptr<Rail>> rails{};
352 std::unique_ptr<Configuration> configuration{};
353 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
354 "vdd0", std::move(configuration), std::move(sensorMonitoring));
355 rails.emplace_back(std::move(rail));
356
357 // Create Device
358 std::unique_ptr<PresenceDetection> presenceDetection{};
359 std::unique_ptr<Configuration> deviceConfiguration{};
360 std::unique_ptr<Device> device = std::make_unique<Device>(
361 "reg1", true, "/system/chassis/motherboard/reg1",
362 std::move(i2cInterface), std::move(presenceDetection),
363 std::move(deviceConfiguration), std::move(rails));
364
365 // Create Chassis
366 devices.emplace_back(std::move(device));
367 std::unique_ptr<Chassis> chassis =
368 std::make_unique<Chassis>(1, std::move(devices));
369 Chassis* chassisPtr = chassis.get();
370
371 // Create System that contains Chassis
372 std::vector<std::unique_ptr<Rule>> rules{};
373 std::vector<std::unique_ptr<Chassis>> chassisVec{};
374 chassisVec.emplace_back(std::move(chassis));
375 System system{std::move(rules), std::move(chassisVec)};
376
377 // Call monitorSensors()
378 journal::clear();
379 chassisPtr->monitorSensors(system);
380 EXPECT_EQ(journal::getDebugMessages().size(), 0);
381 EXPECT_EQ(journal::getErrMessages().size(), 0);
382 }
383}