blob: 3844ca476ec0399c93015b8862c217b181e1f2f8 [file] [log] [blame]
Shawn McCarney8a3afd72020-03-12 14:28:44 -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 McCarney525e20c2020-04-14 11:05:39 -050016#include "action.hpp"
Shawn McCarney8a3afd72020-03-12 14:28:44 -050017#include "chassis.hpp"
Shawn McCarney525e20c2020-04-14 11:05:39 -050018#include "configuration.hpp"
Shawn McCarney8a3afd72020-03-12 14:28:44 -050019#include "device.hpp"
20#include "i2c_interface.hpp"
Shawn McCarneydb0b8332020-04-06 14:13:04 -050021#include "id_map.hpp"
Shawn McCarney525e20c2020-04-14 11:05:39 -050022#include "mock_journal.hpp"
Bob King23243f82020-07-29 10:38:57 +080023#include "mock_services.hpp"
Shawn McCarney050531f2020-06-02 14:17:12 -050024#include "mocked_i2c_interface.hpp"
Bob Kinga2c81a62020-07-08 13:31:16 +080025#include "pmbus_read_sensor_action.hpp"
Shawn McCarney525e20c2020-04-14 11:05:39 -050026#include "presence_detection.hpp"
27#include "rail.hpp"
28#include "rule.hpp"
29#include "system.hpp"
Shawn McCarney8a3afd72020-03-12 14:28:44 -050030#include "test_utils.hpp"
31
32#include <memory>
33#include <stdexcept>
Shawn McCarney525e20c2020-04-14 11:05:39 -050034#include <string>
Shawn McCarney8a3afd72020-03-12 14:28:44 -050035#include <utility>
36#include <vector>
37
Bob Kinga2c81a62020-07-08 13:31:16 +080038#include <gmock/gmock.h>
Shawn McCarney8a3afd72020-03-12 14:28:44 -050039#include <gtest/gtest.h>
40
41using namespace phosphor::power::regulators;
42using namespace phosphor::power::regulators::test_utils;
43
Bob Kinga2c81a62020-07-08 13:31:16 +080044using ::testing::A;
Shawn McCarney050531f2020-06-02 14:17:12 -050045using ::testing::Return;
Bob Kinga2c81a62020-07-08 13:31:16 +080046using ::testing::TypedEq;
Shawn McCarney050531f2020-06-02 14:17:12 -050047
Shawn McCarney8a3afd72020-03-12 14:28:44 -050048TEST(ChassisTests, Constructor)
49{
50 // Test where works: Only required parameters are specified
51 {
52 Chassis chassis{2};
53 EXPECT_EQ(chassis.getNumber(), 2);
54 EXPECT_EQ(chassis.getDevices().size(), 0);
55 }
56
57 // Test where works: All parameters are specified
58 {
59 // Create vector of Device objects
60 std::vector<std::unique_ptr<Device>> devices{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -050061 devices.emplace_back(createDevice("vdd_reg1"));
62 devices.emplace_back(createDevice("vdd_reg2"));
Shawn McCarney8a3afd72020-03-12 14:28:44 -050063
64 // Create Chassis
65 Chassis chassis{1, std::move(devices)};
66 EXPECT_EQ(chassis.getNumber(), 1);
67 EXPECT_EQ(chassis.getDevices().size(), 2);
68 }
69
70 // Test where fails: Invalid chassis number < 1
71 try
72 {
73 Chassis chassis{0};
74 ADD_FAILURE() << "Should not have reached this line.";
75 }
76 catch (const std::invalid_argument& e)
77 {
78 EXPECT_STREQ(e.what(), "Invalid chassis number: 0");
79 }
80 catch (...)
81 {
82 ADD_FAILURE() << "Should not have caught exception.";
83 }
84}
85
Shawn McCarneydb0b8332020-04-06 14:13:04 -050086TEST(ChassisTests, AddToIDMap)
87{
88 // Create vector of Device objects
89 std::vector<std::unique_ptr<Device>> devices{};
90 devices.emplace_back(createDevice("reg1", {"rail1"}));
91 devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"}));
92 devices.emplace_back(createDevice("reg3"));
93
94 // Create Chassis
95 Chassis chassis{1, std::move(devices)};
96
97 // Add Device and Rail objects within the Chassis to an IDMap
98 IDMap idMap{};
99 chassis.addToIDMap(idMap);
100
101 // Verify all Devices are in the IDMap
102 EXPECT_NO_THROW(idMap.getDevice("reg1"));
103 EXPECT_NO_THROW(idMap.getDevice("reg2"));
104 EXPECT_NO_THROW(idMap.getDevice("reg3"));
105 EXPECT_THROW(idMap.getDevice("reg4"), std::invalid_argument);
106
107 // Verify all Rails are in the IDMap
108 EXPECT_NO_THROW(idMap.getRail("rail1"));
109 EXPECT_NO_THROW(idMap.getRail("rail2a"));
110 EXPECT_NO_THROW(idMap.getRail("rail2b"));
111 EXPECT_THROW(idMap.getRail("rail3"), std::invalid_argument);
112}
113
Shawn McCarney050531f2020-06-02 14:17:12 -0500114TEST(ChassisTests, CloseDevices)
115{
116 // Test where no devices were specified in constructor
117 {
Bob Kingd692d6d2020-09-14 13:42:57 +0800118 // Create mock services. Expect logDebug() to be called.
119 MockServices services{};
120 MockJournal& journal = services.getMockJournal();
121 EXPECT_CALL(journal, logDebug("Closing devices in chassis 2")).Times(1);
122
Shawn McCarney050531f2020-06-02 14:17:12 -0500123 // Create Chassis
124 Chassis chassis{2};
125
126 // Call closeDevices()
Bob Kingd692d6d2020-09-14 13:42:57 +0800127 chassis.closeDevices(services);
Shawn McCarney050531f2020-06-02 14:17:12 -0500128 }
129
130 // Test where devices were specified in constructor
131 {
132 std::vector<std::unique_ptr<Device>> devices{};
133
Bob Kingd692d6d2020-09-14 13:42:57 +0800134 // Create mock services. Expect logDebug() to be called.
135 MockServices services{};
136 MockJournal& journal = services.getMockJournal();
137 EXPECT_CALL(journal, logDebug("Closing devices in chassis 1")).Times(1);
138
Shawn McCarney050531f2020-06-02 14:17:12 -0500139 // Create Device vdd0_reg
140 {
141 // Create mock I2CInterface: isOpen() and close() should be called
142 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
143 std::make_unique<i2c::MockedI2CInterface>();
144 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
145 EXPECT_CALL(*i2cInterface, close).Times(1);
146
147 // Create Device
148 std::unique_ptr<Device> device = std::make_unique<Device>(
149 "vdd0_reg", true, "/system/chassis/motherboard/vdd0_reg",
150 std::move(i2cInterface));
151 devices.emplace_back(std::move(device));
152 }
153
154 // Create Device vdd1_reg
155 {
156 // Create mock I2CInterface: isOpen() and close() should be called
157 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
158 std::make_unique<i2c::MockedI2CInterface>();
159 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
160 EXPECT_CALL(*i2cInterface, close).Times(1);
161
162 // Create Device
163 std::unique_ptr<Device> device = std::make_unique<Device>(
164 "vdd1_reg", true, "/system/chassis/motherboard/vdd1_reg",
165 std::move(i2cInterface));
166 devices.emplace_back(std::move(device));
167 }
168
169 // Create Chassis
170 Chassis chassis{1, std::move(devices)};
171
172 // Call closeDevices()
Bob Kingd692d6d2020-09-14 13:42:57 +0800173 chassis.closeDevices(services);
Shawn McCarney050531f2020-06-02 14:17:12 -0500174 }
175}
176
Shawn McCarney525e20c2020-04-14 11:05:39 -0500177TEST(ChassisTests, Configure)
178{
179 // Test where no devices were specified in constructor
180 {
Bob King5cfe5102020-07-30 16:26:18 +0800181 // Create mock services. Expect logInfo() to be called.
Bob King23243f82020-07-29 10:38:57 +0800182 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800183 MockJournal& journal = services.getMockJournal();
184 EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1);
185 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
186 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800187
Shawn McCarney525e20c2020-04-14 11:05:39 -0500188 // Create Chassis
189 std::unique_ptr<Chassis> chassis = std::make_unique<Chassis>(1);
190 Chassis* chassisPtr = chassis.get();
191
192 // Create System that contains Chassis
193 std::vector<std::unique_ptr<Rule>> rules{};
194 std::vector<std::unique_ptr<Chassis>> chassisVec{};
195 chassisVec.emplace_back(std::move(chassis));
196 System system{std::move(rules), std::move(chassisVec)};
197
198 // Call configure()
Bob King23243f82020-07-29 10:38:57 +0800199 chassisPtr->configure(services, system);
Shawn McCarney525e20c2020-04-14 11:05:39 -0500200 }
201
202 // Test where devices were specified in constructor
203 {
204 std::vector<std::unique_ptr<Device>> devices{};
205
Bob King5cfe5102020-07-30 16:26:18 +0800206 // Create mock services. Expect logInfo() and logDebug() to be called.
207 MockServices services{};
208 MockJournal& journal = services.getMockJournal();
209 EXPECT_CALL(journal, logInfo("Configuring chassis 2")).Times(1);
210 EXPECT_CALL(journal, logDebug("Configuring vdd0_reg: volts=1.300000"))
211 .Times(1);
212 EXPECT_CALL(journal, logDebug("Configuring vdd1_reg: volts=1.200000"))
213 .Times(1);
214 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
215
Shawn McCarney525e20c2020-04-14 11:05:39 -0500216 // Create Device vdd0_reg
217 {
218 // Create Configuration
219 std::vector<std::unique_ptr<Action>> actions{};
220 std::unique_ptr<Configuration> configuration =
221 std::make_unique<Configuration>(1.3, std::move(actions));
222
223 // Create Device
224 std::unique_ptr<i2c::I2CInterface> i2cInterface =
225 createI2CInterface();
226 std::unique_ptr<PresenceDetection> presenceDetection{};
227 std::unique_ptr<Device> device = std::make_unique<Device>(
228 "vdd0_reg", true, "/system/chassis/motherboard/vdd0_reg",
229 std::move(i2cInterface), std::move(presenceDetection),
230 std::move(configuration));
231 devices.emplace_back(std::move(device));
232 }
233
234 // Create Device vdd1_reg
235 {
236 // Create Configuration
237 std::vector<std::unique_ptr<Action>> actions{};
238 std::unique_ptr<Configuration> configuration =
239 std::make_unique<Configuration>(1.2, std::move(actions));
240
241 // Create Device
242 std::unique_ptr<i2c::I2CInterface> i2cInterface =
243 createI2CInterface();
244 std::unique_ptr<PresenceDetection> presenceDetection{};
245 std::unique_ptr<Device> device = std::make_unique<Device>(
246 "vdd1_reg", true, "/system/chassis/motherboard/vdd1_reg",
247 std::move(i2cInterface), std::move(presenceDetection),
248 std::move(configuration));
249 devices.emplace_back(std::move(device));
250 }
251
252 // Create Chassis
253 std::unique_ptr<Chassis> chassis =
254 std::make_unique<Chassis>(2, std::move(devices));
255 Chassis* chassisPtr = chassis.get();
256
257 // Create System that contains Chassis
258 std::vector<std::unique_ptr<Rule>> rules{};
259 std::vector<std::unique_ptr<Chassis>> chassisVec{};
260 chassisVec.emplace_back(std::move(chassis));
261 System system{std::move(rules), std::move(chassisVec)};
262
263 // Call configure()
Bob King23243f82020-07-29 10:38:57 +0800264 chassisPtr->configure(services, system);
Shawn McCarney525e20c2020-04-14 11:05:39 -0500265 }
266}
267
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500268TEST(ChassisTests, GetDevices)
269{
270 // Test where no devices were specified in constructor
271 {
272 Chassis chassis{2};
273 EXPECT_EQ(chassis.getDevices().size(), 0);
274 }
275
276 // Test where devices were specified in constructor
277 {
278 // Create vector of Device objects
279 std::vector<std::unique_ptr<Device>> devices{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500280 devices.emplace_back(createDevice("vdd_reg1"));
281 devices.emplace_back(createDevice("vdd_reg2"));
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500282
283 // Create Chassis
284 Chassis chassis{1, std::move(devices)};
285 EXPECT_EQ(chassis.getDevices().size(), 2);
286 EXPECT_EQ(chassis.getDevices()[0]->getID(), "vdd_reg1");
287 EXPECT_EQ(chassis.getDevices()[1]->getID(), "vdd_reg2");
288 }
289}
290
291TEST(ChassisTests, GetNumber)
292{
293 Chassis chassis{3};
294 EXPECT_EQ(chassis.getNumber(), 3);
295}
Bob Kinga2c81a62020-07-08 13:31:16 +0800296
297TEST(ChassisTests, MonitorSensors)
298{
299 // Test where no devices were specified in constructor
300 {
Bob King8a552922020-08-05 17:02:31 +0800301 // Create mock services. No logging should occur.
302 MockServices services{};
303 MockJournal& journal = services.getMockJournal();
304 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
305 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
306
Bob Kinga2c81a62020-07-08 13:31:16 +0800307 // Create Chassis
308 std::vector<std::unique_ptr<Device>> devices{};
309 std::unique_ptr<Chassis> chassis =
310 std::make_unique<Chassis>(1, std::move(devices));
311 Chassis* chassisPtr = chassis.get();
312
313 // Create System that contains Chassis
314 std::vector<std::unique_ptr<Rule>> rules{};
315 std::vector<std::unique_ptr<Chassis>> chassisVec{};
316 chassisVec.emplace_back(std::move(chassis));
317 System system{std::move(rules), std::move(chassisVec)};
318
319 // Call monitorSensors(). Should do nothing.
Bob King8a552922020-08-05 17:02:31 +0800320 chassisPtr->monitorSensors(services, system);
Bob Kinga2c81a62020-07-08 13:31:16 +0800321 }
322
323 // Test where devices were specified in constructor
324 {
Bob King8a552922020-08-05 17:02:31 +0800325 // Create mock services. No logging should occur.
326 MockServices services{};
327 MockJournal& journal = services.getMockJournal();
328 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
329 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
330
Bob Kinga2c81a62020-07-08 13:31:16 +0800331 std::vector<std::unique_ptr<Device>> devices{};
332
333 // Create PMBusReadSensorAction
334 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};
335 uint8_t command = 0x8C;
336 pmbus_utils::SensorDataFormat format{
337 pmbus_utils::SensorDataFormat::linear_11};
338 std::optional<int8_t> exponent{};
339 std::unique_ptr<PMBusReadSensorAction> action =
340 std::make_unique<PMBusReadSensorAction>(type, command, format,
341 exponent);
342
343 // Create mock I2CInterface. A two-byte read should occur.
344 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
345 std::make_unique<i2c::MockedI2CInterface>();
346 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
347 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
348 .Times(1);
349
350 // Create SensorMonitoring
351 std::vector<std::unique_ptr<Action>> actions{};
352 actions.emplace_back(std::move(action));
353 std::unique_ptr<SensorMonitoring> sensorMonitoring =
354 std::make_unique<SensorMonitoring>(std::move(actions));
355
356 // Create Rail
357 std::vector<std::unique_ptr<Rail>> rails{};
358 std::unique_ptr<Configuration> configuration{};
359 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
360 "vdd0", std::move(configuration), std::move(sensorMonitoring));
361 rails.emplace_back(std::move(rail));
362
363 // Create Device
364 std::unique_ptr<PresenceDetection> presenceDetection{};
365 std::unique_ptr<Configuration> deviceConfiguration{};
366 std::unique_ptr<Device> device = std::make_unique<Device>(
367 "reg1", true, "/system/chassis/motherboard/reg1",
368 std::move(i2cInterface), std::move(presenceDetection),
369 std::move(deviceConfiguration), std::move(rails));
370
371 // Create Chassis
372 devices.emplace_back(std::move(device));
373 std::unique_ptr<Chassis> chassis =
374 std::make_unique<Chassis>(1, std::move(devices));
375 Chassis* chassisPtr = chassis.get();
376
377 // Create System that contains Chassis
378 std::vector<std::unique_ptr<Rule>> rules{};
379 std::vector<std::unique_ptr<Chassis>> chassisVec{};
380 chassisVec.emplace_back(std::move(chassis));
381 System system{std::move(rules), std::move(chassisVec)};
382
383 // Call monitorSensors()
Bob King8a552922020-08-05 17:02:31 +0800384 chassisPtr->monitorSensors(services, system);
Bob Kinga2c81a62020-07-08 13:31:16 +0800385 }
386}