blob: e04e150338eff27456ca801a57c0c359af6f752a [file] [log] [blame]
Shawn McCarneya8119f22020-03-02 16:20:18 -06001/**
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_environment.hpp"
17#include "action_error.hpp"
18#include "device.hpp"
19#include "i2c_interface.hpp"
20#include "id_map.hpp"
Bob King73eacee2020-10-23 13:58:02 +080021#include "mock_services.hpp"
Shawn McCarneya8119f22020-03-02 16:20:18 -060022#include "mocked_i2c_interface.hpp"
23#include "pmbus_error.hpp"
24#include "pmbus_utils.hpp"
25#include "pmbus_write_vout_command_action.hpp"
26#include "write_verification_error.hpp"
27
28#include <cstdint>
29#include <memory>
30#include <optional>
31#include <stdexcept>
32#include <string>
33#include <utility>
34
35#include <gmock/gmock.h>
36#include <gtest/gtest.h>
37
38using namespace phosphor::power::regulators;
39
40using ::testing::A;
41using ::testing::Return;
42using ::testing::SetArgReferee;
43using ::testing::Throw;
44using ::testing::TypedEq;
45
46TEST(PMBusWriteVoutCommandActionTests, Constructor)
47{
48 // Test where works: Volts value and exponent value are specified
49 try
50 {
51 std::optional<double> volts{1.3};
52 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
53 std::optional<int8_t> exponent{-8};
54 bool isVerified{true};
55 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
56 EXPECT_EQ(action.getVolts().has_value(), true);
57 EXPECT_EQ(action.getVolts().value(), 1.3);
58 EXPECT_EQ(action.getFormat(), pmbus_utils::VoutDataFormat::linear);
59 EXPECT_EQ(action.getExponent().has_value(), true);
60 EXPECT_EQ(action.getExponent().value(), -8);
61 EXPECT_EQ(action.isVerified(), true);
62 }
63 catch (...)
64 {
65 ADD_FAILURE() << "Should not have caught exception.";
66 }
67
68 // Test where works: Volts value and exponent value are not specified
69 try
70 {
71 std::optional<double> volts{};
72 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
73 std::optional<int8_t> exponent{};
74 bool isVerified{false};
75 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
76 EXPECT_EQ(action.getVolts().has_value(), false);
77 EXPECT_EQ(action.getFormat(), pmbus_utils::VoutDataFormat::linear);
78 EXPECT_EQ(action.getExponent().has_value(), false);
79 EXPECT_EQ(action.isVerified(), false);
80 }
81 catch (...)
82 {
83 ADD_FAILURE() << "Should not have caught exception.";
84 }
85
86 // Test where fails: Data format is not linear
87 try
88 {
89 std::optional<double> volts{};
90 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::direct};
91 std::optional<int8_t> exponent{};
92 bool isVerified{false};
93 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
94 ADD_FAILURE() << "Should not have reached this line.";
95 }
96 catch (const std::invalid_argument& e)
97 {
98 EXPECT_STREQ(e.what(), "Unsupported data format specified");
99 }
100 catch (...)
101 {
102 ADD_FAILURE() << "Should not have caught exception.";
103 }
104}
105
106TEST(PMBusWriteVoutCommandActionTests, Execute)
107{
108 // Test where works: Volts value and exponent value defined in action;
109 // write is verified.
110 try
111 {
112 // Create mock I2CInterface. Expect action to do the following:
113 // * will not read from VOUT_MODE (command/register 0x20)
114 // * will write 0x014D to VOUT_COMMAND (command/register 0x21)
115 // * will read 0x014D from VOUT_COMMAND
116 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
117 std::make_unique<i2c::MockedI2CInterface>();
118 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
119 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint8_t&>())).Times(0);
120 EXPECT_CALL(*i2cInterface,
121 write(TypedEq<uint8_t>(0x21), TypedEq<uint16_t>(0x014D)))
122 .Times(1);
123 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x21), A<uint16_t&>()))
124 .Times(1)
125 .WillOnce(SetArgReferee<1>(0x014D));
126
Bob King73eacee2020-10-23 13:58:02 +0800127 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800128 Device device{
129 "reg1", true,
130 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
131 std::move(i2cInterface)};
Shawn McCarneya8119f22020-03-02 16:20:18 -0600132 IDMap idMap{};
133 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800134 MockServices services{};
135 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarneya8119f22020-03-02 16:20:18 -0600136
137 // Create and execute action
138 // Linear format volts value = (1.3 / 2^(-8)) = 332.8 = 333 = 0x014D
139 std::optional<double> volts{1.3};
140 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
141 std::optional<int8_t> exponent{-8};
142 bool isVerified{true};
143 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
144 EXPECT_EQ(action.execute(env), true);
145 }
146 catch (...)
147 {
148 ADD_FAILURE() << "Should not have caught exception.";
149 }
150
151 // Test where works: Volts value defined in ActionEnvironment; exponent
152 // value defined in VOUT_MODE; write is not verified.
153 try
154 {
155 // Create mock I2CInterface. Expect action to do the following:
156 // * will read 0b0001'0111 (linear format, -9 exponent) from VOUT_MODE
157 // * will write 0x069A to VOUT_COMMAND
158 // * will not read from VOUT_COMMAND
159 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
160 std::make_unique<i2c::MockedI2CInterface>();
161 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
162 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x20), A<uint8_t&>()))
163 .Times(1)
164 .WillOnce(SetArgReferee<1>(0b0001'0111));
165 EXPECT_CALL(*i2cInterface,
166 write(TypedEq<uint8_t>(0x21), TypedEq<uint16_t>(0x069A)))
167 .Times(1);
168 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint16_t&>())).Times(0);
169
Bob King73eacee2020-10-23 13:58:02 +0800170 // Create Device, IDMap, MockServices, and ActionEnvironment. Set
171 // volts value to 3.3 in ActionEnvironment.
Bob Kinga76898f2020-10-13 15:08:33 +0800172 Device device{
173 "reg1", true,
174 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
175 std::move(i2cInterface)};
Shawn McCarneya8119f22020-03-02 16:20:18 -0600176 IDMap idMap{};
177 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800178 MockServices services{};
179 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarneya8119f22020-03-02 16:20:18 -0600180 env.setVolts(3.3);
181
182 // Create and execute action
183 // Linear format volts value = (3.3 / 2^(-9)) = 1689.6 = 1690 = 0x069A
184 std::optional<double> volts{};
185 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
186 std::optional<int8_t> exponent{};
187 bool isVerified{false};
188 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
189 EXPECT_EQ(action.execute(env), true);
190 }
191 catch (...)
192 {
193 ADD_FAILURE() << "Should not have caught exception.";
194 }
195
196 // Test where fails: No volts value defined
197 try
198 {
Bob King73eacee2020-10-23 13:58:02 +0800199 // Create IDMap, MockServices, and ActionEnvironment
Shawn McCarneya8119f22020-03-02 16:20:18 -0600200 IDMap idMap{};
Bob King73eacee2020-10-23 13:58:02 +0800201 MockServices services{};
202 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarneya8119f22020-03-02 16:20:18 -0600203
204 // Create and execute action
205 std::optional<double> volts{};
206 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
207 std::optional<int8_t> exponent{-8};
208 bool isVerified{false};
209 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
210 action.execute(env);
211 ADD_FAILURE() << "Should not have reached this line.";
212 }
213 catch (const ActionError& e)
214 {
215 EXPECT_STREQ(
216 e.what(),
217 "ActionError: pmbus_write_vout_command: { format: linear, "
218 "exponent: -8, is_verified: false }: No volts value defined");
219 }
220 catch (...)
221 {
222 ADD_FAILURE() << "Should not have caught exception.";
223 }
224
225 // Test where fails: Unable to get I2C interface to current device
226 try
227 {
Bob King73eacee2020-10-23 13:58:02 +0800228 // Create IDMap, MockServices, and ActionEnvironment
Shawn McCarneya8119f22020-03-02 16:20:18 -0600229 IDMap idMap{};
Bob King73eacee2020-10-23 13:58:02 +0800230 MockServices services{};
231 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarneya8119f22020-03-02 16:20:18 -0600232
233 // Create and execute action
234 std::optional<double> volts{1.3};
235 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
236 std::optional<int8_t> exponent{-8};
237 bool isVerified{false};
238 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
239 action.execute(env);
240 ADD_FAILURE() << "Should not have reached this line.";
241 }
242 catch (const std::invalid_argument& e)
243 {
244 EXPECT_STREQ(e.what(), "Unable to find device with ID \"reg1\"");
245 }
246 catch (...)
247 {
248 ADD_FAILURE() << "Should not have caught exception.";
249 }
250
251 // Test where fails: Unable to read VOUT_MODE to get exponent
252 try
253 {
254 // Create mock I2CInterface. Expect action to do the following:
255 // * will try to read VOUT_MODE; exception will be thrown
256 // * will not write to VOUT_COMMAND due to exception
257 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
258 std::make_unique<i2c::MockedI2CInterface>();
259 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
260 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x20), A<uint8_t&>()))
261 .Times(1)
262 .WillOnce(Throw(
263 i2c::I2CException{"Failed to read byte", "/dev/i2c-1", 0x70}));
264 EXPECT_CALL(*i2cInterface, write(A<uint8_t>(), A<uint16_t>())).Times(0);
265
Bob King73eacee2020-10-23 13:58:02 +0800266 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800267 Device device{
268 "reg1", true,
269 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
270 std::move(i2cInterface)};
Shawn McCarneya8119f22020-03-02 16:20:18 -0600271 IDMap idMap{};
272 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800273 MockServices services{};
274 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarneya8119f22020-03-02 16:20:18 -0600275
276 // Create and execute action
277 std::optional<double> volts{3.3};
278 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
279 std::optional<int8_t> exponent{};
280 bool isVerified{false};
281 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
282 action.execute(env);
283 ADD_FAILURE() << "Should not have reached this line.";
284 }
285 catch (const ActionError& e)
286 {
287 EXPECT_STREQ(e.what(),
288 "ActionError: pmbus_write_vout_command: { volts: 3.3, "
289 "format: linear, is_verified: false }");
290 try
291 {
292 // Re-throw inner I2CException
293 std::rethrow_if_nested(e);
294 ADD_FAILURE() << "Should not have reached this line.";
295 }
296 catch (const i2c::I2CException& ie)
297 {
298 EXPECT_STREQ(
299 ie.what(),
300 "I2CException: Failed to read byte: bus /dev/i2c-1, addr 0x70");
301 }
302 catch (...)
303 {
304 ADD_FAILURE() << "Should not have caught exception.";
305 }
306 }
307 catch (...)
308 {
309 ADD_FAILURE() << "Should not have caught exception.";
310 }
311
312 // Test where fails: VOUT_MODE data format is not linear
313 try
314 {
315 // Create mock I2CInterface. Expect action to do the following:
316 // * will read 0b0010'0000 (vid data format) from VOUT_MODE
317 // * will not write to VOUT_COMMAND due to data format error
318 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
319 std::make_unique<i2c::MockedI2CInterface>();
320 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
321 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x20), A<uint8_t&>()))
322 .Times(1)
323 .WillOnce(SetArgReferee<1>(0b0010'0000));
324 EXPECT_CALL(*i2cInterface, write(A<uint8_t>(), A<uint16_t>())).Times(0);
325
Bob King73eacee2020-10-23 13:58:02 +0800326 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800327 Device device{
328 "reg1", true,
329 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
330 std::move(i2cInterface)};
Shawn McCarneya8119f22020-03-02 16:20:18 -0600331 IDMap idMap{};
332 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800333 MockServices services{};
334 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarneya8119f22020-03-02 16:20:18 -0600335
336 // Create and execute action
337 std::optional<double> volts{3.3};
338 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
339 std::optional<int8_t> exponent{};
340 bool isVerified{false};
341 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
342 action.execute(env);
343 ADD_FAILURE() << "Should not have reached this line.";
344 }
345 catch (const ActionError& e)
346 {
347 EXPECT_STREQ(e.what(),
348 "ActionError: pmbus_write_vout_command: { volts: 3.3, "
349 "format: linear, is_verified: false }");
350 try
351 {
352 // Re-throw inner PMBusError
353 std::rethrow_if_nested(e);
354 ADD_FAILURE() << "Should not have reached this line.";
355 }
356 catch (const PMBusError& pe)
357 {
358 EXPECT_STREQ(
359 pe.what(),
360 "PMBusError: VOUT_MODE contains unsupported data format");
Shawn McCarney5b819f42021-03-16 14:41:15 -0500361 EXPECT_EQ(pe.getDeviceID(), "reg1");
362 EXPECT_EQ(pe.getInventoryPath(), "/xyz/openbmc_project/inventory/"
363 "system/chassis/motherboard/reg1");
Shawn McCarneya8119f22020-03-02 16:20:18 -0600364 }
365 catch (...)
366 {
367 ADD_FAILURE() << "Should not have caught exception.";
368 }
369 }
370 catch (...)
371 {
372 ADD_FAILURE() << "Should not have caught exception.";
373 }
374
375 // Test where fails: Unable to write VOUT_COMMAND
376 try
377 {
378 // Create mock I2CInterface. Expect action to do the following:
379 // * will not read from VOUT_MODE
380 // * will try to write 0x014D to VOUT_COMMAND; exception will be thrown
381 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
382 std::make_unique<i2c::MockedI2CInterface>();
383 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
384 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint8_t&>())).Times(0);
385 EXPECT_CALL(*i2cInterface,
386 write(TypedEq<uint8_t>(0x21), TypedEq<uint16_t>(0x014D)))
387 .Times(1)
388 .WillOnce(Throw(i2c::I2CException{"Failed to write word data",
389 "/dev/i2c-1", 0x70}));
390
Bob King73eacee2020-10-23 13:58:02 +0800391 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800392 Device device{
393 "reg1", true,
394 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
395 std::move(i2cInterface)};
Shawn McCarneya8119f22020-03-02 16:20:18 -0600396 IDMap idMap{};
397 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800398 MockServices services{};
399 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarneya8119f22020-03-02 16:20:18 -0600400
401 // Create and execute action
402 // Linear format volts value = (1.3 / 2^(-8)) = 332.8 = 333 = 0x014D
403 std::optional<double> volts{1.3};
404 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
405 std::optional<int8_t> exponent{-8};
406 bool isVerified{false};
407 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
408 action.execute(env);
409 ADD_FAILURE() << "Should not have reached this line.";
410 }
411 catch (const ActionError& e)
412 {
413 EXPECT_STREQ(e.what(),
414 "ActionError: pmbus_write_vout_command: { volts: 1.3, "
415 "format: linear, exponent: -8, is_verified: false }");
416 try
417 {
418 // Re-throw inner I2CException
419 std::rethrow_if_nested(e);
420 ADD_FAILURE() << "Should not have reached this line.";
421 }
422 catch (const i2c::I2CException& ie)
423 {
424 EXPECT_STREQ(ie.what(), "I2CException: Failed to write word data: "
425 "bus /dev/i2c-1, addr 0x70");
426 }
427 catch (...)
428 {
429 ADD_FAILURE() << "Should not have caught exception.";
430 }
431 }
432 catch (...)
433 {
434 ADD_FAILURE() << "Should not have caught exception.";
435 }
436
437 // Test where fails: Unable to read VOUT_COMMAND
438 try
439 {
440 // Create mock I2CInterface. Expect action to do the following:
441 // * will not read from VOUT_MODE
442 // * will write 0x014D to VOUT_COMMAND
443 // * will try to read from VOUT_COMMAND; exception will be thrown
444 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
445 std::make_unique<i2c::MockedI2CInterface>();
446 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
447 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint8_t&>())).Times(0);
448 EXPECT_CALL(*i2cInterface,
449 write(TypedEq<uint8_t>(0x21), TypedEq<uint16_t>(0x014D)))
450 .Times(1);
451 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x21), A<uint16_t&>()))
452 .Times(1)
453 .WillOnce(Throw(i2c::I2CException{"Failed to read word data",
454 "/dev/i2c-1", 0x70}));
455
Bob King73eacee2020-10-23 13:58:02 +0800456 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800457 Device device{
458 "reg1", true,
459 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
460 std::move(i2cInterface)};
Shawn McCarneya8119f22020-03-02 16:20:18 -0600461 IDMap idMap{};
462 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800463 MockServices services{};
464 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarneya8119f22020-03-02 16:20:18 -0600465
466 // Create and execute action
467 // Linear format volts value = (1.3 / 2^(-8)) = 332.8 = 333 = 0x014D
468 std::optional<double> volts{1.3};
469 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
470 std::optional<int8_t> exponent{-8};
471 bool isVerified{true};
472 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
473 action.execute(env);
474 ADD_FAILURE() << "Should not have reached this line.";
475 }
476 catch (const ActionError& e)
477 {
478 EXPECT_STREQ(e.what(),
479 "ActionError: pmbus_write_vout_command: { volts: 1.3, "
480 "format: linear, exponent: -8, is_verified: true }");
481 try
482 {
483 // Re-throw inner I2CException
484 std::rethrow_if_nested(e);
485 ADD_FAILURE() << "Should not have reached this line.";
486 }
487 catch (const i2c::I2CException& ie)
488 {
489 EXPECT_STREQ(ie.what(), "I2CException: Failed to read word data: "
490 "bus /dev/i2c-1, addr 0x70");
491 }
492 catch (...)
493 {
494 ADD_FAILURE() << "Should not have caught exception.";
495 }
496 }
497 catch (...)
498 {
499 ADD_FAILURE() << "Should not have caught exception.";
500 }
501
502 // Test where fails: Write verification error
503 try
504 {
505 // Create mock I2CInterface. Expect action to do the following:
506 // * will not read from VOUT_MODE
507 // * will write 0x014D to VOUT_COMMAND
508 // * will read 0x014C from VOUT_COMMAND (not equal to 0x014D)
509 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
510 std::make_unique<i2c::MockedI2CInterface>();
511 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
512 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint8_t&>())).Times(0);
513 EXPECT_CALL(*i2cInterface,
514 write(TypedEq<uint8_t>(0x21), TypedEq<uint16_t>(0x014D)))
515 .Times(1);
516 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x21), A<uint16_t&>()))
517 .Times(1)
518 .WillOnce(SetArgReferee<1>(0x014C));
519
Bob King73eacee2020-10-23 13:58:02 +0800520 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800521 Device device{
522 "reg1", true,
523 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
524 std::move(i2cInterface)};
Shawn McCarneya8119f22020-03-02 16:20:18 -0600525 IDMap idMap{};
526 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800527 MockServices services{};
528 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarneya8119f22020-03-02 16:20:18 -0600529
530 // Create and execute action
531 // Linear format volts value = (1.3 / 2^(-8)) = 332.8 = 333 = 0x014D
532 std::optional<double> volts{1.3};
533 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
534 std::optional<int8_t> exponent{-8};
535 bool isVerified{true};
536 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
537 action.execute(env);
538 ADD_FAILURE() << "Should not have reached this line.";
539 }
540 catch (const ActionError& e)
541 {
542 EXPECT_STREQ(e.what(),
543 "ActionError: pmbus_write_vout_command: { volts: 1.3, "
544 "format: linear, exponent: -8, is_verified: true }");
545 try
546 {
547 // Re-throw inner WriteVerificationError
548 std::rethrow_if_nested(e);
549 ADD_FAILURE() << "Should not have reached this line.";
550 }
551 catch (const WriteVerificationError& we)
552 {
553 EXPECT_STREQ(
554 we.what(),
555 "WriteVerificationError: device: reg1, register: VOUT_COMMAND, "
556 "value_written: 0x14D, value_read: 0x14C");
Shawn McCarney36fc2612021-03-16 15:44:26 -0500557 EXPECT_EQ(we.getDeviceID(), "reg1");
558 EXPECT_EQ(we.getInventoryPath(), "/xyz/openbmc_project/inventory/"
559 "system/chassis/motherboard/reg1");
Shawn McCarneya8119f22020-03-02 16:20:18 -0600560 }
561 catch (...)
562 {
563 ADD_FAILURE() << "Should not have caught exception.";
564 }
565 }
566 catch (...)
567 {
568 ADD_FAILURE() << "Should not have caught exception.";
569 }
570}
571
572TEST(PMBusWriteVoutCommandActionTests, GetExponent)
573{
574 std::optional<double> volts{1.3};
575 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
576 bool isVerified{true};
577
578 // Exponent value was specified
579 {
580 std::optional<int8_t> exponent{-9};
581 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
582 EXPECT_EQ(action.getExponent().has_value(), true);
583 EXPECT_EQ(action.getExponent().value(), -9);
584 }
585
586 // Exponent value was not specified
587 {
588 std::optional<int8_t> exponent{};
589 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
590 EXPECT_EQ(action.getExponent().has_value(), false);
591 }
592}
593
594TEST(PMBusWriteVoutCommandActionTests, GetFormat)
595{
596 std::optional<double> volts{};
597 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
598 std::optional<int8_t> exponent{};
599 bool isVerified{false};
600 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
601 EXPECT_EQ(action.getFormat(), pmbus_utils::VoutDataFormat::linear);
602}
603
604TEST(PMBusWriteVoutCommandActionTests, GetVolts)
605{
606 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
607 std::optional<int8_t> exponent{-8};
608 bool isVerified{true};
609
610 // Volts value was specified
611 {
612 std::optional<double> volts{1.3};
613 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
614 EXPECT_EQ(action.getVolts().has_value(), true);
615 EXPECT_EQ(action.getVolts().value(), 1.3);
616 }
617
618 // Volts value was not specified
619 {
620 std::optional<double> volts{};
621 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
622 EXPECT_EQ(action.getVolts().has_value(), false);
623 }
624}
625
626TEST(PMBusWriteVoutCommandActionTests, IsVerified)
627{
628 std::optional<double> volts{1.3};
629 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
630 std::optional<int8_t> exponent{-8};
631 bool isVerified{true};
632 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
633 EXPECT_EQ(action.isVerified(), true);
634}
635
636TEST(PMBusWriteVoutCommandActionTests, ToString)
637{
638 // Test where volts value and exponent value are specified
639 {
640 std::optional<double> volts{1.3};
641 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
642 std::optional<int8_t> exponent{-8};
643 bool isVerified{true};
644 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
645 EXPECT_EQ(action.toString(),
646 "pmbus_write_vout_command: { volts: 1.3, format: linear, "
647 "exponent: -8, is_verified: true }");
648 }
649
650 // Test where volts value and exponent value are not specified
651 {
652 std::optional<double> volts{};
653 pmbus_utils::VoutDataFormat format{pmbus_utils::VoutDataFormat::linear};
654 std::optional<int8_t> exponent{};
655 bool isVerified{false};
656 PMBusWriteVoutCommandAction action{volts, format, exponent, isVerified};
657 EXPECT_EQ(
658 action.toString(),
659 "pmbus_write_vout_command: { format: linear, is_verified: false }");
660 }
661}