blob: b71155c5462723ce2dce71cd76b5e4b9c5b6248f [file] [log] [blame]
Shawn McCarneyc3991f12020-04-05 13:16:06 -05001/**
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 */
Shawn McCarneyc3991f12020-04-05 13:16:06 -050016#include "chassis.hpp"
Shawn McCarneydb0b8332020-04-06 14:13:04 -050017#include "device.hpp"
18#include "id_map.hpp"
Shawn McCarney2af52892020-04-14 11:54:45 -050019#include "mock_journal.hpp"
Bob King23243f82020-07-29 10:38:57 +080020#include "mock_services.hpp"
Bob King8e2294d2020-07-14 17:41:31 +080021#include "mocked_i2c_interface.hpp"
22#include "pmbus_read_sensor_action.hpp"
Shawn McCarneydb0b8332020-04-06 14:13:04 -050023#include "rail.hpp"
Shawn McCarneyc3991f12020-04-05 13:16:06 -050024#include "rule.hpp"
Bob King5cfe5102020-07-30 16:26:18 +080025#include "services.hpp"
Shawn McCarneyc3991f12020-04-05 13:16:06 -050026#include "system.hpp"
Shawn McCarneydb0b8332020-04-06 14:13:04 -050027#include "test_utils.hpp"
Shawn McCarneyc3991f12020-04-05 13:16:06 -050028
29#include <memory>
Shawn McCarneydb0b8332020-04-06 14:13:04 -050030#include <stdexcept>
Shawn McCarney2af52892020-04-14 11:54:45 -050031#include <string>
Shawn McCarneyc3991f12020-04-05 13:16:06 -050032#include <utility>
33#include <vector>
34
Bob King8e2294d2020-07-14 17:41:31 +080035#include <gmock/gmock.h>
Shawn McCarneyc3991f12020-04-05 13:16:06 -050036#include <gtest/gtest.h>
37
38using namespace phosphor::power::regulators;
Shawn McCarneydb0b8332020-04-06 14:13:04 -050039using namespace phosphor::power::regulators::test_utils;
Shawn McCarneyc3991f12020-04-05 13:16:06 -050040
Bob King8e2294d2020-07-14 17:41:31 +080041using ::testing::A;
42using ::testing::Return;
43using ::testing::TypedEq;
44
Shawn McCarneyc3991f12020-04-05 13:16:06 -050045TEST(SystemTests, Constructor)
46{
47 // Create Rules
48 std::vector<std::unique_ptr<Rule>> rules{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -050049 rules.emplace_back(createRule("set_voltage_rule"));
Shawn McCarneyc3991f12020-04-05 13:16:06 -050050
51 // Create Chassis
52 std::vector<std::unique_ptr<Chassis>> chassis{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -050053 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)));
Shawn McCarneyc3991f12020-04-05 13:16:06 -050056
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);
Shawn McCarneydb0b8332020-04-06 14:13:04 -050061 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);
Shawn McCarneyc3991f12020-04-05 13:16:06 -050065 EXPECT_EQ(system.getRules().size(), 1);
66 EXPECT_EQ(system.getRules()[0]->getID(), "set_voltage_rule");
67}
68
Shawn McCarney9bd94d32021-01-25 19:40:42 -060069TEST(SystemTests, ClearCache)
70{
71 // Create PresenceDetection
72 std::vector<std::unique_ptr<Action>> actions{};
73 std::unique_ptr<PresenceDetection> presenceDetection =
74 std::make_unique<PresenceDetection>(std::move(actions));
75 PresenceDetection* presenceDetectionPtr = presenceDetection.get();
76
77 // Create Device that contains PresenceDetection
78 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
79 std::unique_ptr<Device> device = std::make_unique<Device>(
80 "reg1", true,
81 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
82 std::move(i2cInterface), std::move(presenceDetection));
83 Device* devicePtr = device.get();
84
85 // Create Chassis that contains Device
86 std::vector<std::unique_ptr<Device>> devices{};
87 devices.emplace_back(std::move(device));
88 std::unique_ptr<Chassis> chassis =
89 std::make_unique<Chassis>(1, std::move(devices));
90 Chassis* chassisPtr = chassis.get();
91
92 // Create System that contains Chassis
93 std::vector<std::unique_ptr<Rule>> rules{};
94 std::vector<std::unique_ptr<Chassis>> chassisVec{};
95 chassisVec.emplace_back(std::move(chassis));
96 System system{std::move(rules), std::move(chassisVec)};
97
98 // Cache presence value in PresenceDetection
99 MockServices services{};
100 presenceDetectionPtr->execute(services, system, *chassisPtr, *devicePtr);
101 EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
102
103 // Clear cached data in System
104 system.clearCache();
105
106 // Verify presence value no longer cached in PresenceDetection
107 EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
108}
109
Shawn McCarney5b19ea52020-06-02 18:52:56 -0500110TEST(SystemTests, CloseDevices)
111{
112 // Specify an empty rules vector
113 std::vector<std::unique_ptr<Rule>> rules{};
114
Bob Kingd692d6d2020-09-14 13:42:57 +0800115 // Create mock services. Expect logDebug() to be called.
116 MockServices services{};
117 MockJournal& journal = services.getMockJournal();
118 EXPECT_CALL(journal, logDebug("Closing devices in chassis 1")).Times(1);
119 EXPECT_CALL(journal, logDebug("Closing devices in chassis 3")).Times(1);
120 EXPECT_CALL(journal, logInfo(A<const std::string&>())).Times(0);
121 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
122
Shawn McCarney5b19ea52020-06-02 18:52:56 -0500123 // Create Chassis
124 std::vector<std::unique_ptr<Chassis>> chassis{};
125 chassis.emplace_back(std::make_unique<Chassis>(1));
126 chassis.emplace_back(std::make_unique<Chassis>(3));
127
128 // Create System
129 System system{std::move(rules), std::move(chassis)};
130
131 // Call closeDevices()
Bob Kingd692d6d2020-09-14 13:42:57 +0800132 system.closeDevices(services);
Shawn McCarney5b19ea52020-06-02 18:52:56 -0500133}
134
Shawn McCarney2af52892020-04-14 11:54:45 -0500135TEST(SystemTests, Configure)
136{
Bob King5cfe5102020-07-30 16:26:18 +0800137 // Create mock services. Expect logInfo() to be called.
Bob King23243f82020-07-29 10:38:57 +0800138 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800139 MockJournal& journal = services.getMockJournal();
140 EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1);
141 EXPECT_CALL(journal, logInfo("Configuring chassis 3")).Times(1);
142 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
143 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800144
Shawn McCarney2af52892020-04-14 11:54:45 -0500145 // Specify an empty rules vector
146 std::vector<std::unique_ptr<Rule>> rules{};
147
148 // Create Chassis
149 std::vector<std::unique_ptr<Chassis>> chassis{};
150 chassis.emplace_back(std::make_unique<Chassis>(1));
151 chassis.emplace_back(std::make_unique<Chassis>(3));
152
153 // Create System
154 System system{std::move(rules), std::move(chassis)};
155
156 // Call configure()
Bob King23243f82020-07-29 10:38:57 +0800157 system.configure(services);
Shawn McCarney2af52892020-04-14 11:54:45 -0500158}
159
Shawn McCarneyc3991f12020-04-05 13:16:06 -0500160TEST(SystemTests, GetChassis)
161{
162 // Specify an empty rules vector
163 std::vector<std::unique_ptr<Rule>> rules{};
164
165 // Create Chassis
166 std::vector<std::unique_ptr<Chassis>> chassis{};
167 chassis.emplace_back(std::make_unique<Chassis>(1));
168 chassis.emplace_back(std::make_unique<Chassis>(3));
169
170 // Create System
171 System system{std::move(rules), std::move(chassis)};
172 EXPECT_EQ(system.getChassis().size(), 2);
173 EXPECT_EQ(system.getChassis()[0]->getNumber(), 1);
174 EXPECT_EQ(system.getChassis()[1]->getNumber(), 3);
175}
176
177TEST(SystemTests, GetIDMap)
178{
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500179 // Create Rules
180 std::vector<std::unique_ptr<Rule>> rules{};
181 rules.emplace_back(createRule("set_voltage_rule"));
182 rules.emplace_back(createRule("read_sensors_rule"));
183
184 // Create Chassis
185 std::vector<std::unique_ptr<Chassis>> chassis{};
186 {
187 // Chassis 1
188 std::vector<std::unique_ptr<Device>> devices{};
189 devices.emplace_back(createDevice("reg1", {"rail1"}));
190 devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"}));
191 chassis.emplace_back(std::make_unique<Chassis>(1, std::move(devices)));
192 }
193 {
194 // Chassis 2
195 std::vector<std::unique_ptr<Device>> devices{};
196 devices.emplace_back(createDevice("reg3", {"rail3a", "rail3b"}));
197 devices.emplace_back(createDevice("reg4"));
198 chassis.emplace_back(std::make_unique<Chassis>(2, std::move(devices)));
199 }
200
201 // Create System
202 System system{std::move(rules), std::move(chassis)};
203 const IDMap& idMap = system.getIDMap();
204
205 // Verify all Rules are in the IDMap
206 EXPECT_NO_THROW(idMap.getRule("set_voltage_rule"));
207 EXPECT_NO_THROW(idMap.getRule("read_sensors_rule"));
208 EXPECT_THROW(idMap.getRule("set_voltage_rule2"), std::invalid_argument);
209
210 // Verify all Devices are in the IDMap
211 EXPECT_NO_THROW(idMap.getDevice("reg1"));
212 EXPECT_NO_THROW(idMap.getDevice("reg2"));
213 EXPECT_NO_THROW(idMap.getDevice("reg3"));
214 EXPECT_NO_THROW(idMap.getDevice("reg4"));
215 EXPECT_THROW(idMap.getDevice("reg5"), std::invalid_argument);
216
217 // Verify all Rails are in the IDMap
218 EXPECT_NO_THROW(idMap.getRail("rail1"));
219 EXPECT_NO_THROW(idMap.getRail("rail2a"));
220 EXPECT_NO_THROW(idMap.getRail("rail2b"));
221 EXPECT_NO_THROW(idMap.getRail("rail3a"));
222 EXPECT_NO_THROW(idMap.getRail("rail3b"));
223 EXPECT_THROW(idMap.getRail("rail4"), std::invalid_argument);
Shawn McCarneyc3991f12020-04-05 13:16:06 -0500224}
225
226TEST(SystemTests, GetRules)
227{
228 // Create Rules
229 std::vector<std::unique_ptr<Rule>> rules{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500230 rules.emplace_back(createRule("set_voltage_rule"));
231 rules.emplace_back(createRule("read_sensors_rule"));
Shawn McCarneyc3991f12020-04-05 13:16:06 -0500232
233 // Create Chassis
234 std::vector<std::unique_ptr<Chassis>> chassis{};
235 chassis.emplace_back(std::make_unique<Chassis>(1));
236
237 // Create System
238 System system{std::move(rules), std::move(chassis)};
239 EXPECT_EQ(system.getRules().size(), 2);
240 EXPECT_EQ(system.getRules()[0]->getID(), "set_voltage_rule");
241 EXPECT_EQ(system.getRules()[1]->getID(), "read_sensors_rule");
242}
Bob King8e2294d2020-07-14 17:41:31 +0800243
244TEST(SystemTests, MonitorSensors)
245{
Bob King8a552922020-08-05 17:02:31 +0800246 // Create mock services. No logging should occur.
247 MockServices services{};
248 MockJournal& journal = services.getMockJournal();
249 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
250 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
251
Bob King8e2294d2020-07-14 17:41:31 +0800252 // Create PMBusReadSensorAction
253 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};
254 uint8_t command = 0x8C;
255 pmbus_utils::SensorDataFormat format{
256 pmbus_utils::SensorDataFormat::linear_11};
257 std::optional<int8_t> exponent{};
258 std::unique_ptr<PMBusReadSensorAction> action =
259 std::make_unique<PMBusReadSensorAction>(type, command, format,
260 exponent);
261
262 // Create mock I2CInterface. A two-byte read should occur.
263 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
264 std::make_unique<i2c::MockedI2CInterface>();
265 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
266 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
267 .Times(1);
268
269 // Create SensorMonitoring
270 std::vector<std::unique_ptr<Action>> actions{};
271 actions.emplace_back(std::move(action));
272 std::unique_ptr<SensorMonitoring> sensorMonitoring =
273 std::make_unique<SensorMonitoring>(std::move(actions));
274
275 // Create Rail
276 std::vector<std::unique_ptr<Rail>> rails{};
277 std::unique_ptr<Configuration> configuration{};
278 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
279 "vdd0", std::move(configuration), std::move(sensorMonitoring));
280 rails.emplace_back(std::move(rail));
281
282 // Create Device
283 std::unique_ptr<PresenceDetection> presenceDetection{};
284 std::unique_ptr<Configuration> deviceConfiguration{};
285 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800286 "reg1", true,
287 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob King8e2294d2020-07-14 17:41:31 +0800288 std::move(i2cInterface), std::move(presenceDetection),
289 std::move(deviceConfiguration), std::move(rails));
290
291 // Create Chassis
292 std::vector<std::unique_ptr<Device>> devices{};
293 devices.emplace_back(std::move(device));
294 std::unique_ptr<Chassis> chassis =
295 std::make_unique<Chassis>(1, std::move(devices));
296
297 // Create System that contains Chassis
298 std::vector<std::unique_ptr<Rule>> rules{};
299 std::vector<std::unique_ptr<Chassis>> chassisVec{};
300 chassisVec.emplace_back(std::move(chassis));
301 System system{std::move(rules), std::move(chassisVec)};
302
303 // Call monitorSensors()
Bob King8a552922020-08-05 17:02:31 +0800304 system.monitorSensors(services);
Bob King8e2294d2020-07-14 17:41:31 +0800305}