blob: d03b35878233a781270edc87347e45b7c3e4918b [file] [log] [blame]
Shawn McCarney5ad53942020-02-20 09:33:55 -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_compare_bytes_action.hpp"
20#include "i2c_interface.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#include <vector>
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
42// Test for I2CCompareBytesAction(uint8_t reg,
43// const std::vector<uint8_t>& values)
44TEST(I2CCompareBytesActionTests, Constructor1)
45{
46 // Test where works
47 try
48 {
49 std::vector<uint8_t> values{0x56, 0x14, 0xDA};
50 I2CCompareBytesAction action{0x7C, values};
51
52 EXPECT_EQ(action.getRegister(), 0x7C);
53
54 EXPECT_EQ(action.getValues().size(), 3);
55 EXPECT_EQ(action.getValues()[0], 0x56);
56 EXPECT_EQ(action.getValues()[1], 0x14);
57 EXPECT_EQ(action.getValues()[2], 0xDA);
58
59 EXPECT_EQ(action.getMasks().size(), 3);
60 EXPECT_EQ(action.getMasks()[0], 0xFF);
61 EXPECT_EQ(action.getMasks()[1], 0xFF);
62 EXPECT_EQ(action.getMasks()[2], 0xFF);
63 }
64 catch (...)
65 {
66 ADD_FAILURE() << "Should not have caught exception.";
67 }
68
69 // Test where fails: Values vector is empty
70 try
71 {
72 std::vector<uint8_t> values{};
73 I2CCompareBytesAction action{0x7C, values};
74 ADD_FAILURE() << "Should not have reached this line.";
75 }
76 catch (const std::invalid_argument& e)
77 {
78 EXPECT_STREQ(e.what(), "Values vector is empty");
79 }
80 catch (...)
81 {
82 ADD_FAILURE() << "Should not have caught exception.";
83 }
84}
85
86// Test for I2CCompareBytesAction(uint8_t reg,
87// const std::vector<uint8_t>& values,
88// const std::vector<uint8_t>& masks)
89TEST(I2CCompareBytesActionTests, Constructor2)
90{
91 // Test where works
92 try
93 {
94 std::vector<uint8_t> values{0x56, 0x14};
95 std::vector<uint8_t> masks{0x7E, 0x3C};
96 I2CCompareBytesAction action{0xA0, values, masks};
97
98 EXPECT_EQ(action.getRegister(), 0xA0);
99
100 EXPECT_EQ(action.getValues().size(), 2);
101 EXPECT_EQ(action.getValues()[0], 0x56);
102 EXPECT_EQ(action.getValues()[1], 0x14);
103
104 EXPECT_EQ(action.getMasks().size(), 2);
105 EXPECT_EQ(action.getMasks()[0], 0x7E);
106 EXPECT_EQ(action.getMasks()[1], 0x3C);
107 }
108 catch (...)
109 {
110 ADD_FAILURE() << "Should not have caught exception.";
111 }
112
113 // Test where fails: Values vector is empty
114 try
115 {
116 std::vector<uint8_t> values{};
117 std::vector<uint8_t> masks{};
118 I2CCompareBytesAction action{0xA0, values, masks};
119 ADD_FAILURE() << "Should not have reached this line.";
120 }
121 catch (const std::invalid_argument& e)
122 {
123 EXPECT_STREQ(e.what(), "Values vector is empty");
124 }
125 catch (...)
126 {
127 ADD_FAILURE() << "Should not have caught exception.";
128 }
129
130 // Test where fails: Masks vector different size than values vector
131 try
132 {
133 std::vector<uint8_t> values{0x56, 0x14, 0xFE};
134 std::vector<uint8_t> masks{0x7E, 0x3C};
135 I2CCompareBytesAction action{0x7C, values, masks};
136 ADD_FAILURE() << "Should not have reached this line.";
137 }
138 catch (const std::invalid_argument& e)
139 {
140 EXPECT_STREQ(e.what(), "Masks vector has invalid size");
141 }
142 catch (...)
143 {
144 ADD_FAILURE() << "Should not have caught exception.";
145 }
146}
147
148TEST(I2CCompareBytesActionTests, Execute)
149{
150 // Test where works: Equal: Mask specified
151 try
152 {
153 // Create mock I2CInterface: read() returns values 0xD7, 0x96
154 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
155 std::make_unique<i2c::MockedI2CInterface>();
156 uint8_t actualValues[] = {0xD7, 0x96};
157 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
158 EXPECT_CALL(*i2cInterface, read(0xA0, TypedEq<uint8_t&>(2), NotNull(),
159 i2c::I2CInterface::Mode::I2C))
160 .Times(1)
161 .WillOnce(SetArrayArgument<2>(actualValues, actualValues + 2));
162
163 // Create Device, IDMap, and ActionEnvironment
164 Device device{"reg1", true, "/system/chassis/motherboard/reg1",
165 std::move(i2cInterface)};
166 IDMap idMap{};
167 idMap.addDevice(device);
168 ActionEnvironment env{idMap, "reg1"};
169
170 // Actual values: 0xD7 = 1101 0111 0x96 = 1001 0110
171 // Masks : 0x7E = 0111 1110 0x3C = 0011 1100
172 // Results : 0x56 = 0101 0110 0x14 = 0001 0100
173 const std::vector<uint8_t> values{0x56, 0x14};
174 const std::vector<uint8_t> masks{0x7E, 0x3C};
175 I2CCompareBytesAction action{0xA0, values, masks};
176 EXPECT_EQ(action.execute(env), true);
177 }
178 catch (...)
179 {
180 ADD_FAILURE() << "Should not have caught exception.";
181 }
182
183 // Test where works: Equal: Mask not specified
184 try
185 {
186 // Create mock I2CInterface: read() returns values 0x56, 0x14, 0xDA
187 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
188 std::make_unique<i2c::MockedI2CInterface>();
189 uint8_t actualValues[] = {0x56, 0x14, 0xDA};
190 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
191 EXPECT_CALL(*i2cInterface, read(0x7C, TypedEq<uint8_t&>(3), NotNull(),
192 i2c::I2CInterface::Mode::I2C))
193 .Times(1)
194 .WillOnce(SetArrayArgument<2>(actualValues, actualValues + 3));
195
196 // Create Device, IDMap, and ActionEnvironment
197 Device device{"reg1", true, "/system/chassis/motherboard/reg1",
198 std::move(i2cInterface)};
199 IDMap idMap{};
200 idMap.addDevice(device);
201 ActionEnvironment env{idMap, "reg1"};
202
203 std::vector<uint8_t> values{0x56, 0x14, 0xDA};
204 I2CCompareBytesAction action{0x7C, values};
205 EXPECT_EQ(action.execute(env), true);
206 }
207 catch (...)
208 {
209 ADD_FAILURE() << "Should not have caught exception.";
210 }
211
212 // Test where works: Not equal: Mask specified
213 try
214 {
215 // Create mock I2CInterface: read() returns values 0xD7, 0x96
216 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
217 std::make_unique<i2c::MockedI2CInterface>();
218 uint8_t actualValues[] = {0xD7, 0x96};
219 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
220 EXPECT_CALL(*i2cInterface, read(0xA0, TypedEq<uint8_t&>(2), NotNull(),
221 i2c::I2CInterface::Mode::I2C))
222 .Times(1)
223 .WillOnce(SetArrayArgument<2>(actualValues, actualValues + 2));
224
225 // Create Device, IDMap, and ActionEnvironment
226 Device device{"reg1", true, "/system/chassis/motherboard/reg1",
227 std::move(i2cInterface)};
228 IDMap idMap{};
229 idMap.addDevice(device);
230 ActionEnvironment env{idMap, "reg1"};
231
232 // Actual values: 0xD7 = 1101 0111 0x96 = 1001 0110
233 // Masks : 0x7E = 0111 1110 0x3C = 0011 1100
234 // Results : 0x56 = 0101 0110 0x14 = 0001 0100
235 const std::vector<uint8_t> values{0x56, 0x13};
236 const std::vector<uint8_t> masks{0x7E, 0x3C};
237 I2CCompareBytesAction action{0xA0, values, masks};
238 EXPECT_EQ(action.execute(env), false);
239 }
240 catch (...)
241 {
242 ADD_FAILURE() << "Should not have caught exception.";
243 }
244
245 // Test where works: Not equal: Mask not specified
246 try
247 {
248 // Create mock I2CInterface: read() returns values 0x56, 0x14, 0xDA
249 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
250 std::make_unique<i2c::MockedI2CInterface>();
251 uint8_t actualValues[] = {0x56, 0x14, 0xDA};
252 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
253 EXPECT_CALL(*i2cInterface, read(0x7C, TypedEq<uint8_t&>(3), NotNull(),
254 i2c::I2CInterface::Mode::I2C))
255 .Times(1)
256 .WillOnce(SetArrayArgument<2>(actualValues, actualValues + 3));
257
258 // Create Device, IDMap, and ActionEnvironment
259 Device device{"reg1", true, "/system/chassis/motherboard/reg1",
260 std::move(i2cInterface)};
261 IDMap idMap{};
262 idMap.addDevice(device);
263 ActionEnvironment env{idMap, "reg1"};
264
265 std::vector<uint8_t> values{0x56, 0x14, 0xDB};
266 I2CCompareBytesAction action{0x7C, values};
267 EXPECT_EQ(action.execute(env), false);
268 }
269 catch (...)
270 {
271 ADD_FAILURE() << "Should not have caught exception.";
272 }
273
274 // Test where works: Single byte
275 try
276 {
277 // Create mock I2CInterface: read() returns value 0xD7
278 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
279 std::make_unique<i2c::MockedI2CInterface>();
280 uint8_t actualValues[] = {0xD7};
281 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
282 EXPECT_CALL(*i2cInterface, read(0xA0, TypedEq<uint8_t&>(1), NotNull(),
283 i2c::I2CInterface::Mode::I2C))
284 .Times(1)
285 .WillOnce(SetArrayArgument<2>(actualValues, actualValues + 1));
286
287 // Create Device, IDMap, and ActionEnvironment
288 Device device{"reg1", true, "/system/chassis/motherboard/reg1",
289 std::move(i2cInterface)};
290 IDMap idMap{};
291 idMap.addDevice(device);
292 ActionEnvironment env{idMap, "reg1"};
293
294 // Actual values: 0xD7 = 1101 0111
295 // Masks : 0x7E = 0111 1110
296 // Results : 0x56 = 0101 0110
297 std::vector<uint8_t> values{0x56};
298 std::vector<uint8_t> masks{0x7E};
299 I2CCompareBytesAction action{0xA0, values, masks};
300 EXPECT_EQ(action.execute(env), true);
301 }
302 catch (...)
303 {
304 ADD_FAILURE() << "Should not have caught exception.";
305 }
306
307 // Test where fails: Getting I2CInterface fails
308 try
309 {
310 // Create IDMap and ActionEnvironment
311 IDMap idMap{};
312 ActionEnvironment env{idMap, "reg1"};
313
314 std::vector<uint8_t> values{0x56, 0x14, 0xDB};
315 I2CCompareBytesAction action{0x7C, values};
316 action.execute(env);
317 ADD_FAILURE() << "Should not have reached this line.";
318 }
319 catch (const std::invalid_argument& e)
320 {
321 EXPECT_STREQ(e.what(), "Unable to find device with ID \"reg1\"");
322 }
323 catch (...)
324 {
325 ADD_FAILURE() << "Should not have caught exception.";
326 }
327
328 // Test where fails: Reading bytes fails
329 try
330 {
331 // Create mock I2CInterface: read() throws an I2CException
332 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
333 std::make_unique<i2c::MockedI2CInterface>();
334 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
335 EXPECT_CALL(*i2cInterface, read(0x7C, TypedEq<uint8_t&>(2), NotNull(),
336 i2c::I2CInterface::Mode::I2C))
337 .Times(1)
338 .WillOnce(Throw(i2c::I2CException{"Failed to read i2c block data",
339 "/dev/i2c-1", 0x70}));
340
341 // Create Device, IDMap, and ActionEnvironment
342 Device device{"reg1", true, "/system/chassis/motherboard/reg1",
343 std::move(i2cInterface)};
344 IDMap idMap{};
345 idMap.addDevice(device);
346 ActionEnvironment env{idMap, "reg1"};
347
348 std::vector<uint8_t> values{0x56, 0x14};
349 I2CCompareBytesAction action{0x7C, values};
350 action.execute(env);
351 ADD_FAILURE() << "Should not have reached this line.";
352 }
353 catch (const ActionError& e)
354 {
355 EXPECT_STREQ(e.what(),
356 "ActionError: i2c_compare_bytes: { register: "
357 "0x7C, values: [ 0x56, 0x14 ], masks: [ 0xFF, 0xFF ] }");
358 try
359 {
360 // Re-throw inner I2CException
361 std::rethrow_if_nested(e);
362 ADD_FAILURE() << "Should not have reached this line.";
363 }
364 catch (const i2c::I2CException& ie)
365 {
366 EXPECT_STREQ(ie.what(),
367 "I2CException: Failed to read i2c block data: bus "
368 "/dev/i2c-1, addr 0x70");
369 }
370 catch (...)
371 {
372 ADD_FAILURE() << "Should not have caught exception.";
373 }
374 }
375 catch (...)
376 {
377 ADD_FAILURE() << "Should not have caught exception.";
378 }
379}
380
381TEST(I2CCompareBytesActionTests, GetRegister)
382{
383 std::vector<uint8_t> values{0x56, 0x14};
384 I2CCompareBytesAction action{0xA0, values};
385 EXPECT_EQ(action.getRegister(), 0xA0);
386}
387
388TEST(I2CCompareBytesActionTests, GetValues)
389{
390 std::vector<uint8_t> values{0x56, 0x14};
391 std::vector<uint8_t> masks{0x7E, 0x3C};
392 I2CCompareBytesAction action{0xA0, values, masks};
393 EXPECT_EQ(action.getValues().size(), 2);
394 EXPECT_EQ(action.getValues()[0], 0x56);
395 EXPECT_EQ(action.getValues()[1], 0x14);
396}
397
398TEST(I2CCompareBytesActionTests, GetMasks)
399{
400 // Test where masks were not specified
401 {
402 std::vector<uint8_t> values{0x56, 0x14, 0xDA};
403 I2CCompareBytesAction action{0x7C, values};
404 EXPECT_EQ(action.getMasks().size(), 3);
405 EXPECT_EQ(action.getMasks()[0], 0xFF);
406 EXPECT_EQ(action.getMasks()[1], 0xFF);
407 EXPECT_EQ(action.getMasks()[2], 0xFF);
408 }
409
410 // Test where masks were specified
411 {
412 std::vector<uint8_t> values{0x56, 0x14};
413 std::vector<uint8_t> masks{0x7E, 0x3C};
414 I2CCompareBytesAction action{0xA0, values, masks};
415 EXPECT_EQ(action.getMasks().size(), 2);
416 EXPECT_EQ(action.getMasks()[0], 0x7E);
417 EXPECT_EQ(action.getMasks()[1], 0x3C);
418 }
419}
420
421TEST(I2CCompareBytesActionTests, ToString)
422{
423 std::vector<uint8_t> values{0x56, 0x14};
424 std::vector<uint8_t> masks{0x7E, 0x3C};
425 I2CCompareBytesAction action{0xA0, values, masks};
426 EXPECT_EQ(action.toString(), "i2c_compare_bytes: { register: 0xA0, values: "
427 "[ 0x56, 0x14 ], masks: [ 0x7E, 0x3C ] }");
428}