1*b38da99fSShawn McCarney /** 2*b38da99fSShawn McCarney * Copyright © 2020 IBM Corporation 3*b38da99fSShawn McCarney * 4*b38da99fSShawn McCarney * Licensed under the Apache License, Version 2.0 (the "License"); 5*b38da99fSShawn McCarney * you may not use this file except in compliance with the License. 6*b38da99fSShawn McCarney * You may obtain a copy of the License at 7*b38da99fSShawn McCarney * 8*b38da99fSShawn McCarney * http://www.apache.org/licenses/LICENSE-2.0 9*b38da99fSShawn McCarney * 10*b38da99fSShawn McCarney * Unless required by applicable law or agreed to in writing, software 11*b38da99fSShawn McCarney * distributed under the License is distributed on an "AS IS" BASIS, 12*b38da99fSShawn McCarney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*b38da99fSShawn McCarney * See the License for the specific language governing permissions and 14*b38da99fSShawn McCarney * limitations under the License. 15*b38da99fSShawn McCarney */ 16*b38da99fSShawn McCarney #include "action_environment.hpp" 17*b38da99fSShawn McCarney #include "device.hpp" 18*b38da99fSShawn McCarney #include "i2c_action.hpp" 19*b38da99fSShawn McCarney #include "i2c_interface.hpp" 20*b38da99fSShawn McCarney #include "id_map.hpp" 21*b38da99fSShawn McCarney #include "mocked_i2c_interface.hpp" 22*b38da99fSShawn McCarney 23*b38da99fSShawn McCarney #include <memory> 24*b38da99fSShawn McCarney #include <stdexcept> 25*b38da99fSShawn McCarney #include <string> 26*b38da99fSShawn McCarney #include <utility> 27*b38da99fSShawn McCarney 28*b38da99fSShawn McCarney #include <gmock/gmock.h> 29*b38da99fSShawn McCarney #include <gtest/gtest.h> 30*b38da99fSShawn McCarney 31*b38da99fSShawn McCarney using namespace phosphor::power::regulators; 32*b38da99fSShawn McCarney 33*b38da99fSShawn McCarney using ::testing::Return; 34*b38da99fSShawn McCarney using ::testing::Throw; 35*b38da99fSShawn McCarney 36*b38da99fSShawn McCarney /** 37*b38da99fSShawn McCarney * Define a test implementation of the I2CAction abstract base class. 38*b38da99fSShawn McCarney */ 39*b38da99fSShawn McCarney class I2CActionImpl : public I2CAction 40*b38da99fSShawn McCarney { 41*b38da99fSShawn McCarney public: 42*b38da99fSShawn McCarney virtual bool execute(ActionEnvironment& /* environment */) override 43*b38da99fSShawn McCarney { 44*b38da99fSShawn McCarney return true; 45*b38da99fSShawn McCarney } 46*b38da99fSShawn McCarney 47*b38da99fSShawn McCarney virtual std::string toString() const override 48*b38da99fSShawn McCarney { 49*b38da99fSShawn McCarney return "i2c_action_impl: {}"; 50*b38da99fSShawn McCarney } 51*b38da99fSShawn McCarney 52*b38da99fSShawn McCarney // Make test a friend so it can access protected getI2CInterface() method 53*b38da99fSShawn McCarney FRIEND_TEST(I2CActionTests, GetI2CInterface); 54*b38da99fSShawn McCarney }; 55*b38da99fSShawn McCarney 56*b38da99fSShawn McCarney TEST(I2CActionTests, GetI2CInterface) 57*b38da99fSShawn McCarney { 58*b38da99fSShawn McCarney // Test where works: device was not open 59*b38da99fSShawn McCarney try 60*b38da99fSShawn McCarney { 61*b38da99fSShawn McCarney // Create mock I2CInterface 62*b38da99fSShawn McCarney std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 63*b38da99fSShawn McCarney std::make_unique<i2c::MockedI2CInterface>(); 64*b38da99fSShawn McCarney EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(false)); 65*b38da99fSShawn McCarney EXPECT_CALL(*i2cInterface, open).Times(1); 66*b38da99fSShawn McCarney 67*b38da99fSShawn McCarney // Create Device, IDMap, ActionEnvironment, and I2CAction 68*b38da99fSShawn McCarney Device device{"reg1", true, "/system/chassis/motherboard/reg1", 69*b38da99fSShawn McCarney std::move(i2cInterface)}; 70*b38da99fSShawn McCarney IDMap idMap{}; 71*b38da99fSShawn McCarney idMap.addDevice(device); 72*b38da99fSShawn McCarney ActionEnvironment env{idMap, "reg1"}; 73*b38da99fSShawn McCarney I2CActionImpl action{}; 74*b38da99fSShawn McCarney 75*b38da99fSShawn McCarney // Get I2CInterface. Should succeed without an exception. 76*b38da99fSShawn McCarney action.getI2CInterface(env); 77*b38da99fSShawn McCarney } 78*b38da99fSShawn McCarney catch (...) 79*b38da99fSShawn McCarney { 80*b38da99fSShawn McCarney ADD_FAILURE() << "Should not have caught exception."; 81*b38da99fSShawn McCarney } 82*b38da99fSShawn McCarney 83*b38da99fSShawn McCarney // Test where works: device was already open 84*b38da99fSShawn McCarney try 85*b38da99fSShawn McCarney { 86*b38da99fSShawn McCarney // Create mock I2CInterface 87*b38da99fSShawn McCarney std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 88*b38da99fSShawn McCarney std::make_unique<i2c::MockedI2CInterface>(); 89*b38da99fSShawn McCarney EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 90*b38da99fSShawn McCarney EXPECT_CALL(*i2cInterface, open).Times(0); 91*b38da99fSShawn McCarney 92*b38da99fSShawn McCarney // Create Device, IDMap, ActionEnvironment, and I2CAction 93*b38da99fSShawn McCarney Device device{"reg1", true, "/system/chassis/motherboard/reg1", 94*b38da99fSShawn McCarney std::move(i2cInterface)}; 95*b38da99fSShawn McCarney IDMap idMap{}; 96*b38da99fSShawn McCarney idMap.addDevice(device); 97*b38da99fSShawn McCarney ActionEnvironment env{idMap, "reg1"}; 98*b38da99fSShawn McCarney I2CActionImpl action{}; 99*b38da99fSShawn McCarney 100*b38da99fSShawn McCarney // Get I2CInterface. Should succeed without an exception. 101*b38da99fSShawn McCarney action.getI2CInterface(env); 102*b38da99fSShawn McCarney } 103*b38da99fSShawn McCarney catch (...) 104*b38da99fSShawn McCarney { 105*b38da99fSShawn McCarney ADD_FAILURE() << "Should not have caught exception."; 106*b38da99fSShawn McCarney } 107*b38da99fSShawn McCarney 108*b38da99fSShawn McCarney // Test where fails: getting current device fails 109*b38da99fSShawn McCarney try 110*b38da99fSShawn McCarney { 111*b38da99fSShawn McCarney // Create IDMap, ActionEnvironment, and I2CAction 112*b38da99fSShawn McCarney IDMap idMap{}; 113*b38da99fSShawn McCarney ActionEnvironment env{idMap, "reg1"}; 114*b38da99fSShawn McCarney I2CActionImpl action{}; 115*b38da99fSShawn McCarney 116*b38da99fSShawn McCarney // Get I2CInterface. Should throw an exception since "reg1" is not a 117*b38da99fSShawn McCarney // valid device in the IDMap. 118*b38da99fSShawn McCarney action.getI2CInterface(env); 119*b38da99fSShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 120*b38da99fSShawn McCarney } 121*b38da99fSShawn McCarney catch (const std::invalid_argument& e) 122*b38da99fSShawn McCarney { 123*b38da99fSShawn McCarney EXPECT_STREQ(e.what(), "Unable to find device with ID \"reg1\""); 124*b38da99fSShawn McCarney } 125*b38da99fSShawn McCarney catch (...) 126*b38da99fSShawn McCarney { 127*b38da99fSShawn McCarney ADD_FAILURE() << "Should not have caught exception."; 128*b38da99fSShawn McCarney } 129*b38da99fSShawn McCarney 130*b38da99fSShawn McCarney // Test where fails: opening interface fails 131*b38da99fSShawn McCarney try 132*b38da99fSShawn McCarney { 133*b38da99fSShawn McCarney // Create mock I2CInterface 134*b38da99fSShawn McCarney std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 135*b38da99fSShawn McCarney std::make_unique<i2c::MockedI2CInterface>(); 136*b38da99fSShawn McCarney EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(false)); 137*b38da99fSShawn McCarney EXPECT_CALL(*i2cInterface, open) 138*b38da99fSShawn McCarney .Times(1) 139*b38da99fSShawn McCarney .WillOnce( 140*b38da99fSShawn McCarney Throw(i2c::I2CException{"Failed to open", "/dev/i2c-1", 0x70})); 141*b38da99fSShawn McCarney 142*b38da99fSShawn McCarney // Create Device, IDMap, ActionEnvironment, and I2CAction 143*b38da99fSShawn McCarney Device device{"reg1", true, "/system/chassis/motherboard/reg1", 144*b38da99fSShawn McCarney std::move(i2cInterface)}; 145*b38da99fSShawn McCarney IDMap idMap{}; 146*b38da99fSShawn McCarney idMap.addDevice(device); 147*b38da99fSShawn McCarney ActionEnvironment env{idMap, "reg1"}; 148*b38da99fSShawn McCarney I2CActionImpl action{}; 149*b38da99fSShawn McCarney 150*b38da99fSShawn McCarney // Get I2CInterface. Should throw an exception from the open() call. 151*b38da99fSShawn McCarney action.getI2CInterface(env); 152*b38da99fSShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 153*b38da99fSShawn McCarney } 154*b38da99fSShawn McCarney catch (const i2c::I2CException& e) 155*b38da99fSShawn McCarney { 156*b38da99fSShawn McCarney EXPECT_STREQ(e.what(), 157*b38da99fSShawn McCarney "I2CException: Failed to open: bus /dev/i2c-1, addr 0x70"); 158*b38da99fSShawn McCarney } 159*b38da99fSShawn McCarney catch (...) 160*b38da99fSShawn McCarney { 161*b38da99fSShawn McCarney ADD_FAILURE() << "Should not have caught exception."; 162*b38da99fSShawn McCarney } 163*b38da99fSShawn McCarney } 164