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