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 "mock_action.hpp" 22 #include "mock_journal.hpp" 23 #include "mock_services.hpp" 24 #include "mocked_i2c_interface.hpp" 25 #include "pmbus_read_sensor_action.hpp" 26 #include "presence_detection.hpp" 27 #include "rail.hpp" 28 #include "rule.hpp" 29 #include "sensor_monitoring.hpp" 30 #include "system.hpp" 31 32 #include <memory> 33 #include <optional> 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 42 using ::testing::A; 43 using ::testing::Return; 44 using ::testing::TypedEq; 45 46 TEST(RailTests, Constructor) 47 { 48 // Test where only required parameters are specified 49 { 50 Rail rail{"vdd0"}; 51 EXPECT_EQ(rail.getID(), "vdd0"); 52 EXPECT_EQ(rail.getConfiguration(), nullptr); 53 EXPECT_EQ(rail.getSensorMonitoring(), nullptr); 54 } 55 56 // Test where all parameters are specified 57 { 58 // Create Configuration 59 std::optional<double> volts{1.3}; 60 std::vector<std::unique_ptr<Action>> actions{}; 61 actions.push_back(std::make_unique<MockAction>()); 62 actions.push_back(std::make_unique<MockAction>()); 63 std::unique_ptr<Configuration> configuration = 64 std::make_unique<Configuration>(volts, std::move(actions)); 65 66 // Create SensorMonitoring 67 actions.clear(); 68 actions.push_back(std::make_unique<MockAction>()); 69 std::unique_ptr<SensorMonitoring> sensorMonitoring = 70 std::make_unique<SensorMonitoring>(std::move(actions)); 71 72 // Create Rail 73 Rail rail{"vddr1", std::move(configuration), 74 std::move(sensorMonitoring)}; 75 EXPECT_EQ(rail.getID(), "vddr1"); 76 EXPECT_NE(rail.getConfiguration(), nullptr); 77 EXPECT_EQ(rail.getConfiguration()->getVolts().has_value(), true); 78 EXPECT_EQ(rail.getConfiguration()->getVolts().value(), 1.3); 79 EXPECT_EQ(rail.getConfiguration()->getActions().size(), 2); 80 EXPECT_NE(rail.getSensorMonitoring(), nullptr); 81 EXPECT_EQ(rail.getSensorMonitoring()->getActions().size(), 1); 82 } 83 } 84 85 TEST(RailTests, Configure) 86 { 87 // Test where Configuration was not specified in constructor 88 { 89 // Create mock services. No logging should occur. 90 MockServices services{}; 91 MockJournal& journal = services.getMockJournal(); 92 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 93 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 94 95 // Create Rail 96 std::unique_ptr<Rail> rail = std::make_unique<Rail>("vdd0"); 97 Rail* railPtr = rail.get(); 98 99 // Create Device that contains Rail 100 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 101 std::make_unique<i2c::MockedI2CInterface>(); 102 std::unique_ptr<PresenceDetection> presenceDetection{}; 103 std::unique_ptr<Configuration> deviceConfiguration{}; 104 std::vector<std::unique_ptr<Rail>> rails{}; 105 rails.emplace_back(std::move(rail)); 106 std::unique_ptr<Device> device = std::make_unique<Device>( 107 "reg1", true, 108 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 109 std::move(i2cInterface), std::move(presenceDetection), 110 std::move(deviceConfiguration), std::move(rails)); 111 Device* devicePtr = device.get(); 112 113 // Create Chassis that contains Device 114 std::vector<std::unique_ptr<Device>> devices{}; 115 devices.emplace_back(std::move(device)); 116 std::unique_ptr<Chassis> chassis = 117 std::make_unique<Chassis>(1, std::move(devices)); 118 Chassis* chassisPtr = chassis.get(); 119 120 // Create System that contains Chassis 121 std::vector<std::unique_ptr<Rule>> rules{}; 122 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 123 chassisVec.emplace_back(std::move(chassis)); 124 System system{std::move(rules), std::move(chassisVec)}; 125 126 // Call configure(). 127 railPtr->configure(services, system, *chassisPtr, *devicePtr); 128 } 129 130 // Test where Configuration was specified in constructor 131 { 132 // Create mock services. Expect logDebug() to be called. 133 MockServices services{}; 134 MockJournal& journal = services.getMockJournal(); 135 EXPECT_CALL(journal, logDebug("Configuring vddr1: volts=1.300000")) 136 .Times(1); 137 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 138 139 // Create Configuration 140 std::optional<double> volts{1.3}; 141 std::unique_ptr<MockAction> action = std::make_unique<MockAction>(); 142 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 143 std::vector<std::unique_ptr<Action>> actions{}; 144 actions.emplace_back(std::move(action)); 145 std::unique_ptr<Configuration> configuration = 146 std::make_unique<Configuration>(volts, std::move(actions)); 147 148 // Create Rail 149 std::unique_ptr<Rail> rail = 150 std::make_unique<Rail>("vddr1", std::move(configuration)); 151 Rail* railPtr = rail.get(); 152 153 // Create Device that contains Rail 154 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 155 std::make_unique<i2c::MockedI2CInterface>(); 156 std::unique_ptr<PresenceDetection> presenceDetection{}; 157 std::unique_ptr<Configuration> deviceConfiguration{}; 158 std::vector<std::unique_ptr<Rail>> rails{}; 159 rails.emplace_back(std::move(rail)); 160 std::unique_ptr<Device> device = std::make_unique<Device>( 161 "reg1", true, 162 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 163 std::move(i2cInterface), std::move(presenceDetection), 164 std::move(deviceConfiguration), std::move(rails)); 165 Device* devicePtr = device.get(); 166 167 // Create Chassis that contains Device 168 std::vector<std::unique_ptr<Device>> devices{}; 169 devices.emplace_back(std::move(device)); 170 std::unique_ptr<Chassis> chassis = 171 std::make_unique<Chassis>(1, std::move(devices)); 172 Chassis* chassisPtr = chassis.get(); 173 174 // Create System that contains Chassis 175 std::vector<std::unique_ptr<Rule>> rules{}; 176 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 177 chassisVec.emplace_back(std::move(chassis)); 178 System system{std::move(rules), std::move(chassisVec)}; 179 180 // Call configure(). 181 railPtr->configure(services, system, *chassisPtr, *devicePtr); 182 } 183 } 184 185 TEST(RailTests, GetConfiguration) 186 { 187 // Test where Configuration was not specified in constructor 188 { 189 Rail rail{"vdd0"}; 190 EXPECT_EQ(rail.getConfiguration(), nullptr); 191 } 192 193 // Test where Configuration was specified in constructor 194 { 195 // Create Configuration 196 std::optional<double> volts{3.2}; 197 std::vector<std::unique_ptr<Action>> actions{}; 198 actions.push_back(std::make_unique<MockAction>()); 199 std::unique_ptr<Configuration> configuration = 200 std::make_unique<Configuration>(volts, std::move(actions)); 201 202 // Create Rail 203 Rail rail{"vddr1", std::move(configuration)}; 204 EXPECT_NE(rail.getConfiguration(), nullptr); 205 EXPECT_EQ(rail.getConfiguration()->getVolts().has_value(), true); 206 EXPECT_EQ(rail.getConfiguration()->getVolts().value(), 3.2); 207 EXPECT_EQ(rail.getConfiguration()->getActions().size(), 1); 208 } 209 } 210 211 TEST(RailTests, GetID) 212 { 213 Rail rail{"vio2"}; 214 EXPECT_EQ(rail.getID(), "vio2"); 215 } 216 217 TEST(RailTests, MonitorSensors) 218 { 219 // Test where SensorMonitoring was not specified in constructor 220 { 221 // Create mock services. No logging should occur. 222 MockServices services{}; 223 MockJournal& journal = services.getMockJournal(); 224 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 225 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 226 227 // Create mock I2CInterface. A two-byte read should NOT occur. 228 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 229 std::make_unique<i2c::MockedI2CInterface>(); 230 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint16_t&>())).Times(0); 231 232 // Create Rail 233 std::unique_ptr<Rail> rail = std::make_unique<Rail>("vdd0"); 234 Rail* railPtr = rail.get(); 235 236 // Create Device that contains Rail 237 std::unique_ptr<PresenceDetection> presenceDetection{}; 238 std::unique_ptr<Configuration> deviceConfiguration{}; 239 std::vector<std::unique_ptr<Rail>> rails{}; 240 rails.emplace_back(std::move(rail)); 241 std::unique_ptr<Device> device = std::make_unique<Device>( 242 "reg1", true, 243 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 244 std::move(i2cInterface), std::move(presenceDetection), 245 std::move(deviceConfiguration), std::move(rails)); 246 Device* devicePtr = device.get(); 247 248 // Create Chassis that contains Device 249 std::vector<std::unique_ptr<Device>> devices{}; 250 devices.emplace_back(std::move(device)); 251 std::unique_ptr<Chassis> chassis = 252 std::make_unique<Chassis>(1, std::move(devices)); 253 Chassis* chassisPtr = chassis.get(); 254 255 // Create System that contains Chassis 256 std::vector<std::unique_ptr<Rule>> rules{}; 257 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 258 chassisVec.emplace_back(std::move(chassis)); 259 System system{std::move(rules), std::move(chassisVec)}; 260 261 // Call monitorSensors(). 262 railPtr->monitorSensors(services, system, *chassisPtr, *devicePtr); 263 } 264 265 // Test where SensorMonitoring was specified in constructor 266 { 267 // Create mock services. No logging should occur. 268 MockServices services{}; 269 MockJournal& journal = services.getMockJournal(); 270 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 271 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 272 273 // Create PMBusReadSensorAction 274 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout}; 275 uint8_t command = 0x8C; 276 pmbus_utils::SensorDataFormat format{ 277 pmbus_utils::SensorDataFormat::linear_11}; 278 std::optional<int8_t> exponent{}; 279 std::unique_ptr<PMBusReadSensorAction> action = 280 std::make_unique<PMBusReadSensorAction>(type, command, format, 281 exponent); 282 283 // Create mock I2CInterface. A two-byte read should occur. 284 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 285 std::make_unique<i2c::MockedI2CInterface>(); 286 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 287 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>())) 288 .Times(1); 289 290 // Create SensorMonitoring 291 std::vector<std::unique_ptr<Action>> actions{}; 292 actions.emplace_back(std::move(action)); 293 std::unique_ptr<SensorMonitoring> sensorMonitoring = 294 std::make_unique<SensorMonitoring>(std::move(actions)); 295 296 // Create Rail 297 std::unique_ptr<Configuration> configuration{}; 298 std::unique_ptr<Rail> rail = std::make_unique<Rail>( 299 "vddr1", std::move(configuration), std::move(sensorMonitoring)); 300 Rail* railPtr = rail.get(); 301 302 // Create Device that contains Rail 303 std::unique_ptr<PresenceDetection> presenceDetection{}; 304 std::unique_ptr<Configuration> deviceConfiguration{}; 305 std::vector<std::unique_ptr<Rail>> rails{}; 306 rails.emplace_back(std::move(rail)); 307 std::unique_ptr<Device> device = std::make_unique<Device>( 308 "reg1", true, 309 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 310 std::move(i2cInterface), std::move(presenceDetection), 311 std::move(deviceConfiguration), std::move(rails)); 312 Device* devicePtr = device.get(); 313 314 // Create Chassis that contains Device 315 std::vector<std::unique_ptr<Device>> devices{}; 316 devices.emplace_back(std::move(device)); 317 std::unique_ptr<Chassis> chassis = 318 std::make_unique<Chassis>(1, std::move(devices)); 319 Chassis* chassisPtr = chassis.get(); 320 321 // Create System that contains Chassis 322 std::vector<std::unique_ptr<Rule>> rules{}; 323 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 324 chassisVec.emplace_back(std::move(chassis)); 325 System system{std::move(rules), std::move(chassisVec)}; 326 327 // Call monitorSensors(). 328 railPtr->monitorSensors(services, system, *chassisPtr, *devicePtr); 329 } 330 } 331 332 TEST(RailTests, GetSensorMonitoring) 333 { 334 // Test where SensorMonitoring was not specified in constructor 335 { 336 Rail rail{"vdd0", nullptr, nullptr}; 337 EXPECT_EQ(rail.getSensorMonitoring(), nullptr); 338 } 339 340 // Test where SensorMonitoring was specified in constructor 341 { 342 std::unique_ptr<Configuration> configuration{}; 343 344 // Create SensorMonitoring 345 std::vector<std::unique_ptr<Action>> actions{}; 346 actions.push_back(std::make_unique<MockAction>()); 347 actions.push_back(std::make_unique<MockAction>()); 348 std::unique_ptr<SensorMonitoring> sensorMonitoring = 349 std::make_unique<SensorMonitoring>(std::move(actions)); 350 351 // Create Rail 352 Rail rail{"vddr1", std::move(configuration), 353 std::move(sensorMonitoring)}; 354 EXPECT_NE(rail.getSensorMonitoring(), nullptr); 355 EXPECT_EQ(rail.getSensorMonitoring()->getActions().size(), 2); 356 } 357 } 358