blob: 4f52701272e4a7e7578d7b5a7089b7023a3b2418 [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"
Shawn McCarney4bf310e2020-03-10 17:48:11 -050021#include "mock_action.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050022#include "mock_journal.hpp"
Bob King23243f82020-07-29 10:38:57 +080023#include "mock_services.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050024#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 McCarney2f9e14f2021-04-29 02:45:18 -050030#include "sensors.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 McCarneycb3f6a62021-04-30 10:54:30 -050047static const std::string chassisInvPath{
48 "/xyz/openbmc_project/inventory/system/chassis"};
49
Shawn McCarneya2461b32019-10-24 18:53:01 -050050TEST(RailTests, Constructor)
51{
Shawn McCarney4bf310e2020-03-10 17:48:11 -050052 // Test where only required parameters are specified
53 {
54 Rail rail{"vdd0"};
55 EXPECT_EQ(rail.getID(), "vdd0");
56 EXPECT_EQ(rail.getConfiguration(), nullptr);
57 EXPECT_EQ(rail.getSensorMonitoring(), nullptr);
58 }
59
60 // Test where all parameters are specified
61 {
62 // Create Configuration
63 std::optional<double> volts{1.3};
64 std::vector<std::unique_ptr<Action>> actions{};
65 actions.push_back(std::make_unique<MockAction>());
66 actions.push_back(std::make_unique<MockAction>());
67 std::unique_ptr<Configuration> configuration =
68 std::make_unique<Configuration>(volts, std::move(actions));
69
70 // Create SensorMonitoring
71 actions.clear();
72 actions.push_back(std::make_unique<MockAction>());
73 std::unique_ptr<SensorMonitoring> sensorMonitoring =
74 std::make_unique<SensorMonitoring>(std::move(actions));
75
76 // Create Rail
77 Rail rail{"vddr1", std::move(configuration),
78 std::move(sensorMonitoring)};
79 EXPECT_EQ(rail.getID(), "vddr1");
80 EXPECT_NE(rail.getConfiguration(), nullptr);
81 EXPECT_EQ(rail.getConfiguration()->getVolts().has_value(), true);
82 EXPECT_EQ(rail.getConfiguration()->getVolts().value(), 1.3);
83 EXPECT_EQ(rail.getConfiguration()->getActions().size(), 2);
84 EXPECT_NE(rail.getSensorMonitoring(), nullptr);
85 EXPECT_EQ(rail.getSensorMonitoring()->getActions().size(), 1);
86 }
87}
88
Shawn McCarney779b9562020-04-13 17:05:45 -050089TEST(RailTests, Configure)
90{
91 // Test where Configuration was not specified in constructor
92 {
Bob King5cfe5102020-07-30 16:26:18 +080093 // Create mock services. No logging should occur.
Bob King23243f82020-07-29 10:38:57 +080094 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +080095 MockJournal& journal = services.getMockJournal();
96 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
97 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +080098
Shawn McCarney779b9562020-04-13 17:05:45 -050099 // Create Rail
100 std::unique_ptr<Rail> rail = std::make_unique<Rail>("vdd0");
101 Rail* railPtr = rail.get();
102
103 // Create Device that contains Rail
104 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
105 std::make_unique<i2c::MockedI2CInterface>();
106 std::unique_ptr<PresenceDetection> presenceDetection{};
107 std::unique_ptr<Configuration> deviceConfiguration{};
108 std::vector<std::unique_ptr<Rail>> rails{};
109 rails.emplace_back(std::move(rail));
110 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800111 "reg1", true,
112 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarney779b9562020-04-13 17:05:45 -0500113 std::move(i2cInterface), std::move(presenceDetection),
114 std::move(deviceConfiguration), std::move(rails));
115 Device* devicePtr = device.get();
116
117 // Create Chassis that contains Device
118 std::vector<std::unique_ptr<Device>> devices{};
119 devices.emplace_back(std::move(device));
120 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500121 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Shawn McCarney779b9562020-04-13 17:05:45 -0500122 Chassis* chassisPtr = chassis.get();
123
124 // Create System that contains Chassis
125 std::vector<std::unique_ptr<Rule>> rules{};
126 std::vector<std::unique_ptr<Chassis>> chassisVec{};
127 chassisVec.emplace_back(std::move(chassis));
128 System system{std::move(rules), std::move(chassisVec)};
129
Bob King5cfe5102020-07-30 16:26:18 +0800130 // Call configure().
Bob King23243f82020-07-29 10:38:57 +0800131 railPtr->configure(services, system, *chassisPtr, *devicePtr);
Shawn McCarney779b9562020-04-13 17:05:45 -0500132 }
133
134 // Test where Configuration was specified in constructor
135 {
Bob King5cfe5102020-07-30 16:26:18 +0800136 // Create mock services. Expect logDebug() to be called.
Bob King23243f82020-07-29 10:38:57 +0800137 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800138 MockJournal& journal = services.getMockJournal();
139 EXPECT_CALL(journal, logDebug("Configuring vddr1: volts=1.300000"))
140 .Times(1);
141 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800142
Shawn McCarney779b9562020-04-13 17:05:45 -0500143 // Create Configuration
144 std::optional<double> volts{1.3};
145 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
146 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
147 std::vector<std::unique_ptr<Action>> actions{};
148 actions.emplace_back(std::move(action));
149 std::unique_ptr<Configuration> configuration =
150 std::make_unique<Configuration>(volts, std::move(actions));
151
152 // Create Rail
153 std::unique_ptr<Rail> rail =
154 std::make_unique<Rail>("vddr1", std::move(configuration));
155 Rail* railPtr = rail.get();
156
157 // Create Device that contains Rail
158 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
159 std::make_unique<i2c::MockedI2CInterface>();
160 std::unique_ptr<PresenceDetection> presenceDetection{};
161 std::unique_ptr<Configuration> deviceConfiguration{};
162 std::vector<std::unique_ptr<Rail>> rails{};
163 rails.emplace_back(std::move(rail));
164 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800165 "reg1", true,
166 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarney779b9562020-04-13 17:05:45 -0500167 std::move(i2cInterface), std::move(presenceDetection),
168 std::move(deviceConfiguration), std::move(rails));
169 Device* devicePtr = device.get();
170
171 // Create Chassis that contains Device
172 std::vector<std::unique_ptr<Device>> devices{};
173 devices.emplace_back(std::move(device));
174 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500175 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Shawn McCarney779b9562020-04-13 17:05:45 -0500176 Chassis* chassisPtr = chassis.get();
177
178 // Create System that contains Chassis
179 std::vector<std::unique_ptr<Rule>> rules{};
180 std::vector<std::unique_ptr<Chassis>> chassisVec{};
181 chassisVec.emplace_back(std::move(chassis));
182 System system{std::move(rules), std::move(chassisVec)};
183
Bob King5cfe5102020-07-30 16:26:18 +0800184 // Call configure().
Bob King23243f82020-07-29 10:38:57 +0800185 railPtr->configure(services, system, *chassisPtr, *devicePtr);
Shawn McCarney779b9562020-04-13 17:05:45 -0500186 }
187}
188
Shawn McCarney4bf310e2020-03-10 17:48:11 -0500189TEST(RailTests, GetConfiguration)
190{
191 // Test where Configuration was not specified in constructor
192 {
193 Rail rail{"vdd0"};
194 EXPECT_EQ(rail.getConfiguration(), nullptr);
195 }
196
197 // Test where Configuration was specified in constructor
198 {
199 // Create Configuration
200 std::optional<double> volts{3.2};
201 std::vector<std::unique_ptr<Action>> actions{};
202 actions.push_back(std::make_unique<MockAction>());
203 std::unique_ptr<Configuration> configuration =
204 std::make_unique<Configuration>(volts, std::move(actions));
205
206 // Create Rail
207 Rail rail{"vddr1", std::move(configuration)};
208 EXPECT_NE(rail.getConfiguration(), nullptr);
209 EXPECT_EQ(rail.getConfiguration()->getVolts().has_value(), true);
210 EXPECT_EQ(rail.getConfiguration()->getVolts().value(), 3.2);
211 EXPECT_EQ(rail.getConfiguration()->getActions().size(), 1);
212 }
Shawn McCarneya2461b32019-10-24 18:53:01 -0500213}
214
Shawn McCarney4afb2852019-10-27 18:28:53 -0500215TEST(RailTests, GetID)
Shawn McCarneya2461b32019-10-24 18:53:01 -0500216{
Shawn McCarney4bf310e2020-03-10 17:48:11 -0500217 Rail rail{"vio2"};
Shawn McCarney4afb2852019-10-27 18:28:53 -0500218 EXPECT_EQ(rail.getID(), "vio2");
Shawn McCarneya2461b32019-10-24 18:53:01 -0500219}
Shawn McCarney4bf310e2020-03-10 17:48:11 -0500220
Bob King7b743432020-06-22 17:35:04 +0800221TEST(RailTests, MonitorSensors)
222{
223 // Test where SensorMonitoring was not specified in constructor
224 {
Bob King8a552922020-08-05 17:02:31 +0800225 // Create mock services. No logging should occur.
226 MockServices services{};
227 MockJournal& journal = services.getMockJournal();
228 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
229 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
230
Bob King7b743432020-06-22 17:35:04 +0800231 // Create mock I2CInterface. A two-byte read should NOT occur.
232 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
233 std::make_unique<i2c::MockedI2CInterface>();
234 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint16_t&>())).Times(0);
235
236 // Create Rail
237 std::unique_ptr<Rail> rail = std::make_unique<Rail>("vdd0");
238 Rail* railPtr = rail.get();
239
240 // Create Device that contains Rail
241 std::unique_ptr<PresenceDetection> presenceDetection{};
242 std::unique_ptr<Configuration> deviceConfiguration{};
243 std::vector<std::unique_ptr<Rail>> rails{};
244 rails.emplace_back(std::move(rail));
245 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800246 "reg1", true,
247 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob King7b743432020-06-22 17:35:04 +0800248 std::move(i2cInterface), std::move(presenceDetection),
249 std::move(deviceConfiguration), std::move(rails));
250 Device* devicePtr = device.get();
251
252 // Create Chassis that contains Device
253 std::vector<std::unique_ptr<Device>> devices{};
254 devices.emplace_back(std::move(device));
255 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500256 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Bob King7b743432020-06-22 17:35:04 +0800257 Chassis* chassisPtr = chassis.get();
258
259 // Create System that contains Chassis
260 std::vector<std::unique_ptr<Rule>> rules{};
261 std::vector<std::unique_ptr<Chassis>> chassisVec{};
262 chassisVec.emplace_back(std::move(chassis));
263 System system{std::move(rules), std::move(chassisVec)};
264
Bob King8a552922020-08-05 17:02:31 +0800265 // Call monitorSensors().
266 railPtr->monitorSensors(services, system, *chassisPtr, *devicePtr);
Bob King7b743432020-06-22 17:35:04 +0800267 }
268
269 // Test where SensorMonitoring was specified in constructor
270 {
Bob King8a552922020-08-05 17:02:31 +0800271 // Create mock services. No logging should occur.
272 MockServices services{};
273 MockJournal& journal = services.getMockJournal();
274 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
275 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
276
Bob King7b743432020-06-22 17:35:04 +0800277 // Create PMBusReadSensorAction
Shawn McCarney2f9e14f2021-04-29 02:45:18 -0500278 SensorType type{SensorType::iout};
Bob King7b743432020-06-22 17:35:04 +0800279 uint8_t command = 0x8C;
280 pmbus_utils::SensorDataFormat format{
281 pmbus_utils::SensorDataFormat::linear_11};
282 std::optional<int8_t> exponent{};
283 std::unique_ptr<PMBusReadSensorAction> action =
284 std::make_unique<PMBusReadSensorAction>(type, command, format,
285 exponent);
286
287 // Create mock I2CInterface. A two-byte read should occur.
288 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
289 std::make_unique<i2c::MockedI2CInterface>();
290 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
291 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
292 .Times(1);
293
294 // Create SensorMonitoring
295 std::vector<std::unique_ptr<Action>> actions{};
296 actions.emplace_back(std::move(action));
297 std::unique_ptr<SensorMonitoring> sensorMonitoring =
298 std::make_unique<SensorMonitoring>(std::move(actions));
299
300 // Create Rail
301 std::unique_ptr<Configuration> configuration{};
302 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
303 "vddr1", std::move(configuration), std::move(sensorMonitoring));
304 Rail* railPtr = rail.get();
305
306 // Create Device that contains Rail
307 std::unique_ptr<PresenceDetection> presenceDetection{};
308 std::unique_ptr<Configuration> deviceConfiguration{};
309 std::vector<std::unique_ptr<Rail>> rails{};
310 rails.emplace_back(std::move(rail));
311 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800312 "reg1", true,
313 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob King7b743432020-06-22 17:35:04 +0800314 std::move(i2cInterface), std::move(presenceDetection),
315 std::move(deviceConfiguration), std::move(rails));
316 Device* devicePtr = device.get();
317
318 // Create Chassis that contains Device
319 std::vector<std::unique_ptr<Device>> devices{};
320 devices.emplace_back(std::move(device));
321 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500322 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Bob King7b743432020-06-22 17:35:04 +0800323 Chassis* chassisPtr = chassis.get();
324
325 // Create System that contains Chassis
326 std::vector<std::unique_ptr<Rule>> rules{};
327 std::vector<std::unique_ptr<Chassis>> chassisVec{};
328 chassisVec.emplace_back(std::move(chassis));
329 System system{std::move(rules), std::move(chassisVec)};
330
331 // Call monitorSensors().
Bob King8a552922020-08-05 17:02:31 +0800332 railPtr->monitorSensors(services, system, *chassisPtr, *devicePtr);
Bob King7b743432020-06-22 17:35:04 +0800333 }
334}
335
Shawn McCarney4bf310e2020-03-10 17:48:11 -0500336TEST(RailTests, GetSensorMonitoring)
337{
338 // Test where SensorMonitoring was not specified in constructor
339 {
340 Rail rail{"vdd0", nullptr, nullptr};
341 EXPECT_EQ(rail.getSensorMonitoring(), nullptr);
342 }
343
344 // Test where SensorMonitoring was specified in constructor
345 {
346 std::unique_ptr<Configuration> configuration{};
347
348 // Create SensorMonitoring
349 std::vector<std::unique_ptr<Action>> actions{};
350 actions.push_back(std::make_unique<MockAction>());
351 actions.push_back(std::make_unique<MockAction>());
352 std::unique_ptr<SensorMonitoring> sensorMonitoring =
353 std::make_unique<SensorMonitoring>(std::move(actions));
354
355 // Create Rail
356 Rail rail{"vddr1", std::move(configuration),
357 std::move(sensorMonitoring)};
358 EXPECT_NE(rail.getSensorMonitoring(), nullptr);
359 EXPECT_EQ(rail.getSensorMonitoring()->getActions().size(), 2);
360 }
361}