blob: 2f4ded6c17e91ff6f9904d13e734a1f873d34391 [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"
27#include "pmbus_utils.hpp"
28#include "pmbus_write_vout_command_action.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050029#include "presence_detection.hpp"
Shawn McCarney39765002020-04-09 18:03:26 -050030#include "rail.hpp"
Shawn McCarney779b9562020-04-13 17:05:45 -050031#include "rule.hpp"
Shawn McCarney39765002020-04-09 18:03:26 -050032#include "system.hpp"
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050033
Shawn McCarney779b9562020-04-13 17:05:45 -050034#include <cstdint>
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050035#include <memory>
36#include <optional>
37#include <utility>
38#include <vector>
39
Shawn McCarney39765002020-04-09 18:03:26 -050040#include <gmock/gmock.h>
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050041#include <gtest/gtest.h>
42
43using namespace phosphor::power::regulators;
Shawn McCarney39765002020-04-09 18:03:26 -050044using namespace phosphor::power::regulators::pmbus_utils;
45
Bob King5cfe5102020-07-30 16:26:18 +080046using ::testing::A;
Shawn McCarney81a2f902021-03-23 21:41:34 -050047using ::testing::Ref;
Shawn McCarney39765002020-04-09 18:03:26 -050048using ::testing::Return;
49using ::testing::Throw;
50using ::testing::TypedEq;
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050051
Shawn McCarneycb3f6a62021-04-30 10:54:30 -050052static const std::string chassisInvPath{
53 "/xyz/openbmc_project/inventory/system/chassis"};
54
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050055TEST(ConfigurationTests, Constructor)
56{
57 // Test where volts value specified
58 {
59 std::optional<double> volts{1.3};
60
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
65 Configuration configuration(volts, std::move(actions));
66 EXPECT_EQ(configuration.getVolts().has_value(), true);
67 EXPECT_EQ(configuration.getVolts().value(), 1.3);
68 EXPECT_EQ(configuration.getActions().size(), 2);
69 }
70
71 // Test where volts value not specified
72 {
73 std::optional<double> volts{};
74
75 std::vector<std::unique_ptr<Action>> actions{};
76 actions.push_back(std::make_unique<MockAction>());
77
78 Configuration configuration(volts, std::move(actions));
79 EXPECT_EQ(configuration.getVolts().has_value(), false);
80 EXPECT_EQ(configuration.getActions().size(), 1);
81 }
82}
83
Bob King5cfe5102020-07-30 16:26:18 +080084// Test for execute(Services&, System&, Chassis&, Device&)
Shawn McCarney39765002020-04-09 18:03:26 -050085TEST(ConfigurationTests, ExecuteForDevice)
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050086{
Shawn McCarney39765002020-04-09 18:03:26 -050087 // Test where works: Volts value not specified
88 {
Bob King5cfe5102020-07-30 16:26:18 +080089 // Create mock services. Expect logDebug() to be called.
Bob King23243f82020-07-29 10:38:57 +080090 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +080091 MockJournal& journal = services.getMockJournal();
92 EXPECT_CALL(journal, logDebug("Configuring vdd_reg")).Times(1);
93 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +080094
Shawn McCarney39765002020-04-09 18:03:26 -050095 // Create I2CWriteByteAction with register 0x7C and value 0x0A
96 std::unique_ptr<I2CWriteByteAction> action =
97 std::make_unique<I2CWriteByteAction>(0x7C, 0x0A);
98
99 // Create mock I2CInterface. Expect action to write 0x0A to 0x7C.
100 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
101 std::make_unique<i2c::MockedI2CInterface>();
102 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
103 EXPECT_CALL(*i2cInterface,
104 write(TypedEq<uint8_t>(0x7C), TypedEq<uint8_t>(0x0A)))
105 .Times(1);
106
107 // Create Configuration with no volts value specified
108 std::optional<double> volts{};
109 std::vector<std::unique_ptr<Action>> actions{};
110 actions.emplace_back(std::move(action));
111 std::unique_ptr<Configuration> configuration =
112 std::make_unique<Configuration>(volts, std::move(actions));
113 Configuration* configurationPtr = configuration.get();
114
115 // Create Device that contains Configuration
116 std::unique_ptr<PresenceDetection> presenceDetection{};
117 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800118 "vdd_reg", true,
119 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
Shawn McCarney39765002020-04-09 18:03:26 -0500120 std::move(i2cInterface), std::move(presenceDetection),
121 std::move(configuration));
122 Device* devicePtr = device.get();
123
124 // Create Chassis that contains Device
125 std::vector<std::unique_ptr<Device>> devices{};
126 devices.emplace_back(std::move(device));
127 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500128 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Shawn McCarney39765002020-04-09 18:03:26 -0500129 Chassis* chassisPtr = chassis.get();
130
131 // Create System that contains Chassis
132 std::vector<std::unique_ptr<Rule>> rules{};
133 std::vector<std::unique_ptr<Chassis>> chassisVec{};
134 chassisVec.emplace_back(std::move(chassis));
135 System system{std::move(rules), std::move(chassisVec)};
136
137 // Execute Configuration
Bob King23243f82020-07-29 10:38:57 +0800138 configurationPtr->execute(services, system, *chassisPtr, *devicePtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500139 }
140
141 // Test where works: Volts value specified
142 {
Bob King5cfe5102020-07-30 16:26:18 +0800143 // Create mock services. Expect logDebug() to be called.
Bob King23243f82020-07-29 10:38:57 +0800144 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800145 MockJournal& journal = services.getMockJournal();
146 EXPECT_CALL(journal, logDebug("Configuring vdd_reg: volts=1.300000"))
147 .Times(1);
148 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800149
Shawn McCarney39765002020-04-09 18:03:26 -0500150 // Create PMBusWriteVoutCommandAction. Do not specify a volts value
151 // because it will get a value of 1.3V from the
152 // ActionEnvironment/Configuration. Specify a -8 exponent.
153 // Linear format volts value = (1.3 / 2^(-8)) = 332.8 = 333 = 0x014D.
154 std::optional<double> volts{};
155 std::unique_ptr<PMBusWriteVoutCommandAction> action =
156 std::make_unique<PMBusWriteVoutCommandAction>(
157 volts, pmbus_utils::VoutDataFormat::linear, -8, false);
158
159 // Create mock I2CInterface. Expect action to write 0x014D to
160 // VOUT_COMMAND (command/register 0x21).
161 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
162 std::make_unique<i2c::MockedI2CInterface>();
163 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
164 EXPECT_CALL(*i2cInterface,
165 write(TypedEq<uint8_t>(0x21), TypedEq<uint16_t>(0x014D)))
166 .Times(1);
167
168 // Create Configuration with volts value 1.3V
169 std::vector<std::unique_ptr<Action>> actions{};
170 actions.emplace_back(std::move(action));
171 std::unique_ptr<Configuration> configuration =
172 std::make_unique<Configuration>(1.3, std::move(actions));
173 Configuration* configurationPtr = configuration.get();
174
175 // Create Device that contains Configuration
176 std::unique_ptr<PresenceDetection> presenceDetection{};
177 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800178 "vdd_reg", true,
179 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
Shawn McCarney39765002020-04-09 18:03:26 -0500180 std::move(i2cInterface), std::move(presenceDetection),
181 std::move(configuration));
182 Device* devicePtr = device.get();
183
184 // Create Chassis that contains Device
185 std::vector<std::unique_ptr<Device>> devices{};
186 devices.emplace_back(std::move(device));
187 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500188 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Shawn McCarney39765002020-04-09 18:03:26 -0500189 Chassis* chassisPtr = chassis.get();
190
191 // Create System that contains Chassis
192 std::vector<std::unique_ptr<Rule>> rules{};
193 std::vector<std::unique_ptr<Chassis>> chassisVec{};
194 chassisVec.emplace_back(std::move(chassis));
195 System system{std::move(rules), std::move(chassisVec)};
196
197 // Execute Configuration
Bob King23243f82020-07-29 10:38:57 +0800198 configurationPtr->execute(services, system, *chassisPtr, *devicePtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500199 }
200
201 // Test where fails
202 {
Shawn McCarney81a2f902021-03-23 21:41:34 -0500203 // Create mock services. Expect logDebug(), logError(), and
204 // logI2CError() to be called.
Bob King23243f82020-07-29 10:38:57 +0800205 MockServices services{};
Shawn McCarney81a2f902021-03-23 21:41:34 -0500206 MockErrorLogging& errorLogging = services.getMockErrorLogging();
Bob King5cfe5102020-07-30 16:26:18 +0800207 MockJournal& journal = services.getMockJournal();
208 std::vector<std::string> expectedErrMessagesException{
209 "I2CException: Failed to write byte: bus /dev/i2c-1, addr 0x70",
210 "ActionError: i2c_write_byte: { register: 0x7C, value: 0xA, mask: "
211 "0xFF }"};
212 EXPECT_CALL(journal, logDebug("Configuring vdd_reg")).Times(1);
213 EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
214 EXPECT_CALL(journal, logError("Unable to configure vdd_reg")).Times(1);
Shawn McCarney81a2f902021-03-23 21:41:34 -0500215 EXPECT_CALL(errorLogging,
216 logI2CError(Entry::Level::Warning, Ref(journal),
217 "/dev/i2c-1", 0x70, 0))
218 .Times(1);
Bob King23243f82020-07-29 10:38:57 +0800219
Shawn McCarney39765002020-04-09 18:03:26 -0500220 // Create I2CWriteByteAction with register 0x7C and value 0x0A
221 std::unique_ptr<I2CWriteByteAction> action =
222 std::make_unique<I2CWriteByteAction>(0x7C, 0x0A);
223
224 // Create mock I2CInterface. write() throws an I2CException.
225 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
226 std::make_unique<i2c::MockedI2CInterface>();
227 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
228 EXPECT_CALL(*i2cInterface,
229 write(TypedEq<uint8_t>(0x7C), TypedEq<uint8_t>(0x0A)))
230 .Times(1)
231 .WillOnce(Throw(
232 i2c::I2CException{"Failed to write byte", "/dev/i2c-1", 0x70}));
233
234 // Create Configuration with no volts value specified
235 std::optional<double> volts{};
236 std::vector<std::unique_ptr<Action>> actions{};
237 actions.emplace_back(std::move(action));
238 std::unique_ptr<Configuration> configuration =
239 std::make_unique<Configuration>(volts, std::move(actions));
240 Configuration* configurationPtr = configuration.get();
241
242 // Create Device that contains Configuration
243 std::unique_ptr<PresenceDetection> presenceDetection{};
244 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800245 "vdd_reg", true,
246 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
Shawn McCarney39765002020-04-09 18:03:26 -0500247 std::move(i2cInterface), std::move(presenceDetection),
248 std::move(configuration));
249 Device* devicePtr = device.get();
250
251 // Create Chassis that contains Device
252 std::vector<std::unique_ptr<Device>> devices{};
253 devices.emplace_back(std::move(device));
254 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500255 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Shawn McCarney39765002020-04-09 18:03:26 -0500256 Chassis* chassisPtr = chassis.get();
257
258 // Create System that contains Chassis
259 std::vector<std::unique_ptr<Rule>> rules{};
260 std::vector<std::unique_ptr<Chassis>> chassisVec{};
261 chassisVec.emplace_back(std::move(chassis));
262 System system{std::move(rules), std::move(chassisVec)};
263
264 // Execute Configuration
Bob King23243f82020-07-29 10:38:57 +0800265 configurationPtr->execute(services, system, *chassisPtr, *devicePtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500266 }
267}
268
Bob King5cfe5102020-07-30 16:26:18 +0800269// Test for execute(Services&, System&, Chassis&, Device&, Rail&)
Shawn McCarney39765002020-04-09 18:03:26 -0500270TEST(ConfigurationTests, ExecuteForRail)
271{
272 // Test where works: Volts value not specified
273 {
Bob King5cfe5102020-07-30 16:26:18 +0800274 // Create mock services. Expect logDebug() to be called.
Bob King23243f82020-07-29 10:38:57 +0800275 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800276 MockJournal& journal = services.getMockJournal();
277 EXPECT_CALL(journal, logDebug("Configuring vio2")).Times(1);
278 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800279
Shawn McCarney39765002020-04-09 18:03:26 -0500280 // Create I2CWriteByteAction with register 0x7C and value 0x0A
281 std::unique_ptr<I2CWriteByteAction> action =
282 std::make_unique<I2CWriteByteAction>(0x7C, 0x0A);
283
284 // Create mock I2CInterface. Expect action to write 0x0A to 0x7C.
285 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
286 std::make_unique<i2c::MockedI2CInterface>();
287 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
288 EXPECT_CALL(*i2cInterface,
289 write(TypedEq<uint8_t>(0x7C), TypedEq<uint8_t>(0x0A)))
290 .Times(1);
291
292 // Create Configuration with no volts value specified
293 std::optional<double> volts{};
294 std::vector<std::unique_ptr<Action>> actions{};
295 actions.emplace_back(std::move(action));
296 std::unique_ptr<Configuration> configuration =
297 std::make_unique<Configuration>(volts, std::move(actions));
298 Configuration* configurationPtr = configuration.get();
299
300 // Create Rail that contains Configuration
301 std::unique_ptr<Rail> rail =
302 std::make_unique<Rail>("vio2", std::move(configuration));
303 Rail* railPtr = rail.get();
304
305 // Create Device that contains Rail
306 std::unique_ptr<PresenceDetection> presenceDetection{};
307 std::unique_ptr<Configuration> deviceConfiguration{};
308 std::vector<std::unique_ptr<Rail>> rails{};
309 rails.emplace_back(std::move(rail));
310 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800311 "reg1", true,
312 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarney39765002020-04-09 18:03:26 -0500313 std::move(i2cInterface), std::move(presenceDetection),
314 std::move(deviceConfiguration), std::move(rails));
315 Device* devicePtr = device.get();
316
317 // Create Chassis that contains Device
318 std::vector<std::unique_ptr<Device>> devices{};
319 devices.emplace_back(std::move(device));
320 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500321 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Shawn McCarney39765002020-04-09 18:03:26 -0500322 Chassis* chassisPtr = chassis.get();
323
324 // Create System that contains Chassis
325 std::vector<std::unique_ptr<Rule>> rules{};
326 std::vector<std::unique_ptr<Chassis>> chassisVec{};
327 chassisVec.emplace_back(std::move(chassis));
328 System system{std::move(rules), std::move(chassisVec)};
329
330 // Execute Configuration
Bob King23243f82020-07-29 10:38:57 +0800331 configurationPtr->execute(services, system, *chassisPtr, *devicePtr,
332 *railPtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500333 }
334
335 // Test where works: Volts value specified
336 {
Bob King5cfe5102020-07-30 16:26:18 +0800337 // Create mock services. Expect logDebug() to be called.
Bob King23243f82020-07-29 10:38:57 +0800338 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800339 MockJournal& journal = services.getMockJournal();
340 EXPECT_CALL(journal, logDebug("Configuring vio2: volts=1.300000"))
341 .Times(1);
342 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800343
Shawn McCarney39765002020-04-09 18:03:26 -0500344 // Create PMBusWriteVoutCommandAction. Do not specify a volts value
345 // because it will get a value of 1.3V from the
346 // ActionEnvironment/Configuration. Specify a -8 exponent.
347 // Linear format volts value = (1.3 / 2^(-8)) = 332.8 = 333 = 0x014D.
348 std::optional<double> volts{};
349 std::unique_ptr<PMBusWriteVoutCommandAction> action =
350 std::make_unique<PMBusWriteVoutCommandAction>(
351 volts, pmbus_utils::VoutDataFormat::linear, -8, false);
352
353 // Create mock I2CInterface. Expect action to write 0x014D to
354 // VOUT_COMMAND (command/register 0x21).
355 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
356 std::make_unique<i2c::MockedI2CInterface>();
357 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
358 EXPECT_CALL(*i2cInterface,
359 write(TypedEq<uint8_t>(0x21), TypedEq<uint16_t>(0x014D)))
360 .Times(1);
361
362 // Create Configuration with volts value 1.3V
363 std::vector<std::unique_ptr<Action>> actions{};
364 actions.emplace_back(std::move(action));
365 std::unique_ptr<Configuration> configuration =
366 std::make_unique<Configuration>(1.3, std::move(actions));
367 Configuration* configurationPtr = configuration.get();
368
369 // Create Rail that contains Configuration
370 std::unique_ptr<Rail> rail =
371 std::make_unique<Rail>("vio2", std::move(configuration));
372 Rail* railPtr = rail.get();
373
374 // Create Device that contains Rail
375 std::unique_ptr<PresenceDetection> presenceDetection{};
376 std::unique_ptr<Configuration> deviceConfiguration{};
377 std::vector<std::unique_ptr<Rail>> rails{};
378 rails.emplace_back(std::move(rail));
379 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800380 "reg1", true,
381 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarney39765002020-04-09 18:03:26 -0500382 std::move(i2cInterface), std::move(presenceDetection),
383 std::move(deviceConfiguration), std::move(rails));
384 Device* devicePtr = device.get();
385
386 // Create Chassis that contains Device
387 std::vector<std::unique_ptr<Device>> devices{};
388 devices.emplace_back(std::move(device));
389 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500390 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Shawn McCarney39765002020-04-09 18:03:26 -0500391 Chassis* chassisPtr = chassis.get();
392
393 // Create System that contains Chassis
394 std::vector<std::unique_ptr<Rule>> rules{};
395 std::vector<std::unique_ptr<Chassis>> chassisVec{};
396 chassisVec.emplace_back(std::move(chassis));
397 System system{std::move(rules), std::move(chassisVec)};
398
399 // Execute Configuration
Bob King23243f82020-07-29 10:38:57 +0800400 configurationPtr->execute(services, system, *chassisPtr, *devicePtr,
401 *railPtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500402 }
403
404 // Test where fails
405 {
Shawn McCarney81a2f902021-03-23 21:41:34 -0500406 // Create mock services. Expect logDebug(), logError(), and logI2CError
407 // to be called.
Bob King23243f82020-07-29 10:38:57 +0800408 MockServices services{};
Shawn McCarney81a2f902021-03-23 21:41:34 -0500409 MockErrorLogging& errorLogging = services.getMockErrorLogging();
Bob King5cfe5102020-07-30 16:26:18 +0800410 MockJournal& journal = services.getMockJournal();
411 std::vector<std::string> expectedErrMessagesException{
412 "I2CException: Failed to write byte: bus /dev/i2c-1, addr 0x70",
413 "ActionError: i2c_write_byte: { register: 0x7C, value: 0xA, mask: "
414 "0xFF }"};
415 EXPECT_CALL(journal, logDebug("Configuring vio2")).Times(1);
416 EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
417 EXPECT_CALL(journal, logError("Unable to configure vio2")).Times(1);
Shawn McCarney81a2f902021-03-23 21:41:34 -0500418 EXPECT_CALL(errorLogging,
419 logI2CError(Entry::Level::Warning, Ref(journal),
420 "/dev/i2c-1", 0x70, 0))
421 .Times(1);
Bob King23243f82020-07-29 10:38:57 +0800422
Shawn McCarney39765002020-04-09 18:03:26 -0500423 // Create I2CWriteByteAction with register 0x7C and value 0x0A
424 std::unique_ptr<I2CWriteByteAction> action =
425 std::make_unique<I2CWriteByteAction>(0x7C, 0x0A);
426
427 // Create mock I2CInterface. write() throws an I2CException.
428 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
429 std::make_unique<i2c::MockedI2CInterface>();
430 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
431 EXPECT_CALL(*i2cInterface,
432 write(TypedEq<uint8_t>(0x7C), TypedEq<uint8_t>(0x0A)))
433 .Times(1)
434 .WillOnce(Throw(
435 i2c::I2CException{"Failed to write byte", "/dev/i2c-1", 0x70}));
436
437 // Create Configuration with no volts value specified
438 std::optional<double> volts{};
439 std::vector<std::unique_ptr<Action>> actions{};
440 actions.emplace_back(std::move(action));
441 std::unique_ptr<Configuration> configuration =
442 std::make_unique<Configuration>(volts, std::move(actions));
443 Configuration* configurationPtr = configuration.get();
444
445 // Create Rail that contains Configuration
446 std::unique_ptr<Rail> rail =
447 std::make_unique<Rail>("vio2", std::move(configuration));
448 Rail* railPtr = rail.get();
449
450 // Create Device that contains Rail
451 std::unique_ptr<PresenceDetection> presenceDetection{};
452 std::unique_ptr<Configuration> deviceConfiguration{};
453 std::vector<std::unique_ptr<Rail>> rails{};
454 rails.emplace_back(std::move(rail));
455 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800456 "reg1", true,
457 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarney39765002020-04-09 18:03:26 -0500458 std::move(i2cInterface), std::move(presenceDetection),
459 std::move(deviceConfiguration), std::move(rails));
460 Device* devicePtr = device.get();
461
462 // Create Chassis that contains Device
463 std::vector<std::unique_ptr<Device>> devices{};
464 devices.emplace_back(std::move(device));
465 std::unique_ptr<Chassis> chassis =
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500466 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices));
Shawn McCarney39765002020-04-09 18:03:26 -0500467 Chassis* chassisPtr = chassis.get();
468
469 // Create System that contains Chassis
470 std::vector<std::unique_ptr<Rule>> rules{};
471 std::vector<std::unique_ptr<Chassis>> chassisVec{};
472 chassisVec.emplace_back(std::move(chassis));
473 System system{std::move(rules), std::move(chassisVec)};
474
475 // Execute Configuration
Bob King23243f82020-07-29 10:38:57 +0800476 configurationPtr->execute(services, system, *chassisPtr, *devicePtr,
477 *railPtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500478 }
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -0500479}
480
481TEST(ConfigurationTests, GetActions)
482{
483 std::optional<double> volts{1.3};
484
485 std::vector<std::unique_ptr<Action>> actions{};
486
487 MockAction* action1 = new MockAction{};
488 actions.push_back(std::unique_ptr<MockAction>{action1});
489
490 MockAction* action2 = new MockAction{};
491 actions.push_back(std::unique_ptr<MockAction>{action2});
492
493 Configuration configuration(volts, std::move(actions));
494 EXPECT_EQ(configuration.getActions().size(), 2);
495 EXPECT_EQ(configuration.getActions()[0].get(), action1);
496 EXPECT_EQ(configuration.getActions()[1].get(), action2);
497}
498
499TEST(ConfigurationTests, GetVolts)
500{
501 // Test where volts value specified
502 {
503 std::optional<double> volts{3.2};
504
505 std::vector<std::unique_ptr<Action>> actions{};
506 actions.push_back(std::make_unique<MockAction>());
507
508 Configuration configuration(volts, std::move(actions));
509 EXPECT_EQ(configuration.getVolts().has_value(), true);
510 EXPECT_EQ(configuration.getVolts().value(), 3.2);
511 }
512
513 // Test where volts value not specified
514 {
515 std::optional<double> volts{};
516
517 std::vector<std::unique_ptr<Action>> actions{};
518 actions.push_back(std::make_unique<MockAction>());
519
520 Configuration configuration(volts, std::move(actions));
521 EXPECT_EQ(configuration.getVolts().has_value(), false);
522 }
523}