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 "chassis.hpp" 17 #include "device.hpp" 18 #include "id_map.hpp" 19 #include "mock_journal.hpp" 20 #include "mock_services.hpp" 21 #include "mocked_i2c_interface.hpp" 22 #include "pmbus_read_sensor_action.hpp" 23 #include "rail.hpp" 24 #include "rule.hpp" 25 #include "services.hpp" 26 #include "system.hpp" 27 #include "test_utils.hpp" 28 29 #include <memory> 30 #include <stdexcept> 31 #include <string> 32 #include <utility> 33 #include <vector> 34 35 #include <gmock/gmock.h> 36 #include <gtest/gtest.h> 37 38 using namespace phosphor::power::regulators; 39 using namespace phosphor::power::regulators::test_utils; 40 41 using ::testing::A; 42 using ::testing::Return; 43 using ::testing::TypedEq; 44 45 TEST(SystemTests, Constructor) 46 { 47 // Create Rules 48 std::vector<std::unique_ptr<Rule>> rules{}; 49 rules.emplace_back(createRule("set_voltage_rule")); 50 51 // Create Chassis 52 std::vector<std::unique_ptr<Chassis>> chassis{}; 53 std::vector<std::unique_ptr<Device>> devices{}; 54 devices.emplace_back(createDevice("reg1", {"rail1"})); 55 chassis.emplace_back(std::make_unique<Chassis>(1, std::move(devices))); 56 57 // Create System 58 System system{std::move(rules), std::move(chassis)}; 59 EXPECT_EQ(system.getChassis().size(), 1); 60 EXPECT_EQ(system.getChassis()[0]->getNumber(), 1); 61 EXPECT_NO_THROW(system.getIDMap().getRule("set_voltage_rule")); 62 EXPECT_NO_THROW(system.getIDMap().getDevice("reg1")); 63 EXPECT_NO_THROW(system.getIDMap().getRail("rail1")); 64 EXPECT_THROW(system.getIDMap().getRail("rail2"), std::invalid_argument); 65 EXPECT_EQ(system.getRules().size(), 1); 66 EXPECT_EQ(system.getRules()[0]->getID(), "set_voltage_rule"); 67 } 68 69 TEST(SystemTests, ClearCache) 70 { 71 // Create PresenceDetection 72 std::vector<std::unique_ptr<Action>> actions{}; 73 std::unique_ptr<PresenceDetection> presenceDetection = 74 std::make_unique<PresenceDetection>(std::move(actions)); 75 PresenceDetection* presenceDetectionPtr = presenceDetection.get(); 76 77 // Create Device that contains PresenceDetection 78 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 79 std::unique_ptr<Device> device = std::make_unique<Device>( 80 "reg1", true, 81 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 82 std::move(i2cInterface), std::move(presenceDetection)); 83 Device* devicePtr = device.get(); 84 85 // Create Chassis that contains Device 86 std::vector<std::unique_ptr<Device>> devices{}; 87 devices.emplace_back(std::move(device)); 88 std::unique_ptr<Chassis> chassis = 89 std::make_unique<Chassis>(1, std::move(devices)); 90 Chassis* chassisPtr = chassis.get(); 91 92 // Create System that contains Chassis 93 std::vector<std::unique_ptr<Rule>> rules{}; 94 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 95 chassisVec.emplace_back(std::move(chassis)); 96 System system{std::move(rules), std::move(chassisVec)}; 97 98 // Cache presence value in PresenceDetection 99 MockServices services{}; 100 presenceDetectionPtr->execute(services, system, *chassisPtr, *devicePtr); 101 EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value()); 102 103 // Clear cached data in System 104 system.clearCache(); 105 106 // Verify presence value no longer cached in PresenceDetection 107 EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value()); 108 } 109 110 TEST(SystemTests, CloseDevices) 111 { 112 // Specify an empty rules vector 113 std::vector<std::unique_ptr<Rule>> rules{}; 114 115 // Create mock services. Expect logDebug() to be called. 116 MockServices services{}; 117 MockJournal& journal = services.getMockJournal(); 118 EXPECT_CALL(journal, logDebug("Closing devices in chassis 1")).Times(1); 119 EXPECT_CALL(journal, logDebug("Closing devices in chassis 3")).Times(1); 120 EXPECT_CALL(journal, logInfo(A<const std::string&>())).Times(0); 121 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 122 123 // Create Chassis 124 std::vector<std::unique_ptr<Chassis>> chassis{}; 125 chassis.emplace_back(std::make_unique<Chassis>(1)); 126 chassis.emplace_back(std::make_unique<Chassis>(3)); 127 128 // Create System 129 System system{std::move(rules), std::move(chassis)}; 130 131 // Call closeDevices() 132 system.closeDevices(services); 133 } 134 135 TEST(SystemTests, Configure) 136 { 137 // Create mock services. Expect logInfo() to be called. 138 MockServices services{}; 139 MockJournal& journal = services.getMockJournal(); 140 EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1); 141 EXPECT_CALL(journal, logInfo("Configuring chassis 3")).Times(1); 142 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 143 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 144 145 // Specify an empty rules vector 146 std::vector<std::unique_ptr<Rule>> rules{}; 147 148 // Create Chassis 149 std::vector<std::unique_ptr<Chassis>> chassis{}; 150 chassis.emplace_back(std::make_unique<Chassis>(1)); 151 chassis.emplace_back(std::make_unique<Chassis>(3)); 152 153 // Create System 154 System system{std::move(rules), std::move(chassis)}; 155 156 // Call configure() 157 system.configure(services); 158 } 159 160 TEST(SystemTests, GetChassis) 161 { 162 // Specify an empty rules vector 163 std::vector<std::unique_ptr<Rule>> rules{}; 164 165 // Create Chassis 166 std::vector<std::unique_ptr<Chassis>> chassis{}; 167 chassis.emplace_back(std::make_unique<Chassis>(1)); 168 chassis.emplace_back(std::make_unique<Chassis>(3)); 169 170 // Create System 171 System system{std::move(rules), std::move(chassis)}; 172 EXPECT_EQ(system.getChassis().size(), 2); 173 EXPECT_EQ(system.getChassis()[0]->getNumber(), 1); 174 EXPECT_EQ(system.getChassis()[1]->getNumber(), 3); 175 } 176 177 TEST(SystemTests, GetIDMap) 178 { 179 // Create Rules 180 std::vector<std::unique_ptr<Rule>> rules{}; 181 rules.emplace_back(createRule("set_voltage_rule")); 182 rules.emplace_back(createRule("read_sensors_rule")); 183 184 // Create Chassis 185 std::vector<std::unique_ptr<Chassis>> chassis{}; 186 { 187 // Chassis 1 188 std::vector<std::unique_ptr<Device>> devices{}; 189 devices.emplace_back(createDevice("reg1", {"rail1"})); 190 devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"})); 191 chassis.emplace_back(std::make_unique<Chassis>(1, std::move(devices))); 192 } 193 { 194 // Chassis 2 195 std::vector<std::unique_ptr<Device>> devices{}; 196 devices.emplace_back(createDevice("reg3", {"rail3a", "rail3b"})); 197 devices.emplace_back(createDevice("reg4")); 198 chassis.emplace_back(std::make_unique<Chassis>(2, std::move(devices))); 199 } 200 201 // Create System 202 System system{std::move(rules), std::move(chassis)}; 203 const IDMap& idMap = system.getIDMap(); 204 205 // Verify all Rules are in the IDMap 206 EXPECT_NO_THROW(idMap.getRule("set_voltage_rule")); 207 EXPECT_NO_THROW(idMap.getRule("read_sensors_rule")); 208 EXPECT_THROW(idMap.getRule("set_voltage_rule2"), std::invalid_argument); 209 210 // Verify all Devices are in the IDMap 211 EXPECT_NO_THROW(idMap.getDevice("reg1")); 212 EXPECT_NO_THROW(idMap.getDevice("reg2")); 213 EXPECT_NO_THROW(idMap.getDevice("reg3")); 214 EXPECT_NO_THROW(idMap.getDevice("reg4")); 215 EXPECT_THROW(idMap.getDevice("reg5"), std::invalid_argument); 216 217 // Verify all Rails are in the IDMap 218 EXPECT_NO_THROW(idMap.getRail("rail1")); 219 EXPECT_NO_THROW(idMap.getRail("rail2a")); 220 EXPECT_NO_THROW(idMap.getRail("rail2b")); 221 EXPECT_NO_THROW(idMap.getRail("rail3a")); 222 EXPECT_NO_THROW(idMap.getRail("rail3b")); 223 EXPECT_THROW(idMap.getRail("rail4"), std::invalid_argument); 224 } 225 226 TEST(SystemTests, GetRules) 227 { 228 // Create Rules 229 std::vector<std::unique_ptr<Rule>> rules{}; 230 rules.emplace_back(createRule("set_voltage_rule")); 231 rules.emplace_back(createRule("read_sensors_rule")); 232 233 // Create Chassis 234 std::vector<std::unique_ptr<Chassis>> chassis{}; 235 chassis.emplace_back(std::make_unique<Chassis>(1)); 236 237 // Create System 238 System system{std::move(rules), std::move(chassis)}; 239 EXPECT_EQ(system.getRules().size(), 2); 240 EXPECT_EQ(system.getRules()[0]->getID(), "set_voltage_rule"); 241 EXPECT_EQ(system.getRules()[1]->getID(), "read_sensors_rule"); 242 } 243 244 TEST(SystemTests, MonitorSensors) 245 { 246 // Create mock services. No logging should occur. 247 MockServices services{}; 248 MockJournal& journal = services.getMockJournal(); 249 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 250 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 251 252 // Create PMBusReadSensorAction 253 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout}; 254 uint8_t command = 0x8C; 255 pmbus_utils::SensorDataFormat format{ 256 pmbus_utils::SensorDataFormat::linear_11}; 257 std::optional<int8_t> exponent{}; 258 std::unique_ptr<PMBusReadSensorAction> action = 259 std::make_unique<PMBusReadSensorAction>(type, command, format, 260 exponent); 261 262 // Create mock I2CInterface. A two-byte read should occur. 263 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 264 std::make_unique<i2c::MockedI2CInterface>(); 265 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 266 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>())) 267 .Times(1); 268 269 // Create SensorMonitoring 270 std::vector<std::unique_ptr<Action>> actions{}; 271 actions.emplace_back(std::move(action)); 272 std::unique_ptr<SensorMonitoring> sensorMonitoring = 273 std::make_unique<SensorMonitoring>(std::move(actions)); 274 275 // Create Rail 276 std::vector<std::unique_ptr<Rail>> rails{}; 277 std::unique_ptr<Configuration> configuration{}; 278 std::unique_ptr<Rail> rail = std::make_unique<Rail>( 279 "vdd0", std::move(configuration), std::move(sensorMonitoring)); 280 rails.emplace_back(std::move(rail)); 281 282 // Create Device 283 std::unique_ptr<PresenceDetection> presenceDetection{}; 284 std::unique_ptr<Configuration> deviceConfiguration{}; 285 std::unique_ptr<Device> device = std::make_unique<Device>( 286 "reg1", true, 287 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 288 std::move(i2cInterface), std::move(presenceDetection), 289 std::move(deviceConfiguration), std::move(rails)); 290 291 // Create Chassis 292 std::vector<std::unique_ptr<Device>> devices{}; 293 devices.emplace_back(std::move(device)); 294 std::unique_ptr<Chassis> chassis = 295 std::make_unique<Chassis>(1, std::move(devices)); 296 297 // Create System that contains Chassis 298 std::vector<std::unique_ptr<Rule>> rules{}; 299 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 300 chassisVec.emplace_back(std::move(chassis)); 301 System system{std::move(rules), std::move(chassisVec)}; 302 303 // Call monitorSensors() 304 system.monitorSensors(services); 305 } 306