xref: /openbmc/phosphor-power/phosphor-regulators/test/system_tests.cpp (revision b7552f0cbc6692693ef3430e0faa4f145f7b08c3)
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