1 /**
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_bit_action.hpp"
20 #include "i2c_interface.hpp"
21 #include "id_map.hpp"
22 #include "mock_services.hpp"
23 #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
34 using namespace phosphor::power::regulators;
35
36 using ::testing::A;
37 using ::testing::Return;
38 using ::testing::SetArgReferee;
39 using ::testing::Throw;
40
TEST(I2CCompareBitActionTests,Constructor)41 TEST(I2CCompareBitActionTests, Constructor)
42 {
43 // Test where works
44 try
45 {
46 I2CCompareBitAction 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 I2CCompareBitAction 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 I2CCompareBitAction 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
TEST(I2CCompareBitActionTests,Execute)87 TEST(I2CCompareBitActionTests, Execute)
88 {
89 // Test where works
90 try
91 {
92 // Create mock I2CInterface: read() returns value 0x96 (1001 0110)
93 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
94 std::make_unique<i2c::MockedI2CInterface>();
95 EXPECT_CALL(*i2cInterface, isOpen).WillRepeatedly(Return(true));
96 EXPECT_CALL(*i2cInterface, read(0x7C, A<uint8_t&>()))
97 .WillRepeatedly(SetArgReferee<1>(0x96));
98
99 // Create Device, IDMap, MockServices, and ActionEnvironment
100 Device device{
101 "reg1", true,
102 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
103 std::move(i2cInterface)};
104 IDMap idMap{};
105 idMap.addDevice(device);
106 MockServices services{};
107 ActionEnvironment env{idMap, "reg1", services};
108
109 // Test where actual bit value is equal to expected bit value.
110 // Test all bits in register value 0x96 == 1001 0110).
111 {
112 I2CCompareBitAction actions[] = {
113 I2CCompareBitAction{0x7C, 7, 1},
114 I2CCompareBitAction{0x7C, 6, 0},
115 I2CCompareBitAction{0x7C, 5, 0},
116 I2CCompareBitAction{0x7C, 4, 1},
117 I2CCompareBitAction{0x7C, 3, 0},
118 I2CCompareBitAction{0x7C, 2, 1},
119 I2CCompareBitAction{0x7C, 1, 1},
120 I2CCompareBitAction{0x7C, 0, 0}};
121 for (I2CCompareBitAction& action : actions)
122 {
123 EXPECT_EQ(action.execute(env), true);
124 }
125 }
126
127 // Test where actual bit value is not equal to expected bit value.
128 // Test all bits in register value 0x96 == 1001 0110).
129 {
130 I2CCompareBitAction actions[] = {
131 I2CCompareBitAction{0x7C, 7, 0},
132 I2CCompareBitAction{0x7C, 6, 1},
133 I2CCompareBitAction{0x7C, 5, 1},
134 I2CCompareBitAction{0x7C, 4, 0},
135 I2CCompareBitAction{0x7C, 3, 1},
136 I2CCompareBitAction{0x7C, 2, 0},
137 I2CCompareBitAction{0x7C, 1, 0},
138 I2CCompareBitAction{0x7C, 0, 1}};
139 for (I2CCompareBitAction& action : actions)
140 {
141 EXPECT_EQ(action.execute(env), false);
142 }
143 }
144 }
145 catch (...)
146 {
147 ADD_FAILURE() << "Should not have caught exception.";
148 }
149
150 // Test where fails: Getting I2CInterface fails
151 try
152 {
153 // Create IDMap, MockServices, and ActionEnvironment
154 IDMap idMap{};
155 MockServices services{};
156 ActionEnvironment env{idMap, "reg1", services};
157
158 I2CCompareBitAction action{0x7C, 5, 1};
159 action.execute(env);
160 ADD_FAILURE() << "Should not have reached this line.";
161 }
162 catch (const std::invalid_argument& e)
163 {
164 EXPECT_STREQ(e.what(), "Unable to find device with ID \"reg1\"");
165 }
166 catch (...)
167 {
168 ADD_FAILURE() << "Should not have caught exception.";
169 }
170
171 // Test where fails: Reading byte fails
172 try
173 {
174 // Create mock I2CInterface: read() throws an I2CException
175 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
176 std::make_unique<i2c::MockedI2CInterface>();
177 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
178 EXPECT_CALL(*i2cInterface, read(0x7C, A<uint8_t&>()))
179 .Times(1)
180 .WillOnce(Throw(
181 i2c::I2CException{"Failed to read byte", "/dev/i2c-1", 0x70}));
182
183 // Create Device, IDMap, MockServices, and ActionEnvironment
184 Device device{
185 "reg1", true,
186 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
187 std::move(i2cInterface)};
188 IDMap idMap{};
189 idMap.addDevice(device);
190 MockServices services{};
191 ActionEnvironment env{idMap, "reg1", services};
192
193 I2CCompareBitAction 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_compare_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(I2CCompareBitActionTests,GetRegister)224 TEST(I2CCompareBitActionTests, GetRegister)
225 {
226 I2CCompareBitAction action{0x7C, 5, 1};
227 EXPECT_EQ(action.getRegister(), 0x7C);
228 }
229
TEST(I2CCompareBitActionTests,GetPosition)230 TEST(I2CCompareBitActionTests, GetPosition)
231 {
232 I2CCompareBitAction action{0x7C, 5, 1};
233 EXPECT_EQ(action.getPosition(), 5);
234 }
235
TEST(I2CCompareBitActionTests,GetValue)236 TEST(I2CCompareBitActionTests, GetValue)
237 {
238 I2CCompareBitAction action{0x7C, 5, 1};
239 EXPECT_EQ(action.getValue(), 1);
240 }
241
TEST(I2CCompareBitActionTests,ToString)242 TEST(I2CCompareBitActionTests, ToString)
243 {
244 I2CCompareBitAction action{0x7C, 5, 1};
245 EXPECT_EQ(action.toString(),
246 "i2c_compare_bit: { register: 0x7C, position: 5, value: 1 }");
247 }
248