blob: 5685db75d6d037c70026a26c737e15763b034f6f [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
Bob Kinga76898f2020-10-13 15:08:33 +0800164 Device device{
165 "reg1", true,
166 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
167 std::move(i2cInterface)};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600168 IDMap idMap{};
169 idMap.addDevice(device);
170 ActionEnvironment env{idMap, "reg1"};
171
172 // Actual values: 0xD7 = 1101 0111 0x96 = 1001 0110
173 // Masks : 0x7E = 0111 1110 0x3C = 0011 1100
174 // Results : 0x56 = 0101 0110 0x14 = 0001 0100
175 const std::vector<uint8_t> values{0x56, 0x14};
176 const std::vector<uint8_t> masks{0x7E, 0x3C};
177 I2CCompareBytesAction action{0xA0, values, masks};
178 EXPECT_EQ(action.execute(env), true);
179 }
180 catch (...)
181 {
182 ADD_FAILURE() << "Should not have caught exception.";
183 }
184
185 // Test where works: Equal: Mask not specified
186 try
187 {
188 // Create mock I2CInterface: read() returns values 0x56, 0x14, 0xDA
189 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
190 std::make_unique<i2c::MockedI2CInterface>();
191 uint8_t actualValues[] = {0x56, 0x14, 0xDA};
192 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
193 EXPECT_CALL(*i2cInterface, read(0x7C, TypedEq<uint8_t&>(3), NotNull(),
194 i2c::I2CInterface::Mode::I2C))
195 .Times(1)
196 .WillOnce(SetArrayArgument<2>(actualValues, actualValues + 3));
197
198 // Create Device, IDMap, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800199 Device device{
200 "reg1", true,
201 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
202 std::move(i2cInterface)};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600203 IDMap idMap{};
204 idMap.addDevice(device);
205 ActionEnvironment env{idMap, "reg1"};
206
207 std::vector<uint8_t> values{0x56, 0x14, 0xDA};
208 I2CCompareBytesAction action{0x7C, values};
209 EXPECT_EQ(action.execute(env), true);
210 }
211 catch (...)
212 {
213 ADD_FAILURE() << "Should not have caught exception.";
214 }
215
216 // Test where works: Not equal: Mask specified
217 try
218 {
219 // Create mock I2CInterface: read() returns values 0xD7, 0x96
220 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
221 std::make_unique<i2c::MockedI2CInterface>();
222 uint8_t actualValues[] = {0xD7, 0x96};
223 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
224 EXPECT_CALL(*i2cInterface, read(0xA0, TypedEq<uint8_t&>(2), NotNull(),
225 i2c::I2CInterface::Mode::I2C))
226 .Times(1)
227 .WillOnce(SetArrayArgument<2>(actualValues, actualValues + 2));
228
229 // Create Device, IDMap, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800230 Device device{
231 "reg1", true,
232 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
233 std::move(i2cInterface)};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600234 IDMap idMap{};
235 idMap.addDevice(device);
236 ActionEnvironment env{idMap, "reg1"};
237
238 // Actual values: 0xD7 = 1101 0111 0x96 = 1001 0110
239 // Masks : 0x7E = 0111 1110 0x3C = 0011 1100
240 // Results : 0x56 = 0101 0110 0x14 = 0001 0100
241 const std::vector<uint8_t> values{0x56, 0x13};
242 const std::vector<uint8_t> masks{0x7E, 0x3C};
243 I2CCompareBytesAction action{0xA0, values, masks};
244 EXPECT_EQ(action.execute(env), false);
245 }
246 catch (...)
247 {
248 ADD_FAILURE() << "Should not have caught exception.";
249 }
250
251 // Test where works: Not equal: Mask not specified
252 try
253 {
254 // Create mock I2CInterface: read() returns values 0x56, 0x14, 0xDA
255 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
256 std::make_unique<i2c::MockedI2CInterface>();
257 uint8_t actualValues[] = {0x56, 0x14, 0xDA};
258 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
259 EXPECT_CALL(*i2cInterface, read(0x7C, TypedEq<uint8_t&>(3), NotNull(),
260 i2c::I2CInterface::Mode::I2C))
261 .Times(1)
262 .WillOnce(SetArrayArgument<2>(actualValues, actualValues + 3));
263
264 // Create Device, IDMap, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800265 Device device{
266 "reg1", true,
267 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
268 std::move(i2cInterface)};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600269 IDMap idMap{};
270 idMap.addDevice(device);
271 ActionEnvironment env{idMap, "reg1"};
272
273 std::vector<uint8_t> values{0x56, 0x14, 0xDB};
274 I2CCompareBytesAction action{0x7C, values};
275 EXPECT_EQ(action.execute(env), false);
276 }
277 catch (...)
278 {
279 ADD_FAILURE() << "Should not have caught exception.";
280 }
281
282 // Test where works: Single byte
283 try
284 {
285 // Create mock I2CInterface: read() returns value 0xD7
286 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
287 std::make_unique<i2c::MockedI2CInterface>();
288 uint8_t actualValues[] = {0xD7};
289 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
290 EXPECT_CALL(*i2cInterface, read(0xA0, TypedEq<uint8_t&>(1), NotNull(),
291 i2c::I2CInterface::Mode::I2C))
292 .Times(1)
293 .WillOnce(SetArrayArgument<2>(actualValues, actualValues + 1));
294
295 // Create Device, IDMap, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800296 Device device{
297 "reg1", true,
298 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
299 std::move(i2cInterface)};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600300 IDMap idMap{};
301 idMap.addDevice(device);
302 ActionEnvironment env{idMap, "reg1"};
303
304 // Actual values: 0xD7 = 1101 0111
305 // Masks : 0x7E = 0111 1110
306 // Results : 0x56 = 0101 0110
307 std::vector<uint8_t> values{0x56};
308 std::vector<uint8_t> masks{0x7E};
309 I2CCompareBytesAction action{0xA0, values, masks};
310 EXPECT_EQ(action.execute(env), true);
311 }
312 catch (...)
313 {
314 ADD_FAILURE() << "Should not have caught exception.";
315 }
316
317 // Test where fails: Getting I2CInterface fails
318 try
319 {
320 // Create IDMap and ActionEnvironment
321 IDMap idMap{};
322 ActionEnvironment env{idMap, "reg1"};
323
324 std::vector<uint8_t> values{0x56, 0x14, 0xDB};
325 I2CCompareBytesAction action{0x7C, values};
326 action.execute(env);
327 ADD_FAILURE() << "Should not have reached this line.";
328 }
329 catch (const std::invalid_argument& e)
330 {
331 EXPECT_STREQ(e.what(), "Unable to find device with ID \"reg1\"");
332 }
333 catch (...)
334 {
335 ADD_FAILURE() << "Should not have caught exception.";
336 }
337
338 // Test where fails: Reading bytes fails
339 try
340 {
341 // Create mock I2CInterface: read() throws an I2CException
342 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
343 std::make_unique<i2c::MockedI2CInterface>();
344 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
345 EXPECT_CALL(*i2cInterface, read(0x7C, TypedEq<uint8_t&>(2), NotNull(),
346 i2c::I2CInterface::Mode::I2C))
347 .Times(1)
348 .WillOnce(Throw(i2c::I2CException{"Failed to read i2c block data",
349 "/dev/i2c-1", 0x70}));
350
351 // Create Device, IDMap, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800352 Device device{
353 "reg1", true,
354 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
355 std::move(i2cInterface)};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600356 IDMap idMap{};
357 idMap.addDevice(device);
358 ActionEnvironment env{idMap, "reg1"};
359
360 std::vector<uint8_t> values{0x56, 0x14};
361 I2CCompareBytesAction action{0x7C, values};
362 action.execute(env);
363 ADD_FAILURE() << "Should not have reached this line.";
364 }
365 catch (const ActionError& e)
366 {
367 EXPECT_STREQ(e.what(),
368 "ActionError: i2c_compare_bytes: { register: "
369 "0x7C, values: [ 0x56, 0x14 ], masks: [ 0xFF, 0xFF ] }");
370 try
371 {
372 // Re-throw inner I2CException
373 std::rethrow_if_nested(e);
374 ADD_FAILURE() << "Should not have reached this line.";
375 }
376 catch (const i2c::I2CException& ie)
377 {
378 EXPECT_STREQ(ie.what(),
379 "I2CException: Failed to read i2c block data: bus "
380 "/dev/i2c-1, addr 0x70");
381 }
382 catch (...)
383 {
384 ADD_FAILURE() << "Should not have caught exception.";
385 }
386 }
387 catch (...)
388 {
389 ADD_FAILURE() << "Should not have caught exception.";
390 }
391}
392
393TEST(I2CCompareBytesActionTests, GetRegister)
394{
395 std::vector<uint8_t> values{0x56, 0x14};
396 I2CCompareBytesAction action{0xA0, values};
397 EXPECT_EQ(action.getRegister(), 0xA0);
398}
399
400TEST(I2CCompareBytesActionTests, GetValues)
401{
402 std::vector<uint8_t> values{0x56, 0x14};
403 std::vector<uint8_t> masks{0x7E, 0x3C};
404 I2CCompareBytesAction action{0xA0, values, masks};
405 EXPECT_EQ(action.getValues().size(), 2);
406 EXPECT_EQ(action.getValues()[0], 0x56);
407 EXPECT_EQ(action.getValues()[1], 0x14);
408}
409
410TEST(I2CCompareBytesActionTests, GetMasks)
411{
412 // Test where masks were not specified
413 {
414 std::vector<uint8_t> values{0x56, 0x14, 0xDA};
415 I2CCompareBytesAction action{0x7C, values};
416 EXPECT_EQ(action.getMasks().size(), 3);
417 EXPECT_EQ(action.getMasks()[0], 0xFF);
418 EXPECT_EQ(action.getMasks()[1], 0xFF);
419 EXPECT_EQ(action.getMasks()[2], 0xFF);
420 }
421
422 // Test where masks were specified
423 {
424 std::vector<uint8_t> values{0x56, 0x14};
425 std::vector<uint8_t> masks{0x7E, 0x3C};
426 I2CCompareBytesAction action{0xA0, values, masks};
427 EXPECT_EQ(action.getMasks().size(), 2);
428 EXPECT_EQ(action.getMasks()[0], 0x7E);
429 EXPECT_EQ(action.getMasks()[1], 0x3C);
430 }
431}
432
433TEST(I2CCompareBytesActionTests, ToString)
434{
435 std::vector<uint8_t> values{0x56, 0x14};
436 std::vector<uint8_t> masks{0x7E, 0x3C};
437 I2CCompareBytesAction action{0xA0, values, masks};
438 EXPECT_EQ(action.toString(), "i2c_compare_bytes: { register: 0xA0, values: "
439 "[ 0x56, 0x14 ], masks: [ 0x7E, 0x3C ] }");
440}