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 "device.hpp" 18 #include "i2c_action.hpp" 19 #include "i2c_interface.hpp" 20 #include "id_map.hpp" 21 #include "mocked_i2c_interface.hpp" 22 23 #include <memory> 24 #include <stdexcept> 25 #include <string> 26 #include <utility> 27 28 #include <gmock/gmock.h> 29 #include <gtest/gtest.h> 30 31 using namespace phosphor::power::regulators; 32 33 using ::testing::Return; 34 using ::testing::Throw; 35 36 /** 37 * Define a test implementation of the I2CAction abstract base class. 38 */ 39 class I2CActionImpl : public I2CAction 40 { 41 public: 42 virtual bool execute(ActionEnvironment& /* environment */) override 43 { 44 return true; 45 } 46 47 virtual std::string toString() const override 48 { 49 return "i2c_action_impl: {}"; 50 } 51 52 // Make test a friend so it can access protected getI2CInterface() method 53 FRIEND_TEST(I2CActionTests, GetI2CInterface); 54 }; 55 56 TEST(I2CActionTests, GetI2CInterface) 57 { 58 // Test where works: device was not open 59 try 60 { 61 // Create mock I2CInterface 62 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 63 std::make_unique<i2c::MockedI2CInterface>(); 64 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(false)); 65 EXPECT_CALL(*i2cInterface, open).Times(1); 66 67 // Create Device, IDMap, ActionEnvironment, and I2CAction 68 Device device{"reg1", true, "/system/chassis/motherboard/reg1", 69 std::move(i2cInterface)}; 70 IDMap idMap{}; 71 idMap.addDevice(device); 72 ActionEnvironment env{idMap, "reg1"}; 73 I2CActionImpl action{}; 74 75 // Get I2CInterface. Should succeed without an exception. 76 action.getI2CInterface(env); 77 } 78 catch (...) 79 { 80 ADD_FAILURE() << "Should not have caught exception."; 81 } 82 83 // Test where works: device was already open 84 try 85 { 86 // Create mock I2CInterface 87 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 88 std::make_unique<i2c::MockedI2CInterface>(); 89 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 90 EXPECT_CALL(*i2cInterface, open).Times(0); 91 92 // Create Device, IDMap, ActionEnvironment, and I2CAction 93 Device device{"reg1", true, "/system/chassis/motherboard/reg1", 94 std::move(i2cInterface)}; 95 IDMap idMap{}; 96 idMap.addDevice(device); 97 ActionEnvironment env{idMap, "reg1"}; 98 I2CActionImpl action{}; 99 100 // Get I2CInterface. Should succeed without an exception. 101 action.getI2CInterface(env); 102 } 103 catch (...) 104 { 105 ADD_FAILURE() << "Should not have caught exception."; 106 } 107 108 // Test where fails: getting current device fails 109 try 110 { 111 // Create IDMap, ActionEnvironment, and I2CAction 112 IDMap idMap{}; 113 ActionEnvironment env{idMap, "reg1"}; 114 I2CActionImpl action{}; 115 116 // Get I2CInterface. Should throw an exception since "reg1" is not a 117 // valid device in the IDMap. 118 action.getI2CInterface(env); 119 ADD_FAILURE() << "Should not have reached this line."; 120 } 121 catch (const std::invalid_argument& e) 122 { 123 EXPECT_STREQ(e.what(), "Unable to find device with ID \"reg1\""); 124 } 125 catch (...) 126 { 127 ADD_FAILURE() << "Should not have caught exception."; 128 } 129 130 // Test where fails: opening interface fails 131 try 132 { 133 // Create mock I2CInterface 134 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 135 std::make_unique<i2c::MockedI2CInterface>(); 136 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(false)); 137 EXPECT_CALL(*i2cInterface, open) 138 .Times(1) 139 .WillOnce( 140 Throw(i2c::I2CException{"Failed to open", "/dev/i2c-1", 0x70})); 141 142 // Create Device, IDMap, ActionEnvironment, and I2CAction 143 Device device{"reg1", true, "/system/chassis/motherboard/reg1", 144 std::move(i2cInterface)}; 145 IDMap idMap{}; 146 idMap.addDevice(device); 147 ActionEnvironment env{idMap, "reg1"}; 148 I2CActionImpl action{}; 149 150 // Get I2CInterface. Should throw an exception from the open() call. 151 action.getI2CInterface(env); 152 ADD_FAILURE() << "Should not have reached this line."; 153 } 154 catch (const i2c::I2CException& e) 155 { 156 EXPECT_STREQ(e.what(), 157 "I2CException: Failed to open: bus /dev/i2c-1, addr 0x70"); 158 } 159 catch (...) 160 { 161 ADD_FAILURE() << "Should not have caught exception."; 162 } 163 } 164