blob: 2e57ac2a17e16c659f29ae35df5229ca9226dee9 [file] [log] [blame]
Bob Kingd6820bb2020-04-28 15:37:02 +08001/**
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"
Bob King717d2da2020-06-02 11:11:15 +080017#include "action_error.hpp"
18#include "device.hpp"
Bob Kingd6820bb2020-04-28 15:37:02 +080019#include "i2c_interface.hpp"
Bob King717d2da2020-06-02 11:11:15 +080020#include "id_map.hpp"
Bob King73eacee2020-10-23 13:58:02 +080021#include "mock_services.hpp"
Bob King717d2da2020-06-02 11:11:15 +080022#include "mocked_i2c_interface.hpp"
23#include "pmbus_error.hpp"
Bob Kingd6820bb2020-04-28 15:37:02 +080024#include "pmbus_read_sensor_action.hpp"
25#include "pmbus_utils.hpp"
Shawn McCarney2f9e14f2021-04-29 02:45:18 -050026#include "sensors.hpp"
Shawn McCarney8c232452021-05-05 18:44:57 -050027#include "test_sdbus_error.hpp"
Bob Kingd6820bb2020-04-28 15:37:02 +080028
29#include <cstdint>
Shawn McCarney8c232452021-05-05 18:44:57 -050030#include <exception>
Bob King717d2da2020-06-02 11:11:15 +080031#include <memory>
Bob Kingd6820bb2020-04-28 15:37:02 +080032#include <optional>
33#include <stdexcept>
34#include <string>
Bob King717d2da2020-06-02 11:11:15 +080035#include <utility>
Bob Kingd6820bb2020-04-28 15:37:02 +080036
Bob King717d2da2020-06-02 11:11:15 +080037#include <gmock/gmock.h>
Bob Kingd6820bb2020-04-28 15:37:02 +080038#include <gtest/gtest.h>
39
40using namespace phosphor::power::regulators;
Shawn McCarney8c232452021-05-05 18:44:57 -050041using namespace phosphor::power::regulators::pmbus_utils;
Bob Kingd6820bb2020-04-28 15:37:02 +080042
Bob King717d2da2020-06-02 11:11:15 +080043using ::testing::A;
44using ::testing::Return;
45using ::testing::SetArgReferee;
46using ::testing::Throw;
47using ::testing::TypedEq;
48
Bob Kingd6820bb2020-04-28 15:37:02 +080049TEST(PMBusReadSensorActionTests, Constructor)
50{
51 // Test where works: exponent value is specified
Bob Kingd6820bb2020-04-28 15:37:02 +080052 {
Shawn McCarney8c232452021-05-05 18:44:57 -050053 SensorType type{SensorType::vout};
54 uint8_t command{0x8B};
55 SensorDataFormat format{SensorDataFormat::linear_16};
Bob Kingd6820bb2020-04-28 15:37:02 +080056 std::optional<int8_t> exponent{-8};
57 PMBusReadSensorAction action{type, command, format, exponent};
Shawn McCarney8c232452021-05-05 18:44:57 -050058 EXPECT_EQ(action.getType(), SensorType::vout);
59 EXPECT_EQ(action.getCommand(), 0x8B);
60 EXPECT_EQ(action.getFormat(), SensorDataFormat::linear_16);
Bob Kingd6820bb2020-04-28 15:37:02 +080061 EXPECT_EQ(action.getExponent().has_value(), true);
62 EXPECT_EQ(action.getExponent().value(), -8);
63 }
Bob Kingd6820bb2020-04-28 15:37:02 +080064
65 // Test where works: exponent value is not specified
Bob Kingd6820bb2020-04-28 15:37:02 +080066 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -050067 SensorType type{SensorType::iout};
Shawn McCarney8c232452021-05-05 18:44:57 -050068 uint8_t command{0x8C};
69 SensorDataFormat format{SensorDataFormat::linear_11};
Bob Kingd6820bb2020-04-28 15:37:02 +080070 std::optional<int8_t> exponent{};
71 PMBusReadSensorAction action{type, command, format, exponent};
Shawn McCarney2f9e14f2021-04-29 02:45:18 -050072 EXPECT_EQ(action.getType(), SensorType::iout);
Bob Kingd6820bb2020-04-28 15:37:02 +080073 EXPECT_EQ(action.getCommand(), 0x8C);
Shawn McCarney8c232452021-05-05 18:44:57 -050074 EXPECT_EQ(action.getFormat(), SensorDataFormat::linear_11);
Bob Kingd6820bb2020-04-28 15:37:02 +080075 EXPECT_EQ(action.getExponent().has_value(), false);
76 }
Bob Kingd6820bb2020-04-28 15:37:02 +080077}
78
79TEST(PMBusReadSensorActionTests, Execute)
80{
Shawn McCarney8c232452021-05-05 18:44:57 -050081 // Test where works: linear_11 format
Bob King717d2da2020-06-02 11:11:15 +080082 try
83 {
Shawn McCarney8c232452021-05-05 18:44:57 -050084 // Determine READ_IOUT linear data value and decimal value
85 // * 5 bit exponent: -6 = 11010
86 // * 11 bit mantissa: 736 = 010 1110 0000
87 // * linear data format = 1101 0010 1110 0000 = 0xD2E0
88 // * Decimal value: 736 * 2^(-6) = 11.5
89
90 // Create mock I2CInterface. Expect action to do the following:
Bob King717d2da2020-06-02 11:11:15 +080091 // * will read 0xD2E0 from READ_IOUT (command/register 0x8C)
92 // * will not read from VOUT_MODE (command/register 0x20)
Bob King717d2da2020-06-02 11:11:15 +080093 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
94 std::make_unique<i2c::MockedI2CInterface>();
95 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
96 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
97 .Times(1)
98 .WillOnce(SetArgReferee<1>(0xD2E0));
99 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint8_t&>())).Times(0);
100
Shawn McCarney8c232452021-05-05 18:44:57 -0500101 // Create MockServices. Expect the sensor value to be set.
102 MockServices services{};
103 MockSensors& sensors = services.getMockSensors();
104 EXPECT_CALL(sensors, setValue(SensorType::iout, 11.5)).Times(1);
105
106 // Create Device, IDMap, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800107 Device device{
108 "reg1", true,
109 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
110 std::move(i2cInterface)};
Bob King717d2da2020-06-02 11:11:15 +0800111 IDMap idMap{};
112 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800113 ActionEnvironment env{idMap, "reg1", services};
Bob King717d2da2020-06-02 11:11:15 +0800114
115 // Create and execute action
Shawn McCarney2f9e14f2021-04-29 02:45:18 -0500116 SensorType type{SensorType::iout};
Shawn McCarney8c232452021-05-05 18:44:57 -0500117 uint8_t command{0x8C};
118 SensorDataFormat format{SensorDataFormat::linear_11};
Bob King717d2da2020-06-02 11:11:15 +0800119 std::optional<int8_t> exponent{};
120 PMBusReadSensorAction action{type, command, format, exponent};
121 EXPECT_EQ(action.execute(env), true);
Bob King717d2da2020-06-02 11:11:15 +0800122 }
123 catch (...)
124 {
125 ADD_FAILURE() << "Should not have caught exception.";
126 }
127
Shawn McCarney8c232452021-05-05 18:44:57 -0500128 // Test where works: linear_16 format: exponent specified in constructor
Bob King717d2da2020-06-02 11:11:15 +0800129 try
130 {
Shawn McCarney8c232452021-05-05 18:44:57 -0500131 // Determine READ_VOUT linear data value and decimal value
132 // * Exponent: -8
133 // * 16 bit mantissa: 816 = 0000 0011 0011 0000
134 // * linear data format = 0000 0011 0011 0000 = 0x0330
135 // * Decimal value: 816 * 2^(-8) = 3.1875
136
137 // Create mock I2CInterface. Expect action to do the following:
138 // * will read 0x0330 from READ_VOUT (command/register 0x8B)
Bob King717d2da2020-06-02 11:11:15 +0800139 // * will not read from VOUT_MODE (command/register 0x20)
Bob King717d2da2020-06-02 11:11:15 +0800140 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
141 std::make_unique<i2c::MockedI2CInterface>();
142 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
143 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8B), A<uint16_t&>()))
144 .Times(1)
Shawn McCarney8c232452021-05-05 18:44:57 -0500145 .WillOnce(SetArgReferee<1>(0x0330));
Bob King717d2da2020-06-02 11:11:15 +0800146 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint8_t&>())).Times(0);
147
Shawn McCarney8c232452021-05-05 18:44:57 -0500148 // Create MockServices. Expect the sensor value to be set.
149 MockServices services{};
150 MockSensors& sensors = services.getMockSensors();
151 EXPECT_CALL(sensors, setValue(SensorType::vout, 3.1875)).Times(1);
152
153 // Create Device, IDMap, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800154 Device device{
155 "reg1", true,
156 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
157 std::move(i2cInterface)};
Bob King717d2da2020-06-02 11:11:15 +0800158 IDMap idMap{};
159 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800160 ActionEnvironment env{idMap, "reg1", services};
Bob King717d2da2020-06-02 11:11:15 +0800161
162 // Create and execute action
Shawn McCarney2f9e14f2021-04-29 02:45:18 -0500163 SensorType type{SensorType::vout};
Shawn McCarney8c232452021-05-05 18:44:57 -0500164 uint8_t command{0x8B};
165 SensorDataFormat format{SensorDataFormat::linear_16};
166 std::optional<int8_t> exponent{-8};
Bob King717d2da2020-06-02 11:11:15 +0800167 PMBusReadSensorAction action{type, command, format, exponent};
168 EXPECT_EQ(action.execute(env), true);
Bob King717d2da2020-06-02 11:11:15 +0800169 }
170 catch (...)
171 {
172 ADD_FAILURE() << "Should not have caught exception.";
173 }
174
Shawn McCarney8c232452021-05-05 18:44:57 -0500175 // Test where works: linear_16 format: exponent not specified in constructor
Bob King717d2da2020-06-02 11:11:15 +0800176 try
177 {
Shawn McCarney8c232452021-05-05 18:44:57 -0500178 // Determine READ_VOUT linear data value and decimal value
179 // * Exponent: -8
180 // * 16 bit mantissa: 816 = 0000 0011 0011 0000
181 // * linear data format = 0000 0011 0011 0000 = 0x0330
182 // * Decimal value: 816 * 2^(-8) = 3.1875
183
184 // Create mock I2CInterface. Expect action to do the following:
185 // * will read 0x0330 from READ_VOUT (command/register 0x8B)
186 // * will read 0b0001'1000 (linear format, -8 exponent) from VOUT_MODE
187 // (command/register 0x20)
Bob King717d2da2020-06-02 11:11:15 +0800188 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
189 std::make_unique<i2c::MockedI2CInterface>();
190 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
Shawn McCarney8c232452021-05-05 18:44:57 -0500191 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8B), A<uint16_t&>()))
Bob King717d2da2020-06-02 11:11:15 +0800192 .Times(1)
Shawn McCarney8c232452021-05-05 18:44:57 -0500193 .WillOnce(SetArgReferee<1>(0x0330));
Bob King717d2da2020-06-02 11:11:15 +0800194 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x20), A<uint8_t&>()))
195 .Times(1)
Shawn McCarney8c232452021-05-05 18:44:57 -0500196 .WillOnce(SetArgReferee<1>(0b0001'1000));
197
198 // Create MockServices. Expect the sensor value to be set.
199 MockServices services{};
200 MockSensors& sensors = services.getMockSensors();
201 EXPECT_CALL(sensors, setValue(SensorType::vout, 3.1875)).Times(1);
202
203 // Create Device, IDMap, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800204 Device device{
205 "reg1", true,
206 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
207 std::move(i2cInterface)};
Bob King717d2da2020-06-02 11:11:15 +0800208 IDMap idMap{};
209 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800210 ActionEnvironment env{idMap, "reg1", services};
Bob King717d2da2020-06-02 11:11:15 +0800211
212 // Create and execute action
Shawn McCarney8c232452021-05-05 18:44:57 -0500213 SensorType type{SensorType::vout};
214 uint8_t command{0x8B};
215 SensorDataFormat format{SensorDataFormat::linear_16};
Bob King717d2da2020-06-02 11:11:15 +0800216 std::optional<int8_t> exponent{};
217 PMBusReadSensorAction action{type, command, format, exponent};
218 EXPECT_EQ(action.execute(env), true);
Bob King717d2da2020-06-02 11:11:15 +0800219 }
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
Bob King717d2da2020-06-02 11:11:15 +0800229 IDMap idMap{};
Bob King73eacee2020-10-23 13:58:02 +0800230 MockServices services{};
231 ActionEnvironment env{idMap, "reg1", services};
Bob King717d2da2020-06-02 11:11:15 +0800232
233 // Create and execute action
Shawn McCarney2f9e14f2021-04-29 02:45:18 -0500234 SensorType type{SensorType::pout};
Shawn McCarney8c232452021-05-05 18:44:57 -0500235 uint8_t command{0x96};
236 SensorDataFormat format{SensorDataFormat::linear_11};
Bob King717d2da2020-06-02 11:11:15 +0800237 std::optional<int8_t> exponent{};
238 PMBusReadSensorAction action{type, command, format, exponent};
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: VOUT_MODE data format is not linear
252 try
253 {
254 // Create mock I2CInterface. Expect action to do the following:
Shawn McCarney8c232452021-05-05 18:44:57 -0500255 // * will read READ_VOUT (command/register 0x8B)
256 // * will read 0b0010'0000 (VID data format) from VOUT_MODE
Bob King717d2da2020-06-02 11:11:15 +0800257 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
258 std::make_unique<i2c::MockedI2CInterface>();
259 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
Bob Kingab7d6cb2020-07-17 10:24:07 +0800260 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8B), A<uint16_t&>()))
261 .Times(1);
Bob King717d2da2020-06-02 11:11:15 +0800262 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x20), A<uint8_t&>()))
263 .Times(1)
264 .WillOnce(SetArgReferee<1>(0b0010'0000));
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)};
Bob King717d2da2020-06-02 11:11:15 +0800271 IDMap idMap{};
272 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800273 MockServices services{};
274 ActionEnvironment env{idMap, "reg1", services};
Bob King717d2da2020-06-02 11:11:15 +0800275
276 // Create and execute action
Shawn McCarney2f9e14f2021-04-29 02:45:18 -0500277 SensorType type{SensorType::vout};
Shawn McCarney8c232452021-05-05 18:44:57 -0500278 uint8_t command{0x8B};
279 SensorDataFormat format{SensorDataFormat::linear_16};
Bob King717d2da2020-06-02 11:11:15 +0800280 std::optional<int8_t> exponent{};
281 PMBusReadSensorAction action{type, command, format, exponent};
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(), "ActionError: pmbus_read_sensor: { type: vout, "
288 "command: 0x8B, format: linear_16 }");
289 try
290 {
291 // Re-throw inner PMBusError
292 std::rethrow_if_nested(e);
293 ADD_FAILURE() << "Should not have reached this line.";
294 }
295 catch (const PMBusError& pe)
296 {
297 EXPECT_STREQ(
298 pe.what(),
299 "PMBusError: VOUT_MODE contains unsupported data format");
Shawn McCarney5b819f42021-03-16 14:41:15 -0500300 EXPECT_EQ(pe.getDeviceID(), "reg1");
301 EXPECT_EQ(pe.getInventoryPath(), "/xyz/openbmc_project/inventory/"
302 "system/chassis/motherboard/reg1");
Bob King717d2da2020-06-02 11:11:15 +0800303 }
304 catch (...)
305 {
306 ADD_FAILURE() << "Should not have caught exception.";
307 }
308 }
309 catch (...)
310 {
311 ADD_FAILURE() << "Should not have caught exception.";
312 }
313
314 // Test where fails: Reading VOUT_MODE fails
315 try
316 {
317 // Create mock I2CInterface. Expect action to do the following:
Shawn McCarney8c232452021-05-05 18:44:57 -0500318 // * will read command/register 0xC6
Bob King717d2da2020-06-02 11:11:15 +0800319 // * will try to read VOUT_MODE; exception will be thrown
320 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
321 std::make_unique<i2c::MockedI2CInterface>();
322 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
Bob Kingab7d6cb2020-07-17 10:24:07 +0800323 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0xC6), A<uint16_t&>()))
324 .Times(1);
Bob King717d2da2020-06-02 11:11:15 +0800325 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x20), A<uint8_t&>()))
326 .Times(1)
327 .WillOnce(Throw(
328 i2c::I2CException{"Failed to read byte", "/dev/i2c-1", 0x70}));
329
Bob King73eacee2020-10-23 13:58:02 +0800330 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800331 Device device{
332 "reg1", true,
333 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
334 std::move(i2cInterface)};
Bob King717d2da2020-06-02 11:11:15 +0800335 IDMap idMap{};
336 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800337 MockServices services{};
338 ActionEnvironment env{idMap, "reg1", services};
Bob King717d2da2020-06-02 11:11:15 +0800339
340 // Create and execute action
Shawn McCarney2f9e14f2021-04-29 02:45:18 -0500341 SensorType type{SensorType::vout_peak};
Shawn McCarney8c232452021-05-05 18:44:57 -0500342 uint8_t command{0xC6};
343 SensorDataFormat format{SensorDataFormat::linear_16};
Bob King717d2da2020-06-02 11:11:15 +0800344 std::optional<int8_t> exponent{};
345 PMBusReadSensorAction action{type, command, format, exponent};
346 action.execute(env);
347 ADD_FAILURE() << "Should not have reached this line.";
348 }
349 catch (const ActionError& e)
350 {
351 EXPECT_STREQ(e.what(),
352 "ActionError: pmbus_read_sensor: { type: vout_peak, "
353 "command: 0xC6, format: linear_16 }");
354 try
355 {
356 // Re-throw inner I2CException
357 std::rethrow_if_nested(e);
358 ADD_FAILURE() << "Should not have reached this line.";
359 }
360 catch (const i2c::I2CException& ie)
361 {
362 EXPECT_STREQ(
363 ie.what(),
364 "I2CException: Failed to read byte: bus /dev/i2c-1, addr 0x70");
365 }
366 catch (...)
367 {
368 ADD_FAILURE() << "Should not have caught exception.";
369 }
370 }
371 catch (...)
372 {
373 ADD_FAILURE() << "Should not have caught exception.";
374 }
375
376 // Test where fails: Reading PMBus command code with sensor value fails
377 try
378 {
379 // Create mock I2CInterface. Expect action to do the following:
Shawn McCarney8c232452021-05-05 18:44:57 -0500380 // * will try to read command/register 0x96; exception will be thrown
Bob King717d2da2020-06-02 11:11:15 +0800381 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(TypedEq<uint8_t>(0x96), A<uint16_t&>()))
385 .Times(1)
Shawn McCarney8c232452021-05-05 18:44:57 -0500386 .WillOnce(Throw(i2c::I2CException{"Failed to read word data",
387 "/dev/i2c-1", 0x70}));
Bob King717d2da2020-06-02 11:11:15 +0800388
Bob King73eacee2020-10-23 13:58:02 +0800389 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800390 Device device{
391 "reg1", true,
392 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
393 std::move(i2cInterface)};
Bob King717d2da2020-06-02 11:11:15 +0800394 IDMap idMap{};
395 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800396 MockServices services{};
397 ActionEnvironment env{idMap, "reg1", services};
Bob King717d2da2020-06-02 11:11:15 +0800398
399 // Create and execute action
Shawn McCarney2f9e14f2021-04-29 02:45:18 -0500400 SensorType type{SensorType::pout};
Shawn McCarney8c232452021-05-05 18:44:57 -0500401 uint8_t command{0x96};
402 SensorDataFormat format{SensorDataFormat::linear_11};
Bob King717d2da2020-06-02 11:11:15 +0800403 std::optional<int8_t> exponent{};
404 PMBusReadSensorAction action{type, command, format, exponent};
405 action.execute(env);
406 ADD_FAILURE() << "Should not have reached this line.";
407 }
408 catch (const ActionError& e)
409 {
410 EXPECT_STREQ(e.what(), "ActionError: pmbus_read_sensor: { type: pout, "
411 "command: 0x96, format: linear_11 }");
412 try
413 {
414 // Re-throw inner I2CException
415 std::rethrow_if_nested(e);
416 ADD_FAILURE() << "Should not have reached this line.";
417 }
418 catch (const i2c::I2CException& ie)
419 {
Shawn McCarney8c232452021-05-05 18:44:57 -0500420 EXPECT_STREQ(ie.what(), "I2CException: Failed to read word data: "
421 "bus /dev/i2c-1, addr 0x70");
422 }
423 catch (...)
424 {
425 ADD_FAILURE() << "Should not have caught exception.";
426 }
427 }
428 catch (...)
429 {
430 ADD_FAILURE() << "Should not have caught exception.";
431 }
432
433 // Test where fails: Unable to publish sensor value due to D-Bus exception
434 try
435 {
436 // Determine READ_IOUT linear data value and decimal value
437 // * 5 bit exponent: -6 = 11010
438 // * 11 bit mantissa: 736 = 010 1110 0000
439 // * linear data format = 1101 0010 1110 0000 = 0xD2E0
440 // * Decimal value: 736 * 2^(-6) = 11.5
441
442 // Create mock I2CInterface. Expect action to do the following:
443 // * will read 0xD2E0 from READ_IOUT (command/register 0x8C)
444 // * will not read from VOUT_MODE (command/register 0x20)
445 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
446 std::make_unique<i2c::MockedI2CInterface>();
447 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
448 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
449 .Times(1)
450 .WillOnce(SetArgReferee<1>(0xD2E0));
451 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint8_t&>())).Times(0);
452
453 // Create MockServices. Will throw D-Bus exception when trying to set
454 // sensor value.
455 MockServices services{};
456 MockSensors& sensors = services.getMockSensors();
457 EXPECT_CALL(sensors, setValue(SensorType::iout, 11.5))
458 .Times(1)
459 .WillOnce(Throw(TestSDBusError{"D-Bus error: Invalid property"}));
460
461 // Create Device, IDMap, and ActionEnvironment
462 Device device{
463 "reg1", true,
464 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
465 std::move(i2cInterface)};
466 IDMap idMap{};
467 idMap.addDevice(device);
468 ActionEnvironment env{idMap, "reg1", services};
469
470 // Create and execute action
471 SensorType type{SensorType::iout};
472 uint8_t command{0x8C};
473 SensorDataFormat format{SensorDataFormat::linear_11};
474 std::optional<int8_t> exponent{};
475 PMBusReadSensorAction action{type, command, format, exponent};
476 action.execute(env);
477 ADD_FAILURE() << "Should not have reached this line.";
478 }
479 catch (const ActionError& e)
480 {
481 EXPECT_STREQ(e.what(), "ActionError: pmbus_read_sensor: { type: iout, "
482 "command: 0x8C, format: linear_11 }");
483 try
484 {
485 // Re-throw inner D-Bus exception
486 std::rethrow_if_nested(e);
487 ADD_FAILURE() << "Should not have reached this line.";
488 }
489 catch (const sdbusplus::exception_t& de)
490 {
491 EXPECT_STREQ(de.what(), "D-Bus error: Invalid property");
Bob King717d2da2020-06-02 11:11:15 +0800492 }
493 catch (...)
494 {
495 ADD_FAILURE() << "Should not have caught exception.";
496 }
497 }
498 catch (...)
499 {
500 ADD_FAILURE() << "Should not have caught exception.";
501 }
Bob Kingd6820bb2020-04-28 15:37:02 +0800502}
503
504TEST(PMBusReadSensorActionTests, GetCommand)
505{
Shawn McCarney2f9e14f2021-04-29 02:45:18 -0500506 SensorType type{SensorType::iout};
Shawn McCarney8c232452021-05-05 18:44:57 -0500507 uint8_t command{0x8C};
508 SensorDataFormat format{SensorDataFormat::linear_11};
509 std::optional<int8_t> exponent{};
Bob Kingd6820bb2020-04-28 15:37:02 +0800510 PMBusReadSensorAction action{type, command, format, exponent};
511 EXPECT_EQ(action.getCommand(), 0x8C);
512}
513
514TEST(PMBusReadSensorActionTests, GetExponent)
515{
Shawn McCarney8c232452021-05-05 18:44:57 -0500516 SensorType type{SensorType::vout};
517 uint8_t command{0x8B};
518 SensorDataFormat format{SensorDataFormat::linear_16};
Bob Kingd6820bb2020-04-28 15:37:02 +0800519
520 // Exponent value is specified
521 {
522 std::optional<int8_t> exponent{-9};
523 PMBusReadSensorAction action{type, command, format, exponent};
524 EXPECT_EQ(action.getExponent().has_value(), true);
525 EXPECT_EQ(action.getExponent().value(), -9);
526 }
527
528 // Exponent value is not specified
529 {
530 std::optional<int8_t> exponent{};
531 PMBusReadSensorAction action{type, command, format, exponent};
532 EXPECT_EQ(action.getExponent().has_value(), false);
533 }
534}
535
536TEST(PMBusReadSensorActionTests, GetFormat)
537{
Shawn McCarney2f9e14f2021-04-29 02:45:18 -0500538 SensorType type{SensorType::iout};
Shawn McCarney8c232452021-05-05 18:44:57 -0500539 uint8_t command{0x8C};
540 SensorDataFormat format{SensorDataFormat::linear_11};
541 std::optional<int8_t> exponent{};
Bob Kingd6820bb2020-04-28 15:37:02 +0800542 PMBusReadSensorAction action{type, command, format, exponent};
Shawn McCarney8c232452021-05-05 18:44:57 -0500543 EXPECT_EQ(action.getFormat(), SensorDataFormat::linear_11);
Bob Kingd6820bb2020-04-28 15:37:02 +0800544}
545
546TEST(PMBusReadSensorActionTests, GetType)
547{
Shawn McCarney2f9e14f2021-04-29 02:45:18 -0500548 SensorType type{SensorType::pout};
Shawn McCarney8c232452021-05-05 18:44:57 -0500549 uint8_t command{0x96};
550 SensorDataFormat format{SensorDataFormat::linear_11};
551 std::optional<int8_t> exponent{};
Bob Kingd6820bb2020-04-28 15:37:02 +0800552 PMBusReadSensorAction action{type, command, format, exponent};
Shawn McCarney2f9e14f2021-04-29 02:45:18 -0500553 EXPECT_EQ(action.getType(), SensorType::pout);
Bob Kingd6820bb2020-04-28 15:37:02 +0800554}
555
556TEST(PMBusReadSensorActionTests, ToString)
557{
558 // Test where exponent value is specified
559 {
Shawn McCarney8c232452021-05-05 18:44:57 -0500560 SensorType type{SensorType::vout_peak};
561 uint8_t command{0xC6};
562 SensorDataFormat format{SensorDataFormat::linear_16};
Bob Kingd6820bb2020-04-28 15:37:02 +0800563 std::optional<int8_t> exponent{-8};
564 PMBusReadSensorAction action{type, command, format, exponent};
565 EXPECT_EQ(action.toString(), "pmbus_read_sensor: { type: "
Shawn McCarney8c232452021-05-05 18:44:57 -0500566 "vout_peak, command: 0xC6, format: "
Bob Kingd6820bb2020-04-28 15:37:02 +0800567 "linear_16, exponent: -8 }");
568 }
569
570 // Test where exponent value is not specified
571 {
Shawn McCarney8c232452021-05-05 18:44:57 -0500572 SensorType type{SensorType::iout_valley};
573 uint8_t command{0xCB};
574 SensorDataFormat format{SensorDataFormat::linear_11};
Bob Kingd6820bb2020-04-28 15:37:02 +0800575 std::optional<int8_t> exponent{};
576 PMBusReadSensorAction action{type, command, format, exponent};
Shawn McCarney8c232452021-05-05 18:44:57 -0500577 EXPECT_EQ(action.toString(), "pmbus_read_sensor: { type: iout_valley, "
578 "command: 0xCB, format: linear_11 }");
Bob Kingd6820bb2020-04-28 15:37:02 +0800579 }
580}