blob: cefc948978b6b8206ec4f929c32deaecb43d2282 [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"
22#include "mocked_i2c_interface.hpp"
23
24#include <cstdint>
25#include <memory>
26#include <stdexcept>
27#include <string>
28#include <utility>
29
30#include <gmock/gmock.h>
31#include <gtest/gtest.h>
32
33using namespace phosphor::power::regulators;
34
35using ::testing::A;
36using ::testing::Return;
37using ::testing::SetArgReferee;
38using ::testing::Throw;
39using ::testing::TypedEq;
40
41TEST(I2CWriteBitActionTests, Constructor)
42{
43 // Test where works
44 try
45 {
46 I2CWriteBitAction action{0x7C, 2, 0};
47 EXPECT_EQ(action.getRegister(), 0x7C);
48 EXPECT_EQ(action.getPosition(), 2);
49 EXPECT_EQ(action.getValue(), 0);
50 }
51 catch (...)
52 {
53 ADD_FAILURE() << "Should not have caught exception.";
54 }
55
56 // Test where fails: Invalid bit position > 7
57 try
58 {
59 I2CWriteBitAction action{0x7C, 8, 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 bit position: 8");
65 }
66 catch (...)
67 {
68 ADD_FAILURE() << "Should not have caught exception.";
69 }
70
71 // Test where fails: Invalid bit value > 1
72 try
73 {
74 I2CWriteBitAction action{0x7C, 2, 2};
75 ADD_FAILURE() << "Should not have reached this line.";
76 }
77 catch (const std::invalid_argument& e)
78 {
79 EXPECT_STREQ(e.what(), "Invalid bit value: 2");
80 }
81 catch (...)
82 {
83 ADD_FAILURE() << "Should not have caught exception.";
84 }
85}
86
87TEST(I2CWriteBitActionTests, Execute)
88{
89 // Test where works: Value is 0
90 try
91 {
92 // Create mock I2CInterface: read() returns value 0xB6
93 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(0xA0, A<uint8_t&>()))
97 .Times(1)
98 .WillOnce(SetArgReferee<1>(0xB6));
99 EXPECT_CALL(*i2cInterface,
100 write(TypedEq<uint8_t>(0xA0), TypedEq<uint8_t>(0x96)))
101 .Times(1);
102
103 // Create Device, IDMap, and ActionEnvironment
104 Device device{"reg1", true, "/system/chassis/motherboard/reg1",
105 std::move(i2cInterface)};
106 IDMap idMap{};
107 idMap.addDevice(device);
108 ActionEnvironment env{idMap, "reg1"};
109
110 // Register value : 0xB6 = 1011 0110
111 // 0 in position 5 : 0x00 = --0- ----
112 // New register value: 0x96 = 1001 0110
113 I2CWriteBitAction action{0xA0, 5, 0};
114 EXPECT_EQ(action.execute(env), true);
115 }
116 catch (...)
117 {
118 ADD_FAILURE() << "Should not have caught exception.";
119 }
120
121 // Test where works: Value is 1
122 try
123 {
124 // Create mock I2CInterface: read() returns value 0x96
125 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
126 std::make_unique<i2c::MockedI2CInterface>();
127 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
128 EXPECT_CALL(*i2cInterface, read(0x7C, A<uint8_t&>()))
129 .Times(1)
130 .WillOnce(SetArgReferee<1>(0x96));
131 EXPECT_CALL(*i2cInterface,
132 write(TypedEq<uint8_t>(0x7C), TypedEq<uint8_t>(0xB6)))
133 .Times(1);
134
135 // Create Device, IDMap, and ActionEnvironment
136 Device device{"reg1", true, "/system/chassis/motherboard/reg1",
137 std::move(i2cInterface)};
138 IDMap idMap{};
139 idMap.addDevice(device);
140 ActionEnvironment env{idMap, "reg1"};
141
142 // Register value : 0x96 = 1001 0110
143 // 1 in position 5 : 0x20 = 0010 0000
144 // New register value: 0xB6 = 1011 0110
145 I2CWriteBitAction action{0x7C, 5, 1};
146 EXPECT_EQ(action.execute(env), true);
147 }
148 catch (...)
149 {
150 ADD_FAILURE() << "Should not have caught exception.";
151 }
152
153 // Test where fails: Getting I2CInterface fails
154 try
155 {
156 // Create IDMap and ActionEnvironment
157 IDMap idMap{};
158 ActionEnvironment env{idMap, "reg1"};
159
160 I2CWriteBitAction action{0x7C, 5, 1};
161 action.execute(env);
162 ADD_FAILURE() << "Should not have reached this line.";
163 }
164 catch (const std::invalid_argument& e)
165 {
166 EXPECT_STREQ(e.what(), "Unable to find device with ID \"reg1\"");
167 }
168 catch (...)
169 {
170 ADD_FAILURE() << "Should not have caught exception.";
171 }
172
173 // Test where fails: Reading byte fails
174 try
175 {
176 // Create mock I2CInterface: read() throws an I2CException
177 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
178 std::make_unique<i2c::MockedI2CInterface>();
179 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
180 EXPECT_CALL(*i2cInterface, read(0x7C, A<uint8_t&>()))
181 .Times(1)
182 .WillOnce(Throw(
183 i2c::I2CException{"Failed to read byte", "/dev/i2c-1", 0x70}));
184 EXPECT_CALL(*i2cInterface, write(A<uint8_t>(), A<uint8_t>())).Times(0);
185
186 // Create Device, IDMap, and ActionEnvironment
187 Device device{"reg1", true, "/system/chassis/motherboard/reg1",
188 std::move(i2cInterface)};
189 IDMap idMap{};
190 idMap.addDevice(device);
191 ActionEnvironment env{idMap, "reg1"};
192
193 I2CWriteBitAction action{0x7C, 5, 1};
194 action.execute(env);
195 ADD_FAILURE() << "Should not have reached this line.";
196 }
197 catch (const ActionError& e)
198 {
199 EXPECT_STREQ(e.what(), "ActionError: i2c_write_bit: { register: "
200 "0x7C, position: 5, value: 1 }");
201 try
202 {
203 // Re-throw inner I2CException
204 std::rethrow_if_nested(e);
205 ADD_FAILURE() << "Should not have reached this line.";
206 }
207 catch (const i2c::I2CException& ie)
208 {
209 EXPECT_STREQ(
210 ie.what(),
211 "I2CException: Failed to read byte: bus /dev/i2c-1, addr 0x70");
212 }
213 catch (...)
214 {
215 ADD_FAILURE() << "Should not have caught exception.";
216 }
217 }
218 catch (...)
219 {
220 ADD_FAILURE() << "Should not have caught exception.";
221 }
222
223 // Test where fails: Writing byte fails
224 try
225 {
226 // Create mock I2CInterface: read() returns value 0xB6, write() throws
227 // an I2CException
228 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
229 std::make_unique<i2c::MockedI2CInterface>();
230 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
231 EXPECT_CALL(*i2cInterface, read(0xA0, A<uint8_t&>()))
232 .Times(1)
233 .WillOnce(SetArgReferee<1>(0xB6));
234 EXPECT_CALL(*i2cInterface,
235 write(TypedEq<uint8_t>(0xA0), TypedEq<uint8_t>(0x96)))
236 .Times(1)
237 .WillOnce(Throw(
238 i2c::I2CException{"Failed to write byte", "/dev/i2c-1", 0x70}));
239
240 // Create Device, IDMap, and ActionEnvironment
241 Device device{"reg1", true, "/system/chassis/motherboard/reg1",
242 std::move(i2cInterface)};
243 IDMap idMap{};
244 idMap.addDevice(device);
245 ActionEnvironment env{idMap, "reg1"};
246
247 // Register value : 0xB6 = 1011 0110
248 // 0 in position 5 : 0x00 = --0- ----
249 // New register value: 0x96 = 1001 0110
250 I2CWriteBitAction action{0xA0, 5, 0};
251 action.execute(env);
252 ADD_FAILURE() << "Should not have reached this line.";
253 }
254 catch (const ActionError& e)
255 {
256 EXPECT_STREQ(e.what(), "ActionError: i2c_write_bit: { register: "
257 "0xA0, position: 5, value: 0 }");
258 try
259 {
260 // Re-throw inner I2CException
261 std::rethrow_if_nested(e);
262 ADD_FAILURE() << "Should not have reached this line.";
263 }
264 catch (const i2c::I2CException& ie)
265 {
266 EXPECT_STREQ(ie.what(), "I2CException: Failed to write byte: bus "
267 "/dev/i2c-1, addr 0x70");
268 }
269 catch (...)
270 {
271 ADD_FAILURE() << "Should not have caught exception.";
272 }
273 }
274 catch (...)
275 {
276 ADD_FAILURE() << "Should not have caught exception.";
277 }
278}
279
280TEST(I2CWriteBitActionTests, GetRegister)
281{
282 I2CWriteBitAction action{0x7C, 5, 1};
283 EXPECT_EQ(action.getRegister(), 0x7C);
284}
285
286TEST(I2CWriteBitActionTests, GetPosition)
287{
288 I2CWriteBitAction action{0x7C, 5, 1};
289 EXPECT_EQ(action.getPosition(), 5);
290}
291
292TEST(I2CWriteBitActionTests, GetValue)
293{
294 I2CWriteBitAction action{0x7C, 5, 1};
295 EXPECT_EQ(action.getValue(), 1);
296}
297
298TEST(I2CWriteBitActionTests, ToString)
299{
300 I2CWriteBitAction action{0x7C, 5, 1};
301 EXPECT_EQ(action.toString(),
302 "i2c_write_bit: { register: 0x7C, position: 5, value: 1 }");
303}