blob: eca6d97a2e04a64eb2157675f0ce4fcfa80ae979 [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"
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 {
118 // Create Chassis
119 Chassis chassis{2};
120
121 // Call closeDevices()
122 journal::clear();
123 chassis.closeDevices();
124 EXPECT_EQ(journal::getErrMessages().size(), 0);
125 EXPECT_EQ(journal::getInfoMessages().size(), 0);
126 std::vector<std::string> expectedDebugMessages{
127 "Closing devices in chassis 2"};
128 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
129 }
130
131 // Test where devices were specified in constructor
132 {
133 std::vector<std::unique_ptr<Device>> devices{};
134
135 // Create Device vdd0_reg
136 {
137 // Create mock I2CInterface: isOpen() and close() should be called
138 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
139 std::make_unique<i2c::MockedI2CInterface>();
140 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
141 EXPECT_CALL(*i2cInterface, close).Times(1);
142
143 // Create Device
144 std::unique_ptr<Device> device = std::make_unique<Device>(
145 "vdd0_reg", true, "/system/chassis/motherboard/vdd0_reg",
146 std::move(i2cInterface));
147 devices.emplace_back(std::move(device));
148 }
149
150 // Create Device vdd1_reg
151 {
152 // Create mock I2CInterface: isOpen() and close() should be called
153 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
154 std::make_unique<i2c::MockedI2CInterface>();
155 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
156 EXPECT_CALL(*i2cInterface, close).Times(1);
157
158 // Create Device
159 std::unique_ptr<Device> device = std::make_unique<Device>(
160 "vdd1_reg", true, "/system/chassis/motherboard/vdd1_reg",
161 std::move(i2cInterface));
162 devices.emplace_back(std::move(device));
163 }
164
165 // Create Chassis
166 Chassis chassis{1, std::move(devices)};
167
168 // Call closeDevices()
169 journal::clear();
170 chassis.closeDevices();
171 EXPECT_EQ(journal::getErrMessages().size(), 0);
172 EXPECT_EQ(journal::getInfoMessages().size(), 0);
173 std::vector<std::string> expectedDebugMessages{
174 "Closing devices in chassis 1"};
175 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
176 }
177}
178
Shawn McCarney525e20c2020-04-14 11:05:39 -0500179TEST(ChassisTests, Configure)
180{
181 // Test where no devices were specified in constructor
182 {
183 // Create Chassis
184 std::unique_ptr<Chassis> chassis = std::make_unique<Chassis>(1);
185 Chassis* chassisPtr = chassis.get();
186
187 // Create System that contains Chassis
188 std::vector<std::unique_ptr<Rule>> rules{};
189 std::vector<std::unique_ptr<Chassis>> chassisVec{};
190 chassisVec.emplace_back(std::move(chassis));
191 System system{std::move(rules), std::move(chassisVec)};
192
193 // Call configure()
194 journal::clear();
195 chassisPtr->configure(system);
196 EXPECT_EQ(journal::getDebugMessages().size(), 0);
197 EXPECT_EQ(journal::getErrMessages().size(), 0);
198 std::vector<std::string> expectedInfoMessages{"Configuring chassis 1"};
199 EXPECT_EQ(journal::getInfoMessages(), expectedInfoMessages);
200 }
201
202 // Test where devices were specified in constructor
203 {
204 std::vector<std::unique_ptr<Device>> devices{};
205
206 // Create Device vdd0_reg
207 {
208 // Create Configuration
209 std::vector<std::unique_ptr<Action>> actions{};
210 std::unique_ptr<Configuration> configuration =
211 std::make_unique<Configuration>(1.3, std::move(actions));
212
213 // Create Device
214 std::unique_ptr<i2c::I2CInterface> i2cInterface =
215 createI2CInterface();
216 std::unique_ptr<PresenceDetection> presenceDetection{};
217 std::unique_ptr<Device> device = std::make_unique<Device>(
218 "vdd0_reg", true, "/system/chassis/motherboard/vdd0_reg",
219 std::move(i2cInterface), std::move(presenceDetection),
220 std::move(configuration));
221 devices.emplace_back(std::move(device));
222 }
223
224 // Create Device vdd1_reg
225 {
226 // Create Configuration
227 std::vector<std::unique_ptr<Action>> actions{};
228 std::unique_ptr<Configuration> configuration =
229 std::make_unique<Configuration>(1.2, std::move(actions));
230
231 // Create Device
232 std::unique_ptr<i2c::I2CInterface> i2cInterface =
233 createI2CInterface();
234 std::unique_ptr<PresenceDetection> presenceDetection{};
235 std::unique_ptr<Device> device = std::make_unique<Device>(
236 "vdd1_reg", true, "/system/chassis/motherboard/vdd1_reg",
237 std::move(i2cInterface), std::move(presenceDetection),
238 std::move(configuration));
239 devices.emplace_back(std::move(device));
240 }
241
242 // Create Chassis
243 std::unique_ptr<Chassis> chassis =
244 std::make_unique<Chassis>(2, std::move(devices));
245 Chassis* chassisPtr = chassis.get();
246
247 // Create System that contains Chassis
248 std::vector<std::unique_ptr<Rule>> rules{};
249 std::vector<std::unique_ptr<Chassis>> chassisVec{};
250 chassisVec.emplace_back(std::move(chassis));
251 System system{std::move(rules), std::move(chassisVec)};
252
253 // Call configure()
254 journal::clear();
255 chassisPtr->configure(system);
256 std::vector<std::string> expectedDebugMessages{
257 "Configuring vdd0_reg: volts=1.300000",
258 "Configuring vdd1_reg: volts=1.200000"};
259 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
260 EXPECT_EQ(journal::getErrMessages().size(), 0);
261 std::vector<std::string> expectedInfoMessages{"Configuring chassis 2"};
262 EXPECT_EQ(journal::getInfoMessages(), expectedInfoMessages);
263 }
264}
265
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500266TEST(ChassisTests, GetDevices)
267{
268 // Test where no devices were specified in constructor
269 {
270 Chassis chassis{2};
271 EXPECT_EQ(chassis.getDevices().size(), 0);
272 }
273
274 // Test where devices were specified in constructor
275 {
276 // Create vector of Device objects
277 std::vector<std::unique_ptr<Device>> devices{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500278 devices.emplace_back(createDevice("vdd_reg1"));
279 devices.emplace_back(createDevice("vdd_reg2"));
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500280
281 // Create Chassis
282 Chassis chassis{1, std::move(devices)};
283 EXPECT_EQ(chassis.getDevices().size(), 2);
284 EXPECT_EQ(chassis.getDevices()[0]->getID(), "vdd_reg1");
285 EXPECT_EQ(chassis.getDevices()[1]->getID(), "vdd_reg2");
286 }
287}
288
289TEST(ChassisTests, GetNumber)
290{
291 Chassis chassis{3};
292 EXPECT_EQ(chassis.getNumber(), 3);
293}
Bob Kinga2c81a62020-07-08 13:31:16 +0800294
295TEST(ChassisTests, MonitorSensors)
296{
297 // Test where no devices were specified in constructor
298 {
299 // Create Chassis
300 std::vector<std::unique_ptr<Device>> devices{};
301 std::unique_ptr<Chassis> chassis =
302 std::make_unique<Chassis>(1, std::move(devices));
303 Chassis* chassisPtr = chassis.get();
304
305 // Create System that contains Chassis
306 std::vector<std::unique_ptr<Rule>> rules{};
307 std::vector<std::unique_ptr<Chassis>> chassisVec{};
308 chassisVec.emplace_back(std::move(chassis));
309 System system{std::move(rules), std::move(chassisVec)};
310
311 // Call monitorSensors(). Should do nothing.
312 journal::clear();
313 chassisPtr->monitorSensors(system);
314 EXPECT_EQ(journal::getDebugMessages().size(), 0);
315 EXPECT_EQ(journal::getErrMessages().size(), 0);
316 }
317
318 // Test where devices were specified in constructor
319 {
320 std::vector<std::unique_ptr<Device>> devices{};
321
322 // Create PMBusReadSensorAction
323 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};
324 uint8_t command = 0x8C;
325 pmbus_utils::SensorDataFormat format{
326 pmbus_utils::SensorDataFormat::linear_11};
327 std::optional<int8_t> exponent{};
328 std::unique_ptr<PMBusReadSensorAction> action =
329 std::make_unique<PMBusReadSensorAction>(type, command, format,
330 exponent);
331
332 // Create mock I2CInterface. A two-byte read should occur.
333 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
334 std::make_unique<i2c::MockedI2CInterface>();
335 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
336 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
337 .Times(1);
338
339 // Create SensorMonitoring
340 std::vector<std::unique_ptr<Action>> actions{};
341 actions.emplace_back(std::move(action));
342 std::unique_ptr<SensorMonitoring> sensorMonitoring =
343 std::make_unique<SensorMonitoring>(std::move(actions));
344
345 // Create Rail
346 std::vector<std::unique_ptr<Rail>> rails{};
347 std::unique_ptr<Configuration> configuration{};
348 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
349 "vdd0", std::move(configuration), std::move(sensorMonitoring));
350 rails.emplace_back(std::move(rail));
351
352 // Create Device
353 std::unique_ptr<PresenceDetection> presenceDetection{};
354 std::unique_ptr<Configuration> deviceConfiguration{};
355 std::unique_ptr<Device> device = std::make_unique<Device>(
356 "reg1", true, "/system/chassis/motherboard/reg1",
357 std::move(i2cInterface), std::move(presenceDetection),
358 std::move(deviceConfiguration), std::move(rails));
359
360 // Create Chassis
361 devices.emplace_back(std::move(device));
362 std::unique_ptr<Chassis> chassis =
363 std::make_unique<Chassis>(1, std::move(devices));
364 Chassis* chassisPtr = chassis.get();
365
366 // Create System that contains Chassis
367 std::vector<std::unique_ptr<Rule>> rules{};
368 std::vector<std::unique_ptr<Chassis>> chassisVec{};
369 chassisVec.emplace_back(std::move(chassis));
370 System system{std::move(rules), std::move(chassisVec)};
371
372 // Call monitorSensors()
373 journal::clear();
374 chassisPtr->monitorSensors(system);
375 EXPECT_EQ(journal::getDebugMessages().size(), 0);
376 EXPECT_EQ(journal::getErrMessages().size(), 0);
377 }
378}