blob: 190e48e4def8b1df6c2b2e4087a5801898b80270 [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"
Bob King23243f82020-07-29 10:38:57 +080024#include "mock_services.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050025#include "mocked_i2c_interface.hpp"
Bob King7b743432020-06-22 17:35:04 +080026#include "pmbus_read_sensor_action.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050027#include "presence_detection.hpp"
Shawn McCarneya2461b32019-10-24 18:53:01 -050028#include "rail.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050029#include "rule.hpp"
Shawn McCarney4bf310e2020-03-10 17:48:11 -050030#include "sensor_monitoring.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050031#include "system.hpp"
Shawn McCarney4bf310e2020-03-10 17:48:11 -050032
33#include <memory>
34#include <optional>
35#include <utility>
36#include <vector>
Shawn McCarneya2461b32019-10-24 18:53:01 -050037
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050038#include <gmock/gmock.h>
Shawn McCarneya2461b32019-10-24 18:53:01 -050039#include <gtest/gtest.h>
40
41using namespace phosphor::power::regulators;
42
Bob King7b743432020-06-22 17:35:04 +080043using ::testing::A;
Shawn McCarney779b9562020-04-13 17:05:45 -050044using ::testing::Return;
Bob King7b743432020-06-22 17:35:04 +080045using ::testing::TypedEq;
Shawn McCarney779b9562020-04-13 17:05:45 -050046
Shawn McCarneya2461b32019-10-24 18:53:01 -050047TEST(RailTests, Constructor)
48{
Shawn McCarney4bf310e2020-03-10 17:48:11 -050049 // Test where only required parameters are specified
50 {
51 Rail rail{"vdd0"};
52 EXPECT_EQ(rail.getID(), "vdd0");
53 EXPECT_EQ(rail.getConfiguration(), nullptr);
54 EXPECT_EQ(rail.getSensorMonitoring(), nullptr);
55 }
56
57 // Test where all parameters are specified
58 {
59 // Create Configuration
60 std::optional<double> volts{1.3};
61 std::vector<std::unique_ptr<Action>> actions{};
62 actions.push_back(std::make_unique<MockAction>());
63 actions.push_back(std::make_unique<MockAction>());
64 std::unique_ptr<Configuration> configuration =
65 std::make_unique<Configuration>(volts, std::move(actions));
66
67 // Create SensorMonitoring
68 actions.clear();
69 actions.push_back(std::make_unique<MockAction>());
70 std::unique_ptr<SensorMonitoring> sensorMonitoring =
71 std::make_unique<SensorMonitoring>(std::move(actions));
72
73 // Create Rail
74 Rail rail{"vddr1", std::move(configuration),
75 std::move(sensorMonitoring)};
76 EXPECT_EQ(rail.getID(), "vddr1");
77 EXPECT_NE(rail.getConfiguration(), nullptr);
78 EXPECT_EQ(rail.getConfiguration()->getVolts().has_value(), true);
79 EXPECT_EQ(rail.getConfiguration()->getVolts().value(), 1.3);
80 EXPECT_EQ(rail.getConfiguration()->getActions().size(), 2);
81 EXPECT_NE(rail.getSensorMonitoring(), nullptr);
82 EXPECT_EQ(rail.getSensorMonitoring()->getActions().size(), 1);
83 }
84}
85
Shawn McCarney779b9562020-04-13 17:05:45 -050086TEST(RailTests, Configure)
87{
88 // Test where Configuration was not specified in constructor
89 {
Bob King5cfe5102020-07-30 16:26:18 +080090 // Create mock services. No logging should occur.
Bob King23243f82020-07-29 10:38:57 +080091 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +080092 MockJournal& journal = services.getMockJournal();
93 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
94 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +080095
Shawn McCarney779b9562020-04-13 17:05:45 -050096 // Create Rail
97 std::unique_ptr<Rail> rail = std::make_unique<Rail>("vdd0");
98 Rail* railPtr = rail.get();
99
100 // Create Device that contains Rail
101 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
102 std::make_unique<i2c::MockedI2CInterface>();
103 std::unique_ptr<PresenceDetection> presenceDetection{};
104 std::unique_ptr<Configuration> deviceConfiguration{};
105 std::vector<std::unique_ptr<Rail>> rails{};
106 rails.emplace_back(std::move(rail));
107 std::unique_ptr<Device> device = std::make_unique<Device>(
108 "reg1", true, "/system/chassis/motherboard/reg1",
109 std::move(i2cInterface), std::move(presenceDetection),
110 std::move(deviceConfiguration), std::move(rails));
111 Device* devicePtr = device.get();
112
113 // Create Chassis that contains Device
114 std::vector<std::unique_ptr<Device>> devices{};
115 devices.emplace_back(std::move(device));
116 std::unique_ptr<Chassis> chassis =
117 std::make_unique<Chassis>(1, std::move(devices));
118 Chassis* chassisPtr = chassis.get();
119
120 // Create System that contains Chassis
121 std::vector<std::unique_ptr<Rule>> rules{};
122 std::vector<std::unique_ptr<Chassis>> chassisVec{};
123 chassisVec.emplace_back(std::move(chassis));
124 System system{std::move(rules), std::move(chassisVec)};
125
Bob King5cfe5102020-07-30 16:26:18 +0800126 // Call configure().
Bob King23243f82020-07-29 10:38:57 +0800127 railPtr->configure(services, system, *chassisPtr, *devicePtr);
Shawn McCarney779b9562020-04-13 17:05:45 -0500128 }
129
130 // Test where Configuration was specified in constructor
131 {
Bob King5cfe5102020-07-30 16:26:18 +0800132 // Create mock services. Expect logDebug() to be called.
Bob King23243f82020-07-29 10:38:57 +0800133 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800134 MockJournal& journal = services.getMockJournal();
135 EXPECT_CALL(journal, logDebug("Configuring vddr1: volts=1.300000"))
136 .Times(1);
137 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800138
Shawn McCarney779b9562020-04-13 17:05:45 -0500139 // Create Configuration
140 std::optional<double> volts{1.3};
141 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
142 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
143 std::vector<std::unique_ptr<Action>> actions{};
144 actions.emplace_back(std::move(action));
145 std::unique_ptr<Configuration> configuration =
146 std::make_unique<Configuration>(volts, std::move(actions));
147
148 // Create Rail
149 std::unique_ptr<Rail> rail =
150 std::make_unique<Rail>("vddr1", std::move(configuration));
151 Rail* railPtr = rail.get();
152
153 // Create Device that contains Rail
154 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
155 std::make_unique<i2c::MockedI2CInterface>();
156 std::unique_ptr<PresenceDetection> presenceDetection{};
157 std::unique_ptr<Configuration> deviceConfiguration{};
158 std::vector<std::unique_ptr<Rail>> rails{};
159 rails.emplace_back(std::move(rail));
160 std::unique_ptr<Device> device = std::make_unique<Device>(
161 "reg1", true, "/system/chassis/motherboard/reg1",
162 std::move(i2cInterface), std::move(presenceDetection),
163 std::move(deviceConfiguration), std::move(rails));
164 Device* devicePtr = device.get();
165
166 // Create Chassis that contains Device
167 std::vector<std::unique_ptr<Device>> devices{};
168 devices.emplace_back(std::move(device));
169 std::unique_ptr<Chassis> chassis =
170 std::make_unique<Chassis>(1, std::move(devices));
171 Chassis* chassisPtr = chassis.get();
172
173 // Create System that contains Chassis
174 std::vector<std::unique_ptr<Rule>> rules{};
175 std::vector<std::unique_ptr<Chassis>> chassisVec{};
176 chassisVec.emplace_back(std::move(chassis));
177 System system{std::move(rules), std::move(chassisVec)};
178
Bob King5cfe5102020-07-30 16:26:18 +0800179 // Call configure().
Bob King23243f82020-07-29 10:38:57 +0800180 railPtr->configure(services, system, *chassisPtr, *devicePtr);
Shawn McCarney779b9562020-04-13 17:05:45 -0500181 }
182}
183
Shawn McCarney4bf310e2020-03-10 17:48:11 -0500184TEST(RailTests, GetConfiguration)
185{
186 // Test where Configuration was not specified in constructor
187 {
188 Rail rail{"vdd0"};
189 EXPECT_EQ(rail.getConfiguration(), nullptr);
190 }
191
192 // Test where Configuration was specified in constructor
193 {
194 // Create Configuration
195 std::optional<double> volts{3.2};
196 std::vector<std::unique_ptr<Action>> actions{};
197 actions.push_back(std::make_unique<MockAction>());
198 std::unique_ptr<Configuration> configuration =
199 std::make_unique<Configuration>(volts, std::move(actions));
200
201 // Create Rail
202 Rail rail{"vddr1", std::move(configuration)};
203 EXPECT_NE(rail.getConfiguration(), nullptr);
204 EXPECT_EQ(rail.getConfiguration()->getVolts().has_value(), true);
205 EXPECT_EQ(rail.getConfiguration()->getVolts().value(), 3.2);
206 EXPECT_EQ(rail.getConfiguration()->getActions().size(), 1);
207 }
Shawn McCarneya2461b32019-10-24 18:53:01 -0500208}
209
Shawn McCarney4afb2852019-10-27 18:28:53 -0500210TEST(RailTests, GetID)
Shawn McCarneya2461b32019-10-24 18:53:01 -0500211{
Shawn McCarney4bf310e2020-03-10 17:48:11 -0500212 Rail rail{"vio2"};
Shawn McCarney4afb2852019-10-27 18:28:53 -0500213 EXPECT_EQ(rail.getID(), "vio2");
Shawn McCarneya2461b32019-10-24 18:53:01 -0500214}
Shawn McCarney4bf310e2020-03-10 17:48:11 -0500215
Bob King7b743432020-06-22 17:35:04 +0800216TEST(RailTests, MonitorSensors)
217{
218 // Test where SensorMonitoring was not specified in constructor
219 {
220 // Create mock I2CInterface. A two-byte read should NOT occur.
221 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
222 std::make_unique<i2c::MockedI2CInterface>();
223 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint16_t&>())).Times(0);
224
225 // Create Rail
226 std::unique_ptr<Rail> rail = std::make_unique<Rail>("vdd0");
227 Rail* railPtr = rail.get();
228
229 // Create Device that contains Rail
230 std::unique_ptr<PresenceDetection> presenceDetection{};
231 std::unique_ptr<Configuration> deviceConfiguration{};
232 std::vector<std::unique_ptr<Rail>> rails{};
233 rails.emplace_back(std::move(rail));
234 std::unique_ptr<Device> device = std::make_unique<Device>(
235 "reg1", true, "/system/chassis/motherboard/reg1",
236 std::move(i2cInterface), std::move(presenceDetection),
237 std::move(deviceConfiguration), std::move(rails));
238 Device* devicePtr = device.get();
239
240 // Create Chassis that contains Device
241 std::vector<std::unique_ptr<Device>> devices{};
242 devices.emplace_back(std::move(device));
243 std::unique_ptr<Chassis> chassis =
244 std::make_unique<Chassis>(1, 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 monitorSensors(). Should do nothing.
254 journal::clear();
255 railPtr->monitorSensors(system, *chassisPtr, *devicePtr);
256 EXPECT_EQ(journal::getDebugMessages().size(), 0);
257 EXPECT_EQ(journal::getErrMessages().size(), 0);
258 }
259
260 // Test where SensorMonitoring was specified in constructor
261 {
262 // Create PMBusReadSensorAction
263 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};
264 uint8_t command = 0x8C;
265 pmbus_utils::SensorDataFormat format{
266 pmbus_utils::SensorDataFormat::linear_11};
267 std::optional<int8_t> exponent{};
268 std::unique_ptr<PMBusReadSensorAction> action =
269 std::make_unique<PMBusReadSensorAction>(type, command, format,
270 exponent);
271
272 // Create mock I2CInterface. A two-byte read should occur.
273 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
274 std::make_unique<i2c::MockedI2CInterface>();
275 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
276 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
277 .Times(1);
278
279 // Create SensorMonitoring
280 std::vector<std::unique_ptr<Action>> actions{};
281 actions.emplace_back(std::move(action));
282 std::unique_ptr<SensorMonitoring> sensorMonitoring =
283 std::make_unique<SensorMonitoring>(std::move(actions));
284
285 // Create Rail
286 std::unique_ptr<Configuration> configuration{};
287 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
288 "vddr1", std::move(configuration), std::move(sensorMonitoring));
289 Rail* railPtr = rail.get();
290
291 // Create Device that contains Rail
292 std::unique_ptr<PresenceDetection> presenceDetection{};
293 std::unique_ptr<Configuration> deviceConfiguration{};
294 std::vector<std::unique_ptr<Rail>> rails{};
295 rails.emplace_back(std::move(rail));
296 std::unique_ptr<Device> device = std::make_unique<Device>(
297 "reg1", true, "/system/chassis/motherboard/reg1",
298 std::move(i2cInterface), std::move(presenceDetection),
299 std::move(deviceConfiguration), std::move(rails));
300 Device* devicePtr = device.get();
301
302 // Create Chassis that contains Device
303 std::vector<std::unique_ptr<Device>> devices{};
304 devices.emplace_back(std::move(device));
305 std::unique_ptr<Chassis> chassis =
306 std::make_unique<Chassis>(1, std::move(devices));
307 Chassis* chassisPtr = chassis.get();
308
309 // Create System that contains Chassis
310 std::vector<std::unique_ptr<Rule>> rules{};
311 std::vector<std::unique_ptr<Chassis>> chassisVec{};
312 chassisVec.emplace_back(std::move(chassis));
313 System system{std::move(rules), std::move(chassisVec)};
314
315 // Call monitorSensors().
316 journal::clear();
317 railPtr->monitorSensors(system, *chassisPtr, *devicePtr);
318 EXPECT_EQ(journal::getDebugMessages().size(), 0);
319 EXPECT_EQ(journal::getErrMessages().size(), 0);
320 }
321}
322
Shawn McCarney4bf310e2020-03-10 17:48:11 -0500323TEST(RailTests, GetSensorMonitoring)
324{
325 // Test where SensorMonitoring was not specified in constructor
326 {
327 Rail rail{"vdd0", nullptr, nullptr};
328 EXPECT_EQ(rail.getSensorMonitoring(), nullptr);
329 }
330
331 // Test where SensorMonitoring was specified in constructor
332 {
333 std::unique_ptr<Configuration> configuration{};
334
335 // Create SensorMonitoring
336 std::vector<std::unique_ptr<Action>> actions{};
337 actions.push_back(std::make_unique<MockAction>());
338 actions.push_back(std::make_unique<MockAction>());
339 std::unique_ptr<SensorMonitoring> sensorMonitoring =
340 std::make_unique<SensorMonitoring>(std::move(actions));
341
342 // Create Rail
343 Rail rail{"vddr1", std::move(configuration),
344 std::move(sensorMonitoring)};
345 EXPECT_NE(rail.getSensorMonitoring(), nullptr);
346 EXPECT_EQ(rail.getSensorMonitoring()->getActions().size(), 2);
347 }
348}