blob: 62d807adfd705b82f146da98aa47f00e73e0e71d [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"
Bob King73eacee2020-10-23 13:58:02 +080022#include "mock_services.hpp"
Shawn McCarney5ad53942020-02-20 09:33:55 -060023#include "mocked_i2c_interface.hpp"
24
25#include <cstdint>
26#include <memory>
27#include <stdexcept>
28#include <string>
29#include <utility>
30#include <vector>
31
32#include <gmock/gmock.h>
33#include <gtest/gtest.h>
34
35using namespace phosphor::power::regulators;
36
37using ::testing::NotNull;
38using ::testing::Return;
39using ::testing::SetArrayArgument;
40using ::testing::Throw;
41using ::testing::TypedEq;
42
43// Test for I2CCompareBytesAction(uint8_t reg,
44// const std::vector<uint8_t>& values)
45TEST(I2CCompareBytesActionTests, Constructor1)
46{
47 // Test where works
48 try
49 {
50 std::vector<uint8_t> values{0x56, 0x14, 0xDA};
51 I2CCompareBytesAction action{0x7C, values};
52
53 EXPECT_EQ(action.getRegister(), 0x7C);
54
55 EXPECT_EQ(action.getValues().size(), 3);
56 EXPECT_EQ(action.getValues()[0], 0x56);
57 EXPECT_EQ(action.getValues()[1], 0x14);
58 EXPECT_EQ(action.getValues()[2], 0xDA);
59
60 EXPECT_EQ(action.getMasks().size(), 3);
61 EXPECT_EQ(action.getMasks()[0], 0xFF);
62 EXPECT_EQ(action.getMasks()[1], 0xFF);
63 EXPECT_EQ(action.getMasks()[2], 0xFF);
64 }
65 catch (...)
66 {
67 ADD_FAILURE() << "Should not have caught exception.";
68 }
69
70 // Test where fails: Values vector is empty
71 try
72 {
73 std::vector<uint8_t> values{};
74 I2CCompareBytesAction action{0x7C, values};
75 ADD_FAILURE() << "Should not have reached this line.";
76 }
77 catch (const std::invalid_argument& e)
78 {
79 EXPECT_STREQ(e.what(), "Values vector is empty");
80 }
81 catch (...)
82 {
83 ADD_FAILURE() << "Should not have caught exception.";
84 }
85}
86
87// Test for I2CCompareBytesAction(uint8_t reg,
88// const std::vector<uint8_t>& values,
89// const std::vector<uint8_t>& masks)
90TEST(I2CCompareBytesActionTests, Constructor2)
91{
92 // Test where works
93 try
94 {
95 std::vector<uint8_t> values{0x56, 0x14};
96 std::vector<uint8_t> masks{0x7E, 0x3C};
97 I2CCompareBytesAction action{0xA0, values, masks};
98
99 EXPECT_EQ(action.getRegister(), 0xA0);
100
101 EXPECT_EQ(action.getValues().size(), 2);
102 EXPECT_EQ(action.getValues()[0], 0x56);
103 EXPECT_EQ(action.getValues()[1], 0x14);
104
105 EXPECT_EQ(action.getMasks().size(), 2);
106 EXPECT_EQ(action.getMasks()[0], 0x7E);
107 EXPECT_EQ(action.getMasks()[1], 0x3C);
108 }
109 catch (...)
110 {
111 ADD_FAILURE() << "Should not have caught exception.";
112 }
113
114 // Test where fails: Values vector is empty
115 try
116 {
117 std::vector<uint8_t> values{};
118 std::vector<uint8_t> masks{};
119 I2CCompareBytesAction action{0xA0, values, masks};
120 ADD_FAILURE() << "Should not have reached this line.";
121 }
122 catch (const std::invalid_argument& e)
123 {
124 EXPECT_STREQ(e.what(), "Values vector is empty");
125 }
126 catch (...)
127 {
128 ADD_FAILURE() << "Should not have caught exception.";
129 }
130
131 // Test where fails: Masks vector different size than values vector
132 try
133 {
134 std::vector<uint8_t> values{0x56, 0x14, 0xFE};
135 std::vector<uint8_t> masks{0x7E, 0x3C};
136 I2CCompareBytesAction action{0x7C, values, masks};
137 ADD_FAILURE() << "Should not have reached this line.";
138 }
139 catch (const std::invalid_argument& e)
140 {
141 EXPECT_STREQ(e.what(), "Masks vector has invalid size");
142 }
143 catch (...)
144 {
145 ADD_FAILURE() << "Should not have caught exception.";
146 }
147}
148
149TEST(I2CCompareBytesActionTests, Execute)
150{
151 // Test where works: Equal: Mask specified
152 try
153 {
154 // Create mock I2CInterface: read() returns values 0xD7, 0x96
155 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
156 std::make_unique<i2c::MockedI2CInterface>();
157 uint8_t actualValues[] = {0xD7, 0x96};
158 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
159 EXPECT_CALL(*i2cInterface, read(0xA0, TypedEq<uint8_t&>(2), NotNull(),
160 i2c::I2CInterface::Mode::I2C))
161 .Times(1)
162 .WillOnce(SetArrayArgument<2>(actualValues, actualValues + 2));
163
Bob King73eacee2020-10-23 13:58:02 +0800164 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800165 Device device{
166 "reg1", true,
167 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
168 std::move(i2cInterface)};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600169 IDMap idMap{};
170 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800171 MockServices services{};
172 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600173
174 // Actual values: 0xD7 = 1101 0111 0x96 = 1001 0110
175 // Masks : 0x7E = 0111 1110 0x3C = 0011 1100
176 // Results : 0x56 = 0101 0110 0x14 = 0001 0100
177 const std::vector<uint8_t> values{0x56, 0x14};
178 const std::vector<uint8_t> masks{0x7E, 0x3C};
179 I2CCompareBytesAction action{0xA0, values, masks};
180 EXPECT_EQ(action.execute(env), true);
181 }
182 catch (...)
183 {
184 ADD_FAILURE() << "Should not have caught exception.";
185 }
186
187 // Test where works: Equal: Mask not specified
188 try
189 {
190 // Create mock I2CInterface: read() returns values 0x56, 0x14, 0xDA
191 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
192 std::make_unique<i2c::MockedI2CInterface>();
193 uint8_t actualValues[] = {0x56, 0x14, 0xDA};
194 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
195 EXPECT_CALL(*i2cInterface, read(0x7C, TypedEq<uint8_t&>(3), NotNull(),
196 i2c::I2CInterface::Mode::I2C))
197 .Times(1)
198 .WillOnce(SetArrayArgument<2>(actualValues, actualValues + 3));
199
Bob King73eacee2020-10-23 13:58:02 +0800200 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800201 Device device{
202 "reg1", true,
203 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
204 std::move(i2cInterface)};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600205 IDMap idMap{};
206 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800207 MockServices services{};
208 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600209
210 std::vector<uint8_t> values{0x56, 0x14, 0xDA};
211 I2CCompareBytesAction action{0x7C, values};
212 EXPECT_EQ(action.execute(env), true);
213 }
214 catch (...)
215 {
216 ADD_FAILURE() << "Should not have caught exception.";
217 }
218
219 // Test where works: Not equal: Mask specified
220 try
221 {
222 // Create mock I2CInterface: read() returns values 0xD7, 0x96
223 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
224 std::make_unique<i2c::MockedI2CInterface>();
225 uint8_t actualValues[] = {0xD7, 0x96};
226 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
227 EXPECT_CALL(*i2cInterface, read(0xA0, TypedEq<uint8_t&>(2), NotNull(),
228 i2c::I2CInterface::Mode::I2C))
229 .Times(1)
230 .WillOnce(SetArrayArgument<2>(actualValues, actualValues + 2));
231
Bob King73eacee2020-10-23 13:58:02 +0800232 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800233 Device device{
234 "reg1", true,
235 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
236 std::move(i2cInterface)};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600237 IDMap idMap{};
238 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800239 MockServices services{};
240 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600241
242 // Actual values: 0xD7 = 1101 0111 0x96 = 1001 0110
243 // Masks : 0x7E = 0111 1110 0x3C = 0011 1100
244 // Results : 0x56 = 0101 0110 0x14 = 0001 0100
245 const std::vector<uint8_t> values{0x56, 0x13};
246 const std::vector<uint8_t> masks{0x7E, 0x3C};
247 I2CCompareBytesAction action{0xA0, values, masks};
248 EXPECT_EQ(action.execute(env), false);
249 }
250 catch (...)
251 {
252 ADD_FAILURE() << "Should not have caught exception.";
253 }
254
255 // Test where works: Not equal: Mask not specified
256 try
257 {
258 // Create mock I2CInterface: read() returns values 0x56, 0x14, 0xDA
259 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
260 std::make_unique<i2c::MockedI2CInterface>();
261 uint8_t actualValues[] = {0x56, 0x14, 0xDA};
262 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
263 EXPECT_CALL(*i2cInterface, read(0x7C, TypedEq<uint8_t&>(3), NotNull(),
264 i2c::I2CInterface::Mode::I2C))
265 .Times(1)
266 .WillOnce(SetArrayArgument<2>(actualValues, actualValues + 3));
267
Bob King73eacee2020-10-23 13:58:02 +0800268 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800269 Device device{
270 "reg1", true,
271 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
272 std::move(i2cInterface)};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600273 IDMap idMap{};
274 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800275 MockServices services{};
276 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600277
278 std::vector<uint8_t> values{0x56, 0x14, 0xDB};
279 I2CCompareBytesAction action{0x7C, values};
280 EXPECT_EQ(action.execute(env), false);
281 }
282 catch (...)
283 {
284 ADD_FAILURE() << "Should not have caught exception.";
285 }
286
287 // Test where works: Single byte
288 try
289 {
290 // Create mock I2CInterface: read() returns value 0xD7
291 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
292 std::make_unique<i2c::MockedI2CInterface>();
293 uint8_t actualValues[] = {0xD7};
294 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
295 EXPECT_CALL(*i2cInterface, read(0xA0, TypedEq<uint8_t&>(1), NotNull(),
296 i2c::I2CInterface::Mode::I2C))
297 .Times(1)
298 .WillOnce(SetArrayArgument<2>(actualValues, actualValues + 1));
299
Bob King73eacee2020-10-23 13:58:02 +0800300 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800301 Device device{
302 "reg1", true,
303 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
304 std::move(i2cInterface)};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600305 IDMap idMap{};
306 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800307 MockServices services{};
308 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600309
310 // Actual values: 0xD7 = 1101 0111
311 // Masks : 0x7E = 0111 1110
312 // Results : 0x56 = 0101 0110
313 std::vector<uint8_t> values{0x56};
314 std::vector<uint8_t> masks{0x7E};
315 I2CCompareBytesAction action{0xA0, values, masks};
316 EXPECT_EQ(action.execute(env), true);
317 }
318 catch (...)
319 {
320 ADD_FAILURE() << "Should not have caught exception.";
321 }
322
323 // Test where fails: Getting I2CInterface fails
324 try
325 {
Bob King73eacee2020-10-23 13:58:02 +0800326 // Create IDMap, MockServices, and ActionEnvironment
Shawn McCarney5ad53942020-02-20 09:33:55 -0600327 IDMap idMap{};
Bob King73eacee2020-10-23 13:58:02 +0800328 MockServices services{};
329 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600330
331 std::vector<uint8_t> values{0x56, 0x14, 0xDB};
332 I2CCompareBytesAction action{0x7C, values};
333 action.execute(env);
334 ADD_FAILURE() << "Should not have reached this line.";
335 }
336 catch (const std::invalid_argument& e)
337 {
338 EXPECT_STREQ(e.what(), "Unable to find device with ID \"reg1\"");
339 }
340 catch (...)
341 {
342 ADD_FAILURE() << "Should not have caught exception.";
343 }
344
345 // Test where fails: Reading bytes fails
346 try
347 {
348 // Create mock I2CInterface: read() throws an I2CException
349 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
350 std::make_unique<i2c::MockedI2CInterface>();
351 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
352 EXPECT_CALL(*i2cInterface, read(0x7C, TypedEq<uint8_t&>(2), NotNull(),
353 i2c::I2CInterface::Mode::I2C))
354 .Times(1)
355 .WillOnce(Throw(i2c::I2CException{"Failed to read i2c block data",
356 "/dev/i2c-1", 0x70}));
357
Bob King73eacee2020-10-23 13:58:02 +0800358 // Create Device, IDMap, MockServices, and ActionEnvironment
Bob Kinga76898f2020-10-13 15:08:33 +0800359 Device device{
360 "reg1", true,
361 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
362 std::move(i2cInterface)};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600363 IDMap idMap{};
364 idMap.addDevice(device);
Bob King73eacee2020-10-23 13:58:02 +0800365 MockServices services{};
366 ActionEnvironment env{idMap, "reg1", services};
Shawn McCarney5ad53942020-02-20 09:33:55 -0600367
368 std::vector<uint8_t> values{0x56, 0x14};
369 I2CCompareBytesAction action{0x7C, values};
370 action.execute(env);
371 ADD_FAILURE() << "Should not have reached this line.";
372 }
373 catch (const ActionError& e)
374 {
375 EXPECT_STREQ(e.what(),
376 "ActionError: i2c_compare_bytes: { register: "
377 "0x7C, values: [ 0x56, 0x14 ], masks: [ 0xFF, 0xFF ] }");
378 try
379 {
380 // Re-throw inner I2CException
381 std::rethrow_if_nested(e);
382 ADD_FAILURE() << "Should not have reached this line.";
383 }
384 catch (const i2c::I2CException& ie)
385 {
386 EXPECT_STREQ(ie.what(),
387 "I2CException: Failed to read i2c block data: bus "
388 "/dev/i2c-1, addr 0x70");
389 }
390 catch (...)
391 {
392 ADD_FAILURE() << "Should not have caught exception.";
393 }
394 }
395 catch (...)
396 {
397 ADD_FAILURE() << "Should not have caught exception.";
398 }
399}
400
401TEST(I2CCompareBytesActionTests, GetRegister)
402{
403 std::vector<uint8_t> values{0x56, 0x14};
404 I2CCompareBytesAction action{0xA0, values};
405 EXPECT_EQ(action.getRegister(), 0xA0);
406}
407
408TEST(I2CCompareBytesActionTests, GetValues)
409{
410 std::vector<uint8_t> values{0x56, 0x14};
411 std::vector<uint8_t> masks{0x7E, 0x3C};
412 I2CCompareBytesAction action{0xA0, values, masks};
413 EXPECT_EQ(action.getValues().size(), 2);
414 EXPECT_EQ(action.getValues()[0], 0x56);
415 EXPECT_EQ(action.getValues()[1], 0x14);
416}
417
418TEST(I2CCompareBytesActionTests, GetMasks)
419{
420 // Test where masks were not specified
421 {
422 std::vector<uint8_t> values{0x56, 0x14, 0xDA};
423 I2CCompareBytesAction action{0x7C, values};
424 EXPECT_EQ(action.getMasks().size(), 3);
425 EXPECT_EQ(action.getMasks()[0], 0xFF);
426 EXPECT_EQ(action.getMasks()[1], 0xFF);
427 EXPECT_EQ(action.getMasks()[2], 0xFF);
428 }
429
430 // Test where masks were specified
431 {
432 std::vector<uint8_t> values{0x56, 0x14};
433 std::vector<uint8_t> masks{0x7E, 0x3C};
434 I2CCompareBytesAction action{0xA0, values, masks};
435 EXPECT_EQ(action.getMasks().size(), 2);
436 EXPECT_EQ(action.getMasks()[0], 0x7E);
437 EXPECT_EQ(action.getMasks()[1], 0x3C);
438 }
439}
440
441TEST(I2CCompareBytesActionTests, ToString)
442{
443 std::vector<uint8_t> values{0x56, 0x14};
444 std::vector<uint8_t> masks{0x7E, 0x3C};
445 I2CCompareBytesAction action{0xA0, values, masks};
446 EXPECT_EQ(action.toString(), "i2c_compare_bytes: { register: 0xA0, values: "
447 "[ 0x56, 0x14 ], masks: [ 0x7E, 0x3C ] }");
448}