blob: ab34d200945683dd819b4f7ffe172705f2694eef [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 McCarney2ccf9612021-05-14 11:09:17 -050022#include "mock_error_logging.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050023#include "mock_journal.hpp"
Shawn McCarney17bac892021-05-08 07:55:52 -050024#include "mock_sensors.hpp"
Bob King23243f82020-07-29 10:38:57 +080025#include "mock_services.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050026#include "mocked_i2c_interface.hpp"
27#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 McCarney2f9e14f2021-04-29 02:45:18 -050031#include "sensors.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050032#include "system.hpp"
Shawn McCarney2ccf9612021-05-14 11:09:17 -050033#include "test_sdbus_error.hpp"
Shawn McCarney4bf310e2020-03-10 17:48:11 -050034
35#include <memory>
36#include <optional>
37#include <utility>
38#include <vector>
Shawn McCarneya2461b32019-10-24 18:53:01 -050039
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050040#include <gmock/gmock.h>
Shawn McCarneya2461b32019-10-24 18:53:01 -050041#include <gtest/gtest.h>
42
43using namespace phosphor::power::regulators;
44
Bob King7b743432020-06-22 17:35:04 +080045using ::testing::A;
Shawn McCarney779b9562020-04-13 17:05:45 -050046using ::testing::Return;
Shawn McCarney2ccf9612021-05-14 11:09:17 -050047using ::testing::Throw;
Bob King7b743432020-06-22 17:35:04 +080048using ::testing::TypedEq;
Shawn McCarney779b9562020-04-13 17:05:45 -050049
Shawn McCarneycb3f6a62021-04-30 10:54:30 -050050static const std::string chassisInvPath{
51 "/xyz/openbmc_project/inventory/system/chassis"};
52
Shawn McCarneya2461b32019-10-24 18:53:01 -050053TEST(RailTests, Constructor)
54{
Shawn McCarney4bf310e2020-03-10 17:48:11 -050055 // Test where only required parameters are specified
56 {
57 Rail rail{"vdd0"};
58 EXPECT_EQ(rail.getID(), "vdd0");
59 EXPECT_EQ(rail.getConfiguration(), nullptr);
60 EXPECT_EQ(rail.getSensorMonitoring(), nullptr);
61 }
62
63 // Test where all parameters are specified
64 {
65 // Create Configuration
66 std::optional<double> volts{1.3};
67 std::vector<std::unique_ptr<Action>> actions{};
68 actions.push_back(std::make_unique<MockAction>());
69 actions.push_back(std::make_unique<MockAction>());
70 std::unique_ptr<Configuration> configuration =
71 std::make_unique<Configuration>(volts, std::move(actions));
72
73 // Create SensorMonitoring
74 actions.clear();
75 actions.push_back(std::make_unique<MockAction>());
76 std::unique_ptr<SensorMonitoring> sensorMonitoring =
77 std::make_unique<SensorMonitoring>(std::move(actions));
78
79 // Create Rail
80 Rail rail{"vddr1", std::move(configuration),
81 std::move(sensorMonitoring)};
82 EXPECT_EQ(rail.getID(), "vddr1");
83 EXPECT_NE(rail.getConfiguration(), nullptr);
84 EXPECT_EQ(rail.getConfiguration()->getVolts().has_value(), true);
85 EXPECT_EQ(rail.getConfiguration()->getVolts().value(), 1.3);
86 EXPECT_EQ(rail.getConfiguration()->getActions().size(), 2);
87 EXPECT_NE(rail.getSensorMonitoring(), nullptr);
88 EXPECT_EQ(rail.getSensorMonitoring()->getActions().size(), 1);
89 }
90}
91
Shawn McCarney2ccf9612021-05-14 11:09:17 -050092TEST(RailTests, ClearErrorHistory)
93{
94 // Create SensorMonitoring. Will fail with a DBus exception.
95 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
96 EXPECT_CALL(*action, execute)
97 .WillRepeatedly(Throw(TestSDBusError{"Unable to set sensor value"}));
98 std::vector<std::unique_ptr<Action>> actions{};
99 actions.emplace_back(std::move(action));
100 std::unique_ptr<SensorMonitoring> sensorMonitoring =
101 std::make_unique<SensorMonitoring>(std::move(actions));
102
103 // Create Rail
104 std::unique_ptr<Configuration> configuration{};
105 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
106 "vddr1", std::move(configuration), std::move(sensorMonitoring));
107 Rail* railPtr = rail.get();
108
109 // Create Device that contains Rail
110 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
111 std::make_unique<i2c::MockedI2CInterface>();
112 std::unique_ptr<PresenceDetection> presenceDetection{};
113 std::unique_ptr<Configuration> deviceConfiguration{};
114 std::vector<std::unique_ptr<Rail>> rails{};
115 rails.emplace_back(std::move(rail));
116 std::unique_ptr<Device> device = std::make_unique<Device>(
117 "reg1", true,
118 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
119 std::move(i2cInterface), std::move(presenceDetection),
120 std::move(deviceConfiguration), std::move(rails));
121 Device* devicePtr = device.get();
122
123 // Create Chassis that contains Device
124 std::vector<std::unique_ptr<Device>> devices{};
125 devices.emplace_back(std::move(device));
126 std::unique_ptr<Chassis> chassis =
127 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
128 Chassis* chassisPtr = chassis.get();
129
130 // Create System that contains Chassis
131 std::vector<std::unique_ptr<Rule>> rules{};
132 std::vector<std::unique_ptr<Chassis>> chassisVec{};
133 chassisVec.emplace_back(std::move(chassis));
134 System system{std::move(rules), std::move(chassisVec)};
135
136 // Create mock services
137 MockServices services{};
138
139 // Expect Sensors service to be called 5+5=10 times
140 MockSensors& sensors = services.getMockSensors();
141 EXPECT_CALL(sensors, startRail).Times(10);
142 EXPECT_CALL(sensors, setValue).Times(0);
143 EXPECT_CALL(sensors, endRail).Times(10);
144
145 // Expect Journal service to be called 3+3=6 times to log error messages
146 MockJournal& journal = services.getMockJournal();
147 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
148 .Times(6);
149 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(6);
150
151 // Expect ErrorLogging service to be called 1+1=2 times to log a DBus error
152 MockErrorLogging& errorLogging = services.getMockErrorLogging();
153 EXPECT_CALL(errorLogging, logDBusError).Times(2);
154
155 // Monitor sensors 5 times. Should fail every time, write to journal 3
156 // times, and log one error.
157 for (int i = 1; i <= 5; ++i)
158 {
159 railPtr->monitorSensors(services, system, *chassisPtr, *devicePtr);
160 }
161
162 // Clear error history
163 railPtr->clearErrorHistory();
164
165 // Monitor sensors 5 times again. Should fail every time, write to journal
166 // 3 times, and log one error.
167 for (int i = 1; i <= 5; ++i)
168 {
169 railPtr->monitorSensors(services, system, *chassisPtr, *devicePtr);
170 }
171}
172
Shawn McCarney779b9562020-04-13 17:05:45 -0500173TEST(RailTests, Configure)
174{
175 // Test where Configuration was not specified in constructor
176 {
Bob King5cfe5102020-07-30 16:26:18 +0800177 // Create mock services. No logging should occur.
Bob King23243f82020-07-29 10:38:57 +0800178 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800179 MockJournal& journal = services.getMockJournal();
180 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
181 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800182
Shawn McCarney779b9562020-04-13 17:05:45 -0500183 // Create Rail
184 std::unique_ptr<Rail> rail = std::make_unique<Rail>("vdd0");
185 Rail* railPtr = rail.get();
186
187 // Create Device that contains Rail
188 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
189 std::make_unique<i2c::MockedI2CInterface>();
190 std::unique_ptr<PresenceDetection> presenceDetection{};
191 std::unique_ptr<Configuration> deviceConfiguration{};
192 std::vector<std::unique_ptr<Rail>> rails{};
193 rails.emplace_back(std::move(rail));
194 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800195 "reg1", true,
196 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarney779b9562020-04-13 17:05:45 -0500197 std::move(i2cInterface), std::move(presenceDetection),
198 std::move(deviceConfiguration), std::move(rails));
199 Device* devicePtr = device.get();
200
201 // Create Chassis that contains Device
202 std::vector<std::unique_ptr<Device>> devices{};
203 devices.emplace_back(std::move(device));
204 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500205 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Shawn McCarney779b9562020-04-13 17:05:45 -0500206 Chassis* chassisPtr = chassis.get();
207
208 // Create System that contains Chassis
209 std::vector<std::unique_ptr<Rule>> rules{};
210 std::vector<std::unique_ptr<Chassis>> chassisVec{};
211 chassisVec.emplace_back(std::move(chassis));
212 System system{std::move(rules), std::move(chassisVec)};
213
Bob King5cfe5102020-07-30 16:26:18 +0800214 // Call configure().
Bob King23243f82020-07-29 10:38:57 +0800215 railPtr->configure(services, system, *chassisPtr, *devicePtr);
Shawn McCarney779b9562020-04-13 17:05:45 -0500216 }
217
218 // Test where Configuration was specified in constructor
219 {
Bob King5cfe5102020-07-30 16:26:18 +0800220 // Create mock services. Expect logDebug() to be called.
Bob King23243f82020-07-29 10:38:57 +0800221 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800222 MockJournal& journal = services.getMockJournal();
223 EXPECT_CALL(journal, logDebug("Configuring vddr1: volts=1.300000"))
224 .Times(1);
225 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800226
Shawn McCarney779b9562020-04-13 17:05:45 -0500227 // Create Configuration
228 std::optional<double> volts{1.3};
229 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
230 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
231 std::vector<std::unique_ptr<Action>> actions{};
232 actions.emplace_back(std::move(action));
233 std::unique_ptr<Configuration> configuration =
234 std::make_unique<Configuration>(volts, std::move(actions));
235
236 // Create Rail
237 std::unique_ptr<Rail> rail =
238 std::make_unique<Rail>("vddr1", std::move(configuration));
239 Rail* railPtr = rail.get();
240
241 // Create Device that contains Rail
242 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
243 std::make_unique<i2c::MockedI2CInterface>();
244 std::unique_ptr<PresenceDetection> presenceDetection{};
245 std::unique_ptr<Configuration> deviceConfiguration{};
246 std::vector<std::unique_ptr<Rail>> rails{};
247 rails.emplace_back(std::move(rail));
248 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800249 "reg1", true,
250 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarney779b9562020-04-13 17:05:45 -0500251 std::move(i2cInterface), std::move(presenceDetection),
252 std::move(deviceConfiguration), std::move(rails));
253 Device* devicePtr = device.get();
254
255 // Create Chassis that contains Device
256 std::vector<std::unique_ptr<Device>> devices{};
257 devices.emplace_back(std::move(device));
258 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500259 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Shawn McCarney779b9562020-04-13 17:05:45 -0500260 Chassis* chassisPtr = chassis.get();
261
262 // Create System that contains Chassis
263 std::vector<std::unique_ptr<Rule>> rules{};
264 std::vector<std::unique_ptr<Chassis>> chassisVec{};
265 chassisVec.emplace_back(std::move(chassis));
266 System system{std::move(rules), std::move(chassisVec)};
267
Bob King5cfe5102020-07-30 16:26:18 +0800268 // Call configure().
Bob King23243f82020-07-29 10:38:57 +0800269 railPtr->configure(services, system, *chassisPtr, *devicePtr);
Shawn McCarney779b9562020-04-13 17:05:45 -0500270 }
271}
272
Shawn McCarney4bf310e2020-03-10 17:48:11 -0500273TEST(RailTests, GetConfiguration)
274{
275 // Test where Configuration was not specified in constructor
276 {
277 Rail rail{"vdd0"};
278 EXPECT_EQ(rail.getConfiguration(), nullptr);
279 }
280
281 // Test where Configuration was specified in constructor
282 {
283 // Create Configuration
284 std::optional<double> volts{3.2};
285 std::vector<std::unique_ptr<Action>> actions{};
286 actions.push_back(std::make_unique<MockAction>());
287 std::unique_ptr<Configuration> configuration =
288 std::make_unique<Configuration>(volts, std::move(actions));
289
290 // Create Rail
291 Rail rail{"vddr1", std::move(configuration)};
292 EXPECT_NE(rail.getConfiguration(), nullptr);
293 EXPECT_EQ(rail.getConfiguration()->getVolts().has_value(), true);
294 EXPECT_EQ(rail.getConfiguration()->getVolts().value(), 3.2);
295 EXPECT_EQ(rail.getConfiguration()->getActions().size(), 1);
296 }
Shawn McCarneya2461b32019-10-24 18:53:01 -0500297}
298
Shawn McCarney4afb2852019-10-27 18:28:53 -0500299TEST(RailTests, GetID)
Shawn McCarneya2461b32019-10-24 18:53:01 -0500300{
Shawn McCarney4bf310e2020-03-10 17:48:11 -0500301 Rail rail{"vio2"};
Shawn McCarney4afb2852019-10-27 18:28:53 -0500302 EXPECT_EQ(rail.getID(), "vio2");
Shawn McCarneya2461b32019-10-24 18:53:01 -0500303}
Shawn McCarney4bf310e2020-03-10 17:48:11 -0500304
Bob King7b743432020-06-22 17:35:04 +0800305TEST(RailTests, MonitorSensors)
306{
307 // Test where SensorMonitoring was not specified in constructor
308 {
Shawn McCarney17bac892021-05-08 07:55:52 -0500309 // Create mock services. No Sensors methods should be called.
Bob King8a552922020-08-05 17:02:31 +0800310 MockServices services{};
Shawn McCarney17bac892021-05-08 07:55:52 -0500311 MockSensors& sensors = services.getMockSensors();
312 EXPECT_CALL(sensors, startRail).Times(0);
313 EXPECT_CALL(sensors, setValue).Times(0);
314 EXPECT_CALL(sensors, endRail).Times(0);
Bob King7b743432020-06-22 17:35:04 +0800315
316 // Create Rail
317 std::unique_ptr<Rail> rail = std::make_unique<Rail>("vdd0");
318 Rail* railPtr = rail.get();
319
320 // Create Device that contains Rail
Shawn McCarney17bac892021-05-08 07:55:52 -0500321 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
322 std::make_unique<i2c::MockedI2CInterface>();
Bob King7b743432020-06-22 17:35:04 +0800323 std::unique_ptr<PresenceDetection> presenceDetection{};
324 std::unique_ptr<Configuration> deviceConfiguration{};
325 std::vector<std::unique_ptr<Rail>> rails{};
326 rails.emplace_back(std::move(rail));
327 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800328 "reg1", true,
329 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob King7b743432020-06-22 17:35:04 +0800330 std::move(i2cInterface), std::move(presenceDetection),
331 std::move(deviceConfiguration), std::move(rails));
332 Device* devicePtr = device.get();
333
334 // Create Chassis that contains Device
335 std::vector<std::unique_ptr<Device>> devices{};
336 devices.emplace_back(std::move(device));
337 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500338 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Bob King7b743432020-06-22 17:35:04 +0800339 Chassis* chassisPtr = chassis.get();
340
341 // Create System that contains Chassis
342 std::vector<std::unique_ptr<Rule>> rules{};
343 std::vector<std::unique_ptr<Chassis>> chassisVec{};
344 chassisVec.emplace_back(std::move(chassis));
345 System system{std::move(rules), std::move(chassisVec)};
346
Shawn McCarney17bac892021-05-08 07:55:52 -0500347 // Call monitorSensors()
Bob King8a552922020-08-05 17:02:31 +0800348 railPtr->monitorSensors(services, system, *chassisPtr, *devicePtr);
Bob King7b743432020-06-22 17:35:04 +0800349 }
350
351 // Test where SensorMonitoring was specified in constructor
352 {
Shawn McCarney17bac892021-05-08 07:55:52 -0500353 // Create mock services. Set Sensors service expectations.
Bob King8a552922020-08-05 17:02:31 +0800354 MockServices services{};
Shawn McCarney17bac892021-05-08 07:55:52 -0500355 MockSensors& sensors = services.getMockSensors();
356 EXPECT_CALL(sensors,
357 startRail("vddr1",
358 "/xyz/openbmc_project/inventory/system/chassis/"
359 "motherboard/reg1",
360 chassisInvPath))
Bob King7b743432020-06-22 17:35:04 +0800361 .Times(1);
Shawn McCarney17bac892021-05-08 07:55:52 -0500362 EXPECT_CALL(sensors, setValue).Times(0);
363 EXPECT_CALL(sensors, endRail(false)).Times(1);
Bob King7b743432020-06-22 17:35:04 +0800364
365 // Create SensorMonitoring
Shawn McCarney17bac892021-05-08 07:55:52 -0500366 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
367 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
Bob King7b743432020-06-22 17:35:04 +0800368 std::vector<std::unique_ptr<Action>> actions{};
369 actions.emplace_back(std::move(action));
370 std::unique_ptr<SensorMonitoring> sensorMonitoring =
371 std::make_unique<SensorMonitoring>(std::move(actions));
372
373 // Create Rail
374 std::unique_ptr<Configuration> configuration{};
375 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
376 "vddr1", std::move(configuration), std::move(sensorMonitoring));
377 Rail* railPtr = rail.get();
378
379 // Create Device that contains Rail
Shawn McCarney17bac892021-05-08 07:55:52 -0500380 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
381 std::make_unique<i2c::MockedI2CInterface>();
Bob King7b743432020-06-22 17:35:04 +0800382 std::unique_ptr<PresenceDetection> presenceDetection{};
383 std::unique_ptr<Configuration> deviceConfiguration{};
384 std::vector<std::unique_ptr<Rail>> rails{};
385 rails.emplace_back(std::move(rail));
386 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800387 "reg1", true,
388 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob King7b743432020-06-22 17:35:04 +0800389 std::move(i2cInterface), std::move(presenceDetection),
390 std::move(deviceConfiguration), std::move(rails));
391 Device* devicePtr = device.get();
392
393 // Create Chassis that contains Device
394 std::vector<std::unique_ptr<Device>> devices{};
395 devices.emplace_back(std::move(device));
396 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500397 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Bob King7b743432020-06-22 17:35:04 +0800398 Chassis* chassisPtr = chassis.get();
399
400 // Create System that contains Chassis
401 std::vector<std::unique_ptr<Rule>> rules{};
402 std::vector<std::unique_ptr<Chassis>> chassisVec{};
403 chassisVec.emplace_back(std::move(chassis));
404 System system{std::move(rules), std::move(chassisVec)};
405
Shawn McCarney17bac892021-05-08 07:55:52 -0500406 // Call monitorSensors()
Bob King8a552922020-08-05 17:02:31 +0800407 railPtr->monitorSensors(services, system, *chassisPtr, *devicePtr);
Bob King7b743432020-06-22 17:35:04 +0800408 }
409}
410
Shawn McCarney4bf310e2020-03-10 17:48:11 -0500411TEST(RailTests, GetSensorMonitoring)
412{
413 // Test where SensorMonitoring was not specified in constructor
414 {
415 Rail rail{"vdd0", nullptr, nullptr};
416 EXPECT_EQ(rail.getSensorMonitoring(), nullptr);
417 }
418
419 // Test where SensorMonitoring was specified in constructor
420 {
421 std::unique_ptr<Configuration> configuration{};
422
423 // Create SensorMonitoring
424 std::vector<std::unique_ptr<Action>> actions{};
425 actions.push_back(std::make_unique<MockAction>());
426 actions.push_back(std::make_unique<MockAction>());
427 std::unique_ptr<SensorMonitoring> sensorMonitoring =
428 std::make_unique<SensorMonitoring>(std::move(actions));
429
430 // Create Rail
431 Rail rail{"vddr1", std::move(configuration),
432 std::move(sensorMonitoring)};
433 EXPECT_NE(rail.getSensorMonitoring(), nullptr);
434 EXPECT_EQ(rail.getSensorMonitoring()->getActions().size(), 2);
435 }
436}