1 /** 2 * Copyright © 2019 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_action.hpp" 24 #include "mock_journal.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 <optional> 33 #include <string> 34 #include <utility> 35 #include <vector> 36 37 #include <gmock/gmock.h> 38 #include <gtest/gtest.h> 39 40 using namespace phosphor::power::regulators; 41 using namespace phosphor::power::regulators::test_utils; 42 43 using ::testing::Return; 44 45 TEST(DeviceTests, Constructor) 46 { 47 // Test where only required parameters are specified 48 { 49 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 50 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get(); 51 Device device{"vdd_reg", true, "/system/chassis/motherboard/reg2", 52 std::move(i2cInterface)}; 53 EXPECT_EQ(device.getID(), "vdd_reg"); 54 EXPECT_EQ(device.isRegulator(), true); 55 EXPECT_EQ(device.getFRU(), "/system/chassis/motherboard/reg2"); 56 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr); 57 EXPECT_EQ(device.getPresenceDetection(), nullptr); 58 EXPECT_EQ(device.getConfiguration(), nullptr); 59 EXPECT_EQ(device.getRails().size(), 0); 60 } 61 62 // Test where all parameters are specified 63 { 64 // Create I2CInterface 65 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 66 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get(); 67 68 // Create PresenceDetection 69 std::vector<std::unique_ptr<Action>> actions{}; 70 actions.push_back(std::make_unique<MockAction>()); 71 std::unique_ptr<PresenceDetection> presenceDetection = 72 std::make_unique<PresenceDetection>(std::move(actions)); 73 74 // Create Configuration 75 std::optional<double> volts{}; 76 actions.clear(); 77 actions.push_back(std::make_unique<MockAction>()); 78 actions.push_back(std::make_unique<MockAction>()); 79 std::unique_ptr<Configuration> configuration = 80 std::make_unique<Configuration>(volts, std::move(actions)); 81 82 // Create vector of Rail objects 83 std::vector<std::unique_ptr<Rail>> rails{}; 84 rails.push_back(std::make_unique<Rail>("vdd0")); 85 rails.push_back(std::make_unique<Rail>("vdd1")); 86 87 // Create Device 88 Device device{"vdd_reg", 89 false, 90 "/system/chassis/motherboard/reg1", 91 std::move(i2cInterface), 92 std::move(presenceDetection), 93 std::move(configuration), 94 std::move(rails)}; 95 EXPECT_EQ(device.getID(), "vdd_reg"); 96 EXPECT_EQ(device.isRegulator(), false); 97 EXPECT_EQ(device.getFRU(), "/system/chassis/motherboard/reg1"); 98 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr); 99 EXPECT_NE(device.getPresenceDetection(), nullptr); 100 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1); 101 EXPECT_NE(device.getConfiguration(), nullptr); 102 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), false); 103 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2); 104 EXPECT_EQ(device.getRails().size(), 2); 105 } 106 } 107 108 TEST(DeviceTests, AddToIDMap) 109 { 110 std::unique_ptr<PresenceDetection> presenceDetection{}; 111 std::unique_ptr<Configuration> configuration{}; 112 113 // Create vector of Rail objects 114 std::vector<std::unique_ptr<Rail>> rails{}; 115 rails.push_back(std::make_unique<Rail>("vdd0")); 116 rails.push_back(std::make_unique<Rail>("vdd1")); 117 118 // Create Device 119 Device device{"vdd_reg", 120 false, 121 "/system/chassis/motherboard/reg2", 122 std::move(createI2CInterface()), 123 std::move(presenceDetection), 124 std::move(configuration), 125 std::move(rails)}; 126 127 // Add Device and Rail objects to an IDMap 128 IDMap idMap{}; 129 device.addToIDMap(idMap); 130 131 // Verify Device is in the IDMap 132 EXPECT_NO_THROW(idMap.getDevice("vdd_reg")); 133 EXPECT_THROW(idMap.getDevice("vio_reg"), std::invalid_argument); 134 135 // Verify all Rails are in the IDMap 136 EXPECT_NO_THROW(idMap.getRail("vdd0")); 137 EXPECT_NO_THROW(idMap.getRail("vdd1")); 138 EXPECT_THROW(idMap.getRail("vdd2"), std::invalid_argument); 139 } 140 141 TEST(DeviceTests, Configure) 142 { 143 // Test where Configuration and Rails were not specified in constructor 144 { 145 // Create Device 146 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 147 std::unique_ptr<Device> device = std::make_unique<Device>( 148 "reg1", true, "/system/chassis/motherboard/reg1", 149 std::move(i2cInterface)); 150 Device* devicePtr = device.get(); 151 152 // Create Chassis that contains Device 153 std::vector<std::unique_ptr<Device>> devices{}; 154 devices.emplace_back(std::move(device)); 155 std::unique_ptr<Chassis> chassis = 156 std::make_unique<Chassis>(1, std::move(devices)); 157 Chassis* chassisPtr = chassis.get(); 158 159 // Create System that contains Chassis 160 std::vector<std::unique_ptr<Rule>> rules{}; 161 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 162 chassisVec.emplace_back(std::move(chassis)); 163 System system{std::move(rules), std::move(chassisVec)}; 164 165 // Call configure(). Should do nothing. 166 journal::clear(); 167 devicePtr->configure(system, *chassisPtr); 168 EXPECT_EQ(journal::getDebugMessages().size(), 0); 169 EXPECT_EQ(journal::getErrMessages().size(), 0); 170 } 171 172 // Test where Configuration and Rails were specified in constructor 173 { 174 std::vector<std::unique_ptr<Rail>> rails{}; 175 176 // Create Rail vdd0 177 { 178 // Create Configuration for Rail 179 std::optional<double> volts{1.3}; 180 std::unique_ptr<MockAction> action = std::make_unique<MockAction>(); 181 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 182 std::vector<std::unique_ptr<Action>> actions{}; 183 actions.emplace_back(std::move(action)); 184 std::unique_ptr<Configuration> configuration = 185 std::make_unique<Configuration>(volts, std::move(actions)); 186 187 // Create Rail 188 std::unique_ptr<Rail> rail = 189 std::make_unique<Rail>("vdd0", std::move(configuration)); 190 rails.emplace_back(std::move(rail)); 191 } 192 193 // Create Rail vio0 194 { 195 // Create Configuration for Rail 196 std::optional<double> volts{3.2}; 197 std::unique_ptr<MockAction> action = std::make_unique<MockAction>(); 198 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 199 std::vector<std::unique_ptr<Action>> actions{}; 200 actions.emplace_back(std::move(action)); 201 std::unique_ptr<Configuration> configuration = 202 std::make_unique<Configuration>(volts, std::move(actions)); 203 204 // Create Rail 205 std::unique_ptr<Rail> rail = 206 std::make_unique<Rail>("vio0", std::move(configuration)); 207 rails.emplace_back(std::move(rail)); 208 } 209 210 // Create Configuration for Device 211 std::optional<double> volts{}; 212 std::unique_ptr<MockAction> action = std::make_unique<MockAction>(); 213 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 214 std::vector<std::unique_ptr<Action>> actions{}; 215 actions.emplace_back(std::move(action)); 216 std::unique_ptr<Configuration> configuration = 217 std::make_unique<Configuration>(volts, std::move(actions)); 218 219 // Create Device 220 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 221 std::unique_ptr<PresenceDetection> presenceDetection{}; 222 std::unique_ptr<Device> device = std::make_unique<Device>( 223 "reg1", true, "/system/chassis/motherboard/reg1", 224 std::move(i2cInterface), std::move(presenceDetection), 225 std::move(configuration), std::move(rails)); 226 Device* devicePtr = device.get(); 227 228 // Create Chassis that contains Device 229 std::vector<std::unique_ptr<Device>> devices{}; 230 devices.emplace_back(std::move(device)); 231 std::unique_ptr<Chassis> chassis = 232 std::make_unique<Chassis>(1, std::move(devices)); 233 Chassis* chassisPtr = chassis.get(); 234 235 // Create System that contains Chassis 236 std::vector<std::unique_ptr<Rule>> rules{}; 237 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 238 chassisVec.emplace_back(std::move(chassis)); 239 System system{std::move(rules), std::move(chassisVec)}; 240 241 // Call configure(). For the Device and both Rails, should execute the 242 // Configuration and log a debug message. 243 journal::clear(); 244 devicePtr->configure(system, *chassisPtr); 245 std::vector<std::string> expectedDebugMessages{ 246 "Configuring reg1", "Configuring vdd0: volts=1.300000", 247 "Configuring vio0: volts=3.200000"}; 248 EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages); 249 EXPECT_EQ(journal::getErrMessages().size(), 0); 250 } 251 } 252 253 TEST(DeviceTests, GetConfiguration) 254 { 255 // Test where Configuration was not specified in constructor 256 { 257 Device device{"vdd_reg", true, "/system/chassis/motherboard/reg2", 258 std::move(createI2CInterface())}; 259 EXPECT_EQ(device.getConfiguration(), nullptr); 260 } 261 262 // Test where Configuration was specified in constructor 263 { 264 std::unique_ptr<PresenceDetection> presenceDetection{}; 265 266 // Create Configuration 267 std::optional<double> volts{3.2}; 268 std::vector<std::unique_ptr<Action>> actions{}; 269 actions.push_back(std::make_unique<MockAction>()); 270 actions.push_back(std::make_unique<MockAction>()); 271 std::unique_ptr<Configuration> configuration = 272 std::make_unique<Configuration>(volts, std::move(actions)); 273 274 // Create Device 275 Device device{"vdd_reg", 276 true, 277 "/system/chassis/motherboard/reg2", 278 std::move(createI2CInterface()), 279 std::move(presenceDetection), 280 std::move(configuration)}; 281 EXPECT_NE(device.getConfiguration(), nullptr); 282 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), true); 283 EXPECT_EQ(device.getConfiguration()->getVolts().value(), 3.2); 284 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2); 285 } 286 } 287 288 TEST(DeviceTests, GetFRU) 289 { 290 Device device{"vdd_reg", true, "/system/chassis/motherboard/reg2", 291 std::move(createI2CInterface())}; 292 EXPECT_EQ(device.getFRU(), "/system/chassis/motherboard/reg2"); 293 } 294 295 TEST(DeviceTests, GetI2CInterface) 296 { 297 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 298 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get(); 299 Device device{"vdd_reg", true, "/system/chassis/motherboard/reg2", 300 std::move(i2cInterface)}; 301 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr); 302 } 303 304 TEST(DeviceTests, GetID) 305 { 306 Device device{"vdd_reg", false, "/system/chassis/motherboard/reg2", 307 std::move(createI2CInterface())}; 308 EXPECT_EQ(device.getID(), "vdd_reg"); 309 } 310 311 TEST(DeviceTests, GetPresenceDetection) 312 { 313 // Test where PresenceDetection was not specified in constructor 314 { 315 Device device{"vdd_reg", true, "/system/chassis/motherboard/reg2", 316 std::move(createI2CInterface())}; 317 EXPECT_EQ(device.getPresenceDetection(), nullptr); 318 } 319 320 // Test where PresenceDetection was specified in constructor 321 { 322 // Create PresenceDetection 323 std::vector<std::unique_ptr<Action>> actions{}; 324 actions.push_back(std::make_unique<MockAction>()); 325 std::unique_ptr<PresenceDetection> presenceDetection = 326 std::make_unique<PresenceDetection>(std::move(actions)); 327 328 // Create Device 329 Device device{"vdd_reg", false, "/system/chassis/motherboard/reg2", 330 std::move(createI2CInterface()), 331 std::move(presenceDetection)}; 332 EXPECT_NE(device.getPresenceDetection(), nullptr); 333 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1); 334 } 335 } 336 337 TEST(DeviceTests, GetRails) 338 { 339 // Test where no rails were specified in constructor 340 { 341 Device device{"vdd_reg", true, "/system/chassis/motherboard/reg2", 342 std::move(createI2CInterface())}; 343 EXPECT_EQ(device.getRails().size(), 0); 344 } 345 346 // Test where rails were specified in constructor 347 { 348 std::unique_ptr<PresenceDetection> presenceDetection{}; 349 std::unique_ptr<Configuration> configuration{}; 350 351 // Create vector of Rail objects 352 std::vector<std::unique_ptr<Rail>> rails{}; 353 rails.push_back(std::make_unique<Rail>("vdd0")); 354 rails.push_back(std::make_unique<Rail>("vdd1")); 355 356 // Create Device 357 Device device{"vdd_reg", 358 false, 359 "/system/chassis/motherboard/reg2", 360 std::move(createI2CInterface()), 361 std::move(presenceDetection), 362 std::move(configuration), 363 std::move(rails)}; 364 EXPECT_EQ(device.getRails().size(), 2); 365 EXPECT_EQ(device.getRails()[0]->getID(), "vdd0"); 366 EXPECT_EQ(device.getRails()[1]->getID(), "vdd1"); 367 } 368 } 369 370 TEST(DeviceTests, IsRegulator) 371 { 372 Device device{"vdd_reg", false, "/system/chassis/motherboard/reg2", 373 std::move(createI2CInterface())}; 374 EXPECT_EQ(device.isRegulator(), false); 375 } 376