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