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 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 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[] = {I2CCompareBitAction{0x7C, 7, 1}, 113 I2CCompareBitAction{0x7C, 6, 0}, 114 I2CCompareBitAction{0x7C, 5, 0}, 115 I2CCompareBitAction{0x7C, 4, 1}, 116 I2CCompareBitAction{0x7C, 3, 0}, 117 I2CCompareBitAction{0x7C, 2, 1}, 118 I2CCompareBitAction{0x7C, 1, 1}, 119 I2CCompareBitAction{0x7C, 0, 0}}; 120 for (I2CCompareBitAction& action : actions) 121 { 122 EXPECT_EQ(action.execute(env), true); 123 } 124 } 125 126 // Test where actual bit value is not equal to expected bit value. 127 // Test all bits in register value 0x96 == 1001 0110). 128 { 129 I2CCompareBitAction actions[] = {I2CCompareBitAction{0x7C, 7, 0}, 130 I2CCompareBitAction{0x7C, 6, 1}, 131 I2CCompareBitAction{0x7C, 5, 1}, 132 I2CCompareBitAction{0x7C, 4, 0}, 133 I2CCompareBitAction{0x7C, 3, 1}, 134 I2CCompareBitAction{0x7C, 2, 0}, 135 I2CCompareBitAction{0x7C, 1, 0}, 136 I2CCompareBitAction{0x7C, 0, 1}}; 137 for (I2CCompareBitAction& action : actions) 138 { 139 EXPECT_EQ(action.execute(env), false); 140 } 141 } 142 } 143 catch (...) 144 { 145 ADD_FAILURE() << "Should not have caught exception."; 146 } 147 148 // Test where fails: Getting I2CInterface fails 149 try 150 { 151 // Create IDMap, MockServices, and ActionEnvironment 152 IDMap idMap{}; 153 MockServices services{}; 154 ActionEnvironment env{idMap, "reg1", services}; 155 156 I2CCompareBitAction action{0x7C, 5, 1}; 157 action.execute(env); 158 ADD_FAILURE() << "Should not have reached this line."; 159 } 160 catch (const std::invalid_argument& e) 161 { 162 EXPECT_STREQ(e.what(), "Unable to find device with ID \"reg1\""); 163 } 164 catch (...) 165 { 166 ADD_FAILURE() << "Should not have caught exception."; 167 } 168 169 // Test where fails: Reading byte fails 170 try 171 { 172 // Create mock I2CInterface: read() throws an I2CException 173 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 174 std::make_unique<i2c::MockedI2CInterface>(); 175 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 176 EXPECT_CALL(*i2cInterface, read(0x7C, A<uint8_t&>())) 177 .Times(1) 178 .WillOnce(Throw( 179 i2c::I2CException{"Failed to read byte", "/dev/i2c-1", 0x70})); 180 181 // Create Device, IDMap, MockServices, and ActionEnvironment 182 Device device{ 183 "reg1", true, 184 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 185 std::move(i2cInterface)}; 186 IDMap idMap{}; 187 idMap.addDevice(device); 188 MockServices services{}; 189 ActionEnvironment env{idMap, "reg1", services}; 190 191 I2CCompareBitAction action{0x7C, 5, 1}; 192 action.execute(env); 193 ADD_FAILURE() << "Should not have reached this line."; 194 } 195 catch (const ActionError& e) 196 { 197 EXPECT_STREQ(e.what(), "ActionError: i2c_compare_bit: { register: " 198 "0x7C, position: 5, value: 1 }"); 199 try 200 { 201 // Re-throw inner I2CException 202 std::rethrow_if_nested(e); 203 ADD_FAILURE() << "Should not have reached this line."; 204 } 205 catch (const i2c::I2CException& ie) 206 { 207 EXPECT_STREQ( 208 ie.what(), 209 "I2CException: Failed to read byte: bus /dev/i2c-1, addr 0x70"); 210 } 211 catch (...) 212 { 213 ADD_FAILURE() << "Should not have caught exception."; 214 } 215 } 216 catch (...) 217 { 218 ADD_FAILURE() << "Should not have caught exception."; 219 } 220 } 221 222 TEST(I2CCompareBitActionTests, GetRegister) 223 { 224 I2CCompareBitAction action{0x7C, 5, 1}; 225 EXPECT_EQ(action.getRegister(), 0x7C); 226 } 227 228 TEST(I2CCompareBitActionTests, GetPosition) 229 { 230 I2CCompareBitAction action{0x7C, 5, 1}; 231 EXPECT_EQ(action.getPosition(), 5); 232 } 233 234 TEST(I2CCompareBitActionTests, GetValue) 235 { 236 I2CCompareBitAction action{0x7C, 5, 1}; 237 EXPECT_EQ(action.getValue(), 1); 238 } 239 240 TEST(I2CCompareBitActionTests, ToString) 241 { 242 I2CCompareBitAction action{0x7C, 5, 1}; 243 EXPECT_EQ(action.toString(), 244 "i2c_compare_bit: { register: 0x7C, position: 5, value: 1 }"); 245 } 246