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.hpp" 17 #include "chassis.hpp" 18 #include "configuration.hpp" 19 #include "device.hpp" 20 #include "i2c_interface.hpp" 21 #include "id_map.hpp" 22 #include "journal.hpp" 23 #include "mock_journal.hpp" 24 #include "mocked_i2c_interface.hpp" 25 #include "presence_detection.hpp" 26 #include "rail.hpp" 27 #include "rule.hpp" 28 #include "system.hpp" 29 #include "test_utils.hpp" 30 31 #include <memory> 32 #include <stdexcept> 33 #include <string> 34 #include <utility> 35 #include <vector> 36 37 #include <gtest/gtest.h> 38 39 using namespace phosphor::power::regulators; 40 using namespace phosphor::power::regulators::test_utils; 41 42 using ::testing::Return; 43 44 TEST(ChassisTests, Constructor) 45 { 46 // Test where works: Only required parameters are specified 47 { 48 Chassis chassis{2}; 49 EXPECT_EQ(chassis.getNumber(), 2); 50 EXPECT_EQ(chassis.getDevices().size(), 0); 51 } 52 53 // Test where works: All parameters are specified 54 { 55 // Create vector of Device objects 56 std::vector<std::unique_ptr<Device>> devices{}; 57 devices.emplace_back(createDevice("vdd_reg1")); 58 devices.emplace_back(createDevice("vdd_reg2")); 59 60 // Create Chassis 61 Chassis chassis{1, std::move(devices)}; 62 EXPECT_EQ(chassis.getNumber(), 1); 63 EXPECT_EQ(chassis.getDevices().size(), 2); 64 } 65 66 // Test where fails: Invalid chassis number < 1 67 try 68 { 69 Chassis chassis{0}; 70 ADD_FAILURE() << "Should not have reached this line."; 71 } 72 catch (const std::invalid_argument& e) 73 { 74 EXPECT_STREQ(e.what(), "Invalid chassis number: 0"); 75 } 76 catch (...) 77 { 78 ADD_FAILURE() << "Should not have caught exception."; 79 } 80 } 81 82 TEST(ChassisTests, AddToIDMap) 83 { 84 // Create vector of Device objects 85 std::vector<std::unique_ptr<Device>> devices{}; 86 devices.emplace_back(createDevice("reg1", {"rail1"})); 87 devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"})); 88 devices.emplace_back(createDevice("reg3")); 89 90 // Create Chassis 91 Chassis chassis{1, std::move(devices)}; 92 93 // Add Device and Rail objects within the Chassis to an IDMap 94 IDMap idMap{}; 95 chassis.addToIDMap(idMap); 96 97 // Verify all Devices are in the IDMap 98 EXPECT_NO_THROW(idMap.getDevice("reg1")); 99 EXPECT_NO_THROW(idMap.getDevice("reg2")); 100 EXPECT_NO_THROW(idMap.getDevice("reg3")); 101 EXPECT_THROW(idMap.getDevice("reg4"), std::invalid_argument); 102 103 // Verify all Rails are in the IDMap 104 EXPECT_NO_THROW(idMap.getRail("rail1")); 105 EXPECT_NO_THROW(idMap.getRail("rail2a")); 106 EXPECT_NO_THROW(idMap.getRail("rail2b")); 107 EXPECT_THROW(idMap.getRail("rail3"), std::invalid_argument); 108 } 109 110 TEST(ChassisTests, CloseDevices) 111 { 112 // Test where no devices were specified in constructor 113 { 114 // Create Chassis 115 Chassis chassis{2}; 116 117 // Call closeDevices() 118 journal::clear(); 119 chassis.closeDevices(); 120 EXPECT_EQ(journal::getErrMessages().size(), 0); 121 EXPECT_EQ(journal::getInfoMessages().size(), 0); 122 std::vector<std::string> expectedDebugMessages{ 123 "Closing devices in chassis 2"}; 124 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages); 125 } 126 127 // Test where devices were specified in constructor 128 { 129 std::vector<std::unique_ptr<Device>> devices{}; 130 131 // Create Device vdd0_reg 132 { 133 // Create mock I2CInterface: isOpen() and close() should be called 134 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 135 std::make_unique<i2c::MockedI2CInterface>(); 136 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 137 EXPECT_CALL(*i2cInterface, close).Times(1); 138 139 // Create Device 140 std::unique_ptr<Device> device = std::make_unique<Device>( 141 "vdd0_reg", true, "/system/chassis/motherboard/vdd0_reg", 142 std::move(i2cInterface)); 143 devices.emplace_back(std::move(device)); 144 } 145 146 // Create Device vdd1_reg 147 { 148 // Create mock I2CInterface: isOpen() and close() should be called 149 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 150 std::make_unique<i2c::MockedI2CInterface>(); 151 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 152 EXPECT_CALL(*i2cInterface, close).Times(1); 153 154 // Create Device 155 std::unique_ptr<Device> device = std::make_unique<Device>( 156 "vdd1_reg", true, "/system/chassis/motherboard/vdd1_reg", 157 std::move(i2cInterface)); 158 devices.emplace_back(std::move(device)); 159 } 160 161 // Create Chassis 162 Chassis chassis{1, std::move(devices)}; 163 164 // Call closeDevices() 165 journal::clear(); 166 chassis.closeDevices(); 167 EXPECT_EQ(journal::getErrMessages().size(), 0); 168 EXPECT_EQ(journal::getInfoMessages().size(), 0); 169 std::vector<std::string> expectedDebugMessages{ 170 "Closing devices in chassis 1"}; 171 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages); 172 } 173 } 174 175 TEST(ChassisTests, Configure) 176 { 177 // Test where no devices were specified in constructor 178 { 179 // Create Chassis 180 std::unique_ptr<Chassis> chassis = std::make_unique<Chassis>(1); 181 Chassis* chassisPtr = chassis.get(); 182 183 // Create System that contains Chassis 184 std::vector<std::unique_ptr<Rule>> rules{}; 185 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 186 chassisVec.emplace_back(std::move(chassis)); 187 System system{std::move(rules), std::move(chassisVec)}; 188 189 // Call configure() 190 journal::clear(); 191 chassisPtr->configure(system); 192 EXPECT_EQ(journal::getDebugMessages().size(), 0); 193 EXPECT_EQ(journal::getErrMessages().size(), 0); 194 std::vector<std::string> expectedInfoMessages{"Configuring chassis 1"}; 195 EXPECT_EQ(journal::getInfoMessages(), expectedInfoMessages); 196 } 197 198 // Test where devices were specified in constructor 199 { 200 std::vector<std::unique_ptr<Device>> devices{}; 201 202 // Create Device vdd0_reg 203 { 204 // Create Configuration 205 std::vector<std::unique_ptr<Action>> actions{}; 206 std::unique_ptr<Configuration> configuration = 207 std::make_unique<Configuration>(1.3, std::move(actions)); 208 209 // Create Device 210 std::unique_ptr<i2c::I2CInterface> i2cInterface = 211 createI2CInterface(); 212 std::unique_ptr<PresenceDetection> presenceDetection{}; 213 std::unique_ptr<Device> device = std::make_unique<Device>( 214 "vdd0_reg", true, "/system/chassis/motherboard/vdd0_reg", 215 std::move(i2cInterface), std::move(presenceDetection), 216 std::move(configuration)); 217 devices.emplace_back(std::move(device)); 218 } 219 220 // Create Device vdd1_reg 221 { 222 // Create Configuration 223 std::vector<std::unique_ptr<Action>> actions{}; 224 std::unique_ptr<Configuration> configuration = 225 std::make_unique<Configuration>(1.2, std::move(actions)); 226 227 // Create Device 228 std::unique_ptr<i2c::I2CInterface> i2cInterface = 229 createI2CInterface(); 230 std::unique_ptr<PresenceDetection> presenceDetection{}; 231 std::unique_ptr<Device> device = std::make_unique<Device>( 232 "vdd1_reg", true, "/system/chassis/motherboard/vdd1_reg", 233 std::move(i2cInterface), std::move(presenceDetection), 234 std::move(configuration)); 235 devices.emplace_back(std::move(device)); 236 } 237 238 // Create Chassis 239 std::unique_ptr<Chassis> chassis = 240 std::make_unique<Chassis>(2, std::move(devices)); 241 Chassis* chassisPtr = chassis.get(); 242 243 // Create System that contains Chassis 244 std::vector<std::unique_ptr<Rule>> rules{}; 245 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 246 chassisVec.emplace_back(std::move(chassis)); 247 System system{std::move(rules), std::move(chassisVec)}; 248 249 // Call configure() 250 journal::clear(); 251 chassisPtr->configure(system); 252 std::vector<std::string> expectedDebugMessages{ 253 "Configuring vdd0_reg: volts=1.300000", 254 "Configuring vdd1_reg: volts=1.200000"}; 255 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages); 256 EXPECT_EQ(journal::getErrMessages().size(), 0); 257 std::vector<std::string> expectedInfoMessages{"Configuring chassis 2"}; 258 EXPECT_EQ(journal::getInfoMessages(), expectedInfoMessages); 259 } 260 } 261 262 TEST(ChassisTests, GetDevices) 263 { 264 // Test where no devices were specified in constructor 265 { 266 Chassis chassis{2}; 267 EXPECT_EQ(chassis.getDevices().size(), 0); 268 } 269 270 // Test where devices were specified in constructor 271 { 272 // Create vector of Device objects 273 std::vector<std::unique_ptr<Device>> devices{}; 274 devices.emplace_back(createDevice("vdd_reg1")); 275 devices.emplace_back(createDevice("vdd_reg2")); 276 277 // Create Chassis 278 Chassis chassis{1, std::move(devices)}; 279 EXPECT_EQ(chassis.getDevices().size(), 2); 280 EXPECT_EQ(chassis.getDevices()[0]->getID(), "vdd_reg1"); 281 EXPECT_EQ(chassis.getDevices()[1]->getID(), "vdd_reg2"); 282 } 283 } 284 285 TEST(ChassisTests, GetNumber) 286 { 287 Chassis chassis{3}; 288 EXPECT_EQ(chassis.getNumber(), 3); 289 } 290