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