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, CloseDevices) 70 { 71 // Specify an empty rules vector 72 std::vector<std::unique_ptr<Rule>> rules{}; 73 74 // Create mock services. Expect logDebug() to be called. 75 MockServices services{}; 76 MockJournal& journal = services.getMockJournal(); 77 EXPECT_CALL(journal, logDebug("Closing devices in chassis 1")).Times(1); 78 EXPECT_CALL(journal, logDebug("Closing devices in chassis 3")).Times(1); 79 EXPECT_CALL(journal, logInfo(A<const std::string&>())).Times(0); 80 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 81 82 // Create Chassis 83 std::vector<std::unique_ptr<Chassis>> chassis{}; 84 chassis.emplace_back(std::make_unique<Chassis>(1)); 85 chassis.emplace_back(std::make_unique<Chassis>(3)); 86 87 // Create System 88 System system{std::move(rules), std::move(chassis)}; 89 90 // Call closeDevices() 91 system.closeDevices(services); 92 } 93 94 TEST(SystemTests, Configure) 95 { 96 // Create mock services. Expect logInfo() to be called. 97 MockServices services{}; 98 MockJournal& journal = services.getMockJournal(); 99 EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1); 100 EXPECT_CALL(journal, logInfo("Configuring chassis 3")).Times(1); 101 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 102 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 103 104 // Specify an empty rules vector 105 std::vector<std::unique_ptr<Rule>> rules{}; 106 107 // Create Chassis 108 std::vector<std::unique_ptr<Chassis>> chassis{}; 109 chassis.emplace_back(std::make_unique<Chassis>(1)); 110 chassis.emplace_back(std::make_unique<Chassis>(3)); 111 112 // Create System 113 System system{std::move(rules), std::move(chassis)}; 114 115 // Call configure() 116 system.configure(services); 117 } 118 119 TEST(SystemTests, GetChassis) 120 { 121 // Specify an empty rules vector 122 std::vector<std::unique_ptr<Rule>> rules{}; 123 124 // Create Chassis 125 std::vector<std::unique_ptr<Chassis>> chassis{}; 126 chassis.emplace_back(std::make_unique<Chassis>(1)); 127 chassis.emplace_back(std::make_unique<Chassis>(3)); 128 129 // Create System 130 System system{std::move(rules), std::move(chassis)}; 131 EXPECT_EQ(system.getChassis().size(), 2); 132 EXPECT_EQ(system.getChassis()[0]->getNumber(), 1); 133 EXPECT_EQ(system.getChassis()[1]->getNumber(), 3); 134 } 135 136 TEST(SystemTests, GetIDMap) 137 { 138 // Create Rules 139 std::vector<std::unique_ptr<Rule>> rules{}; 140 rules.emplace_back(createRule("set_voltage_rule")); 141 rules.emplace_back(createRule("read_sensors_rule")); 142 143 // Create Chassis 144 std::vector<std::unique_ptr<Chassis>> chassis{}; 145 { 146 // Chassis 1 147 std::vector<std::unique_ptr<Device>> devices{}; 148 devices.emplace_back(createDevice("reg1", {"rail1"})); 149 devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"})); 150 chassis.emplace_back(std::make_unique<Chassis>(1, std::move(devices))); 151 } 152 { 153 // Chassis 2 154 std::vector<std::unique_ptr<Device>> devices{}; 155 devices.emplace_back(createDevice("reg3", {"rail3a", "rail3b"})); 156 devices.emplace_back(createDevice("reg4")); 157 chassis.emplace_back(std::make_unique<Chassis>(2, std::move(devices))); 158 } 159 160 // Create System 161 System system{std::move(rules), std::move(chassis)}; 162 const IDMap& idMap = system.getIDMap(); 163 164 // Verify all Rules are in the IDMap 165 EXPECT_NO_THROW(idMap.getRule("set_voltage_rule")); 166 EXPECT_NO_THROW(idMap.getRule("read_sensors_rule")); 167 EXPECT_THROW(idMap.getRule("set_voltage_rule2"), std::invalid_argument); 168 169 // Verify all Devices are in the IDMap 170 EXPECT_NO_THROW(idMap.getDevice("reg1")); 171 EXPECT_NO_THROW(idMap.getDevice("reg2")); 172 EXPECT_NO_THROW(idMap.getDevice("reg3")); 173 EXPECT_NO_THROW(idMap.getDevice("reg4")); 174 EXPECT_THROW(idMap.getDevice("reg5"), std::invalid_argument); 175 176 // Verify all Rails are in the IDMap 177 EXPECT_NO_THROW(idMap.getRail("rail1")); 178 EXPECT_NO_THROW(idMap.getRail("rail2a")); 179 EXPECT_NO_THROW(idMap.getRail("rail2b")); 180 EXPECT_NO_THROW(idMap.getRail("rail3a")); 181 EXPECT_NO_THROW(idMap.getRail("rail3b")); 182 EXPECT_THROW(idMap.getRail("rail4"), std::invalid_argument); 183 } 184 185 TEST(SystemTests, GetRules) 186 { 187 // Create Rules 188 std::vector<std::unique_ptr<Rule>> rules{}; 189 rules.emplace_back(createRule("set_voltage_rule")); 190 rules.emplace_back(createRule("read_sensors_rule")); 191 192 // Create Chassis 193 std::vector<std::unique_ptr<Chassis>> chassis{}; 194 chassis.emplace_back(std::make_unique<Chassis>(1)); 195 196 // Create System 197 System system{std::move(rules), std::move(chassis)}; 198 EXPECT_EQ(system.getRules().size(), 2); 199 EXPECT_EQ(system.getRules()[0]->getID(), "set_voltage_rule"); 200 EXPECT_EQ(system.getRules()[1]->getID(), "read_sensors_rule"); 201 } 202 203 TEST(SystemTests, MonitorSensors) 204 { 205 // Create mock services. No logging should occur. 206 MockServices services{}; 207 MockJournal& journal = services.getMockJournal(); 208 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 209 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 210 211 // Create PMBusReadSensorAction 212 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout}; 213 uint8_t command = 0x8C; 214 pmbus_utils::SensorDataFormat format{ 215 pmbus_utils::SensorDataFormat::linear_11}; 216 std::optional<int8_t> exponent{}; 217 std::unique_ptr<PMBusReadSensorAction> action = 218 std::make_unique<PMBusReadSensorAction>(type, command, format, 219 exponent); 220 221 // Create mock I2CInterface. A two-byte read should occur. 222 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 223 std::make_unique<i2c::MockedI2CInterface>(); 224 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 225 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>())) 226 .Times(1); 227 228 // Create SensorMonitoring 229 std::vector<std::unique_ptr<Action>> actions{}; 230 actions.emplace_back(std::move(action)); 231 std::unique_ptr<SensorMonitoring> sensorMonitoring = 232 std::make_unique<SensorMonitoring>(std::move(actions)); 233 234 // Create Rail 235 std::vector<std::unique_ptr<Rail>> rails{}; 236 std::unique_ptr<Configuration> configuration{}; 237 std::unique_ptr<Rail> rail = std::make_unique<Rail>( 238 "vdd0", std::move(configuration), std::move(sensorMonitoring)); 239 rails.emplace_back(std::move(rail)); 240 241 // Create Device 242 std::unique_ptr<PresenceDetection> presenceDetection{}; 243 std::unique_ptr<Configuration> deviceConfiguration{}; 244 std::unique_ptr<Device> device = std::make_unique<Device>( 245 "reg1", true, "/system/chassis/motherboard/reg1", 246 std::move(i2cInterface), std::move(presenceDetection), 247 std::move(deviceConfiguration), std::move(rails)); 248 249 // Create Chassis 250 std::vector<std::unique_ptr<Device>> devices{}; 251 devices.emplace_back(std::move(device)); 252 std::unique_ptr<Chassis> chassis = 253 std::make_unique<Chassis>(1, std::move(devices)); 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 system.monitorSensors(services); 263 } 264