blob: 36042d49d3d98b2e24a2ff8293d19dad7a4c1cb9 [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"
Shawn McCarney2f9e14f2021-04-29 02:45:18 -050029#include "sensors.hpp"
Shawn McCarney525e20c2020-04-14 11:05:39 -050030#include "system.hpp"
Shawn McCarney8a3afd72020-03-12 14:28:44 -050031#include "test_utils.hpp"
32
33#include <memory>
34#include <stdexcept>
Shawn McCarney525e20c2020-04-14 11:05:39 -050035#include <string>
Shawn McCarney8a3afd72020-03-12 14:28:44 -050036#include <utility>
37#include <vector>
38
Bob Kinga2c81a62020-07-08 13:31:16 +080039#include <gmock/gmock.h>
Shawn McCarney8a3afd72020-03-12 14:28:44 -050040#include <gtest/gtest.h>
41
42using namespace phosphor::power::regulators;
43using namespace phosphor::power::regulators::test_utils;
44
Bob Kinga2c81a62020-07-08 13:31:16 +080045using ::testing::A;
Shawn McCarney050531f2020-06-02 14:17:12 -050046using ::testing::Return;
Bob Kinga2c81a62020-07-08 13:31:16 +080047using ::testing::TypedEq;
Shawn McCarney050531f2020-06-02 14:17:12 -050048
Shawn McCarney8a3afd72020-03-12 14:28:44 -050049TEST(ChassisTests, Constructor)
50{
51 // Test where works: Only required parameters are specified
52 {
53 Chassis chassis{2};
54 EXPECT_EQ(chassis.getNumber(), 2);
55 EXPECT_EQ(chassis.getDevices().size(), 0);
56 }
57
58 // Test where works: All parameters are specified
59 {
60 // Create vector of Device objects
61 std::vector<std::unique_ptr<Device>> devices{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -050062 devices.emplace_back(createDevice("vdd_reg1"));
63 devices.emplace_back(createDevice("vdd_reg2"));
Shawn McCarney8a3afd72020-03-12 14:28:44 -050064
65 // Create Chassis
66 Chassis chassis{1, std::move(devices)};
67 EXPECT_EQ(chassis.getNumber(), 1);
68 EXPECT_EQ(chassis.getDevices().size(), 2);
69 }
70
71 // Test where fails: Invalid chassis number < 1
72 try
73 {
74 Chassis chassis{0};
75 ADD_FAILURE() << "Should not have reached this line.";
76 }
77 catch (const std::invalid_argument& e)
78 {
79 EXPECT_STREQ(e.what(), "Invalid chassis number: 0");
80 }
81 catch (...)
82 {
83 ADD_FAILURE() << "Should not have caught exception.";
84 }
85}
86
Shawn McCarneydb0b8332020-04-06 14:13:04 -050087TEST(ChassisTests, AddToIDMap)
88{
89 // Create vector of Device objects
90 std::vector<std::unique_ptr<Device>> devices{};
91 devices.emplace_back(createDevice("reg1", {"rail1"}));
92 devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"}));
93 devices.emplace_back(createDevice("reg3"));
94
95 // Create Chassis
96 Chassis chassis{1, std::move(devices)};
97
98 // Add Device and Rail objects within the Chassis to an IDMap
99 IDMap idMap{};
100 chassis.addToIDMap(idMap);
101
102 // Verify all Devices are in the IDMap
103 EXPECT_NO_THROW(idMap.getDevice("reg1"));
104 EXPECT_NO_THROW(idMap.getDevice("reg2"));
105 EXPECT_NO_THROW(idMap.getDevice("reg3"));
106 EXPECT_THROW(idMap.getDevice("reg4"), std::invalid_argument);
107
108 // Verify all Rails are in the IDMap
109 EXPECT_NO_THROW(idMap.getRail("rail1"));
110 EXPECT_NO_THROW(idMap.getRail("rail2a"));
111 EXPECT_NO_THROW(idMap.getRail("rail2b"));
112 EXPECT_THROW(idMap.getRail("rail3"), std::invalid_argument);
113}
114
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600115TEST(ChassisTests, ClearCache)
116{
117 // Create PresenceDetection
118 std::vector<std::unique_ptr<Action>> actions{};
119 std::unique_ptr<PresenceDetection> presenceDetection =
120 std::make_unique<PresenceDetection>(std::move(actions));
121 PresenceDetection* presenceDetectionPtr = presenceDetection.get();
122
123 // Create Device that contains PresenceDetection
124 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
125 std::unique_ptr<Device> device = std::make_unique<Device>(
126 "reg1", true,
127 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
128 std::move(i2cInterface), std::move(presenceDetection));
129 Device* devicePtr = device.get();
130
131 // Create Chassis that contains Device
132 std::vector<std::unique_ptr<Device>> devices{};
133 devices.emplace_back(std::move(device));
134 std::unique_ptr<Chassis> chassis =
135 std::make_unique<Chassis>(1, std::move(devices));
136 Chassis* chassisPtr = chassis.get();
137
138 // Create System that contains Chassis
139 std::vector<std::unique_ptr<Rule>> rules{};
140 std::vector<std::unique_ptr<Chassis>> chassisVec{};
141 chassisVec.emplace_back(std::move(chassis));
142 System system{std::move(rules), std::move(chassisVec)};
143
144 // Cache presence value in PresenceDetection
145 MockServices services{};
146 presenceDetectionPtr->execute(services, system, *chassisPtr, *devicePtr);
147 EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
148
149 // Clear cached data in Chassis
150 chassisPtr->clearCache();
151
152 // Verify presence value no longer cached in PresenceDetection
153 EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
154}
155
Shawn McCarney050531f2020-06-02 14:17:12 -0500156TEST(ChassisTests, CloseDevices)
157{
158 // Test where no devices were specified in constructor
159 {
Bob Kingd692d6d2020-09-14 13:42:57 +0800160 // Create mock services. Expect logDebug() to be called.
161 MockServices services{};
162 MockJournal& journal = services.getMockJournal();
163 EXPECT_CALL(journal, logDebug("Closing devices in chassis 2")).Times(1);
164
Shawn McCarney050531f2020-06-02 14:17:12 -0500165 // Create Chassis
166 Chassis chassis{2};
167
168 // Call closeDevices()
Bob Kingd692d6d2020-09-14 13:42:57 +0800169 chassis.closeDevices(services);
Shawn McCarney050531f2020-06-02 14:17:12 -0500170 }
171
172 // Test where devices were specified in constructor
173 {
174 std::vector<std::unique_ptr<Device>> devices{};
175
Bob Kingd692d6d2020-09-14 13:42:57 +0800176 // Create mock services. Expect logDebug() to be called.
177 MockServices services{};
178 MockJournal& journal = services.getMockJournal();
179 EXPECT_CALL(journal, logDebug("Closing devices in chassis 1")).Times(1);
180
Shawn McCarney050531f2020-06-02 14:17:12 -0500181 // Create Device vdd0_reg
182 {
183 // Create mock I2CInterface: isOpen() and close() should be called
184 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
185 std::make_unique<i2c::MockedI2CInterface>();
186 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
187 EXPECT_CALL(*i2cInterface, close).Times(1);
188
189 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800190 std::unique_ptr<Device> device =
191 std::make_unique<Device>("vdd0_reg", true,
192 "/xyz/openbmc_project/inventory/"
193 "system/chassis/motherboard/vdd0_reg",
194 std::move(i2cInterface));
Shawn McCarney050531f2020-06-02 14:17:12 -0500195 devices.emplace_back(std::move(device));
196 }
197
198 // Create Device vdd1_reg
199 {
200 // Create mock I2CInterface: isOpen() and close() should be called
201 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
202 std::make_unique<i2c::MockedI2CInterface>();
203 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
204 EXPECT_CALL(*i2cInterface, close).Times(1);
205
206 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800207 std::unique_ptr<Device> device =
208 std::make_unique<Device>("vdd1_reg", true,
209 "/xyz/openbmc_project/inventory/"
210 "system/chassis/motherboard/vdd1_reg",
211 std::move(i2cInterface));
Shawn McCarney050531f2020-06-02 14:17:12 -0500212 devices.emplace_back(std::move(device));
213 }
214
215 // Create Chassis
216 Chassis chassis{1, std::move(devices)};
217
218 // Call closeDevices()
Bob Kingd692d6d2020-09-14 13:42:57 +0800219 chassis.closeDevices(services);
Shawn McCarney050531f2020-06-02 14:17:12 -0500220 }
221}
222
Shawn McCarney525e20c2020-04-14 11:05:39 -0500223TEST(ChassisTests, Configure)
224{
225 // Test where no devices were specified in constructor
226 {
Bob King5cfe5102020-07-30 16:26:18 +0800227 // Create mock services. Expect logInfo() to be called.
Bob King23243f82020-07-29 10:38:57 +0800228 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800229 MockJournal& journal = services.getMockJournal();
230 EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1);
231 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
232 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800233
Shawn McCarney525e20c2020-04-14 11:05:39 -0500234 // Create Chassis
235 std::unique_ptr<Chassis> chassis = std::make_unique<Chassis>(1);
236 Chassis* chassisPtr = chassis.get();
237
238 // Create System that contains Chassis
239 std::vector<std::unique_ptr<Rule>> rules{};
240 std::vector<std::unique_ptr<Chassis>> chassisVec{};
241 chassisVec.emplace_back(std::move(chassis));
242 System system{std::move(rules), std::move(chassisVec)};
243
244 // Call configure()
Bob King23243f82020-07-29 10:38:57 +0800245 chassisPtr->configure(services, system);
Shawn McCarney525e20c2020-04-14 11:05:39 -0500246 }
247
248 // Test where devices were specified in constructor
249 {
250 std::vector<std::unique_ptr<Device>> devices{};
251
Bob King5cfe5102020-07-30 16:26:18 +0800252 // Create mock services. Expect logInfo() and logDebug() to be called.
253 MockServices services{};
254 MockJournal& journal = services.getMockJournal();
255 EXPECT_CALL(journal, logInfo("Configuring chassis 2")).Times(1);
256 EXPECT_CALL(journal, logDebug("Configuring vdd0_reg: volts=1.300000"))
257 .Times(1);
258 EXPECT_CALL(journal, logDebug("Configuring vdd1_reg: volts=1.200000"))
259 .Times(1);
260 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
261
Shawn McCarney525e20c2020-04-14 11:05:39 -0500262 // Create Device vdd0_reg
263 {
264 // Create Configuration
265 std::vector<std::unique_ptr<Action>> actions{};
266 std::unique_ptr<Configuration> configuration =
267 std::make_unique<Configuration>(1.3, std::move(actions));
268
269 // Create Device
270 std::unique_ptr<i2c::I2CInterface> i2cInterface =
271 createI2CInterface();
272 std::unique_ptr<PresenceDetection> presenceDetection{};
273 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800274 "vdd0_reg", true,
275 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
276 "vdd0_reg",
Shawn McCarney525e20c2020-04-14 11:05:39 -0500277 std::move(i2cInterface), std::move(presenceDetection),
278 std::move(configuration));
279 devices.emplace_back(std::move(device));
280 }
281
282 // Create Device vdd1_reg
283 {
284 // Create Configuration
285 std::vector<std::unique_ptr<Action>> actions{};
286 std::unique_ptr<Configuration> configuration =
287 std::make_unique<Configuration>(1.2, std::move(actions));
288
289 // Create Device
290 std::unique_ptr<i2c::I2CInterface> i2cInterface =
291 createI2CInterface();
292 std::unique_ptr<PresenceDetection> presenceDetection{};
293 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800294 "vdd1_reg", true,
295 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
296 "vdd1_reg",
Shawn McCarney525e20c2020-04-14 11:05:39 -0500297 std::move(i2cInterface), std::move(presenceDetection),
298 std::move(configuration));
299 devices.emplace_back(std::move(device));
300 }
301
302 // Create Chassis
303 std::unique_ptr<Chassis> chassis =
304 std::make_unique<Chassis>(2, std::move(devices));
305 Chassis* chassisPtr = chassis.get();
306
307 // Create System that contains Chassis
308 std::vector<std::unique_ptr<Rule>> rules{};
309 std::vector<std::unique_ptr<Chassis>> chassisVec{};
310 chassisVec.emplace_back(std::move(chassis));
311 System system{std::move(rules), std::move(chassisVec)};
312
313 // Call configure()
Bob King23243f82020-07-29 10:38:57 +0800314 chassisPtr->configure(services, system);
Shawn McCarney525e20c2020-04-14 11:05:39 -0500315 }
316}
317
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500318TEST(ChassisTests, GetDevices)
319{
320 // Test where no devices were specified in constructor
321 {
322 Chassis chassis{2};
323 EXPECT_EQ(chassis.getDevices().size(), 0);
324 }
325
326 // Test where devices were specified in constructor
327 {
328 // Create vector of Device objects
329 std::vector<std::unique_ptr<Device>> devices{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500330 devices.emplace_back(createDevice("vdd_reg1"));
331 devices.emplace_back(createDevice("vdd_reg2"));
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500332
333 // Create Chassis
334 Chassis chassis{1, std::move(devices)};
335 EXPECT_EQ(chassis.getDevices().size(), 2);
336 EXPECT_EQ(chassis.getDevices()[0]->getID(), "vdd_reg1");
337 EXPECT_EQ(chassis.getDevices()[1]->getID(), "vdd_reg2");
338 }
339}
340
341TEST(ChassisTests, GetNumber)
342{
343 Chassis chassis{3};
344 EXPECT_EQ(chassis.getNumber(), 3);
345}
Bob Kinga2c81a62020-07-08 13:31:16 +0800346
347TEST(ChassisTests, MonitorSensors)
348{
349 // Test where no devices were specified in constructor
350 {
Bob King8a552922020-08-05 17:02:31 +0800351 // Create mock services. No logging should occur.
352 MockServices services{};
353 MockJournal& journal = services.getMockJournal();
354 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
355 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
356
Bob Kinga2c81a62020-07-08 13:31:16 +0800357 // Create Chassis
358 std::vector<std::unique_ptr<Device>> devices{};
359 std::unique_ptr<Chassis> chassis =
360 std::make_unique<Chassis>(1, std::move(devices));
361 Chassis* chassisPtr = chassis.get();
362
363 // Create System that contains Chassis
364 std::vector<std::unique_ptr<Rule>> rules{};
365 std::vector<std::unique_ptr<Chassis>> chassisVec{};
366 chassisVec.emplace_back(std::move(chassis));
367 System system{std::move(rules), std::move(chassisVec)};
368
369 // Call monitorSensors(). Should do nothing.
Bob King8a552922020-08-05 17:02:31 +0800370 chassisPtr->monitorSensors(services, system);
Bob Kinga2c81a62020-07-08 13:31:16 +0800371 }
372
373 // Test where devices were specified in constructor
374 {
Bob King8a552922020-08-05 17:02:31 +0800375 // Create mock services. No logging should occur.
376 MockServices services{};
377 MockJournal& journal = services.getMockJournal();
378 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
379 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
380
Bob Kinga2c81a62020-07-08 13:31:16 +0800381 std::vector<std::unique_ptr<Device>> devices{};
382
383 // Create PMBusReadSensorAction
Shawn McCarney2f9e14f2021-04-29 02:45:18 -0500384 SensorType type{SensorType::iout};
Bob Kinga2c81a62020-07-08 13:31:16 +0800385 uint8_t command = 0x8C;
386 pmbus_utils::SensorDataFormat format{
387 pmbus_utils::SensorDataFormat::linear_11};
388 std::optional<int8_t> exponent{};
389 std::unique_ptr<PMBusReadSensorAction> action =
390 std::make_unique<PMBusReadSensorAction>(type, command, format,
391 exponent);
392
393 // Create mock I2CInterface. A two-byte read should occur.
394 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
395 std::make_unique<i2c::MockedI2CInterface>();
396 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
397 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
398 .Times(1);
399
400 // Create SensorMonitoring
401 std::vector<std::unique_ptr<Action>> actions{};
402 actions.emplace_back(std::move(action));
403 std::unique_ptr<SensorMonitoring> sensorMonitoring =
404 std::make_unique<SensorMonitoring>(std::move(actions));
405
406 // Create Rail
407 std::vector<std::unique_ptr<Rail>> rails{};
408 std::unique_ptr<Configuration> configuration{};
409 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
410 "vdd0", std::move(configuration), std::move(sensorMonitoring));
411 rails.emplace_back(std::move(rail));
412
413 // Create Device
414 std::unique_ptr<PresenceDetection> presenceDetection{};
415 std::unique_ptr<Configuration> deviceConfiguration{};
416 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800417 "reg1", true,
418 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob Kinga2c81a62020-07-08 13:31:16 +0800419 std::move(i2cInterface), std::move(presenceDetection),
420 std::move(deviceConfiguration), std::move(rails));
421
422 // Create Chassis
423 devices.emplace_back(std::move(device));
424 std::unique_ptr<Chassis> chassis =
425 std::make_unique<Chassis>(1, std::move(devices));
426 Chassis* chassisPtr = chassis.get();
427
428 // Create System that contains Chassis
429 std::vector<std::unique_ptr<Rule>> rules{};
430 std::vector<std::unique_ptr<Chassis>> chassisVec{};
431 chassisVec.emplace_back(std::move(chassis));
432 System system{std::move(rules), std::move(chassisVec)};
433
434 // Call monitorSensors()
Bob King8a552922020-08-05 17:02:31 +0800435 chassisPtr->monitorSensors(services, system);
Bob Kinga2c81a62020-07-08 13:31:16 +0800436 }
437}