blob: 481d71db9985db023125fb842d7ba036280b01ec [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 King23243f82020-07-29 10:38:57 +0800184 // Create mock services.
185 MockServices services{};
186
Shawn McCarney525e20c2020-04-14 11:05:39 -0500187 // Create Chassis
188 std::unique_ptr<Chassis> chassis = std::make_unique<Chassis>(1);
189 Chassis* chassisPtr = chassis.get();
190
191 // Create System that contains Chassis
192 std::vector<std::unique_ptr<Rule>> rules{};
193 std::vector<std::unique_ptr<Chassis>> chassisVec{};
194 chassisVec.emplace_back(std::move(chassis));
195 System system{std::move(rules), std::move(chassisVec)};
196
197 // Call configure()
198 journal::clear();
Bob King23243f82020-07-29 10:38:57 +0800199 chassisPtr->configure(services, system);
Shawn McCarney525e20c2020-04-14 11:05:39 -0500200 EXPECT_EQ(journal::getDebugMessages().size(), 0);
201 EXPECT_EQ(journal::getErrMessages().size(), 0);
202 std::vector<std::string> expectedInfoMessages{"Configuring chassis 1"};
203 EXPECT_EQ(journal::getInfoMessages(), expectedInfoMessages);
204 }
205
206 // Test where devices were specified in constructor
207 {
Bob King23243f82020-07-29 10:38:57 +0800208 // Create mock services.
209 MockServices services{};
210
Shawn McCarney525e20c2020-04-14 11:05:39 -0500211 std::vector<std::unique_ptr<Device>> devices{};
212
213 // Create Device vdd0_reg
214 {
215 // Create Configuration
216 std::vector<std::unique_ptr<Action>> actions{};
217 std::unique_ptr<Configuration> configuration =
218 std::make_unique<Configuration>(1.3, std::move(actions));
219
220 // Create Device
221 std::unique_ptr<i2c::I2CInterface> i2cInterface =
222 createI2CInterface();
223 std::unique_ptr<PresenceDetection> presenceDetection{};
224 std::unique_ptr<Device> device = std::make_unique<Device>(
225 "vdd0_reg", true, "/system/chassis/motherboard/vdd0_reg",
226 std::move(i2cInterface), std::move(presenceDetection),
227 std::move(configuration));
228 devices.emplace_back(std::move(device));
229 }
230
231 // Create Device vdd1_reg
232 {
233 // Create Configuration
234 std::vector<std::unique_ptr<Action>> actions{};
235 std::unique_ptr<Configuration> configuration =
236 std::make_unique<Configuration>(1.2, std::move(actions));
237
238 // Create Device
239 std::unique_ptr<i2c::I2CInterface> i2cInterface =
240 createI2CInterface();
241 std::unique_ptr<PresenceDetection> presenceDetection{};
242 std::unique_ptr<Device> device = std::make_unique<Device>(
243 "vdd1_reg", true, "/system/chassis/motherboard/vdd1_reg",
244 std::move(i2cInterface), std::move(presenceDetection),
245 std::move(configuration));
246 devices.emplace_back(std::move(device));
247 }
248
249 // Create Chassis
250 std::unique_ptr<Chassis> chassis =
251 std::make_unique<Chassis>(2, std::move(devices));
252 Chassis* chassisPtr = chassis.get();
253
254 // Create System that contains Chassis
255 std::vector<std::unique_ptr<Rule>> rules{};
256 std::vector<std::unique_ptr<Chassis>> chassisVec{};
257 chassisVec.emplace_back(std::move(chassis));
258 System system{std::move(rules), std::move(chassisVec)};
259
260 // Call configure()
261 journal::clear();
Bob King23243f82020-07-29 10:38:57 +0800262 chassisPtr->configure(services, system);
Shawn McCarney525e20c2020-04-14 11:05:39 -0500263 std::vector<std::string> expectedDebugMessages{
264 "Configuring vdd0_reg: volts=1.300000",
265 "Configuring vdd1_reg: volts=1.200000"};
266 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
267 EXPECT_EQ(journal::getErrMessages().size(), 0);
268 std::vector<std::string> expectedInfoMessages{"Configuring chassis 2"};
269 EXPECT_EQ(journal::getInfoMessages(), expectedInfoMessages);
270 }
271}
272
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500273TEST(ChassisTests, GetDevices)
274{
275 // Test where no devices were specified in constructor
276 {
277 Chassis chassis{2};
278 EXPECT_EQ(chassis.getDevices().size(), 0);
279 }
280
281 // Test where devices were specified in constructor
282 {
283 // Create vector of Device objects
284 std::vector<std::unique_ptr<Device>> devices{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500285 devices.emplace_back(createDevice("vdd_reg1"));
286 devices.emplace_back(createDevice("vdd_reg2"));
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500287
288 // Create Chassis
289 Chassis chassis{1, std::move(devices)};
290 EXPECT_EQ(chassis.getDevices().size(), 2);
291 EXPECT_EQ(chassis.getDevices()[0]->getID(), "vdd_reg1");
292 EXPECT_EQ(chassis.getDevices()[1]->getID(), "vdd_reg2");
293 }
294}
295
296TEST(ChassisTests, GetNumber)
297{
298 Chassis chassis{3};
299 EXPECT_EQ(chassis.getNumber(), 3);
300}
Bob Kinga2c81a62020-07-08 13:31:16 +0800301
302TEST(ChassisTests, MonitorSensors)
303{
304 // Test where no devices were specified in constructor
305 {
306 // Create Chassis
307 std::vector<std::unique_ptr<Device>> devices{};
308 std::unique_ptr<Chassis> chassis =
309 std::make_unique<Chassis>(1, std::move(devices));
310 Chassis* chassisPtr = chassis.get();
311
312 // Create System that contains Chassis
313 std::vector<std::unique_ptr<Rule>> rules{};
314 std::vector<std::unique_ptr<Chassis>> chassisVec{};
315 chassisVec.emplace_back(std::move(chassis));
316 System system{std::move(rules), std::move(chassisVec)};
317
318 // Call monitorSensors(). Should do nothing.
319 journal::clear();
320 chassisPtr->monitorSensors(system);
321 EXPECT_EQ(journal::getDebugMessages().size(), 0);
322 EXPECT_EQ(journal::getErrMessages().size(), 0);
323 }
324
325 // Test where devices were specified in constructor
326 {
327 std::vector<std::unique_ptr<Device>> devices{};
328
329 // Create PMBusReadSensorAction
330 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};
331 uint8_t command = 0x8C;
332 pmbus_utils::SensorDataFormat format{
333 pmbus_utils::SensorDataFormat::linear_11};
334 std::optional<int8_t> exponent{};
335 std::unique_ptr<PMBusReadSensorAction> action =
336 std::make_unique<PMBusReadSensorAction>(type, command, format,
337 exponent);
338
339 // Create mock I2CInterface. A two-byte read should occur.
340 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
341 std::make_unique<i2c::MockedI2CInterface>();
342 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
343 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
344 .Times(1);
345
346 // Create SensorMonitoring
347 std::vector<std::unique_ptr<Action>> actions{};
348 actions.emplace_back(std::move(action));
349 std::unique_ptr<SensorMonitoring> sensorMonitoring =
350 std::make_unique<SensorMonitoring>(std::move(actions));
351
352 // Create Rail
353 std::vector<std::unique_ptr<Rail>> rails{};
354 std::unique_ptr<Configuration> configuration{};
355 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
356 "vdd0", std::move(configuration), std::move(sensorMonitoring));
357 rails.emplace_back(std::move(rail));
358
359 // Create Device
360 std::unique_ptr<PresenceDetection> presenceDetection{};
361 std::unique_ptr<Configuration> deviceConfiguration{};
362 std::unique_ptr<Device> device = std::make_unique<Device>(
363 "reg1", true, "/system/chassis/motherboard/reg1",
364 std::move(i2cInterface), std::move(presenceDetection),
365 std::move(deviceConfiguration), std::move(rails));
366
367 // Create Chassis
368 devices.emplace_back(std::move(device));
369 std::unique_ptr<Chassis> chassis =
370 std::make_unique<Chassis>(1, std::move(devices));
371 Chassis* chassisPtr = chassis.get();
372
373 // Create System that contains Chassis
374 std::vector<std::unique_ptr<Rule>> rules{};
375 std::vector<std::unique_ptr<Chassis>> chassisVec{};
376 chassisVec.emplace_back(std::move(chassis));
377 System system{std::move(rules), std::move(chassisVec)};
378
379 // Call monitorSensors()
380 journal::clear();
381 chassisPtr->monitorSensors(system);
382 EXPECT_EQ(journal::getDebugMessages().size(), 0);
383 EXPECT_EQ(journal::getErrMessages().size(), 0);
384 }
385}