blob: 93f1be8d8d4eb4cf3eb346e7fdbab970e77d6988 [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"
22#include "journal.hpp"
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050023#include "mock_action.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
46using ::testing::Return;
47using ::testing::Throw;
48using ::testing::TypedEq;
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050049
50TEST(ConfigurationTests, Constructor)
51{
52 // Test where volts value specified
53 {
54 std::optional<double> volts{1.3};
55
56 std::vector<std::unique_ptr<Action>> actions{};
57 actions.push_back(std::make_unique<MockAction>());
58 actions.push_back(std::make_unique<MockAction>());
59
60 Configuration configuration(volts, std::move(actions));
61 EXPECT_EQ(configuration.getVolts().has_value(), true);
62 EXPECT_EQ(configuration.getVolts().value(), 1.3);
63 EXPECT_EQ(configuration.getActions().size(), 2);
64 }
65
66 // Test where volts value not specified
67 {
68 std::optional<double> volts{};
69
70 std::vector<std::unique_ptr<Action>> actions{};
71 actions.push_back(std::make_unique<MockAction>());
72
73 Configuration configuration(volts, std::move(actions));
74 EXPECT_EQ(configuration.getVolts().has_value(), false);
75 EXPECT_EQ(configuration.getActions().size(), 1);
76 }
77}
78
Shawn McCarney39765002020-04-09 18:03:26 -050079// Test for execute(System&, Chassis&, Device&)
80TEST(ConfigurationTests, ExecuteForDevice)
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -050081{
Shawn McCarney39765002020-04-09 18:03:26 -050082 // Test where works: Volts value not specified
83 {
Bob King23243f82020-07-29 10:38:57 +080084 // Create mock services.
85 MockServices services{};
86
Shawn McCarney39765002020-04-09 18:03:26 -050087 // Create I2CWriteByteAction with register 0x7C and value 0x0A
88 std::unique_ptr<I2CWriteByteAction> action =
89 std::make_unique<I2CWriteByteAction>(0x7C, 0x0A);
90
91 // Create mock I2CInterface. Expect action to write 0x0A to 0x7C.
92 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
93 std::make_unique<i2c::MockedI2CInterface>();
94 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
95 EXPECT_CALL(*i2cInterface,
96 write(TypedEq<uint8_t>(0x7C), TypedEq<uint8_t>(0x0A)))
97 .Times(1);
98
99 // Create Configuration with no volts value specified
100 std::optional<double> volts{};
101 std::vector<std::unique_ptr<Action>> actions{};
102 actions.emplace_back(std::move(action));
103 std::unique_ptr<Configuration> configuration =
104 std::make_unique<Configuration>(volts, std::move(actions));
105 Configuration* configurationPtr = configuration.get();
106
107 // Create Device that contains Configuration
108 std::unique_ptr<PresenceDetection> presenceDetection{};
109 std::unique_ptr<Device> device = std::make_unique<Device>(
110 "vdd_reg", true, "/system/chassis/motherboard/reg2",
111 std::move(i2cInterface), std::move(presenceDetection),
112 std::move(configuration));
113 Device* devicePtr = device.get();
114
115 // Create Chassis that contains Device
116 std::vector<std::unique_ptr<Device>> devices{};
117 devices.emplace_back(std::move(device));
118 std::unique_ptr<Chassis> chassis =
119 std::make_unique<Chassis>(1, std::move(devices));
120 Chassis* chassisPtr = chassis.get();
121
122 // Create System that contains Chassis
123 std::vector<std::unique_ptr<Rule>> rules{};
124 std::vector<std::unique_ptr<Chassis>> chassisVec{};
125 chassisVec.emplace_back(std::move(chassis));
126 System system{std::move(rules), std::move(chassisVec)};
127
128 // Execute Configuration
129 journal::clear();
Bob King23243f82020-07-29 10:38:57 +0800130 configurationPtr->execute(services, system, *chassisPtr, *devicePtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500131 std::vector<std::string> expectedDebugMessages{"Configuring vdd_reg"};
132 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
133 EXPECT_EQ(journal::getErrMessages().size(), 0);
134 }
135
136 // Test where works: Volts value specified
137 {
Bob King23243f82020-07-29 10:38:57 +0800138 // Create mock services.
139 MockServices services{};
140
Shawn McCarney39765002020-04-09 18:03:26 -0500141 // Create PMBusWriteVoutCommandAction. Do not specify a volts value
142 // because it will get a value of 1.3V from the
143 // ActionEnvironment/Configuration. Specify a -8 exponent.
144 // Linear format volts value = (1.3 / 2^(-8)) = 332.8 = 333 = 0x014D.
145 std::optional<double> volts{};
146 std::unique_ptr<PMBusWriteVoutCommandAction> action =
147 std::make_unique<PMBusWriteVoutCommandAction>(
148 volts, pmbus_utils::VoutDataFormat::linear, -8, false);
149
150 // Create mock I2CInterface. Expect action to write 0x014D to
151 // VOUT_COMMAND (command/register 0x21).
152 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
153 std::make_unique<i2c::MockedI2CInterface>();
154 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
155 EXPECT_CALL(*i2cInterface,
156 write(TypedEq<uint8_t>(0x21), TypedEq<uint16_t>(0x014D)))
157 .Times(1);
158
159 // Create Configuration with volts value 1.3V
160 std::vector<std::unique_ptr<Action>> actions{};
161 actions.emplace_back(std::move(action));
162 std::unique_ptr<Configuration> configuration =
163 std::make_unique<Configuration>(1.3, std::move(actions));
164 Configuration* configurationPtr = configuration.get();
165
166 // Create Device that contains Configuration
167 std::unique_ptr<PresenceDetection> presenceDetection{};
168 std::unique_ptr<Device> device = std::make_unique<Device>(
169 "vdd_reg", true, "/system/chassis/motherboard/reg2",
170 std::move(i2cInterface), std::move(presenceDetection),
171 std::move(configuration));
172 Device* devicePtr = device.get();
173
174 // Create Chassis that contains Device
175 std::vector<std::unique_ptr<Device>> devices{};
176 devices.emplace_back(std::move(device));
177 std::unique_ptr<Chassis> chassis =
178 std::make_unique<Chassis>(1, std::move(devices));
179 Chassis* chassisPtr = chassis.get();
180
181 // Create System that contains Chassis
182 std::vector<std::unique_ptr<Rule>> rules{};
183 std::vector<std::unique_ptr<Chassis>> chassisVec{};
184 chassisVec.emplace_back(std::move(chassis));
185 System system{std::move(rules), std::move(chassisVec)};
186
187 // Execute Configuration
188 journal::clear();
Bob King23243f82020-07-29 10:38:57 +0800189 configurationPtr->execute(services, system, *chassisPtr, *devicePtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500190 std::vector<std::string> expectedDebugMessages{
191 "Configuring vdd_reg: volts=1.300000"};
192 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
193 EXPECT_EQ(journal::getErrMessages().size(), 0);
194 }
195
196 // Test where fails
197 {
Bob King23243f82020-07-29 10:38:57 +0800198 // Create mock services.
199 MockServices services{};
200
Shawn McCarney39765002020-04-09 18:03:26 -0500201 // Create I2CWriteByteAction with register 0x7C and value 0x0A
202 std::unique_ptr<I2CWriteByteAction> action =
203 std::make_unique<I2CWriteByteAction>(0x7C, 0x0A);
204
205 // Create mock I2CInterface. write() throws an I2CException.
206 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
207 std::make_unique<i2c::MockedI2CInterface>();
208 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
209 EXPECT_CALL(*i2cInterface,
210 write(TypedEq<uint8_t>(0x7C), TypedEq<uint8_t>(0x0A)))
211 .Times(1)
212 .WillOnce(Throw(
213 i2c::I2CException{"Failed to write byte", "/dev/i2c-1", 0x70}));
214
215 // Create Configuration with no volts value specified
216 std::optional<double> volts{};
217 std::vector<std::unique_ptr<Action>> actions{};
218 actions.emplace_back(std::move(action));
219 std::unique_ptr<Configuration> configuration =
220 std::make_unique<Configuration>(volts, std::move(actions));
221 Configuration* configurationPtr = configuration.get();
222
223 // Create Device that contains Configuration
224 std::unique_ptr<PresenceDetection> presenceDetection{};
225 std::unique_ptr<Device> device = std::make_unique<Device>(
226 "vdd_reg", true, "/system/chassis/motherboard/reg2",
227 std::move(i2cInterface), std::move(presenceDetection),
228 std::move(configuration));
229 Device* devicePtr = device.get();
230
231 // Create Chassis that contains Device
232 std::vector<std::unique_ptr<Device>> devices{};
233 devices.emplace_back(std::move(device));
234 std::unique_ptr<Chassis> chassis =
235 std::make_unique<Chassis>(1, std::move(devices));
236 Chassis* chassisPtr = chassis.get();
237
238 // Create System that contains Chassis
239 std::vector<std::unique_ptr<Rule>> rules{};
240 std::vector<std::unique_ptr<Chassis>> chassisVec{};
241 chassisVec.emplace_back(std::move(chassis));
242 System system{std::move(rules), std::move(chassisVec)};
243
244 // Execute Configuration
245 journal::clear();
Bob King23243f82020-07-29 10:38:57 +0800246 configurationPtr->execute(services, system, *chassisPtr, *devicePtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500247 std::vector<std::string> expectedDebugMessages{"Configuring vdd_reg"};
248 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
249 std::vector<std::string> expectedErrMessages{
250 "I2CException: Failed to write byte: bus /dev/i2c-1, addr 0x70",
251 "ActionError: i2c_write_byte: { register: 0x7C, value: 0xA, mask: "
252 "0xFF }",
253 "Unable to configure vdd_reg"};
254 EXPECT_EQ(journal::getErrMessages(), expectedErrMessages);
255 }
256}
257
258// Test for execute(System&, Chassis&, Device&, Rail&)
259TEST(ConfigurationTests, ExecuteForRail)
260{
261 // Test where works: Volts value not specified
262 {
Bob King23243f82020-07-29 10:38:57 +0800263 // Create mock services.
264 MockServices services{};
265
Shawn McCarney39765002020-04-09 18:03:26 -0500266 // Create I2CWriteByteAction with register 0x7C and value 0x0A
267 std::unique_ptr<I2CWriteByteAction> action =
268 std::make_unique<I2CWriteByteAction>(0x7C, 0x0A);
269
270 // Create mock I2CInterface. Expect action to write 0x0A to 0x7C.
271 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
272 std::make_unique<i2c::MockedI2CInterface>();
273 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
274 EXPECT_CALL(*i2cInterface,
275 write(TypedEq<uint8_t>(0x7C), TypedEq<uint8_t>(0x0A)))
276 .Times(1);
277
278 // Create Configuration with no volts value specified
279 std::optional<double> volts{};
280 std::vector<std::unique_ptr<Action>> actions{};
281 actions.emplace_back(std::move(action));
282 std::unique_ptr<Configuration> configuration =
283 std::make_unique<Configuration>(volts, std::move(actions));
284 Configuration* configurationPtr = configuration.get();
285
286 // Create Rail that contains Configuration
287 std::unique_ptr<Rail> rail =
288 std::make_unique<Rail>("vio2", std::move(configuration));
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 // Execute Configuration
316 journal::clear();
Bob King23243f82020-07-29 10:38:57 +0800317 configurationPtr->execute(services, system, *chassisPtr, *devicePtr,
318 *railPtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500319 std::vector<std::string> expectedDebugMessages{"Configuring vio2"};
320 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
321 EXPECT_EQ(journal::getErrMessages().size(), 0);
322 }
323
324 // Test where works: Volts value specified
325 {
Bob King23243f82020-07-29 10:38:57 +0800326 // Create mock services.
327 MockServices services{};
328
Shawn McCarney39765002020-04-09 18:03:26 -0500329 // Create PMBusWriteVoutCommandAction. Do not specify a volts value
330 // because it will get a value of 1.3V from the
331 // ActionEnvironment/Configuration. Specify a -8 exponent.
332 // Linear format volts value = (1.3 / 2^(-8)) = 332.8 = 333 = 0x014D.
333 std::optional<double> volts{};
334 std::unique_ptr<PMBusWriteVoutCommandAction> action =
335 std::make_unique<PMBusWriteVoutCommandAction>(
336 volts, pmbus_utils::VoutDataFormat::linear, -8, false);
337
338 // Create mock I2CInterface. Expect action to write 0x014D to
339 // VOUT_COMMAND (command/register 0x21).
340 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
341 std::make_unique<i2c::MockedI2CInterface>();
342 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
343 EXPECT_CALL(*i2cInterface,
344 write(TypedEq<uint8_t>(0x21), TypedEq<uint16_t>(0x014D)))
345 .Times(1);
346
347 // Create Configuration with volts value 1.3V
348 std::vector<std::unique_ptr<Action>> actions{};
349 actions.emplace_back(std::move(action));
350 std::unique_ptr<Configuration> configuration =
351 std::make_unique<Configuration>(1.3, std::move(actions));
352 Configuration* configurationPtr = configuration.get();
353
354 // Create Rail that contains Configuration
355 std::unique_ptr<Rail> rail =
356 std::make_unique<Rail>("vio2", std::move(configuration));
357 Rail* railPtr = rail.get();
358
359 // Create Device that contains Rail
360 std::unique_ptr<PresenceDetection> presenceDetection{};
361 std::unique_ptr<Configuration> deviceConfiguration{};
362 std::vector<std::unique_ptr<Rail>> rails{};
363 rails.emplace_back(std::move(rail));
364 std::unique_ptr<Device> device = std::make_unique<Device>(
365 "reg1", true, "/system/chassis/motherboard/reg1",
366 std::move(i2cInterface), std::move(presenceDetection),
367 std::move(deviceConfiguration), std::move(rails));
368 Device* devicePtr = device.get();
369
370 // Create Chassis that contains Device
371 std::vector<std::unique_ptr<Device>> devices{};
372 devices.emplace_back(std::move(device));
373 std::unique_ptr<Chassis> chassis =
374 std::make_unique<Chassis>(1, std::move(devices));
375 Chassis* chassisPtr = chassis.get();
376
377 // Create System that contains Chassis
378 std::vector<std::unique_ptr<Rule>> rules{};
379 std::vector<std::unique_ptr<Chassis>> chassisVec{};
380 chassisVec.emplace_back(std::move(chassis));
381 System system{std::move(rules), std::move(chassisVec)};
382
383 // Execute Configuration
384 journal::clear();
Bob King23243f82020-07-29 10:38:57 +0800385 configurationPtr->execute(services, system, *chassisPtr, *devicePtr,
386 *railPtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500387 std::vector<std::string> expectedDebugMessages{
388 "Configuring vio2: volts=1.300000"};
389 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
390 EXPECT_EQ(journal::getErrMessages().size(), 0);
391 }
392
393 // Test where fails
394 {
Bob King23243f82020-07-29 10:38:57 +0800395 // Create mock services.
396 MockServices services{};
397
Shawn McCarney39765002020-04-09 18:03:26 -0500398 // Create I2CWriteByteAction with register 0x7C and value 0x0A
399 std::unique_ptr<I2CWriteByteAction> action =
400 std::make_unique<I2CWriteByteAction>(0x7C, 0x0A);
401
402 // Create mock I2CInterface. write() throws an I2CException.
403 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
404 std::make_unique<i2c::MockedI2CInterface>();
405 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
406 EXPECT_CALL(*i2cInterface,
407 write(TypedEq<uint8_t>(0x7C), TypedEq<uint8_t>(0x0A)))
408 .Times(1)
409 .WillOnce(Throw(
410 i2c::I2CException{"Failed to write byte", "/dev/i2c-1", 0x70}));
411
412 // Create Configuration with no volts value specified
413 std::optional<double> volts{};
414 std::vector<std::unique_ptr<Action>> actions{};
415 actions.emplace_back(std::move(action));
416 std::unique_ptr<Configuration> configuration =
417 std::make_unique<Configuration>(volts, std::move(actions));
418 Configuration* configurationPtr = configuration.get();
419
420 // Create Rail that contains Configuration
421 std::unique_ptr<Rail> rail =
422 std::make_unique<Rail>("vio2", std::move(configuration));
423 Rail* railPtr = rail.get();
424
425 // Create Device that contains Rail
426 std::unique_ptr<PresenceDetection> presenceDetection{};
427 std::unique_ptr<Configuration> deviceConfiguration{};
428 std::vector<std::unique_ptr<Rail>> rails{};
429 rails.emplace_back(std::move(rail));
430 std::unique_ptr<Device> device = std::make_unique<Device>(
431 "reg1", true, "/system/chassis/motherboard/reg1",
432 std::move(i2cInterface), std::move(presenceDetection),
433 std::move(deviceConfiguration), std::move(rails));
434 Device* devicePtr = device.get();
435
436 // Create Chassis that contains Device
437 std::vector<std::unique_ptr<Device>> devices{};
438 devices.emplace_back(std::move(device));
439 std::unique_ptr<Chassis> chassis =
440 std::make_unique<Chassis>(1, std::move(devices));
441 Chassis* chassisPtr = chassis.get();
442
443 // Create System that contains Chassis
444 std::vector<std::unique_ptr<Rule>> rules{};
445 std::vector<std::unique_ptr<Chassis>> chassisVec{};
446 chassisVec.emplace_back(std::move(chassis));
447 System system{std::move(rules), std::move(chassisVec)};
448
449 // Execute Configuration
450 journal::clear();
Bob King23243f82020-07-29 10:38:57 +0800451 configurationPtr->execute(services, system, *chassisPtr, *devicePtr,
452 *railPtr);
Shawn McCarney39765002020-04-09 18:03:26 -0500453 std::vector<std::string> expectedDebugMessages{"Configuring vio2"};
454 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
455 std::vector<std::string> expectedErrMessages{
456 "I2CException: Failed to write byte: bus /dev/i2c-1, addr 0x70",
457 "ActionError: i2c_write_byte: { register: 0x7C, value: 0xA, mask: "
458 "0xFF }",
459 "Unable to configure vio2"};
460 EXPECT_EQ(journal::getErrMessages(), expectedErrMessages);
461 }
Shawn McCarneyd3a8aab2020-03-10 10:30:02 -0500462}
463
464TEST(ConfigurationTests, GetActions)
465{
466 std::optional<double> volts{1.3};
467
468 std::vector<std::unique_ptr<Action>> actions{};
469
470 MockAction* action1 = new MockAction{};
471 actions.push_back(std::unique_ptr<MockAction>{action1});
472
473 MockAction* action2 = new MockAction{};
474 actions.push_back(std::unique_ptr<MockAction>{action2});
475
476 Configuration configuration(volts, std::move(actions));
477 EXPECT_EQ(configuration.getActions().size(), 2);
478 EXPECT_EQ(configuration.getActions()[0].get(), action1);
479 EXPECT_EQ(configuration.getActions()[1].get(), action2);
480}
481
482TEST(ConfigurationTests, GetVolts)
483{
484 // Test where volts value specified
485 {
486 std::optional<double> volts{3.2};
487
488 std::vector<std::unique_ptr<Action>> actions{};
489 actions.push_back(std::make_unique<MockAction>());
490
491 Configuration configuration(volts, std::move(actions));
492 EXPECT_EQ(configuration.getVolts().has_value(), true);
493 EXPECT_EQ(configuration.getVolts().value(), 3.2);
494 }
495
496 // Test where volts value not specified
497 {
498 std::optional<double> volts{};
499
500 std::vector<std::unique_ptr<Action>> actions{};
501 actions.push_back(std::make_unique<MockAction>());
502
503 Configuration configuration(volts, std::move(actions));
504 EXPECT_EQ(configuration.getVolts().has_value(), false);
505 }
506}