blob: 7963430da45fc34bff1156099b4c71e834b3f57b [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 McCarney50e57c62021-09-09 22:53:42 -050022#include "log_phase_fault_action.hpp"
Shawn McCarney17bac892021-05-08 07:55:52 -050023#include "mock_action.hpp"
Shawn McCarney9f3e54e2021-05-14 14:56:13 -050024#include "mock_error_logging.hpp"
Shawn McCarney525e20c2020-04-14 11:05:39 -050025#include "mock_journal.hpp"
Shawn McCarney17bac892021-05-08 07:55:52 -050026#include "mock_sensors.hpp"
Bob King23243f82020-07-29 10:38:57 +080027#include "mock_services.hpp"
Shawn McCarney050531f2020-06-02 14:17:12 -050028#include "mocked_i2c_interface.hpp"
Shawn McCarney50e57c62021-09-09 22:53:42 -050029#include "phase_fault.hpp"
Shawn McCarney32252592021-09-08 15:29:36 -050030#include "phase_fault_detection.hpp"
Shawn McCarney525e20c2020-04-14 11:05:39 -050031#include "presence_detection.hpp"
32#include "rail.hpp"
33#include "rule.hpp"
Shawn McCarney17bac892021-05-08 07:55:52 -050034#include "sensor_monitoring.hpp"
Shawn McCarney2f9e14f2021-04-29 02:45:18 -050035#include "sensors.hpp"
Shawn McCarney525e20c2020-04-14 11:05:39 -050036#include "system.hpp"
Shawn McCarney9f3e54e2021-05-14 14:56:13 -050037#include "test_sdbus_error.hpp"
Shawn McCarney8a3afd72020-03-12 14:28:44 -050038#include "test_utils.hpp"
39
40#include <memory>
41#include <stdexcept>
Shawn McCarney525e20c2020-04-14 11:05:39 -050042#include <string>
Shawn McCarney8a3afd72020-03-12 14:28:44 -050043#include <utility>
44#include <vector>
45
Bob Kinga2c81a62020-07-08 13:31:16 +080046#include <gmock/gmock.h>
Shawn McCarney8a3afd72020-03-12 14:28:44 -050047#include <gtest/gtest.h>
48
49using namespace phosphor::power::regulators;
50using namespace phosphor::power::regulators::test_utils;
51
Bob Kinga2c81a62020-07-08 13:31:16 +080052using ::testing::A;
Shawn McCarney050531f2020-06-02 14:17:12 -050053using ::testing::Return;
Shawn McCarney9f3e54e2021-05-14 14:56:13 -050054using ::testing::Throw;
Bob Kinga2c81a62020-07-08 13:31:16 +080055using ::testing::TypedEq;
Shawn McCarney050531f2020-06-02 14:17:12 -050056
Shawn McCarney83058602021-09-09 20:52:45 -050057class ChassisTests : public ::testing::Test
58{
59 public:
60 /**
61 * Constructor.
62 *
63 * Creates the System object needed for calling some Chassis methods.
64 */
65 ChassisTests() : ::testing::Test{}
66 {
67 std::vector<std::unique_ptr<Rule>> rules{};
68 std::vector<std::unique_ptr<Chassis>> chassis{};
69 system = std::make_unique<System>(std::move(rules), std::move(chassis));
70 }
Shawn McCarneycb3f6a62021-04-30 10:54:30 -050071
Shawn McCarney83058602021-09-09 20:52:45 -050072 protected:
73 const std::string defaultInventoryPath{
74 "/xyz/openbmc_project/inventory/system/chassis"};
75
76 std::unique_ptr<System> system{};
77};
78
79TEST_F(ChassisTests, Constructor)
Shawn McCarney8a3afd72020-03-12 14:28:44 -050080{
81 // Test where works: Only required parameters are specified
82 {
Shawn McCarneycb3f6a62021-04-30 10:54:30 -050083 Chassis chassis{2, defaultInventoryPath};
Shawn McCarney8a3afd72020-03-12 14:28:44 -050084 EXPECT_EQ(chassis.getNumber(), 2);
Shawn McCarneycb3f6a62021-04-30 10:54:30 -050085 EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath);
Shawn McCarney8a3afd72020-03-12 14:28:44 -050086 EXPECT_EQ(chassis.getDevices().size(), 0);
87 }
88
89 // Test where works: All parameters are specified
90 {
91 // Create vector of Device objects
92 std::vector<std::unique_ptr<Device>> devices{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -050093 devices.emplace_back(createDevice("vdd_reg1"));
94 devices.emplace_back(createDevice("vdd_reg2"));
Shawn McCarney8a3afd72020-03-12 14:28:44 -050095
96 // Create Chassis
Shawn McCarneycb3f6a62021-04-30 10:54:30 -050097 Chassis chassis{1, defaultInventoryPath, std::move(devices)};
Shawn McCarney8a3afd72020-03-12 14:28:44 -050098 EXPECT_EQ(chassis.getNumber(), 1);
Shawn McCarneycb3f6a62021-04-30 10:54:30 -050099 EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath);
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500100 EXPECT_EQ(chassis.getDevices().size(), 2);
101 }
102
103 // Test where fails: Invalid chassis number < 1
104 try
105 {
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500106 Chassis chassis{0, defaultInventoryPath};
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500107 ADD_FAILURE() << "Should not have reached this line.";
108 }
109 catch (const std::invalid_argument& e)
110 {
111 EXPECT_STREQ(e.what(), "Invalid chassis number: 0");
112 }
113 catch (...)
114 {
115 ADD_FAILURE() << "Should not have caught exception.";
116 }
117}
118
Shawn McCarney83058602021-09-09 20:52:45 -0500119TEST_F(ChassisTests, AddToIDMap)
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500120{
121 // Create vector of Device objects
122 std::vector<std::unique_ptr<Device>> devices{};
123 devices.emplace_back(createDevice("reg1", {"rail1"}));
124 devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"}));
125 devices.emplace_back(createDevice("reg3"));
126
127 // Create Chassis
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500128 Chassis chassis{1, defaultInventoryPath, std::move(devices)};
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500129
130 // Add Device and Rail objects within the Chassis to an IDMap
131 IDMap idMap{};
132 chassis.addToIDMap(idMap);
133
134 // Verify all Devices are in the IDMap
135 EXPECT_NO_THROW(idMap.getDevice("reg1"));
136 EXPECT_NO_THROW(idMap.getDevice("reg2"));
137 EXPECT_NO_THROW(idMap.getDevice("reg3"));
138 EXPECT_THROW(idMap.getDevice("reg4"), std::invalid_argument);
139
140 // Verify all Rails are in the IDMap
141 EXPECT_NO_THROW(idMap.getRail("rail1"));
142 EXPECT_NO_THROW(idMap.getRail("rail2a"));
143 EXPECT_NO_THROW(idMap.getRail("rail2b"));
144 EXPECT_THROW(idMap.getRail("rail3"), std::invalid_argument);
145}
146
Shawn McCarney83058602021-09-09 20:52:45 -0500147TEST_F(ChassisTests, ClearCache)
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600148{
149 // Create PresenceDetection
150 std::vector<std::unique_ptr<Action>> actions{};
Shawn McCarney83058602021-09-09 20:52:45 -0500151 auto presenceDetection =
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600152 std::make_unique<PresenceDetection>(std::move(actions));
153 PresenceDetection* presenceDetectionPtr = presenceDetection.get();
154
155 // Create Device that contains PresenceDetection
Shawn McCarney83058602021-09-09 20:52:45 -0500156 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
157 auto device = std::make_unique<Device>(
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600158 "reg1", true,
159 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
160 std::move(i2cInterface), std::move(presenceDetection));
161 Device* devicePtr = device.get();
162
163 // Create Chassis that contains Device
164 std::vector<std::unique_ptr<Device>> devices{};
165 devices.emplace_back(std::move(device));
Shawn McCarney83058602021-09-09 20:52:45 -0500166 Chassis chassis{1, defaultInventoryPath, std::move(devices)};
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600167
168 // Cache presence value in PresenceDetection
169 MockServices services{};
Shawn McCarney83058602021-09-09 20:52:45 -0500170 presenceDetectionPtr->execute(services, *system, chassis, *devicePtr);
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600171 EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
172
173 // Clear cached data in Chassis
Shawn McCarney83058602021-09-09 20:52:45 -0500174 chassis.clearCache();
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600175
176 // Verify presence value no longer cached in PresenceDetection
177 EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
178}
179
Shawn McCarney83058602021-09-09 20:52:45 -0500180TEST_F(ChassisTests, ClearErrorHistory)
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500181{
182 // Create SensorMonitoring. Will fail with a DBus exception.
Shawn McCarney83058602021-09-09 20:52:45 -0500183 auto action = std::make_unique<MockAction>();
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500184 EXPECT_CALL(*action, execute)
185 .WillRepeatedly(Throw(TestSDBusError{"Unable to set sensor value"}));
186 std::vector<std::unique_ptr<Action>> actions{};
187 actions.emplace_back(std::move(action));
Shawn McCarney83058602021-09-09 20:52:45 -0500188 auto sensorMonitoring =
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500189 std::make_unique<SensorMonitoring>(std::move(actions));
190
191 // Create Rail
192 std::unique_ptr<Configuration> configuration{};
Shawn McCarney83058602021-09-09 20:52:45 -0500193 auto rail = std::make_unique<Rail>("vddr1", std::move(configuration),
194 std::move(sensorMonitoring));
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500195
196 // Create Device that contains Rail
Shawn McCarney83058602021-09-09 20:52:45 -0500197 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500198 std::unique_ptr<PresenceDetection> presenceDetection{};
199 std::unique_ptr<Configuration> deviceConfiguration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500200 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500201 std::vector<std::unique_ptr<Rail>> rails{};
202 rails.emplace_back(std::move(rail));
Shawn McCarney83058602021-09-09 20:52:45 -0500203 auto device = std::make_unique<Device>(
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500204 "reg1", true,
205 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
206 std::move(i2cInterface), std::move(presenceDetection),
Shawn McCarney32252592021-09-08 15:29:36 -0500207 std::move(deviceConfiguration), std::move(phaseFaultDetection),
208 std::move(rails));
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500209
210 // Create Chassis that contains Device
211 std::vector<std::unique_ptr<Device>> devices{};
212 devices.emplace_back(std::move(device));
Shawn McCarney83058602021-09-09 20:52:45 -0500213 Chassis chassis{1, defaultInventoryPath, std::move(devices)};
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500214
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500215 // Create lambda that sets MockServices expectations. The lambda allows
216 // us to set expectations multiple times without duplicate code.
217 auto setExpectations = [](MockServices& services) {
218 // Expect Sensors service to be called 10 times
219 MockSensors& sensors = services.getMockSensors();
220 EXPECT_CALL(sensors, startRail).Times(10);
221 EXPECT_CALL(sensors, setValue).Times(0);
222 EXPECT_CALL(sensors, endRail).Times(10);
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500223
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500224 // Expect Journal service to be called 6 times to log error messages
225 MockJournal& journal = services.getMockJournal();
226 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
227 .Times(6);
228 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(6);
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500229
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500230 // Expect ErrorLogging service to be called once to log a DBus error
231 MockErrorLogging& errorLogging = services.getMockErrorLogging();
232 EXPECT_CALL(errorLogging, logDBusError).Times(1);
233 };
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500234
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500235 // Monitor sensors 10 times. Verify errors logged.
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500236 {
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500237 // Create mock services. Set expectations via lambda.
238 MockServices services{};
239 setExpectations(services);
240
241 for (int i = 1; i <= 10; ++i)
242 {
243 chassis.monitorSensors(services, *system);
244 }
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500245 }
246
247 // Clear error history
Shawn McCarney83058602021-09-09 20:52:45 -0500248 chassis.clearErrorHistory();
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500249
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500250 // Monitor sensors 10 more times. Verify errors logged again.
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500251 {
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500252 // Create mock services. Set expectations via lambda.
253 MockServices services{};
254 setExpectations(services);
255
256 for (int i = 1; i <= 10; ++i)
257 {
258 chassis.monitorSensors(services, *system);
259 }
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500260 }
261}
262
Shawn McCarney83058602021-09-09 20:52:45 -0500263TEST_F(ChassisTests, CloseDevices)
Shawn McCarney050531f2020-06-02 14:17:12 -0500264{
265 // Test where no devices were specified in constructor
266 {
Bob Kingd692d6d2020-09-14 13:42:57 +0800267 // Create mock services. Expect logDebug() to be called.
268 MockServices services{};
269 MockJournal& journal = services.getMockJournal();
270 EXPECT_CALL(journal, logDebug("Closing devices in chassis 2")).Times(1);
271
Shawn McCarney050531f2020-06-02 14:17:12 -0500272 // Create Chassis
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500273 Chassis chassis{2, defaultInventoryPath};
Shawn McCarney050531f2020-06-02 14:17:12 -0500274
275 // Call closeDevices()
Bob Kingd692d6d2020-09-14 13:42:57 +0800276 chassis.closeDevices(services);
Shawn McCarney050531f2020-06-02 14:17:12 -0500277 }
278
279 // Test where devices were specified in constructor
280 {
281 std::vector<std::unique_ptr<Device>> devices{};
282
Bob Kingd692d6d2020-09-14 13:42:57 +0800283 // Create mock services. Expect logDebug() to be called.
284 MockServices services{};
285 MockJournal& journal = services.getMockJournal();
286 EXPECT_CALL(journal, logDebug("Closing devices in chassis 1")).Times(1);
287
Shawn McCarney050531f2020-06-02 14:17:12 -0500288 // Create Device vdd0_reg
289 {
290 // Create mock I2CInterface: isOpen() and close() should be called
Shawn McCarney83058602021-09-09 20:52:45 -0500291 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarney050531f2020-06-02 14:17:12 -0500292 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
293 EXPECT_CALL(*i2cInterface, close).Times(1);
294
295 // Create Device
Shawn McCarney83058602021-09-09 20:52:45 -0500296 auto device =
Bob Kinga76898f2020-10-13 15:08:33 +0800297 std::make_unique<Device>("vdd0_reg", true,
298 "/xyz/openbmc_project/inventory/"
299 "system/chassis/motherboard/vdd0_reg",
300 std::move(i2cInterface));
Shawn McCarney050531f2020-06-02 14:17:12 -0500301 devices.emplace_back(std::move(device));
302 }
303
304 // Create Device vdd1_reg
305 {
306 // Create mock I2CInterface: isOpen() and close() should be called
Shawn McCarney83058602021-09-09 20:52:45 -0500307 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarney050531f2020-06-02 14:17:12 -0500308 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
309 EXPECT_CALL(*i2cInterface, close).Times(1);
310
311 // Create Device
Shawn McCarney83058602021-09-09 20:52:45 -0500312 auto device =
Bob Kinga76898f2020-10-13 15:08:33 +0800313 std::make_unique<Device>("vdd1_reg", true,
314 "/xyz/openbmc_project/inventory/"
315 "system/chassis/motherboard/vdd1_reg",
316 std::move(i2cInterface));
Shawn McCarney050531f2020-06-02 14:17:12 -0500317 devices.emplace_back(std::move(device));
318 }
319
320 // Create Chassis
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500321 Chassis chassis{1, defaultInventoryPath, std::move(devices)};
Shawn McCarney050531f2020-06-02 14:17:12 -0500322
323 // Call closeDevices()
Bob Kingd692d6d2020-09-14 13:42:57 +0800324 chassis.closeDevices(services);
Shawn McCarney050531f2020-06-02 14:17:12 -0500325 }
326}
327
Shawn McCarney83058602021-09-09 20:52:45 -0500328TEST_F(ChassisTests, Configure)
Shawn McCarney525e20c2020-04-14 11:05:39 -0500329{
330 // Test where no devices were specified in constructor
331 {
Bob King5cfe5102020-07-30 16:26:18 +0800332 // Create mock services. Expect logInfo() to be called.
Bob King23243f82020-07-29 10:38:57 +0800333 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800334 MockJournal& journal = services.getMockJournal();
335 EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1);
336 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
337 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800338
Shawn McCarney525e20c2020-04-14 11:05:39 -0500339 // Create Chassis
Shawn McCarney83058602021-09-09 20:52:45 -0500340 Chassis chassis{1, defaultInventoryPath};
Shawn McCarney525e20c2020-04-14 11:05:39 -0500341
342 // Call configure()
Shawn McCarney83058602021-09-09 20:52:45 -0500343 chassis.configure(services, *system);
Shawn McCarney525e20c2020-04-14 11:05:39 -0500344 }
345
346 // Test where devices were specified in constructor
347 {
348 std::vector<std::unique_ptr<Device>> devices{};
349
Bob King5cfe5102020-07-30 16:26:18 +0800350 // Create mock services. Expect logInfo() and logDebug() to be called.
351 MockServices services{};
352 MockJournal& journal = services.getMockJournal();
353 EXPECT_CALL(journal, logInfo("Configuring chassis 2")).Times(1);
354 EXPECT_CALL(journal, logDebug("Configuring vdd0_reg: volts=1.300000"))
355 .Times(1);
356 EXPECT_CALL(journal, logDebug("Configuring vdd1_reg: volts=1.200000"))
357 .Times(1);
358 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
359
Shawn McCarney525e20c2020-04-14 11:05:39 -0500360 // Create Device vdd0_reg
361 {
362 // Create Configuration
363 std::vector<std::unique_ptr<Action>> actions{};
Shawn McCarney83058602021-09-09 20:52:45 -0500364 auto configuration =
Shawn McCarney525e20c2020-04-14 11:05:39 -0500365 std::make_unique<Configuration>(1.3, std::move(actions));
366
367 // Create Device
Shawn McCarney83058602021-09-09 20:52:45 -0500368 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarney525e20c2020-04-14 11:05:39 -0500369 std::unique_ptr<PresenceDetection> presenceDetection{};
Shawn McCarney83058602021-09-09 20:52:45 -0500370 auto device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800371 "vdd0_reg", true,
372 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
373 "vdd0_reg",
Shawn McCarney525e20c2020-04-14 11:05:39 -0500374 std::move(i2cInterface), std::move(presenceDetection),
375 std::move(configuration));
376 devices.emplace_back(std::move(device));
377 }
378
379 // Create Device vdd1_reg
380 {
381 // Create Configuration
382 std::vector<std::unique_ptr<Action>> actions{};
Shawn McCarney83058602021-09-09 20:52:45 -0500383 auto configuration =
Shawn McCarney525e20c2020-04-14 11:05:39 -0500384 std::make_unique<Configuration>(1.2, std::move(actions));
385
386 // Create Device
Shawn McCarney83058602021-09-09 20:52:45 -0500387 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarney525e20c2020-04-14 11:05:39 -0500388 std::unique_ptr<PresenceDetection> presenceDetection{};
Shawn McCarney83058602021-09-09 20:52:45 -0500389 auto device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800390 "vdd1_reg", true,
391 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
392 "vdd1_reg",
Shawn McCarney525e20c2020-04-14 11:05:39 -0500393 std::move(i2cInterface), std::move(presenceDetection),
394 std::move(configuration));
395 devices.emplace_back(std::move(device));
396 }
397
398 // Create Chassis
Shawn McCarney83058602021-09-09 20:52:45 -0500399 Chassis chassis{2, defaultInventoryPath, std::move(devices)};
Shawn McCarney525e20c2020-04-14 11:05:39 -0500400
401 // Call configure()
Shawn McCarney83058602021-09-09 20:52:45 -0500402 chassis.configure(services, *system);
Shawn McCarney525e20c2020-04-14 11:05:39 -0500403 }
404}
405
Shawn McCarney50e57c62021-09-09 22:53:42 -0500406TEST_F(ChassisTests, DetectPhaseFaults)
407{
408 // Test where no devices were specified in constructor
409 {
410 // Create mock services. No errors should be logged.
411 MockServices services{};
412 MockJournal& journal = services.getMockJournal();
413 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
414 MockErrorLogging& errorLogging = services.getMockErrorLogging();
415 EXPECT_CALL(errorLogging, logPhaseFault).Times(0);
416
417 // Create Chassis
418 Chassis chassis{1, defaultInventoryPath};
419
420 // Call detectPhaseFaults() 5 times. Should do nothing.
421 for (int i = 1; i <= 5; ++i)
422 {
423 chassis.detectPhaseFaults(services, *system);
424 }
425 }
426
427 // Test where devices were specified in constructor
428 {
429 // Create mock services with the following expectations:
430 // - 2 error messages in journal for N phase fault detected in reg0
431 // - 2 error messages in journal for N phase fault detected in reg1
432 // - 1 N phase fault error logged for reg0
433 // - 1 N phase fault error logged for reg1
434 MockServices services{};
435 MockJournal& journal = services.getMockJournal();
436 EXPECT_CALL(
437 journal,
438 logError("n phase fault detected in regulator reg0: count=1"))
439 .Times(1);
440 EXPECT_CALL(
441 journal,
442 logError("n phase fault detected in regulator reg0: count=2"))
443 .Times(1);
444 EXPECT_CALL(
445 journal,
446 logError("n phase fault detected in regulator reg1: count=1"))
447 .Times(1);
448 EXPECT_CALL(
449 journal,
450 logError("n phase fault detected in regulator reg1: count=2"))
451 .Times(1);
452 MockErrorLogging& errorLogging = services.getMockErrorLogging();
453 EXPECT_CALL(errorLogging, logPhaseFault).Times(2);
454
455 std::vector<std::unique_ptr<Device>> devices{};
456
457 // Create Device reg0
458 {
459 // Create PhaseFaultDetection
460 auto action =
461 std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
462 std::vector<std::unique_ptr<Action>> actions{};
463 actions.push_back(std::move(action));
464 auto phaseFaultDetection =
465 std::make_unique<PhaseFaultDetection>(std::move(actions));
466
467 // Create Device
468 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
469 std::unique_ptr<PresenceDetection> presenceDetection{};
470 std::unique_ptr<Configuration> configuration{};
471 auto device = std::make_unique<Device>(
472 "reg0", true,
473 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
474 "reg0",
475 std::move(i2cInterface), std::move(presenceDetection),
476 std::move(configuration), std::move(phaseFaultDetection));
477 devices.emplace_back(std::move(device));
478 }
479
480 // Create Device reg1
481 {
482 // Create PhaseFaultDetection
483 auto action =
484 std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
485 std::vector<std::unique_ptr<Action>> actions{};
486 actions.push_back(std::move(action));
487 auto phaseFaultDetection =
488 std::make_unique<PhaseFaultDetection>(std::move(actions));
489
490 // Create Device
491 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
492 std::unique_ptr<PresenceDetection> presenceDetection{};
493 std::unique_ptr<Configuration> configuration{};
494 auto device = std::make_unique<Device>(
495 "reg1", true,
496 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
497 "reg1",
498 std::move(i2cInterface), std::move(presenceDetection),
499 std::move(configuration), std::move(phaseFaultDetection));
500 devices.emplace_back(std::move(device));
501 }
502
503 // Create Chassis
504 Chassis chassis{2, defaultInventoryPath, std::move(devices)};
505
506 // Call detectPhaseFaults() 5 times
507 for (int i = 1; i <= 5; ++i)
508 {
509 chassis.detectPhaseFaults(services, *system);
510 }
511 }
512}
513
Shawn McCarney83058602021-09-09 20:52:45 -0500514TEST_F(ChassisTests, GetDevices)
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500515{
516 // Test where no devices were specified in constructor
517 {
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500518 Chassis chassis{2, defaultInventoryPath};
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500519 EXPECT_EQ(chassis.getDevices().size(), 0);
520 }
521
522 // Test where devices were specified in constructor
523 {
524 // Create vector of Device objects
525 std::vector<std::unique_ptr<Device>> devices{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500526 devices.emplace_back(createDevice("vdd_reg1"));
527 devices.emplace_back(createDevice("vdd_reg2"));
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500528
529 // Create Chassis
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500530 Chassis chassis{1, defaultInventoryPath, std::move(devices)};
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500531 EXPECT_EQ(chassis.getDevices().size(), 2);
532 EXPECT_EQ(chassis.getDevices()[0]->getID(), "vdd_reg1");
533 EXPECT_EQ(chassis.getDevices()[1]->getID(), "vdd_reg2");
534 }
535}
536
Shawn McCarney83058602021-09-09 20:52:45 -0500537TEST_F(ChassisTests, GetInventoryPath)
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500538{
539 Chassis chassis{3, defaultInventoryPath};
540 EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath);
541}
542
Shawn McCarney83058602021-09-09 20:52:45 -0500543TEST_F(ChassisTests, GetNumber)
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500544{
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500545 Chassis chassis{3, defaultInventoryPath};
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500546 EXPECT_EQ(chassis.getNumber(), 3);
547}
Bob Kinga2c81a62020-07-08 13:31:16 +0800548
Shawn McCarney83058602021-09-09 20:52:45 -0500549TEST_F(ChassisTests, MonitorSensors)
Bob Kinga2c81a62020-07-08 13:31:16 +0800550{
551 // Test where no devices were specified in constructor
552 {
Shawn McCarney17bac892021-05-08 07:55:52 -0500553 // Create mock services. No Sensors methods should be called.
Bob King8a552922020-08-05 17:02:31 +0800554 MockServices services{};
Shawn McCarney17bac892021-05-08 07:55:52 -0500555 MockSensors& sensors = services.getMockSensors();
556 EXPECT_CALL(sensors, startRail).Times(0);
557 EXPECT_CALL(sensors, setValue).Times(0);
558 EXPECT_CALL(sensors, endRail).Times(0);
Bob King8a552922020-08-05 17:02:31 +0800559
Bob Kinga2c81a62020-07-08 13:31:16 +0800560 // Create Chassis
Shawn McCarney83058602021-09-09 20:52:45 -0500561 Chassis chassis{1, defaultInventoryPath};
Bob Kinga2c81a62020-07-08 13:31:16 +0800562
563 // Call monitorSensors(). Should do nothing.
Shawn McCarney83058602021-09-09 20:52:45 -0500564 chassis.monitorSensors(services, *system);
Bob Kinga2c81a62020-07-08 13:31:16 +0800565 }
566
567 // Test where devices were specified in constructor
568 {
Shawn McCarney17bac892021-05-08 07:55:52 -0500569 // Create mock services. Set Sensors service expectations.
Bob King8a552922020-08-05 17:02:31 +0800570 MockServices services{};
Shawn McCarney17bac892021-05-08 07:55:52 -0500571 MockSensors& sensors = services.getMockSensors();
572 EXPECT_CALL(sensors, startRail("vdd0",
573 "/xyz/openbmc_project/inventory/system/"
574 "chassis/motherboard/vdd0_reg",
575 defaultInventoryPath))
576 .Times(1);
577 EXPECT_CALL(sensors, startRail("vdd1",
578 "/xyz/openbmc_project/inventory/system/"
579 "chassis/motherboard/vdd1_reg",
580 defaultInventoryPath))
581 .Times(1);
582 EXPECT_CALL(sensors, setValue).Times(0);
583 EXPECT_CALL(sensors, endRail(false)).Times(2);
Bob King8a552922020-08-05 17:02:31 +0800584
Bob Kinga2c81a62020-07-08 13:31:16 +0800585 std::vector<std::unique_ptr<Device>> devices{};
586
Shawn McCarney17bac892021-05-08 07:55:52 -0500587 // Create Device vdd0_reg
588 {
589 // Create SensorMonitoring for Rail
Shawn McCarney83058602021-09-09 20:52:45 -0500590 auto action = std::make_unique<MockAction>();
Shawn McCarney17bac892021-05-08 07:55:52 -0500591 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
592 std::vector<std::unique_ptr<Action>> actions{};
593 actions.emplace_back(std::move(action));
Shawn McCarney83058602021-09-09 20:52:45 -0500594 auto sensorMonitoring =
Shawn McCarney17bac892021-05-08 07:55:52 -0500595 std::make_unique<SensorMonitoring>(std::move(actions));
Bob Kinga2c81a62020-07-08 13:31:16 +0800596
Shawn McCarney17bac892021-05-08 07:55:52 -0500597 // Create Rail
598 std::unique_ptr<Configuration> configuration{};
Shawn McCarney83058602021-09-09 20:52:45 -0500599 auto rail = std::make_unique<Rail>("vdd0", std::move(configuration),
600 std::move(sensorMonitoring));
Bob Kinga2c81a62020-07-08 13:31:16 +0800601
Shawn McCarney17bac892021-05-08 07:55:52 -0500602 // Create Device
Shawn McCarney83058602021-09-09 20:52:45 -0500603 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarney17bac892021-05-08 07:55:52 -0500604 std::unique_ptr<PresenceDetection> presenceDetection{};
605 std::unique_ptr<Configuration> deviceConfiguration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500606 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney17bac892021-05-08 07:55:52 -0500607 std::vector<std::unique_ptr<Rail>> rails{};
608 rails.emplace_back(std::move(rail));
Shawn McCarney83058602021-09-09 20:52:45 -0500609 auto device = std::make_unique<Device>(
Shawn McCarney17bac892021-05-08 07:55:52 -0500610 "vdd0_reg", true,
611 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
612 "vdd0_reg",
613 std::move(i2cInterface), std::move(presenceDetection),
Shawn McCarney32252592021-09-08 15:29:36 -0500614 std::move(deviceConfiguration), std::move(phaseFaultDetection),
615 std::move(rails));
Shawn McCarney17bac892021-05-08 07:55:52 -0500616 devices.emplace_back(std::move(device));
617 }
Bob Kinga2c81a62020-07-08 13:31:16 +0800618
Shawn McCarney17bac892021-05-08 07:55:52 -0500619 // Create Device vdd1_reg
620 {
621 // Create SensorMonitoring for Rail
Shawn McCarney83058602021-09-09 20:52:45 -0500622 auto action = std::make_unique<MockAction>();
Shawn McCarney17bac892021-05-08 07:55:52 -0500623 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
624 std::vector<std::unique_ptr<Action>> actions{};
625 actions.emplace_back(std::move(action));
Shawn McCarney83058602021-09-09 20:52:45 -0500626 auto sensorMonitoring =
Shawn McCarney17bac892021-05-08 07:55:52 -0500627 std::make_unique<SensorMonitoring>(std::move(actions));
Bob Kinga2c81a62020-07-08 13:31:16 +0800628
Shawn McCarney17bac892021-05-08 07:55:52 -0500629 // Create Rail
630 std::unique_ptr<Configuration> configuration{};
Shawn McCarney83058602021-09-09 20:52:45 -0500631 auto rail = std::make_unique<Rail>("vdd1", std::move(configuration),
632 std::move(sensorMonitoring));
Bob Kinga2c81a62020-07-08 13:31:16 +0800633
Shawn McCarney17bac892021-05-08 07:55:52 -0500634 // Create Device
Shawn McCarney83058602021-09-09 20:52:45 -0500635 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarney17bac892021-05-08 07:55:52 -0500636 std::unique_ptr<PresenceDetection> presenceDetection{};
637 std::unique_ptr<Configuration> deviceConfiguration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500638 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney17bac892021-05-08 07:55:52 -0500639 std::vector<std::unique_ptr<Rail>> rails{};
640 rails.emplace_back(std::move(rail));
Shawn McCarney83058602021-09-09 20:52:45 -0500641 auto device = std::make_unique<Device>(
Shawn McCarney17bac892021-05-08 07:55:52 -0500642 "vdd1_reg", true,
643 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
644 "vdd1_reg",
645 std::move(i2cInterface), std::move(presenceDetection),
Shawn McCarney32252592021-09-08 15:29:36 -0500646 std::move(deviceConfiguration), std::move(phaseFaultDetection),
647 std::move(rails));
Shawn McCarney17bac892021-05-08 07:55:52 -0500648 devices.emplace_back(std::move(device));
649 }
650
651 // Create Chassis that contains Devices
Shawn McCarney83058602021-09-09 20:52:45 -0500652 Chassis chassis{2, defaultInventoryPath, std::move(devices)};
Bob Kinga2c81a62020-07-08 13:31:16 +0800653
654 // Call monitorSensors()
Shawn McCarney83058602021-09-09 20:52:45 -0500655 chassis.monitorSensors(services, *system);
Bob Kinga2c81a62020-07-08 13:31:16 +0800656 }
657}