blob: e3c1c6a22a6bfaf6c4f7b4f2ebf7124577783a30 [file] [log] [blame]
Shawn McCarneya2461b32019-10-24 18:53:01 -05001/**
2 * Copyright © 2019 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 McCarney4bf310e2020-03-10 17:48:11 -050016#include "action.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050017#include "chassis.hpp"
Shawn McCarney4bf310e2020-03-10 17:48:11 -050018#include "configuration.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050019#include "device.hpp"
20#include "i2c_interface.hpp"
21#include "journal.hpp"
Shawn McCarney4bf310e2020-03-10 17:48:11 -050022#include "mock_action.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050023#include "mock_journal.hpp"
24#include "mocked_i2c_interface.hpp"
Bob King7b743432020-06-22 17:35:04 +080025#include "pmbus_read_sensor_action.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050026#include "presence_detection.hpp"
Shawn McCarneya2461b32019-10-24 18:53:01 -050027#include "rail.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050028#include "rule.hpp"
Shawn McCarney4bf310e2020-03-10 17:48:11 -050029#include "sensor_monitoring.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050030#include "system.hpp"
Shawn McCarney4bf310e2020-03-10 17:48:11 -050031
32#include <memory>
33#include <optional>
34#include <utility>
35#include <vector>
Shawn McCarneya2461b32019-10-24 18:53:01 -050036
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050037#include <gmock/gmock.h>
Shawn McCarneya2461b32019-10-24 18:53:01 -050038#include <gtest/gtest.h>
39
40using namespace phosphor::power::regulators;
41
Bob King7b743432020-06-22 17:35:04 +080042using ::testing::A;
Shawn McCarney779b9562020-04-13 17:05:45 -050043using ::testing::Return;
Bob King7b743432020-06-22 17:35:04 +080044using ::testing::TypedEq;
Shawn McCarney779b9562020-04-13 17:05:45 -050045
Shawn McCarneya2461b32019-10-24 18:53:01 -050046TEST(RailTests, Constructor)
47{
Shawn McCarney4bf310e2020-03-10 17:48:11 -050048 // Test where only required parameters are specified
49 {
50 Rail rail{"vdd0"};
51 EXPECT_EQ(rail.getID(), "vdd0");
52 EXPECT_EQ(rail.getConfiguration(), nullptr);
53 EXPECT_EQ(rail.getSensorMonitoring(), nullptr);
54 }
55
56 // Test where all parameters are specified
57 {
58 // Create Configuration
59 std::optional<double> volts{1.3};
60 std::vector<std::unique_ptr<Action>> actions{};
61 actions.push_back(std::make_unique<MockAction>());
62 actions.push_back(std::make_unique<MockAction>());
63 std::unique_ptr<Configuration> configuration =
64 std::make_unique<Configuration>(volts, std::move(actions));
65
66 // Create SensorMonitoring
67 actions.clear();
68 actions.push_back(std::make_unique<MockAction>());
69 std::unique_ptr<SensorMonitoring> sensorMonitoring =
70 std::make_unique<SensorMonitoring>(std::move(actions));
71
72 // Create Rail
73 Rail rail{"vddr1", std::move(configuration),
74 std::move(sensorMonitoring)};
75 EXPECT_EQ(rail.getID(), "vddr1");
76 EXPECT_NE(rail.getConfiguration(), nullptr);
77 EXPECT_EQ(rail.getConfiguration()->getVolts().has_value(), true);
78 EXPECT_EQ(rail.getConfiguration()->getVolts().value(), 1.3);
79 EXPECT_EQ(rail.getConfiguration()->getActions().size(), 2);
80 EXPECT_NE(rail.getSensorMonitoring(), nullptr);
81 EXPECT_EQ(rail.getSensorMonitoring()->getActions().size(), 1);
82 }
83}
84
Shawn McCarney779b9562020-04-13 17:05:45 -050085TEST(RailTests, Configure)
86{
87 // Test where Configuration was not specified in constructor
88 {
89 // Create Rail
90 std::unique_ptr<Rail> rail = std::make_unique<Rail>("vdd0");
91 Rail* railPtr = rail.get();
92
93 // Create Device that contains Rail
94 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
95 std::make_unique<i2c::MockedI2CInterface>();
96 std::unique_ptr<PresenceDetection> presenceDetection{};
97 std::unique_ptr<Configuration> deviceConfiguration{};
98 std::vector<std::unique_ptr<Rail>> rails{};
99 rails.emplace_back(std::move(rail));
100 std::unique_ptr<Device> device = std::make_unique<Device>(
101 "reg1", true, "/system/chassis/motherboard/reg1",
102 std::move(i2cInterface), std::move(presenceDetection),
103 std::move(deviceConfiguration), std::move(rails));
104 Device* devicePtr = device.get();
105
106 // Create Chassis that contains Device
107 std::vector<std::unique_ptr<Device>> devices{};
108 devices.emplace_back(std::move(device));
109 std::unique_ptr<Chassis> chassis =
110 std::make_unique<Chassis>(1, std::move(devices));
111 Chassis* chassisPtr = chassis.get();
112
113 // Create System that contains Chassis
114 std::vector<std::unique_ptr<Rule>> rules{};
115 std::vector<std::unique_ptr<Chassis>> chassisVec{};
116 chassisVec.emplace_back(std::move(chassis));
117 System system{std::move(rules), std::move(chassisVec)};
118
119 // Call configure(). Should do nothing.
120 journal::clear();
121 railPtr->configure(system, *chassisPtr, *devicePtr);
122 EXPECT_EQ(journal::getDebugMessages().size(), 0);
123 EXPECT_EQ(journal::getErrMessages().size(), 0);
124 }
125
126 // Test where Configuration was specified in constructor
127 {
128 // Create Configuration
129 std::optional<double> volts{1.3};
130 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
131 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
132 std::vector<std::unique_ptr<Action>> actions{};
133 actions.emplace_back(std::move(action));
134 std::unique_ptr<Configuration> configuration =
135 std::make_unique<Configuration>(volts, std::move(actions));
136
137 // Create Rail
138 std::unique_ptr<Rail> rail =
139 std::make_unique<Rail>("vddr1", std::move(configuration));
140 Rail* railPtr = rail.get();
141
142 // Create Device that contains Rail
143 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
144 std::make_unique<i2c::MockedI2CInterface>();
145 std::unique_ptr<PresenceDetection> presenceDetection{};
146 std::unique_ptr<Configuration> deviceConfiguration{};
147 std::vector<std::unique_ptr<Rail>> rails{};
148 rails.emplace_back(std::move(rail));
149 std::unique_ptr<Device> device = std::make_unique<Device>(
150 "reg1", true, "/system/chassis/motherboard/reg1",
151 std::move(i2cInterface), std::move(presenceDetection),
152 std::move(deviceConfiguration), std::move(rails));
153 Device* devicePtr = device.get();
154
155 // Create Chassis that contains Device
156 std::vector<std::unique_ptr<Device>> devices{};
157 devices.emplace_back(std::move(device));
158 std::unique_ptr<Chassis> chassis =
159 std::make_unique<Chassis>(1, std::move(devices));
160 Chassis* chassisPtr = chassis.get();
161
162 // Create System that contains Chassis
163 std::vector<std::unique_ptr<Rule>> rules{};
164 std::vector<std::unique_ptr<Chassis>> chassisVec{};
165 chassisVec.emplace_back(std::move(chassis));
166 System system{std::move(rules), std::move(chassisVec)};
167
168 // Call configure(). Should execute Configuration and log debug message
169 // to journal.
170 journal::clear();
171 railPtr->configure(system, *chassisPtr, *devicePtr);
172 std::vector<std::string> expectedDebugMessages{
173 "Configuring vddr1: volts=1.300000"};
174 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
175 EXPECT_EQ(journal::getErrMessages().size(), 0);
176 }
177}
178
Shawn McCarney4bf310e2020-03-10 17:48:11 -0500179TEST(RailTests, GetConfiguration)
180{
181 // Test where Configuration was not specified in constructor
182 {
183 Rail rail{"vdd0"};
184 EXPECT_EQ(rail.getConfiguration(), nullptr);
185 }
186
187 // Test where Configuration was specified in constructor
188 {
189 // Create Configuration
190 std::optional<double> volts{3.2};
191 std::vector<std::unique_ptr<Action>> actions{};
192 actions.push_back(std::make_unique<MockAction>());
193 std::unique_ptr<Configuration> configuration =
194 std::make_unique<Configuration>(volts, std::move(actions));
195
196 // Create Rail
197 Rail rail{"vddr1", std::move(configuration)};
198 EXPECT_NE(rail.getConfiguration(), nullptr);
199 EXPECT_EQ(rail.getConfiguration()->getVolts().has_value(), true);
200 EXPECT_EQ(rail.getConfiguration()->getVolts().value(), 3.2);
201 EXPECT_EQ(rail.getConfiguration()->getActions().size(), 1);
202 }
Shawn McCarneya2461b32019-10-24 18:53:01 -0500203}
204
Shawn McCarney4afb2852019-10-27 18:28:53 -0500205TEST(RailTests, GetID)
Shawn McCarneya2461b32019-10-24 18:53:01 -0500206{
Shawn McCarney4bf310e2020-03-10 17:48:11 -0500207 Rail rail{"vio2"};
Shawn McCarney4afb2852019-10-27 18:28:53 -0500208 EXPECT_EQ(rail.getID(), "vio2");
Shawn McCarneya2461b32019-10-24 18:53:01 -0500209}
Shawn McCarney4bf310e2020-03-10 17:48:11 -0500210
Bob King7b743432020-06-22 17:35:04 +0800211TEST(RailTests, MonitorSensors)
212{
213 // Test where SensorMonitoring was not specified in constructor
214 {
215 // Create mock I2CInterface. A two-byte read should NOT occur.
216 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
217 std::make_unique<i2c::MockedI2CInterface>();
218 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint16_t&>())).Times(0);
219
220 // Create Rail
221 std::unique_ptr<Rail> rail = std::make_unique<Rail>("vdd0");
222 Rail* railPtr = rail.get();
223
224 // Create Device that contains Rail
225 std::unique_ptr<PresenceDetection> presenceDetection{};
226 std::unique_ptr<Configuration> deviceConfiguration{};
227 std::vector<std::unique_ptr<Rail>> rails{};
228 rails.emplace_back(std::move(rail));
229 std::unique_ptr<Device> device = std::make_unique<Device>(
230 "reg1", true, "/system/chassis/motherboard/reg1",
231 std::move(i2cInterface), std::move(presenceDetection),
232 std::move(deviceConfiguration), std::move(rails));
233 Device* devicePtr = device.get();
234
235 // Create Chassis that contains Device
236 std::vector<std::unique_ptr<Device>> devices{};
237 devices.emplace_back(std::move(device));
238 std::unique_ptr<Chassis> chassis =
239 std::make_unique<Chassis>(1, std::move(devices));
240 Chassis* chassisPtr = chassis.get();
241
242 // Create System that contains Chassis
243 std::vector<std::unique_ptr<Rule>> rules{};
244 std::vector<std::unique_ptr<Chassis>> chassisVec{};
245 chassisVec.emplace_back(std::move(chassis));
246 System system{std::move(rules), std::move(chassisVec)};
247
248 // Call monitorSensors(). Should do nothing.
249 journal::clear();
250 railPtr->monitorSensors(system, *chassisPtr, *devicePtr);
251 EXPECT_EQ(journal::getDebugMessages().size(), 0);
252 EXPECT_EQ(journal::getErrMessages().size(), 0);
253 }
254
255 // Test where SensorMonitoring was specified in constructor
256 {
257 // Create PMBusReadSensorAction
258 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};
259 uint8_t command = 0x8C;
260 pmbus_utils::SensorDataFormat format{
261 pmbus_utils::SensorDataFormat::linear_11};
262 std::optional<int8_t> exponent{};
263 std::unique_ptr<PMBusReadSensorAction> action =
264 std::make_unique<PMBusReadSensorAction>(type, command, format,
265 exponent);
266
267 // Create mock I2CInterface. A two-byte read should occur.
268 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
269 std::make_unique<i2c::MockedI2CInterface>();
270 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
271 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
272 .Times(1);
273
274 // Create SensorMonitoring
275 std::vector<std::unique_ptr<Action>> actions{};
276 actions.emplace_back(std::move(action));
277 std::unique_ptr<SensorMonitoring> sensorMonitoring =
278 std::make_unique<SensorMonitoring>(std::move(actions));
279
280 // Create Rail
281 std::unique_ptr<Configuration> configuration{};
282 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
283 "vddr1", std::move(configuration), std::move(sensorMonitoring));
284 Rail* railPtr = rail.get();
285
286 // Create Device that contains Rail
287 std::unique_ptr<PresenceDetection> presenceDetection{};
288 std::unique_ptr<Configuration> deviceConfiguration{};
289 std::vector<std::unique_ptr<Rail>> rails{};
290 rails.emplace_back(std::move(rail));
291 std::unique_ptr<Device> device = std::make_unique<Device>(
292 "reg1", true, "/system/chassis/motherboard/reg1",
293 std::move(i2cInterface), std::move(presenceDetection),
294 std::move(deviceConfiguration), std::move(rails));
295 Device* devicePtr = device.get();
296
297 // Create Chassis that contains Device
298 std::vector<std::unique_ptr<Device>> devices{};
299 devices.emplace_back(std::move(device));
300 std::unique_ptr<Chassis> chassis =
301 std::make_unique<Chassis>(1, std::move(devices));
302 Chassis* chassisPtr = chassis.get();
303
304 // Create System that contains Chassis
305 std::vector<std::unique_ptr<Rule>> rules{};
306 std::vector<std::unique_ptr<Chassis>> chassisVec{};
307 chassisVec.emplace_back(std::move(chassis));
308 System system{std::move(rules), std::move(chassisVec)};
309
310 // Call monitorSensors().
311 journal::clear();
312 railPtr->monitorSensors(system, *chassisPtr, *devicePtr);
313 EXPECT_EQ(journal::getDebugMessages().size(), 0);
314 EXPECT_EQ(journal::getErrMessages().size(), 0);
315 }
316}
317
Shawn McCarney4bf310e2020-03-10 17:48:11 -0500318TEST(RailTests, GetSensorMonitoring)
319{
320 // Test where SensorMonitoring was not specified in constructor
321 {
322 Rail rail{"vdd0", nullptr, nullptr};
323 EXPECT_EQ(rail.getSensorMonitoring(), nullptr);
324 }
325
326 // Test where SensorMonitoring was specified in constructor
327 {
328 std::unique_ptr<Configuration> configuration{};
329
330 // Create SensorMonitoring
331 std::vector<std::unique_ptr<Action>> actions{};
332 actions.push_back(std::make_unique<MockAction>());
333 actions.push_back(std::make_unique<MockAction>());
334 std::unique_ptr<SensorMonitoring> sensorMonitoring =
335 std::make_unique<SensorMonitoring>(std::move(actions));
336
337 // Create Rail
338 Rail rail{"vddr1", std::move(configuration),
339 std::move(sensorMonitoring)};
340 EXPECT_NE(rail.getSensorMonitoring(), nullptr);
341 EXPECT_EQ(rail.getSensorMonitoring()->getActions().size(), 2);
342 }
343}