blob: c285480533aef8ea59afa258b51079b5de819d1e [file] [log] [blame]
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -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 */
16#include "action.hpp"
Shawn McCarney39765002020-04-09 18:03:26 -050017#include "chassis.hpp"
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050018#include "configuration.hpp"
Shawn McCarney39765002020-04-09 18:03:26 -050019#include "device.hpp"
20#include "i2c_interface.hpp"
21#include "i2c_write_byte_action.hpp"
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050022#include "mock_action.hpp"
Shawn McCarney81a2f902021-03-23 21:41:34 -050023#include "mock_error_logging.hpp"
Shawn McCarney39765002020-04-09 18:03:26 -050024#include "mock_journal.hpp"
Bob King23243f82020-07-29 10:38:57 +080025#include "mock_services.hpp"
Shawn McCarney39765002020-04-09 18:03:26 -050026#include "mocked_i2c_interface.hpp"
Shawn McCarney32252592021-09-08 15:29:36 -050027#include "phase_fault_detection.hpp"
Shawn McCarney39765002020-04-09 18:03:26 -050028#include "pmbus_utils.hpp"
29#include "pmbus_write_vout_command_action.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050030#include "presence_detection.hpp"
Shawn McCarney39765002020-04-09 18:03:26 -050031#include "rail.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050032#include "rule.hpp"
Shawn McCarney39765002020-04-09 18:03:26 -050033#include "system.hpp"
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050034
Shawn McCarney779b9562020-04-13 17:05:45 -050035#include <cstdint>
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050036#include <memory>
37#include <optional>
38#include <utility>
39#include <vector>
40
Shawn McCarney39765002020-04-09 18:03:26 -050041#include <gmock/gmock.h>
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050042#include <gtest/gtest.h>
43
44using namespace phosphor::power::regulators;
Shawn McCarney39765002020-04-09 18:03:26 -050045using namespace phosphor::power::regulators::pmbus_utils;
46
Bob King5cfe5102020-07-30 16:26:18 +080047using ::testing::A;
Shawn McCarney81a2f902021-03-23 21:41:34 -050048using ::testing::Ref;
Shawn McCarney39765002020-04-09 18:03:26 -050049using ::testing::Return;
50using ::testing::Throw;
51using ::testing::TypedEq;
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050052
Shawn McCarneycb3f6a62021-04-30 10:54:30 -050053static const std::string chassisInvPath{
54 "/xyz/openbmc_project/inventory/system/chassis"};
55
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050056TEST(ConfigurationTests, Constructor)
57{
58 // Test where volts value specified
59 {
60 std::optional<double> volts{1.3};
61
62 std::vector<std::unique_ptr<Action>> actions{};
63 actions.push_back(std::make_unique<MockAction>());
64 actions.push_back(std::make_unique<MockAction>());
65
66 Configuration configuration(volts, std::move(actions));
67 EXPECT_EQ(configuration.getVolts().has_value(), true);
68 EXPECT_EQ(configuration.getVolts().value(), 1.3);
69 EXPECT_EQ(configuration.getActions().size(), 2);
70 }
71
72 // Test where volts value not specified
73 {
74 std::optional<double> volts{};
75
76 std::vector<std::unique_ptr<Action>> actions{};
77 actions.push_back(std::make_unique<MockAction>());
78
79 Configuration configuration(volts, std::move(actions));
80 EXPECT_EQ(configuration.getVolts().has_value(), false);
81 EXPECT_EQ(configuration.getActions().size(), 1);
82 }
83}
84
Bob King5cfe5102020-07-30 16:26:18 +080085// Test for execute(Services&, System&, Chassis&, Device&)
Shawn McCarney39765002020-04-09 18:03:26 -050086TEST(ConfigurationTests, ExecuteForDevice)
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050087{
Shawn McCarney39765002020-04-09 18:03:26 -050088 // Test where works: Volts value not specified
89 {
Bob King5cfe5102020-07-30 16:26:18 +080090 // Create mock services. Expect logDebug() to be called.
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("Configuring vdd_reg")).Times(1);
94 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +080095
Shawn McCarney39765002020-04-09 18:03:26 -050096 // Create I2CWriteByteAction with register 0x7C and value 0x0A
97 std::unique_ptr<I2CWriteByteAction> action =
98 std::make_unique<I2CWriteByteAction>(0x7C, 0x0A);
99
100 // Create mock I2CInterface. Expect action to write 0x0A to 0x7C.
101 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
102 std::make_unique<i2c::MockedI2CInterface>();
103 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
104 EXPECT_CALL(*i2cInterface,
105 write(TypedEq<uint8_t>(0x7C), TypedEq<uint8_t>(0x0A)))
106 .Times(1);
107
108 // Create Configuration with no volts value specified
109 std::optional<double> volts{};
110 std::vector<std::unique_ptr<Action>> actions{};
111 actions.emplace_back(std::move(action));
112 std::unique_ptr<Configuration> configuration =
113 std::make_unique<Configuration>(volts, std::move(actions));
114 Configuration* configurationPtr = configuration.get();
115
116 // Create Device that contains Configuration
117 std::unique_ptr<PresenceDetection> presenceDetection{};
118 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800119 "vdd_reg", true,
120 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
Shawn McCarney39765002020-04-09 18:03:26 -0500121 std::move(i2cInterface), std::move(presenceDetection),
122 std::move(configuration));
123 Device* devicePtr = device.get();
124
125 // Create Chassis that contains Device
126 std::vector<std::unique_ptr<Device>> devices{};
127 devices.emplace_back(std::move(device));
128 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500129 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Shawn McCarney39765002020-04-09 18:03:26 -0500130 Chassis* chassisPtr = chassis.get();
131
132 // Create System that contains Chassis
133 std::vector<std::unique_ptr<Rule>> rules{};
134 std::vector<std::unique_ptr<Chassis>> chassisVec{};
135 chassisVec.emplace_back(std::move(chassis));
136 System system{std::move(rules), std::move(chassisVec)};
137
138 // Execute Configuration
Bob King23243f82020-07-29 10:38:57 +0800139 configurationPtr->execute(services, system, *chassisPtr, *devicePtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500140 }
141
142 // Test where works: Volts value specified
143 {
Bob King5cfe5102020-07-30 16:26:18 +0800144 // Create mock services. Expect logDebug() to be called.
Bob King23243f82020-07-29 10:38:57 +0800145 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800146 MockJournal& journal = services.getMockJournal();
147 EXPECT_CALL(journal, logDebug("Configuring vdd_reg: volts=1.300000"))
148 .Times(1);
149 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800150
Shawn McCarney39765002020-04-09 18:03:26 -0500151 // Create PMBusWriteVoutCommandAction. Do not specify a volts value
152 // because it will get a value of 1.3V from the
153 // ActionEnvironment/Configuration. Specify a -8 exponent.
154 // Linear format volts value = (1.3 / 2^(-8)) = 332.8 = 333 = 0x014D.
155 std::optional<double> volts{};
156 std::unique_ptr<PMBusWriteVoutCommandAction> action =
157 std::make_unique<PMBusWriteVoutCommandAction>(
158 volts, pmbus_utils::VoutDataFormat::linear, -8, false);
159
160 // Create mock I2CInterface. Expect action to write 0x014D to
161 // VOUT_COMMAND (command/register 0x21).
162 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
163 std::make_unique<i2c::MockedI2CInterface>();
164 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
165 EXPECT_CALL(*i2cInterface,
166 write(TypedEq<uint8_t>(0x21), TypedEq<uint16_t>(0x014D)))
167 .Times(1);
168
169 // Create Configuration with volts value 1.3V
170 std::vector<std::unique_ptr<Action>> actions{};
171 actions.emplace_back(std::move(action));
172 std::unique_ptr<Configuration> configuration =
173 std::make_unique<Configuration>(1.3, std::move(actions));
174 Configuration* configurationPtr = configuration.get();
175
176 // Create Device that contains Configuration
177 std::unique_ptr<PresenceDetection> presenceDetection{};
178 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800179 "vdd_reg", true,
180 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
Shawn McCarney39765002020-04-09 18:03:26 -0500181 std::move(i2cInterface), std::move(presenceDetection),
182 std::move(configuration));
183 Device* devicePtr = device.get();
184
185 // Create Chassis that contains Device
186 std::vector<std::unique_ptr<Device>> devices{};
187 devices.emplace_back(std::move(device));
188 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500189 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Shawn McCarney39765002020-04-09 18:03:26 -0500190 Chassis* chassisPtr = chassis.get();
191
192 // Create System that contains Chassis
193 std::vector<std::unique_ptr<Rule>> rules{};
194 std::vector<std::unique_ptr<Chassis>> chassisVec{};
195 chassisVec.emplace_back(std::move(chassis));
196 System system{std::move(rules), std::move(chassisVec)};
197
198 // Execute Configuration
Bob King23243f82020-07-29 10:38:57 +0800199 configurationPtr->execute(services, system, *chassisPtr, *devicePtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500200 }
201
202 // Test where fails
203 {
Shawn McCarney81a2f902021-03-23 21:41:34 -0500204 // Create mock services. Expect logDebug(), logError(), and
205 // logI2CError() to be called.
Bob King23243f82020-07-29 10:38:57 +0800206 MockServices services{};
Shawn McCarney81a2f902021-03-23 21:41:34 -0500207 MockErrorLogging& errorLogging = services.getMockErrorLogging();
Bob King5cfe5102020-07-30 16:26:18 +0800208 MockJournal& journal = services.getMockJournal();
209 std::vector<std::string> expectedErrMessagesException{
210 "I2CException: Failed to write byte: bus /dev/i2c-1, addr 0x70",
211 "ActionError: i2c_write_byte: { register: 0x7C, value: 0xA, mask: "
212 "0xFF }"};
213 EXPECT_CALL(journal, logDebug("Configuring vdd_reg")).Times(1);
214 EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
215 EXPECT_CALL(journal, logError("Unable to configure vdd_reg")).Times(1);
Shawn McCarney81a2f902021-03-23 21:41:34 -0500216 EXPECT_CALL(errorLogging,
217 logI2CError(Entry::Level::Warning, Ref(journal),
218 "/dev/i2c-1", 0x70, 0))
219 .Times(1);
Bob King23243f82020-07-29 10:38:57 +0800220
Shawn McCarney39765002020-04-09 18:03:26 -0500221 // Create I2CWriteByteAction with register 0x7C and value 0x0A
222 std::unique_ptr<I2CWriteByteAction> action =
223 std::make_unique<I2CWriteByteAction>(0x7C, 0x0A);
224
225 // Create mock I2CInterface. write() throws an I2CException.
226 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
227 std::make_unique<i2c::MockedI2CInterface>();
228 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
229 EXPECT_CALL(*i2cInterface,
230 write(TypedEq<uint8_t>(0x7C), TypedEq<uint8_t>(0x0A)))
231 .Times(1)
232 .WillOnce(Throw(
233 i2c::I2CException{"Failed to write byte", "/dev/i2c-1", 0x70}));
234
235 // Create Configuration with no volts value specified
236 std::optional<double> volts{};
237 std::vector<std::unique_ptr<Action>> actions{};
238 actions.emplace_back(std::move(action));
239 std::unique_ptr<Configuration> configuration =
240 std::make_unique<Configuration>(volts, std::move(actions));
241 Configuration* configurationPtr = configuration.get();
242
243 // Create Device that contains Configuration
244 std::unique_ptr<PresenceDetection> presenceDetection{};
245 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800246 "vdd_reg", true,
247 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
Shawn McCarney39765002020-04-09 18:03:26 -0500248 std::move(i2cInterface), std::move(presenceDetection),
249 std::move(configuration));
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));
Shawn McCarney39765002020-04-09 18:03:26 -0500257 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
265 // Execute Configuration
Bob King23243f82020-07-29 10:38:57 +0800266 configurationPtr->execute(services, system, *chassisPtr, *devicePtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500267 }
268}
269
Bob King5cfe5102020-07-30 16:26:18 +0800270// Test for execute(Services&, System&, Chassis&, Device&, Rail&)
Shawn McCarney39765002020-04-09 18:03:26 -0500271TEST(ConfigurationTests, ExecuteForRail)
272{
273 // Test where works: Volts value not specified
274 {
Bob King5cfe5102020-07-30 16:26:18 +0800275 // Create mock services. Expect logDebug() to be called.
Bob King23243f82020-07-29 10:38:57 +0800276 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800277 MockJournal& journal = services.getMockJournal();
278 EXPECT_CALL(journal, logDebug("Configuring vio2")).Times(1);
279 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800280
Shawn McCarney39765002020-04-09 18:03:26 -0500281 // Create I2CWriteByteAction with register 0x7C and value 0x0A
282 std::unique_ptr<I2CWriteByteAction> action =
283 std::make_unique<I2CWriteByteAction>(0x7C, 0x0A);
284
285 // Create mock I2CInterface. Expect action to write 0x0A to 0x7C.
286 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
287 std::make_unique<i2c::MockedI2CInterface>();
288 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
289 EXPECT_CALL(*i2cInterface,
290 write(TypedEq<uint8_t>(0x7C), TypedEq<uint8_t>(0x0A)))
291 .Times(1);
292
293 // Create Configuration with no volts value specified
294 std::optional<double> volts{};
295 std::vector<std::unique_ptr<Action>> actions{};
296 actions.emplace_back(std::move(action));
297 std::unique_ptr<Configuration> configuration =
298 std::make_unique<Configuration>(volts, std::move(actions));
299 Configuration* configurationPtr = configuration.get();
300
301 // Create Rail that contains Configuration
302 std::unique_ptr<Rail> rail =
303 std::make_unique<Rail>("vio2", std::move(configuration));
304 Rail* railPtr = rail.get();
305
306 // Create Device that contains Rail
307 std::unique_ptr<PresenceDetection> presenceDetection{};
308 std::unique_ptr<Configuration> deviceConfiguration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500309 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney39765002020-04-09 18:03:26 -0500310 std::vector<std::unique_ptr<Rail>> rails{};
311 rails.emplace_back(std::move(rail));
312 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800313 "reg1", true,
314 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarney39765002020-04-09 18:03:26 -0500315 std::move(i2cInterface), std::move(presenceDetection),
Shawn McCarney32252592021-09-08 15:29:36 -0500316 std::move(deviceConfiguration), std::move(phaseFaultDetection),
317 std::move(rails));
Shawn McCarney39765002020-04-09 18:03:26 -0500318 Device* devicePtr = device.get();
319
320 // Create Chassis that contains Device
321 std::vector<std::unique_ptr<Device>> devices{};
322 devices.emplace_back(std::move(device));
323 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500324 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Shawn McCarney39765002020-04-09 18:03:26 -0500325 Chassis* chassisPtr = chassis.get();
326
327 // Create System that contains Chassis
328 std::vector<std::unique_ptr<Rule>> rules{};
329 std::vector<std::unique_ptr<Chassis>> chassisVec{};
330 chassisVec.emplace_back(std::move(chassis));
331 System system{std::move(rules), std::move(chassisVec)};
332
333 // Execute Configuration
Bob King23243f82020-07-29 10:38:57 +0800334 configurationPtr->execute(services, system, *chassisPtr, *devicePtr,
335 *railPtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500336 }
337
338 // Test where works: Volts value specified
339 {
Bob King5cfe5102020-07-30 16:26:18 +0800340 // Create mock services. Expect logDebug() to be called.
Bob King23243f82020-07-29 10:38:57 +0800341 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800342 MockJournal& journal = services.getMockJournal();
343 EXPECT_CALL(journal, logDebug("Configuring vio2: volts=1.300000"))
344 .Times(1);
345 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800346
Shawn McCarney39765002020-04-09 18:03:26 -0500347 // Create PMBusWriteVoutCommandAction. Do not specify a volts value
348 // because it will get a value of 1.3V from the
349 // ActionEnvironment/Configuration. Specify a -8 exponent.
350 // Linear format volts value = (1.3 / 2^(-8)) = 332.8 = 333 = 0x014D.
351 std::optional<double> volts{};
352 std::unique_ptr<PMBusWriteVoutCommandAction> action =
353 std::make_unique<PMBusWriteVoutCommandAction>(
354 volts, pmbus_utils::VoutDataFormat::linear, -8, false);
355
356 // Create mock I2CInterface. Expect action to write 0x014D to
357 // VOUT_COMMAND (command/register 0x21).
358 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
359 std::make_unique<i2c::MockedI2CInterface>();
360 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
361 EXPECT_CALL(*i2cInterface,
362 write(TypedEq<uint8_t>(0x21), TypedEq<uint16_t>(0x014D)))
363 .Times(1);
364
365 // Create Configuration with volts value 1.3V
366 std::vector<std::unique_ptr<Action>> actions{};
367 actions.emplace_back(std::move(action));
368 std::unique_ptr<Configuration> configuration =
369 std::make_unique<Configuration>(1.3, std::move(actions));
370 Configuration* configurationPtr = configuration.get();
371
372 // Create Rail that contains Configuration
373 std::unique_ptr<Rail> rail =
374 std::make_unique<Rail>("vio2", std::move(configuration));
375 Rail* railPtr = rail.get();
376
377 // Create Device that contains Rail
378 std::unique_ptr<PresenceDetection> presenceDetection{};
379 std::unique_ptr<Configuration> deviceConfiguration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500380 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney39765002020-04-09 18:03:26 -0500381 std::vector<std::unique_ptr<Rail>> rails{};
382 rails.emplace_back(std::move(rail));
383 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800384 "reg1", true,
385 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarney39765002020-04-09 18:03:26 -0500386 std::move(i2cInterface), std::move(presenceDetection),
Shawn McCarney32252592021-09-08 15:29:36 -0500387 std::move(deviceConfiguration), std::move(phaseFaultDetection),
388 std::move(rails));
Shawn McCarney39765002020-04-09 18:03:26 -0500389 Device* devicePtr = device.get();
390
391 // Create Chassis that contains Device
392 std::vector<std::unique_ptr<Device>> devices{};
393 devices.emplace_back(std::move(device));
394 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500395 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Shawn McCarney39765002020-04-09 18:03:26 -0500396 Chassis* chassisPtr = chassis.get();
397
398 // Create System that contains Chassis
399 std::vector<std::unique_ptr<Rule>> rules{};
400 std::vector<std::unique_ptr<Chassis>> chassisVec{};
401 chassisVec.emplace_back(std::move(chassis));
402 System system{std::move(rules), std::move(chassisVec)};
403
404 // Execute Configuration
Bob King23243f82020-07-29 10:38:57 +0800405 configurationPtr->execute(services, system, *chassisPtr, *devicePtr,
406 *railPtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500407 }
408
409 // Test where fails
410 {
Shawn McCarney81a2f902021-03-23 21:41:34 -0500411 // Create mock services. Expect logDebug(), logError(), and logI2CError
412 // to be called.
Bob King23243f82020-07-29 10:38:57 +0800413 MockServices services{};
Shawn McCarney81a2f902021-03-23 21:41:34 -0500414 MockErrorLogging& errorLogging = services.getMockErrorLogging();
Bob King5cfe5102020-07-30 16:26:18 +0800415 MockJournal& journal = services.getMockJournal();
416 std::vector<std::string> expectedErrMessagesException{
417 "I2CException: Failed to write byte: bus /dev/i2c-1, addr 0x70",
418 "ActionError: i2c_write_byte: { register: 0x7C, value: 0xA, mask: "
419 "0xFF }"};
420 EXPECT_CALL(journal, logDebug("Configuring vio2")).Times(1);
421 EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
422 EXPECT_CALL(journal, logError("Unable to configure vio2")).Times(1);
Shawn McCarney81a2f902021-03-23 21:41:34 -0500423 EXPECT_CALL(errorLogging,
424 logI2CError(Entry::Level::Warning, Ref(journal),
425 "/dev/i2c-1", 0x70, 0))
426 .Times(1);
Bob King23243f82020-07-29 10:38:57 +0800427
Shawn McCarney39765002020-04-09 18:03:26 -0500428 // Create I2CWriteByteAction with register 0x7C and value 0x0A
429 std::unique_ptr<I2CWriteByteAction> action =
430 std::make_unique<I2CWriteByteAction>(0x7C, 0x0A);
431
432 // Create mock I2CInterface. write() throws an I2CException.
433 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
434 std::make_unique<i2c::MockedI2CInterface>();
435 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
436 EXPECT_CALL(*i2cInterface,
437 write(TypedEq<uint8_t>(0x7C), TypedEq<uint8_t>(0x0A)))
438 .Times(1)
439 .WillOnce(Throw(
440 i2c::I2CException{"Failed to write byte", "/dev/i2c-1", 0x70}));
441
442 // Create Configuration with no volts value specified
443 std::optional<double> volts{};
444 std::vector<std::unique_ptr<Action>> actions{};
445 actions.emplace_back(std::move(action));
446 std::unique_ptr<Configuration> configuration =
447 std::make_unique<Configuration>(volts, std::move(actions));
448 Configuration* configurationPtr = configuration.get();
449
450 // Create Rail that contains Configuration
451 std::unique_ptr<Rail> rail =
452 std::make_unique<Rail>("vio2", std::move(configuration));
453 Rail* railPtr = rail.get();
454
455 // Create Device that contains Rail
456 std::unique_ptr<PresenceDetection> presenceDetection{};
457 std::unique_ptr<Configuration> deviceConfiguration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500458 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney39765002020-04-09 18:03:26 -0500459 std::vector<std::unique_ptr<Rail>> rails{};
460 rails.emplace_back(std::move(rail));
461 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800462 "reg1", true,
463 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarney39765002020-04-09 18:03:26 -0500464 std::move(i2cInterface), std::move(presenceDetection),
Shawn McCarney32252592021-09-08 15:29:36 -0500465 std::move(deviceConfiguration), std::move(phaseFaultDetection),
466 std::move(rails));
Shawn McCarney39765002020-04-09 18:03:26 -0500467 Device* devicePtr = device.get();
468
469 // Create Chassis that contains Device
470 std::vector<std::unique_ptr<Device>> devices{};
471 devices.emplace_back(std::move(device));
472 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500473 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Shawn McCarney39765002020-04-09 18:03:26 -0500474 Chassis* chassisPtr = chassis.get();
475
476 // Create System that contains Chassis
477 std::vector<std::unique_ptr<Rule>> rules{};
478 std::vector<std::unique_ptr<Chassis>> chassisVec{};
479 chassisVec.emplace_back(std::move(chassis));
480 System system{std::move(rules), std::move(chassisVec)};
481
482 // Execute Configuration
Bob King23243f82020-07-29 10:38:57 +0800483 configurationPtr->execute(services, system, *chassisPtr, *devicePtr,
484 *railPtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500485 }
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -0500486}
487
488TEST(ConfigurationTests, GetActions)
489{
490 std::optional<double> volts{1.3};
491
492 std::vector<std::unique_ptr<Action>> actions{};
493
494 MockAction* action1 = new MockAction{};
495 actions.push_back(std::unique_ptr<MockAction>{action1});
496
497 MockAction* action2 = new MockAction{};
498 actions.push_back(std::unique_ptr<MockAction>{action2});
499
500 Configuration configuration(volts, std::move(actions));
501 EXPECT_EQ(configuration.getActions().size(), 2);
502 EXPECT_EQ(configuration.getActions()[0].get(), action1);
503 EXPECT_EQ(configuration.getActions()[1].get(), action2);
504}
505
506TEST(ConfigurationTests, GetVolts)
507{
508 // Test where volts value specified
509 {
510 std::optional<double> volts{3.2};
511
512 std::vector<std::unique_ptr<Action>> actions{};
513 actions.push_back(std::make_unique<MockAction>());
514
515 Configuration configuration(volts, std::move(actions));
516 EXPECT_EQ(configuration.getVolts().has_value(), true);
517 EXPECT_EQ(configuration.getVolts().value(), 3.2);
518 }
519
520 // Test where volts value not specified
521 {
522 std::optional<double> volts{};
523
524 std::vector<std::unique_ptr<Action>> actions{};
525 actions.push_back(std::make_unique<MockAction>());
526
527 Configuration configuration(volts, std::move(actions));
528 EXPECT_EQ(configuration.getVolts().has_value(), false);
529 }
530}