blob: f806a09bf5a985b8f17fe2eb3950ff88a14e0cd6 [file] [log] [blame]
Shawn McCarney3b242b72021-08-27 09:55:22 -05001/**
2 * Copyright © 2021 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_capture_bytes_action.hpp"
20#include "i2c_interface.hpp"
21#include "id_map.hpp"
22#include "mock_services.hpp"
23#include "mocked_i2c_interface.hpp"
24
25#include <cstdint>
26#include <memory>
27#include <stdexcept>
28#include <string>
29#include <utility>
30
31#include <gmock/gmock.h>
32#include <gtest/gtest.h>
33
34using namespace phosphor::power::regulators;
35
36using ::testing::NotNull;
37using ::testing::Return;
38using ::testing::SetArrayArgument;
39using ::testing::Throw;
40using ::testing::TypedEq;
41
42TEST(I2CCaptureBytesActionTests, Constructor)
43{
44 // Test where works
45 try
46 {
47 I2CCaptureBytesAction action{0x2A, 2};
48 EXPECT_EQ(action.getRegister(), 0x2A);
49 EXPECT_EQ(action.getCount(), 2);
50 }
51 catch (...)
52 {
53 ADD_FAILURE() << "Should not have caught exception.";
54 }
55
56 // Test where fails: Count < 1
57 try
58 {
59 I2CCaptureBytesAction action{0x2A, 0};
60 ADD_FAILURE() << "Should not have reached this line.";
61 }
62 catch (const std::invalid_argument& e)
63 {
64 EXPECT_STREQ(e.what(), "Invalid byte count: Less than 1");
65 }
66 catch (...)
67 {
68 ADD_FAILURE() << "Should not have caught exception.";
69 }
70}
71
72TEST(I2CCaptureBytesActionTests, Execute)
73{
74 // Test where works: One byte captured
75 try
76 {
77 // Create mock I2CInterface: read() returns value 0xD7
78 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
79 std::make_unique<i2c::MockedI2CInterface>();
80 uint8_t values[] = {0xD7};
81 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
82 EXPECT_CALL(*i2cInterface, read(0xA0, TypedEq<uint8_t&>(1), NotNull(),
83 i2c::I2CInterface::Mode::I2C))
84 .Times(1)
85 .WillOnce(SetArrayArgument<2>(values, values + 1));
86
87 // Create Device, IDMap, MockServices, and ActionEnvironment
88 Device device{
89 "vdd1", true,
90 "/xyz/openbmc_project/inventory/system/chassis/motherboard/vdd1",
91 std::move(i2cInterface)};
92 IDMap idMap{};
93 idMap.addDevice(device);
94 MockServices services{};
95 ActionEnvironment env{idMap, "vdd1", services};
96
97 I2CCaptureBytesAction action{0xA0, 1};
98 EXPECT_EQ(action.execute(env), true);
99 EXPECT_EQ(env.getAdditionalErrorData().size(), 1);
100 EXPECT_EQ(env.getAdditionalErrorData().at("vdd1_register_0xA0"),
101 "[ 0xD7 ]");
102 }
103 catch (...)
104 {
105 ADD_FAILURE() << "Should not have caught exception.";
106 }
107
108 // Test where works: Multiple bytes captured
109 try
110 {
111 // Create mock I2CInterface: read() returns values 0x56, 0x14, 0xDA
112 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
113 std::make_unique<i2c::MockedI2CInterface>();
114 uint8_t values[] = {0x56, 0x14, 0xDA};
115 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
116 EXPECT_CALL(*i2cInterface, read(0x7C, TypedEq<uint8_t&>(3), NotNull(),
117 i2c::I2CInterface::Mode::I2C))
118 .Times(1)
119 .WillOnce(SetArrayArgument<2>(values, values + 3));
120
121 // Create Device, IDMap, MockServices, and ActionEnvironment
122 Device device{
123 "vdd1", true,
124 "/xyz/openbmc_project/inventory/system/chassis/motherboard/vdd1",
125 std::move(i2cInterface)};
126 IDMap idMap{};
127 idMap.addDevice(device);
128 MockServices services{};
129 ActionEnvironment env{idMap, "vdd1", services};
130
131 I2CCaptureBytesAction action{0x7C, 3};
132 EXPECT_EQ(action.execute(env), true);
133 EXPECT_EQ(env.getAdditionalErrorData().size(), 1);
134 EXPECT_EQ(env.getAdditionalErrorData().at("vdd1_register_0x7C"),
135 "[ 0x56, 0x14, 0xDA ]");
136 }
137 catch (...)
138 {
139 ADD_FAILURE() << "Should not have caught exception.";
140 }
141
142 // Test where fails: Getting I2CInterface fails
143 try
144 {
145 // Create IDMap, MockServices, and ActionEnvironment
146 IDMap idMap{};
147 MockServices services{};
148 ActionEnvironment env{idMap, "vdd1", services};
149
150 I2CCaptureBytesAction action{0x7C, 2};
151 action.execute(env);
152 ADD_FAILURE() << "Should not have reached this line.";
153 }
154 catch (const std::invalid_argument& e)
155 {
156 EXPECT_STREQ(e.what(), "Unable to find device with ID \"vdd1\"");
157 }
158 catch (...)
159 {
160 ADD_FAILURE() << "Should not have caught exception.";
161 }
162
163 // Test where fails: Reading bytes fails
164 try
165 {
166 // Create mock I2CInterface: read() throws an I2CException
167 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
168 std::make_unique<i2c::MockedI2CInterface>();
169 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
170 EXPECT_CALL(*i2cInterface, read(0x7C, TypedEq<uint8_t&>(2), NotNull(),
171 i2c::I2CInterface::Mode::I2C))
172 .Times(1)
173 .WillOnce(Throw(i2c::I2CException{"Failed to read i2c block data",
174 "/dev/i2c-1", 0x70}));
175
176 // Create Device, IDMap, MockServices, and ActionEnvironment
177 Device device{
178 "vdd1", true,
179 "/xyz/openbmc_project/inventory/system/chassis/motherboard/vdd1",
180 std::move(i2cInterface)};
181 IDMap idMap{};
182 idMap.addDevice(device);
183 MockServices services{};
184 ActionEnvironment env{idMap, "vdd1", services};
185
186 I2CCaptureBytesAction action{0x7C, 2};
187 action.execute(env);
188 ADD_FAILURE() << "Should not have reached this line.";
189 }
190 catch (const ActionError& e)
191 {
192 EXPECT_STREQ(
193 e.what(),
194 "ActionError: i2c_capture_bytes: { register: 0x7C, count: 2 }");
195 try
196 {
197 // Re-throw inner I2CException
198 std::rethrow_if_nested(e);
199 ADD_FAILURE() << "Should not have reached this line.";
200 }
201 catch (const i2c::I2CException& ie)
202 {
203 EXPECT_STREQ(ie.what(),
204 "I2CException: Failed to read i2c block data: bus "
205 "/dev/i2c-1, addr 0x70");
206 }
207 catch (...)
208 {
209 ADD_FAILURE() << "Should not have caught exception.";
210 }
211 }
212 catch (...)
213 {
214 ADD_FAILURE() << "Should not have caught exception.";
215 }
216}
217
218TEST(I2CCaptureBytesActionTests, GetCount)
219{
220 I2CCaptureBytesAction action{0xA0, 3};
221 EXPECT_EQ(action.getCount(), 3);
222}
223
224TEST(I2CCaptureBytesActionTests, GetRegister)
225{
226 I2CCaptureBytesAction action{0xA0, 3};
227 EXPECT_EQ(action.getRegister(), 0xA0);
228}
229
230TEST(I2CCaptureBytesActionTests, ToString)
231{
232 I2CCaptureBytesAction action{0xA0, 3};
233 EXPECT_EQ(action.toString(),
234 "i2c_capture_bytes: { register: 0xA0, count: 3 }");
235}