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, "/system/chassis/motherboard/reg1", 108 std::move(i2cInterface), std::move(presenceDetection), 109 std::move(deviceConfiguration), std::move(rails)); 110 Device* devicePtr = device.get(); 111 112 // Create Chassis that contains Device 113 std::vector<std::unique_ptr<Device>> devices{}; 114 devices.emplace_back(std::move(device)); 115 std::unique_ptr<Chassis> chassis = 116 std::make_unique<Chassis>(1, std::move(devices)); 117 Chassis* chassisPtr = chassis.get(); 118 119 // Create System that contains Chassis 120 std::vector<std::unique_ptr<Rule>> rules{}; 121 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 122 chassisVec.emplace_back(std::move(chassis)); 123 System system{std::move(rules), std::move(chassisVec)}; 124 125 // Call configure(). 126 railPtr->configure(services, system, *chassisPtr, *devicePtr); 127 } 128 129 // Test where Configuration was specified in constructor 130 { 131 // Create mock services. Expect logDebug() to be called. 132 MockServices services{}; 133 MockJournal& journal = services.getMockJournal(); 134 EXPECT_CALL(journal, logDebug("Configuring vddr1: volts=1.300000")) 135 .Times(1); 136 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 137 138 // Create Configuration 139 std::optional<double> volts{1.3}; 140 std::unique_ptr<MockAction> action = std::make_unique<MockAction>(); 141 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 142 std::vector<std::unique_ptr<Action>> actions{}; 143 actions.emplace_back(std::move(action)); 144 std::unique_ptr<Configuration> configuration = 145 std::make_unique<Configuration>(volts, std::move(actions)); 146 147 // Create Rail 148 std::unique_ptr<Rail> rail = 149 std::make_unique<Rail>("vddr1", std::move(configuration)); 150 Rail* railPtr = rail.get(); 151 152 // Create Device that contains Rail 153 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 154 std::make_unique<i2c::MockedI2CInterface>(); 155 std::unique_ptr<PresenceDetection> presenceDetection{}; 156 std::unique_ptr<Configuration> deviceConfiguration{}; 157 std::vector<std::unique_ptr<Rail>> rails{}; 158 rails.emplace_back(std::move(rail)); 159 std::unique_ptr<Device> device = std::make_unique<Device>( 160 "reg1", true, "/system/chassis/motherboard/reg1", 161 std::move(i2cInterface), std::move(presenceDetection), 162 std::move(deviceConfiguration), std::move(rails)); 163 Device* devicePtr = device.get(); 164 165 // Create Chassis that contains Device 166 std::vector<std::unique_ptr<Device>> devices{}; 167 devices.emplace_back(std::move(device)); 168 std::unique_ptr<Chassis> chassis = 169 std::make_unique<Chassis>(1, std::move(devices)); 170 Chassis* chassisPtr = chassis.get(); 171 172 // Create System that contains Chassis 173 std::vector<std::unique_ptr<Rule>> rules{}; 174 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 175 chassisVec.emplace_back(std::move(chassis)); 176 System system{std::move(rules), std::move(chassisVec)}; 177 178 // Call configure(). 179 railPtr->configure(services, system, *chassisPtr, *devicePtr); 180 } 181 } 182 183 TEST(RailTests, GetConfiguration) 184 { 185 // Test where Configuration was not specified in constructor 186 { 187 Rail rail{"vdd0"}; 188 EXPECT_EQ(rail.getConfiguration(), nullptr); 189 } 190 191 // Test where Configuration was specified in constructor 192 { 193 // Create Configuration 194 std::optional<double> volts{3.2}; 195 std::vector<std::unique_ptr<Action>> actions{}; 196 actions.push_back(std::make_unique<MockAction>()); 197 std::unique_ptr<Configuration> configuration = 198 std::make_unique<Configuration>(volts, std::move(actions)); 199 200 // Create Rail 201 Rail rail{"vddr1", std::move(configuration)}; 202 EXPECT_NE(rail.getConfiguration(), nullptr); 203 EXPECT_EQ(rail.getConfiguration()->getVolts().has_value(), true); 204 EXPECT_EQ(rail.getConfiguration()->getVolts().value(), 3.2); 205 EXPECT_EQ(rail.getConfiguration()->getActions().size(), 1); 206 } 207 } 208 209 TEST(RailTests, GetID) 210 { 211 Rail rail{"vio2"}; 212 EXPECT_EQ(rail.getID(), "vio2"); 213 } 214 215 TEST(RailTests, MonitorSensors) 216 { 217 // Test where SensorMonitoring was not specified in constructor 218 { 219 // Create mock services. No logging should occur. 220 MockServices services{}; 221 MockJournal& journal = services.getMockJournal(); 222 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 223 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 224 225 // Create mock I2CInterface. A two-byte read should NOT occur. 226 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 227 std::make_unique<i2c::MockedI2CInterface>(); 228 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint16_t&>())).Times(0); 229 230 // Create Rail 231 std::unique_ptr<Rail> rail = std::make_unique<Rail>("vdd0"); 232 Rail* railPtr = rail.get(); 233 234 // Create Device that contains Rail 235 std::unique_ptr<PresenceDetection> presenceDetection{}; 236 std::unique_ptr<Configuration> deviceConfiguration{}; 237 std::vector<std::unique_ptr<Rail>> rails{}; 238 rails.emplace_back(std::move(rail)); 239 std::unique_ptr<Device> device = std::make_unique<Device>( 240 "reg1", true, "/system/chassis/motherboard/reg1", 241 std::move(i2cInterface), std::move(presenceDetection), 242 std::move(deviceConfiguration), std::move(rails)); 243 Device* devicePtr = device.get(); 244 245 // Create Chassis that contains Device 246 std::vector<std::unique_ptr<Device>> devices{}; 247 devices.emplace_back(std::move(device)); 248 std::unique_ptr<Chassis> chassis = 249 std::make_unique<Chassis>(1, std::move(devices)); 250 Chassis* chassisPtr = chassis.get(); 251 252 // Create System that contains Chassis 253 std::vector<std::unique_ptr<Rule>> rules{}; 254 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 255 chassisVec.emplace_back(std::move(chassis)); 256 System system{std::move(rules), std::move(chassisVec)}; 257 258 // Call monitorSensors(). 259 railPtr->monitorSensors(services, system, *chassisPtr, *devicePtr); 260 } 261 262 // Test where SensorMonitoring was specified in constructor 263 { 264 // Create mock services. No logging should occur. 265 MockServices services{}; 266 MockJournal& journal = services.getMockJournal(); 267 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 268 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 269 270 // Create PMBusReadSensorAction 271 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout}; 272 uint8_t command = 0x8C; 273 pmbus_utils::SensorDataFormat format{ 274 pmbus_utils::SensorDataFormat::linear_11}; 275 std::optional<int8_t> exponent{}; 276 std::unique_ptr<PMBusReadSensorAction> action = 277 std::make_unique<PMBusReadSensorAction>(type, command, format, 278 exponent); 279 280 // Create mock I2CInterface. A two-byte read should occur. 281 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 282 std::make_unique<i2c::MockedI2CInterface>(); 283 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 284 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>())) 285 .Times(1); 286 287 // Create SensorMonitoring 288 std::vector<std::unique_ptr<Action>> actions{}; 289 actions.emplace_back(std::move(action)); 290 std::unique_ptr<SensorMonitoring> sensorMonitoring = 291 std::make_unique<SensorMonitoring>(std::move(actions)); 292 293 // Create Rail 294 std::unique_ptr<Configuration> configuration{}; 295 std::unique_ptr<Rail> rail = std::make_unique<Rail>( 296 "vddr1", std::move(configuration), std::move(sensorMonitoring)); 297 Rail* railPtr = rail.get(); 298 299 // Create Device that contains Rail 300 std::unique_ptr<PresenceDetection> presenceDetection{}; 301 std::unique_ptr<Configuration> deviceConfiguration{}; 302 std::vector<std::unique_ptr<Rail>> rails{}; 303 rails.emplace_back(std::move(rail)); 304 std::unique_ptr<Device> device = std::make_unique<Device>( 305 "reg1", true, "/system/chassis/motherboard/reg1", 306 std::move(i2cInterface), std::move(presenceDetection), 307 std::move(deviceConfiguration), std::move(rails)); 308 Device* devicePtr = device.get(); 309 310 // Create Chassis that contains Device 311 std::vector<std::unique_ptr<Device>> devices{}; 312 devices.emplace_back(std::move(device)); 313 std::unique_ptr<Chassis> chassis = 314 std::make_unique<Chassis>(1, std::move(devices)); 315 Chassis* chassisPtr = chassis.get(); 316 317 // Create System that contains Chassis 318 std::vector<std::unique_ptr<Rule>> rules{}; 319 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 320 chassisVec.emplace_back(std::move(chassis)); 321 System system{std::move(rules), std::move(chassisVec)}; 322 323 // Call monitorSensors(). 324 railPtr->monitorSensors(services, system, *chassisPtr, *devicePtr); 325 } 326 } 327 328 TEST(RailTests, GetSensorMonitoring) 329 { 330 // Test where SensorMonitoring was not specified in constructor 331 { 332 Rail rail{"vdd0", nullptr, nullptr}; 333 EXPECT_EQ(rail.getSensorMonitoring(), nullptr); 334 } 335 336 // Test where SensorMonitoring was specified in constructor 337 { 338 std::unique_ptr<Configuration> configuration{}; 339 340 // Create SensorMonitoring 341 std::vector<std::unique_ptr<Action>> actions{}; 342 actions.push_back(std::make_unique<MockAction>()); 343 actions.push_back(std::make_unique<MockAction>()); 344 std::unique_ptr<SensorMonitoring> sensorMonitoring = 345 std::make_unique<SensorMonitoring>(std::move(actions)); 346 347 // Create Rail 348 Rail rail{"vddr1", std::move(configuration), 349 std::move(sensorMonitoring)}; 350 EXPECT_NE(rail.getSensorMonitoring(), nullptr); 351 EXPECT_EQ(rail.getSensorMonitoring()->getActions().size(), 2); 352 } 353 } 354