1c3991f16SShawn McCarney /** 2c3991f16SShawn McCarney * Copyright © 2020 IBM Corporation 3c3991f16SShawn McCarney * 4c3991f16SShawn McCarney * Licensed under the Apache License, Version 2.0 (the "License"); 5c3991f16SShawn McCarney * you may not use this file except in compliance with the License. 6c3991f16SShawn McCarney * You may obtain a copy of the License at 7c3991f16SShawn McCarney * 8c3991f16SShawn McCarney * http://www.apache.org/licenses/LICENSE-2.0 9c3991f16SShawn McCarney * 10c3991f16SShawn McCarney * Unless required by applicable law or agreed to in writing, software 11c3991f16SShawn McCarney * distributed under the License is distributed on an "AS IS" BASIS, 12c3991f16SShawn McCarney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c3991f16SShawn McCarney * See the License for the specific language governing permissions and 14c3991f16SShawn McCarney * limitations under the License. 15c3991f16SShawn McCarney */ 16c3991f16SShawn McCarney #include "chassis.hpp" 17db0b833cSShawn McCarney #include "device.hpp" 18db0b833cSShawn McCarney #include "id_map.hpp" 192af5289dSShawn McCarney #include "mock_journal.hpp" 2023243f84SBob King #include "mock_services.hpp" 218e2294dcSBob King #include "mocked_i2c_interface.hpp" 228e2294dcSBob King #include "pmbus_read_sensor_action.hpp" 23db0b833cSShawn McCarney #include "rail.hpp" 24c3991f16SShawn McCarney #include "rule.hpp" 255cfe5103SBob King #include "services.hpp" 26c3991f16SShawn McCarney #include "system.hpp" 27db0b833cSShawn McCarney #include "test_utils.hpp" 28c3991f16SShawn McCarney 29c3991f16SShawn McCarney #include <memory> 30db0b833cSShawn McCarney #include <stdexcept> 312af5289dSShawn McCarney #include <string> 32c3991f16SShawn McCarney #include <utility> 33c3991f16SShawn McCarney #include <vector> 34c3991f16SShawn McCarney 358e2294dcSBob King #include <gmock/gmock.h> 36c3991f16SShawn McCarney #include <gtest/gtest.h> 37c3991f16SShawn McCarney 38c3991f16SShawn McCarney using namespace phosphor::power::regulators; 39db0b833cSShawn McCarney using namespace phosphor::power::regulators::test_utils; 40c3991f16SShawn McCarney 418e2294dcSBob King using ::testing::A; 428e2294dcSBob King using ::testing::Return; 438e2294dcSBob King using ::testing::TypedEq; 448e2294dcSBob King 45c3991f16SShawn McCarney TEST(SystemTests, Constructor) 46c3991f16SShawn McCarney { 47c3991f16SShawn McCarney // Create Rules 48c3991f16SShawn McCarney std::vector<std::unique_ptr<Rule>> rules{}; 49db0b833cSShawn McCarney rules.emplace_back(createRule("set_voltage_rule")); 50c3991f16SShawn McCarney 51c3991f16SShawn McCarney // Create Chassis 52c3991f16SShawn McCarney std::vector<std::unique_ptr<Chassis>> chassis{}; 53db0b833cSShawn McCarney std::vector<std::unique_ptr<Device>> devices{}; 54db0b833cSShawn McCarney devices.emplace_back(createDevice("reg1", {"rail1"})); 55db0b833cSShawn McCarney chassis.emplace_back(std::make_unique<Chassis>(1, std::move(devices))); 56c3991f16SShawn McCarney 57c3991f16SShawn McCarney // Create System 58c3991f16SShawn McCarney System system{std::move(rules), std::move(chassis)}; 59c3991f16SShawn McCarney EXPECT_EQ(system.getChassis().size(), 1); 60c3991f16SShawn McCarney EXPECT_EQ(system.getChassis()[0]->getNumber(), 1); 61db0b833cSShawn McCarney EXPECT_NO_THROW(system.getIDMap().getRule("set_voltage_rule")); 62db0b833cSShawn McCarney EXPECT_NO_THROW(system.getIDMap().getDevice("reg1")); 63db0b833cSShawn McCarney EXPECT_NO_THROW(system.getIDMap().getRail("rail1")); 64db0b833cSShawn McCarney EXPECT_THROW(system.getIDMap().getRail("rail2"), std::invalid_argument); 65c3991f16SShawn McCarney EXPECT_EQ(system.getRules().size(), 1); 66c3991f16SShawn McCarney EXPECT_EQ(system.getRules()[0]->getID(), "set_voltage_rule"); 67c3991f16SShawn McCarney } 68c3991f16SShawn McCarney 695b19ea51SShawn McCarney TEST(SystemTests, CloseDevices) 705b19ea51SShawn McCarney { 715b19ea51SShawn McCarney // Specify an empty rules vector 725b19ea51SShawn McCarney std::vector<std::unique_ptr<Rule>> rules{}; 735b19ea51SShawn McCarney 745b19ea51SShawn McCarney // Create Chassis 755b19ea51SShawn McCarney std::vector<std::unique_ptr<Chassis>> chassis{}; 765b19ea51SShawn McCarney chassis.emplace_back(std::make_unique<Chassis>(1)); 775b19ea51SShawn McCarney chassis.emplace_back(std::make_unique<Chassis>(3)); 785b19ea51SShawn McCarney 795b19ea51SShawn McCarney // Create System 805b19ea51SShawn McCarney System system{std::move(rules), std::move(chassis)}; 815b19ea51SShawn McCarney 825b19ea51SShawn McCarney // Call closeDevices() 835b19ea51SShawn McCarney journal::clear(); 845b19ea51SShawn McCarney system.closeDevices(); 855b19ea51SShawn McCarney EXPECT_EQ(journal::getErrMessages().size(), 0); 865b19ea51SShawn McCarney EXPECT_EQ(journal::getInfoMessages().size(), 0); 875b19ea51SShawn McCarney std::vector<std::string> expectedDebugMessages{ 885b19ea51SShawn McCarney "Closing devices in chassis 1", "Closing devices in chassis 3"}; 895b19ea51SShawn McCarney EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages); 905b19ea51SShawn McCarney } 915b19ea51SShawn McCarney 922af5289dSShawn McCarney TEST(SystemTests, Configure) 932af5289dSShawn McCarney { 945cfe5103SBob King // Create mock services. Expect logInfo() to be called. 9523243f84SBob King MockServices services{}; 965cfe5103SBob King MockJournal& journal = services.getMockJournal(); 975cfe5103SBob King EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1); 985cfe5103SBob King EXPECT_CALL(journal, logInfo("Configuring chassis 3")).Times(1); 995cfe5103SBob King EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 1005cfe5103SBob King EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 10123243f84SBob King 1022af5289dSShawn McCarney // Specify an empty rules vector 1032af5289dSShawn McCarney std::vector<std::unique_ptr<Rule>> rules{}; 1042af5289dSShawn McCarney 1052af5289dSShawn McCarney // Create Chassis 1062af5289dSShawn McCarney std::vector<std::unique_ptr<Chassis>> chassis{}; 1072af5289dSShawn McCarney chassis.emplace_back(std::make_unique<Chassis>(1)); 1082af5289dSShawn McCarney chassis.emplace_back(std::make_unique<Chassis>(3)); 1092af5289dSShawn McCarney 1102af5289dSShawn McCarney // Create System 1112af5289dSShawn McCarney System system{std::move(rules), std::move(chassis)}; 1122af5289dSShawn McCarney 1132af5289dSShawn McCarney // Call configure() 11423243f84SBob King system.configure(services); 1152af5289dSShawn McCarney } 1162af5289dSShawn McCarney 117c3991f16SShawn McCarney TEST(SystemTests, GetChassis) 118c3991f16SShawn McCarney { 119c3991f16SShawn McCarney // Specify an empty rules vector 120c3991f16SShawn McCarney std::vector<std::unique_ptr<Rule>> rules{}; 121c3991f16SShawn McCarney 122c3991f16SShawn McCarney // Create Chassis 123c3991f16SShawn McCarney std::vector<std::unique_ptr<Chassis>> chassis{}; 124c3991f16SShawn McCarney chassis.emplace_back(std::make_unique<Chassis>(1)); 125c3991f16SShawn McCarney chassis.emplace_back(std::make_unique<Chassis>(3)); 126c3991f16SShawn McCarney 127c3991f16SShawn McCarney // Create System 128c3991f16SShawn McCarney System system{std::move(rules), std::move(chassis)}; 129c3991f16SShawn McCarney EXPECT_EQ(system.getChassis().size(), 2); 130c3991f16SShawn McCarney EXPECT_EQ(system.getChassis()[0]->getNumber(), 1); 131c3991f16SShawn McCarney EXPECT_EQ(system.getChassis()[1]->getNumber(), 3); 132c3991f16SShawn McCarney } 133c3991f16SShawn McCarney 134c3991f16SShawn McCarney TEST(SystemTests, GetIDMap) 135c3991f16SShawn McCarney { 136db0b833cSShawn McCarney // Create Rules 137db0b833cSShawn McCarney std::vector<std::unique_ptr<Rule>> rules{}; 138db0b833cSShawn McCarney rules.emplace_back(createRule("set_voltage_rule")); 139db0b833cSShawn McCarney rules.emplace_back(createRule("read_sensors_rule")); 140db0b833cSShawn McCarney 141db0b833cSShawn McCarney // Create Chassis 142db0b833cSShawn McCarney std::vector<std::unique_ptr<Chassis>> chassis{}; 143db0b833cSShawn McCarney { 144db0b833cSShawn McCarney // Chassis 1 145db0b833cSShawn McCarney std::vector<std::unique_ptr<Device>> devices{}; 146db0b833cSShawn McCarney devices.emplace_back(createDevice("reg1", {"rail1"})); 147db0b833cSShawn McCarney devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"})); 148db0b833cSShawn McCarney chassis.emplace_back(std::make_unique<Chassis>(1, std::move(devices))); 149db0b833cSShawn McCarney } 150db0b833cSShawn McCarney { 151db0b833cSShawn McCarney // Chassis 2 152db0b833cSShawn McCarney std::vector<std::unique_ptr<Device>> devices{}; 153db0b833cSShawn McCarney devices.emplace_back(createDevice("reg3", {"rail3a", "rail3b"})); 154db0b833cSShawn McCarney devices.emplace_back(createDevice("reg4")); 155db0b833cSShawn McCarney chassis.emplace_back(std::make_unique<Chassis>(2, std::move(devices))); 156db0b833cSShawn McCarney } 157db0b833cSShawn McCarney 158db0b833cSShawn McCarney // Create System 159db0b833cSShawn McCarney System system{std::move(rules), std::move(chassis)}; 160db0b833cSShawn McCarney const IDMap& idMap = system.getIDMap(); 161db0b833cSShawn McCarney 162db0b833cSShawn McCarney // Verify all Rules are in the IDMap 163db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getRule("set_voltage_rule")); 164db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getRule("read_sensors_rule")); 165db0b833cSShawn McCarney EXPECT_THROW(idMap.getRule("set_voltage_rule2"), std::invalid_argument); 166db0b833cSShawn McCarney 167db0b833cSShawn McCarney // Verify all Devices are in the IDMap 168db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getDevice("reg1")); 169db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getDevice("reg2")); 170db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getDevice("reg3")); 171db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getDevice("reg4")); 172db0b833cSShawn McCarney EXPECT_THROW(idMap.getDevice("reg5"), std::invalid_argument); 173db0b833cSShawn McCarney 174db0b833cSShawn McCarney // Verify all Rails are in the IDMap 175db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getRail("rail1")); 176db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getRail("rail2a")); 177db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getRail("rail2b")); 178db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getRail("rail3a")); 179db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getRail("rail3b")); 180db0b833cSShawn McCarney EXPECT_THROW(idMap.getRail("rail4"), std::invalid_argument); 181c3991f16SShawn McCarney } 182c3991f16SShawn McCarney 183c3991f16SShawn McCarney TEST(SystemTests, GetRules) 184c3991f16SShawn McCarney { 185c3991f16SShawn McCarney // Create Rules 186c3991f16SShawn McCarney std::vector<std::unique_ptr<Rule>> rules{}; 187db0b833cSShawn McCarney rules.emplace_back(createRule("set_voltage_rule")); 188db0b833cSShawn McCarney rules.emplace_back(createRule("read_sensors_rule")); 189c3991f16SShawn McCarney 190c3991f16SShawn McCarney // Create Chassis 191c3991f16SShawn McCarney std::vector<std::unique_ptr<Chassis>> chassis{}; 192c3991f16SShawn McCarney chassis.emplace_back(std::make_unique<Chassis>(1)); 193c3991f16SShawn McCarney 194c3991f16SShawn McCarney // Create System 195c3991f16SShawn McCarney System system{std::move(rules), std::move(chassis)}; 196c3991f16SShawn McCarney EXPECT_EQ(system.getRules().size(), 2); 197c3991f16SShawn McCarney EXPECT_EQ(system.getRules()[0]->getID(), "set_voltage_rule"); 198c3991f16SShawn McCarney EXPECT_EQ(system.getRules()[1]->getID(), "read_sensors_rule"); 199c3991f16SShawn McCarney } 2008e2294dcSBob King 2018e2294dcSBob King TEST(SystemTests, MonitorSensors) 2028e2294dcSBob King { 203*8a55292dSBob King // Create mock services. No logging should occur. 204*8a55292dSBob King MockServices services{}; 205*8a55292dSBob King MockJournal& journal = services.getMockJournal(); 206*8a55292dSBob King EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 207*8a55292dSBob King EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 208*8a55292dSBob King 2098e2294dcSBob King // Create PMBusReadSensorAction 2108e2294dcSBob King pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout}; 2118e2294dcSBob King uint8_t command = 0x8C; 2128e2294dcSBob King pmbus_utils::SensorDataFormat format{ 2138e2294dcSBob King pmbus_utils::SensorDataFormat::linear_11}; 2148e2294dcSBob King std::optional<int8_t> exponent{}; 2158e2294dcSBob King std::unique_ptr<PMBusReadSensorAction> action = 2168e2294dcSBob King std::make_unique<PMBusReadSensorAction>(type, command, format, 2178e2294dcSBob King exponent); 2188e2294dcSBob King 2198e2294dcSBob King // Create mock I2CInterface. A two-byte read should occur. 2208e2294dcSBob King std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 2218e2294dcSBob King std::make_unique<i2c::MockedI2CInterface>(); 2228e2294dcSBob King EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 2238e2294dcSBob King EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>())) 2248e2294dcSBob King .Times(1); 2258e2294dcSBob King 2268e2294dcSBob King // Create SensorMonitoring 2278e2294dcSBob King std::vector<std::unique_ptr<Action>> actions{}; 2288e2294dcSBob King actions.emplace_back(std::move(action)); 2298e2294dcSBob King std::unique_ptr<SensorMonitoring> sensorMonitoring = 2308e2294dcSBob King std::make_unique<SensorMonitoring>(std::move(actions)); 2318e2294dcSBob King 2328e2294dcSBob King // Create Rail 2338e2294dcSBob King std::vector<std::unique_ptr<Rail>> rails{}; 2348e2294dcSBob King std::unique_ptr<Configuration> configuration{}; 2358e2294dcSBob King std::unique_ptr<Rail> rail = std::make_unique<Rail>( 2368e2294dcSBob King "vdd0", std::move(configuration), std::move(sensorMonitoring)); 2378e2294dcSBob King rails.emplace_back(std::move(rail)); 2388e2294dcSBob King 2398e2294dcSBob King // Create Device 2408e2294dcSBob King std::unique_ptr<PresenceDetection> presenceDetection{}; 2418e2294dcSBob King std::unique_ptr<Configuration> deviceConfiguration{}; 2428e2294dcSBob King std::unique_ptr<Device> device = std::make_unique<Device>( 2438e2294dcSBob King "reg1", true, "/system/chassis/motherboard/reg1", 2448e2294dcSBob King std::move(i2cInterface), std::move(presenceDetection), 2458e2294dcSBob King std::move(deviceConfiguration), std::move(rails)); 2468e2294dcSBob King 2478e2294dcSBob King // Create Chassis 2488e2294dcSBob King std::vector<std::unique_ptr<Device>> devices{}; 2498e2294dcSBob King devices.emplace_back(std::move(device)); 2508e2294dcSBob King std::unique_ptr<Chassis> chassis = 2518e2294dcSBob King std::make_unique<Chassis>(1, std::move(devices)); 2528e2294dcSBob King 2538e2294dcSBob King // Create System that contains Chassis 2548e2294dcSBob King std::vector<std::unique_ptr<Rule>> rules{}; 2558e2294dcSBob King std::vector<std::unique_ptr<Chassis>> chassisVec{}; 2568e2294dcSBob King chassisVec.emplace_back(std::move(chassis)); 2578e2294dcSBob King System system{std::move(rules), std::move(chassisVec)}; 2588e2294dcSBob King 2598e2294dcSBob King // Call monitorSensors() 260*8a55292dSBob King system.monitorSensors(services); 2618e2294dcSBob King } 262