blob: 97df0e9c442278e5ace826db8b4dd0e484dea928 [file] [log] [blame]
Shawn McCarney88d5b692020-02-25 10:39:02 -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 "i2c_write_bit_action.hpp"
21#include "id_map.hpp"
Bob King73eacee2020-10-23 13:58:02 +080022#include "mock_services.hpp"
Shawn McCarney88d5b692020-02-25 10:39:02 -060023#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::A;
37using ::testing::Return;
38using ::testing::SetArgReferee;
39using ::testing::Throw;
40using ::testing::TypedEq;
41
42TEST(I2CWriteBitActionTests, Constructor)
43{
44 // Test where works
45 try
46 {
47 I2CWriteBitAction action{0x7C, 2, 0};
48 EXPECT_EQ(action.getRegister(), 0x7C);
49 EXPECT_EQ(action.getPosition(), 2);
50 EXPECT_EQ(action.getValue(), 0);
51 }
52 catch (...)
53 {
54 ADD_FAILURE() << "Should not have caught exception.";
55 }
56
57 // Test where fails: Invalid bit position > 7
58 try
59 {
60 I2CWriteBitAction action{0x7C, 8, 0};
61 ADD_FAILURE() << "Should not have reached this line.";
62 }
63 catch (const std::invalid_argument& e)
64 {
65 EXPECT_STREQ(e.what(), "Invalid bit position: 8");
66 }
67 catch (...)
68 {
69 ADD_FAILURE() << "Should not have caught exception.";
70 }
71
72 // Test where fails: Invalid bit value > 1
73 try
74 {
75 I2CWriteBitAction action{0x7C, 2, 2};
76 ADD_FAILURE() << "Should not have reached this line.";
77 }
78 catch (const std::invalid_argument& e)
79 {
80 EXPECT_STREQ(e.what(), "Invalid bit value: 2");
81 }
82 catch (...)
83 {
84 ADD_FAILURE() << "Should not have caught exception.";
85 }
86}
87
88TEST(I2CWriteBitActionTests, Execute)
89{
90 // Test where works: Value is 0
91 try
92 {
93 // Create mock I2CInterface: read() returns value 0xB6
94 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
95 std::make_unique<i2c::MockedI2CInterface>();
96 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
97 EXPECT_CALL(*i2cInterface, read(0xA0, A<uint8_t&>()))
98 .Times(1)
99 .WillOnce(SetArgReferee<1>(0xB6));
100 EXPECT_CALL(*i2cInterface,
101 write(TypedEq<uint8_t>(0xA0), TypedEq<uint8_t>(0x96)))
102 .Times(1);
103
Bob King73eacee2020-10-23 13:58:02 +0800104 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800105 Device device{
106 "reg1", true,
107 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
108 std::move(i2cInterface)};
Shawn McCarney88d5b692020-02-25 10:39:02 -0600109 IDMap idMap{};
110 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800111 MockServices services{};
112 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarney88d5b692020-02-25 10:39:02 -0600113
114 // Register value : 0xB6 = 1011 0110
115 // 0 in position 5 : 0x00 = --0- ----
116 // New register value: 0x96 = 1001 0110
117 I2CWriteBitAction action{0xA0, 5, 0};
118 EXPECT_EQ(action.execute(env), true);
119 }
120 catch (...)
121 {
122 ADD_FAILURE() << "Should not have caught exception.";
123 }
124
125 // Test where works: Value is 1
126 try
127 {
128 // Create mock I2CInterface: read() returns value 0x96
129 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
130 std::make_unique<i2c::MockedI2CInterface>();
131 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
132 EXPECT_CALL(*i2cInterface, read(0x7C, A<uint8_t&>()))
133 .Times(1)
134 .WillOnce(SetArgReferee<1>(0x96));
135 EXPECT_CALL(*i2cInterface,
136 write(TypedEq<uint8_t>(0x7C), TypedEq<uint8_t>(0xB6)))
137 .Times(1);
138
Bob King73eacee2020-10-23 13:58:02 +0800139 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800140 Device device{
141 "reg1", true,
142 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
143 std::move(i2cInterface)};
Shawn McCarney88d5b692020-02-25 10:39:02 -0600144 IDMap idMap{};
145 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800146 MockServices services{};
147 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarney88d5b692020-02-25 10:39:02 -0600148
149 // Register value : 0x96 = 1001 0110
150 // 1 in position 5 : 0x20 = 0010 0000
151 // New register value: 0xB6 = 1011 0110
152 I2CWriteBitAction action{0x7C, 5, 1};
153 EXPECT_EQ(action.execute(env), true);
154 }
155 catch (...)
156 {
157 ADD_FAILURE() << "Should not have caught exception.";
158 }
159
160 // Test where fails: Getting I2CInterface fails
161 try
162 {
Bob King73eacee2020-10-23 13:58:02 +0800163 // Create IDMap, MockServices, and ActionEnvironment
Shawn McCarney88d5b692020-02-25 10:39:02 -0600164 IDMap idMap{};
Bob King73eacee2020-10-23 13:58:02 +0800165 MockServices services{};
166 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarney88d5b692020-02-25 10:39:02 -0600167
168 I2CWriteBitAction action{0x7C, 5, 1};
169 action.execute(env);
170 ADD_FAILURE() << "Should not have reached this line.";
171 }
172 catch (const std::invalid_argument& e)
173 {
174 EXPECT_STREQ(e.what(), "Unable to find device with ID \"reg1\"");
175 }
176 catch (...)
177 {
178 ADD_FAILURE() << "Should not have caught exception.";
179 }
180
181 // Test where fails: Reading byte fails
182 try
183 {
184 // Create mock I2CInterface: read() throws an I2CException
185 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
186 std::make_unique<i2c::MockedI2CInterface>();
187 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
188 EXPECT_CALL(*i2cInterface, read(0x7C, A<uint8_t&>()))
189 .Times(1)
190 .WillOnce(Throw(
191 i2c::I2CException{"Failed to read byte", "/dev/i2c-1", 0x70}));
192 EXPECT_CALL(*i2cInterface, write(A<uint8_t>(), A<uint8_t>())).Times(0);
193
Bob King73eacee2020-10-23 13:58:02 +0800194 // Create Device, IDMap, MockServices and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800195 Device device{
196 "reg1", true,
197 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
198 std::move(i2cInterface)};
Shawn McCarney88d5b692020-02-25 10:39:02 -0600199 IDMap idMap{};
200 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800201 MockServices services{};
202 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarney88d5b692020-02-25 10:39:02 -0600203
204 I2CWriteBitAction action{0x7C, 5, 1};
205 action.execute(env);
206 ADD_FAILURE() << "Should not have reached this line.";
207 }
208 catch (const ActionError& e)
209 {
210 EXPECT_STREQ(e.what(), "ActionError: i2c_write_bit: { register: "
211 "0x7C, position: 5, value: 1 }");
212 try
213 {
214 // Re-throw inner I2CException
215 std::rethrow_if_nested(e);
216 ADD_FAILURE() << "Should not have reached this line.";
217 }
218 catch (const i2c::I2CException& ie)
219 {
220 EXPECT_STREQ(
221 ie.what(),
222 "I2CException: Failed to read byte: bus /dev/i2c-1, addr 0x70");
223 }
224 catch (...)
225 {
226 ADD_FAILURE() << "Should not have caught exception.";
227 }
228 }
229 catch (...)
230 {
231 ADD_FAILURE() << "Should not have caught exception.";
232 }
233
234 // Test where fails: Writing byte fails
235 try
236 {
237 // Create mock I2CInterface: read() returns value 0xB6, write() throws
238 // an I2CException
239 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
240 std::make_unique<i2c::MockedI2CInterface>();
241 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
242 EXPECT_CALL(*i2cInterface, read(0xA0, A<uint8_t&>()))
243 .Times(1)
244 .WillOnce(SetArgReferee<1>(0xB6));
245 EXPECT_CALL(*i2cInterface,
246 write(TypedEq<uint8_t>(0xA0), TypedEq<uint8_t>(0x96)))
247 .Times(1)
248 .WillOnce(Throw(
249 i2c::I2CException{"Failed to write byte", "/dev/i2c-1", 0x70}));
250
Bob King73eacee2020-10-23 13:58:02 +0800251 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800252 Device device{
253 "reg1", true,
254 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
255 std::move(i2cInterface)};
Shawn McCarney88d5b692020-02-25 10:39:02 -0600256 IDMap idMap{};
257 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800258 MockServices services{};
259 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarney88d5b692020-02-25 10:39:02 -0600260
261 // Register value : 0xB6 = 1011 0110
262 // 0 in position 5 : 0x00 = --0- ----
263 // New register value: 0x96 = 1001 0110
264 I2CWriteBitAction action{0xA0, 5, 0};
265 action.execute(env);
266 ADD_FAILURE() << "Should not have reached this line.";
267 }
268 catch (const ActionError& e)
269 {
270 EXPECT_STREQ(e.what(), "ActionError: i2c_write_bit: { register: "
271 "0xA0, position: 5, value: 0 }");
272 try
273 {
274 // Re-throw inner I2CException
275 std::rethrow_if_nested(e);
276 ADD_FAILURE() << "Should not have reached this line.";
277 }
278 catch (const i2c::I2CException& ie)
279 {
280 EXPECT_STREQ(ie.what(), "I2CException: Failed to write byte: bus "
281 "/dev/i2c-1, addr 0x70");
282 }
283 catch (...)
284 {
285 ADD_FAILURE() << "Should not have caught exception.";
286 }
287 }
288 catch (...)
289 {
290 ADD_FAILURE() << "Should not have caught exception.";
291 }
292}
293
294TEST(I2CWriteBitActionTests, GetRegister)
295{
296 I2CWriteBitAction action{0x7C, 5, 1};
297 EXPECT_EQ(action.getRegister(), 0x7C);
298}
299
300TEST(I2CWriteBitActionTests, GetPosition)
301{
302 I2CWriteBitAction action{0x7C, 5, 1};
303 EXPECT_EQ(action.getPosition(), 5);
304}
305
306TEST(I2CWriteBitActionTests, GetValue)
307{
308 I2CWriteBitAction action{0x7C, 5, 1};
309 EXPECT_EQ(action.getValue(), 1);
310}
311
312TEST(I2CWriteBitActionTests, ToString)
313{
314 I2CWriteBitAction action{0x7C, 5, 1};
315 EXPECT_EQ(action.toString(),
316 "i2c_write_bit: { register: 0x7C, position: 5, value: 1 }");
317}